@conduction/nextcloud-vue 2.104.0 → 2.106.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/esm/components/CnAdminSettingsShell/CnAdminSettingsShell.vue.js +1 -1
- package/dist/esm/components/CnAdminSettingsShell/CnAdminSettingsShell.vue2.js.map +1 -1
- package/dist/esm/components/CnAdminSettingsShell/CnAdminSettingsShell.vue3.js +1 -1
- package/dist/esm/components/CnAdminSettingsShell/CnAdminSettingsShell.vue3.js.map +1 -1
- package/dist/esm/components/CnCardGrid/CnCardGrid.vue.js +1 -1
- package/dist/esm/components/CnCardGrid/CnCardGrid.vue2.js +18 -0
- package/dist/esm/components/CnCardGrid/CnCardGrid.vue2.js.map +1 -1
- package/dist/esm/components/CnCardGrid/CnCardGrid.vue3.js +3 -1
- package/dist/esm/components/CnCardGrid/CnCardGrid.vue3.js.map +1 -1
- package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue.js +1 -1
- package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue2.js +18 -0
- package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue2.js.map +1 -1
- package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue3.js +1 -1
- package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue3.js.map +1 -1
- package/dist/esm/components/CnChartWidget/CnChartWidget.vue.js +1 -1
- package/dist/esm/components/CnChartWidget/CnChartWidget.vue2.js +93 -1
- package/dist/esm/components/CnChartWidget/CnChartWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnChartWidget/CnChartWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue.js +1 -1
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue2.js +6 -3
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue2.js.map +1 -1
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue3.js +3 -3
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue3.js.map +1 -1
- package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js +112 -5
- package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js.map +1 -1
- package/dist/esm/components/CnDetailPage/CnDetailPage.vue3.js.map +1 -1
- package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHeaderItems.vue.js +9 -0
- package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHeaderItems.vue.js.map +1 -0
- package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHeaderItems.vue2.js +24 -0
- package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHeaderItems.vue2.js.map +1 -0
- package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHeaderItems.vue3.js +49 -0
- package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHeaderItems.vue3.js.map +1 -0
- package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue.js +1 -1
- package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue2.js +36 -18
- package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue2.js.map +1 -1
- package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue3.js +17 -38
- package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue3.js.map +1 -1
- package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue.js +1 -1
- package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnFeaturesAndRoadmapView/CnFeaturesAndRoadmapView.vue.js +1 -1
- package/dist/esm/components/CnFeaturesAndRoadmapView/CnFeaturesAndRoadmapView.vue2.js +1 -1
- package/dist/esm/components/CnFeaturesAndRoadmapView/CnFeaturesAndRoadmapView.vue2.js.map +1 -1
- package/dist/esm/components/CnFeaturesAndRoadmapView/CnFeaturesAndRoadmapView.vue3.js.map +1 -1
- package/dist/esm/components/CnFeaturesBoard/CnFeaturesBoard.vue.js +1 -1
- package/dist/esm/components/CnFeaturesBoard/CnFeaturesBoard.vue2.js +2 -0
- package/dist/esm/components/CnFeaturesBoard/CnFeaturesBoard.vue2.js.map +1 -1
- package/dist/esm/components/CnFeaturesBoard/CnFeaturesBoard.vue3.js +32 -29
- package/dist/esm/components/CnFeaturesBoard/CnFeaturesBoard.vue3.js.map +1 -1
- package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue.js +1 -1
- package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue2.js +53 -2
- package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue2.js.map +1 -1
- package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue3.js +119 -111
- package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue3.js.map +1 -1
- package/dist/esm/components/CnFlowRunsWidget/CnFlowRunsWidget.vue.js +1 -1
- package/dist/esm/components/CnFlowRunsWidget/CnFlowRunsWidget.vue2.js +62 -1
- package/dist/esm/components/CnFlowRunsWidget/CnFlowRunsWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnFlowRunsWidget/CnFlowRunsWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnFlowsPage/CnFlowBoard.vue.js +1 -1
- package/dist/esm/components/CnFlowsPage/CnFlowBoard.vue2.js +73 -4
- package/dist/esm/components/CnFlowsPage/CnFlowBoard.vue2.js.map +1 -1
- package/dist/esm/components/CnFlowsPage/CnFlowBoard.vue3.js +74 -27
- package/dist/esm/components/CnFlowsPage/CnFlowBoard.vue3.js.map +1 -1
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js +208 -46
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js.map +1 -1
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js +121 -98
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js.map +1 -1
- package/dist/esm/components/CnIndexPage/CnIndexPageWidgets.vue.js +1 -1
- package/dist/esm/components/CnIndexPage/CnIndexPageWidgets.vue2.js +24 -0
- package/dist/esm/components/CnIndexPage/CnIndexPageWidgets.vue2.js.map +1 -1
- package/dist/esm/components/CnIndexPage/CnIndexPageWidgets.vue3.js +20 -4
- package/dist/esm/components/CnIndexPage/CnIndexPageWidgets.vue3.js.map +1 -1
- package/dist/esm/components/CnIndexPage/useSelfFetchList.js +25 -6
- package/dist/esm/components/CnIndexPage/useSelfFetchList.js.map +1 -1
- package/dist/esm/components/CnIndexSidebar/CnIndexSidebar.vue2.js +112 -1
- package/dist/esm/components/CnIndexSidebar/CnIndexSidebar.vue2.js.map +1 -1
- package/dist/esm/components/CnIndexSidebar/CnIndexSidebar.vue3.js +100 -44
- package/dist/esm/components/CnIndexSidebar/CnIndexSidebar.vue3.js.map +1 -1
- package/dist/esm/components/CnNcWidgetWidget/CnNcWidgetWidget.vue.js +1 -1
- package/dist/esm/components/CnNcWidgetWidget/CnNcWidgetWidget.vue2.js +67 -4
- package/dist/esm/components/CnNcWidgetWidget/CnNcWidgetWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnNcWidgetWidget/CnNcWidgetWidget.vue3.js +1 -1
- package/dist/esm/components/CnNcWidgetWidget/CnNcWidgetWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnNoticeWidget/CnNoticeWidget.vue.js +9 -0
- package/dist/esm/components/CnNoticeWidget/CnNoticeWidget.vue.js.map +1 -0
- package/dist/esm/components/CnNoticeWidget/CnNoticeWidget.vue2.js +88 -0
- package/dist/esm/components/CnNoticeWidget/CnNoticeWidget.vue2.js.map +1 -0
- package/dist/esm/components/CnNoticeWidget/CnNoticeWidget.vue3.js +39 -0
- package/dist/esm/components/CnNoticeWidget/CnNoticeWidget.vue3.js.map +1 -0
- package/dist/esm/components/CnObjectCard/CnObjectCard.vue.js +1 -1
- package/dist/esm/components/CnObjectCard/CnObjectCard.vue2.js +295 -12
- package/dist/esm/components/CnObjectCard/CnObjectCard.vue2.js.map +1 -1
- package/dist/esm/components/CnObjectCard/CnObjectCard.vue3.js +267 -144
- package/dist/esm/components/CnObjectCard/CnObjectCard.vue3.js.map +1 -1
- package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue.js +1 -1
- package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue2.js +4 -0
- package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue2.js.map +1 -1
- package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue3.js +3 -1
- package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue3.js.map +1 -1
- package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue.js +1 -1
- package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue2.js +93 -1
- package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue3.js +322 -246
- package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnRelatedObjectsWidget/CnRelatedObjectsWidget.vue.js +1 -1
- package/dist/esm/components/CnRelatedObjectsWidget/CnRelatedObjectsWidget.vue2.js +122 -7
- package/dist/esm/components/CnRelatedObjectsWidget/CnRelatedObjectsWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnRelatedObjectsWidget/CnRelatedObjectsWidget.vue3.js +189 -93
- package/dist/esm/components/CnRelatedObjectsWidget/CnRelatedObjectsWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnSettingsField/CnSettingsField.vue.js +1 -1
- package/dist/esm/components/CnSettingsField/CnSettingsField.vue2.js.map +1 -1
- package/dist/esm/components/CnSettingsField/CnSettingsField.vue3.js +3 -3
- package/dist/esm/components/CnSettingsField/CnSettingsField.vue3.js.map +1 -1
- package/dist/esm/components/CnSetupWizard/CnSetupWizard.vue.js +1 -1
- package/dist/esm/components/CnSetupWizard/CnSetupWizard.vue2.js.map +1 -1
- package/dist/esm/components/CnSetupWizard/CnSetupWizard.vue3.js +16 -4
- package/dist/esm/components/CnSetupWizard/CnSetupWizard.vue3.js.map +1 -1
- package/dist/esm/components/CnTabs/CnTabs.vue.js +1 -1
- package/dist/esm/components/CnTabs/CnTabs.vue2.js.map +1 -1
- package/dist/esm/components/CnTabs/CnTabs.vue3.js.map +1 -1
- package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue.js +1 -1
- package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue2.js +42 -0
- package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue3.js +38 -19
- package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnTeamWorkloadWidget/CnTeamWorkloadWidget.vue.js +9 -0
- package/dist/esm/components/CnTeamWorkloadWidget/CnTeamWorkloadWidget.vue.js.map +1 -0
- package/dist/esm/components/CnTeamWorkloadWidget/CnTeamWorkloadWidget.vue2.js +258 -0
- package/dist/esm/components/CnTeamWorkloadWidget/CnTeamWorkloadWidget.vue2.js.map +1 -0
- package/dist/esm/components/CnTeamWorkloadWidget/CnTeamWorkloadWidget.vue3.js +69 -0
- package/dist/esm/components/CnTeamWorkloadWidget/CnTeamWorkloadWidget.vue3.js.map +1 -0
- package/dist/esm/components/CnVersionInfoCard/CnVersionInfoCard.vue.js +1 -1
- package/dist/esm/components/CnVersionInfoCard/CnVersionInfoCard.vue2.js +11 -0
- package/dist/esm/components/CnVersionInfoCard/CnVersionInfoCard.vue2.js.map +1 -1
- package/dist/esm/components/CnVersionInfoCard/CnVersionInfoCard.vue3.js +4 -4
- package/dist/esm/components/CnVersionInfoCard/CnVersionInfoCard.vue3.js.map +1 -1
- package/dist/esm/components/CnWidgetGrid/builtInWidgets.js +16 -14
- package/dist/esm/components/CnWidgetGrid/builtInWidgets.js.map +1 -1
- package/dist/esm/components/CnWidgetGrid/registerDashboardWidgets.js +12 -0
- package/dist/esm/components/CnWidgetGrid/registerDashboardWidgets.js.map +1 -1
- package/dist/esm/index.js +2 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/l10n/en.json.js +24 -1
- package/dist/esm/l10n/en.json.js.map +1 -1
- package/dist/esm/l10n/nl.json.js +24 -1
- package/dist/esm/l10n/nl.json.js.map +1 -1
- package/dist/esm/library-style.js +1 -1
- package/dist/esm/nextcloud-vue.css +1369 -748
- package/dist/esm/utils/dueText.js +18 -3
- package/dist/esm/utils/dueText.js.map +1 -1
- package/dist/esm/utils/libraryWidgetKeys.js +2 -0
- package/dist/esm/utils/libraryWidgetKeys.js.map +1 -1
- package/dist/esm/utils/nextcloudApps.js +45 -0
- package/dist/esm/utils/nextcloudApps.js.map +1 -0
- package/dist/esm/utils/scopeListLayout.js +9 -2
- package/dist/esm/utils/scopeListLayout.js.map +1 -1
- package/dist/esm/utils/sortOrder.js +11 -1
- package/dist/esm/utils/sortOrder.js.map +1 -1
- package/dist/esm/utils/validateManifestV2.compiled.js +3 -3
- package/dist/esm/utils/validateManifestV2.compiled.js.map +1 -1
- package/dist/esm/utils/visibleWhen.js +12 -4
- package/dist/esm/utils/visibleWhen.js.map +1 -1
- package/dist/nextcloud-vue.cjs.js +8965 -6497
- package/dist/nextcloud-vue.cjs.js.map +2 -2
- package/dist/nextcloud-vue.css +1369 -748
- package/l10n/en.json +24 -1
- package/l10n/nl.json +24 -1
- package/package.json +1 -1
- package/src/components/CnAdminSettingsShell/CnAdminSettingsShell.vue +1 -1
- package/src/components/CnCardGrid/CnCardGrid.md +2 -0
- package/src/components/CnCardGrid/CnCardGrid.vue +20 -0
- package/src/components/CnCellRenderer/CnCellRenderer.vue +19 -1
- package/src/components/CnChartWidget/CnChartWidget.md +2 -0
- package/src/components/CnChartWidget/CnChartWidget.vue +93 -1
- package/src/components/CnDashboardPage/CnDashboardPage.vue +9 -6
- package/src/components/CnDetailPage/CnDetailPage.md +3 -2
- package/src/components/CnDetailPage/CnDetailPage.vue +112 -5
- package/src/components/CnDetailWidgetHost/CnDetailWidgetHeaderItems.vue +60 -0
- package/src/components/CnDetailWidgetHost/CnDetailWidgetHost.vue +36 -29
- package/src/components/CnFactsWidget/CnFactsWidget.vue +4 -0
- package/src/components/CnFeaturesAndRoadmapView/CnFeaturesAndRoadmapView.vue +1 -1
- package/src/components/CnFeaturesBoard/CnFeaturesBoard.vue +4 -1
- package/src/components/CnFilesBrowser/CnFilesBrowser.vue +70 -4
- package/src/components/CnFlowRunsWidget/CnFlowRunsWidget.vue +62 -1
- package/src/components/CnFlowsPage/CnFlowBoard.vue +132 -8
- package/src/components/CnIndexPage/CnIndexPage.md +8 -5
- package/src/components/CnIndexPage/CnIndexPage.vue +236 -54
- package/src/components/CnIndexPage/CnIndexPageWidgets.vue +36 -1
- package/src/components/CnIndexPage/useSelfFetchList.js +25 -6
- package/src/components/CnIndexSidebar/CnIndexSidebar.md +2 -0
- package/src/components/CnIndexSidebar/CnIndexSidebar.vue +148 -1
- package/src/components/CnNcWidgetWidget/CnNcWidgetWidget.vue +68 -5
- package/src/components/CnNoticeWidget/CnNoticeWidget.vue +153 -0
- package/src/components/CnNoticeWidget/index.js +12 -0
- package/src/components/CnObjectCard/CnObjectCard.md +1 -0
- package/src/components/CnObjectCard/CnObjectCard.vue +354 -13
- package/src/components/CnObjectSidebar/CnFilesTab.vue +6 -0
- package/src/components/CnRecordListWidget/CnRecordListWidget.vue +190 -4
- package/src/components/CnRelatedObjectsWidget/CnRelatedObjectsWidget.vue +209 -9
- package/src/components/CnSettingsField/CnSettingsField.vue +4 -1
- package/src/components/CnSetupWizard/CnSetupWizard.vue +9 -1
- package/src/components/CnTabs/CnTabs.vue +11 -0
- package/src/components/CnTabsWidget/CnTabsWidget.vue +91 -18
- package/src/components/CnTeamWorkloadWidget/CnTeamWorkloadWidget.md +11 -0
- package/src/components/CnTeamWorkloadWidget/CnTeamWorkloadWidget.vue +382 -0
- package/src/components/CnTeamWorkloadWidget/index.js +14 -0
- package/src/components/CnVersionInfoCard/CnVersionInfoCard.vue +15 -4
- package/src/components/CnWidgetGrid/builtInWidgets.js +2 -0
- package/src/components/CnWidgetGrid/registerDashboardWidgets.js +12 -0
- package/src/components/index.js +2 -0
- package/src/css/dialog.css +20 -2
- package/src/css/index-page.css +14 -2
- package/src/css/look-board-detail.css +125 -8
- package/src/css/look-board-index.css +100 -4
- package/src/css/look-board.css +122 -14
- package/src/index.js +2 -1
- package/src/schemas/app-manifest-v2.schema.json +110 -8
- package/src/utils/dueText.js +18 -3
- package/src/utils/libraryWidgetKeys.js +2 -0
- package/src/utils/nextcloudApps.js +50 -0
- package/src/utils/scopeListLayout.js +9 -2
- package/src/utils/sortOrder.js +10 -0
- package/src/utils/validateManifestV2.compiled.js +3 -3
- package/src/utils/visibleWhen.js +12 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CnObjectCard.vue3.js","sources":["../../../../src/components/CnObjectCard/CnObjectCard.vue?vue&type=template&id=59552a5b&lang.js"],"sourcesContent":["<template>\n\t<div\n\t\tclass=\"cn-object-card\"\n\t\t:class=\"[{ 'cn-object-card--selected': selected, 'cn-object-card--board': isBoardLook }, accentVariant && ['cn-object-card--accent', `cn-object-card--accent-${accentVariant}`]]\"\n\t\t@mousedown=\"onCardMouseDown\"\n\t\t@click=\"onCardClick($event)\"\n\t\t@auxclick=\"onCardAuxClick($event)\">\n\t\t<!-- Selection checkbox -->\n\t\t<div v-if=\"selectable\"\n\t\t\tclass=\"cn-object-card__checkbox\"\n\t\t\t@click.stop\n\t\t\t@auxclick.stop>\n\t\t\t<NcCheckboxRadioSwitch\n\t\t\t\t:modelValue=\"selected\"\n\t\t\t\t@update:modelValue=\"$emit('select', object)\" />\n\t\t</div>\n\n\t\t<!-- Card content -->\n\t\t<div class=\"cn-object-card__content\">\n\t\t\t<!-- Header: image + title -->\n\t\t\t<div class=\"cn-object-card__header\">\n\t\t\t\t<!-- Board look: the leading element, initials in a circle or an icon on a tint. -->\n\t\t\t\t<span\n\t\t\t\t\tv-if=\"isBoardLook && leadingKind\"\n\t\t\t\t\tclass=\"cn-object-card__leading\"\n\t\t\t\t\t:class=\"`cn-object-card__leading--${leadingKind}`\"\n\t\t\t\t\tdata-testid=\"cn-object-card-leading\"\n\t\t\t\t\taria-hidden=\"true\">\n\t\t\t\t\t<template v-if=\"leadingKind === 'initials'\">{{ leading.initials }}</template>\n\t\t\t\t\t<CnIcon v-else :name=\"leading.icon\" :size=\"20\" />\n\t\t\t\t</span>\n\t\t\t\t<img\n\t\t\t\t\tv-if=\"imageUrl\"\n\t\t\t\t\t:src=\"imageUrl\"\n\t\t\t\t\t:alt=\"title\"\n\t\t\t\t\tclass=\"cn-object-card__image\">\n\n\t\t\t\t<div class=\"cn-object-card__title-area\">\n\t\t\t\t\t<h3 class=\"cn-object-card__title\">\n\t\t\t\t\t\t<!-- Beside the title, not in the badges row: the badges\n\t\t\t\t\t\t slot is the consumer's, and a lock is the library's\n\t\t\t\t\t\t to report. A card whose consumer passes no badges\n\t\t\t\t\t\t would otherwise show no padlock at all. -->\n\t\t\t\t\t\t<CnLockIndicator :object=\"object\" :size=\"16\" />\n\t\t\t\t\t\t<span\n\t\t\t\t\t\t\tv-if=\"accentVariant && accent.icon\"\n\t\t\t\t\t\t\tclass=\"cn-object-card__accent-icon\"\n\t\t\t\t\t\t\tdata-testid=\"cn-object-card-accent-icon\"\n\t\t\t\t\t\t\t:role=\"accent.label ? 'img' : null\"\n\t\t\t\t\t\t\t:aria-label=\"accent.label || null\"\n\t\t\t\t\t\t\t:aria-hidden=\"accent.label ? null : 'true'\"\n\t\t\t\t\t\t\t:title=\"accent.label || null\">\n\t\t\t\t\t\t\t<CnIcon :name=\"accent.icon\" :size=\"16\" />\n\t\t\t\t\t\t</span>\n\t\t\t\t\t\t{{ title }}\n\t\t\t\t\t</h3>\n\t\t\t\t\t<p v-if=\"description\" class=\"cn-object-card__description\">\n\t\t\t\t\t\t{{ truncatedDescription }}\n\t\t\t\t\t</p>\n\t\t\t\t</div>\n\t\t\t\t<!-- Board look, end of the head: the status pill, or else the row menu. -->\n\t\t\t\t<template v-if=\"isBoardLook\">\n\t\t\t\t\t<CnStatusBadge\n\t\t\t\t\t\tv-if=\"statusPill\"\n\t\t\t\t\t\tclass=\"cn-object-card__status\"\n\t\t\t\t\t\t:label=\"statusPill.label\"\n\t\t\t\t\t\t:variant=\"statusPill.variant\"\n\t\t\t\t\t\tdata-testid=\"cn-object-card-status\" />\n\t\t\t\t\t<div\n\t\t\t\t\t\tv-else-if=\"$slots.actions\"\n\t\t\t\t\t\tclass=\"cn-object-card__menu\"\n\t\t\t\t\t\t@click.stop\n\t\t\t\t\t\t@auxclick.stop>\n\t\t\t\t\t\t<slot name=\"actions\" :object=\"object\" />\n\t\t\t\t\t</div>\n\t\t\t\t</template>\n\t\t\t</div>\n\n\t\t\t<!-- Badges slot -->\n\t\t\t<div v-if=\"$slots.badges\" class=\"cn-object-card__badges\">\n\t\t\t\t<slot name=\"badges\" :object=\"object\" />\n\t\t\t</div>\n\n\t\t\t<!-- Metadata: visible properties as label:value pairs -->\n\t\t\t<div v-if=\"metadataFields.length > 0\" class=\"cn-object-card__metadata\" :class=\"{ 'cn-object-card__metadata--facts': isBoardLook }\">\n\t\t\t\t<slot name=\"metadata\" :object=\"object\" :fields=\"metadataFields\">\n\t\t\t\t\t<div\n\t\t\t\t\t\tv-for=\"field in metadataFields\"\n\t\t\t\t\t\t:key=\"field.key\"\n\t\t\t\t\t\tclass=\"cn-object-card__meta-item\">\n\t\t\t\t\t\t<span class=\"cn-object-card__meta-label\">{{ field.label }}</span>\n\t\t\t\t\t\t<CnCellRenderer\n\t\t\t\t\t\t\t:value=\"field.value\"\n\t\t\t\t\t\t\t:property=\"field.property\"\n\t\t\t\t\t\t\t:truncate=\"60\" />\n\t\t\t\t\t</div>\n\t\t\t\t</slot>\n\t\t\t</div>\n\n\t\t\t<!-- Board look: one footer action, with a muted meta text at the start. -->\n\t\t\t<div\n\t\t\t\tv-if=\"isBoardLook && footerAction\"\n\t\t\t\tclass=\"cn-object-card__footer\"\n\t\t\t\tdata-testid=\"cn-object-card-footer\"\n\t\t\t\t@click.stop\n\t\t\t\t@auxclick.stop>\n\t\t\t\t<span v-if=\"footerAction.meta\" class=\"cn-object-card__footer-meta\">{{ footerAction.meta }}</span>\n\t\t\t\t<NcButton\n\t\t\t\t\tvariant=\"secondary\"\n\t\t\t\t\tclass=\"cn-object-card__footer-action\"\n\t\t\t\t\tdata-testid=\"cn-object-card-footer-action\"\n\t\t\t\t\t:aria-label=\"footerAction.ariaLabel || `${footerAction.label} ${title}`\"\n\t\t\t\t\t@click=\"$emit('footer-action', object, footerAction)\">\n\t\t\t\t\t{{ footerAction.label }}\n\t\t\t\t</NcButton>\n\t\t\t</div>\n\t\t</div>\n\n\t\t<!-- Actions slot -->\n\t\t<div v-if=\"$slots.actions && !isBoardLook\"\n\t\t\tclass=\"cn-object-card__actions\"\n\t\t\t@click.stop\n\t\t\t@auxclick.stop>\n\t\t\t<slot name=\"actions\" :object=\"object\" />\n\t\t</div>\n\t</div>\n</template>\n\n<script>\nimport { NcButton, NcCheckboxRadioSwitch } from '@nextcloud/vue'\nimport { useClickDragGuard } from '../../composables/useClickDragGuard.js'\nimport { normalizeLook } from '../../composables/useLook.js'\nimport { resolveImageUrl } from '../../utils/resolveImageUrl.js'\nimport { isRowMiddleClick, preventMiddleClickAutoscroll } from '../../utils/rowAuxClick.js'\nimport { formatValue } from '../../utils/schema.js'\nimport { CnCellRenderer } from '../CnCellRenderer/index.js'\nimport { CnIcon } from '../CnIcon/index.js'\nimport { CnLockIndicator } from '../CnLockIndicator/index.js'\nimport { CnStatusBadge } from '../CnStatusBadge/index.js'\n\nconst ACCENT_VARIANTS = ['success', 'warning', 'error', 'info', 'primary']\n\n/**\n * CnObjectCard — Schema-configuration-driven card for object display.\n *\n * Uses `schema.configuration` to determine which fields map to the card title,\n * description, and image. Remaining visible properties are shown as metadata.\n *\n * ```vue\n * <CnObjectCard :object=\"publication\" :schema=\"pubSchema\">\n * <template #actions=\"{ object }\">\n * <NcActions><NcActionButton @click=\"edit(object)\">Edit</NcActionButton></NcActions>\n * </template>\n * </CnObjectCard>\n * ```\n */\nexport default {\n\tname: 'CnObjectCard',\n\n\tcomponents: {\n\t\tNcButton,\n\t\tNcCheckboxRadioSwitch,\n\t\tCnCellRenderer,\n\t\tCnIcon,\n\t\tCnLockIndicator,\n\t\tCnStatusBadge,\n\t},\n\n\tinject: {\n\t\t/**\n\t\t * Consumer translation function, provided by CnAppRoot as\n\t\t * `cnTranslate: this.translate` (bound to the host app's id). Metadata\n\t\t * labels come from schema property titles, authored in English as the\n\t\t * canonical source; the visible label is resolved through this function\n\t\t * so it follows the user's language. Defaults to identity when used\n\t\t * standalone (no CnAppRoot ancestor).\n\t\t */\n\t\tcnTranslate: { default: () => (key) => key },\n\t\t/** The look CnAppRoot provides; `board` draws the record card of the screens. */\n\t\tcnLook: { default: 'nextcloud' },\n\t},\n\n\tprops: {\n\t\t/** The object data */\n\t\tobject: {\n\t\t\ttype: Object,\n\t\t\trequired: true,\n\t\t},\n\n\t\t/** Schema definition with properties and configuration */\n\t\tschema: {\n\t\t\ttype: Object,\n\t\t\trequired: true,\n\t\t},\n\n\t\t/** Whether this card is selected */\n\t\tselected: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\n\t\t/** Whether to show selection checkbox */\n\t\tselectable: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\n\t\t/**\n\t\t * When true, a body click on a SELECTABLE card emits `click`\n\t\t * (navigation) instead of toggling selection — selection then happens\n\t\t * via the checkbox only. The card counterpart of CnIndexPage's\n\t\t * `rowClickToView` (a table row click already navigates in that mode).\n\t\t *\n\t\t * @type {boolean}\n\t\t */\n\t\tclickToView: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\n\t\t/**\n\t\t * Board look: the status pill at the end of the head row, as a label\n\t\t * (`\"Open\"`) or `{ label, variant }` with a CnStatusBadge variant\n\t\t * (`success`, `warning`, `error`, `info`, `primary`, `default`).\n\t\t * Without it the head row ends in the row menu, when there is one.\n\t\t *\n\t\t * @type {(string|{label: string, variant?: string})}\n\t\t * @spec openspec/changes/screens-card-parity/specs/card-board-look/spec.md#requirement-a-record-card-has-a-head-facts-and-one-action\n\t\t */\n\t\tstatus: {\n\t\t\ttype: [String, Object],\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/**\n\t\t * Board look: the leading element of the head row. `{ initials }`\n\t\t * draws the initials in a 36px circle; `{ icon }` a schema icon in a\n\t\t * 36px rounded square on a tint.\n\t\t *\n\t\t * @type {{initials?: string, icon?: string}}\n\t\t */\n\t\tleading: {\n\t\t\ttype: Object,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/**\n\t\t * Board look: the card's one footer action. `{ label, meta?,\n\t\t * ariaLabel? }`; `meta` is the 13px muted text at the start of the\n\t\t * footer. Clicking emits `footer-action`.\n\t\t *\n\t\t * @type {{label: string, meta?: string, ariaLabel?: string}}\n\t\t */\n\t\tfooterAction: {\n\t\t\ttype: Object,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/**\n\t\t * A status accent: a colored border at the start of the card and,\n\t\t * with `icon`, a colored icon before the title. `variant` is one of\n\t\t * `success`, `warning`, `error`, `info` or `primary`; `icon` is a\n\t\t * name registered with CnIcon; `label` names the status for screen\n\t\t * readers and as the icon's tooltip.\n\t\t *\n\t\t * @type {{variant: string, icon?: string, label?: string}}\n\t\t */\n\t\taccent: {\n\t\t\ttype: Object,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/**\n\t\t * The property keys the facts list shows, in order (manifest key\n\t\t * `config.cardFields`). Without it the card shows the first\n\t\t * `maxMetadata` visible properties, as before.\n\t\t *\n\t\t * @type {Array<string>}\n\t\t */\n\t\tcardFields: {\n\t\t\ttype: Array,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/** Maximum number of metadata fields to show */\n\t\tmaxMetadata: {\n\t\t\ttype: Number,\n\t\t\tdefault: 4,\n\t\t},\n\t},\n\n\temits: ['click', 'select', 'aux-click', 'footer-action'],\n\n\tsetup() {\n\t\t// Tell a deliberate card click apart from a text-selection drag.\n\t\treturn useClickDragGuard()\n\t},\n\n\tcomputed: {\n\t\t/**\n\t\t * Whether the record card of the board look is drawn.\n\t\t *\n\t\t * @return {boolean}\n\t\t */\n\t\tisBoardLook() {\n\t\t\treturn normalizeLook(this.cnLook) === 'board'\n\t\t},\n\n\t\t/**\n\t\t * `initials`, `icon` or '' for the head row's leading element.\n\t\t *\n\t\t * @return {string}\n\t\t */\n\t\tleadingKind() {\n\t\t\tif (this.leading && typeof this.leading.initials === 'string' && this.leading.initials !== '') {\n\t\t\t\treturn 'initials'\n\t\t\t}\n\t\t\treturn this.leading && typeof this.leading.icon === 'string' && this.leading.icon !== '' ? 'icon' : ''\n\t\t},\n\n\t\t/**\n\t\t * The status as `{ label, variant }`, or null.\n\t\t *\n\t\t * @return {?{label: string, variant: string}}\n\t\t */\n\t\tstatusPill() {\n\t\t\tif (typeof this.status === 'string' && this.status !== '') {\n\t\t\t\treturn { label: this.status, variant: 'default' }\n\t\t\t}\n\t\t\tif (this.status && typeof this.status.label === 'string' && this.status.label !== '') {\n\t\t\t\treturn { label: this.status.label, variant: this.status.variant || 'default' }\n\t\t\t}\n\t\t\treturn null\n\t\t},\n\n\t\t/**\n\t\t * The accent variant when it is a known one, else ''.\n\t\t *\n\t\t * @return {string}\n\t\t */\n\t\taccentVariant() {\n\t\t\tconst variant = this.accent?.variant\n\t\t\treturn ACCENT_VARIANTS.includes(variant) ? variant : ''\n\t\t},\n\n\t\tconfig() {\n\t\t\treturn this.schema?.configuration || {}\n\t\t},\n\n\t\ttitle() {\n\t\t\tconst field = this.config.objectNameField\n\t\t\tif (field && this.object[field]) {\n\t\t\t\treturn String(this.object[field])\n\t\t\t}\n\t\t\treturn this.object.title || this.object.name || this.object.id || '—'\n\t\t},\n\n\t\tdescription() {\n\t\t\tconst field = this.config.objectDescriptionField\n\t\t\tif (field && this.object[field]) {\n\t\t\t\treturn String(this.object[field])\n\t\t\t}\n\t\t\treturn null\n\t\t},\n\n\t\ttruncatedDescription() {\n\t\t\tif (!this.description) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tif (this.description.length > 120) {\n\t\t\t\treturn this.description.substring(0, 120) + '...'\n\t\t\t}\n\t\t\treturn this.description\n\t\t},\n\n\t\timageUrl() {\n\t\t\tconst field = this.config.objectImageField\n\t\t\tif (field && this.object[field]) {\n\t\t\t\treturn resolveImageUrl(this.object[field])\n\t\t\t}\n\t\t\treturn null\n\t\t},\n\n\t\t/** Fields excluded from metadata (already shown as title/desc/image) */\n\t\tconfigFields() {\n\t\t\treturn [\n\t\t\t\tthis.config.objectNameField,\n\t\t\t\tthis.config.objectDescriptionField,\n\t\t\t\tthis.config.objectSummaryField,\n\t\t\t\tthis.config.objectImageField,\n\t\t\t].filter(Boolean)\n\t\t},\n\n\t\t/** Remaining visible properties for the metadata section */\n\t\tmetadataFields() {\n\t\t\tif (!this.schema?.properties) {\n\t\t\t\treturn []\n\t\t\t}\n\n\t\t\t// The page names the facts: those properties, in that order.\n\t\t\tif (Array.isArray(this.cardFields)) {\n\t\t\t\treturn this.cardFields\n\t\t\t\t\t.filter((key) => typeof key === 'string' && this.schema.properties[key] && !this.configFields.includes(key))\n\t\t\t\t\t.map((key) => ({\n\t\t\t\t\t\tkey,\n\t\t\t\t\t\tlabel: this.cnTranslate(this.schema.properties[key].title || key),\n\t\t\t\t\t\tvalue: this.object[key],\n\t\t\t\t\t\tproperty: this.schema.properties[key],\n\t\t\t\t\t}))\n\t\t\t}\n\n\t\t\treturn Object.entries(this.schema.properties)\n\t\t\t\t.filter(([key, prop]) => {\n\t\t\t\t\tif (this.configFields.includes(key)) {\n\t\t\t\t\t\treturn false\n\t\t\t\t\t}\n\t\t\t\t\tif (prop.visible === false) {\n\t\t\t\t\t\treturn false\n\t\t\t\t\t}\n\t\t\t\t\tif (prop.type === 'object') {\n\t\t\t\t\t\treturn false\n\t\t\t\t\t}\n\t\t\t\t\tif (prop.format === 'markdown') {\n\t\t\t\t\t\treturn false\n\t\t\t\t\t}\n\t\t\t\t\treturn true\n\t\t\t\t})\n\t\t\t\t.sort(([, a], [, b]) => {\n\t\t\t\t\tconst orderA = typeof a.order === 'number' ? a.order : Infinity\n\t\t\t\t\tconst orderB = typeof b.order === 'number' ? b.order : Infinity\n\t\t\t\t\treturn orderA - orderB\n\t\t\t\t})\n\t\t\t\t.slice(0, this.maxMetadata)\n\t\t\t\t.map(([key, prop]) => ({\n\t\t\t\t\tkey,\n\t\t\t\t\tlabel: this.cnTranslate(prop.title || key),\n\t\t\t\t\tvalue: this.object[key],\n\t\t\t\t\tproperty: prop,\n\t\t\t\t}))\n\t\t},\n\t},\n\n\tmethods: {\n\t\tformatValue,\n\n\t\t/**\n\t\t * Card-body click: emits `select` when `selectable` (ignoring drags),\n\t\t * otherwise emits `click` for navigation. With `clickToView`, a\n\t\t * selectable card's body click navigates too — the checkbox is the\n\t\t * only selection surface, mirroring the table's rowClickToView split.\n\t\t *\n\t\t * @param {MouseEvent} [event] The originating click event.\n\t\t */\n\t\tonCardClick(event) {\n\t\t\tif (this.selectable && !this.clickToView) {\n\t\t\t\tif (this.wasDrag(event)) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\t/**\n\t\t\t\t * @event select Emitted when the card toggles selection (clicking the body of a selectable card, or its checkbox).\n\t\t\t\t * @type {object} The card's object.\n\t\t\t\t */\n\t\t\t\tthis.$emit('select', this.object)\n\t\t\t\t// Deprecation: selectable cards used to emit `click`. Keep emitting it\n\t\t\t\t// for listeners that still rely on it, but warn them to migrate to `select`.\n\t\t\t\t// `$.vnode.props`, not `$attrs`: `click` is a declared emit, and\n\t\t\t\t// Vue keeps declared emits out of `$attrs`.\n\t\t\t\tif (this.$.vnode.props?.onClick) {\n\t\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\t\tconsole.warn('[CnObjectCard] @click on selectable cards is deprecated; use @select instead.')\n\t\t\t\t\tthis.$emit('click', this.object)\n\t\t\t\t}\n\t\t\t\treturn\n\t\t\t}\n\t\t\t/**\n\t\t\t * @event click Emitted when a non-selectable (or `clickToView`) card is clicked. Payload: `(object, event)` — the card's object and the native click event, for opening it in a new tab on a ctrl/cmd/shift click. A middle click emits `aux-click` instead. Selectable cards emit `select`; they also emit `click` (deprecated) when a `click` listener is present, so migrate selectable consumers to `@select`.\n\t\t\t * @type {object} The card's object.\n\t\t\t */\n\t\t\tthis.$emit('click', this.object, event)\n\t\t},\n\n\t\t/**\n\t\t * Card mousedown: record the press for the drag guard, and on a card a\n\t\t * middle click opens, keep the browser from starting autoscroll.\n\t\t *\n\t\t * @param {MouseEvent} event The mousedown event.\n\t\t */\n\t\tonCardMouseDown(event) {\n\t\t\tthis.onPointerDown(event)\n\t\t\tif (!this.selectable || this.clickToView) {\n\t\t\t\tpreventMiddleClickAutoscroll(event)\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Card-body middle click: emits `aux-click`, not `click`, so an existing\n\t\t * `click` listener that navigates never moves the current tab away.\n\t\t * Ignored on a select-on-click card, on nested controls and on drags.\n\t\t *\n\t\t * @param {MouseEvent} event The auxclick event.\n\t\t */\n\t\tonCardAuxClick(event) {\n\t\t\tif (!isRowMiddleClick(event) || this.wasDrag(event)) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif (this.selectable && !this.clickToView) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\t/**\n\t\t\t * @event aux-click Emitted when a non-selectable (or `clickToView`) card is middle-clicked, for opening it in a new tab (see `openRowTarget`). Payload: `(object, event)` — the card's object and the native auxclick event.\n\t\t\t * @type {object} The card's object.\n\t\t\t */\n\t\t\tthis.$emit('aux-click', this.object, event)\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n.cn-object-card {\n\tdisplay: flex;\n\tgap: 12px;\n\tpadding: 16px;\n\tbackground: var(--color-main-background);\n\tborder: 1px solid var(--color-border);\n\tborder-radius: var(--border-radius-large, 10px);\n\tcursor: pointer;\n\ttransition: box-shadow 0.2s ease, border-color 0.2s ease;\n}\n\n.cn-object-card:hover {\n\tborder-color: var(--color-primary-element);\n\tbox-shadow: 0 2px 8px var(--color-box-shadow);\n}\n\n.cn-object-card--selected {\n\tborder-color: var(--color-primary-element);\n\tbackground: var(--color-primary-element-light);\n}\n\n/* The 4px start border takes 3px of padding, so the content stays put. */\n.cn-object-card.cn-object-card--accent {\n\tborder-inline-start-width: 4px;\n\tpadding-inline-start: 13px;\n}\n\n.cn-object-card.cn-object-card--accent-success {\n\tborder-inline-start-color: var(--color-element-success);\n}\n\n.cn-object-card.cn-object-card--accent-warning {\n\tborder-inline-start-color: var(--color-element-warning);\n}\n\n.cn-object-card.cn-object-card--accent-error {\n\tborder-inline-start-color: var(--color-element-error);\n}\n\n.cn-object-card.cn-object-card--accent-info {\n\tborder-inline-start-color: var(--color-element-info);\n}\n\n.cn-object-card.cn-object-card--accent-primary {\n\tborder-inline-start-color: var(--color-primary-element);\n}\n\n.cn-object-card__accent-icon {\n\tdisplay: inline-flex;\n\tvertical-align: -2px;\n\tmargin-inline-end: 4px;\n}\n\n.cn-object-card--accent-success .cn-object-card__accent-icon {\n\tcolor: var(--color-text-success);\n}\n\n.cn-object-card--accent-warning .cn-object-card__accent-icon {\n\tcolor: var(--color-text-warning);\n}\n\n.cn-object-card--accent-error .cn-object-card__accent-icon {\n\tcolor: var(--color-text-error);\n}\n\n.cn-object-card--accent-info .cn-object-card__accent-icon {\n\tcolor: var(--color-element-info);\n}\n\n.cn-object-card--accent-primary .cn-object-card__accent-icon {\n\tcolor: var(--color-primary-element);\n}\n\n.cn-object-card__checkbox {\n\tflex-shrink: 0;\n\tpadding-top: 2px;\n}\n\n.cn-object-card__content {\n\tflex: 1;\n\tmin-width: 0;\n}\n\n.cn-object-card__header {\n\tdisplay: flex;\n\tgap: 12px;\n\talign-items: flex-start;\n}\n\n.cn-object-card__image {\n\twidth: 48px;\n\theight: 48px;\n\tborder-radius: var(--border-radius);\n\tobject-fit: cover;\n\tflex-shrink: 0;\n}\n\n.cn-object-card__title-area {\n\tflex: 1;\n\tmin-width: 0;\n}\n\n.cn-object-card__title {\n\tmargin: 0;\n\tfont-size: 16px;\n\tfont-weight: 600;\n\tline-height: 1.3;\n\toverflow: hidden;\n\ttext-overflow: ellipsis;\n\twhite-space: nowrap;\n}\n\n.cn-object-card__description {\n\tmargin: 4px 0 0;\n\tfont-size: 13px;\n\tcolor: var(--color-text-maxcontrast);\n\tline-height: 1.4;\n}\n\n.cn-object-card__badges {\n\tmargin-top: 8px;\n}\n\n.cn-object-card__metadata {\n\tdisplay: grid;\n\tgrid-template-columns: repeat(auto-fill, minmax(160px, 1fr));\n\tgap: 8px;\n\tmargin-top: 12px;\n\tpadding-top: 12px;\n\tborder-top: 1px solid var(--color-border);\n}\n\n.cn-object-card__meta-item {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 2px;\n}\n\n.cn-object-card__meta-label {\n\tfont-size: 11px;\n\tfont-weight: 500;\n\tcolor: var(--color-text-maxcontrast);\n\ttext-transform: uppercase;\n\tletter-spacing: 0.3px;\n}\n\n.cn-object-card__actions {\n\tflex-shrink: 0;\n}\n</style>\n"],"names":["_createElementBlock","_normalizeClass","_createVNode","_createElementVNode","_Fragment","_createTextVNode","_toDisplayString","_createBlock","_renderSlot","_openBlock","_renderList"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"CnObjectCard.vue3.js","sources":["../../../../src/components/CnObjectCard/CnObjectCard.vue?vue&type=template&id=78efa77e&lang.js"],"sourcesContent":["<template>\n\t<div\n\t\tclass=\"cn-object-card\"\n\t\t:class=\"[{ 'cn-object-card--selected': selected, 'cn-object-card--board': isBoardLook }, accentVariant && ['cn-object-card--accent', `cn-object-card--accent-${accentVariant}`]]\"\n\t\t@mousedown=\"onCardMouseDown\"\n\t\t@click=\"onCardClick($event)\"\n\t\t@auxclick=\"onCardAuxClick($event)\">\n\t\t<!-- Selection checkbox -->\n\t\t<div v-if=\"selectable\"\n\t\t\tclass=\"cn-object-card__checkbox\"\n\t\t\t@click.stop\n\t\t\t@auxclick.stop>\n\t\t\t<NcCheckboxRadioSwitch\n\t\t\t\t:modelValue=\"selected\"\n\t\t\t\t@update:modelValue=\"$emit('select', object)\" />\n\t\t</div>\n\n\t\t<!-- Board look, record layout (`layout`): head pill and number, title,\n\t\t meta line, then a footer with a pill and a date. -->\n\t\t<div v-if=\"recordLayout\" class=\"cn-object-card__content cn-object-card__record\" data-testid=\"cn-object-card-record\">\n\t\t\t<div class=\"cn-object-card__record-head\">\n\t\t\t\t<CnStatusBadge\n\t\t\t\t\tv-if=\"recordHeadPill\"\n\t\t\t\t\tclass=\"cn-object-card__record-pill\"\n\t\t\t\t\t:label=\"recordHeadPill.label\"\n\t\t\t\t\t:variant=\"recordHeadPill.variant\"\n\t\t\t\t\tdata-testid=\"cn-object-card-head-pill\" />\n\t\t\t\t<span v-if=\"recordNumber\" class=\"cn-object-card__record-number\" data-testid=\"cn-object-card-number\">{{ recordNumber }}</span>\n\t\t\t\t<div\n\t\t\t\t\tv-if=\"$slots.actions\"\n\t\t\t\t\tclass=\"cn-object-card__menu\"\n\t\t\t\t\t@click.stop\n\t\t\t\t\t@auxclick.stop>\n\t\t\t\t\t<slot name=\"actions\" :object=\"object\" />\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<h3 class=\"cn-object-card__title\">\n\t\t\t\t<CnLockIndicator :object=\"object\" :size=\"16\" />\n\t\t\t\t{{ recordTitle }}\n\t\t\t</h3>\n\t\t\t<!-- A part whose field names a page column with a widget draws through\n\t\t\t it, as its table cell does; the rest are text. -->\n\t\t\t<p v-if=\"recordMetaParts.length > 0\" class=\"cn-object-card__record-meta\" data-testid=\"cn-object-card-meta\">\n\t\t\t\t<template v-for=\"(part, index) in recordMetaParts\" :key=\"part.field\">\n\t\t\t\t\t<span v-if=\"index > 0\" aria-hidden=\"true\"> · </span>\n\t\t\t\t\t<CnCellRenderer\n\t\t\t\t\t\tv-if=\"part.column && part.column.widget\"\n\t\t\t\t\t\t:value=\"part.value\"\n\t\t\t\t\t\t:widget=\"part.column.widget\"\n\t\t\t\t\t\t:widgetProps=\"part.column.widgetProps || undefined\"\n\t\t\t\t\t\t:formatter=\"part.column.formatter || null\"\n\t\t\t\t\t\t:formatterOptions=\"part.column.formatterOptions || null\"\n\t\t\t\t\t\t:row=\"object\" />\n\t\t\t\t\t<span v-else>{{ part.text }}</span>\n\t\t\t\t</template>\n\t\t\t</p>\n\t\t\t<div v-if=\"$slots.badges\" class=\"cn-object-card__badges\">\n\t\t\t\t<slot name=\"badges\" :object=\"object\" />\n\t\t\t</div>\n\t\t\t<div v-if=\"recordFootPill || recordDate\" class=\"cn-object-card__record-foot\" data-testid=\"cn-object-card-foot\">\n\t\t\t\t<CnStatusBadge\n\t\t\t\t\tv-if=\"recordFootPill\"\n\t\t\t\t\tclass=\"cn-object-card__record-pill\"\n\t\t\t\t\t:label=\"recordFootPill.label\"\n\t\t\t\t\t:variant=\"recordFootPill.variant\"\n\t\t\t\t\tdata-testid=\"cn-object-card-foot-pill\" />\n\t\t\t\t<span v-if=\"recordDate\" class=\"cn-object-card__record-date\" data-testid=\"cn-object-card-date\">{{ recordDate }}</span>\n\t\t\t</div>\n\t\t</div>\n\n\t\t<!-- Card content -->\n\t\t<div v-else class=\"cn-object-card__content\">\n\t\t\t<!-- Header: image + title -->\n\t\t\t<div class=\"cn-object-card__header\">\n\t\t\t\t<!-- Board look: the leading element, initials in a circle or an icon on a tint. -->\n\t\t\t\t<span\n\t\t\t\t\tv-if=\"isBoardLook && leadingKind\"\n\t\t\t\t\tclass=\"cn-object-card__leading\"\n\t\t\t\t\t:class=\"`cn-object-card__leading--${leadingKind}`\"\n\t\t\t\t\tdata-testid=\"cn-object-card-leading\"\n\t\t\t\t\taria-hidden=\"true\">\n\t\t\t\t\t<template v-if=\"leadingKind === 'initials'\">{{ leading.initials }}</template>\n\t\t\t\t\t<CnIcon v-else :name=\"leading.icon\" :size=\"20\" />\n\t\t\t\t</span>\n\t\t\t\t<img\n\t\t\t\t\tv-if=\"imageUrl\"\n\t\t\t\t\t:src=\"imageUrl\"\n\t\t\t\t\t:alt=\"title\"\n\t\t\t\t\tclass=\"cn-object-card__image\">\n\n\t\t\t\t<div class=\"cn-object-card__title-area\">\n\t\t\t\t\t<h3 class=\"cn-object-card__title\">\n\t\t\t\t\t\t<!-- Beside the title, not in the badges row: the badges\n\t\t\t\t\t\t slot is the consumer's, and a lock is the library's\n\t\t\t\t\t\t to report. A card whose consumer passes no badges\n\t\t\t\t\t\t would otherwise show no padlock at all. -->\n\t\t\t\t\t\t<CnLockIndicator :object=\"object\" :size=\"16\" />\n\t\t\t\t\t\t<span\n\t\t\t\t\t\t\tv-if=\"accentVariant && accent.icon\"\n\t\t\t\t\t\t\tclass=\"cn-object-card__accent-icon\"\n\t\t\t\t\t\t\tdata-testid=\"cn-object-card-accent-icon\"\n\t\t\t\t\t\t\t:role=\"accent.label ? 'img' : null\"\n\t\t\t\t\t\t\t:aria-label=\"accent.label || null\"\n\t\t\t\t\t\t\t:aria-hidden=\"accent.label ? null : 'true'\"\n\t\t\t\t\t\t\t:title=\"accent.label || null\">\n\t\t\t\t\t\t\t<CnIcon :name=\"accent.icon\" :size=\"16\" />\n\t\t\t\t\t\t</span>\n\t\t\t\t\t\t{{ title }}\n\t\t\t\t\t</h3>\n\t\t\t\t\t<p v-if=\"description\" class=\"cn-object-card__description\">\n\t\t\t\t\t\t{{ truncatedDescription }}\n\t\t\t\t\t</p>\n\t\t\t\t</div>\n\t\t\t\t<!-- Board look, end of the head: the status pill, or else the row menu. -->\n\t\t\t\t<template v-if=\"isBoardLook\">\n\t\t\t\t\t<CnStatusBadge\n\t\t\t\t\t\tv-if=\"statusPill\"\n\t\t\t\t\t\tclass=\"cn-object-card__status\"\n\t\t\t\t\t\t:label=\"statusPill.label\"\n\t\t\t\t\t\t:variant=\"statusPill.variant\"\n\t\t\t\t\t\tdata-testid=\"cn-object-card-status\" />\n\t\t\t\t\t<div\n\t\t\t\t\t\tv-else-if=\"$slots.actions\"\n\t\t\t\t\t\tclass=\"cn-object-card__menu\"\n\t\t\t\t\t\t@click.stop\n\t\t\t\t\t\t@auxclick.stop>\n\t\t\t\t\t\t<slot name=\"actions\" :object=\"object\" />\n\t\t\t\t\t</div>\n\t\t\t\t</template>\n\t\t\t</div>\n\n\t\t\t<!-- Badges slot -->\n\t\t\t<div v-if=\"$slots.badges\" class=\"cn-object-card__badges\">\n\t\t\t\t<slot name=\"badges\" :object=\"object\" />\n\t\t\t</div>\n\n\t\t\t<!-- Metadata: visible properties as label:value pairs -->\n\t\t\t<div v-if=\"metadataFields.length > 0\" class=\"cn-object-card__metadata\" :class=\"{ 'cn-object-card__metadata--facts': isBoardLook }\">\n\t\t\t\t<slot name=\"metadata\" :object=\"object\" :fields=\"metadataFields\">\n\t\t\t\t\t<div\n\t\t\t\t\t\tv-for=\"field in metadataFields\"\n\t\t\t\t\t\t:key=\"field.key\"\n\t\t\t\t\t\tclass=\"cn-object-card__meta-item\">\n\t\t\t\t\t\t<span class=\"cn-object-card__meta-label\">{{ field.label }}</span>\n\t\t\t\t\t\t<CnCellRenderer\n\t\t\t\t\t\t\t:value=\"field.value\"\n\t\t\t\t\t\t\t:property=\"field.property\"\n\t\t\t\t\t\t\t:formatter=\"field.column && field.column.formatter || null\"\n\t\t\t\t\t\t\t:formatterOptions=\"field.column && field.column.formatterOptions || null\"\n\t\t\t\t\t\t\t:widget=\"field.column && field.column.widget || null\"\n\t\t\t\t\t\t\t:widgetProps=\"field.column && field.column.widgetProps || undefined\"\n\t\t\t\t\t\t\t:row=\"object\"\n\t\t\t\t\t\t\t:truncate=\"60\" />\n\t\t\t\t\t</div>\n\t\t\t\t</slot>\n\t\t\t</div>\n\n\t\t\t<!-- Board look: one footer action, with a muted meta text at the start. -->\n\t\t\t<div\n\t\t\t\tv-if=\"isBoardLook && footerAction\"\n\t\t\t\tclass=\"cn-object-card__footer\"\n\t\t\t\tdata-testid=\"cn-object-card-footer\"\n\t\t\t\t@click.stop\n\t\t\t\t@auxclick.stop>\n\t\t\t\t<span v-if=\"footerAction.meta\" class=\"cn-object-card__footer-meta\">{{ footerAction.meta }}</span>\n\t\t\t\t<NcButton\n\t\t\t\t\tvariant=\"secondary\"\n\t\t\t\t\tclass=\"cn-object-card__footer-action\"\n\t\t\t\t\tdata-testid=\"cn-object-card-footer-action\"\n\t\t\t\t\t:aria-label=\"footerAction.ariaLabel || `${footerAction.label} ${title}`\"\n\t\t\t\t\t@click=\"$emit('footer-action', object, footerAction)\">\n\t\t\t\t\t{{ footerAction.label }}\n\t\t\t\t</NcButton>\n\t\t\t</div>\n\t\t</div>\n\n\t\t<!-- Actions slot -->\n\t\t<div v-if=\"$slots.actions && !isBoardLook\"\n\t\t\tclass=\"cn-object-card__actions\"\n\t\t\t@click.stop\n\t\t\t@auxclick.stop>\n\t\t\t<slot name=\"actions\" :object=\"object\" />\n\t\t</div>\n\t</div>\n</template>\n\n<script>\nimport { translate as t } from '@nextcloud/l10n'\nimport { NcButton, NcCheckboxRadioSwitch } from '@nextcloud/vue'\nimport { useClickDragGuard } from '../../composables/useClickDragGuard.js'\nimport { normalizeLook } from '../../composables/useLook.js'\nimport { isBadgeVariant } from '../../utils/badgeVariants.js'\nimport { formatBoardDate } from '../../utils/boardDate.js'\nimport { resolveDateVariant } from '../../utils/dateVariant.js'\nimport { resolveDue } from '../../utils/dueText.js'\nimport { readPath } from '../../utils/readPath.js'\nimport { resolveImageUrl } from '../../utils/resolveImageUrl.js'\nimport { isRowMiddleClick, preventMiddleClickAutoscroll } from '../../utils/rowAuxClick.js'\nimport { formatValue } from '../../utils/schema.js'\nimport { CnCellRenderer } from '../CnCellRenderer/index.js'\nimport { CnIcon } from '../CnIcon/index.js'\nimport { CnLockIndicator } from '../CnLockIndicator/index.js'\nimport { CnStatusBadge } from '../CnStatusBadge/index.js'\n\nconst ACCENT_VARIANTS = ['success', 'warning', 'error', 'info', 'primary']\n\n/**\n * CnObjectCard — Schema-configuration-driven card for object display.\n *\n * Uses `schema.configuration` to determine which fields map to the card title,\n * description, and image. Remaining visible properties are shown as metadata.\n *\n * ```vue\n * <CnObjectCard :object=\"publication\" :schema=\"pubSchema\">\n * <template #actions=\"{ object }\">\n * <NcActions><NcActionButton @click=\"edit(object)\">Edit</NcActionButton></NcActions>\n * </template>\n * </CnObjectCard>\n * ```\n */\nexport default {\n\tname: 'CnObjectCard',\n\n\tcomponents: {\n\t\tNcButton,\n\t\tNcCheckboxRadioSwitch,\n\t\tCnCellRenderer,\n\t\tCnIcon,\n\t\tCnLockIndicator,\n\t\tCnStatusBadge,\n\t},\n\n\tinject: {\n\t\t/**\n\t\t * Consumer translation function, provided by CnAppRoot as\n\t\t * `cnTranslate: this.translate` (bound to the host app's id). Metadata\n\t\t * labels come from schema property titles, authored in English as the\n\t\t * canonical source; the visible label is resolved through this function\n\t\t * so it follows the user's language. Defaults to identity when used\n\t\t * standalone (no CnAppRoot ancestor).\n\t\t */\n\t\tcnTranslate: { default: () => (key) => key },\n\t\t/** The look CnAppRoot provides; `board` draws the record card of the screens. */\n\t\tcnLook: { default: 'nextcloud' },\n\t\t/** The cell formatters CnAppRoot provides, for a layout part whose page column names one. */\n\t\tcnFormatters: { default: () => ({}) },\n\t},\n\n\tprops: {\n\t\t/** The object data */\n\t\tobject: {\n\t\t\ttype: Object,\n\t\t\trequired: true,\n\t\t},\n\n\t\t/** Schema definition with properties and configuration */\n\t\tschema: {\n\t\t\ttype: Object,\n\t\t\trequired: true,\n\t\t},\n\n\t\t/** Whether this card is selected */\n\t\tselected: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\n\t\t/** Whether to show selection checkbox */\n\t\tselectable: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\n\t\t/**\n\t\t * When true, a body click on a SELECTABLE card emits `click`\n\t\t * (navigation) instead of toggling selection — selection then happens\n\t\t * via the checkbox only. The card counterpart of CnIndexPage's\n\t\t * `rowClickToView` (a table row click already navigates in that mode).\n\t\t *\n\t\t * @type {boolean}\n\t\t */\n\t\tclickToView: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\n\t\t/**\n\t\t * Board look: the status pill at the end of the head row, as a label\n\t\t * (`\"Open\"`) or `{ label, variant }` with a CnStatusBadge variant\n\t\t * (`success`, `warning`, `error`, `info`, `primary`, `default`).\n\t\t * Without it the head row ends in the row menu, when there is one.\n\t\t *\n\t\t * @type {(string|{label: string, variant?: string})}\n\t\t * @spec openspec/changes/screens-card-parity/specs/card-board-look/spec.md#requirement-a-record-card-has-a-head-facts-and-one-action\n\t\t */\n\t\tstatus: {\n\t\t\ttype: [String, Object],\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/**\n\t\t * Board look: the leading element of the head row. `{ initials }`\n\t\t * draws the initials in a 36px circle; `{ icon }` a schema icon in a\n\t\t * 36px rounded square on a tint.\n\t\t *\n\t\t * @type {{initials?: string, icon?: string}}\n\t\t */\n\t\tleading: {\n\t\t\ttype: Object,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/**\n\t\t * Board look: the card's one footer action. `{ label, meta?,\n\t\t * ariaLabel? }`; `meta` is the 13px muted text at the start of the\n\t\t * footer. Clicking emits `footer-action`.\n\t\t *\n\t\t * @type {{label: string, meta?: string, ariaLabel?: string}}\n\t\t */\n\t\tfooterAction: {\n\t\t\ttype: Object,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/**\n\t\t * A status accent: a colored border at the start of the card and,\n\t\t * with `icon`, a colored icon before the title. `variant` is one of\n\t\t * `success`, `warning`, `error`, `info` or `primary`; `icon` is a\n\t\t * name registered with CnIcon; `label` names the status for screen\n\t\t * readers and as the icon's tooltip.\n\t\t *\n\t\t * @type {{variant: string, icon?: string, label?: string}}\n\t\t */\n\t\taccent: {\n\t\t\ttype: Object,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/**\n\t\t * Board look: the record layout (manifest key `config.cardLayout`).\n\t\t * Every part names a field of the object (a dot path) and is left out\n\t\t * while that field is empty:\n\t\t * `{ headPill, number, title, meta, footerPill, footerDate }`.\n\t\t * A pill is `{ field, colorMap?, labels?, variant? }`: `colorMap` maps a\n\t\t * value to a CnStatusBadge variant (ignoring case), `labels` a value to\n\t\t * the text shown. `meta` is a list of fields, joined with \" · \".\n\t\t * `footerDate` is `{ field, label? }`, drawn as \"Termijn 5 okt\".\n\t\t * Without it the card keeps its head, facts and action.\n\t\t *\n\t\t * @type {{headPill?: object, number?: string, title?: string, meta?: Array<string>, footerPill?: object, footerDate?: {field: string, label?: string}}}\n\t\t * @spec openspec/changes/board-record-card-layout/specs/board-record-card-layout/spec.md#requirement-a-board-card-can-draw-the-record-layout-from-config\n\t\t */\n\t\tlayout: {\n\t\t\ttype: Object,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/**\n\t\t * The property keys the facts list shows, in order (manifest key\n\t\t * `config.cardFields`). Without it the card shows the first\n\t\t * `maxMetadata` visible properties, as before.\n\t\t *\n\t\t * @type {Array<string>}\n\t\t */\n\t\tcardFields: {\n\t\t\ttype: Array,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/**\n\t\t * The page's columns by key: a fact whose key names a column renders\n\t\t * through that column's label, formatter and widget, as the table does.\n\t\t *\n\t\t * @type {object}\n\t\t */\n\t\tcardFieldColumns: {\n\t\t\ttype: Object,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/** Maximum number of metadata fields to show */\n\t\tmaxMetadata: {\n\t\t\ttype: Number,\n\t\t\tdefault: 4,\n\t\t},\n\t},\n\n\temits: ['click', 'select', 'aux-click', 'footer-action'],\n\n\tsetup() {\n\t\t// Tell a deliberate card click apart from a text-selection drag.\n\t\treturn useClickDragGuard()\n\t},\n\n\tcomputed: {\n\t\t/**\n\t\t * Whether the record card of the board look is drawn.\n\t\t *\n\t\t * @return {boolean}\n\t\t */\n\t\tisBoardLook() {\n\t\t\treturn normalizeLook(this.cnLook) === 'board'\n\t\t},\n\n\t\t/**\n\t\t * `initials`, `icon` or '' for the head row's leading element.\n\t\t *\n\t\t * @return {string}\n\t\t */\n\t\tleadingKind() {\n\t\t\tif (this.leading && typeof this.leading.initials === 'string' && this.leading.initials !== '') {\n\t\t\t\treturn 'initials'\n\t\t\t}\n\t\t\treturn this.leading && typeof this.leading.icon === 'string' && this.leading.icon !== '' ? 'icon' : ''\n\t\t},\n\n\t\t/**\n\t\t * The status as `{ label, variant }`, or null.\n\t\t *\n\t\t * @return {?{label: string, variant: string}}\n\t\t */\n\t\tstatusPill() {\n\t\t\tif (typeof this.status === 'string' && this.status !== '') {\n\t\t\t\treturn { label: this.status, variant: 'default' }\n\t\t\t}\n\t\t\tif (this.status && typeof this.status.label === 'string' && this.status.label !== '') {\n\t\t\t\treturn { label: this.status.label, variant: this.status.variant || 'default' }\n\t\t\t}\n\t\t\treturn null\n\t\t},\n\n\t\t/**\n\t\t * The record layout when the board look draws it, else null.\n\t\t *\n\t\t * @return {?object}\n\t\t * @spec openspec/changes/board-record-card-layout/specs/board-record-card-layout/spec.md#requirement-a-board-card-can-draw-the-record-layout-from-config\n\t\t */\n\t\trecordLayout() {\n\t\t\treturn this.isBoardLook && this.layout && typeof this.layout === 'object' ? this.layout : null\n\t\t},\n\n\t\t/**\n\t\t * The record layout's head pill, or null.\n\t\t *\n\t\t * @return {?{label: string, variant: string}}\n\t\t */\n\t\trecordHeadPill() {\n\t\t\treturn this.recordLayout ? this.layoutPill(this.recordLayout.headPill) : null\n\t\t},\n\n\t\t/**\n\t\t * The record layout's footer pill, or null.\n\t\t *\n\t\t * @return {?{label: string, variant: string}}\n\t\t */\n\t\trecordFootPill() {\n\t\t\treturn this.recordLayout ? this.layoutPill(this.recordLayout.footerPill) : null\n\t\t},\n\n\t\t/**\n\t\t * The record number at the end of the head, or ''.\n\t\t *\n\t\t * @return {string}\n\t\t */\n\t\trecordNumber() {\n\t\t\treturn this.recordLayout ? this.layoutText(this.recordLayout.number) : ''\n\t\t},\n\n\t\t/**\n\t\t * The title: the layout's `title` field, else the card's own title.\n\t\t *\n\t\t * @return {string}\n\t\t */\n\t\trecordTitle() {\n\t\t\tconst text = this.recordLayout ? this.layoutText(this.recordLayout.title) : ''\n\t\t\treturn text !== '' ? text : this.title\n\t\t},\n\n\t\t/**\n\t\t * The meta line: the layout's `meta` fields that hold a value, joined.\n\t\t *\n\t\t * @return {string}\n\t\t */\n\t\trecordMeta() {\n\t\t\treturn this.recordMetaParts.map((part) => part.text).join(' · ')\n\t\t},\n\n\t\t/**\n\t\t * The meta line's parts that hold a value: each with its text and, when\n\t\t * its field names a page column, that column (whose widget draws it).\n\t\t *\n\t\t * @return {Array<{field: string, value: unknown, text: string, column: ?object}>}\n\t\t */\n\t\trecordMetaParts() {\n\t\t\tconst fields = this.recordLayout && Array.isArray(this.recordLayout.meta) ? this.recordLayout.meta : []\n\t\t\treturn fields\n\t\t\t\t.map((part) => this.metaPart(part))\n\t\t\t\t.filter((part) => part !== null && part.text !== '')\n\t\t},\n\n\t\t/**\n\t\t * The footer date with its label (\"Termijn 5 okt\"), or ''.\n\t\t *\n\t\t * @return {string}\n\t\t */\n\t\trecordDate() {\n\t\t\tconst def = this.recordLayout ? this.recordLayout.footerDate : null\n\t\t\tif (!def || typeof def.field !== 'string') {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t\tconst date = formatBoardDate(readPath(this.object, def.field))\n\t\t\tif (date === '') {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t\treturn typeof def.label === 'string' && def.label !== '' ? `${this.cnTranslate(def.label)} ${date}` : date\n\t\t},\n\n\t\t/**\n\t\t * The accent variant when it is a known one, else ''.\n\t\t *\n\t\t * @return {string}\n\t\t */\n\t\taccentVariant() {\n\t\t\tconst variant = this.accent?.variant\n\t\t\treturn ACCENT_VARIANTS.includes(variant) ? variant : ''\n\t\t},\n\n\t\tconfig() {\n\t\t\treturn this.schema?.configuration || {}\n\t\t},\n\n\t\ttitle() {\n\t\t\tconst field = this.config.objectNameField\n\t\t\tif (field && this.object[field]) {\n\t\t\t\treturn String(this.object[field])\n\t\t\t}\n\t\t\treturn this.object.title || this.object.name || this.object.id || '—'\n\t\t},\n\n\t\tdescription() {\n\t\t\tconst field = this.config.objectDescriptionField\n\t\t\tif (field && this.object[field]) {\n\t\t\t\treturn String(this.object[field])\n\t\t\t}\n\t\t\treturn null\n\t\t},\n\n\t\ttruncatedDescription() {\n\t\t\tif (!this.description) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tif (this.description.length > 120) {\n\t\t\t\treturn this.description.substring(0, 120) + '...'\n\t\t\t}\n\t\t\treturn this.description\n\t\t},\n\n\t\timageUrl() {\n\t\t\tconst field = this.config.objectImageField\n\t\t\tif (field && this.object[field]) {\n\t\t\t\treturn resolveImageUrl(this.object[field])\n\t\t\t}\n\t\t\treturn null\n\t\t},\n\n\t\t/** Fields excluded from metadata (already shown as title/desc/image) */\n\t\tconfigFields() {\n\t\t\treturn [\n\t\t\t\tthis.config.objectNameField,\n\t\t\t\tthis.config.objectDescriptionField,\n\t\t\t\tthis.config.objectSummaryField,\n\t\t\t\tthis.config.objectImageField,\n\t\t\t].filter(Boolean)\n\t\t},\n\n\t\t/** Remaining visible properties for the metadata section */\n\t\tmetadataFields() {\n\t\t\tif (!this.schema?.properties) {\n\t\t\t\treturn []\n\t\t\t}\n\n\t\t\t// The page names the facts: those properties, in that order.\n\t\t\tif (Array.isArray(this.cardFields)) {\n\t\t\t\treturn this.cardFields\n\t\t\t\t\t.filter((key) => typeof key === 'string' && this.schema.properties[key] && !this.configFields.includes(key))\n\t\t\t\t\t.map((key) => this.metadataField(key, this.schema.properties[key]))\n\t\t\t}\n\n\t\t\treturn Object.entries(this.schema.properties)\n\t\t\t\t.filter(([key, prop]) => {\n\t\t\t\t\tif (this.configFields.includes(key)) {\n\t\t\t\t\t\treturn false\n\t\t\t\t\t}\n\t\t\t\t\tif (prop.visible === false) {\n\t\t\t\t\t\treturn false\n\t\t\t\t\t}\n\t\t\t\t\tif (prop.type === 'object') {\n\t\t\t\t\t\treturn false\n\t\t\t\t\t}\n\t\t\t\t\tif (prop.format === 'markdown') {\n\t\t\t\t\t\treturn false\n\t\t\t\t\t}\n\t\t\t\t\treturn true\n\t\t\t\t})\n\t\t\t\t.sort(([, a], [, b]) => {\n\t\t\t\t\tconst orderA = typeof a.order === 'number' ? a.order : Infinity\n\t\t\t\t\tconst orderB = typeof b.order === 'number' ? b.order : Infinity\n\t\t\t\t\treturn orderA - orderB\n\t\t\t\t})\n\t\t\t\t.slice(0, this.maxMetadata)\n\t\t\t\t.map(([key, prop]) => this.metadataField(key, prop))\n\t\t},\n\t},\n\n\tmethods: {\n\t\t/**\n\t\t * One meta part: a field name reads through the page column it names;\n\t\t * `{ field, formatter?, formatterOptions? }` reads as plain text through\n\t\t * its own formatter, so a column's widget (a badge) stays in the table.\n\t\t *\n\t\t * @param {string|{field: string, formatter?: string, formatterOptions?: object}} part The part.\n\t\t * @return {?{field: string, value: unknown, text: string, column: ?object}} The part, or null when it names no field.\n\t\t * @spec openspec/changes/card-layout-part-formatter/specs/card-layout-part-formatter/spec.md#requirement-a-card-meta-part-can-name-its-own-formatter\n\t\t */\n\t\tmetaPart(part) {\n\t\t\tif (typeof part === 'string' && part !== '') {\n\t\t\t\treturn { field: part, value: readPath(this.object, part), text: this.layoutText(part), column: this.layoutColumn(part) }\n\t\t\t}\n\t\t\tif (!part || typeof part !== 'object' || typeof part.field !== 'string' || part.field === '') {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tconst column = typeof part.formatter === 'string' ? { formatter: part.formatter, formatterOptions: part.formatterOptions } : null\n\t\t\treturn { field: part.field, value: readPath(this.object, part.field), text: this.layoutText(part.field, column), column }\n\t\t},\n\n\t\t/**\n\t\t * A field's value as text: a person or a record by its display name,\n\t\t * title or name, anything else as a string. '' for an empty value or\n\t\t * a field that is not named.\n\t\t *\n\t\t * @param {unknown} field A dot path into the object.\n\t\t * @param {?object} [own] The column to read through instead of the one the field names.\n\t\t * @return {string}\n\t\t */\n\t\tlayoutText(field, own) {\n\t\t\tif (typeof field !== 'string' || field === '') {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t\tconst value = readPath(this.object, field)\n\t\t\tif (value === null || value === undefined || value === '') {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t\t// A part whose field names a page column with a formatter reads as\n\t\t\t// its table cell does (a case type uuid as its name).\n\t\t\tconst column = own === undefined ? this.layoutColumn(field) : own\n\t\t\tconst format = column && column.formatter && this.cnFormatters ? this.cnFormatters[column.formatter] : null\n\t\t\tif (typeof format === 'function') {\n\t\t\t\tconst formatted = format(value, this.object, this.schema?.properties?.[field], column.formatterOptions || undefined)\n\t\t\t\treturn formatted === null || formatted === undefined ? '' : String(formatted)\n\t\t\t}\n\t\t\tif (typeof value === 'object') {\n\t\t\t\tconst name = value.displayName || value.title || value.name\n\t\t\t\treturn typeof name === 'string' ? name : ''\n\t\t\t}\n\t\t\treturn String(value)\n\t\t},\n\n\t\t/**\n\t\t * The page column a layout part's field names, or null.\n\t\t *\n\t\t * @param {string} field The part's field.\n\t\t * @return {?object} The column.\n\t\t */\n\t\tlayoutColumn(field) {\n\t\t\treturn (this.cardFieldColumns && typeof field === 'string' && this.cardFieldColumns[field]) || null\n\t\t},\n\n\t\t/**\n\t\t * A pill that reads its date field through the due rules: `variantWhen`\n\t\t * (the first rule the days left match gives the tone), else `due`\n\t\t * (overdue reads as error, within `due.soonWithin` days as warning).\n\t\t * The label is `labels[variant]`, else `labels.overdue` / `labels.soon`,\n\t\t * else Overdue / Soon, through the host's translate. Any other date\n\t\t * draws no pill.\n\t\t *\n\t\t * @param {{field: string, due?: object, variantWhen?: Array, labels?: object}} def The pill.\n\t\t * @return {?{label: string, variant: string}}\n\t\t */\n\t\tdatePill(def) {\n\t\t\tconst value = readPath(this.object, def.field)\n\t\t\tconst variant = Array.isArray(def.variantWhen)\n\t\t\t\t? this.dateRuleVariant(value, def.variantWhen)\n\t\t\t\t: this.dueVariant(value, def.due)\n\t\t\tif (variant === '') {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tconst labels = def.labels && typeof def.labels === 'object' ? def.labels : {}\n\t\t\tconst state = variant === 'error' ? 'overdue' : (variant === 'warning' ? 'soon' : '')\n\t\t\tconst authored = labels[variant] || (state && labels[state])\n\t\t\tif (typeof authored === 'string' && authored !== '') {\n\t\t\t\treturn { label: this.cnTranslate(authored), variant }\n\t\t\t}\n\t\t\tif (state === 'overdue') {\n\t\t\t\treturn { label: t('nextcloud-vue', 'Overdue'), variant }\n\t\t\t}\n\t\t\tif (state === 'soon') {\n\t\t\t\treturn { label: t('nextcloud-vue', 'Soon'), variant }\n\t\t\t}\n\t\t\treturn null\n\t\t},\n\n\t\t/**\n\t\t * The variant of the first `variantWhen` rule a date matches, or ''.\n\t\t *\n\t\t * @param {unknown} value The date.\n\t\t * @param {Array} rules The rules.\n\t\t * @return {string} The variant, or ''.\n\t\t */\n\t\tdateRuleVariant(value, rules) {\n\t\t\tconst matched = resolveDateVariant(value, rules)\n\t\t\treturn matched === 'default' ? '' : matched\n\t\t},\n\n\t\t/**\n\t\t * The variant the due rules give a date: error when overdue, warning\n\t\t * within `soonWithin` days, else ''.\n\t\t *\n\t\t * @param {unknown} value The date.\n\t\t * @param {object} config The `due` config.\n\t\t * @return {string} The variant, or ''.\n\t\t */\n\t\tdueVariant(value, config) {\n\t\t\tconst due = resolveDue(value, config)\n\t\t\tif (due && due.tone === 'danger') {\n\t\t\t\treturn 'error'\n\t\t\t}\n\t\t\treturn due && due.soon ? 'warning' : ''\n\t\t},\n\n\t\t/**\n\t\t * A layout pill as `{ label, variant }`, or null while its field is\n\t\t * empty.\n\t\t *\n\t\t * @param {?{field: string, colorMap?: object, labels?: object, variant?: string}} def The pill.\n\t\t * @return {?{label: string, variant: string}}\n\t\t */\n\t\tlayoutPill(def) {\n\t\t\tif (!def || typeof def !== 'object') {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tif (def.due || Array.isArray(def.variantWhen)) {\n\t\t\t\treturn this.datePill(def)\n\t\t\t}\n\t\t\tconst value = this.layoutText(def.field)\n\t\t\tif (value === '') {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tconst labels = def.labels && typeof def.labels === 'object' ? def.labels : {}\n\t\t\tconst label = typeof labels[value] === 'string' ? this.cnTranslate(labels[value]) : value\n\t\t\tconst colorMap = def.colorMap && typeof def.colorMap === 'object' ? def.colorMap : {}\n\t\t\tconst key = Object.keys(colorMap).find((k) => k.toLowerCase() === value.toLowerCase())\n\t\t\tconst variant = key !== undefined ? colorMap[key] : def.variant\n\t\t\treturn { label, variant: isBadgeVariant(variant) ? variant : 'default' }\n\t\t},\n\n\t\t/**\n\t\t * One fact of the card: the property's value with the matching page\n\t\t * column (label, formatter, widget) when there is one.\n\t\t *\n\t\t * @param {string} key The property key.\n\t\t * @param {object} prop The schema property.\n\t\t * @return {object} { key, label, value, property, column }\n\t\t */\n\t\tmetadataField(key, prop) {\n\t\t\tconst column = (this.cardFieldColumns && this.cardFieldColumns[key]) || null\n\t\t\treturn {\n\t\t\t\tkey,\n\t\t\t\tlabel: this.cnTranslate((column && column.label) || prop.title || key),\n\t\t\t\tvalue: this.object[key],\n\t\t\t\tproperty: prop,\n\t\t\t\tcolumn,\n\t\t\t}\n\t\t},\n\n\t\tformatValue,\n\n\t\t/**\n\t\t * Card-body click: emits `select` when `selectable` (ignoring drags),\n\t\t * otherwise emits `click` for navigation. With `clickToView`, a\n\t\t * selectable card's body click navigates too — the checkbox is the\n\t\t * only selection surface, mirroring the table's rowClickToView split.\n\t\t *\n\t\t * @param {MouseEvent} [event] The originating click event.\n\t\t */\n\t\tonCardClick(event) {\n\t\t\tif (this.selectable && !this.clickToView) {\n\t\t\t\tif (this.wasDrag(event)) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\t/**\n\t\t\t\t * @event select Emitted when the card toggles selection (clicking the body of a selectable card, or its checkbox).\n\t\t\t\t * @type {object} The card's object.\n\t\t\t\t */\n\t\t\t\tthis.$emit('select', this.object)\n\t\t\t\t// Deprecation: selectable cards used to emit `click`. Keep emitting it\n\t\t\t\t// for listeners that still rely on it, but warn them to migrate to `select`.\n\t\t\t\t// `$.vnode.props`, not `$attrs`: `click` is a declared emit, and\n\t\t\t\t// Vue keeps declared emits out of `$attrs`.\n\t\t\t\tif (this.$.vnode.props?.onClick) {\n\t\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\t\tconsole.warn('[CnObjectCard] @click on selectable cards is deprecated; use @select instead.')\n\t\t\t\t\tthis.$emit('click', this.object)\n\t\t\t\t}\n\t\t\t\treturn\n\t\t\t}\n\t\t\t/**\n\t\t\t * @event click Emitted when a non-selectable (or `clickToView`) card is clicked. Payload: `(object, event)` — the card's object and the native click event, for opening it in a new tab on a ctrl/cmd/shift click. A middle click emits `aux-click` instead. Selectable cards emit `select`; they also emit `click` (deprecated) when a `click` listener is present, so migrate selectable consumers to `@select`.\n\t\t\t * @type {object} The card's object.\n\t\t\t */\n\t\t\tthis.$emit('click', this.object, event)\n\t\t},\n\n\t\t/**\n\t\t * Card mousedown: record the press for the drag guard, and on a card a\n\t\t * middle click opens, keep the browser from starting autoscroll.\n\t\t *\n\t\t * @param {MouseEvent} event The mousedown event.\n\t\t */\n\t\tonCardMouseDown(event) {\n\t\t\tthis.onPointerDown(event)\n\t\t\tif (!this.selectable || this.clickToView) {\n\t\t\t\tpreventMiddleClickAutoscroll(event)\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Card-body middle click: emits `aux-click`, not `click`, so an existing\n\t\t * `click` listener that navigates never moves the current tab away.\n\t\t * Ignored on a select-on-click card, on nested controls and on drags.\n\t\t *\n\t\t * @param {MouseEvent} event The auxclick event.\n\t\t */\n\t\tonCardAuxClick(event) {\n\t\t\tif (!isRowMiddleClick(event) || this.wasDrag(event)) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif (this.selectable && !this.clickToView) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\t/**\n\t\t\t * @event aux-click Emitted when a non-selectable (or `clickToView`) card is middle-clicked, for opening it in a new tab (see `openRowTarget`). Payload: `(object, event)` — the card's object and the native auxclick event.\n\t\t\t * @type {object} The card's object.\n\t\t\t */\n\t\t\tthis.$emit('aux-click', this.object, event)\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n.cn-object-card {\n\tdisplay: flex;\n\tgap: 12px;\n\tpadding: 16px;\n\tbackground: var(--color-main-background);\n\tborder: 1px solid var(--color-border);\n\tborder-radius: var(--border-radius-large, 10px);\n\tcursor: pointer;\n\ttransition: box-shadow 0.2s ease, border-color 0.2s ease;\n}\n\n.cn-object-card:hover {\n\tborder-color: var(--color-primary-element);\n\tbox-shadow: 0 2px 8px var(--color-box-shadow);\n}\n\n.cn-object-card--selected {\n\tborder-color: var(--color-primary-element);\n\tbackground: var(--color-primary-element-light);\n}\n\n/* The 4px start border takes 3px of padding, so the content stays put. */\n.cn-object-card.cn-object-card--accent {\n\tborder-inline-start-width: 4px;\n\tpadding-inline-start: 13px;\n}\n\n.cn-object-card.cn-object-card--accent-success {\n\tborder-inline-start-color: var(--color-element-success);\n}\n\n.cn-object-card.cn-object-card--accent-warning {\n\tborder-inline-start-color: var(--color-element-warning);\n}\n\n.cn-object-card.cn-object-card--accent-error {\n\tborder-inline-start-color: var(--color-element-error);\n}\n\n.cn-object-card.cn-object-card--accent-info {\n\tborder-inline-start-color: var(--color-element-info);\n}\n\n.cn-object-card.cn-object-card--accent-primary {\n\tborder-inline-start-color: var(--color-primary-element);\n}\n\n.cn-object-card__accent-icon {\n\tdisplay: inline-flex;\n\tvertical-align: -2px;\n\tmargin-inline-end: 4px;\n}\n\n.cn-object-card--accent-success .cn-object-card__accent-icon {\n\tcolor: var(--color-text-success);\n}\n\n.cn-object-card--accent-warning .cn-object-card__accent-icon {\n\tcolor: var(--color-text-warning);\n}\n\n.cn-object-card--accent-error .cn-object-card__accent-icon {\n\tcolor: var(--color-text-error);\n}\n\n.cn-object-card--accent-info .cn-object-card__accent-icon {\n\tcolor: var(--color-element-info);\n}\n\n.cn-object-card--accent-primary .cn-object-card__accent-icon {\n\tcolor: var(--color-primary-element);\n}\n\n.cn-object-card__checkbox {\n\tflex-shrink: 0;\n\tpadding-top: 2px;\n}\n\n.cn-object-card__content {\n\tflex: 1;\n\tmin-width: 0;\n}\n\n.cn-object-card__header {\n\tdisplay: flex;\n\tgap: 12px;\n\talign-items: flex-start;\n}\n\n.cn-object-card__image {\n\twidth: 48px;\n\theight: 48px;\n\tborder-radius: var(--border-radius);\n\tobject-fit: cover;\n\tflex-shrink: 0;\n}\n\n.cn-object-card__title-area {\n\tflex: 1;\n\tmin-width: 0;\n}\n\n.cn-object-card__title {\n\tmargin: 0;\n\tfont-size: 16px;\n\tfont-weight: 600;\n\tline-height: 1.3;\n\toverflow: hidden;\n\ttext-overflow: ellipsis;\n\twhite-space: nowrap;\n}\n\n.cn-object-card__description {\n\tmargin: 4px 0 0;\n\tfont-size: 13px;\n\tcolor: var(--color-text-maxcontrast);\n\tline-height: 1.4;\n}\n\n.cn-object-card__badges {\n\tmargin-top: 8px;\n}\n\n.cn-object-card__metadata {\n\tdisplay: grid;\n\tgrid-template-columns: repeat(auto-fill, minmax(160px, 1fr));\n\tgap: 8px;\n\tmargin-top: 12px;\n\tpadding-top: 12px;\n\tborder-top: 1px solid var(--color-border);\n}\n\n.cn-object-card__meta-item {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 2px;\n}\n\n.cn-object-card__meta-label {\n\tfont-size: 11px;\n\tfont-weight: 500;\n\tcolor: var(--color-text-maxcontrast);\n\ttext-transform: uppercase;\n\tletter-spacing: 0.3px;\n}\n\n.cn-object-card__actions {\n\tflex-shrink: 0;\n}\n</style>\n"],"names":["_createElementBlock","_normalizeClass","_createVNode","_openBlock","_createElementVNode","_createBlock","_toDisplayString","_renderSlot","_createTextVNode","_Fragment","_renderList"],"mappings":";;;;AAmB2B,EAAA,KAAK,EAAC,gDAA+C;AAAE,EAAA,aAAW,EAAC,uBAAuB;;AAC7G,MAAA,UAAA,GAAA,EAAA,KAAK,EAAC,6BAA6B,GAAA;;;AAOb,EAAA,KAAK,EAAC,+BAAgC;AAAA,EAAA,aAAW,EAAC,uBAAuB;;AAShG,MAAA,UAAA,GAAA,EAAA,KAAK,EAAC,uBAAuB,GAAA;;;AAMI,EAAA,KAAK,EAAC,6BAA8B;AAAA,EAAA,aAAW,EAAC,qBAAqB;;;;AAEjF,EAAA,aAAW,EAAC,MAAM;;;;;AAYjB,EAAA,KAAK,EAAC,wBAAwB;;;;AAGf,EAAA,KAAK,EAAC,6BAA4B;AAAE,EAAA,aAAW,EAAC,qBAAqB;;;;AAOrF,EAAA,KAAK,EAAC,6BAA8B;AAAA,EAAA,aAAW,EAAC,qBAAqB;;;;AAKnF,EAAA,KAAK,EAAC,yBAAyB;;AAErC,MAAA,WAAA,GAAA,EAAA,KAAK,EAAC,wBAAwB,GAAA;;AAiB7B,MAAA,WAAA,GAAA,EAAA,KAAK,EAAC,4BAA4B,GAAA;AAClC,MAAA,WAAA,GAAA,EAAA,KAAK,EAAC,uBAAuB,GAAA;;;;AAkBX,EAAA,KAAK,EAAC,6BAA6B;;;;AAuBjC,EAAA,KAAK,EAAC,wBAAwB;;AAW/C,MAAA,WAAA,GAAA,EAAA,KAAK,EAAC,4BAA4B,GAAA;;;AAqBX,EAAA,KAAK,EAAC,6BAA6B;;;;;;;;;;;uBAnKrEA,kBAsLK,CAAA,KAAA,EAAA;IArLJ,KAAK,EAAAC,cAAA,CAAA,CAAC,gBAAe,EACkB,CAAA,EAAA,0BAAA,EAAA,MAAA,CAAA,QAAQ,2BAA2B,wBAAe,+EAAsE,QAAa,CAAA,aAAA,CAAA,CAAA,CAAA,CAAA,CAAA,CAAA;AAC3K,IAAA,WAAS,4CAAE,QAAe,CAAA,eAAA,IAAA,QAAA,CAAA,eAAA,CAAA,GAAA,IAAA,CAAA,CAAA,CAAA;IAC1B,OAAK,EAAA,MAAA,CAAA,EAAA,CAAA,KAAA,MAAA,CAAA,EAAA,CAAA,GAAA,MAAA,KAAE,QAAW,CAAA,WAAA,CAAC,MAAM,CAAA,CAAA,CAAA;IACzB,UAAQ,EAAA,MAAA,CAAA,EAAA,CAAA,KAAA,MAAA,CAAA,EAAA,CAAA,GAAA,MAAA,KAAE,QAAc,CAAA,cAAA,CAAC,MAAM,CAAA,CAAA,CAAA;;KAErB,MAAU,CAAA,UAAA;sBAArBD,kBAOK,CAAA,KAAA,EAAA;;AANJ,UAAA,KAAK,EAAC,0BAAyB;AAC9B,UAAA,OAAK,0CAAN,MAAU,EAAA,EAAA,CAAA,MAAA,CAAA,CAAA,CAAA;AACT,UAAA,UAAQ,0CAAT,MAAc,EAAA,EAAA,CAAA,MAAA,CAAA,CAAA,CAAA;;UACdE,WAE+C,CAAA,gCAAA,EAAA;AAD7C,YAAA,UAAU,EAAE,MAAQ,CAAA,QAAA;YACpB,qBAAiB,EAAA,MAAA,CAAA,CAAA,CAAA,KAAA,MAAA,CAAA,CAAA,CAAA,GAAA,MAAA,KAAE,IAAK,CAAA,KAAA,CAAA,QAAA,EAAW,MAAM,CAAA,MAAA,CAAA,CAAA,CAAA;;;;KAKjC,QAAY,CAAA,YAAA;AAAvB,SAAAC,SAAA,EAAA,EAAAH,kBAAA,CAiDK,OAjDL,UAiDK,EAAA;AAhDJ,UAAAI,kBAAA,CAeK,OAfL,UAeK,EAAA;aAbG,QAAc,CAAA,cAAA;8BADrBC,WAKyC,CAAA,wBAAA,EAAA;;AAHxC,kBAAA,KAAK,EAAC,6BAA4B;kBACjC,KAAK,EAAE,QAAc,CAAA,cAAA,CAAC,KAAK;kBAC3B,OAAO,EAAE,QAAc,CAAA,cAAA,CAAC,OAAO;AAChC,kBAAA,aAAW,EAAC;;;aACD,QAAY,CAAA,YAAA;8BAAxBL,kBAA4H,CAAA,MAAA,EAA5H,UAA4H,EAAAM,eAAA,CAArB,QAAa,CAAA,YAAA,CAAA,EAAA,CAAA,YAAA;;AAE7G,YAAA,CAAA,IAAA,CAAA,MAAM,CAAC,OAAO;8BADrBN,kBAMK,CAAA,KAAA,EAAA;;AAJJ,kBAAA,KAAK,EAAC,sBAAqB;AAC1B,kBAAA,OAAK,0CAAN,MAAU,EAAA,EAAA,CAAA,MAAA,CAAA,CAAA,CAAA;AACT,kBAAA,UAAQ,0CAAT,MAAc,EAAA,EAAA,CAAA,MAAA,CAAA,CAAA,CAAA;;kBACdO,UAAuC,CAAA,IAAA,CAAA,MAAA,EAAA,SAAA,EAAA,EAAjB,MAAM,EAAE,MAAM,CAAA,MAAA,EAAA,CAAA;;;;AAGtC,UAAAH,kBAAA,CAGI,MAHJ,UAGI,EAAA;YAFHF,WAA8C,CAAA,0BAAA,EAAA;AAA5B,cAAA,MAAM,EAAE,MAAM,CAAA,MAAA;AAAG,cAAA,IAAI,EAAE,EAAE;;AAAG,YAAAM,eAAA,CAAA,GAC9C,mBAAG,QAAU,CAAA,WAAA,CAAA,EAAA,CAAA,YAAA;;AAIL,UAAA,CAAA,QAAA,CAAA,eAAe,CAAC,MAAK,GAAA,CAAA;AAA9B,eAAAL,SAAA,EAAA,EAAAH,kBAAA,CAaG,KAbH,UAaG,EAAA;AAZF,iBAAAG,SAAA,CAAA,IAAA,CAAA,EAAAH,kBAAA,CAWUS,QAXwB,EAAA,IAAA,EAAAC,UAAA,CAAA,QAAA,CAAA,eAAe,EAA/B,CAAA,IAAI,EAAE,KAAK,KAAA;;AAA4B,oBAAA,GAAA,EAAA,IAAI,CAAC,KAAK;;qBACtD,KAAI,GAAA,CAAA;sCAAhBV,kBAAmD,CAAA,MAAA,EAAnD,UAAmD,OAAN,CAAA;;AAEtC,oBAAA,CAAA,IAAI,CAAC,MAAO,IAAG,IAAI,CAAC,MAAM,CAAC,MAAM;sCADxCK,WAOgB,CAAA,yBAAA,EAAA;;0BALd,KAAK,EAAE,IAAI,CAAC,KAAK;AACjB,0BAAA,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,MAAM;AAC1B,0BAAA,WAAW,EAAE,IAAI,CAAC,MAAM,CAAC,eAAe,SAAS;AACjD,0BAAA,SAAS,EAAE,IAAI,CAAC,MAAM,CAAC,SAAU,IAAA,IAAA;AACjC,0BAAA,gBAAgB,EAAE,IAAI,CAAC,MAAM,CAAC,gBAAe,IAAA,IAAA;AAC7C,0BAAA,GAAG,EAAE,MAAM,CAAA,MAAA;;sCACbL,kBAAkC,CAAA,MAAA,EAAA,UAAA,EAAAM,eAAA,CAAlB,IAAI,CAAC,IAAG,CAAA,EAAA,CAAA,YAAA,CAAA;;;;;AAGf,UAAA,CAAA,IAAA,CAAA,MAAM,CAAC,MAAM;AAAxB,eAAAH,SAAA,EAAA,EAAAH,kBAAA,CAEK,OAFL,UAEK,EAAA;gBADJO,UAAsC,CAAA,IAAA,CAAA,MAAA,EAAA,QAAA,EAAA,EAAjB,MAAM,EAAE,MAAM,CAAA,MAAA,EAAA,CAAA;;;AAEzB,UAAA,CAAA,QAAA,CAAA,cAAe,IAAG,QAAU,CAAA,UAAA;AAAvC,eAAAJ,SAAA,EAAA,EAAAH,kBAAA,CAQK,OARL,UAQK,EAAA;iBANG,QAAc,CAAA,cAAA;kCADrBK,WAKyC,CAAA,wBAAA,EAAA;;AAHxC,sBAAA,KAAK,EAAC,6BAA4B;sBACjC,KAAK,EAAE,QAAc,CAAA,cAAA,CAAC,KAAK;sBAC3B,OAAO,EAAE,QAAc,CAAA,cAAA,CAAC,OAAO;AAChC,sBAAA,aAAW,EAAC;;;iBACD,QAAU,CAAA,UAAA;kCAAtBL,kBAAoH,CAAA,MAAA,EAApH,WAAoH,EAAAM,eAAA,CAAnB,QAAW,CAAA,UAAA,CAAA,EAAA,CAAA,YAAA;;;;;AAK9G,SAAAH,SAAA,EAAA,EAAAH,kBAAA,CAuGK,OAvGL,WAuGK,EAAA;AArGJ,UAAAI,kBAAA,CAwDK,OAxDL,WAwDK,EAAA;AArDG,YAAA,CAAA,QAAA,CAAA,WAAU,IAAK,QAAW,CAAA,WAAA;8BADjCJ,kBAQM,CAAA,MAAA,EAAA;;kBANL,KAAK,EAAAC,cAAA,CAAA,CAAC,yBAAwB,EAAA,CAAA,yBAAA,EACM,QAAW,CAAA,WAAA,CAAA,CAAA,CAAA,CAAA;AAC/C,kBAAA,aAAW,EAAC,wBAAuB;AACnC,kBAAA,aAAW,EAAC,MAAM;;mBACF,QAAU,CAAA,WAAA,KAAA,UAAA;oCAA1BD,kBAA4E,CAAAS,QAAA,EAAA,EAAA,GAAA,EAAA,CAAA,EAAA,EAAA;AAA7B,wBAAAD,eAAA,CAAAF,eAAA,CAAA,MAAA,CAAA,OAAO,CAAC,QAAO,CAAA,EAAA,CAAA,YAAA;;oCAC9DD,WAAgD,CAAA,iBAAA,EAAA;;wBAAhC,IAAI,EAAE,MAAO,CAAA,OAAA,CAAC,IAAI;AAAG,wBAAA,IAAI,EAAE,EAAE;;;;aAGvC,QAAQ,CAAA,QAAA;8BADfL,kBAI8B,CAAA,KAAA,EAAA;;AAF5B,kBAAA,GAAG,EAAE,QAAQ,CAAA,QAAA;AACb,kBAAA,GAAG,EAAE,QAAK,CAAA,KAAA;AACX,kBAAA,KAAK,EAAC,uBAAuB;;;AAE9B,YAAAI,kBAAA,CAsBK,OAtBL,WAsBK,EAAA;AArBJ,cAAAA,kBAAA,CAiBI,MAjBJ,WAiBI,EAAA;gBAZHF,WAA8C,CAAA,0BAAA,EAAA;AAA5B,kBAAA,MAAM,EAAE,MAAM,CAAA,MAAA;AAAG,kBAAA,IAAI,EAAE,EAAE;;iBAEpC,QAAc,CAAA,aAAA,IAAG,MAAM,CAAA,MAAA,CAAC,IAAI;kCADnCF,kBASM,CAAA,MAAA,EAAA;;AAPL,sBAAA,KAAK,EAAC,6BAA4B;AAClC,sBAAA,aAAW,EAAC,4BAA2B;sBACtC,IAAI,EAAE,MAAM,CAAA,MAAA,CAAC,KAAI,GAAA,KAAA,GAAA,IAAA;sBACjB,YAAU,EAAE,MAAM,CAAA,MAAA,CAAC,KAAI,IAAA,IAAA;sBACvB,aAAW,EAAE,MAAM,CAAA,MAAA,CAAC,KAAI,GAAA,IAAA,GAAA,MAAA;sBACxB,KAAK,EAAE,MAAM,CAAA,MAAA,CAAC,KAAI,IAAA,IAAA;;sBACnBE,WAAwC,CAAA,iBAAA,EAAA;wBAA/B,IAAI,EAAE,MAAM,CAAA,MAAA,CAAC,IAAI;AAAG,wBAAA,IAAI,EAAE,EAAE;;;;AAChC,gBAAAM,eAAA,CAAA,GACN,mBAAG;;eAEK,QAAW,CAAA,WAAA;gCAApBR,kBAEG,CAAA,GAAA,EAFH,WAEG,EAAAM,eAAA,CADC,QAAmB,CAAA,oBAAA,CAAA,EAAA,CAAA,YAAA;;;aAIR,QAAW,CAAA,WAAA;8BAA3BN,kBAcU,CAAAS,QAAA,EAAA,EAAA,GAAA,EAAA,CAAA,EAAA,EAAA;mBAZF,QAAU,CAAA,UAAA;oCADjBJ,WAKsC,CAAA,wBAAA,EAAA;;AAHrC,wBAAA,KAAK,EAAC,wBAAuB;wBAC5B,KAAK,EAAE,QAAU,CAAA,UAAA,CAAC,KAAK;wBACvB,OAAO,EAAE,QAAU,CAAA,UAAA,CAAC,OAAO;AAC5B,wBAAA,aAAW,EAAC;;AAED,sBAAA,CAAA,IAAA,CAAA,MAAM,CAAC,OAAO;sCAD1BL,kBAMK,CAAA,KAAA,EAAA;;AAJJ,0BAAA,KAAK,EAAC,sBAAqB;AAC1B,0BAAA,OAAK,0CAAN,MAAU,EAAA,EAAA,CAAA,MAAA,CAAA,CAAA,CAAA;AACT,0BAAA,UAAQ,0CAAT,MAAc,EAAA,EAAA,CAAA,MAAA,CAAA,CAAA,CAAA;;0BACdO,UAAuC,CAAA,IAAA,CAAA,MAAA,EAAA,SAAA,EAAA,EAAjB,MAAM,EAAE,MAAM,CAAA,MAAA,EAAA,CAAA;;;;;;AAM5B,UAAA,CAAA,IAAA,CAAA,MAAM,CAAC,MAAM;AAAxB,eAAAJ,SAAA,EAAA,EAAAH,kBAAA,CAEK,OAFL,WAEK,EAAA;gBADJO,UAAsC,CAAA,IAAA,CAAA,MAAA,EAAA,QAAA,EAAA,EAAjB,MAAM,EAAE,MAAM,CAAA,MAAA,EAAA,CAAA;;;AAIzB,UAAA,CAAA,QAAA,CAAA,cAAc,CAAC;4BAA1BP,kBAkBK,CAAA,KAAA,EAAA;;gBAlBiC,KAAK,EAAAC,cAAA,CAAA,CAAC,0BAAyB,EAAA,EAAA,iCAAA,EAA+C,QAAY,CAAA,WAAA,EAAA,CAAA,CAAA;;gBAC/HM,UAgBM,CAAA,IAAA,CAAA,MAAA,EAAA,UAAA,EAAA;AAhBiB,kBAAA,MAAM,EAAE,MAAM,CAAA,MAAA;AAAG,kBAAA,MAAM,EAAE,QAAc,CAAA,cAAA;mBAA9D,MAgBM;oCAfLP,kBAcK,CAAAS,QAAA,EAAA,IAAA,EAAAC,UAAA,CAbY,QAAc,CAAA,cAAA,EAAA,CAAvB,KAAI,KAAA;yCADZV,kBAcK,CAAA,KAAA,EAAA;sBAZH,GAAG,EAAE,KAAK,CAAC,GAAG;AACf,sBAAA,KAAK,EAAC,2BAA2B;;AACjC,sBAAAI,kBAAA,CAAgE,MAAhE,EAAA,WAAgE,EAApBE,eAAA,CAAA,KAAK,CAAC,KAAM,CAAA,EAAA,CAAA,YAAA;sBACxDJ,WAQiB,CAAA,yBAAA,EAAA;wBAPf,KAAK,EAAE,KAAK,CAAC,KAAK;wBAClB,QAAQ,EAAE,KAAK,CAAC,QAAQ;wBACxB,SAAS,EAAE,KAAK,CAAC,MAAO,IAAG,KAAK,CAAC,MAAM,CAAC,SAAQ,IAAA,IAAA;wBAChD,gBAAgB,EAAE,KAAK,CAAC,MAAK,IAAK,KAAK,CAAC,MAAM,CAAC,gBAAe,IAAA,IAAA;wBAC9D,MAAM,EAAE,KAAK,CAAC,MAAO,IAAG,KAAK,CAAC,MAAM,CAAC,MAAK,IAAA,IAAA;wBAC1C,WAAW,EAAE,KAAK,CAAC,MAAO,IAAG,KAAK,CAAC,MAAM,CAAC,WAAY,IAAG,SAAS;AAClE,wBAAA,GAAG,EAAE,MAAM,CAAA,MAAA;AACX,wBAAA,QAAQ,EAAE,EAAE;;;;;;;AAOV,UAAA,CAAA,QAAA,CAAA,WAAU,IAAK,MAAY,CAAA,YAAA;4BADlCF,kBAeK,CAAA,KAAA,EAAA;;AAbJ,gBAAA,KAAK,EAAC,wBAAuB;AAC7B,gBAAA,aAAW,EAAC,uBAAsB;AACjC,gBAAA,OAAK,0CAAN,MAAU,EAAA,EAAA,CAAA,MAAA,CAAA,CAAA,CAAA;AACT,gBAAA,UAAQ,0CAAT,MAAc,EAAA,EAAA,CAAA,MAAA,CAAA,CAAA,CAAA;;AACF,gBAAA,CAAA,MAAA,CAAA,YAAY,CAAC,IAAI;AAA7B,qBAAAG,SAAA,EAAA,EAAAH,kBAAA,CAAgG,MAAhG,EAAA,WAAgG,EAA1BM,eAAA,CAAA,MAAA,CAAA,YAAY,CAAC,IAAG,CAAA,EAAA,CAAA,YAAA;;gBACtFJ,WAOU,CAAA,mBAAA,EAAA;AANT,kBAAA,OAAO,EAAC,WAAU;AAClB,kBAAA,KAAK,EAAC,+BAA8B;AACpC,kBAAA,aAAW,EAAC,8BAA6B;kBACxC,YAAU,EAAE,mBAAY,CAAC,SAAU,OAAM,MAAY,CAAA,YAAA,CAAC,KAAK,CAAA,CAAA,EAAI,QAAK,CAAA,KAAA,CAAA,CAAA;AACpE,kBAAA,OAAK,EAAE,MAAA,CAAA,CAAA,CAAA,KAAA,MAAA,CAAA,CAAA,CAAA,GAAA,MAAA,KAAA,IAAA,CAAA,KAAK,CAAkB,eAAA,EAAA,MAAA,CAAA,MAAM,EAAE,MAAY,CAAA,YAAA,CAAA,CAAA,CAAA;;mCACnD,MAAuB;AAApB,oBAAAM,eAAA,CAAAF,eAAA,CAAA,MAAA,CAAA,YAAY,CAAC;;;;;;;KAMR,IAAM,CAAA,MAAA,CAAC,OAAM,IAAA,CAAM,QAAW,CAAA,WAAA;sBAAzCN,kBAKK,CAAA,KAAA,EAAA;;AAJJ,UAAA,KAAK,EAAC,yBAAwB;AAC7B,UAAA,OAAK,4CAAN,MAAU,EAAA,EAAA,CAAA,MAAA,CAAA,CAAA,CAAA;AACT,UAAA,UAAQ,4CAAT,MAAc,EAAA,EAAA,CAAA,MAAA,CAAA,CAAA,CAAA;;UACdO,UAAuC,CAAA,IAAA,CAAA,MAAA,EAAA,SAAA,EAAA,EAAjB,MAAM,EAAE,MAAM,CAAA,MAAA,EAAA,CAAA;;;;;;;;"}
|
|
@@ -109,6 +109,10 @@ var script = {
|
|
|
109
109
|
uploadButton: { type: Boolean, default: false },
|
|
110
110
|
/** Forwarded to CnFilesBrowser: the drop state drawn over the list ("Drop to add") and announced. */
|
|
111
111
|
dropOverlay: { type: Boolean, default: false },
|
|
112
|
+
/** Forwarded to CnFilesBrowser: the drop state's line ("Laat los om toe te voegen"); the library's own without it. */
|
|
113
|
+
dropLabel: { type: String, default: undefined },
|
|
114
|
+
/** Forwarded to CnFilesBrowser: the drop state's second line, `{count}` the files dragged; it also makes the overlay fill the panel. */
|
|
115
|
+
dropDetail: { type: String, default: '' },
|
|
112
116
|
/** Forwarded to CnFilesBrowser: "Or drag files onto this list." under the list. */
|
|
113
117
|
dropHint: { type: Boolean, default: false },
|
|
114
118
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CnFilesTab.vue2.js","sources":["../../../../src/components/CnObjectSidebar/CnFilesTab.vue"],"sourcesContent":["<template>\n\t<div class=\"cn-sidebar-tab\">\n\t\t<!-- The object's folder as a real files browser, on the Files app's own\n\t\t primitives (its actions, its New menu, its breadcrumbs), when the\n\t\t folder resolves for this user. The list below is the fallback for an\n\t\t object with no folder, or a user the folder is not shared with. -->\n\t\t<CnFilesBrowser\n\t\t\tv-if=\"browserRoot !== null\"\n\t\t\t:rootPath=\"browserRoot\"\n\t\t\t:rootLabel=\"effectiveBrowserRootLabel\"\n\t\t\t:source=\"browserSource\"\n\t\t\t:deleteLabel=\"deleteLabel\"\n\t\t\t:uploadButton=\"uploadButton\"\n\t\t\t:dropOverlay=\"dropOverlay\"\n\t\t\t:dropHint=\"dropHint\"\n\t\t\t:rowActions=\"rowActions\"\n\t\t\t:newActions=\"newActions\"\n\t\t\t:headerActions=\"headerActions\"\n\t\t\t:rowButton=\"rowButton\"\n\t\t\t:reviewSummary=\"reviewSummary\"\n\t\t\t:footnote=\"footnote\"\n\t\t\t:nameSecondary=\"nameSecondary\"\n\t\t\t:linkedItems=\"linkedItems\"\n\t\t\t:columns=\"columns\"\n\t\t\t:rowData=\"rowDataSource\"\n\t\t\t:preferenceApp=\"preferenceApp\"\n\t\t\t:preferenceKey=\"preferenceKey\"\n\t\t\t:bulkActions=\"bulkActions\"\n\t\t\t:selectionLabel=\"selectionLabel\"\n\t\t\t:selectionLabelOne=\"selectionLabelOne\"\n\t\t\t:showClearSelection=\"showClearSelection\"\n\t\t\t:sideCards=\"sideCards\"\n\t\t\t:groupBy=\"groupBy\"\n\t\t\t:facets=\"facets\"\n\t\t\t@changed=\"onBrowserChanged\" />\n\t\t<template v-else>\n\t\t\t<!-- Upload error -->\n\t\t\t<div v-if=\"uploadError\" class=\"cn-sidebar-tab__upload-error\">\n\t\t\t\t{{ uploadError }}\n\t\t\t</div>\n\n\t\t\t<!-- Share toggle — seeds from schema config (defaultAutoShare) or\n\t\t from the `defaultShare` prop. Hidden via `showShareToggle=false`. -->\n\t\t\t<NcCheckboxRadioSwitch\n\t\t\t\tv-if=\"showShareToggle\"\n\t\t\t\tv-model=\"share\"\n\t\t\t\tclass=\"cn-sidebar-tab__share\"\n\t\t\t\t:disabled=\"loading\"\n\t\t\t\ttype=\"switch\">\n\t\t\t\t{{ shareLabel }}\n\t\t\t</NcCheckboxRadioSwitch>\n\n\t\t\t<!-- File drop zone -->\n\t\t\t<div\n\t\t\t\tclass=\"cn-sidebar-tab__dropzone\"\n\t\t\t\t:class=\"{ 'cn-sidebar-tab__dropzone--active': isDragOver }\"\n\t\t\t\t@click=\"triggerFileInput\"\n\t\t\t\t@dragover.prevent=\"onDragOver\"\n\t\t\t\t@dragleave.prevent=\"onDragLeave\"\n\t\t\t\t@drop.prevent=\"onDrop\">\n\t\t\t\t<!--\n\t\t\t\t`:ref` (dynamic), not `ref` (static), and this is load-bearing.\n\n\t\t\t\tEvery other binding on this input is static, and Vue caches the\n\t\t\t\t`@change` handler, so with a STATIC ref the compiler hoists the\n\t\t\t\twhole vnode to module scope. A hoisted vnode is created once,\n\t\t\t\toutside any render, so its ref carries no owner instance\n\t\t\t\t(`rawRef.i === null`).\n\n\t\t\t\t`setRef()` guards that — but the guard AND its early `return`\n\t\t\t\tlive inside `if (process.env.NODE_ENV !== 'production')`. In a\n\t\t\t\tdevelopment build you get the warning \"Missing ref owner\n\t\t\t\tcontext. ref cannot be used on hoisted vnodes.\" and nothing\n\t\t\t\tbreaks. In a PRODUCTION build the guard is compiled out and\n\t\t\t\texecution falls through to `owner.refs`, throwing\n\t\t\t\t`TypeError: Cannot read properties of null (reading 'refs')`\n\t\t\t\t— which aborts the render of whatever mounted this tab.\n\n\t\t\t\tMeasured: hrmq's detail pages (the only pages in the fleet that\n\t\t\t\treach CnIntegrationWidget through a `widgets[]` grid) rendered a\n\t\t\t\tCOMPLETELY BLANK content pane in production while looking fine\n\t\t\t\tin dev. A dynamic ref is compiled as a patchable prop, so the\n\t\t\t\tvnode is created inside the render function and owns a proper\n\t\t\t\tinstance.\n\t\t\t-->\n\t\t\t\t<input\n\t\t\t\t\t:ref=\"fileInputRef\"\n\t\t\t\t\ttype=\"file\"\n\t\t\t\t\tmultiple\n\t\t\t\t\tclass=\"cn-sidebar-tab__file-input\"\n\t\t\t\t\t@change=\"onFileUpload\">\n\t\t\t\t<Upload :size=\"24\" class=\"cn-sidebar-tab__dropzone-icon\" />\n\t\t\t\t<span class=\"cn-sidebar-tab__dropzone-text\">{{ dropZoneLabel }}</span>\n\t\t\t</div>\n\n\t\t\t<!-- File list. Each row borrows what Nextcloud already has on this\n\t\t page: the theme's own mime icon (OC.MimeType), the core preview\n\t\t endpoint for images, the Viewer for opening, and the Files sidebar\n\t\t for details, sharing and versions. Nothing of the Files app is\n\t\t rebuilt here; the row hands over to it. -->\n\t\t\t<NcLoadingIcon v-if=\"loading\" />\n\t\t\t<NcEmptyContent\n\t\t\t\tv-else-if=\"files.length === 0\"\n\t\t\t\tclass=\"cn-sidebar-tab__empty\"\n\t\t\t\t:name=\"noFilesLabel\"\n\t\t\t\t:description=\"dropZoneLabel\">\n\t\t\t\t<template #icon>\n\t\t\t\t\t<Paperclip :size=\"44\" />\n\t\t\t\t</template>\n\t\t\t</NcEmptyContent>\n\t\t\t<div v-else class=\"cn-sidebar-tab__list\">\n\t\t\t\t<NcListItem\n\t\t\t\t\tv-for=\"file in files\"\n\t\t\t\t\t:key=\"file.id\"\n\t\t\t\t\t:name=\"file.name || file.title\"\n\t\t\t\t\t:bold=\"false\"\n\t\t\t\t\t:forceDisplayActions=\"true\"\n\t\t\t\t\t@click=\"openFile(file)\">\n\t\t\t\t\t<template #icon>\n\t\t\t\t\t\t<img\n\t\t\t\t\t\t\tv-if=\"previewUrlFor(file)\"\n\t\t\t\t\t\t\tclass=\"cn-sidebar-tab__thumb\"\n\t\t\t\t\t\t\t:src=\"previewUrlFor(file)\"\n\t\t\t\t\t\t\talt=\"\"\n\t\t\t\t\t\t\tloading=\"lazy\"\n\t\t\t\t\t\t\t@error=\"onPreviewError(file)\">\n\t\t\t\t\t\t<img\n\t\t\t\t\t\t\tv-else-if=\"mimeIconFor(file)\"\n\t\t\t\t\t\t\tclass=\"cn-sidebar-tab__mime\"\n\t\t\t\t\t\t\t:src=\"mimeIconFor(file)\"\n\t\t\t\t\t\t\talt=\"\">\n\t\t\t\t\t\t<FileOutline v-else :size=\"32\" />\n\t\t\t\t\t</template>\n\t\t\t\t\t<template #subname>\n\t\t\t\t\t\t<span class=\"cn-sidebar-tab__meta\">\n\t\t\t\t\t\t\t<span>{{ formatFileSize(file.size) }}</span>\n\t\t\t\t\t\t\t<template v-if=\"modifiedAt(file)\">\n\t\t\t\t\t\t\t\t<span aria-hidden=\"true\"> · </span>\n\t\t\t\t\t\t\t\t<NcDateTime :timestamp=\"modifiedAt(file)\" :ignoreSeconds=\"true\" />\n\t\t\t\t\t\t\t</template>\n\t\t\t\t\t\t\t<template v-if=\"labelsOf(file)\">\n\t\t\t\t\t\t\t\t<span aria-hidden=\"true\"> · </span>\n\t\t\t\t\t\t\t\t<span>{{ labelsOf(file) }}</span>\n\t\t\t\t\t\t\t</template>\n\t\t\t\t\t\t</span>\n\t\t\t\t\t</template>\n\t\t\t\t\t<template #actions>\n\t\t\t\t\t\t<NcActionButton :closeAfterClick=\"true\" @click=\"openFile(file)\">\n\t\t\t\t\t\t\t<template #icon>\n\t\t\t\t\t\t\t\t<OpenInNew :size=\"20\" />\n\t\t\t\t\t\t\t</template>\n\t\t\t\t\t\t\t{{ openLabel }}\n\t\t\t\t\t\t</NcActionButton>\n\t\t\t\t\t\t<!-- OpenRegister's Office page applies the object rule:\n\t\t\t\t\t\t update edits, read views, no read is a 404. -->\n\t\t\t\t\t\t<NcActionLink\n\t\t\t\t\t\t\tv-if=\"officeOpens(file)\"\n\t\t\t\t\t\t\t:href=\"officeUrlFor(file)\"\n\t\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\t\t:closeAfterClick=\"true\">\n\t\t\t\t\t\t\t<template #icon>\n\t\t\t\t\t\t\t\t<FileDocumentEditOutline :size=\"20\" />\n\t\t\t\t\t\t\t</template>\n\t\t\t\t\t\t\t{{ openInOfficeLabel }}\n\t\t\t\t\t\t</NcActionLink>\n\t\t\t\t\t\t<NcActionLink\n\t\t\t\t\t\t\tv-if=\"file.id\"\n\t\t\t\t\t\t\t:href=\"downloadUrlFor(file)\"\n\t\t\t\t\t\t\t:download=\"file.name || file.title || ''\"\n\t\t\t\t\t\t\t:closeAfterClick=\"true\">\n\t\t\t\t\t\t\t<template #icon>\n\t\t\t\t\t\t\t\t<Download :size=\"20\" />\n\t\t\t\t\t\t\t</template>\n\t\t\t\t\t\t\t{{ downloadLabel }}\n\t\t\t\t\t\t</NcActionLink>\n\t\t\t\t\t\t<NcActionButton\n\t\t\t\t\t\t\tv-if=\"canShowDetails() && file.path\"\n\t\t\t\t\t\t\t:closeAfterClick=\"true\"\n\t\t\t\t\t\t\t@click=\"showDetails(file)\">\n\t\t\t\t\t\t\t<template #icon>\n\t\t\t\t\t\t\t\t<InformationOutline :size=\"20\" />\n\t\t\t\t\t\t\t</template>\n\t\t\t\t\t\t\t{{ detailsLabel }}\n\t\t\t\t\t\t</NcActionButton>\n\t\t\t\t\t\t<NcActionLink\n\t\t\t\t\t\t\tv-if=\"file.id\"\n\t\t\t\t\t\t\t:href=\"showInFilesUrl(file)\"\n\t\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\t\t:closeAfterClick=\"true\">\n\t\t\t\t\t\t\t<template #icon>\n\t\t\t\t\t\t\t\t<FolderOutline :size=\"20\" />\n\t\t\t\t\t\t\t</template>\n\t\t\t\t\t\t\t{{ showInFilesLabel }}\n\t\t\t\t\t\t</NcActionLink>\n\t\t\t\t\t\t<NcActionButton v-if=\"file.id\" :closeAfterClick=\"true\" @click=\"copyLink(file)\">\n\t\t\t\t\t\t\t<template #icon>\n\t\t\t\t\t\t\t\t<LinkVariant :size=\"20\" />\n\t\t\t\t\t\t\t</template>\n\t\t\t\t\t\t\t{{ copyLinkLabel }}\n\t\t\t\t\t\t</NcActionButton>\n\t\t\t\t\t\t<NcActionSeparator />\n\t\t\t\t\t\t<NcActionButton :closeAfterClick=\"true\" @click=\"deleteFile(file)\">\n\t\t\t\t\t\t\t<template #icon>\n\t\t\t\t\t\t\t\t<Delete :size=\"20\" />\n\t\t\t\t\t\t\t</template>\n\t\t\t\t\t\t\t{{ deleteLabel }}\n\t\t\t\t\t\t</NcActionButton>\n\t\t\t\t\t</template>\n\t\t\t\t</NcListItem>\n\t\t\t</div>\n\t\t\t<NcButton\n\t\t\t\tv-if=\"files.length < total\"\n\t\t\t\tvariant=\"tertiary\"\n\t\t\t\t:wide=\"true\"\n\t\t\t\t:disabled=\"loadingMore\"\n\t\t\t\tclass=\"cn-sidebar-tab__load-more\"\n\t\t\t\t@click=\"loadMore\">\n\t\t\t\t<template v-if=\"loadingMore\" #icon>\n\t\t\t\t\t<NcLoadingIcon :size=\"20\" />\n\t\t\t\t</template>\n\t\t\t\t{{ loadMoreLabel }}\n\t\t\t</NcButton>\n\t\t</template>\n\t\t<CnFilePreview v-if=\"previewFile\" :file=\"previewFile\" @close=\"previewFile = null\" />\n\t</div>\n</template>\n\n<script>\nimport { getCurrentUser } from '@nextcloud/auth'\nimport axios from '@nextcloud/axios'\nimport { getCapabilities } from '@nextcloud/capabilities'\nimport { translate as t } from '@nextcloud/l10n'\nimport { generateRemoteUrl, generateUrl } from '@nextcloud/router'\nimport {\n\tNcActionButton,\n\tNcActionLink,\n\tNcActionSeparator,\n\tNcButton,\n\tNcCheckboxRadioSwitch,\n\tNcDateTime,\n\tNcEmptyContent,\n\tNcListItem,\n\tNcLoadingIcon,\n} from '@nextcloud/vue'\nimport Delete from 'vue-material-design-icons/Delete.vue'\nimport Download from 'vue-material-design-icons/Download.vue'\nimport FileDocumentEditOutline from 'vue-material-design-icons/FileDocumentEditOutline.vue'\nimport FileOutline from 'vue-material-design-icons/FileOutline.vue'\nimport FolderOutline from 'vue-material-design-icons/FolderOutline.vue'\nimport InformationOutline from 'vue-material-design-icons/InformationOutline.vue'\nimport LinkVariant from 'vue-material-design-icons/LinkVariant.vue'\nimport OpenInNew from 'vue-material-design-icons/OpenInNew.vue'\nimport Paperclip from 'vue-material-design-icons/Paperclip.vue'\nimport Upload from 'vue-material-design-icons/Upload.vue'\nimport CnFilePreview from '../CnFilePreview/CnFilePreview.vue'\nimport CnFilesBrowser from '../CnFilesBrowser/CnFilesBrowser.vue'\nimport { useFileOpener } from '../../composables/useFileOpener.js'\nimport { buildHeaders, prefixUrl } from '../../utils/index.js'\nimport { indexRowData, objectDisplayName, resolveObjectFolderInfo } from '../CnFilesBrowser/filesBrowser.js'\nimport { createOpenRegisterSource } from '../CnFilesBrowser/openRegisterSource.js'\n\n/**\n * The mime types Nextcloud Office opens by default for the current person.\n *\n * richdocuments publishes its capabilities only to a person it lets use\n * Office, so an empty list means no Office here, or none for them.\n *\n * @return {Array<string>} The mime types, or an empty list.\n */\nfunction readOfficeMimetypes() {\n\ttry {\n\t\tconst mimetypes = getCapabilities()?.richdocuments?.mimetypes\n\t\treturn Array.isArray(mimetypes) ? mimetypes.filter((mime) => typeof mime === 'string') : []\n\t} catch {\n\t\treturn []\n\t}\n}\n\nexport default {\n\tname: 'CnFilesTab',\n\n\tcomponents: {\n\t\tCnFilePreview,\n\t\tCnFilesBrowser,\n\t\tNcActionButton,\n\t\tNcActionLink,\n\t\tNcActionSeparator,\n\t\tNcButton,\n\t\tNcCheckboxRadioSwitch,\n\t\tNcDateTime,\n\t\tNcEmptyContent,\n\t\tNcListItem,\n\t\tNcLoadingIcon,\n\t\tDelete,\n\t\tDownload,\n\t\tFileDocumentEditOutline,\n\t\tFileOutline,\n\t\tFolderOutline,\n\t\tInformationOutline,\n\t\tLinkVariant,\n\t\tOpenInNew,\n\t\tPaperclip,\n\t\tUpload,\n\t},\n\n\tprops: {\n\t\t/** ID of the object this tab belongs to */\n\t\tobjectId: { type: String, required: true },\n\t\t/** OpenRegister register slug */\n\t\tregister: { type: String, default: '' },\n\t\t/** JSON Schema definition for the object */\n\t\tschema: { type: String, default: '' },\n\t\t/** Base URL for the OpenRegister API */\n\t\tapiBase: { type: String, default: '/apps/openregister/api' },\n\t\t/** Text shown inside the file drop zone */\n\t\tdropZoneLabel: { type: String, default: () => t('nextcloud-vue', 'Drop files here or click to browse') },\n\t\t/** Text shown when no files are attached */\n\t\tnoFilesLabel: { type: String, default: () => t('nextcloud-vue', 'No files attached') },\n\t\t/** Label for the open/view file action */\n\t\topenLabel: { type: String, default: () => t('nextcloud-vue', 'Open') },\n\t\t/**\n\t\t * Label of the action that opens a document in Nextcloud Office through\n\t\t * OpenRegister's Office page. Shown only when Office is there for this\n\t\t * person and opens the file's type; the page opens it for editing or\n\t\t * read-only by the object's own rule.\n\t\t */\n\t\topenInOfficeLabel: { type: String, default: () => t('nextcloud-vue', 'Open in Office') },\n\t\t/** Label for the delete action */\n\t\tdeleteLabel: { type: String, default: () => t('nextcloud-vue', 'Delete') },\n\t\t/** What the files browser's root crumb reads; null shows the object's name, else the folder's own name. */\n\t\tbrowserRootLabel: { type: String, default: null },\n\t\t/**\n\t\t * Where the files browser reads the object's folder from.\n\t\t * `openregister` (the default) goes through OpenRegister's files API under\n\t\t * the object's access rule, so anyone who may read the object sees its\n\t\t * files, without a share. `webdav` is the earlier behaviour: the folder is\n\t\t * looked up in the person's own Files over WebDAV and the browser shows\n\t\t * only when it is shared with them.\n\t\t */\n\t\tsource: {\n\t\t\ttype: String,\n\t\t\tdefault: 'openregister',\n\t\t\tvalidator: (value) => ['openregister', 'webdav'].includes(value),\n\t\t},\n\n\t\t/** Forwarded to CnFilesBrowser: a primary \"Add files\" button beside the New menu. */\n\t\tuploadButton: { type: Boolean, default: false },\n\t\t/** Forwarded to CnFilesBrowser: the drop state drawn over the list (\"Drop to add\") and announced. */\n\t\tdropOverlay: { type: Boolean, default: false },\n\t\t/** Forwarded to CnFilesBrowser: \"Or drag files onto this list.\" under the list. */\n\t\tdropHint: { type: Boolean, default: false },\n\t\t/**\n\t\t * The host's own actions on each file row of the browser, forwarded\n\t\t * to CnFilesBrowser's `rowActions`: declared like any manifest action\n\t\t * and dispatched with the file's id, name and path merged in.\n\t\t *\n\t\t * @type {Array<{id: string, label: string, icon?: string, type?: string, target?: string, props?: object}>}\n\t\t */\n\t\trowActions: { type: Array, default: () => [] },\n\t\t/**\n\t\t * The host's own entries in the browser's New menu, forwarded to\n\t\t * CnFilesBrowser's `newActions`: declared like a row action and\n\t\t * dispatched with the folder rather than a row, for things like\n\t\t * \"new from template\" or \"request a file from a party\".\n\t\t *\n\t\t * @type {Array<{id: string, label: string, icon?: string, type?: string, target?: string, props?: object}>}\n\t\t */\n\t\tnewActions: { type: Array, default: () => [] },\n\t\t/**\n\t\t * An app endpoint that answers the object's linked files, rows the\n\t\t * browser shows after the folder's own (files the host joined from\n\t\t * another object's folder). App-relative; `{objectId}` is replaced.\n\t\t * The response is an array (or `{ items: [] }`) of\n\t\t * `{ id, name, mime?, size?, mtime?, href?, downloadHref?, note?, noteHref? }`.\n\t\t * Null fetches nothing.\n\t\t */\n\t\tlinkedItemsUrl: { type: String, default: null },\n\t\t/**\n\t\t * Forwarded to CnFilesBrowser: the columns the browser shows, built-in\n\t\t * names or declared columns (`{ key, label, source, formatter }`).\n\t\t * A `source: 'row'` column reads the host's record for the file from\n\t\t * `rowDataUrl`. None keeps name, size and modified.\n\t\t *\n\t\t * @type {Array<string|object>}\n\t\t */\n\t\tcolumns: { type: Array, default: () => [] },\n\t\t/** Forwarded to CnFilesBrowser: the app id the user's column choice is stored under; unset offers no Columns chooser. */\n\t\tpreferenceApp: { type: String, default: '' },\n\t\t/** Forwarded to CnFilesBrowser: the key the column choice is stored under. */\n\t\tpreferenceKey: { type: String, default: 'files-browser-columns' },\n\t\t/**\n\t\t * An app endpoint that answers the host's own record per file, for the\n\t\t * browser's `source: 'row'` columns. App-relative; `{objectId}` is\n\t\t * replaced. Read once per listing. The answer is a list of records\n\t\t * (or the list at `rowDataPath`, or under `items` or `results`), each\n\t\t * naming its file in `rowDataKey`. Null reads nothing.\n\t\t */\n\t\trowDataUrl: { type: String, default: null },\n\t\t/**\n\t\t * Forwarded to CnFilesBrowser: the host's actions on a selection of\n\t\t * files. With at least one, files get checkboxes and a bulk bar.\n\t\t *\n\t\t * @type {Array<{id: string, label: string, icon?: string, type?: string, target?: string, props?: object}>}\n\t\t */\n\t\tbulkActions: { type: Array, default: () => [] },\n\t\t/** Forwarded to CnFilesBrowser: the bulk bar's count, a template with `{count}`. */\n\t\tselectionLabel: { type: String, default: '' },\n\t\t/** Forwarded to CnFilesBrowser: the bulk bar's count for one file. */\n\t\tselectionLabelOne: { type: String, default: '' },\n\t\t/** Forwarded to CnFilesBrowser: whether the bulk bar ends in \"Clear selection\". */\n\t\tshowClearSelection: { type: Boolean, default: true },\n\t\t/**\n\t\t * Forwarded to CnFilesBrowser: cards beside the list about the last\n\t\t * selected file.\n\t\t *\n\t\t * @type {Array<{id: string, title: string, fields?: Array<object>, actions?: Array<object>}>}\n\t\t */\n\t\tsideCards: { type: Array, default: () => [] },\n\t\t/** Forwarded to CnFilesBrowser: the key of a declared column to group the files on. */\n\t\tgroupBy: { type: String, default: '' },\n\t\t/**\n\t\t * Forwarded to CnFilesBrowser: keys of declared columns to filter on,\n\t\t * a chip per value in use.\n\t\t *\n\t\t * @type {string[]}\n\t\t */\n\t\tfacets: { type: Array, default: () => [] },\n\t\t/** Forwarded to CnFilesBrowser: the host's own buttons in the bar. */\n\t\theaderActions: { type: Array, default: () => [] },\n\t\t/** Forwarded to CnFilesBrowser: one visible button on every file row. */\n\t\trowButton: { type: Object, default: null },\n\t\t/** Forwarded to CnFilesBrowser: the review summary above the list. */\n\t\treviewSummary: { type: Object, default: null },\n\t\t/** Forwarded to CnFilesBrowser: the host's own line under the list. */\n\t\tfootnote: { type: String, default: '' },\n\t\t/** Forwarded to CnFilesBrowser: the second line under each file's name. */\n\t\tnameSecondary: { type: String, default: '' },\n\t\t/** A dotted path to the list of records in the `rowDataUrl` answer; empty reads the answer itself. */\n\t\trowDataPath: { type: String, default: '' },\n\t\t/** The record field that holds the Nextcloud file id. */\n\t\trowDataKey: { type: String, default: 'fileId' },\n\t\t/** Label of the Download action. */\n\t\tdownloadLabel: { type: String, default: () => t('nextcloud-vue', 'Download') },\n\t\t/** Label of the action that opens the Files sidebar on the file. */\n\t\tdetailsLabel: { type: String, default: () => t('nextcloud-vue', 'Details and sharing') },\n\t\t/** Label of the link that opens the file in the Files app. */\n\t\tshowInFilesLabel: { type: String, default: () => t('nextcloud-vue', 'Show in Files') },\n\t\t/** Label of the action that copies the file permalink. */\n\t\tcopyLinkLabel: { type: String, default: () => t('nextcloud-vue', 'Copy link') },\n\t\t/** Label for the load-more button */\n\t\tloadMoreLabel: { type: String, default: () => t('nextcloud-vue', 'Load more') },\n\t\t/**\n\t\t * Whether to render the \"share uploaded files\" toggle. Off by default;\n\t\t * when false, uploads never set the share flag (no auto-publish).\n\t\t *\n\t\t * @type {boolean}\n\t\t */\n\t\tshowShareToggle: { type: Boolean, default: false },\n\t\t/**\n\t\t * Initial state for the share toggle. `true`/`false` wins outright;\n\t\t * `null` (the default) defers to the schema's\n\t\t * `configuration.defaultAutoShare` from OpenRegister.\n\t\t *\n\t\t * @type {boolean|null}\n\t\t */\n\t\tdefaultShare: { type: Boolean, default: null },\n\t\t/** Label for the share toggle */\n\t\tshareLabel: { type: String, default: () => t('nextcloud-vue', 'Share uploaded files') },\n\t},\n\n\tdata() {\n\t\treturn {\n\t\t\tpreviewFile: null,\n\t\t\tfiles: [],\n\t\t\tloading: false,\n\t\t\tloadingMore: false,\n\t\t\tisDragOver: false,\n\t\t\tuploadError: '',\n\t\t\tpage: 1,\n\t\t\ttotal: 0,\n\t\t\tlimit: 20,\n\t\t\tshare: false,\n\t\t\t/** The object's folder as a user-relative path, or null while unresolved or absent. */\n\t\t\tbrowserRoot: null,\n\t\t\t/** The browser's data source for `source: 'openregister'`, or null for WebDAV. */\n\t\t\tbrowserSource: null,\n\t\t\tbrowserObjectName: null,\n\t\t\tlinkedItems: [],\n\t\t\t/** File ids whose preview request failed, so the row falls back to the mime icon. */\n\t\t\tpreviewFailed: {},\n\t\t\t/**\n\t\t\t * The file input element, set by the template's function ref.\n\t\t\t *\n\t\t\t * Held here rather than read back through `$refs` so the ref stays\n\t\t\t * DYNAMIC — see the long comment on the input itself for why a\n\t\t\t * static ref on this element is a production crash.\n\t\t\t *\n\t\t\t * @type {HTMLInputElement|null}\n\t\t\t */\n\t\t\tfileInputEl: null,\n\t\t\t/** The mime types Nextcloud Office opens for this person; empty without Office. */\n\t\t\tofficeMimetypes: readOfficeMimetypes(),\n\t\t}\n\t},\n\n\tcomputed: {\n\t\t/**\n\t\t * The browser's `rowData`: a function that reads the host's records\n\t\t * from `rowDataUrl` and keys them by file id, or null without a url.\n\t\t * The browser calls it once per listing.\n\t\t *\n\t\t * @return {(function(): Promise<object>)|null} The row data source.\n\t\t * @spec openspec/changes/files-browser-hosts-a-documents-list/specs/files-browser/spec.md\n\t\t */\n\t\trowDataSource() {\n\t\t\tif (!this.rowDataUrl || !this.objectId) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tconst url = generateUrl(this.rowDataUrl.replace('{objectId}', encodeURIComponent(this.objectId)))\n\t\t\tconst path = this.rowDataPath\n\t\t\tconst key = this.rowDataKey\n\t\t\treturn async () => {\n\t\t\t\tconst { data } = await axios.get(url)\n\t\t\t\treturn indexRowData(data, { path, key })\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * The root crumb: the host's label, else the object's name (its folder\n\t\t * on disk is called after its uuid), else the folder's own name.\n\t\t *\n\t\t * @return {string|null}\n\t\t * @spec openspec/changes/dutch-library-strings-and-files-crumb/specs/dutch-library-strings-and-files-crumb/spec.md#requirement-the-files-browser-names-the-object-in-its-root-crumb\n\t\t */\n\t\teffectiveBrowserRootLabel() {\n\t\t\treturn this.browserRootLabel || this.browserObjectName || null\n\t\t},\n\t},\n\n\twatch: {\n\t\t// Match every other CnObjectSidebar tab — a single immediate\n\t\t// `objectId` watcher drives all initial loads. Folding the\n\t\t// share-toggle seed in here avoids two concurrent GETs of\n\t\t// `schemas/{schema}` on mount (one per immediate watcher).\n\t\tobjectId: {\n\t\t\timmediate: true,\n\t\t\thandler(id) {\n\t\t\t\tif (id) {\n\t\t\t\t\tthis.fetchFiles()\n\t\t\t\t}\n\t\t\t\tthis.applyShareDefault()\n\t\t\t\tthis.resolveBrowserRoot()\n\t\t\t\tthis.fetchLinkedItems()\n\t\t\t},\n\t\t},\n\n\t\tlinkedItemsUrl() {\n\t\t\tthis.fetchLinkedItems()\n\t\t},\n\n\t\tsource() {\n\t\t\tthis.resolveBrowserRoot()\n\t\t},\n\t},\n\n\tmethods: {\n\t\t/**\n\t\t * Function ref for the file input.\n\t\t *\n\t\t * A method (not an inline arrow in the template) so the binding is a\n\t\t * stable reference across renders and Vue does not detach/reattach the\n\t\t * ref on every patch. Being a function ref is what keeps the vnode\n\t\t * dynamic — see the template comment on the input.\n\t\t *\n\t\t * @param {HTMLInputElement|null} el The element, or null on unmount.\n\t\t * @return {void}\n\t\t */\n\t\tfileInputRef(el) {\n\t\t\tthis.fileInputEl = el || null\n\t\t},\n\n\t\t/**\n\t\t * Find the object's folder for the browser, or leave the legacy list.\n\t\t *\n\t\t * @return {Promise<void>}\n\t\t */\n\t\t/**\n\t\t * The browser changed the folder: refresh the object's file list and\n\t\t * the linked rows, since a join or a move can change either.\n\t\t *\n\t\t * @return {void}\n\t\t */\n\t\tonBrowserChanged() {\n\t\t\tthis.fetchFiles()\n\t\t\tthis.fetchLinkedItems()\n\t\t},\n\n\t\t/**\n\t\t * Read the object's linked files from the host's endpoint, if any.\n\t\t *\n\t\t * A failure leaves the last list in place and logs at debug: the\n\t\t * folder's own rows are the surface, the linked rows a supplement.\n\t\t *\n\t\t * @return {Promise<void>}\n\t\t */\n\t\tasync fetchLinkedItems() {\n\t\t\tif (!this.linkedItemsUrl || !this.objectId) {\n\t\t\t\tthis.linkedItems = []\n\t\t\t\treturn\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tconst url = generateUrl(this.linkedItemsUrl.replace('{objectId}', encodeURIComponent(this.objectId)))\n\t\t\t\tconst { data } = await axios.get(url)\n\t\t\t\tconst items = Array.isArray(data) ? data : (Array.isArray(data?.items) ? data.items : [])\n\t\t\t\tthis.linkedItems = items.filter((item) => item && typeof item === 'object')\n\t\t\t} catch (error) {\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.debug('[CnFilesTab] linked items not read', error)\n\t\t\t}\n\t\t},\n\n\t\tasync resolveBrowserRoot() {\n\t\t\tthis.browserRoot = null\n\t\t\tthis.browserSource = null\n\t\t\tthis.browserObjectName = null\n\t\t\tif (!this.objectId || !this.register || !this.schema) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif (this.source === 'openregister') {\n\t\t\t\tawait this.resolveOpenRegisterSource()\n\t\t\t\treturn\n\t\t\t}\n\t\t\tlet remoteUrl\n\t\t\ttry {\n\t\t\t\tremoteUrl = generateRemoteUrl('dav')\n\t\t\t} catch {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst info = await resolveObjectFolderInfo({\n\t\t\t\tapiBase: this.apiBase,\n\t\t\t\tregister: this.register,\n\t\t\t\tschema: this.schema,\n\t\t\t\tobjectId: this.objectId,\n\t\t\t\tuid: getCurrentUser()?.uid || '',\n\t\t\t\tremoteUrl,\n\t\t\t})\n\t\t\tthis.browserRoot = info === null ? null : info.path\n\t\t\tthis.browserObjectName = info === null ? null : info.name\n\t\t},\n\n\t\t/**\n\t\t * Use OpenRegister's files API for the browser, when this person may read\n\t\t * the object's folder through it. A listing that fails (no read on the\n\t\t * object, or an OpenRegister without the folder endpoints) leaves the\n\t\t * legacy list, as an unresolved WebDAV folder did.\n\t\t *\n\t\t * @return {Promise<void>}\n\t\t * @spec openspec/changes/files-browser-openregister-source/specs/files-browser/spec.md\n\t\t */\n\t\tasync resolveOpenRegisterSource() {\n\t\t\tconst objectId = this.objectId\n\t\t\tconst source = createOpenRegisterSource({\n\t\t\t\tapiBase: this.apiBase,\n\t\t\t\tregister: this.register,\n\t\t\t\tschema: this.schema,\n\t\t\t\tobjectId,\n\t\t\t})\n\t\t\ttry {\n\t\t\t\tawait source.list('/')\n\t\t\t} catch {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif (objectId !== this.objectId) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.browserSource = source\n\t\t\tthis.browserRoot = '/'\n\t\t\tthis.fetchObjectName()\n\t\t},\n\n\t\t/**\n\t\t * Read the object's name for the root crumb, by the same rule the WebDAV\n\t\t * path uses (`objectDisplayName`: never the uuid). The OpenRegister path\n\t\t * has no folder lookup to piggyback on, so this is its one object read.\n\t\t * A failure keeps the crumb on its default.\n\t\t *\n\t\t * @return {Promise<void>}\n\t\t */\n\t\tasync fetchObjectName() {\n\t\t\tconst objectId = this.objectId\n\t\t\ttry {\n\t\t\t\tconst { data } = await axios.get(generateUrl(`${this.apiBase}/objects/{register}/{schema}/{objectId}`, {\n\t\t\t\t\tregister: this.register,\n\t\t\t\t\tschema: this.schema,\n\t\t\t\t\tobjectId,\n\t\t\t\t}))\n\t\t\t\tif (objectId === this.objectId) {\n\t\t\t\t\tthis.browserObjectName = objectDisplayName(data, objectId)\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\t// The crumb keeps its default.\n\t\t\t}\n\t\t},\n\n\t\tasync fetchFiles(append = false) {\n\t\t\tif (!this.register || !this.schema) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif (append) {\n\t\t\t\tthis.loadingMore = true\n\t\t\t} else {\n\t\t\t\tthis.loading = true\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tconst params = new URLSearchParams({ limit: this.limit, _page: this.page })\n\t\t\t\tconst response = await fetch(\n\t\t\t\t\tprefixUrl(`${this.apiBase}/objects/${this.register}/${this.schema}/${this.objectId}/files?${params}`),\n\t\t\t\t\t{ headers: buildHeaders() },\n\t\t\t\t)\n\t\t\t\tif (response.ok) {\n\t\t\t\t\tconst data = await response.json()\n\t\t\t\t\tconst results = data.results || data || []\n\t\t\t\t\tthis.files = append ? [...this.files, ...results] : results\n\t\t\t\t\tthis.total = data.total || this.files.length\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.error('CnFilesTab: Failed to fetch files', err)\n\t\t\t} finally {\n\t\t\t\tthis.loading = false\n\t\t\t\tthis.loadingMore = false\n\t\t\t}\n\t\t},\n\n\t\tloadMore() {\n\t\t\tthis.page++\n\t\t\tthis.fetchFiles(true)\n\t\t},\n\n\t\t/**\n\t\t * Seed the `share` toggle. The `defaultShare` prop wins when set\n\t\t * (non-null); otherwise we look up the active schema's\n\t\t * `configuration.defaultAutoShare` from OpenRegister and use that.\n\t\t * Network failure or missing key → keep the safe default (false) so\n\t\t * a hiccup never silently flips uploads to \"share\".\n\t\t *\n\t\t * @return {Promise<void>}\n\t\t */\n\t\tasync applyShareDefault() {\n\t\t\tif (this.defaultShare !== null && this.defaultShare !== undefined) {\n\t\t\t\tthis.share = !!this.defaultShare\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.share = false\n\t\t\tif (!this.schema) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tconst response = await fetch(\n\t\t\t\t\tprefixUrl(`${this.apiBase}/schemas/${this.schema}`),\n\t\t\t\t\t{ headers: buildHeaders() },\n\t\t\t\t)\n\t\t\t\tif (!response.ok) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tconst data = await response.json().catch(() => null)\n\t\t\t\tif (data?.configuration?.defaultAutoShare === true) {\n\t\t\t\t\tthis.share = true\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\t// Non-fatal — keep the safe default, but surface the\n\t\t\t\t// failure so a missing toggle default isn't silent.\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.error('CnFilesTab: Failed to fetch schema default for share toggle', err)\n\t\t\t}\n\t\t},\n\n\t\ttriggerFileInput() {\n\t\t\tthis.fileInputEl?.click()\n\t\t},\n\n\t\tonDragOver() {\n\t\t\tthis.isDragOver = true\n\t\t},\n\n\t\tonDragLeave() {\n\t\t\tthis.isDragOver = false\n\t\t},\n\n\t\tonDrop(event) {\n\t\t\tthis.isDragOver = false\n\t\t\tconst droppedFiles = event.dataTransfer?.files\n\t\t\tif (droppedFiles?.length) {\n\t\t\t\tthis.uploadFiles(droppedFiles)\n\t\t\t}\n\t\t},\n\n\t\tasync onFileUpload(event) {\n\t\t\tconst inputFiles = event.target.files\n\t\t\tif (!inputFiles?.length) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tawait this.uploadFiles(inputFiles)\n\t\t\tif (this.fileInputEl) {\n\t\t\t\tthis.fileInputEl.value = ''\n\t\t\t}\n\t\t},\n\n\t\tasync uploadFiles(fileList) {\n\t\t\tif (!fileList?.length || !this.register || !this.schema) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.uploadError = ''\n\t\t\tconst formData = new FormData()\n\t\t\tfor (const file of fileList) {\n\t\t\t\tformData.append('files[]', file)\n\t\t\t}\n\t\t\t// Only forward the share flag when the toggle is actually visible.\n\t\t\t// Hiding the toggle (showShareToggle=false) means \"don't auto-publish\".\n\t\t\tif (this.showShareToggle) {\n\t\t\t\tformData.append('share', String(this.share))\n\t\t\t}\n\n\t\t\tthis.loading = true\n\t\t\ttry {\n\t\t\t\tconst response = await fetch(\n\t\t\t\t\tprefixUrl(`${this.apiBase}/objects/${this.register}/${this.schema}/${this.objectId}/filesMultipart`),\n\t\t\t\t\t{\n\t\t\t\t\t\tmethod: 'POST',\n\t\t\t\t\t\theaders: { requesttoken: OC?.requestToken || '', 'OCS-APIREQUEST': 'true' },\n\t\t\t\t\t\tbody: formData,\n\t\t\t\t\t},\n\t\t\t\t)\n\t\t\t\tif (!response.ok) {\n\t\t\t\t\tconst data = await response.json().catch(() => ({}))\n\t\t\t\t\tthis.uploadError = data.error || `Upload failed (${response.status})`\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tawait this.fetchFiles()\n\t\t\t} catch (err) {\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.error('CnFilesTab: Failed to upload file', err)\n\t\t\t\tthis.uploadError = 'Upload failed: could not connect to server'\n\t\t\t} finally {\n\t\t\t\tthis.loading = false\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Whether the Files app's details sidebar is on this page.\n\t\t *\n\t\t * It is when the host page dispatched Nextcloud's `LoadSidebar` event\n\t\t * server-side; then `OCA.Files.Sidebar.open(path)` shows the same\n\t\t * sharing, versions, comments and activity tabs the Files app shows.\n\t\t * Absent, the row offers no details action rather than a dead one. A\n\t\t * method rather than a computed: the global is not reactive, so a\n\t\t * cached answer from before the sidebar script ran would stay wrong.\n\t\t *\n\t\t * @return {boolean} true when the sidebar can be opened.\n\t\t */\n\t\tcanShowDetails() {\n\t\t\treturn typeof window !== 'undefined' && typeof window.OCA?.Files?.Sidebar?.open === 'function'\n\t\t},\n\n\t\t/**\n\t\t * The file's path relative to the user's files root, which is the path\n\t\t * the Viewer and the Files sidebar take. OpenRegister reports the node's\n\t\t * full path (`/{uid}/files/…`), so the first two segments come off.\n\t\t *\n\t\t * @param {string} path The node path as OpenRegister reports it.\n\t\t * @return {string} The user-relative path, `/` at least.\n\t\t */\n\t\tuserRelativePath(path) {\n\t\t\tconst stripped = String(path || '').replace(/^\\/[^/]+\\/files(?=\\/|$)/, '')\n\t\t\treturn stripped === '' ? '/' : stripped\n\t\t},\n\n\t\t/**\n\t\t * The theme's own icon for the file's mime type, the one the Files app\n\t\t * draws, or null on a page without Nextcloud's core script.\n\t\t *\n\t\t * @param {object} file The file row.\n\t\t * @return {string|null} The icon url.\n\t\t */\n\t\tmimeIconFor(file) {\n\t\t\tconst getIconUrl = typeof window !== 'undefined' ? window.OC?.MimeType?.getIconUrl : null\n\t\t\tif (typeof getIconUrl !== 'function') {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tconst mime = file.type || file.mimetype || file.mimeType || ''\n\t\t\ttry {\n\t\t\t\treturn getIconUrl(mime) || null\n\t\t\t} catch {\n\t\t\t\treturn null\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * A small preview for an image, through Nextcloud's core preview\n\t\t * endpoint, or null for anything else or after the preview failed once.\n\t\t *\n\t\t * @param {object} file The file row.\n\t\t * @return {string|null} The preview url.\n\t\t */\n\t\tpreviewUrlFor(file) {\n\t\t\tconst mime = file.type || file.mimetype || file.mimeType || ''\n\t\t\tif (!file.id || !/^image\\//i.test(mime) || /svg/i.test(mime) || this.previewFailed[file.id]) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\treturn generateUrl('/core/preview?fileId={fileId}&x=64&y=64&a=1', { fileId: file.id })\n\t\t},\n\n\t\t/**\n\t\t * Remember that a preview did not load, so the row shows the mime icon.\n\t\t *\n\t\t * @param {object} file The file row.\n\t\t * @return {void}\n\t\t */\n\t\tonPreviewError(file) {\n\t\t\tthis.previewFailed = { ...this.previewFailed, [file.id]: true }\n\t\t},\n\n\t\t/**\n\t\t * The file's modification moment as a Date, or null when unknown.\n\t\t *\n\t\t * @param {object} file The file row.\n\t\t * @return {Date|null} The moment.\n\t\t */\n\t\tmodifiedAt(file) {\n\t\t\tconst raw = file.modified || file.updated || ''\n\t\t\tif (!raw) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tconst date = new Date(raw)\n\t\t\treturn Number.isNaN(date.getTime()) ? null : date\n\t\t},\n\n\t\t/**\n\t\t * The file's labels (Nextcloud tags), joined for the meta line.\n\t\t *\n\t\t * @param {object} file The file row.\n\t\t * @return {string} The labels, or the empty string.\n\t\t */\n\t\tlabelsOf(file) {\n\t\t\treturn Array.isArray(file.labels) ? file.labels.filter(Boolean).join(', ') : ''\n\t\t},\n\n\t\t/**\n\t\t * The download url for a file, through OpenRegister's file endpoint,\n\t\t * which streams the node the object owns.\n\t\t *\n\t\t * @param {object} file The file row.\n\t\t * @return {string} The url.\n\t\t */\n\t\tdownloadUrlFor(file) {\n\t\t\treturn `${this.apiBase}/files/${encodeURIComponent(String(file.id))}/download`\n\t\t},\n\n\t\t/**\n\t\t * Whether Nextcloud Office opens this file for this person.\n\t\t *\n\t\t * @param {object} file The file row.\n\t\t * @return {boolean} true when the Office action applies.\n\t\t */\n\t\tofficeOpens(file) {\n\t\t\tconst mime = file.type || file.mimetype || file.mimeType || ''\n\t\t\treturn Boolean(file.id) && mime !== '' && this.officeMimetypes.includes(mime)\n\t\t},\n\n\t\t/**\n\t\t * OpenRegister's Office page for a file of this object, which checks the\n\t\t * object rule and opens the document editable or read-only.\n\t\t *\n\t\t * @param {object} file The file row.\n\t\t * @return {string} The url.\n\t\t */\n\t\tofficeUrlFor(file) {\n\t\t\tconst appBase = /\\/api\\/?$/.test(this.apiBase) ? this.apiBase.replace(/\\/api\\/?$/, '') : '/apps/openregister'\n\t\t\tconst segments = [this.register, this.schema, this.objectId, String(file.id)].map((part) => encodeURIComponent(String(part)))\n\t\t\treturn prefixUrl(`${appBase}/office/${segments.join('/')}`)\n\t\t},\n\n\t\t/**\n\t\t * The Files app's permalink for a file: opens the Files app at the\n\t\t * file's folder with the file selected.\n\t\t *\n\t\t * @param {object} file The file row.\n\t\t * @return {string} The url.\n\t\t */\n\t\tshowInFilesUrl(file) {\n\t\t\treturn generateUrl('/f/{fileid}', { fileid: file.id })\n\t\t},\n\n\t\t/**\n\t\t * Open the Files sidebar on this file: details, sharing, versions,\n\t\t * comments and activity, exactly as the Files app offers them.\n\t\t *\n\t\t * @param {object} file The file row.\n\t\t * @return {void}\n\t\t */\n\t\tshowDetails(file) {\n\t\t\tif (!this.canShowDetails() || !file.path) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\twindow.OCA.Files.Sidebar.open(this.userRelativePath(file.path))\n\t\t},\n\n\t\t/**\n\t\t * Put the file's permalink on the clipboard and say so.\n\t\t *\n\t\t * @param {object} file The file row.\n\t\t * @return {Promise<void>}\n\t\t */\n\t\tasync copyLink(file) {\n\t\t\tconst href = new URL(this.showInFilesUrl(file), window.location.origin).href\n\t\t\ttry {\n\t\t\t\tawait navigator.clipboard.writeText(href)\n\t\t\t\tconst { showSuccess } = await import('@nextcloud/dialogs')\n\t\t\t\tshowSuccess(t('nextcloud-vue', 'Link copied'))\n\t\t\t} catch {\n\t\t\t\tconst { showError } = await import('@nextcloud/dialogs')\n\t\t\t\tshowError(t('nextcloud-vue', 'The link could not be copied'))\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Show a file in the in-page preview.\n\t\t *\n\t\t * @param {object} file The file to preview.\n\t\t */\n\t\tshowPreview(file) {\n\t\t\tthis.previewFile = file\n\t\t},\n\n\t\t/**\n\t\t * Open a file through the shared opener (Viewer, preview, browser, Files).\n\t\t *\n\t\t * @param {object} file The file row.\n\t\t */\n\t\topenFile(file) {\n\t\t\tuseFileOpener({\n\t\t\t\tonPreview: this.showPreview,\n\t\t\t\tuserRelativePath: this.userRelativePath,\n\t\t\t\tanyAccessUrl: true,\n\t\t\t\tfilesAppUrl: (f) => {\n\t\t\t\t\tconst dirPath = f.path ? f.path.substring(0, f.path.lastIndexOf('/')) : ''\n\t\t\t\t\tconst cleanPath = dirPath.replace(/^\\/admin\\/files\\//, '/')\n\t\t\t\t\treturn `/index.php/apps/files/files/${f.id}?dir=${encodeURIComponent(cleanPath)}&openfile=true`\n\t\t\t\t},\n\t\t\t}).open(file)\n\t\t},\n\n\t\tasync deleteFile(file) {\n\t\t\tif (!this.register || !this.schema) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tawait fetch(\n\t\t\t\t\tprefixUrl(`${this.apiBase}/objects/${this.register}/${this.schema}/${this.objectId}/files/${file.id}`),\n\t\t\t\t\t{ method: 'DELETE', headers: buildHeaders() },\n\t\t\t\t)\n\t\t\t\tthis.files = this.files.filter((f) => f.id !== file.id)\n\t\t\t} catch (err) {\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.error('CnFilesTab: Failed to delete file', err)\n\t\t\t}\n\t\t},\n\n\t\tformatFileSize(bytes) {\n\t\t\tconst sizes = ['Bytes', 'KB', 'MB', 'GB']\n\t\t\tif (!bytes || bytes === 0) {\n\t\t\t\treturn 'n/a'\n\t\t\t}\n\t\t\tconst i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)))\n\t\t\tif (i === 0) {\n\t\t\t\treturn '< 1 KB'\n\t\t\t}\n\t\t\treturn (bytes / Math.pow(1024, i)).toFixed(1) + ' ' + sizes[i]\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n.cn-sidebar-tab { padding: 12px; }\n\n.cn-sidebar-tab__upload-error {\n\tpadding: 8px 12px;\n\tmargin-bottom: 8px;\n\tborder-radius: var(--border-radius, 4px);\n\tbackground-color: var(--color-error-light, rgba(229, 57, 53, 0.1));\n\tcolor: var(--color-error, #e53935);\n\tfont-size: 13px;\n}\n\n.cn-sidebar-tab__dropzone {\n\tdisplay: flex;\n\tflex-direction: column;\n\talign-items: center;\n\tjustify-content: center;\n\tgap: 8px;\n\tpadding: 20px 12px;\n\tmargin-bottom: 16px;\n\tborder: 2px dashed var(--color-border);\n\tborder-radius: var(--border-radius-large, 8px);\n\tcursor: pointer;\n\ttransition: border-color 0.15s ease, background-color 0.15s ease;\n}\n\n.cn-sidebar-tab__dropzone:hover {\n\tborder-color: var(--color-primary-element);\n\tbackground-color: var(--color-primary-element-light, rgba(0, 130, 201, 0.08));\n}\n\n.cn-sidebar-tab__dropzone--active {\n\tborder-color: var(--color-primary-element);\n\tbackground-color: var(--color-primary-element-light, rgba(0, 130, 201, 0.12));\n}\n\n.cn-sidebar-tab__share { margin-bottom: 12px; }\n\n.cn-sidebar-tab__dropzone-icon { color: var(--color-text-maxcontrast); }\n\n.cn-sidebar-tab__dropzone--active .cn-sidebar-tab__dropzone-icon,\n.cn-sidebar-tab__dropzone:hover .cn-sidebar-tab__dropzone-icon { color: var(--color-primary-element); }\n\n.cn-sidebar-tab__dropzone-text { font-size: 13px; color: var(--color-text-maxcontrast); }\n\n.cn-sidebar-tab__file-input { display: none; }\n\n.cn-sidebar-tab__empty {\n\ttext-align: center;\n\tpadding: 24px 12px;\n\tcolor: var(--color-text-maxcontrast);\n\tfont-size: 13px;\n}\n\n.cn-sidebar-tab__list { display: flex; flex-direction: column; gap: 2px; }\n\n.cn-sidebar-tab__mime,\n.cn-sidebar-tab__thumb {\n\twidth: 32px;\n\theight: 32px;\n\tdisplay: block;\n}\n\n.cn-sidebar-tab__thumb {\n\tobject-fit: cover;\n\tborder-radius: var(--border-radius, 4px);\n}\n\n.cn-sidebar-tab__meta { color: var(--color-text-maxcontrast); }\n\n.cn-sidebar-tab__load-more { margin-top: 8px; }\n</style>\n"],"names":["CnFilePreview","CnFilesBrowser","t","axios"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"CnFilesTab.vue2.js","sources":["../../../../src/components/CnObjectSidebar/CnFilesTab.vue"],"sourcesContent":["<template>\n\t<div class=\"cn-sidebar-tab\">\n\t\t<!-- The object's folder as a real files browser, on the Files app's own\n\t\t primitives (its actions, its New menu, its breadcrumbs), when the\n\t\t folder resolves for this user. The list below is the fallback for an\n\t\t object with no folder, or a user the folder is not shared with. -->\n\t\t<CnFilesBrowser\n\t\t\tv-if=\"browserRoot !== null\"\n\t\t\t:rootPath=\"browserRoot\"\n\t\t\t:rootLabel=\"effectiveBrowserRootLabel\"\n\t\t\t:source=\"browserSource\"\n\t\t\t:deleteLabel=\"deleteLabel\"\n\t\t\t:uploadButton=\"uploadButton\"\n\t\t\t:dropOverlay=\"dropOverlay\"\n\t\t\t:dropLabel=\"dropLabel\"\n\t\t\t:dropDetail=\"dropDetail\"\n\t\t\t:dropHint=\"dropHint\"\n\t\t\t:rowActions=\"rowActions\"\n\t\t\t:newActions=\"newActions\"\n\t\t\t:headerActions=\"headerActions\"\n\t\t\t:rowButton=\"rowButton\"\n\t\t\t:reviewSummary=\"reviewSummary\"\n\t\t\t:footnote=\"footnote\"\n\t\t\t:nameSecondary=\"nameSecondary\"\n\t\t\t:linkedItems=\"linkedItems\"\n\t\t\t:columns=\"columns\"\n\t\t\t:rowData=\"rowDataSource\"\n\t\t\t:preferenceApp=\"preferenceApp\"\n\t\t\t:preferenceKey=\"preferenceKey\"\n\t\t\t:bulkActions=\"bulkActions\"\n\t\t\t:selectionLabel=\"selectionLabel\"\n\t\t\t:selectionLabelOne=\"selectionLabelOne\"\n\t\t\t:showClearSelection=\"showClearSelection\"\n\t\t\t:sideCards=\"sideCards\"\n\t\t\t:groupBy=\"groupBy\"\n\t\t\t:facets=\"facets\"\n\t\t\t@changed=\"onBrowserChanged\" />\n\t\t<template v-else>\n\t\t\t<!-- Upload error -->\n\t\t\t<div v-if=\"uploadError\" class=\"cn-sidebar-tab__upload-error\">\n\t\t\t\t{{ uploadError }}\n\t\t\t</div>\n\n\t\t\t<!-- Share toggle — seeds from schema config (defaultAutoShare) or\n\t\t from the `defaultShare` prop. Hidden via `showShareToggle=false`. -->\n\t\t\t<NcCheckboxRadioSwitch\n\t\t\t\tv-if=\"showShareToggle\"\n\t\t\t\tv-model=\"share\"\n\t\t\t\tclass=\"cn-sidebar-tab__share\"\n\t\t\t\t:disabled=\"loading\"\n\t\t\t\ttype=\"switch\">\n\t\t\t\t{{ shareLabel }}\n\t\t\t</NcCheckboxRadioSwitch>\n\n\t\t\t<!-- File drop zone -->\n\t\t\t<div\n\t\t\t\tclass=\"cn-sidebar-tab__dropzone\"\n\t\t\t\t:class=\"{ 'cn-sidebar-tab__dropzone--active': isDragOver }\"\n\t\t\t\t@click=\"triggerFileInput\"\n\t\t\t\t@dragover.prevent=\"onDragOver\"\n\t\t\t\t@dragleave.prevent=\"onDragLeave\"\n\t\t\t\t@drop.prevent=\"onDrop\">\n\t\t\t\t<!--\n\t\t\t\t`:ref` (dynamic), not `ref` (static), and this is load-bearing.\n\n\t\t\t\tEvery other binding on this input is static, and Vue caches the\n\t\t\t\t`@change` handler, so with a STATIC ref the compiler hoists the\n\t\t\t\twhole vnode to module scope. A hoisted vnode is created once,\n\t\t\t\toutside any render, so its ref carries no owner instance\n\t\t\t\t(`rawRef.i === null`).\n\n\t\t\t\t`setRef()` guards that — but the guard AND its early `return`\n\t\t\t\tlive inside `if (process.env.NODE_ENV !== 'production')`. In a\n\t\t\t\tdevelopment build you get the warning \"Missing ref owner\n\t\t\t\tcontext. ref cannot be used on hoisted vnodes.\" and nothing\n\t\t\t\tbreaks. In a PRODUCTION build the guard is compiled out and\n\t\t\t\texecution falls through to `owner.refs`, throwing\n\t\t\t\t`TypeError: Cannot read properties of null (reading 'refs')`\n\t\t\t\t— which aborts the render of whatever mounted this tab.\n\n\t\t\t\tMeasured: hrmq's detail pages (the only pages in the fleet that\n\t\t\t\treach CnIntegrationWidget through a `widgets[]` grid) rendered a\n\t\t\t\tCOMPLETELY BLANK content pane in production while looking fine\n\t\t\t\tin dev. A dynamic ref is compiled as a patchable prop, so the\n\t\t\t\tvnode is created inside the render function and owns a proper\n\t\t\t\tinstance.\n\t\t\t-->\n\t\t\t\t<input\n\t\t\t\t\t:ref=\"fileInputRef\"\n\t\t\t\t\ttype=\"file\"\n\t\t\t\t\tmultiple\n\t\t\t\t\tclass=\"cn-sidebar-tab__file-input\"\n\t\t\t\t\t@change=\"onFileUpload\">\n\t\t\t\t<Upload :size=\"24\" class=\"cn-sidebar-tab__dropzone-icon\" />\n\t\t\t\t<span class=\"cn-sidebar-tab__dropzone-text\">{{ dropZoneLabel }}</span>\n\t\t\t</div>\n\n\t\t\t<!-- File list. Each row borrows what Nextcloud already has on this\n\t\t page: the theme's own mime icon (OC.MimeType), the core preview\n\t\t endpoint for images, the Viewer for opening, and the Files sidebar\n\t\t for details, sharing and versions. Nothing of the Files app is\n\t\t rebuilt here; the row hands over to it. -->\n\t\t\t<NcLoadingIcon v-if=\"loading\" />\n\t\t\t<NcEmptyContent\n\t\t\t\tv-else-if=\"files.length === 0\"\n\t\t\t\tclass=\"cn-sidebar-tab__empty\"\n\t\t\t\t:name=\"noFilesLabel\"\n\t\t\t\t:description=\"dropZoneLabel\">\n\t\t\t\t<template #icon>\n\t\t\t\t\t<Paperclip :size=\"44\" />\n\t\t\t\t</template>\n\t\t\t</NcEmptyContent>\n\t\t\t<div v-else class=\"cn-sidebar-tab__list\">\n\t\t\t\t<NcListItem\n\t\t\t\t\tv-for=\"file in files\"\n\t\t\t\t\t:key=\"file.id\"\n\t\t\t\t\t:name=\"file.name || file.title\"\n\t\t\t\t\t:bold=\"false\"\n\t\t\t\t\t:forceDisplayActions=\"true\"\n\t\t\t\t\t@click=\"openFile(file)\">\n\t\t\t\t\t<template #icon>\n\t\t\t\t\t\t<img\n\t\t\t\t\t\t\tv-if=\"previewUrlFor(file)\"\n\t\t\t\t\t\t\tclass=\"cn-sidebar-tab__thumb\"\n\t\t\t\t\t\t\t:src=\"previewUrlFor(file)\"\n\t\t\t\t\t\t\talt=\"\"\n\t\t\t\t\t\t\tloading=\"lazy\"\n\t\t\t\t\t\t\t@error=\"onPreviewError(file)\">\n\t\t\t\t\t\t<img\n\t\t\t\t\t\t\tv-else-if=\"mimeIconFor(file)\"\n\t\t\t\t\t\t\tclass=\"cn-sidebar-tab__mime\"\n\t\t\t\t\t\t\t:src=\"mimeIconFor(file)\"\n\t\t\t\t\t\t\talt=\"\">\n\t\t\t\t\t\t<FileOutline v-else :size=\"32\" />\n\t\t\t\t\t</template>\n\t\t\t\t\t<template #subname>\n\t\t\t\t\t\t<span class=\"cn-sidebar-tab__meta\">\n\t\t\t\t\t\t\t<span>{{ formatFileSize(file.size) }}</span>\n\t\t\t\t\t\t\t<template v-if=\"modifiedAt(file)\">\n\t\t\t\t\t\t\t\t<span aria-hidden=\"true\"> · </span>\n\t\t\t\t\t\t\t\t<NcDateTime :timestamp=\"modifiedAt(file)\" :ignoreSeconds=\"true\" />\n\t\t\t\t\t\t\t</template>\n\t\t\t\t\t\t\t<template v-if=\"labelsOf(file)\">\n\t\t\t\t\t\t\t\t<span aria-hidden=\"true\"> · </span>\n\t\t\t\t\t\t\t\t<span>{{ labelsOf(file) }}</span>\n\t\t\t\t\t\t\t</template>\n\t\t\t\t\t\t</span>\n\t\t\t\t\t</template>\n\t\t\t\t\t<template #actions>\n\t\t\t\t\t\t<NcActionButton :closeAfterClick=\"true\" @click=\"openFile(file)\">\n\t\t\t\t\t\t\t<template #icon>\n\t\t\t\t\t\t\t\t<OpenInNew :size=\"20\" />\n\t\t\t\t\t\t\t</template>\n\t\t\t\t\t\t\t{{ openLabel }}\n\t\t\t\t\t\t</NcActionButton>\n\t\t\t\t\t\t<!-- OpenRegister's Office page applies the object rule:\n\t\t\t\t\t\t update edits, read views, no read is a 404. -->\n\t\t\t\t\t\t<NcActionLink\n\t\t\t\t\t\t\tv-if=\"officeOpens(file)\"\n\t\t\t\t\t\t\t:href=\"officeUrlFor(file)\"\n\t\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\t\t:closeAfterClick=\"true\">\n\t\t\t\t\t\t\t<template #icon>\n\t\t\t\t\t\t\t\t<FileDocumentEditOutline :size=\"20\" />\n\t\t\t\t\t\t\t</template>\n\t\t\t\t\t\t\t{{ openInOfficeLabel }}\n\t\t\t\t\t\t</NcActionLink>\n\t\t\t\t\t\t<NcActionLink\n\t\t\t\t\t\t\tv-if=\"file.id\"\n\t\t\t\t\t\t\t:href=\"downloadUrlFor(file)\"\n\t\t\t\t\t\t\t:download=\"file.name || file.title || ''\"\n\t\t\t\t\t\t\t:closeAfterClick=\"true\">\n\t\t\t\t\t\t\t<template #icon>\n\t\t\t\t\t\t\t\t<Download :size=\"20\" />\n\t\t\t\t\t\t\t</template>\n\t\t\t\t\t\t\t{{ downloadLabel }}\n\t\t\t\t\t\t</NcActionLink>\n\t\t\t\t\t\t<NcActionButton\n\t\t\t\t\t\t\tv-if=\"canShowDetails() && file.path\"\n\t\t\t\t\t\t\t:closeAfterClick=\"true\"\n\t\t\t\t\t\t\t@click=\"showDetails(file)\">\n\t\t\t\t\t\t\t<template #icon>\n\t\t\t\t\t\t\t\t<InformationOutline :size=\"20\" />\n\t\t\t\t\t\t\t</template>\n\t\t\t\t\t\t\t{{ detailsLabel }}\n\t\t\t\t\t\t</NcActionButton>\n\t\t\t\t\t\t<NcActionLink\n\t\t\t\t\t\t\tv-if=\"file.id\"\n\t\t\t\t\t\t\t:href=\"showInFilesUrl(file)\"\n\t\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\t\t:closeAfterClick=\"true\">\n\t\t\t\t\t\t\t<template #icon>\n\t\t\t\t\t\t\t\t<FolderOutline :size=\"20\" />\n\t\t\t\t\t\t\t</template>\n\t\t\t\t\t\t\t{{ showInFilesLabel }}\n\t\t\t\t\t\t</NcActionLink>\n\t\t\t\t\t\t<NcActionButton v-if=\"file.id\" :closeAfterClick=\"true\" @click=\"copyLink(file)\">\n\t\t\t\t\t\t\t<template #icon>\n\t\t\t\t\t\t\t\t<LinkVariant :size=\"20\" />\n\t\t\t\t\t\t\t</template>\n\t\t\t\t\t\t\t{{ copyLinkLabel }}\n\t\t\t\t\t\t</NcActionButton>\n\t\t\t\t\t\t<NcActionSeparator />\n\t\t\t\t\t\t<NcActionButton :closeAfterClick=\"true\" @click=\"deleteFile(file)\">\n\t\t\t\t\t\t\t<template #icon>\n\t\t\t\t\t\t\t\t<Delete :size=\"20\" />\n\t\t\t\t\t\t\t</template>\n\t\t\t\t\t\t\t{{ deleteLabel }}\n\t\t\t\t\t\t</NcActionButton>\n\t\t\t\t\t</template>\n\t\t\t\t</NcListItem>\n\t\t\t</div>\n\t\t\t<NcButton\n\t\t\t\tv-if=\"files.length < total\"\n\t\t\t\tvariant=\"tertiary\"\n\t\t\t\t:wide=\"true\"\n\t\t\t\t:disabled=\"loadingMore\"\n\t\t\t\tclass=\"cn-sidebar-tab__load-more\"\n\t\t\t\t@click=\"loadMore\">\n\t\t\t\t<template v-if=\"loadingMore\" #icon>\n\t\t\t\t\t<NcLoadingIcon :size=\"20\" />\n\t\t\t\t</template>\n\t\t\t\t{{ loadMoreLabel }}\n\t\t\t</NcButton>\n\t\t</template>\n\t\t<CnFilePreview v-if=\"previewFile\" :file=\"previewFile\" @close=\"previewFile = null\" />\n\t</div>\n</template>\n\n<script>\nimport { getCurrentUser } from '@nextcloud/auth'\nimport axios from '@nextcloud/axios'\nimport { getCapabilities } from '@nextcloud/capabilities'\nimport { translate as t } from '@nextcloud/l10n'\nimport { generateRemoteUrl, generateUrl } from '@nextcloud/router'\nimport {\n\tNcActionButton,\n\tNcActionLink,\n\tNcActionSeparator,\n\tNcButton,\n\tNcCheckboxRadioSwitch,\n\tNcDateTime,\n\tNcEmptyContent,\n\tNcListItem,\n\tNcLoadingIcon,\n} from '@nextcloud/vue'\nimport Delete from 'vue-material-design-icons/Delete.vue'\nimport Download from 'vue-material-design-icons/Download.vue'\nimport FileDocumentEditOutline from 'vue-material-design-icons/FileDocumentEditOutline.vue'\nimport FileOutline from 'vue-material-design-icons/FileOutline.vue'\nimport FolderOutline from 'vue-material-design-icons/FolderOutline.vue'\nimport InformationOutline from 'vue-material-design-icons/InformationOutline.vue'\nimport LinkVariant from 'vue-material-design-icons/LinkVariant.vue'\nimport OpenInNew from 'vue-material-design-icons/OpenInNew.vue'\nimport Paperclip from 'vue-material-design-icons/Paperclip.vue'\nimport Upload from 'vue-material-design-icons/Upload.vue'\nimport CnFilePreview from '../CnFilePreview/CnFilePreview.vue'\nimport CnFilesBrowser from '../CnFilesBrowser/CnFilesBrowser.vue'\nimport { useFileOpener } from '../../composables/useFileOpener.js'\nimport { buildHeaders, prefixUrl } from '../../utils/index.js'\nimport { indexRowData, objectDisplayName, resolveObjectFolderInfo } from '../CnFilesBrowser/filesBrowser.js'\nimport { createOpenRegisterSource } from '../CnFilesBrowser/openRegisterSource.js'\n\n/**\n * The mime types Nextcloud Office opens by default for the current person.\n *\n * richdocuments publishes its capabilities only to a person it lets use\n * Office, so an empty list means no Office here, or none for them.\n *\n * @return {Array<string>} The mime types, or an empty list.\n */\nfunction readOfficeMimetypes() {\n\ttry {\n\t\tconst mimetypes = getCapabilities()?.richdocuments?.mimetypes\n\t\treturn Array.isArray(mimetypes) ? mimetypes.filter((mime) => typeof mime === 'string') : []\n\t} catch {\n\t\treturn []\n\t}\n}\n\nexport default {\n\tname: 'CnFilesTab',\n\n\tcomponents: {\n\t\tCnFilePreview,\n\t\tCnFilesBrowser,\n\t\tNcActionButton,\n\t\tNcActionLink,\n\t\tNcActionSeparator,\n\t\tNcButton,\n\t\tNcCheckboxRadioSwitch,\n\t\tNcDateTime,\n\t\tNcEmptyContent,\n\t\tNcListItem,\n\t\tNcLoadingIcon,\n\t\tDelete,\n\t\tDownload,\n\t\tFileDocumentEditOutline,\n\t\tFileOutline,\n\t\tFolderOutline,\n\t\tInformationOutline,\n\t\tLinkVariant,\n\t\tOpenInNew,\n\t\tPaperclip,\n\t\tUpload,\n\t},\n\n\tprops: {\n\t\t/** ID of the object this tab belongs to */\n\t\tobjectId: { type: String, required: true },\n\t\t/** OpenRegister register slug */\n\t\tregister: { type: String, default: '' },\n\t\t/** JSON Schema definition for the object */\n\t\tschema: { type: String, default: '' },\n\t\t/** Base URL for the OpenRegister API */\n\t\tapiBase: { type: String, default: '/apps/openregister/api' },\n\t\t/** Text shown inside the file drop zone */\n\t\tdropZoneLabel: { type: String, default: () => t('nextcloud-vue', 'Drop files here or click to browse') },\n\t\t/** Text shown when no files are attached */\n\t\tnoFilesLabel: { type: String, default: () => t('nextcloud-vue', 'No files attached') },\n\t\t/** Label for the open/view file action */\n\t\topenLabel: { type: String, default: () => t('nextcloud-vue', 'Open') },\n\t\t/**\n\t\t * Label of the action that opens a document in Nextcloud Office through\n\t\t * OpenRegister's Office page. Shown only when Office is there for this\n\t\t * person and opens the file's type; the page opens it for editing or\n\t\t * read-only by the object's own rule.\n\t\t */\n\t\topenInOfficeLabel: { type: String, default: () => t('nextcloud-vue', 'Open in Office') },\n\t\t/** Label for the delete action */\n\t\tdeleteLabel: { type: String, default: () => t('nextcloud-vue', 'Delete') },\n\t\t/** What the files browser's root crumb reads; null shows the object's name, else the folder's own name. */\n\t\tbrowserRootLabel: { type: String, default: null },\n\t\t/**\n\t\t * Where the files browser reads the object's folder from.\n\t\t * `openregister` (the default) goes through OpenRegister's files API under\n\t\t * the object's access rule, so anyone who may read the object sees its\n\t\t * files, without a share. `webdav` is the earlier behaviour: the folder is\n\t\t * looked up in the person's own Files over WebDAV and the browser shows\n\t\t * only when it is shared with them.\n\t\t */\n\t\tsource: {\n\t\t\ttype: String,\n\t\t\tdefault: 'openregister',\n\t\t\tvalidator: (value) => ['openregister', 'webdav'].includes(value),\n\t\t},\n\n\t\t/** Forwarded to CnFilesBrowser: a primary \"Add files\" button beside the New menu. */\n\t\tuploadButton: { type: Boolean, default: false },\n\t\t/** Forwarded to CnFilesBrowser: the drop state drawn over the list (\"Drop to add\") and announced. */\n\t\tdropOverlay: { type: Boolean, default: false },\n\t\t/** Forwarded to CnFilesBrowser: the drop state's line (\"Laat los om toe te voegen\"); the library's own without it. */\n\t\tdropLabel: { type: String, default: undefined },\n\t\t/** Forwarded to CnFilesBrowser: the drop state's second line, `{count}` the files dragged; it also makes the overlay fill the panel. */\n\t\tdropDetail: { type: String, default: '' },\n\t\t/** Forwarded to CnFilesBrowser: \"Or drag files onto this list.\" under the list. */\n\t\tdropHint: { type: Boolean, default: false },\n\t\t/**\n\t\t * The host's own actions on each file row of the browser, forwarded\n\t\t * to CnFilesBrowser's `rowActions`: declared like any manifest action\n\t\t * and dispatched with the file's id, name and path merged in.\n\t\t *\n\t\t * @type {Array<{id: string, label: string, icon?: string, type?: string, target?: string, props?: object}>}\n\t\t */\n\t\trowActions: { type: Array, default: () => [] },\n\t\t/**\n\t\t * The host's own entries in the browser's New menu, forwarded to\n\t\t * CnFilesBrowser's `newActions`: declared like a row action and\n\t\t * dispatched with the folder rather than a row, for things like\n\t\t * \"new from template\" or \"request a file from a party\".\n\t\t *\n\t\t * @type {Array<{id: string, label: string, icon?: string, type?: string, target?: string, props?: object}>}\n\t\t */\n\t\tnewActions: { type: Array, default: () => [] },\n\t\t/**\n\t\t * An app endpoint that answers the object's linked files, rows the\n\t\t * browser shows after the folder's own (files the host joined from\n\t\t * another object's folder). App-relative; `{objectId}` is replaced.\n\t\t * The response is an array (or `{ items: [] }`) of\n\t\t * `{ id, name, mime?, size?, mtime?, href?, downloadHref?, note?, noteHref? }`.\n\t\t * Null fetches nothing.\n\t\t */\n\t\tlinkedItemsUrl: { type: String, default: null },\n\t\t/**\n\t\t * Forwarded to CnFilesBrowser: the columns the browser shows, built-in\n\t\t * names or declared columns (`{ key, label, source, formatter }`).\n\t\t * A `source: 'row'` column reads the host's record for the file from\n\t\t * `rowDataUrl`. None keeps name, size and modified.\n\t\t *\n\t\t * @type {Array<string|object>}\n\t\t */\n\t\tcolumns: { type: Array, default: () => [] },\n\t\t/** Forwarded to CnFilesBrowser: the app id the user's column choice is stored under; unset offers no Columns chooser. */\n\t\tpreferenceApp: { type: String, default: '' },\n\t\t/** Forwarded to CnFilesBrowser: the key the column choice is stored under. */\n\t\tpreferenceKey: { type: String, default: 'files-browser-columns' },\n\t\t/**\n\t\t * An app endpoint that answers the host's own record per file, for the\n\t\t * browser's `source: 'row'` columns. App-relative; `{objectId}` is\n\t\t * replaced. Read once per listing. The answer is a list of records\n\t\t * (or the list at `rowDataPath`, or under `items` or `results`), each\n\t\t * naming its file in `rowDataKey`. Null reads nothing.\n\t\t */\n\t\trowDataUrl: { type: String, default: null },\n\t\t/**\n\t\t * Forwarded to CnFilesBrowser: the host's actions on a selection of\n\t\t * files. With at least one, files get checkboxes and a bulk bar.\n\t\t *\n\t\t * @type {Array<{id: string, label: string, icon?: string, type?: string, target?: string, props?: object}>}\n\t\t */\n\t\tbulkActions: { type: Array, default: () => [] },\n\t\t/** Forwarded to CnFilesBrowser: the bulk bar's count, a template with `{count}`. */\n\t\tselectionLabel: { type: String, default: '' },\n\t\t/** Forwarded to CnFilesBrowser: the bulk bar's count for one file. */\n\t\tselectionLabelOne: { type: String, default: '' },\n\t\t/** Forwarded to CnFilesBrowser: whether the bulk bar ends in \"Clear selection\". */\n\t\tshowClearSelection: { type: Boolean, default: true },\n\t\t/**\n\t\t * Forwarded to CnFilesBrowser: cards beside the list about the last\n\t\t * selected file.\n\t\t *\n\t\t * @type {Array<{id: string, title: string, fields?: Array<object>, actions?: Array<object>}>}\n\t\t */\n\t\tsideCards: { type: Array, default: () => [] },\n\t\t/** Forwarded to CnFilesBrowser: the key of a declared column to group the files on. */\n\t\tgroupBy: { type: String, default: '' },\n\t\t/**\n\t\t * Forwarded to CnFilesBrowser: keys of declared columns to filter on,\n\t\t * a chip per value in use.\n\t\t *\n\t\t * @type {string[]}\n\t\t */\n\t\tfacets: { type: Array, default: () => [] },\n\t\t/** Forwarded to CnFilesBrowser: the host's own buttons in the bar. */\n\t\theaderActions: { type: Array, default: () => [] },\n\t\t/** Forwarded to CnFilesBrowser: one visible button on every file row. */\n\t\trowButton: { type: Object, default: null },\n\t\t/** Forwarded to CnFilesBrowser: the review summary above the list. */\n\t\treviewSummary: { type: Object, default: null },\n\t\t/** Forwarded to CnFilesBrowser: the host's own line under the list. */\n\t\tfootnote: { type: String, default: '' },\n\t\t/** Forwarded to CnFilesBrowser: the second line under each file's name. */\n\t\tnameSecondary: { type: String, default: '' },\n\t\t/** A dotted path to the list of records in the `rowDataUrl` answer; empty reads the answer itself. */\n\t\trowDataPath: { type: String, default: '' },\n\t\t/** The record field that holds the Nextcloud file id. */\n\t\trowDataKey: { type: String, default: 'fileId' },\n\t\t/** Label of the Download action. */\n\t\tdownloadLabel: { type: String, default: () => t('nextcloud-vue', 'Download') },\n\t\t/** Label of the action that opens the Files sidebar on the file. */\n\t\tdetailsLabel: { type: String, default: () => t('nextcloud-vue', 'Details and sharing') },\n\t\t/** Label of the link that opens the file in the Files app. */\n\t\tshowInFilesLabel: { type: String, default: () => t('nextcloud-vue', 'Show in Files') },\n\t\t/** Label of the action that copies the file permalink. */\n\t\tcopyLinkLabel: { type: String, default: () => t('nextcloud-vue', 'Copy link') },\n\t\t/** Label for the load-more button */\n\t\tloadMoreLabel: { type: String, default: () => t('nextcloud-vue', 'Load more') },\n\t\t/**\n\t\t * Whether to render the \"share uploaded files\" toggle. Off by default;\n\t\t * when false, uploads never set the share flag (no auto-publish).\n\t\t *\n\t\t * @type {boolean}\n\t\t */\n\t\tshowShareToggle: { type: Boolean, default: false },\n\t\t/**\n\t\t * Initial state for the share toggle. `true`/`false` wins outright;\n\t\t * `null` (the default) defers to the schema's\n\t\t * `configuration.defaultAutoShare` from OpenRegister.\n\t\t *\n\t\t * @type {boolean|null}\n\t\t */\n\t\tdefaultShare: { type: Boolean, default: null },\n\t\t/** Label for the share toggle */\n\t\tshareLabel: { type: String, default: () => t('nextcloud-vue', 'Share uploaded files') },\n\t},\n\n\tdata() {\n\t\treturn {\n\t\t\tpreviewFile: null,\n\t\t\tfiles: [],\n\t\t\tloading: false,\n\t\t\tloadingMore: false,\n\t\t\tisDragOver: false,\n\t\t\tuploadError: '',\n\t\t\tpage: 1,\n\t\t\ttotal: 0,\n\t\t\tlimit: 20,\n\t\t\tshare: false,\n\t\t\t/** The object's folder as a user-relative path, or null while unresolved or absent. */\n\t\t\tbrowserRoot: null,\n\t\t\t/** The browser's data source for `source: 'openregister'`, or null for WebDAV. */\n\t\t\tbrowserSource: null,\n\t\t\tbrowserObjectName: null,\n\t\t\tlinkedItems: [],\n\t\t\t/** File ids whose preview request failed, so the row falls back to the mime icon. */\n\t\t\tpreviewFailed: {},\n\t\t\t/**\n\t\t\t * The file input element, set by the template's function ref.\n\t\t\t *\n\t\t\t * Held here rather than read back through `$refs` so the ref stays\n\t\t\t * DYNAMIC — see the long comment on the input itself for why a\n\t\t\t * static ref on this element is a production crash.\n\t\t\t *\n\t\t\t * @type {HTMLInputElement|null}\n\t\t\t */\n\t\t\tfileInputEl: null,\n\t\t\t/** The mime types Nextcloud Office opens for this person; empty without Office. */\n\t\t\tofficeMimetypes: readOfficeMimetypes(),\n\t\t}\n\t},\n\n\tcomputed: {\n\t\t/**\n\t\t * The browser's `rowData`: a function that reads the host's records\n\t\t * from `rowDataUrl` and keys them by file id, or null without a url.\n\t\t * The browser calls it once per listing.\n\t\t *\n\t\t * @return {(function(): Promise<object>)|null} The row data source.\n\t\t * @spec openspec/changes/files-browser-hosts-a-documents-list/specs/files-browser/spec.md\n\t\t */\n\t\trowDataSource() {\n\t\t\tif (!this.rowDataUrl || !this.objectId) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tconst url = generateUrl(this.rowDataUrl.replace('{objectId}', encodeURIComponent(this.objectId)))\n\t\t\tconst path = this.rowDataPath\n\t\t\tconst key = this.rowDataKey\n\t\t\treturn async () => {\n\t\t\t\tconst { data } = await axios.get(url)\n\t\t\t\treturn indexRowData(data, { path, key })\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * The root crumb: the host's label, else the object's name (its folder\n\t\t * on disk is called after its uuid), else the folder's own name.\n\t\t *\n\t\t * @return {string|null}\n\t\t * @spec openspec/changes/dutch-library-strings-and-files-crumb/specs/dutch-library-strings-and-files-crumb/spec.md#requirement-the-files-browser-names-the-object-in-its-root-crumb\n\t\t */\n\t\teffectiveBrowserRootLabel() {\n\t\t\treturn this.browserRootLabel || this.browserObjectName || null\n\t\t},\n\t},\n\n\twatch: {\n\t\t// Match every other CnObjectSidebar tab — a single immediate\n\t\t// `objectId` watcher drives all initial loads. Folding the\n\t\t// share-toggle seed in here avoids two concurrent GETs of\n\t\t// `schemas/{schema}` on mount (one per immediate watcher).\n\t\tobjectId: {\n\t\t\timmediate: true,\n\t\t\thandler(id) {\n\t\t\t\tif (id) {\n\t\t\t\t\tthis.fetchFiles()\n\t\t\t\t}\n\t\t\t\tthis.applyShareDefault()\n\t\t\t\tthis.resolveBrowserRoot()\n\t\t\t\tthis.fetchLinkedItems()\n\t\t\t},\n\t\t},\n\n\t\tlinkedItemsUrl() {\n\t\t\tthis.fetchLinkedItems()\n\t\t},\n\n\t\tsource() {\n\t\t\tthis.resolveBrowserRoot()\n\t\t},\n\t},\n\n\tmethods: {\n\t\t/**\n\t\t * Function ref for the file input.\n\t\t *\n\t\t * A method (not an inline arrow in the template) so the binding is a\n\t\t * stable reference across renders and Vue does not detach/reattach the\n\t\t * ref on every patch. Being a function ref is what keeps the vnode\n\t\t * dynamic — see the template comment on the input.\n\t\t *\n\t\t * @param {HTMLInputElement|null} el The element, or null on unmount.\n\t\t * @return {void}\n\t\t */\n\t\tfileInputRef(el) {\n\t\t\tthis.fileInputEl = el || null\n\t\t},\n\n\t\t/**\n\t\t * Find the object's folder for the browser, or leave the legacy list.\n\t\t *\n\t\t * @return {Promise<void>}\n\t\t */\n\t\t/**\n\t\t * The browser changed the folder: refresh the object's file list and\n\t\t * the linked rows, since a join or a move can change either.\n\t\t *\n\t\t * @return {void}\n\t\t */\n\t\tonBrowserChanged() {\n\t\t\tthis.fetchFiles()\n\t\t\tthis.fetchLinkedItems()\n\t\t},\n\n\t\t/**\n\t\t * Read the object's linked files from the host's endpoint, if any.\n\t\t *\n\t\t * A failure leaves the last list in place and logs at debug: the\n\t\t * folder's own rows are the surface, the linked rows a supplement.\n\t\t *\n\t\t * @return {Promise<void>}\n\t\t */\n\t\tasync fetchLinkedItems() {\n\t\t\tif (!this.linkedItemsUrl || !this.objectId) {\n\t\t\t\tthis.linkedItems = []\n\t\t\t\treturn\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tconst url = generateUrl(this.linkedItemsUrl.replace('{objectId}', encodeURIComponent(this.objectId)))\n\t\t\t\tconst { data } = await axios.get(url)\n\t\t\t\tconst items = Array.isArray(data) ? data : (Array.isArray(data?.items) ? data.items : [])\n\t\t\t\tthis.linkedItems = items.filter((item) => item && typeof item === 'object')\n\t\t\t} catch (error) {\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.debug('[CnFilesTab] linked items not read', error)\n\t\t\t}\n\t\t},\n\n\t\tasync resolveBrowserRoot() {\n\t\t\tthis.browserRoot = null\n\t\t\tthis.browserSource = null\n\t\t\tthis.browserObjectName = null\n\t\t\tif (!this.objectId || !this.register || !this.schema) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif (this.source === 'openregister') {\n\t\t\t\tawait this.resolveOpenRegisterSource()\n\t\t\t\treturn\n\t\t\t}\n\t\t\tlet remoteUrl\n\t\t\ttry {\n\t\t\t\tremoteUrl = generateRemoteUrl('dav')\n\t\t\t} catch {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst info = await resolveObjectFolderInfo({\n\t\t\t\tapiBase: this.apiBase,\n\t\t\t\tregister: this.register,\n\t\t\t\tschema: this.schema,\n\t\t\t\tobjectId: this.objectId,\n\t\t\t\tuid: getCurrentUser()?.uid || '',\n\t\t\t\tremoteUrl,\n\t\t\t})\n\t\t\tthis.browserRoot = info === null ? null : info.path\n\t\t\tthis.browserObjectName = info === null ? null : info.name\n\t\t},\n\n\t\t/**\n\t\t * Use OpenRegister's files API for the browser, when this person may read\n\t\t * the object's folder through it. A listing that fails (no read on the\n\t\t * object, or an OpenRegister without the folder endpoints) leaves the\n\t\t * legacy list, as an unresolved WebDAV folder did.\n\t\t *\n\t\t * @return {Promise<void>}\n\t\t * @spec openspec/changes/files-browser-openregister-source/specs/files-browser/spec.md\n\t\t */\n\t\tasync resolveOpenRegisterSource() {\n\t\t\tconst objectId = this.objectId\n\t\t\tconst source = createOpenRegisterSource({\n\t\t\t\tapiBase: this.apiBase,\n\t\t\t\tregister: this.register,\n\t\t\t\tschema: this.schema,\n\t\t\t\tobjectId,\n\t\t\t})\n\t\t\ttry {\n\t\t\t\tawait source.list('/')\n\t\t\t} catch {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif (objectId !== this.objectId) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.browserSource = source\n\t\t\tthis.browserRoot = '/'\n\t\t\tthis.fetchObjectName()\n\t\t},\n\n\t\t/**\n\t\t * Read the object's name for the root crumb, by the same rule the WebDAV\n\t\t * path uses (`objectDisplayName`: never the uuid). The OpenRegister path\n\t\t * has no folder lookup to piggyback on, so this is its one object read.\n\t\t * A failure keeps the crumb on its default.\n\t\t *\n\t\t * @return {Promise<void>}\n\t\t */\n\t\tasync fetchObjectName() {\n\t\t\tconst objectId = this.objectId\n\t\t\ttry {\n\t\t\t\tconst { data } = await axios.get(generateUrl(`${this.apiBase}/objects/{register}/{schema}/{objectId}`, {\n\t\t\t\t\tregister: this.register,\n\t\t\t\t\tschema: this.schema,\n\t\t\t\t\tobjectId,\n\t\t\t\t}))\n\t\t\t\tif (objectId === this.objectId) {\n\t\t\t\t\tthis.browserObjectName = objectDisplayName(data, objectId)\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\t// The crumb keeps its default.\n\t\t\t}\n\t\t},\n\n\t\tasync fetchFiles(append = false) {\n\t\t\tif (!this.register || !this.schema) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif (append) {\n\t\t\t\tthis.loadingMore = true\n\t\t\t} else {\n\t\t\t\tthis.loading = true\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tconst params = new URLSearchParams({ limit: this.limit, _page: this.page })\n\t\t\t\tconst response = await fetch(\n\t\t\t\t\tprefixUrl(`${this.apiBase}/objects/${this.register}/${this.schema}/${this.objectId}/files?${params}`),\n\t\t\t\t\t{ headers: buildHeaders() },\n\t\t\t\t)\n\t\t\t\tif (response.ok) {\n\t\t\t\t\tconst data = await response.json()\n\t\t\t\t\tconst results = data.results || data || []\n\t\t\t\t\tthis.files = append ? [...this.files, ...results] : results\n\t\t\t\t\tthis.total = data.total || this.files.length\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.error('CnFilesTab: Failed to fetch files', err)\n\t\t\t} finally {\n\t\t\t\tthis.loading = false\n\t\t\t\tthis.loadingMore = false\n\t\t\t}\n\t\t},\n\n\t\tloadMore() {\n\t\t\tthis.page++\n\t\t\tthis.fetchFiles(true)\n\t\t},\n\n\t\t/**\n\t\t * Seed the `share` toggle. The `defaultShare` prop wins when set\n\t\t * (non-null); otherwise we look up the active schema's\n\t\t * `configuration.defaultAutoShare` from OpenRegister and use that.\n\t\t * Network failure or missing key → keep the safe default (false) so\n\t\t * a hiccup never silently flips uploads to \"share\".\n\t\t *\n\t\t * @return {Promise<void>}\n\t\t */\n\t\tasync applyShareDefault() {\n\t\t\tif (this.defaultShare !== null && this.defaultShare !== undefined) {\n\t\t\t\tthis.share = !!this.defaultShare\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.share = false\n\t\t\tif (!this.schema) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tconst response = await fetch(\n\t\t\t\t\tprefixUrl(`${this.apiBase}/schemas/${this.schema}`),\n\t\t\t\t\t{ headers: buildHeaders() },\n\t\t\t\t)\n\t\t\t\tif (!response.ok) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tconst data = await response.json().catch(() => null)\n\t\t\t\tif (data?.configuration?.defaultAutoShare === true) {\n\t\t\t\t\tthis.share = true\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t\t// Non-fatal — keep the safe default, but surface the\n\t\t\t\t// failure so a missing toggle default isn't silent.\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.error('CnFilesTab: Failed to fetch schema default for share toggle', err)\n\t\t\t}\n\t\t},\n\n\t\ttriggerFileInput() {\n\t\t\tthis.fileInputEl?.click()\n\t\t},\n\n\t\tonDragOver() {\n\t\t\tthis.isDragOver = true\n\t\t},\n\n\t\tonDragLeave() {\n\t\t\tthis.isDragOver = false\n\t\t},\n\n\t\tonDrop(event) {\n\t\t\tthis.isDragOver = false\n\t\t\tconst droppedFiles = event.dataTransfer?.files\n\t\t\tif (droppedFiles?.length) {\n\t\t\t\tthis.uploadFiles(droppedFiles)\n\t\t\t}\n\t\t},\n\n\t\tasync onFileUpload(event) {\n\t\t\tconst inputFiles = event.target.files\n\t\t\tif (!inputFiles?.length) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tawait this.uploadFiles(inputFiles)\n\t\t\tif (this.fileInputEl) {\n\t\t\t\tthis.fileInputEl.value = ''\n\t\t\t}\n\t\t},\n\n\t\tasync uploadFiles(fileList) {\n\t\t\tif (!fileList?.length || !this.register || !this.schema) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.uploadError = ''\n\t\t\tconst formData = new FormData()\n\t\t\tfor (const file of fileList) {\n\t\t\t\tformData.append('files[]', file)\n\t\t\t}\n\t\t\t// Only forward the share flag when the toggle is actually visible.\n\t\t\t// Hiding the toggle (showShareToggle=false) means \"don't auto-publish\".\n\t\t\tif (this.showShareToggle) {\n\t\t\t\tformData.append('share', String(this.share))\n\t\t\t}\n\n\t\t\tthis.loading = true\n\t\t\ttry {\n\t\t\t\tconst response = await fetch(\n\t\t\t\t\tprefixUrl(`${this.apiBase}/objects/${this.register}/${this.schema}/${this.objectId}/filesMultipart`),\n\t\t\t\t\t{\n\t\t\t\t\t\tmethod: 'POST',\n\t\t\t\t\t\theaders: { requesttoken: OC?.requestToken || '', 'OCS-APIREQUEST': 'true' },\n\t\t\t\t\t\tbody: formData,\n\t\t\t\t\t},\n\t\t\t\t)\n\t\t\t\tif (!response.ok) {\n\t\t\t\t\tconst data = await response.json().catch(() => ({}))\n\t\t\t\t\tthis.uploadError = data.error || `Upload failed (${response.status})`\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tawait this.fetchFiles()\n\t\t\t} catch (err) {\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.error('CnFilesTab: Failed to upload file', err)\n\t\t\t\tthis.uploadError = 'Upload failed: could not connect to server'\n\t\t\t} finally {\n\t\t\t\tthis.loading = false\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Whether the Files app's details sidebar is on this page.\n\t\t *\n\t\t * It is when the host page dispatched Nextcloud's `LoadSidebar` event\n\t\t * server-side; then `OCA.Files.Sidebar.open(path)` shows the same\n\t\t * sharing, versions, comments and activity tabs the Files app shows.\n\t\t * Absent, the row offers no details action rather than a dead one. A\n\t\t * method rather than a computed: the global is not reactive, so a\n\t\t * cached answer from before the sidebar script ran would stay wrong.\n\t\t *\n\t\t * @return {boolean} true when the sidebar can be opened.\n\t\t */\n\t\tcanShowDetails() {\n\t\t\treturn typeof window !== 'undefined' && typeof window.OCA?.Files?.Sidebar?.open === 'function'\n\t\t},\n\n\t\t/**\n\t\t * The file's path relative to the user's files root, which is the path\n\t\t * the Viewer and the Files sidebar take. OpenRegister reports the node's\n\t\t * full path (`/{uid}/files/…`), so the first two segments come off.\n\t\t *\n\t\t * @param {string} path The node path as OpenRegister reports it.\n\t\t * @return {string} The user-relative path, `/` at least.\n\t\t */\n\t\tuserRelativePath(path) {\n\t\t\tconst stripped = String(path || '').replace(/^\\/[^/]+\\/files(?=\\/|$)/, '')\n\t\t\treturn stripped === '' ? '/' : stripped\n\t\t},\n\n\t\t/**\n\t\t * The theme's own icon for the file's mime type, the one the Files app\n\t\t * draws, or null on a page without Nextcloud's core script.\n\t\t *\n\t\t * @param {object} file The file row.\n\t\t * @return {string|null} The icon url.\n\t\t */\n\t\tmimeIconFor(file) {\n\t\t\tconst getIconUrl = typeof window !== 'undefined' ? window.OC?.MimeType?.getIconUrl : null\n\t\t\tif (typeof getIconUrl !== 'function') {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tconst mime = file.type || file.mimetype || file.mimeType || ''\n\t\t\ttry {\n\t\t\t\treturn getIconUrl(mime) || null\n\t\t\t} catch {\n\t\t\t\treturn null\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * A small preview for an image, through Nextcloud's core preview\n\t\t * endpoint, or null for anything else or after the preview failed once.\n\t\t *\n\t\t * @param {object} file The file row.\n\t\t * @return {string|null} The preview url.\n\t\t */\n\t\tpreviewUrlFor(file) {\n\t\t\tconst mime = file.type || file.mimetype || file.mimeType || ''\n\t\t\tif (!file.id || !/^image\\//i.test(mime) || /svg/i.test(mime) || this.previewFailed[file.id]) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\treturn generateUrl('/core/preview?fileId={fileId}&x=64&y=64&a=1', { fileId: file.id })\n\t\t},\n\n\t\t/**\n\t\t * Remember that a preview did not load, so the row shows the mime icon.\n\t\t *\n\t\t * @param {object} file The file row.\n\t\t * @return {void}\n\t\t */\n\t\tonPreviewError(file) {\n\t\t\tthis.previewFailed = { ...this.previewFailed, [file.id]: true }\n\t\t},\n\n\t\t/**\n\t\t * The file's modification moment as a Date, or null when unknown.\n\t\t *\n\t\t * @param {object} file The file row.\n\t\t * @return {Date|null} The moment.\n\t\t */\n\t\tmodifiedAt(file) {\n\t\t\tconst raw = file.modified || file.updated || ''\n\t\t\tif (!raw) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tconst date = new Date(raw)\n\t\t\treturn Number.isNaN(date.getTime()) ? null : date\n\t\t},\n\n\t\t/**\n\t\t * The file's labels (Nextcloud tags), joined for the meta line.\n\t\t *\n\t\t * @param {object} file The file row.\n\t\t * @return {string} The labels, or the empty string.\n\t\t */\n\t\tlabelsOf(file) {\n\t\t\treturn Array.isArray(file.labels) ? file.labels.filter(Boolean).join(', ') : ''\n\t\t},\n\n\t\t/**\n\t\t * The download url for a file, through OpenRegister's file endpoint,\n\t\t * which streams the node the object owns.\n\t\t *\n\t\t * @param {object} file The file row.\n\t\t * @return {string} The url.\n\t\t */\n\t\tdownloadUrlFor(file) {\n\t\t\treturn `${this.apiBase}/files/${encodeURIComponent(String(file.id))}/download`\n\t\t},\n\n\t\t/**\n\t\t * Whether Nextcloud Office opens this file for this person.\n\t\t *\n\t\t * @param {object} file The file row.\n\t\t * @return {boolean} true when the Office action applies.\n\t\t */\n\t\tofficeOpens(file) {\n\t\t\tconst mime = file.type || file.mimetype || file.mimeType || ''\n\t\t\treturn Boolean(file.id) && mime !== '' && this.officeMimetypes.includes(mime)\n\t\t},\n\n\t\t/**\n\t\t * OpenRegister's Office page for a file of this object, which checks the\n\t\t * object rule and opens the document editable or read-only.\n\t\t *\n\t\t * @param {object} file The file row.\n\t\t * @return {string} The url.\n\t\t */\n\t\tofficeUrlFor(file) {\n\t\t\tconst appBase = /\\/api\\/?$/.test(this.apiBase) ? this.apiBase.replace(/\\/api\\/?$/, '') : '/apps/openregister'\n\t\t\tconst segments = [this.register, this.schema, this.objectId, String(file.id)].map((part) => encodeURIComponent(String(part)))\n\t\t\treturn prefixUrl(`${appBase}/office/${segments.join('/')}`)\n\t\t},\n\n\t\t/**\n\t\t * The Files app's permalink for a file: opens the Files app at the\n\t\t * file's folder with the file selected.\n\t\t *\n\t\t * @param {object} file The file row.\n\t\t * @return {string} The url.\n\t\t */\n\t\tshowInFilesUrl(file) {\n\t\t\treturn generateUrl('/f/{fileid}', { fileid: file.id })\n\t\t},\n\n\t\t/**\n\t\t * Open the Files sidebar on this file: details, sharing, versions,\n\t\t * comments and activity, exactly as the Files app offers them.\n\t\t *\n\t\t * @param {object} file The file row.\n\t\t * @return {void}\n\t\t */\n\t\tshowDetails(file) {\n\t\t\tif (!this.canShowDetails() || !file.path) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\twindow.OCA.Files.Sidebar.open(this.userRelativePath(file.path))\n\t\t},\n\n\t\t/**\n\t\t * Put the file's permalink on the clipboard and say so.\n\t\t *\n\t\t * @param {object} file The file row.\n\t\t * @return {Promise<void>}\n\t\t */\n\t\tasync copyLink(file) {\n\t\t\tconst href = new URL(this.showInFilesUrl(file), window.location.origin).href\n\t\t\ttry {\n\t\t\t\tawait navigator.clipboard.writeText(href)\n\t\t\t\tconst { showSuccess } = await import('@nextcloud/dialogs')\n\t\t\t\tshowSuccess(t('nextcloud-vue', 'Link copied'))\n\t\t\t} catch {\n\t\t\t\tconst { showError } = await import('@nextcloud/dialogs')\n\t\t\t\tshowError(t('nextcloud-vue', 'The link could not be copied'))\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Show a file in the in-page preview.\n\t\t *\n\t\t * @param {object} file The file to preview.\n\t\t */\n\t\tshowPreview(file) {\n\t\t\tthis.previewFile = file\n\t\t},\n\n\t\t/**\n\t\t * Open a file through the shared opener (Viewer, preview, browser, Files).\n\t\t *\n\t\t * @param {object} file The file row.\n\t\t */\n\t\topenFile(file) {\n\t\t\tuseFileOpener({\n\t\t\t\tonPreview: this.showPreview,\n\t\t\t\tuserRelativePath: this.userRelativePath,\n\t\t\t\tanyAccessUrl: true,\n\t\t\t\tfilesAppUrl: (f) => {\n\t\t\t\t\tconst dirPath = f.path ? f.path.substring(0, f.path.lastIndexOf('/')) : ''\n\t\t\t\t\tconst cleanPath = dirPath.replace(/^\\/admin\\/files\\//, '/')\n\t\t\t\t\treturn `/index.php/apps/files/files/${f.id}?dir=${encodeURIComponent(cleanPath)}&openfile=true`\n\t\t\t\t},\n\t\t\t}).open(file)\n\t\t},\n\n\t\tasync deleteFile(file) {\n\t\t\tif (!this.register || !this.schema) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tawait fetch(\n\t\t\t\t\tprefixUrl(`${this.apiBase}/objects/${this.register}/${this.schema}/${this.objectId}/files/${file.id}`),\n\t\t\t\t\t{ method: 'DELETE', headers: buildHeaders() },\n\t\t\t\t)\n\t\t\t\tthis.files = this.files.filter((f) => f.id !== file.id)\n\t\t\t} catch (err) {\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.error('CnFilesTab: Failed to delete file', err)\n\t\t\t}\n\t\t},\n\n\t\tformatFileSize(bytes) {\n\t\t\tconst sizes = ['Bytes', 'KB', 'MB', 'GB']\n\t\t\tif (!bytes || bytes === 0) {\n\t\t\t\treturn 'n/a'\n\t\t\t}\n\t\t\tconst i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)))\n\t\t\tif (i === 0) {\n\t\t\t\treturn '< 1 KB'\n\t\t\t}\n\t\t\treturn (bytes / Math.pow(1024, i)).toFixed(1) + ' ' + sizes[i]\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n.cn-sidebar-tab { padding: 12px; }\n\n.cn-sidebar-tab__upload-error {\n\tpadding: 8px 12px;\n\tmargin-bottom: 8px;\n\tborder-radius: var(--border-radius, 4px);\n\tbackground-color: var(--color-error-light, rgba(229, 57, 53, 0.1));\n\tcolor: var(--color-error, #e53935);\n\tfont-size: 13px;\n}\n\n.cn-sidebar-tab__dropzone {\n\tdisplay: flex;\n\tflex-direction: column;\n\talign-items: center;\n\tjustify-content: center;\n\tgap: 8px;\n\tpadding: 20px 12px;\n\tmargin-bottom: 16px;\n\tborder: 2px dashed var(--color-border);\n\tborder-radius: var(--border-radius-large, 8px);\n\tcursor: pointer;\n\ttransition: border-color 0.15s ease, background-color 0.15s ease;\n}\n\n.cn-sidebar-tab__dropzone:hover {\n\tborder-color: var(--color-primary-element);\n\tbackground-color: var(--color-primary-element-light, rgba(0, 130, 201, 0.08));\n}\n\n.cn-sidebar-tab__dropzone--active {\n\tborder-color: var(--color-primary-element);\n\tbackground-color: var(--color-primary-element-light, rgba(0, 130, 201, 0.12));\n}\n\n.cn-sidebar-tab__share { margin-bottom: 12px; }\n\n.cn-sidebar-tab__dropzone-icon { color: var(--color-text-maxcontrast); }\n\n.cn-sidebar-tab__dropzone--active .cn-sidebar-tab__dropzone-icon,\n.cn-sidebar-tab__dropzone:hover .cn-sidebar-tab__dropzone-icon { color: var(--color-primary-element); }\n\n.cn-sidebar-tab__dropzone-text { font-size: 13px; color: var(--color-text-maxcontrast); }\n\n.cn-sidebar-tab__file-input { display: none; }\n\n.cn-sidebar-tab__empty {\n\ttext-align: center;\n\tpadding: 24px 12px;\n\tcolor: var(--color-text-maxcontrast);\n\tfont-size: 13px;\n}\n\n.cn-sidebar-tab__list { display: flex; flex-direction: column; gap: 2px; }\n\n.cn-sidebar-tab__mime,\n.cn-sidebar-tab__thumb {\n\twidth: 32px;\n\theight: 32px;\n\tdisplay: block;\n}\n\n.cn-sidebar-tab__thumb {\n\tobject-fit: cover;\n\tborder-radius: var(--border-radius, 4px);\n}\n\n.cn-sidebar-tab__meta { color: var(--color-text-maxcontrast); }\n\n.cn-sidebar-tab__load-more { margin-top: 8px; }\n</style>\n"],"names":["CnFilePreview","CnFilesBrowser","t","axios"],"mappings":"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"}
|
|
@@ -47,6 +47,8 @@ function render(_ctx, _cache, $props, $setup, $data, $options) {
|
|
|
47
47
|
deleteLabel: $props.deleteLabel,
|
|
48
48
|
uploadButton: $props.uploadButton,
|
|
49
49
|
dropOverlay: $props.dropOverlay,
|
|
50
|
+
dropLabel: $props.dropLabel,
|
|
51
|
+
dropDetail: $props.dropDetail,
|
|
50
52
|
dropHint: $props.dropHint,
|
|
51
53
|
rowActions: $props.rowActions,
|
|
52
54
|
newActions: $props.newActions,
|
|
@@ -68,7 +70,7 @@ function render(_ctx, _cache, $props, $setup, $data, $options) {
|
|
|
68
70
|
groupBy: $props.groupBy,
|
|
69
71
|
facets: $props.facets,
|
|
70
72
|
onChanged: $options.onBrowserChanged
|
|
71
|
-
}, null, 8 /* PROPS */, ["rootPath", "rootLabel", "source", "deleteLabel", "uploadButton", "dropOverlay", "dropHint", "rowActions", "newActions", "headerActions", "rowButton", "reviewSummary", "footnote", "nameSecondary", "linkedItems", "columns", "rowData", "preferenceApp", "preferenceKey", "bulkActions", "selectionLabel", "selectionLabelOne", "showClearSelection", "sideCards", "groupBy", "facets", "onChanged"]))
|
|
73
|
+
}, null, 8 /* PROPS */, ["rootPath", "rootLabel", "source", "deleteLabel", "uploadButton", "dropOverlay", "dropLabel", "dropDetail", "dropHint", "rowActions", "newActions", "headerActions", "rowButton", "reviewSummary", "footnote", "nameSecondary", "linkedItems", "columns", "rowData", "preferenceApp", "preferenceKey", "bulkActions", "selectionLabel", "selectionLabelOne", "showClearSelection", "sideCards", "groupBy", "facets", "onChanged"]))
|
|
72
74
|
: (openBlock(), createElementBlock(Fragment, { key: 1 }, [
|
|
73
75
|
($data.uploadError)
|
|
74
76
|
? (openBlock(), createElementBlock("div", _hoisted_2, toDisplayString($data.uploadError), 1 /* TEXT */))
|