@conduction/nextcloud-vue 2.119.0 → 2.120.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.
Files changed (126) hide show
  1. package/dist/esm/components/CnAiFeaturesWidget/CnAiFeaturesWidget.vue.js +9 -0
  2. package/dist/esm/components/CnAiFeaturesWidget/CnAiFeaturesWidget.vue.js.map +1 -0
  3. package/dist/esm/components/CnAiFeaturesWidget/CnAiFeaturesWidget.vue2.js +226 -0
  4. package/dist/esm/components/CnAiFeaturesWidget/CnAiFeaturesWidget.vue2.js.map +1 -0
  5. package/dist/esm/components/CnAiFeaturesWidget/CnAiFeaturesWidget.vue3.js +211 -0
  6. package/dist/esm/components/CnAiFeaturesWidget/CnAiFeaturesWidget.vue3.js.map +1 -0
  7. package/dist/esm/components/CnAiFeaturesWidget/CnAiSuggestionDecision.vue.js +9 -0
  8. package/dist/esm/components/CnAiFeaturesWidget/CnAiSuggestionDecision.vue.js.map +1 -0
  9. package/dist/esm/components/CnAiFeaturesWidget/CnAiSuggestionDecision.vue2.js +64 -0
  10. package/dist/esm/components/CnAiFeaturesWidget/CnAiSuggestionDecision.vue2.js.map +1 -0
  11. package/dist/esm/components/CnAiFeaturesWidget/CnAiSuggestionDecision.vue3.js +89 -0
  12. package/dist/esm/components/CnAiFeaturesWidget/CnAiSuggestionDecision.vue3.js.map +1 -0
  13. package/dist/esm/components/CnIcon/semanticIcons.js +2 -2
  14. package/dist/esm/components/CnIcon/semanticIcons.js.map +1 -1
  15. package/dist/esm/components/CnObjectPermissionsTab/CnObjectPermissionsTab.vue.js +9 -0
  16. package/dist/esm/components/CnObjectPermissionsTab/CnObjectPermissionsTab.vue.js.map +1 -0
  17. package/dist/esm/components/CnObjectPermissionsTab/CnObjectPermissionsTab.vue2.js +257 -0
  18. package/dist/esm/components/CnObjectPermissionsTab/CnObjectPermissionsTab.vue2.js.map +1 -0
  19. package/dist/esm/components/CnObjectPermissionsTab/CnObjectPermissionsTab.vue3.js +266 -0
  20. package/dist/esm/components/CnObjectPermissionsTab/CnObjectPermissionsTab.vue3.js.map +1 -0
  21. package/dist/esm/components/CnObjectSidebar/CnObjectSidebar.vue.js +1 -1
  22. package/dist/esm/components/CnObjectSidebar/CnObjectSidebar.vue2.js +14 -7
  23. package/dist/esm/components/CnObjectSidebar/CnObjectSidebar.vue2.js.map +1 -1
  24. package/dist/esm/components/CnObjectSidebar/CnObjectSidebar.vue3.js.map +1 -1
  25. package/dist/esm/components/CnObjectTranslationsWidget/CnObjectTranslationsWidget.vue.js +9 -0
  26. package/dist/esm/components/CnObjectTranslationsWidget/CnObjectTranslationsWidget.vue.js.map +1 -0
  27. package/dist/esm/components/CnObjectTranslationsWidget/CnObjectTranslationsWidget.vue2.js +278 -0
  28. package/dist/esm/components/CnObjectTranslationsWidget/CnObjectTranslationsWidget.vue2.js.map +1 -0
  29. package/dist/esm/components/CnObjectTranslationsWidget/CnObjectTranslationsWidget.vue3.js +128 -0
  30. package/dist/esm/components/CnObjectTranslationsWidget/CnObjectTranslationsWidget.vue3.js.map +1 -0
  31. package/dist/esm/components/CnStateMachineEditor/CnStateMachineEditor.vue.js +10 -0
  32. package/dist/esm/components/CnStateMachineEditor/CnStateMachineEditor.vue.js.map +1 -0
  33. package/dist/esm/components/CnStateMachineEditor/CnStateMachineEditor.vue2.js +944 -0
  34. package/dist/esm/components/CnStateMachineEditor/CnStateMachineEditor.vue2.js.map +1 -0
  35. package/dist/esm/components/CnStateMachineEditor/CnStateMachineEditor.vue3.js +276 -0
  36. package/dist/esm/components/CnStateMachineEditor/CnStateMachineEditor.vue3.js.map +1 -0
  37. package/dist/esm/components/CnStateMachineEditor/CnStateMachineFields.vue.js +9 -0
  38. package/dist/esm/components/CnStateMachineEditor/CnStateMachineFields.vue.js.map +1 -0
  39. package/dist/esm/components/CnStateMachineEditor/CnStateMachineFields.vue2.js +354 -0
  40. package/dist/esm/components/CnStateMachineEditor/CnStateMachineFields.vue2.js.map +1 -0
  41. package/dist/esm/components/CnStateMachineEditor/CnStateMachineFields.vue3.js +392 -0
  42. package/dist/esm/components/CnStateMachineEditor/CnStateMachineFields.vue3.js.map +1 -0
  43. package/dist/esm/components/CnStateMachineEditor/CnStateMachineNode.vue.js +9 -0
  44. package/dist/esm/components/CnStateMachineEditor/CnStateMachineNode.vue.js.map +1 -0
  45. package/dist/esm/components/CnStateMachineEditor/CnStateMachineNode.vue2.js +180 -0
  46. package/dist/esm/components/CnStateMachineEditor/CnStateMachineNode.vue2.js.map +1 -0
  47. package/dist/esm/components/CnStateMachineEditor/CnStateMachineNode.vue3.js +208 -0
  48. package/dist/esm/components/CnStateMachineEditor/CnStateMachineNode.vue3.js.map +1 -0
  49. package/dist/esm/components/CnStateMachineEditor/CnStateMachinePanel.vue.js +9 -0
  50. package/dist/esm/components/CnStateMachineEditor/CnStateMachinePanel.vue.js.map +1 -0
  51. package/dist/esm/components/CnStateMachineEditor/CnStateMachinePanel.vue2.js +244 -0
  52. package/dist/esm/components/CnStateMachineEditor/CnStateMachinePanel.vue2.js.map +1 -0
  53. package/dist/esm/components/CnStateMachineEditor/CnStateMachinePanel.vue3.js +76 -0
  54. package/dist/esm/components/CnStateMachineEditor/CnStateMachinePanel.vue3.js.map +1 -0
  55. package/dist/esm/components/CnStateMachineEditor/stateMachineFields.js +290 -0
  56. package/dist/esm/components/CnStateMachineEditor/stateMachineFields.js.map +1 -0
  57. package/dist/esm/components/CnTimelineWidget/CnTimelineManage.vue.js +9 -0
  58. package/dist/esm/components/CnTimelineWidget/CnTimelineManage.vue.js.map +1 -0
  59. package/dist/esm/components/CnTimelineWidget/CnTimelineManage.vue2.js +448 -0
  60. package/dist/esm/components/CnTimelineWidget/CnTimelineManage.vue2.js.map +1 -0
  61. package/dist/esm/components/CnTimelineWidget/CnTimelineManage.vue3.js +303 -0
  62. package/dist/esm/components/CnTimelineWidget/CnTimelineManage.vue3.js.map +1 -0
  63. package/dist/esm/components/CnTimelineWidget/CnTimelineWidget.vue.js +1 -1
  64. package/dist/esm/components/CnTimelineWidget/CnTimelineWidget.vue2.js +19 -2
  65. package/dist/esm/components/CnTimelineWidget/CnTimelineWidget.vue2.js.map +1 -1
  66. package/dist/esm/components/CnTimelineWidget/CnTimelineWidget.vue3.js +73 -62
  67. package/dist/esm/components/CnTimelineWidget/CnTimelineWidget.vue3.js.map +1 -1
  68. package/dist/esm/components/CnWidgetGrid/builtInWidgets.js +6 -0
  69. package/dist/esm/components/CnWidgetGrid/builtInWidgets.js.map +1 -1
  70. package/dist/esm/index.js +5 -0
  71. package/dist/esm/index.js.map +1 -1
  72. package/dist/esm/l10n/en.json.js +166 -1
  73. package/dist/esm/l10n/en.json.js.map +1 -1
  74. package/dist/esm/l10n/nl.json.js +166 -1
  75. package/dist/esm/l10n/nl.json.js.map +1 -1
  76. package/dist/esm/library-style.js +1 -1
  77. package/dist/esm/nextcloud-vue.css +889 -101
  78. package/dist/esm/utils/aiFeatures.js +245 -0
  79. package/dist/esm/utils/aiFeatures.js.map +1 -0
  80. package/dist/esm/utils/aiSuggestionTracker.js +182 -0
  81. package/dist/esm/utils/aiSuggestionTracker.js.map +1 -0
  82. package/dist/esm/utils/libraryWidgetKeys.js +1 -0
  83. package/dist/esm/utils/libraryWidgetKeys.js.map +1 -1
  84. package/dist/esm/utils/objectPermissions.js +552 -0
  85. package/dist/esm/utils/objectPermissions.js.map +1 -0
  86. package/dist/esm/utils/objectTranslations.js +180 -0
  87. package/dist/esm/utils/objectTranslations.js.map +1 -0
  88. package/dist/esm/utils/stateMachineValidation.js +254 -0
  89. package/dist/esm/utils/stateMachineValidation.js.map +1 -0
  90. package/dist/esm/utils/widgetDispatch.js +3 -1
  91. package/dist/esm/utils/widgetDispatch.js.map +1 -1
  92. package/dist/nextcloud-vue.cjs.js +20052 -13138
  93. package/dist/nextcloud-vue.cjs.js.map +2 -2
  94. package/dist/nextcloud-vue.css +889 -101
  95. package/l10n/en.json +166 -1
  96. package/l10n/nl.json +166 -1
  97. package/package.json +1 -1
  98. package/src/components/CnAiFeaturesWidget/CnAiFeaturesWidget.vue +416 -0
  99. package/src/components/CnAiFeaturesWidget/CnAiSuggestionDecision.vue +136 -0
  100. package/src/components/CnAiFeaturesWidget/__tests__/CnAiFeaturesWidget.spec.js +213 -0
  101. package/src/components/CnAiFeaturesWidget/index.js +14 -0
  102. package/src/components/CnObjectPermissionsTab/CnObjectPermissionsTab.vue +499 -0
  103. package/src/components/CnObjectPermissionsTab/__tests__/CnObjectPermissionsTab.spec.js +186 -0
  104. package/src/components/CnObjectPermissionsTab/index.js +13 -0
  105. package/src/components/CnObjectSidebar/CnObjectSidebar.vue +8 -1
  106. package/src/components/CnObjectTranslationsWidget/CnObjectTranslationsWidget.vue +424 -0
  107. package/src/components/CnObjectTranslationsWidget/__tests__/CnObjectTranslationsWidget.spec.js +189 -0
  108. package/src/components/CnObjectTranslationsWidget/index.js +13 -0
  109. package/src/components/CnStateMachineEditor/CnStateMachineEditor.vue +1332 -0
  110. package/src/components/CnStateMachineEditor/CnStateMachineFields.vue +791 -0
  111. package/src/components/CnStateMachineEditor/CnStateMachineNode.vue +442 -0
  112. package/src/components/CnStateMachineEditor/CnStateMachinePanel.vue +326 -0
  113. package/src/components/CnStateMachineEditor/index.js +8 -0
  114. package/src/components/CnStateMachineEditor/stateMachineFields.js +287 -0
  115. package/src/components/CnTimelineWidget/CnTimelineManage.vue +827 -0
  116. package/src/components/CnTimelineWidget/CnTimelineWidget.vue +29 -3
  117. package/src/components/CnWidgetGrid/builtInWidgets.js +6 -0
  118. package/src/components/index.js +4 -0
  119. package/src/index.js +5 -0
  120. package/src/utils/aiFeatures.js +241 -0
  121. package/src/utils/aiSuggestionTracker.js +178 -0
  122. package/src/utils/libraryWidgetKeys.js +1 -0
  123. package/src/utils/objectPermissions.js +548 -0
  124. package/src/utils/objectTranslations.js +176 -0
  125. package/src/utils/stateMachineValidation.js +250 -0
  126. package/src/utils/widgetDispatch.js +3 -1
@@ -1 +1 @@
1
- {"version":3,"file":"CnObjectSidebar.vue2.js","sources":["../../../../src/components/CnObjectSidebar/CnObjectSidebar.vue"],"sourcesContent":["<!--\n CnObjectSidebar — Right sidebar with standardized tabs for generic object functionality.\n\n Provides Files, Notes, Tags, Tasks, and Audit Trail tabs that integrate with\n OpenRegister API endpoints (which bridge to Nextcloud-native APIs).\n All tabs are optional and overridable via props and slots.\n-->\n<template>\n\t<!-- `subname` is NcAppSidebar's visible secondary line; `subtitle` is only\n\t the tooltip on it, and the line is not rendered at all while subname is\n\t empty — so passing subtitle alone showed nothing. Same pair as\n\t name/title, and as CnIndexSidebar. -->\n\t<NcAppSidebar\n\t\tv-model:active=\"activeTab\"\n\t\t:name=\"sidebarTitle\"\n\t\t:title=\"sidebarTitle\"\n\t\t:subname=\"sidebarSubtitle\"\n\t\t:subtitle=\"sidebarSubtitle\"\n\t\t:open=\"open\"\n\t\tdata-testid=\"cn-object-sidebar\"\n\t\t@update:open=\"$emit('update:open', $event)\"\n\t\t@close=\"$emit('update:open', false)\">\n\t\t<!-- REGISTRY BRANCH: pluggable integration registry-driven.\n\t\t Renders one tab per provider registered on\n\t\t `window.OCA.OpenRegister.integrations`. `hiddenTabs` /\n\t\t `excludeIntegrations` filter the set; the `#extra-tabs`\n\t\t slot still appends consumer-supplied tabs. Per-integration\n\t\t slot overrides aren't supported in registry mode — apps\n\t\t that need to override a built-in tab should register their\n\t\t own provider with the same id (collision policy: first\n\t\t wins) before OpenRegister's bundle loads. -->\n\t\t<template v-if=\"isRegistryMode\">\n\t\t\t<NcAppSidebarTab\n\t\t\t\tv-for=\"(provider, idx) in filteredRegistryIntegrations\"\n\t\t\t\t:id=\"provider.id\"\n\t\t\t\t:key=\"provider.id\"\n\t\t\t\t:name=\"provider.label\"\n\t\t\t\t:order=\"provider.order != null ? provider.order : idx + 1\"\n\t\t\t\t:data-testid=\"`cn-object-sidebar-tab-${provider.id}`\">\n\t\t\t\t<template #icon>\n\t\t\t\t\t<CnIcon v-if=\"provider.icon\" :name=\"provider.icon\" :size=\"20\" />\n\t\t\t\t</template>\n\t\t\t\t<!-- MOUNT BRANCH (openregister#2127): a `renderMode: 'mount'`\n\t\t\t\t leaf renders through CnLeafMountHost — a bare host-owned\n\t\t\t\t element the leaf mounts its own framework into. Mounted\n\t\t\t\t lazily when the tab is active; unmounted on hide/teardown. -->\n\t\t\t\t<CnLeafMountHost\n\t\t\t\t\tv-if=\"isMountProvider(provider)\"\n\t\t\t\t\t:provider=\"provider\"\n\t\t\t\t\t:active=\"activeTab === provider.id\"\n\t\t\t\t\t:mountProps=\"sidebarMountProps\" />\n\t\t\t\t<component\n\t\t\t\t\t:is=\"resolveRegistryTab(provider)\"\n\t\t\t\t\tv-else\n\t\t\t\t\tv-bind=\"sharedTabProps\" />\n\t\t\t</NcAppSidebarTab>\n\t\t\t<slot name=\"extra-tabs\" />\n\t\t</template>\n\n\t\t<!-- BACKWARDS-COMPATIBLE BRANCH: hard-coded built-in tabs.\n\t\t Used when no custom `tabs` prop is provided and the\n\t\t registry mode is not active. The slot overrides\n\t\t (#tab-files etc.) and `hiddenTabs` filtering remain\n\t\t unchanged. -->\n\t\t<template v-else-if=\"!hasCustomTabs\">\n\t\t\t<!-- Files Tab -->\n\t\t\t<NcAppSidebarTab\n\t\t\t\tv-if=\"!isTabHidden('files')\"\n\t\t\t\tid=\"files\"\n\t\t\t\t:name=\"filesLabel\"\n\t\t\t\t:order=\"1\"\n\t\t\t\tdata-testid=\"cn-object-sidebar-tab-files\">\n\t\t\t\t<template #icon>\n\t\t\t\t\t<Paperclip :size=\"20\" />\n\t\t\t\t</template>\n\t\t\t\t<slot name=\"tab-files\" :objectId=\"objectId\" :objectType=\"objectType\">\n\t\t\t\t\t<CnFilesTab\n\t\t\t\t\t\t:objectId=\"objectId\"\n\t\t\t\t\t\t:register=\"register\"\n\t\t\t\t\t\t:schema=\"schema\"\n\t\t\t\t\t\t:apiBase=\"apiBase\" />\n\t\t\t\t</slot>\n\t\t\t</NcAppSidebarTab>\n\n\t\t\t<!-- Notes Tab -->\n\t\t\t<NcAppSidebarTab\n\t\t\t\tv-if=\"!isTabHidden('notes')\"\n\t\t\t\tid=\"notes\"\n\t\t\t\t:name=\"notesLabel\"\n\t\t\t\t:order=\"2\"\n\t\t\t\tdata-testid=\"cn-object-sidebar-tab-notes\">\n\t\t\t\t<template #icon>\n\t\t\t\t\t<CommentTextOutline :size=\"20\" />\n\t\t\t\t</template>\n\t\t\t\t<slot name=\"tab-notes\" :objectId=\"objectId\" :objectType=\"objectType\">\n\t\t\t\t\t<!-- The `mention` passthrough is the notification hook: apps\n\t\t\t\t\t mounting the full sidebar receive the mentioned user ids\n\t\t\t\t\t and dispatch NC notifications from their own backend. -->\n\t\t\t\t\t<CnNotesTab\n\t\t\t\t\t\t:objectId=\"objectId\"\n\t\t\t\t\t\t:register=\"register\"\n\t\t\t\t\t\t:schema=\"schema\"\n\t\t\t\t\t\t:apiBase=\"apiBase\"\n\t\t\t\t\t\t@mention=\"$emit('mention', $event)\" />\n\t\t\t\t</slot>\n\t\t\t</NcAppSidebarTab>\n\n\t\t\t<!-- Tags Tab -->\n\t\t\t<NcAppSidebarTab\n\t\t\t\tv-if=\"!isTabHidden('tags')\"\n\t\t\t\tid=\"tags\"\n\t\t\t\t:name=\"tagsLabel\"\n\t\t\t\t:order=\"3\"\n\t\t\t\tdata-testid=\"cn-object-sidebar-tab-tags\">\n\t\t\t\t<template #icon>\n\t\t\t\t\t<TagOutline :size=\"20\" />\n\t\t\t\t</template>\n\t\t\t\t<slot name=\"tab-tags\" :objectId=\"objectId\" :objectType=\"objectType\">\n\t\t\t\t\t<CnTagsTab\n\t\t\t\t\t\t:objectId=\"objectId\"\n\t\t\t\t\t\t:register=\"register\"\n\t\t\t\t\t\t:schema=\"schema\"\n\t\t\t\t\t\t:apiBase=\"apiBase\" />\n\t\t\t\t</slot>\n\t\t\t</NcAppSidebarTab>\n\n\t\t\t<!-- Tasks Tab -->\n\t\t\t<NcAppSidebarTab\n\t\t\t\tv-if=\"!isTabHidden('tasks')\"\n\t\t\t\tid=\"tasks\"\n\t\t\t\t:name=\"tasksLabel\"\n\t\t\t\t:order=\"4\"\n\t\t\t\tdata-testid=\"cn-object-sidebar-tab-tasks\">\n\t\t\t\t<template #icon>\n\t\t\t\t\t<CheckboxMarkedOutline :size=\"20\" />\n\t\t\t\t</template>\n\t\t\t\t<slot name=\"tab-tasks\" :objectId=\"objectId\" :objectType=\"objectType\">\n\t\t\t\t\t<CnTasksTab\n\t\t\t\t\t\t:objectId=\"objectId\"\n\t\t\t\t\t\t:register=\"register\"\n\t\t\t\t\t\t:schema=\"schema\"\n\t\t\t\t\t\t:apiBase=\"apiBase\"\n\t\t\t\t\t\t:source=\"tasksSource\" />\n\t\t\t\t</slot>\n\t\t\t</NcAppSidebarTab>\n\n\t\t\t<!-- Audit Trail Tab -->\n\t\t\t<NcAppSidebarTab\n\t\t\t\tv-if=\"!isTabHidden('auditTrail')\"\n\t\t\t\tid=\"auditTrail\"\n\t\t\t\t:name=\"auditTrailLabel\"\n\t\t\t\t:order=\"5\"\n\t\t\t\tdata-testid=\"cn-object-sidebar-tab-audit-trail\">\n\t\t\t\t<template #icon>\n\t\t\t\t\t<History :size=\"20\" />\n\t\t\t\t</template>\n\t\t\t\t<slot name=\"tab-audit-trail\" :objectId=\"objectId\" :objectType=\"objectType\">\n\t\t\t\t\t<CnAuditTrailTab\n\t\t\t\t\t\t:objectId=\"objectId\"\n\t\t\t\t\t\t:register=\"register\"\n\t\t\t\t\t\t:schema=\"schema\"\n\t\t\t\t\t\t:apiBase=\"apiBase\" />\n\t\t\t\t</slot>\n\t\t\t</NcAppSidebarTab>\n\n\t\t\t<!-- Custom tabs slot (only relevant in legacy mode) -->\n\t\t\t<slot name=\"extra-tabs\" />\n\t\t</template>\n\n\t\t<!-- OPEN-ENUM BRANCH: render the consumer-supplied `tabs` array.\n\t\t Each tab declares its content via `widgets` (resolved against\n\t\t the built-in widget registry — `data` → CnObjectDataWidget,\n\t\t `metadata` → CnObjectMetadataWidget, `audit`/`audit-trail` →\n\t\t CnAuditTrailTab, `object-table` → CnWidgetObjectTable — with the\n\t\t customComponents registry as the escape hatch) OR `component`\n\t\t (resolved against the customComponents registry directly). -->\n\t\t<template v-else>\n\t\t\t<NcAppSidebarTab\n\t\t\t\tv-for=\"(tab, idx) in tabs\"\n\t\t\t\t:id=\"tab.id\"\n\t\t\t\t:key=\"tab.id\"\n\t\t\t\t:name=\"shown(tab.label)\"\n\t\t\t\t:lang=\"langOf(tab.label)\"\n\t\t\t\t:order=\"tab.order != null ? tab.order : idx + 1\"\n\t\t\t\t:data-testid=\"`cn-object-sidebar-tab-${tab.id}`\">\n\t\t\t\t<template v-if=\"tab.icon\" #icon>\n\t\t\t\t\t<CnIcon :name=\"tab.icon\" :size=\"20\" />\n\t\t\t\t</template>\n\n\t\t\t\t<!-- Component-registry escape hatch wins when `component` is set\n\t\t\t\t (with a console.warn at mount time when widgets is also set). -->\n\t\t\t\t<component\n\t\t\t\t\t:is=\"resolveTabComponent(tab)\"\n\t\t\t\t\tv-if=\"tab.component\"\n\t\t\t\t\tv-bind=\"sharedTabProps\" />\n\n\t\t\t\t<!-- Widget array path. Each widget receives the shared object\n\t\t\t\t context plus its own `props` via `widgetBindings` (which also\n\t\t\t\t hands the prop-driven `data` / `metadata` built-ins the loaded\n\t\t\t\t object and schema); per-widget props win on overlap. -->\n\t\t\t\t<div v-else class=\"cn-object-sidebar__tab-widgets\">\n\t\t\t\t\t<template v-for=\"(w, wIdx) in tab.widgets || []\">\n\t\t\t\t\t\t<component\n\t\t\t\t\t\t\t:is=\"resolveWidgetComponent(w.type)\"\n\t\t\t\t\t\t\tv-if=\"resolveWidgetComponent(w.type)\"\n\t\t\t\t\t\t\t:key=\"wIdx\"\n\t\t\t\t\t\t\tv-bind=\"widgetBindings(w)\" />\n\t\t\t\t\t</template>\n\t\t\t\t</div>\n\t\t\t</NcAppSidebarTab>\n\t\t</template>\n\t</NcAppSidebar>\n</template>\n\n<script>\nimport { translate as t } from '@nextcloud/l10n'\nimport { NcAppSidebar, NcAppSidebarTab } from '@nextcloud/vue'\nimport { inject, provide, ref, watch } from 'vue'\nimport CheckboxMarkedOutline from 'vue-material-design-icons/CheckboxMarkedOutline.vue'\nimport CommentTextOutline from 'vue-material-design-icons/CommentTextOutline.vue'\nimport History from 'vue-material-design-icons/History.vue'\nimport Paperclip from 'vue-material-design-icons/Paperclip.vue'\nimport TagOutline from 'vue-material-design-icons/TagOutline.vue'\nimport CnWidgetObjectTable from '../CnWidgetObjectTable/CnWidgetObjectTable.vue'\nimport CnAuditTrailTab from './CnAuditTrailTab.vue'\nimport CnFilesTab from './CnFilesTab.vue'\nimport CnNotesTab from './CnNotesTab.vue'\nimport CnTagsTab from './CnTagsTab.vue'\nimport CnTasksTab from './CnTasksTab.vue'\nimport { useIntegrationRegistry } from '../../composables/useIntegrationRegistry.js'\nimport { useObjectSubscription } from '../../composables/useObjectSubscription.js'\nimport { pickDeclaredProps } from '../../utils/declaredProps.js'\nimport { labelLang } from '../../utils/manifestTranslate.js'\nimport { CnIcon } from '../CnIcon/index.js'\nimport { CnLeafMountHost } from '../CnLeafMountHost/index.js'\nimport { CnObjectDataWidget } from '../CnObjectDataWidget/index.js'\nimport { CnObjectMetadataWidget } from '../CnObjectMetadataWidget/index.js'\n\n/**\n * Built-in widget registry used by the open-enum `tabs` prop.\n * - `data` → CnObjectDataWidget (schema-driven editable grid)\n * - `metadata` → CnObjectMetadataWidget (read-only system metadata)\n * - `audit` → CnAuditTrailTab (the object's change log / audit trail)\n * - `object-table` → CnWidgetObjectTable (a declarative list scoped to the\n * parent object — the full source / endpointSource / columns / actions\n * contract). Resolves `@objectId` / `@object.<field>` filter tokens against\n * the object context this sidebar `provide`s (see setup), so a detail\n * page's ZGW-style relation tab (e.g. a zaak's besluiten, filtered by\n * `{ zaak: \"@objectId\" }`) renders as a sidebar tab with no bespoke code.\n *\n * Any `widgets[].type` value not in this map falls back to the\n * customComponents registry (prop, then injected `cnCustomComponents`).\n */\nconst BUILTIN_WIDGETS = {\n\tdata: CnObjectDataWidget,\n\tmetadata: CnObjectMetadataWidget,\n\taudit: CnAuditTrailTab,\n\t// Alias matching the dashboard/detail-page widget key `audit-trail` so a\n\t// manifest can declare a sidebar tab with `widgets: [{ type: 'audit-trail' }]`\n\t// (the same key it uses for the detail-page body widget) and get the object's\n\t// change log as a proper sidebar tab.\n\t'audit-trail': CnAuditTrailTab,\n\t// The declarative list widget (same key as the detail-page body widget), so\n\t// a sidebar tab can render a related-object list scoped to the parent\n\t// object via `@objectId` / `@object.<field>` tokens in its `source.filter`.\n\t'object-table': CnWidgetObjectTable,\n}\n\n/**\n * CnObjectSidebar — Right sidebar for entity detail pages.\n *\n * Provides standardized tabs for generic object functionality (Files, Notes, Tags,\n * Tasks, Audit Trail) that integrate with OpenRegister API endpoints bridging to\n * Nextcloud-native APIs. Each tab is a self-contained component.\n *\n * Basic usage\n * ```vue\n * <CnObjectSidebar\n * object-type=\"pipelinq_lead\"\n * :object-id=\"leadId\"\n * :register=\"registerConfig.register\"\n * :schema=\"registerConfig.schema\" />\n * ```\n *\n * Hide specific tabs\n * ```vue\n * <CnObjectSidebar\n * object-type=\"pipelinq_lead\"\n * :object-id=\"leadId\"\n * :hidden-tabs=\"['tasks', 'tags']\" />\n * ```\n *\n * Override a tab\n * ```vue\n * <CnObjectSidebar object-type=\"pipelinq_lead\" :object-id=\"leadId\">\n * <template #tab-notes=\"{ objectId }\">\n * <MyCustomNotesComponent :id=\"objectId\" />\n * </template>\n * </CnObjectSidebar>\n * ```\n */\nexport default {\n\tname: 'CnObjectSidebar',\n\n\tcomponents: {\n\t\tNcAppSidebar,\n\t\tNcAppSidebarTab,\n\t\tPaperclip,\n\t\tCommentTextOutline,\n\t\tTagOutline,\n\t\tCheckboxMarkedOutline,\n\t\tHistory,\n\t\tCnFilesTab,\n\t\tCnNotesTab,\n\t\tCnTagsTab,\n\t\tCnTasksTab,\n\t\tCnAuditTrailTab,\n\t\tCnIcon,\n\t\tCnLeafMountHost,\n\t},\n\n\tinject: {\n\t\tcnCustomComponents: { default: () => ({}) },\n\t\t// v2 component registry (ADR-036). Kind-tagged entries\n\t\t// ({ kind, component }); a sidebar tab's `component` ref resolves\n\t\t// against this first so apps that migrated their tab components to\n\t\t// the registry (e.g. as `kind: 'page'`) still render. Empty default\n\t\t// keeps the legacy `customComponents`-only path unchanged.\n\t\tcnRegistry: { default: () => ({}) },\n\t\t// The label lookup from CnAppRoot, so tab labels and the title show in the user's language.\n\t\tcnTranslate: { default: null },\n\t},\n\n\tprops: {\n\t\t/** The entity type (e.g., \"pipelinq_lead\", \"procest_case\") */\n\t\tobjectType: {\n\t\t\ttype: String,\n\t\t\trequired: true,\n\t\t},\n\n\t\t/** The object UUID */\n\t\tobjectId: {\n\t\t\ttype: String,\n\t\t\trequired: true,\n\t\t},\n\n\t\t/** OpenRegister register ID */\n\t\tregister: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/** OpenRegister schema ID */\n\t\tschema: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/**\n\t\t * The loaded object, forwarded to prop-driven sidebar-tab widgets\n\t\t * (the `data` / `metadata` built-ins) as `objectData`. The sidebar is\n\t\t * otherwise coordinate-based — most tabs self-fetch from\n\t\t * `objectId`/`register`/`schema` — so this is null unless a host (e.g.\n\t\t * CnDetailPage via CnAppRoot) publishes the loaded object.\n\t\t *\n\t\t * @type {object|null}\n\t\t */\n\t\tobjectData: {\n\t\t\ttype: Object,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/**\n\t\t * The resolved JSON Schema OBJECT (with a `properties` field), forwarded\n\t\t * to the `data` built-in tab widget (CnObjectDataWidget), which needs the\n\t\t * schema definition rather than the `schema` slug string. Null unless a\n\t\t * host (e.g. CnDetailPage via CnAppRoot) publishes it.\n\t\t *\n\t\t * @type {object|null}\n\t\t */\n\t\tobjectSchema: {\n\t\t\ttype: Object,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/** Array of tab IDs to hide: 'files', 'notes', 'tags', 'tasks', 'auditTrail' */\n\t\thiddenTabs: {\n\t\t\ttype: Array,\n\t\t\tdefault: () => [],\n\t\t},\n\n\t\t/**\n\t\t * Use the pluggable integration registry to drive the sidebar\n\t\t * tabs. Defaults to `true` (ADR-019): tabs are rendered one per\n\t\t * provider registered on `window.OCA.OpenRegister.integrations`\n\t\t * (and via `useIntegrationRegistry()`). The canonical five\n\t\t * built-ins — files / notes / tags / tasks / audit-trail — are\n\t\t * shipped as providers in `builtinIntegrations` and registered by\n\t\t * OpenRegister's bootstrap (`registerBuiltinIntegrations()`), so\n\t\t * the default surface is unchanged for apps that register them.\n\t\t *\n\t\t * Set `false` to opt back into the legacy hardcoded-tabs path,\n\t\t * which renders the five built-in tabs directly from this\n\t\t * component and supports the `#tab-<id>` slot overrides. Use this\n\t\t * for consumers that do not call `registerBuiltinIntegrations()`\n\t\t * and want the built-in tabs without standing up the registry.\n\t\t *\n\t\t * `hiddenTabs` / `excludeIntegrations` and the `#extra-tabs` slot\n\t\t * apply in both modes.\n\t\t *\n\t\t * Mutually exclusive with the open-enum `tabs` prop — when both\n\t\t * are set, `tabs` wins and a console.warn is logged.\n\t\t *\n\t\t * @type {boolean}\n\t\t */\n\t\tuseRegistry: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: true,\n\t\t},\n\n\t\t/**\n\t\t * Integration ids to exclude when rendering registry-driven\n\t\t * tabs. Mirrors `hiddenTabs` for the legacy mode.\n\t\t *\n\t\t * @type {string[]}\n\t\t */\n\t\texcludeIntegrations: {\n\t\t\ttype: Array,\n\t\t\tdefault: () => [],\n\t\t},\n\n\t\t/** Whether the sidebar is open */\n\t\topen: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: true,\n\t\t},\n\n\t\t/** Sidebar title (defaults to objectType) */\n\t\ttitle: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/** Sidebar subtitle */\n\t\tsubtitle: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/** @deprecated Use `subtitle` instead. Alias kept for backwards compatibility. */\n\t\tsubtitleProp: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/** Base API URL for OpenRegister */\n\t\tapiBase: {\n\t\t\ttype: String,\n\t\t\tdefault: '/apps/openregister/api',\n\t\t},\n\n\t\t/**\n\t\t * Whether to auto-subscribe to live updates for the\n\t\t * current object. Defaults to true. The sidebar calls\n\t\t * `objectStore.subscribe(objectType, objectId)` on mount and\n\t\t * unsubscribes on unmount via `tryOnScopeDispose`.\n\t\t *\n\t\t * @type {boolean}\n\t\t */\n\t\tsubscribe: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: true,\n\t\t},\n\n\t\t/**\n\t\t * Optional explicit Pinia store instance. When omitted,\n\t\t * the sidebar skips auto-subscribe (Pinia not yet active\n\t\t * in the consumer context).\n\t\t *\n\t\t * @type {object|null}\n\t\t */\n\t\tobjectStore: {\n\t\t\ttype: Object,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t// --- Pre-translated labels ---\n\t\t/** Label for the Files tab */\n\t\tfilesLabel: { type: String, default: () => t('nextcloud-vue', 'Files') },\n\t\t/** Label for the Notes tab */\n\t\tnotesLabel: { type: String, default: () => t('nextcloud-vue', 'Notes') },\n\t\t/** Label for the Tags tab */\n\t\ttagsLabel: { type: String, default: () => t('nextcloud-vue', 'Tags') },\n\t\t/** Label for the Tasks tab */\n\t\ttasksLabel: { type: String, default: () => t('nextcloud-vue', 'Tasks') },\n\t\t/**\n\t\t * Source of the Tasks tab: `vtodo` (default, the record's linked Nextcloud\n\t\t * tasks) or `flow-tasks` (the OpenRegister flow tasks anchored on the\n\t\t * record, with create and per-row verbs). Passed to `CnTasksTab`.\n\t\t *\n\t\t * @type {'vtodo'|'flow-tasks'}\n\t\t */\n\t\ttasksSource: { type: String, default: 'vtodo', validator: (v) => ['vtodo', 'flow-tasks'].includes(v) },\n\t\t/** Label for the Audit Trail tab */\n\t\tauditTrailLabel: { type: String, default: () => t('nextcloud-vue', 'Audit trail') },\n\n\t\t/**\n\t\t * Open-enum tab definitions. When provided with at least one\n\t\t * entry, REPLACES the hard-coded built-in tabs (Files, Notes,\n\t\t * Tags, Tasks, Audit Trail). When unset (the default), the\n\t\t * built-in tabs render as today.\n\t\t *\n\t\t * Each entry shape:\n\t\t * - `id` (string, required) — unique tab id, used for active-tab tracking.\n\t\t * - `label` (string, required) — tab display label (caller-resolved i18n).\n\t\t * - `icon` (string, optional) — MDI icon name resolved via CnIcon.\n\t\t * - `widgets` (array, optional) — list of widget specs `{ type, props? }`\n\t\t * to render inside the tab. Built-in types: `data` → CnObjectDataWidget,\n\t\t * `metadata` → CnObjectMetadataWidget, `audit` / `audit-trail` →\n\t\t * CnAuditTrailTab, `object-table` → CnWidgetObjectTable (a declarative\n\t\t * list scoped to the parent object via `@objectId` / `@object.<field>`\n\t\t * filter tokens). Any other `type` resolves against the customComponents\n\t\t * registry.\n\t\t * - `component` (string, optional) — name resolved against the\n\t\t * customComponents registry. Mutually exclusive with `widgets`\n\t\t * (when both are set, `component` wins and a console.warn is logged).\n\t\t * - `order` (number, optional) — explicit order; defaults to array index + 1.\n\t\t *\n\t\t * @type {Array<{ id: string, label: string, icon?: string, widgets?: Array<{ type: string, props?: object }>, component?: string, order?: number }>|null}\n\t\t */\n\t\ttabs: {\n\t\t\ttype: Array,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/**\n\t\t * Custom-component registry. Keys are names referenced by\n\t\t * `tabs[].component` and unknown `tabs[].widgets[].type` values.\n\t\t * Falls back to the injected `cnCustomComponents` from a\n\t\t * CnAppRoot ancestor when omitted.\n\t\t *\n\t\t * @type {object|null}\n\t\t */\n\t\tcustomComponents: {\n\t\t\ttype: Object,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/**\n\t\t * Externally-requested active tab id. When set to a non-null id,\n\t\t * the sidebar switches to that tab — lets a host deep-link into a\n\t\t * specific leaf (e.g. a \"Linked apps\" row on the detail page that\n\t\t * opens the Mails tab). Leave null for normal internal tracking.\n\t\t *\n\t\t * @spec openspec/changes/case-page-and-list-as-a-place/specs/index-page/spec.md\n\t\t */\n\t\trequestedTab: {\n\t\t\ttype: String,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/**\n\t\t * Called with the tab this sidebar actually settled on, and whether\n\t\t * that was a correction rather than a reader's choice. A host that\n\t\t * keeps the tab in the address uses it to write the address, so the\n\t\t * address always names a tab this reader can actually see.\n\t\t *\n\t\t * @type {(tabId: string, canonicalising: boolean) => void}\n\t\t */\n\t\tonTabChange: {\n\t\t\ttype: Function,\n\t\t\tdefault: null,\n\t\t},\n\t},\n\n\temits: [\n\t\t'update:open',\n\t\t/**\n\t\t * The active tab changed. Payload is `{ tabId, canonicalising }`:\n\t\t * `canonicalising` is true when the sidebar corrected an address\n\t\t * naming a tab that does not exist or that this reader may not see,\n\t\t * rather than the reader choosing one.\n\t\t */\n\t\t'tab-change',\n\t\t/**\n\t\t * Forwarded unchanged from the built-in CnNotesTab after a note with\n\t\t * at least one `@mention` was saved. Payload:\n\t\t * `{ objectId, register, schema, noteId, mentionedUserIds }`.\n\t\t */\n\t\t'mention',\n\t],\n\n\tsetup(props) {\n\t\tconst exposed = {}\n\t\t// Integration registry: on by default via the `useRegistry`\n\t\t// prop (ADR-019). We always wire the composable up so consumers\n\t\t// can toggle `useRegistry` reactively without a remount.\n\t\tconst { integrations: registryIntegrations, resolveWidget, resolveTab } = useIntegrationRegistry()\n\t\texposed.registryIntegrations = registryIntegrations\n\t\texposed.resolveRegistryWidget = resolveWidget\n\t\t// `resolveTab` is local-first (LIB_INTEGRATION_COMPONENTS) so the\n\t\t// dispatched sidebar tab component is bound to this rendering\n\t\t// bundle's Vue — sidesteps the dual-runtime ADR-019 trap that\n\t\t// surfaced as `useNcFormBox(...)` undefined on cross-bundle\n\t\t// registrations. See openregister#1958.\n\t\texposed.resolveRegistryTabComponent = resolveTab\n\n\t\t// Object token context for sidebar-tab widgets that resolve `@objectId` /\n\t\t// `@object.<field>` tokens — the `object-table` built-in in particular\n\t\t// (e.g. a detail page's ZGW relation tab listing a zaak's besluiten,\n\t\t// filtered by `{ zaak: \"@objectId\" }`). Mirrors the reactive\n\t\t// `{ objectId, object, register, schema }` ref CnDetailPage provides.\n\t\t//\n\t\t// Provided ONLY when no ancestor already supplies `cnObjectContext`, so\n\t\t// a CnDetailPage parent's richer context (which carries the loaded\n\t\t// `object` for `@object.<field>`) keeps flowing through to the tab\n\t\t// widgets unchanged. When the sidebar is mounted standalone (no detail\n\t\t// page ancestor) it seeds the context from its own props — enough for\n\t\t// `@objectId` + register/schema resolution.\n\t\tconst parentObjectContext = inject('cnObjectContext', null)\n\t\tif (!parentObjectContext) {\n\t\t\tconst cnObjectContext = ref({\n\t\t\t\tobjectId: props.objectId || null,\n\t\t\t\tobject: null,\n\t\t\t\tregister: props.register || '',\n\t\t\t\tschema: props.schema || '',\n\t\t\t})\n\t\t\tprovide('cnObjectContext', cnObjectContext)\n\t\t\twatch(\n\t\t\t\t() => [props.objectId, props.register, props.schema],\n\t\t\t\t() => {\n\t\t\t\t\tcnObjectContext.value = {\n\t\t\t\t\t\tobjectId: props.objectId || null,\n\t\t\t\t\t\tobject: cnObjectContext.value.object || null,\n\t\t\t\t\t\tregister: props.register || '',\n\t\t\t\t\t\tschema: props.schema || '',\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t)\n\t\t}\n\n\t\t// Auto-subscribe to live updates for the active object. No-op\n\t\t// when `objectStore` is null (no Pinia active) or when the\n\t\t// consumer disabled it via `subscribe: false`. The\n\t\t// composable's reactive `id` argument keeps the subscription\n\t\t// in sync as the user navigates between sidebar objects.\n\t\tif (props.objectStore && props.subscribe) {\n\t\t\tuseObjectSubscription(\n\t\t\t\tprops.objectStore,\n\t\t\t\t() => props.objectType,\n\t\t\t\t() => props.objectId,\n\t\t\t\t{ enabled: () => Boolean(props.objectType && props.objectId) },\n\t\t\t)\n\t\t}\n\t\treturn exposed\n\t},\n\n\tdata() {\n\t\treturn {\n\t\t\tactiveTab: this.requestedTab || this.computeInitialActiveTab(),\n\t\t\t// The tab id already warned about, so an address naming a tab the\n\t\t\t// reader cannot see says so once rather than on every render.\n\t\t\twarnedTabId: null,\n\t\t}\n\t},\n\n\tcomputed: {\n\t\tsidebarTitle() {\n\t\t\treturn this.shown(this.title) || this.objectType || 'Details'\n\t\t},\n\n\t\tsidebarSubtitle() {\n\t\t\treturn this.subtitle || this.subtitleProp || ''\n\t\t},\n\n\t\t/** Whether the consumer has supplied a custom `tabs` array. */\n\t\thasCustomTabs() {\n\t\t\treturn Array.isArray(this.tabs) && this.tabs.length > 0\n\t\t},\n\n\t\t/**\n\t\t * Whether registry mode is active. Custom `tabs` always wins\n\t\t * (with a warning at mount) so consumers don't get a surprise\n\t\t * mode switch.\n\t\t */\n\t\tisRegistryMode() {\n\t\t\treturn this.useRegistry === true && this.hasCustomTabs === false\n\t\t},\n\n\t\t/**\n\t\t * Filtered registry snapshot: drops providers whose id is in\n\t\t * `excludeIntegrations` or `hiddenTabs`. Stays reactive on\n\t\t * the underlying registry's `onChange` notifications.\n\t\t */\n\t\tfilteredRegistryIntegrations() {\n\t\t\tconst excluded = new Set([\n\t\t\t\t...(this.excludeIntegrations || []),\n\t\t\t\t...(this.hiddenTabs || []),\n\t\t\t])\n\t\t\tconst all = this.registryIntegrations || []\n\t\t\treturn all.filter((p) => excluded.has(p.id) === false)\n\t\t},\n\n\t\t/** Effective customComponents registry: prop wins, inject fallback. */\n\t\teffectiveCustomComponents() {\n\t\t\treturn this.customComponents || this.cnCustomComponents || {}\n\t\t},\n\n\t\t/**\n\t\t * Effective v2 component registry (ADR-036). Kind-tagged entries\n\t\t * keyed by component name. Consulted by `resolveTabComponent` so a\n\t\t * tab's `component` ref resolves against the registry as well as the\n\t\t * legacy `customComponents` map.\n\t\t */\n\t\teffectiveRegistry() {\n\t\t\treturn this.cnRegistry || {}\n\t\t},\n\n\t\t/**\n\t\t * Shared object context forwarded to every widget / component\n\t\t * mounted inside a custom tab — same context the built-in tabs\n\t\t * receive today.\n\t\t */\n\t\tsharedTabProps() {\n\t\t\treturn {\n\t\t\t\tobjectId: this.objectId,\n\t\t\t\tobjectType: this.objectType,\n\t\t\t\tregister: this.register,\n\t\t\t\tschema: this.schema,\n\t\t\t\tapiBase: this.apiBase,\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Context forwarded to a mount-mode leaf's `mount(el, props)` for the\n\t\t * single-entity sidebar surface — the same shape an SFC tab receives,\n\t\t * plus the `surface` name and an `integrationContext` bag. Reactive\n\t\t * on the object identity so CnLeafMountHost re-mounts on object change.\n\t\t */\n\t\tsidebarMountProps() {\n\t\t\treturn {\n\t\t\t\t...this.sharedTabProps,\n\t\t\t\tsurface: 'single-entity',\n\t\t\t\tintegrationContext: {\n\t\t\t\t\tregister: this.register,\n\t\t\t\t\tschema: this.schema,\n\t\t\t\t\tobjectId: this.objectId,\n\t\t\t\t},\n\t\t\t}\n\t\t},\n\t},\n\n\twatch: {\n\t\ttabs: {\n\t\t\timmediate: false,\n\t\t\t/**\n\t\t\t * Re-anchor the active tab when the tab set changes, so the\n\t\t\t * active id stays one the reader can actually see.\n\t\t\t *\n\t\t\t * @spec openspec/changes/case-page-and-list-as-a-place/specs/index-page/spec.md\n\t\t\t */\n\t\t\thandler() {\n\t\t\t\t// Re-anchor activeTab when the tab set changes so the\n\t\t\t\t// active id stays valid (otherwise NcAppSidebar shows no\n\t\t\t\t// active tab when the consumer swaps in a fresh array).\n\t\t\t\tthis.settleOnTab(this.requestedTab)\n\t\t\t},\n\t\t},\n\n\t\t/**\n\t\t * Host deep-link: settle on the requested tab when it changes, which\n\t\t * is how an address naming a tab reaches the tab strip.\n\t\t *\n\t\t * @param {string} id The tab asked for.\n\t\t * @spec openspec/changes/case-page-and-list-as-a-place/specs/index-page/spec.md\n\t\t */\n\t\trequestedTab(id) {\n\t\t\tif (id) {\n\t\t\t\tthis.settleOnTab(id)\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * The reader clicked a tab. Reported back so a host keeping the tab\n\t\t * in the address writes it there, which is what makes a tab linkable.\n\t\t *\n\t\t * @param {string} id The tab now active.\n\t\t * @param {string} previous The tab before it.\n\t\t * @spec openspec/changes/case-page-and-list-as-a-place/specs/index-page/spec.md\n\t\t */\n\t\tactiveTab(id, previous) {\n\t\t\tif (id && previous !== undefined && id !== previous && typeof this.onTabChange === 'function') {\n\t\t\t\tthis.onTabChange(id, false)\n\t\t\t}\n\t\t},\n\t},\n\n\t/**\n\t * Settle on a tab on arrival, and warn about a tab set the consumer\n\t * declared two ways.\n\t *\n\t * @spec openspec/changes/case-page-and-list-as-a-place/specs/index-page/spec.md\n\t */\n\tmounted() {\n\t\t// Settle on arrival, so an address carrying no tab is corrected to\n\t\t// its canonical form once rather than staying tabless until the\n\t\t// reader happens to click something (ADR-052).\n\t\tif (typeof this.onTabChange === 'function') {\n\t\t\tthis.settleOnTab(this.requestedTab)\n\t\t}\n\t\tif (this.useRegistry === true && this.hasCustomTabs === true) {\n\t\t\t// eslint-disable-next-line no-console\n\t\t\tconsole.warn('[CnObjectSidebar] `useRegistry` is true but `tabs` is also set — falling back to `tabs` (registry mode ignored). Pass one or the other.')\n\t\t}\n\t},\n\n\tmethods: {\n\n\t\t/**\n\t\t * A manifest label through the injected lookup, or as written.\n\t\t *\n\t\t * @param {string} text The label as written.\n\t\t * @return {string} The label in the user's language.\n\t\t */\n\t\tshown(text) {\n\t\t\treturn typeof this.cnTranslate === 'function' && typeof text === 'string' && text !== '' ? this.cnTranslate(text) : text\n\t\t},\n\n\t\t/**\n\t\t * The `lang` of a label that fell back to its written text in another language.\n\t\t *\n\t\t * @param {string} text The label as written.\n\t\t * @return {string|undefined} The source language, or undefined.\n\t\t */\n\t\tlangOf(text) {\n\t\t\treturn labelLang(this.cnTranslate, text) || undefined\n\t\t},\n\n\t\tisTabHidden(tabId) {\n\t\t\treturn this.hiddenTabs.includes(tabId)\n\t\t},\n\n\t\t/**\n\t\t * Resolve a registry provider's tab component, preferring the\n\t\t * LOCAL lib-owned component (rendering-bundle Vue) over the\n\t\t * shared registry's stored object. Falls back to the stored\n\t\t * `provider.tab` for consumer-custom ids (which live in the\n\t\t * consumer's own bundle and therefore render under the same\n\t\t * Vue instance with no mismatch). See openregister#1958.\n\t\t *\n\t\t * @param {object} provider Normalised registry entry.\n\t\t * @return {object|null} Vue component, or null.\n\t\t */\n\t\tresolveRegistryTab(provider) {\n\t\t\tif (!provider || typeof provider.id !== 'string') {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tconst local = this.resolveRegistryTabComponent(provider.id)\n\t\t\tif (local) {\n\t\t\t\treturn local\n\t\t\t}\n\t\t\treturn provider.tab || null\n\t\t},\n\n\t\t/**\n\t\t * Whether a registry provider renders via the mount hand-off\n\t\t * (`renderMode: 'mount'`, openregister#2127) rather than an SFC tab.\n\t\t * Mount-mode leaves carry `mount`/`unmount` functions the host calls\n\t\t * against a bare element via CnLeafMountHost.\n\t\t *\n\t\t * @param {object} provider Normalised registry entry.\n\t\t * @return {boolean} true when the provider is mount-mode.\n\t\t */\n\t\tisMountProvider(provider) {\n\t\t\treturn Boolean(provider)\n\t\t\t\t&& provider.renderMode === 'mount'\n\t\t\t\t&& typeof provider.mount === 'function'\n\t\t\t\t&& typeof provider.unmount === 'function'\n\t\t},\n\n\t\t/**\n\t\t * Pick a sensible default active tab on mount and on tabs[]\n\t\t * changes. When custom tabs are present, the first entry wins.\n\t\t * When unset, the built-in `files` tab is the default (matches\n\t\t * the legacy behavior).\n\t\t */\n\t\tcomputeInitialActiveTab() {\n\t\t\tif (Array.isArray(this.tabs) && this.tabs.length > 0) {\n\t\t\t\treturn this.tabs[0].id\n\t\t\t}\n\t\t\treturn 'files'\n\t\t},\n\n\t\t/**\n\t\t * The tab ids this reader can actually see, in the order shown.\n\t\t *\n\t\t * Three tab sources, one answer. Without this the address could name\n\t\t * a tab that is hidden, excluded or simply not registered, and the\n\t\t * sidebar would show its first tab while the address went on claiming\n\t\t * a different one.\n\t\t *\n\t\t * @return {Array<string>} The visible tab ids.\n\t\t * @spec openspec/changes/case-page-and-list-as-a-place/specs/index-page/spec.md\n\t\t */\n\t\tvisibleTabIds() {\n\t\t\tif (this.isRegistryMode) {\n\t\t\t\treturn (this.filteredRegistryIntegrations || []).map((p) => p.id)\n\t\t\t}\n\t\t\tif (Array.isArray(this.tabs) && this.tabs.length > 0) {\n\t\t\t\treturn this.tabs.filter((tab) => tab && !this.isTabHidden(tab.id)).map((tab) => tab.id)\n\t\t\t}\n\t\t\treturn ['files', 'notes', 'tags', 'tasks', 'auditTrail'].filter((id) => !this.isTabHidden(id))\n\t\t},\n\n\t\t/**\n\t\t * Settle on a tab, and say whether the address had to be corrected.\n\t\t *\n\t\t * An address naming a tab that does not exist, or one this reader may\n\t\t * not see, falls back to the first tab they can see and says so ONCE.\n\t\t * Silently showing a different tab than the address names is the\n\t\t * failure here: the reader then sends a colleague a link that opens\n\t\t * somewhere else again.\n\t\t *\n\t\t * @param {string|null} requested The tab the address asked for.\n\t\t * @return {{ tabId: string, canonicalising: boolean }} The tab to show.\n\t\t * @spec openspec/changes/case-page-and-list-as-a-place/specs/index-page/spec.md\n\t\t */\n\t\tresolveTabRequest(requested) {\n\t\t\tconst visible = this.visibleTabIds\n\t\t\tconst fallback = visible[0] || this.computeInitialActiveTab()\n\t\t\tif (!requested) {\n\t\t\t\treturn { tabId: fallback, canonicalising: true }\n\t\t\t}\n\t\t\tif (visible.length === 0 || visible.includes(requested)) {\n\t\t\t\treturn { tabId: requested, canonicalising: false }\n\t\t\t}\n\t\t\tif (this.warnedTabId !== requested) {\n\t\t\t\tthis.warnedTabId = requested\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.warn(`[CnObjectSidebar] The address asks for the \"${requested}\" tab, which is not available here. Showing \"${fallback}\" instead.`)\n\t\t\t}\n\t\t\treturn { tabId: fallback, canonicalising: true }\n\t\t},\n\n\t\t/**\n\t\t * Show a tab and tell the host, so the address can follow.\n\t\t *\n\t\t * @param {string|null} requested The tab asked for.\n\t\t * @spec openspec/changes/case-page-and-list-as-a-place/specs/index-page/spec.md\n\t\t */\n\t\tsettleOnTab(requested) {\n\t\t\tconst { tabId, canonicalising } = this.resolveTabRequest(requested)\n\t\t\tthis.activeTab = tabId\n\t\t\tif (typeof this.onTabChange === 'function') {\n\t\t\t\tthis.onTabChange(tabId, canonicalising)\n\t\t\t}\n\t\t\t/**\n\t\t\t * @event tab-change Emitted when the active tab settles, including when the sidebar corrected the address.\n\t\t\t * @type {{ tabId: string, canonicalising: boolean }}\n\t\t\t */\n\t\t\tthis.$emit('tab-change', { tabId, canonicalising })\n\t\t},\n\n\t\t/**\n\t\t * Build the prop bag for a widget in the `widgets[]` tab path. All\n\t\t * widgets get the shared coordinate context plus the loaded object\n\t\t * (`objectData`); the prop-driven `data` built-in also gets the schema\n\t\t * OBJECT bound to its `schema` prop (the other tabs use the `schema`\n\t\t * slug string, so the override is scoped to `type: 'data'`). Of a\n\t\t * widget's own `props`, the ones its component declares win on overlap;\n\t\t * an undeclared one would only fall through onto the component's root.\n\t\t *\n\t\t * @spec openspec/changes/declared-props-detail-index-sidebar/specs/widget-hosts/spec.md#requirement-a-widget-host-passes-only-the-keys-a-widget-declares\n\t\t * @param {{ type: string, props?: object }} w Widget spec\n\t\t * @return {object} Props to v-bind onto the resolved widget component\n\t\t */\n\t\twidgetBindings(w) {\n\t\t\tconst bindings = { ...this.sharedTabProps, objectData: this.objectData }\n\t\t\tif (w.type === 'data') {\n\t\t\t\t// CnObjectDataWidget wants the schema OBJECT, never the slug the\n\t\t\t\t// other tabs use. Pass the resolved object (null until it loads —\n\t\t\t\t// the widget renders its empty state meanwhile) so it never sees\n\t\t\t\t// a String `schema`.\n\t\t\t\tbindings.schema = this.objectSchema\n\t\t\t}\n\t\t\treturn { ...bindings, ...pickDeclaredProps(this.resolveWidgetComponent(w.type), w.props || {}, w.type || '') }\n\t\t},\n\n\t\t/**\n\t\t * Resolve a widget type to a component. Built-in types (`data`,\n\t\t * `metadata`, `audit` / `audit-trail`, `object-table`) map to their\n\t\t * lib component; any other type resolves against the v2 registry, then\n\t\t * the legacy customComponents map. Logs a console.warn and returns null when nothing\n\t\t * resolves.\n\t\t *\n\t\t * @param {string} type Widget type identifier\n\t\t * @return {object|null} Vue component, or null when unresolved\n\t\t */\n\t\tresolveWidgetComponent(type) {\n\t\t\tif (BUILTIN_WIDGETS[type]) {\n\t\t\t\treturn BUILTIN_WIDGETS[type]\n\t\t\t}\n\t\t\tconst registryEntry = this.effectiveRegistry[type]\n\t\t\tif (registryEntry && registryEntry.component) {\n\t\t\t\treturn registryEntry.component\n\t\t\t}\n\t\t\tconst reg = this.effectiveCustomComponents\n\t\t\tif (reg && reg[type]) {\n\t\t\t\treturn reg[type]\n\t\t\t}\n\t\t\t// eslint-disable-next-line no-console\n\t\t\tconsole.warn(`[CnObjectSidebar] Unknown widget type \"${type}\" — not in built-ins (data, metadata, audit, audit-trail, object-table), the registry or customComponents.`)\n\t\t\treturn null\n\t\t},\n\n\t\t/**\n\t\t * Resolve a tab's `component` registry name. Logs a\n\t\t * console.warn when both `widgets` and `component` are set\n\t\t * (component wins) or when the registry name is missing.\n\t\t *\n\t\t * @param {object} tab Tab definition\n\t\t * @return {object|null} Vue component, or null when unresolved\n\t\t */\n\t\tresolveTabComponent(tab) {\n\t\t\tif (tab.widgets && tab.widgets.length > 0) {\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.warn(`[CnObjectSidebar] Tab \"${tab.id}\" declares both widgets[] and component — component wins, widgets are ignored.`)\n\t\t\t}\n\t\t\t// v2 registry first (ADR-036): any kind-tagged entry with a\n\t\t\t// `component` field is acceptable for a slot/tab lookup — this\n\t\t\t// is what lets a `kind: 'page'` tab component (the procest\n\t\t\t// pattern) render. Fall back to the legacy customComponents map.\n\t\t\tconst registryEntry = this.effectiveRegistry[tab.component]\n\t\t\tif (registryEntry && registryEntry.component) {\n\t\t\t\treturn registryEntry.component\n\t\t\t}\n\t\t\tconst reg = this.effectiveCustomComponents\n\t\t\tconst resolved = reg && reg[tab.component]\n\t\t\tif (!resolved) {\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.warn(`[CnObjectSidebar] Tab \"${tab.id}\" component \"${tab.component}\" not found in registry or customComponents.`)\n\t\t\t\treturn null\n\t\t\t}\n\t\t\treturn resolved\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n/* NcAppSidebar lays every tab out as an equal share of the sidebar width\n * (`flex: 1 1`) with an ellipsis caption, so an object with many tabs — e.g. a\n * lead's 5+ tabs — shrinks them until the labels truncate. Keep the tabs\n * equal-width (uniform) but stop them shrinking below a readable minimum, and\n * let the strip scroll horizontally once they no longer fit. `flex-basis: 0`\n * + equal grow keeps every tab the same width whether the row fits or scrolls.\n * Apps with longer labels can widen the floor via --cn-sidebar-tab-min-width. */\n:deep(.app-sidebar-tabs__nav) {\n\toverflow-x: auto;\n}\n\n:deep(.app-sidebar-tabs__nav .app-sidebar-tabs__tab) {\n\tflex-grow: 1;\n\tflex-shrink: 0;\n\tflex-basis: 0;\n\t/* !important to beat NcAppSidebar's own min-width on the button variant. */\n\tmin-width: var(--cn-sidebar-tab-min-width, 7rem) !important;\n}\n</style>\n"],"names":["CnObjectDataWidget","CnObjectMetadataWidget","CnAuditTrailTab","CnWidgetObjectTable","CnFilesTab","CnNotesTab","CnTagsTab","CnTasksTab","CnIcon","CnLeafMountHost","t"],"mappings":"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"}
1
+ {"version":3,"file":"CnObjectSidebar.vue2.js","sources":["../../../../src/components/CnObjectSidebar/CnObjectSidebar.vue"],"sourcesContent":["<!--\n CnObjectSidebar — Right sidebar with standardized tabs for generic object functionality.\n\n Provides Files, Notes, Tags, Tasks, and Audit Trail tabs that integrate with\n OpenRegister API endpoints (which bridge to Nextcloud-native APIs).\n All tabs are optional and overridable via props and slots.\n-->\n<template>\n\t<!-- `subname` is NcAppSidebar's visible secondary line; `subtitle` is only\n\t the tooltip on it, and the line is not rendered at all while subname is\n\t empty — so passing subtitle alone showed nothing. Same pair as\n\t name/title, and as CnIndexSidebar. -->\n\t<NcAppSidebar\n\t\tv-model:active=\"activeTab\"\n\t\t:name=\"sidebarTitle\"\n\t\t:title=\"sidebarTitle\"\n\t\t:subname=\"sidebarSubtitle\"\n\t\t:subtitle=\"sidebarSubtitle\"\n\t\t:open=\"open\"\n\t\tdata-testid=\"cn-object-sidebar\"\n\t\t@update:open=\"$emit('update:open', $event)\"\n\t\t@close=\"$emit('update:open', false)\">\n\t\t<!-- REGISTRY BRANCH: pluggable integration registry-driven.\n\t\t Renders one tab per provider registered on\n\t\t `window.OCA.OpenRegister.integrations`. `hiddenTabs` /\n\t\t `excludeIntegrations` filter the set; the `#extra-tabs`\n\t\t slot still appends consumer-supplied tabs. Per-integration\n\t\t slot overrides aren't supported in registry mode — apps\n\t\t that need to override a built-in tab should register their\n\t\t own provider with the same id (collision policy: first\n\t\t wins) before OpenRegister's bundle loads. -->\n\t\t<template v-if=\"isRegistryMode\">\n\t\t\t<NcAppSidebarTab\n\t\t\t\tv-for=\"(provider, idx) in filteredRegistryIntegrations\"\n\t\t\t\t:id=\"provider.id\"\n\t\t\t\t:key=\"provider.id\"\n\t\t\t\t:name=\"provider.label\"\n\t\t\t\t:order=\"provider.order != null ? provider.order : idx + 1\"\n\t\t\t\t:data-testid=\"`cn-object-sidebar-tab-${provider.id}`\">\n\t\t\t\t<template #icon>\n\t\t\t\t\t<CnIcon v-if=\"provider.icon\" :name=\"provider.icon\" :size=\"20\" />\n\t\t\t\t</template>\n\t\t\t\t<!-- MOUNT BRANCH (openregister#2127): a `renderMode: 'mount'`\n\t\t\t\t leaf renders through CnLeafMountHost — a bare host-owned\n\t\t\t\t element the leaf mounts its own framework into. Mounted\n\t\t\t\t lazily when the tab is active; unmounted on hide/teardown. -->\n\t\t\t\t<CnLeafMountHost\n\t\t\t\t\tv-if=\"isMountProvider(provider)\"\n\t\t\t\t\t:provider=\"provider\"\n\t\t\t\t\t:active=\"activeTab === provider.id\"\n\t\t\t\t\t:mountProps=\"sidebarMountProps\" />\n\t\t\t\t<component\n\t\t\t\t\t:is=\"resolveRegistryTab(provider)\"\n\t\t\t\t\tv-else\n\t\t\t\t\tv-bind=\"sharedTabProps\" />\n\t\t\t</NcAppSidebarTab>\n\t\t\t<slot name=\"extra-tabs\" />\n\t\t</template>\n\n\t\t<!-- BACKWARDS-COMPATIBLE BRANCH: hard-coded built-in tabs.\n\t\t Used when no custom `tabs` prop is provided and the\n\t\t registry mode is not active. The slot overrides\n\t\t (#tab-files etc.) and `hiddenTabs` filtering remain\n\t\t unchanged. -->\n\t\t<template v-else-if=\"!hasCustomTabs\">\n\t\t\t<!-- Files Tab -->\n\t\t\t<NcAppSidebarTab\n\t\t\t\tv-if=\"!isTabHidden('files')\"\n\t\t\t\tid=\"files\"\n\t\t\t\t:name=\"filesLabel\"\n\t\t\t\t:order=\"1\"\n\t\t\t\tdata-testid=\"cn-object-sidebar-tab-files\">\n\t\t\t\t<template #icon>\n\t\t\t\t\t<Paperclip :size=\"20\" />\n\t\t\t\t</template>\n\t\t\t\t<slot name=\"tab-files\" :objectId=\"objectId\" :objectType=\"objectType\">\n\t\t\t\t\t<CnFilesTab\n\t\t\t\t\t\t:objectId=\"objectId\"\n\t\t\t\t\t\t:register=\"register\"\n\t\t\t\t\t\t:schema=\"schema\"\n\t\t\t\t\t\t:apiBase=\"apiBase\" />\n\t\t\t\t</slot>\n\t\t\t</NcAppSidebarTab>\n\n\t\t\t<!-- Notes Tab -->\n\t\t\t<NcAppSidebarTab\n\t\t\t\tv-if=\"!isTabHidden('notes')\"\n\t\t\t\tid=\"notes\"\n\t\t\t\t:name=\"notesLabel\"\n\t\t\t\t:order=\"2\"\n\t\t\t\tdata-testid=\"cn-object-sidebar-tab-notes\">\n\t\t\t\t<template #icon>\n\t\t\t\t\t<CommentTextOutline :size=\"20\" />\n\t\t\t\t</template>\n\t\t\t\t<slot name=\"tab-notes\" :objectId=\"objectId\" :objectType=\"objectType\">\n\t\t\t\t\t<!-- The `mention` passthrough is the notification hook: apps\n\t\t\t\t\t mounting the full sidebar receive the mentioned user ids\n\t\t\t\t\t and dispatch NC notifications from their own backend. -->\n\t\t\t\t\t<CnNotesTab\n\t\t\t\t\t\t:objectId=\"objectId\"\n\t\t\t\t\t\t:register=\"register\"\n\t\t\t\t\t\t:schema=\"schema\"\n\t\t\t\t\t\t:apiBase=\"apiBase\"\n\t\t\t\t\t\t@mention=\"$emit('mention', $event)\" />\n\t\t\t\t</slot>\n\t\t\t</NcAppSidebarTab>\n\n\t\t\t<!-- Tags Tab -->\n\t\t\t<NcAppSidebarTab\n\t\t\t\tv-if=\"!isTabHidden('tags')\"\n\t\t\t\tid=\"tags\"\n\t\t\t\t:name=\"tagsLabel\"\n\t\t\t\t:order=\"3\"\n\t\t\t\tdata-testid=\"cn-object-sidebar-tab-tags\">\n\t\t\t\t<template #icon>\n\t\t\t\t\t<TagOutline :size=\"20\" />\n\t\t\t\t</template>\n\t\t\t\t<slot name=\"tab-tags\" :objectId=\"objectId\" :objectType=\"objectType\">\n\t\t\t\t\t<CnTagsTab\n\t\t\t\t\t\t:objectId=\"objectId\"\n\t\t\t\t\t\t:register=\"register\"\n\t\t\t\t\t\t:schema=\"schema\"\n\t\t\t\t\t\t:apiBase=\"apiBase\" />\n\t\t\t\t</slot>\n\t\t\t</NcAppSidebarTab>\n\n\t\t\t<!-- Tasks Tab -->\n\t\t\t<NcAppSidebarTab\n\t\t\t\tv-if=\"!isTabHidden('tasks')\"\n\t\t\t\tid=\"tasks\"\n\t\t\t\t:name=\"tasksLabel\"\n\t\t\t\t:order=\"4\"\n\t\t\t\tdata-testid=\"cn-object-sidebar-tab-tasks\">\n\t\t\t\t<template #icon>\n\t\t\t\t\t<CheckboxMarkedOutline :size=\"20\" />\n\t\t\t\t</template>\n\t\t\t\t<slot name=\"tab-tasks\" :objectId=\"objectId\" :objectType=\"objectType\">\n\t\t\t\t\t<CnTasksTab\n\t\t\t\t\t\t:objectId=\"objectId\"\n\t\t\t\t\t\t:register=\"register\"\n\t\t\t\t\t\t:schema=\"schema\"\n\t\t\t\t\t\t:apiBase=\"apiBase\"\n\t\t\t\t\t\t:source=\"tasksSource\" />\n\t\t\t\t</slot>\n\t\t\t</NcAppSidebarTab>\n\n\t\t\t<!-- Audit Trail Tab -->\n\t\t\t<NcAppSidebarTab\n\t\t\t\tv-if=\"!isTabHidden('auditTrail')\"\n\t\t\t\tid=\"auditTrail\"\n\t\t\t\t:name=\"auditTrailLabel\"\n\t\t\t\t:order=\"5\"\n\t\t\t\tdata-testid=\"cn-object-sidebar-tab-audit-trail\">\n\t\t\t\t<template #icon>\n\t\t\t\t\t<History :size=\"20\" />\n\t\t\t\t</template>\n\t\t\t\t<slot name=\"tab-audit-trail\" :objectId=\"objectId\" :objectType=\"objectType\">\n\t\t\t\t\t<CnAuditTrailTab\n\t\t\t\t\t\t:objectId=\"objectId\"\n\t\t\t\t\t\t:register=\"register\"\n\t\t\t\t\t\t:schema=\"schema\"\n\t\t\t\t\t\t:apiBase=\"apiBase\" />\n\t\t\t\t</slot>\n\t\t\t</NcAppSidebarTab>\n\n\t\t\t<!-- Custom tabs slot (only relevant in legacy mode) -->\n\t\t\t<slot name=\"extra-tabs\" />\n\t\t</template>\n\n\t\t<!-- OPEN-ENUM BRANCH: render the consumer-supplied `tabs` array.\n\t\t Each tab declares its content via `widgets` (resolved against\n\t\t the built-in widget registry — `data` → CnObjectDataWidget,\n\t\t `metadata` → CnObjectMetadataWidget, `audit`/`audit-trail` →\n\t\t CnAuditTrailTab, `object-table` → CnWidgetObjectTable — with the\n\t\t customComponents registry as the escape hatch) OR `component`\n\t\t (resolved against the customComponents registry directly). -->\n\t\t<template v-else>\n\t\t\t<NcAppSidebarTab\n\t\t\t\tv-for=\"(tab, idx) in tabs\"\n\t\t\t\t:id=\"tab.id\"\n\t\t\t\t:key=\"tab.id\"\n\t\t\t\t:name=\"shown(tab.label)\"\n\t\t\t\t:lang=\"langOf(tab.label)\"\n\t\t\t\t:order=\"tab.order != null ? tab.order : idx + 1\"\n\t\t\t\t:data-testid=\"`cn-object-sidebar-tab-${tab.id}`\">\n\t\t\t\t<template v-if=\"tab.icon\" #icon>\n\t\t\t\t\t<CnIcon :name=\"tab.icon\" :size=\"20\" />\n\t\t\t\t</template>\n\n\t\t\t\t<!-- Component-registry escape hatch wins when `component` is set\n\t\t\t\t (with a console.warn at mount time when widgets is also set). -->\n\t\t\t\t<component\n\t\t\t\t\t:is=\"resolveTabComponent(tab)\"\n\t\t\t\t\tv-if=\"tab.component\"\n\t\t\t\t\tv-bind=\"sharedTabProps\" />\n\n\t\t\t\t<!-- Widget array path. Each widget receives the shared object\n\t\t\t\t context plus its own `props` via `widgetBindings` (which also\n\t\t\t\t hands the prop-driven `data` / `metadata` built-ins the loaded\n\t\t\t\t object and schema); per-widget props win on overlap. -->\n\t\t\t\t<div v-else class=\"cn-object-sidebar__tab-widgets\">\n\t\t\t\t\t<template v-for=\"(w, wIdx) in tab.widgets || []\">\n\t\t\t\t\t\t<component\n\t\t\t\t\t\t\t:is=\"resolveWidgetComponent(w.type)\"\n\t\t\t\t\t\t\tv-if=\"resolveWidgetComponent(w.type)\"\n\t\t\t\t\t\t\t:key=\"wIdx\"\n\t\t\t\t\t\t\tv-bind=\"widgetBindings(w)\" />\n\t\t\t\t\t</template>\n\t\t\t\t</div>\n\t\t\t</NcAppSidebarTab>\n\t\t</template>\n\t</NcAppSidebar>\n</template>\n\n<script>\nimport { translate as t } from '@nextcloud/l10n'\nimport { NcAppSidebar, NcAppSidebarTab } from '@nextcloud/vue'\nimport { inject, provide, ref, watch } from 'vue'\nimport CheckboxMarkedOutline from 'vue-material-design-icons/CheckboxMarkedOutline.vue'\nimport CommentTextOutline from 'vue-material-design-icons/CommentTextOutline.vue'\nimport History from 'vue-material-design-icons/History.vue'\nimport Paperclip from 'vue-material-design-icons/Paperclip.vue'\nimport TagOutline from 'vue-material-design-icons/TagOutline.vue'\nimport CnWidgetObjectTable from '../CnWidgetObjectTable/CnWidgetObjectTable.vue'\nimport CnAuditTrailTab from './CnAuditTrailTab.vue'\nimport CnFilesTab from './CnFilesTab.vue'\nimport CnNotesTab from './CnNotesTab.vue'\nimport CnTagsTab from './CnTagsTab.vue'\nimport CnTasksTab from './CnTasksTab.vue'\nimport { useIntegrationRegistry } from '../../composables/useIntegrationRegistry.js'\nimport { useObjectSubscription } from '../../composables/useObjectSubscription.js'\nimport { pickDeclaredProps } from '../../utils/declaredProps.js'\nimport { labelLang } from '../../utils/manifestTranslate.js'\nimport { CnAiFeaturesWidget } from '../CnAiFeaturesWidget/index.js'\nimport { CnIcon } from '../CnIcon/index.js'\nimport { CnLeafMountHost } from '../CnLeafMountHost/index.js'\nimport { CnObjectDataWidget } from '../CnObjectDataWidget/index.js'\nimport { CnObjectMetadataWidget } from '../CnObjectMetadataWidget/index.js'\nimport { CnObjectPermissionsTab } from '../CnObjectPermissionsTab/index.js'\n\n/**\n * Built-in widget registry used by the open-enum `tabs` prop.\n * - `data` → CnObjectDataWidget (schema-driven editable grid)\n * - `metadata` → CnObjectMetadataWidget (read-only system metadata)\n * - `audit` → CnAuditTrailTab (the object's change log / audit trail)\n * - `object-permissions` → CnObjectPermissionsTab (read-only: who holds which\n * right on the object, where each grant came from, and on a past date)\n * - `object-table` → CnWidgetObjectTable (a declarative list scoped to the\n * parent object — the full source / endpointSource / columns / actions\n * contract). Resolves `@objectId` / `@object.<field>` filter tokens against\n * the object context this sidebar `provide`s (see setup), so a detail\n * page's ZGW-style relation tab (e.g. a zaak's besluiten, filtered by\n * `{ zaak: \"@objectId\" }`) renders as a sidebar tab with no bespoke code.\n *\n * Any `widgets[].type` value not in this map falls back to the\n * customComponents registry (prop, then injected `cnCustomComponents`).\n */\nconst BUILTIN_WIDGETS = {\n\t// The hermiq AI features a record's type switches on (CnAiFeaturesWidget).\n\t'ai-features': CnAiFeaturesWidget,\n\tdata: CnObjectDataWidget,\n\tmetadata: CnObjectMetadataWidget,\n\taudit: CnAuditTrailTab,\n\t// Alias matching the dashboard/detail-page widget key `audit-trail` so a\n\t// manifest can declare a sidebar tab with `widgets: [{ type: 'audit-trail' }]`\n\t// (the same key it uses for the detail-page body widget) and get the object's\n\t// change log as a proper sidebar tab.\n\t'audit-trail': CnAuditTrailTab,\n\t// The declarative list widget (same key as the detail-page body widget), so\n\t// a sidebar tab can render a related-object list scoped to the parent\n\t// object via `@objectId` / `@object.<field>` tokens in its `source.filter`.\n\t'object-table': CnWidgetObjectTable,\n\t'object-permissions': CnObjectPermissionsTab,\n}\n\n/**\n * CnObjectSidebar — Right sidebar for entity detail pages.\n *\n * Provides standardized tabs for generic object functionality (Files, Notes, Tags,\n * Tasks, Audit Trail) that integrate with OpenRegister API endpoints bridging to\n * Nextcloud-native APIs. Each tab is a self-contained component.\n *\n * Basic usage\n * ```vue\n * <CnObjectSidebar\n * object-type=\"pipelinq_lead\"\n * :object-id=\"leadId\"\n * :register=\"registerConfig.register\"\n * :schema=\"registerConfig.schema\" />\n * ```\n *\n * Hide specific tabs\n * ```vue\n * <CnObjectSidebar\n * object-type=\"pipelinq_lead\"\n * :object-id=\"leadId\"\n * :hidden-tabs=\"['tasks', 'tags']\" />\n * ```\n *\n * Override a tab\n * ```vue\n * <CnObjectSidebar object-type=\"pipelinq_lead\" :object-id=\"leadId\">\n * <template #tab-notes=\"{ objectId }\">\n * <MyCustomNotesComponent :id=\"objectId\" />\n * </template>\n * </CnObjectSidebar>\n * ```\n */\nexport default {\n\tname: 'CnObjectSidebar',\n\n\tcomponents: {\n\t\tNcAppSidebar,\n\t\tNcAppSidebarTab,\n\t\tPaperclip,\n\t\tCommentTextOutline,\n\t\tTagOutline,\n\t\tCheckboxMarkedOutline,\n\t\tHistory,\n\t\tCnFilesTab,\n\t\tCnNotesTab,\n\t\tCnTagsTab,\n\t\tCnTasksTab,\n\t\tCnAuditTrailTab,\n\t\tCnIcon,\n\t\tCnLeafMountHost,\n\t},\n\n\tinject: {\n\t\tcnCustomComponents: { default: () => ({}) },\n\t\t// v2 component registry (ADR-036). Kind-tagged entries\n\t\t// ({ kind, component }); a sidebar tab's `component` ref resolves\n\t\t// against this first so apps that migrated their tab components to\n\t\t// the registry (e.g. as `kind: 'page'`) still render. Empty default\n\t\t// keeps the legacy `customComponents`-only path unchanged.\n\t\tcnRegistry: { default: () => ({}) },\n\t\t// The label lookup from CnAppRoot, so tab labels and the title show in the user's language.\n\t\tcnTranslate: { default: null },\n\t},\n\n\tprops: {\n\t\t/** The entity type (e.g., \"pipelinq_lead\", \"procest_case\") */\n\t\tobjectType: {\n\t\t\ttype: String,\n\t\t\trequired: true,\n\t\t},\n\n\t\t/** The object UUID */\n\t\tobjectId: {\n\t\t\ttype: String,\n\t\t\trequired: true,\n\t\t},\n\n\t\t/** OpenRegister register ID */\n\t\tregister: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/** OpenRegister schema ID */\n\t\tschema: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/**\n\t\t * The loaded object, forwarded to prop-driven sidebar-tab widgets\n\t\t * (the `data` / `metadata` built-ins) as `objectData`. The sidebar is\n\t\t * otherwise coordinate-based — most tabs self-fetch from\n\t\t * `objectId`/`register`/`schema` — so this is null unless a host (e.g.\n\t\t * CnDetailPage via CnAppRoot) publishes the loaded object.\n\t\t *\n\t\t * @type {object|null}\n\t\t */\n\t\tobjectData: {\n\t\t\ttype: Object,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/**\n\t\t * The resolved JSON Schema OBJECT (with a `properties` field), forwarded\n\t\t * to the `data` built-in tab widget (CnObjectDataWidget), which needs the\n\t\t * schema definition rather than the `schema` slug string. Null unless a\n\t\t * host (e.g. CnDetailPage via CnAppRoot) publishes it.\n\t\t *\n\t\t * @type {object|null}\n\t\t */\n\t\tobjectSchema: {\n\t\t\ttype: Object,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/** Array of tab IDs to hide: 'files', 'notes', 'tags', 'tasks', 'auditTrail' */\n\t\thiddenTabs: {\n\t\t\ttype: Array,\n\t\t\tdefault: () => [],\n\t\t},\n\n\t\t/**\n\t\t * Use the pluggable integration registry to drive the sidebar\n\t\t * tabs. Defaults to `true` (ADR-019): tabs are rendered one per\n\t\t * provider registered on `window.OCA.OpenRegister.integrations`\n\t\t * (and via `useIntegrationRegistry()`). The canonical five\n\t\t * built-ins — files / notes / tags / tasks / audit-trail — are\n\t\t * shipped as providers in `builtinIntegrations` and registered by\n\t\t * OpenRegister's bootstrap (`registerBuiltinIntegrations()`), so\n\t\t * the default surface is unchanged for apps that register them.\n\t\t *\n\t\t * Set `false` to opt back into the legacy hardcoded-tabs path,\n\t\t * which renders the five built-in tabs directly from this\n\t\t * component and supports the `#tab-<id>` slot overrides. Use this\n\t\t * for consumers that do not call `registerBuiltinIntegrations()`\n\t\t * and want the built-in tabs without standing up the registry.\n\t\t *\n\t\t * `hiddenTabs` / `excludeIntegrations` and the `#extra-tabs` slot\n\t\t * apply in both modes.\n\t\t *\n\t\t * Mutually exclusive with the open-enum `tabs` prop — when both\n\t\t * are set, `tabs` wins and a console.warn is logged.\n\t\t *\n\t\t * @type {boolean}\n\t\t */\n\t\tuseRegistry: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: true,\n\t\t},\n\n\t\t/**\n\t\t * Integration ids to exclude when rendering registry-driven\n\t\t * tabs. Mirrors `hiddenTabs` for the legacy mode.\n\t\t *\n\t\t * @type {string[]}\n\t\t */\n\t\texcludeIntegrations: {\n\t\t\ttype: Array,\n\t\t\tdefault: () => [],\n\t\t},\n\n\t\t/** Whether the sidebar is open */\n\t\topen: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: true,\n\t\t},\n\n\t\t/** Sidebar title (defaults to objectType) */\n\t\ttitle: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/** Sidebar subtitle */\n\t\tsubtitle: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/** @deprecated Use `subtitle` instead. Alias kept for backwards compatibility. */\n\t\tsubtitleProp: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/** Base API URL for OpenRegister */\n\t\tapiBase: {\n\t\t\ttype: String,\n\t\t\tdefault: '/apps/openregister/api',\n\t\t},\n\n\t\t/**\n\t\t * Whether to auto-subscribe to live updates for the\n\t\t * current object. Defaults to true. The sidebar calls\n\t\t * `objectStore.subscribe(objectType, objectId)` on mount and\n\t\t * unsubscribes on unmount via `tryOnScopeDispose`.\n\t\t *\n\t\t * @type {boolean}\n\t\t */\n\t\tsubscribe: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: true,\n\t\t},\n\n\t\t/**\n\t\t * Optional explicit Pinia store instance. When omitted,\n\t\t * the sidebar skips auto-subscribe (Pinia not yet active\n\t\t * in the consumer context).\n\t\t *\n\t\t * @type {object|null}\n\t\t */\n\t\tobjectStore: {\n\t\t\ttype: Object,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t// --- Pre-translated labels ---\n\t\t/** Label for the Files tab */\n\t\tfilesLabel: { type: String, default: () => t('nextcloud-vue', 'Files') },\n\t\t/** Label for the Notes tab */\n\t\tnotesLabel: { type: String, default: () => t('nextcloud-vue', 'Notes') },\n\t\t/** Label for the Tags tab */\n\t\ttagsLabel: { type: String, default: () => t('nextcloud-vue', 'Tags') },\n\t\t/** Label for the Tasks tab */\n\t\ttasksLabel: { type: String, default: () => t('nextcloud-vue', 'Tasks') },\n\t\t/**\n\t\t * Source of the Tasks tab: `vtodo` (default, the record's linked Nextcloud\n\t\t * tasks) or `flow-tasks` (the OpenRegister flow tasks anchored on the\n\t\t * record, with create and per-row verbs). Passed to `CnTasksTab`.\n\t\t *\n\t\t * @type {'vtodo'|'flow-tasks'}\n\t\t */\n\t\ttasksSource: { type: String, default: 'vtodo', validator: (v) => ['vtodo', 'flow-tasks'].includes(v) },\n\t\t/** Label for the Audit Trail tab */\n\t\tauditTrailLabel: { type: String, default: () => t('nextcloud-vue', 'Audit trail') },\n\n\t\t/**\n\t\t * Open-enum tab definitions. When provided with at least one\n\t\t * entry, REPLACES the hard-coded built-in tabs (Files, Notes,\n\t\t * Tags, Tasks, Audit Trail). When unset (the default), the\n\t\t * built-in tabs render as today.\n\t\t *\n\t\t * Each entry shape:\n\t\t * - `id` (string, required) — unique tab id, used for active-tab tracking.\n\t\t * - `label` (string, required) — tab display label (caller-resolved i18n).\n\t\t * - `icon` (string, optional) — MDI icon name resolved via CnIcon.\n\t\t * - `widgets` (array, optional) — list of widget specs `{ type, props? }`\n\t\t * to render inside the tab. Built-in types: `data` → CnObjectDataWidget,\n\t\t * `metadata` → CnObjectMetadataWidget, `audit` / `audit-trail` →\n\t\t * CnAuditTrailTab, `object-table` → CnWidgetObjectTable (a declarative\n\t\t * list scoped to the parent object via `@objectId` / `@object.<field>`\n\t\t * filter tokens). Any other `type` resolves against the customComponents\n\t\t * registry.\n\t\t * - `component` (string, optional) — name resolved against the\n\t\t * customComponents registry. Mutually exclusive with `widgets`\n\t\t * (when both are set, `component` wins and a console.warn is logged).\n\t\t * - `order` (number, optional) — explicit order; defaults to array index + 1.\n\t\t *\n\t\t * @type {Array<{ id: string, label: string, icon?: string, widgets?: Array<{ type: string, props?: object }>, component?: string, order?: number }>|null}\n\t\t */\n\t\ttabs: {\n\t\t\ttype: Array,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/**\n\t\t * Custom-component registry. Keys are names referenced by\n\t\t * `tabs[].component` and unknown `tabs[].widgets[].type` values.\n\t\t * Falls back to the injected `cnCustomComponents` from a\n\t\t * CnAppRoot ancestor when omitted.\n\t\t *\n\t\t * @type {object|null}\n\t\t */\n\t\tcustomComponents: {\n\t\t\ttype: Object,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/**\n\t\t * Externally-requested active tab id. When set to a non-null id,\n\t\t * the sidebar switches to that tab — lets a host deep-link into a\n\t\t * specific leaf (e.g. a \"Linked apps\" row on the detail page that\n\t\t * opens the Mails tab). Leave null for normal internal tracking.\n\t\t *\n\t\t * @spec openspec/changes/case-page-and-list-as-a-place/specs/index-page/spec.md\n\t\t */\n\t\trequestedTab: {\n\t\t\ttype: String,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/**\n\t\t * Called with the tab this sidebar actually settled on, and whether\n\t\t * that was a correction rather than a reader's choice. A host that\n\t\t * keeps the tab in the address uses it to write the address, so the\n\t\t * address always names a tab this reader can actually see.\n\t\t *\n\t\t * @type {(tabId: string, canonicalising: boolean) => void}\n\t\t */\n\t\tonTabChange: {\n\t\t\ttype: Function,\n\t\t\tdefault: null,\n\t\t},\n\t},\n\n\temits: [\n\t\t'update:open',\n\t\t/**\n\t\t * The active tab changed. Payload is `{ tabId, canonicalising }`:\n\t\t * `canonicalising` is true when the sidebar corrected an address\n\t\t * naming a tab that does not exist or that this reader may not see,\n\t\t * rather than the reader choosing one.\n\t\t */\n\t\t'tab-change',\n\t\t/**\n\t\t * Forwarded unchanged from the built-in CnNotesTab after a note with\n\t\t * at least one `@mention` was saved. Payload:\n\t\t * `{ objectId, register, schema, noteId, mentionedUserIds }`.\n\t\t */\n\t\t'mention',\n\t],\n\n\tsetup(props) {\n\t\tconst exposed = {}\n\t\t// Integration registry: on by default via the `useRegistry`\n\t\t// prop (ADR-019). We always wire the composable up so consumers\n\t\t// can toggle `useRegistry` reactively without a remount.\n\t\tconst { integrations: registryIntegrations, resolveWidget, resolveTab } = useIntegrationRegistry()\n\t\texposed.registryIntegrations = registryIntegrations\n\t\texposed.resolveRegistryWidget = resolveWidget\n\t\t// `resolveTab` is local-first (LIB_INTEGRATION_COMPONENTS) so the\n\t\t// dispatched sidebar tab component is bound to this rendering\n\t\t// bundle's Vue — sidesteps the dual-runtime ADR-019 trap that\n\t\t// surfaced as `useNcFormBox(...)` undefined on cross-bundle\n\t\t// registrations. See openregister#1958.\n\t\texposed.resolveRegistryTabComponent = resolveTab\n\n\t\t// Object token context for sidebar-tab widgets that resolve `@objectId` /\n\t\t// `@object.<field>` tokens — the `object-table` built-in in particular\n\t\t// (e.g. a detail page's ZGW relation tab listing a zaak's besluiten,\n\t\t// filtered by `{ zaak: \"@objectId\" }`). Mirrors the reactive\n\t\t// `{ objectId, object, register, schema }` ref CnDetailPage provides.\n\t\t//\n\t\t// Provided ONLY when no ancestor already supplies `cnObjectContext`, so\n\t\t// a CnDetailPage parent's richer context (which carries the loaded\n\t\t// `object` for `@object.<field>`) keeps flowing through to the tab\n\t\t// widgets unchanged. When the sidebar is mounted standalone (no detail\n\t\t// page ancestor) it seeds the context from its own props — enough for\n\t\t// `@objectId` + register/schema resolution.\n\t\tconst parentObjectContext = inject('cnObjectContext', null)\n\t\tif (!parentObjectContext) {\n\t\t\tconst cnObjectContext = ref({\n\t\t\t\tobjectId: props.objectId || null,\n\t\t\t\tobject: null,\n\t\t\t\tregister: props.register || '',\n\t\t\t\tschema: props.schema || '',\n\t\t\t})\n\t\t\tprovide('cnObjectContext', cnObjectContext)\n\t\t\twatch(\n\t\t\t\t() => [props.objectId, props.register, props.schema],\n\t\t\t\t() => {\n\t\t\t\t\tcnObjectContext.value = {\n\t\t\t\t\t\tobjectId: props.objectId || null,\n\t\t\t\t\t\tobject: cnObjectContext.value.object || null,\n\t\t\t\t\t\tregister: props.register || '',\n\t\t\t\t\t\tschema: props.schema || '',\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t)\n\t\t}\n\n\t\t// Auto-subscribe to live updates for the active object. No-op\n\t\t// when `objectStore` is null (no Pinia active) or when the\n\t\t// consumer disabled it via `subscribe: false`. The\n\t\t// composable's reactive `id` argument keeps the subscription\n\t\t// in sync as the user navigates between sidebar objects.\n\t\tif (props.objectStore && props.subscribe) {\n\t\t\tuseObjectSubscription(\n\t\t\t\tprops.objectStore,\n\t\t\t\t() => props.objectType,\n\t\t\t\t() => props.objectId,\n\t\t\t\t{ enabled: () => Boolean(props.objectType && props.objectId) },\n\t\t\t)\n\t\t}\n\t\treturn exposed\n\t},\n\n\tdata() {\n\t\treturn {\n\t\t\tactiveTab: this.requestedTab || this.computeInitialActiveTab(),\n\t\t\t// The tab id already warned about, so an address naming a tab the\n\t\t\t// reader cannot see says so once rather than on every render.\n\t\t\twarnedTabId: null,\n\t\t}\n\t},\n\n\tcomputed: {\n\t\tsidebarTitle() {\n\t\t\treturn this.shown(this.title) || this.objectType || 'Details'\n\t\t},\n\n\t\tsidebarSubtitle() {\n\t\t\treturn this.subtitle || this.subtitleProp || ''\n\t\t},\n\n\t\t/** Whether the consumer has supplied a custom `tabs` array. */\n\t\thasCustomTabs() {\n\t\t\treturn Array.isArray(this.tabs) && this.tabs.length > 0\n\t\t},\n\n\t\t/**\n\t\t * Whether registry mode is active. Custom `tabs` always wins\n\t\t * (with a warning at mount) so consumers don't get a surprise\n\t\t * mode switch.\n\t\t */\n\t\tisRegistryMode() {\n\t\t\treturn this.useRegistry === true && this.hasCustomTabs === false\n\t\t},\n\n\t\t/**\n\t\t * Filtered registry snapshot: drops providers whose id is in\n\t\t * `excludeIntegrations` or `hiddenTabs`. Stays reactive on\n\t\t * the underlying registry's `onChange` notifications.\n\t\t */\n\t\tfilteredRegistryIntegrations() {\n\t\t\tconst excluded = new Set([\n\t\t\t\t...(this.excludeIntegrations || []),\n\t\t\t\t...(this.hiddenTabs || []),\n\t\t\t])\n\t\t\tconst all = this.registryIntegrations || []\n\t\t\treturn all.filter((p) => excluded.has(p.id) === false)\n\t\t},\n\n\t\t/** Effective customComponents registry: prop wins, inject fallback. */\n\t\teffectiveCustomComponents() {\n\t\t\treturn this.customComponents || this.cnCustomComponents || {}\n\t\t},\n\n\t\t/**\n\t\t * Effective v2 component registry (ADR-036). Kind-tagged entries\n\t\t * keyed by component name. Consulted by `resolveTabComponent` so a\n\t\t * tab's `component` ref resolves against the registry as well as the\n\t\t * legacy `customComponents` map.\n\t\t */\n\t\teffectiveRegistry() {\n\t\t\treturn this.cnRegistry || {}\n\t\t},\n\n\t\t/**\n\t\t * Shared object context forwarded to every widget / component\n\t\t * mounted inside a custom tab — same context the built-in tabs\n\t\t * receive today.\n\t\t */\n\t\tsharedTabProps() {\n\t\t\treturn {\n\t\t\t\tobjectId: this.objectId,\n\t\t\t\tobjectType: this.objectType,\n\t\t\t\tregister: this.register,\n\t\t\t\tschema: this.schema,\n\t\t\t\tapiBase: this.apiBase,\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Context forwarded to a mount-mode leaf's `mount(el, props)` for the\n\t\t * single-entity sidebar surface — the same shape an SFC tab receives,\n\t\t * plus the `surface` name and an `integrationContext` bag. Reactive\n\t\t * on the object identity so CnLeafMountHost re-mounts on object change.\n\t\t */\n\t\tsidebarMountProps() {\n\t\t\treturn {\n\t\t\t\t...this.sharedTabProps,\n\t\t\t\tsurface: 'single-entity',\n\t\t\t\tintegrationContext: {\n\t\t\t\t\tregister: this.register,\n\t\t\t\t\tschema: this.schema,\n\t\t\t\t\tobjectId: this.objectId,\n\t\t\t\t},\n\t\t\t}\n\t\t},\n\t},\n\n\twatch: {\n\t\ttabs: {\n\t\t\timmediate: false,\n\t\t\t/**\n\t\t\t * Re-anchor the active tab when the tab set changes, so the\n\t\t\t * active id stays one the reader can actually see.\n\t\t\t *\n\t\t\t * @spec openspec/changes/case-page-and-list-as-a-place/specs/index-page/spec.md\n\t\t\t */\n\t\t\thandler() {\n\t\t\t\t// Re-anchor activeTab when the tab set changes so the\n\t\t\t\t// active id stays valid (otherwise NcAppSidebar shows no\n\t\t\t\t// active tab when the consumer swaps in a fresh array).\n\t\t\t\tthis.settleOnTab(this.requestedTab)\n\t\t\t},\n\t\t},\n\n\t\t/**\n\t\t * Host deep-link: settle on the requested tab when it changes, which\n\t\t * is how an address naming a tab reaches the tab strip.\n\t\t *\n\t\t * @param {string} id The tab asked for.\n\t\t * @spec openspec/changes/case-page-and-list-as-a-place/specs/index-page/spec.md\n\t\t */\n\t\trequestedTab(id) {\n\t\t\tif (id) {\n\t\t\t\tthis.settleOnTab(id)\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * The reader clicked a tab. Reported back so a host keeping the tab\n\t\t * in the address writes it there, which is what makes a tab linkable.\n\t\t *\n\t\t * @param {string} id The tab now active.\n\t\t * @param {string} previous The tab before it.\n\t\t * @spec openspec/changes/case-page-and-list-as-a-place/specs/index-page/spec.md\n\t\t */\n\t\tactiveTab(id, previous) {\n\t\t\tif (id && previous !== undefined && id !== previous && typeof this.onTabChange === 'function') {\n\t\t\t\tthis.onTabChange(id, false)\n\t\t\t}\n\t\t},\n\t},\n\n\t/**\n\t * Settle on a tab on arrival, and warn about a tab set the consumer\n\t * declared two ways.\n\t *\n\t * @spec openspec/changes/case-page-and-list-as-a-place/specs/index-page/spec.md\n\t */\n\tmounted() {\n\t\t// Settle on arrival, so an address carrying no tab is corrected to\n\t\t// its canonical form once rather than staying tabless until the\n\t\t// reader happens to click something (ADR-052).\n\t\tif (typeof this.onTabChange === 'function') {\n\t\t\tthis.settleOnTab(this.requestedTab)\n\t\t}\n\t\tif (this.useRegistry === true && this.hasCustomTabs === true) {\n\t\t\t// eslint-disable-next-line no-console\n\t\t\tconsole.warn('[CnObjectSidebar] `useRegistry` is true but `tabs` is also set — falling back to `tabs` (registry mode ignored). Pass one or the other.')\n\t\t}\n\t},\n\n\tmethods: {\n\n\t\t/**\n\t\t * A manifest label through the injected lookup, or as written.\n\t\t *\n\t\t * @param {string} text The label as written.\n\t\t * @return {string} The label in the user's language.\n\t\t */\n\t\tshown(text) {\n\t\t\treturn typeof this.cnTranslate === 'function' && typeof text === 'string' && text !== '' ? this.cnTranslate(text) : text\n\t\t},\n\n\t\t/**\n\t\t * The `lang` of a label that fell back to its written text in another language.\n\t\t *\n\t\t * @param {string} text The label as written.\n\t\t * @return {string|undefined} The source language, or undefined.\n\t\t */\n\t\tlangOf(text) {\n\t\t\treturn labelLang(this.cnTranslate, text) || undefined\n\t\t},\n\n\t\tisTabHidden(tabId) {\n\t\t\treturn this.hiddenTabs.includes(tabId)\n\t\t},\n\n\t\t/**\n\t\t * Resolve a registry provider's tab component, preferring the\n\t\t * LOCAL lib-owned component (rendering-bundle Vue) over the\n\t\t * shared registry's stored object. Falls back to the stored\n\t\t * `provider.tab` for consumer-custom ids (which live in the\n\t\t * consumer's own bundle and therefore render under the same\n\t\t * Vue instance with no mismatch). See openregister#1958.\n\t\t *\n\t\t * @param {object} provider Normalised registry entry.\n\t\t * @return {object|null} Vue component, or null.\n\t\t */\n\t\tresolveRegistryTab(provider) {\n\t\t\tif (!provider || typeof provider.id !== 'string') {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tconst local = this.resolveRegistryTabComponent(provider.id)\n\t\t\tif (local) {\n\t\t\t\treturn local\n\t\t\t}\n\t\t\treturn provider.tab || null\n\t\t},\n\n\t\t/**\n\t\t * Whether a registry provider renders via the mount hand-off\n\t\t * (`renderMode: 'mount'`, openregister#2127) rather than an SFC tab.\n\t\t * Mount-mode leaves carry `mount`/`unmount` functions the host calls\n\t\t * against a bare element via CnLeafMountHost.\n\t\t *\n\t\t * @param {object} provider Normalised registry entry.\n\t\t * @return {boolean} true when the provider is mount-mode.\n\t\t */\n\t\tisMountProvider(provider) {\n\t\t\treturn Boolean(provider)\n\t\t\t\t&& provider.renderMode === 'mount'\n\t\t\t\t&& typeof provider.mount === 'function'\n\t\t\t\t&& typeof provider.unmount === 'function'\n\t\t},\n\n\t\t/**\n\t\t * Pick a sensible default active tab on mount and on tabs[]\n\t\t * changes. When custom tabs are present, the first entry wins.\n\t\t * When unset, the built-in `files` tab is the default (matches\n\t\t * the legacy behavior).\n\t\t */\n\t\tcomputeInitialActiveTab() {\n\t\t\tif (Array.isArray(this.tabs) && this.tabs.length > 0) {\n\t\t\t\treturn this.tabs[0].id\n\t\t\t}\n\t\t\treturn 'files'\n\t\t},\n\n\t\t/**\n\t\t * The tab ids this reader can actually see, in the order shown.\n\t\t *\n\t\t * Three tab sources, one answer. Without this the address could name\n\t\t * a tab that is hidden, excluded or simply not registered, and the\n\t\t * sidebar would show its first tab while the address went on claiming\n\t\t * a different one.\n\t\t *\n\t\t * @return {Array<string>} The visible tab ids.\n\t\t * @spec openspec/changes/case-page-and-list-as-a-place/specs/index-page/spec.md\n\t\t */\n\t\tvisibleTabIds() {\n\t\t\tif (this.isRegistryMode) {\n\t\t\t\treturn (this.filteredRegistryIntegrations || []).map((p) => p.id)\n\t\t\t}\n\t\t\tif (Array.isArray(this.tabs) && this.tabs.length > 0) {\n\t\t\t\treturn this.tabs.filter((tab) => tab && !this.isTabHidden(tab.id)).map((tab) => tab.id)\n\t\t\t}\n\t\t\treturn ['files', 'notes', 'tags', 'tasks', 'auditTrail'].filter((id) => !this.isTabHidden(id))\n\t\t},\n\n\t\t/**\n\t\t * Settle on a tab, and say whether the address had to be corrected.\n\t\t *\n\t\t * An address naming a tab that does not exist, or one this reader may\n\t\t * not see, falls back to the first tab they can see and says so ONCE.\n\t\t * Silently showing a different tab than the address names is the\n\t\t * failure here: the reader then sends a colleague a link that opens\n\t\t * somewhere else again.\n\t\t *\n\t\t * @param {string|null} requested The tab the address asked for.\n\t\t * @return {{ tabId: string, canonicalising: boolean }} The tab to show.\n\t\t * @spec openspec/changes/case-page-and-list-as-a-place/specs/index-page/spec.md\n\t\t */\n\t\tresolveTabRequest(requested) {\n\t\t\tconst visible = this.visibleTabIds\n\t\t\tconst fallback = visible[0] || this.computeInitialActiveTab()\n\t\t\tif (!requested) {\n\t\t\t\treturn { tabId: fallback, canonicalising: true }\n\t\t\t}\n\t\t\tif (visible.length === 0 || visible.includes(requested)) {\n\t\t\t\treturn { tabId: requested, canonicalising: false }\n\t\t\t}\n\t\t\tif (this.warnedTabId !== requested) {\n\t\t\t\tthis.warnedTabId = requested\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.warn(`[CnObjectSidebar] The address asks for the \"${requested}\" tab, which is not available here. Showing \"${fallback}\" instead.`)\n\t\t\t}\n\t\t\treturn { tabId: fallback, canonicalising: true }\n\t\t},\n\n\t\t/**\n\t\t * Show a tab and tell the host, so the address can follow.\n\t\t *\n\t\t * @param {string|null} requested The tab asked for.\n\t\t * @spec openspec/changes/case-page-and-list-as-a-place/specs/index-page/spec.md\n\t\t */\n\t\tsettleOnTab(requested) {\n\t\t\tconst { tabId, canonicalising } = this.resolveTabRequest(requested)\n\t\t\tthis.activeTab = tabId\n\t\t\tif (typeof this.onTabChange === 'function') {\n\t\t\t\tthis.onTabChange(tabId, canonicalising)\n\t\t\t}\n\t\t\t/**\n\t\t\t * @event tab-change Emitted when the active tab settles, including when the sidebar corrected the address.\n\t\t\t * @type {{ tabId: string, canonicalising: boolean }}\n\t\t\t */\n\t\t\tthis.$emit('tab-change', { tabId, canonicalising })\n\t\t},\n\n\t\t/**\n\t\t * Build the prop bag for a widget in the `widgets[]` tab path. All\n\t\t * widgets get the shared coordinate context plus the loaded object\n\t\t * (`objectData`); the prop-driven `data` built-in also gets the schema\n\t\t * OBJECT bound to its `schema` prop (the other tabs use the `schema`\n\t\t * slug string, so the override is scoped to `type: 'data'`). Of a\n\t\t * widget's own `props`, the ones its component declares win on overlap;\n\t\t * an undeclared one would only fall through onto the component's root.\n\t\t *\n\t\t * @spec openspec/changes/declared-props-detail-index-sidebar/specs/widget-hosts/spec.md#requirement-a-widget-host-passes-only-the-keys-a-widget-declares\n\t\t * @param {{ type: string, props?: object }} w Widget spec\n\t\t * @return {object} Props to v-bind onto the resolved widget component\n\t\t */\n\t\twidgetBindings(w) {\n\t\t\tconst bindings = { ...this.sharedTabProps, objectData: this.objectData }\n\t\t\tif (w.type === 'data') {\n\t\t\t\t// CnObjectDataWidget wants the schema OBJECT, never the slug the\n\t\t\t\t// other tabs use. Pass the resolved object (null until it loads —\n\t\t\t\t// the widget renders its empty state meanwhile) so it never sees\n\t\t\t\t// a String `schema`.\n\t\t\t\tbindings.schema = this.objectSchema\n\t\t\t}\n\t\t\treturn { ...bindings, ...pickDeclaredProps(this.resolveWidgetComponent(w.type), w.props || {}, w.type || '') }\n\t\t},\n\n\t\t/**\n\t\t * Resolve a widget type to a component. Built-in types (`data`,\n\t\t * `metadata`, `audit` / `audit-trail`, `object-table`) map to their\n\t\t * lib component; any other type resolves against the v2 registry, then\n\t\t * the legacy customComponents map. Logs a console.warn and returns null when nothing\n\t\t * resolves.\n\t\t *\n\t\t * @param {string} type Widget type identifier\n\t\t * @return {object|null} Vue component, or null when unresolved\n\t\t */\n\t\tresolveWidgetComponent(type) {\n\t\t\tif (BUILTIN_WIDGETS[type]) {\n\t\t\t\treturn BUILTIN_WIDGETS[type]\n\t\t\t}\n\t\t\tconst registryEntry = this.effectiveRegistry[type]\n\t\t\tif (registryEntry && registryEntry.component) {\n\t\t\t\treturn registryEntry.component\n\t\t\t}\n\t\t\tconst reg = this.effectiveCustomComponents\n\t\t\tif (reg && reg[type]) {\n\t\t\t\treturn reg[type]\n\t\t\t}\n\t\t\t// eslint-disable-next-line no-console\n\t\t\tconsole.warn(`[CnObjectSidebar] Unknown widget type \"${type}\" — not in built-ins (data, metadata, audit, audit-trail, object-table, object-permissions), the registry or customComponents.`)\n\t\t\treturn null\n\t\t},\n\n\t\t/**\n\t\t * Resolve a tab's `component` registry name. Logs a\n\t\t * console.warn when both `widgets` and `component` are set\n\t\t * (component wins) or when the registry name is missing.\n\t\t *\n\t\t * @param {object} tab Tab definition\n\t\t * @return {object|null} Vue component, or null when unresolved\n\t\t */\n\t\tresolveTabComponent(tab) {\n\t\t\tif (tab.widgets && tab.widgets.length > 0) {\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.warn(`[CnObjectSidebar] Tab \"${tab.id}\" declares both widgets[] and component — component wins, widgets are ignored.`)\n\t\t\t}\n\t\t\t// v2 registry first (ADR-036): any kind-tagged entry with a\n\t\t\t// `component` field is acceptable for a slot/tab lookup — this\n\t\t\t// is what lets a `kind: 'page'` tab component (the procest\n\t\t\t// pattern) render. Fall back to the legacy customComponents map.\n\t\t\tconst registryEntry = this.effectiveRegistry[tab.component]\n\t\t\tif (registryEntry && registryEntry.component) {\n\t\t\t\treturn registryEntry.component\n\t\t\t}\n\t\t\tconst reg = this.effectiveCustomComponents\n\t\t\tconst resolved = reg && reg[tab.component]\n\t\t\tif (!resolved) {\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.warn(`[CnObjectSidebar] Tab \"${tab.id}\" component \"${tab.component}\" not found in registry or customComponents.`)\n\t\t\t\treturn null\n\t\t\t}\n\t\t\treturn resolved\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n/* NcAppSidebar lays every tab out as an equal share of the sidebar width\n * (`flex: 1 1`) with an ellipsis caption, so an object with many tabs — e.g. a\n * lead's 5+ tabs — shrinks them until the labels truncate. Keep the tabs\n * equal-width (uniform) but stop them shrinking below a readable minimum, and\n * let the strip scroll horizontally once they no longer fit. `flex-basis: 0`\n * + equal grow keeps every tab the same width whether the row fits or scrolls.\n * Apps with longer labels can widen the floor via --cn-sidebar-tab-min-width. */\n:deep(.app-sidebar-tabs__nav) {\n\toverflow-x: auto;\n}\n\n:deep(.app-sidebar-tabs__nav .app-sidebar-tabs__tab) {\n\tflex-grow: 1;\n\tflex-shrink: 0;\n\tflex-basis: 0;\n\t/* !important to beat NcAppSidebar's own min-width on the button variant. */\n\tmin-width: var(--cn-sidebar-tab-min-width, 7rem) !important;\n}\n</style>\n"],"names":["CnAiFeaturesWidget","CnObjectDataWidget","CnObjectMetadataWidget","CnAuditTrailTab","CnWidgetObjectTable","CnObjectPermissionsTab","CnFilesTab","CnNotesTab","CnTagsTab","CnTasksTab","CnIcon","CnLeafMountHost","t"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"CnObjectSidebar.vue3.js","sources":["../../../../src/components/CnObjectSidebar/CnObjectSidebar.vue?vue&type=template&id=09402703&lang.js"],"sourcesContent":["<!--\n CnObjectSidebar — Right sidebar with standardized tabs for generic object functionality.\n\n Provides Files, Notes, Tags, Tasks, and Audit Trail tabs that integrate with\n OpenRegister API endpoints (which bridge to Nextcloud-native APIs).\n All tabs are optional and overridable via props and slots.\n-->\n<template>\n\t<!-- `subname` is NcAppSidebar's visible secondary line; `subtitle` is only\n\t the tooltip on it, and the line is not rendered at all while subname is\n\t empty — so passing subtitle alone showed nothing. Same pair as\n\t name/title, and as CnIndexSidebar. -->\n\t<NcAppSidebar\n\t\tv-model:active=\"activeTab\"\n\t\t:name=\"sidebarTitle\"\n\t\t:title=\"sidebarTitle\"\n\t\t:subname=\"sidebarSubtitle\"\n\t\t:subtitle=\"sidebarSubtitle\"\n\t\t:open=\"open\"\n\t\tdata-testid=\"cn-object-sidebar\"\n\t\t@update:open=\"$emit('update:open', $event)\"\n\t\t@close=\"$emit('update:open', false)\">\n\t\t<!-- REGISTRY BRANCH: pluggable integration registry-driven.\n\t\t Renders one tab per provider registered on\n\t\t `window.OCA.OpenRegister.integrations`. `hiddenTabs` /\n\t\t `excludeIntegrations` filter the set; the `#extra-tabs`\n\t\t slot still appends consumer-supplied tabs. Per-integration\n\t\t slot overrides aren't supported in registry mode — apps\n\t\t that need to override a built-in tab should register their\n\t\t own provider with the same id (collision policy: first\n\t\t wins) before OpenRegister's bundle loads. -->\n\t\t<template v-if=\"isRegistryMode\">\n\t\t\t<NcAppSidebarTab\n\t\t\t\tv-for=\"(provider, idx) in filteredRegistryIntegrations\"\n\t\t\t\t:id=\"provider.id\"\n\t\t\t\t:key=\"provider.id\"\n\t\t\t\t:name=\"provider.label\"\n\t\t\t\t:order=\"provider.order != null ? provider.order : idx + 1\"\n\t\t\t\t:data-testid=\"`cn-object-sidebar-tab-${provider.id}`\">\n\t\t\t\t<template #icon>\n\t\t\t\t\t<CnIcon v-if=\"provider.icon\" :name=\"provider.icon\" :size=\"20\" />\n\t\t\t\t</template>\n\t\t\t\t<!-- MOUNT BRANCH (openregister#2127): a `renderMode: 'mount'`\n\t\t\t\t leaf renders through CnLeafMountHost — a bare host-owned\n\t\t\t\t element the leaf mounts its own framework into. Mounted\n\t\t\t\t lazily when the tab is active; unmounted on hide/teardown. -->\n\t\t\t\t<CnLeafMountHost\n\t\t\t\t\tv-if=\"isMountProvider(provider)\"\n\t\t\t\t\t:provider=\"provider\"\n\t\t\t\t\t:active=\"activeTab === provider.id\"\n\t\t\t\t\t:mountProps=\"sidebarMountProps\" />\n\t\t\t\t<component\n\t\t\t\t\t:is=\"resolveRegistryTab(provider)\"\n\t\t\t\t\tv-else\n\t\t\t\t\tv-bind=\"sharedTabProps\" />\n\t\t\t</NcAppSidebarTab>\n\t\t\t<slot name=\"extra-tabs\" />\n\t\t</template>\n\n\t\t<!-- BACKWARDS-COMPATIBLE BRANCH: hard-coded built-in tabs.\n\t\t Used when no custom `tabs` prop is provided and the\n\t\t registry mode is not active. The slot overrides\n\t\t (#tab-files etc.) and `hiddenTabs` filtering remain\n\t\t unchanged. -->\n\t\t<template v-else-if=\"!hasCustomTabs\">\n\t\t\t<!-- Files Tab -->\n\t\t\t<NcAppSidebarTab\n\t\t\t\tv-if=\"!isTabHidden('files')\"\n\t\t\t\tid=\"files\"\n\t\t\t\t:name=\"filesLabel\"\n\t\t\t\t:order=\"1\"\n\t\t\t\tdata-testid=\"cn-object-sidebar-tab-files\">\n\t\t\t\t<template #icon>\n\t\t\t\t\t<Paperclip :size=\"20\" />\n\t\t\t\t</template>\n\t\t\t\t<slot name=\"tab-files\" :objectId=\"objectId\" :objectType=\"objectType\">\n\t\t\t\t\t<CnFilesTab\n\t\t\t\t\t\t:objectId=\"objectId\"\n\t\t\t\t\t\t:register=\"register\"\n\t\t\t\t\t\t:schema=\"schema\"\n\t\t\t\t\t\t:apiBase=\"apiBase\" />\n\t\t\t\t</slot>\n\t\t\t</NcAppSidebarTab>\n\n\t\t\t<!-- Notes Tab -->\n\t\t\t<NcAppSidebarTab\n\t\t\t\tv-if=\"!isTabHidden('notes')\"\n\t\t\t\tid=\"notes\"\n\t\t\t\t:name=\"notesLabel\"\n\t\t\t\t:order=\"2\"\n\t\t\t\tdata-testid=\"cn-object-sidebar-tab-notes\">\n\t\t\t\t<template #icon>\n\t\t\t\t\t<CommentTextOutline :size=\"20\" />\n\t\t\t\t</template>\n\t\t\t\t<slot name=\"tab-notes\" :objectId=\"objectId\" :objectType=\"objectType\">\n\t\t\t\t\t<!-- The `mention` passthrough is the notification hook: apps\n\t\t\t\t\t mounting the full sidebar receive the mentioned user ids\n\t\t\t\t\t and dispatch NC notifications from their own backend. -->\n\t\t\t\t\t<CnNotesTab\n\t\t\t\t\t\t:objectId=\"objectId\"\n\t\t\t\t\t\t:register=\"register\"\n\t\t\t\t\t\t:schema=\"schema\"\n\t\t\t\t\t\t:apiBase=\"apiBase\"\n\t\t\t\t\t\t@mention=\"$emit('mention', $event)\" />\n\t\t\t\t</slot>\n\t\t\t</NcAppSidebarTab>\n\n\t\t\t<!-- Tags Tab -->\n\t\t\t<NcAppSidebarTab\n\t\t\t\tv-if=\"!isTabHidden('tags')\"\n\t\t\t\tid=\"tags\"\n\t\t\t\t:name=\"tagsLabel\"\n\t\t\t\t:order=\"3\"\n\t\t\t\tdata-testid=\"cn-object-sidebar-tab-tags\">\n\t\t\t\t<template #icon>\n\t\t\t\t\t<TagOutline :size=\"20\" />\n\t\t\t\t</template>\n\t\t\t\t<slot name=\"tab-tags\" :objectId=\"objectId\" :objectType=\"objectType\">\n\t\t\t\t\t<CnTagsTab\n\t\t\t\t\t\t:objectId=\"objectId\"\n\t\t\t\t\t\t:register=\"register\"\n\t\t\t\t\t\t:schema=\"schema\"\n\t\t\t\t\t\t:apiBase=\"apiBase\" />\n\t\t\t\t</slot>\n\t\t\t</NcAppSidebarTab>\n\n\t\t\t<!-- Tasks Tab -->\n\t\t\t<NcAppSidebarTab\n\t\t\t\tv-if=\"!isTabHidden('tasks')\"\n\t\t\t\tid=\"tasks\"\n\t\t\t\t:name=\"tasksLabel\"\n\t\t\t\t:order=\"4\"\n\t\t\t\tdata-testid=\"cn-object-sidebar-tab-tasks\">\n\t\t\t\t<template #icon>\n\t\t\t\t\t<CheckboxMarkedOutline :size=\"20\" />\n\t\t\t\t</template>\n\t\t\t\t<slot name=\"tab-tasks\" :objectId=\"objectId\" :objectType=\"objectType\">\n\t\t\t\t\t<CnTasksTab\n\t\t\t\t\t\t:objectId=\"objectId\"\n\t\t\t\t\t\t:register=\"register\"\n\t\t\t\t\t\t:schema=\"schema\"\n\t\t\t\t\t\t:apiBase=\"apiBase\"\n\t\t\t\t\t\t:source=\"tasksSource\" />\n\t\t\t\t</slot>\n\t\t\t</NcAppSidebarTab>\n\n\t\t\t<!-- Audit Trail Tab -->\n\t\t\t<NcAppSidebarTab\n\t\t\t\tv-if=\"!isTabHidden('auditTrail')\"\n\t\t\t\tid=\"auditTrail\"\n\t\t\t\t:name=\"auditTrailLabel\"\n\t\t\t\t:order=\"5\"\n\t\t\t\tdata-testid=\"cn-object-sidebar-tab-audit-trail\">\n\t\t\t\t<template #icon>\n\t\t\t\t\t<History :size=\"20\" />\n\t\t\t\t</template>\n\t\t\t\t<slot name=\"tab-audit-trail\" :objectId=\"objectId\" :objectType=\"objectType\">\n\t\t\t\t\t<CnAuditTrailTab\n\t\t\t\t\t\t:objectId=\"objectId\"\n\t\t\t\t\t\t:register=\"register\"\n\t\t\t\t\t\t:schema=\"schema\"\n\t\t\t\t\t\t:apiBase=\"apiBase\" />\n\t\t\t\t</slot>\n\t\t\t</NcAppSidebarTab>\n\n\t\t\t<!-- Custom tabs slot (only relevant in legacy mode) -->\n\t\t\t<slot name=\"extra-tabs\" />\n\t\t</template>\n\n\t\t<!-- OPEN-ENUM BRANCH: render the consumer-supplied `tabs` array.\n\t\t Each tab declares its content via `widgets` (resolved against\n\t\t the built-in widget registry — `data` → CnObjectDataWidget,\n\t\t `metadata` → CnObjectMetadataWidget, `audit`/`audit-trail` →\n\t\t CnAuditTrailTab, `object-table` → CnWidgetObjectTable — with the\n\t\t customComponents registry as the escape hatch) OR `component`\n\t\t (resolved against the customComponents registry directly). -->\n\t\t<template v-else>\n\t\t\t<NcAppSidebarTab\n\t\t\t\tv-for=\"(tab, idx) in tabs\"\n\t\t\t\t:id=\"tab.id\"\n\t\t\t\t:key=\"tab.id\"\n\t\t\t\t:name=\"shown(tab.label)\"\n\t\t\t\t:lang=\"langOf(tab.label)\"\n\t\t\t\t:order=\"tab.order != null ? tab.order : idx + 1\"\n\t\t\t\t:data-testid=\"`cn-object-sidebar-tab-${tab.id}`\">\n\t\t\t\t<template v-if=\"tab.icon\" #icon>\n\t\t\t\t\t<CnIcon :name=\"tab.icon\" :size=\"20\" />\n\t\t\t\t</template>\n\n\t\t\t\t<!-- Component-registry escape hatch wins when `component` is set\n\t\t\t\t (with a console.warn at mount time when widgets is also set). -->\n\t\t\t\t<component\n\t\t\t\t\t:is=\"resolveTabComponent(tab)\"\n\t\t\t\t\tv-if=\"tab.component\"\n\t\t\t\t\tv-bind=\"sharedTabProps\" />\n\n\t\t\t\t<!-- Widget array path. Each widget receives the shared object\n\t\t\t\t context plus its own `props` via `widgetBindings` (which also\n\t\t\t\t hands the prop-driven `data` / `metadata` built-ins the loaded\n\t\t\t\t object and schema); per-widget props win on overlap. -->\n\t\t\t\t<div v-else class=\"cn-object-sidebar__tab-widgets\">\n\t\t\t\t\t<template v-for=\"(w, wIdx) in tab.widgets || []\">\n\t\t\t\t\t\t<component\n\t\t\t\t\t\t\t:is=\"resolveWidgetComponent(w.type)\"\n\t\t\t\t\t\t\tv-if=\"resolveWidgetComponent(w.type)\"\n\t\t\t\t\t\t\t:key=\"wIdx\"\n\t\t\t\t\t\t\tv-bind=\"widgetBindings(w)\" />\n\t\t\t\t\t</template>\n\t\t\t\t</div>\n\t\t\t</NcAppSidebarTab>\n\t\t</template>\n\t</NcAppSidebar>\n</template>\n\n<script>\nimport { translate as t } from '@nextcloud/l10n'\nimport { NcAppSidebar, NcAppSidebarTab } from '@nextcloud/vue'\nimport { inject, provide, ref, watch } from 'vue'\nimport CheckboxMarkedOutline from 'vue-material-design-icons/CheckboxMarkedOutline.vue'\nimport CommentTextOutline from 'vue-material-design-icons/CommentTextOutline.vue'\nimport History from 'vue-material-design-icons/History.vue'\nimport Paperclip from 'vue-material-design-icons/Paperclip.vue'\nimport TagOutline from 'vue-material-design-icons/TagOutline.vue'\nimport CnWidgetObjectTable from '../CnWidgetObjectTable/CnWidgetObjectTable.vue'\nimport CnAuditTrailTab from './CnAuditTrailTab.vue'\nimport CnFilesTab from './CnFilesTab.vue'\nimport CnNotesTab from './CnNotesTab.vue'\nimport CnTagsTab from './CnTagsTab.vue'\nimport CnTasksTab from './CnTasksTab.vue'\nimport { useIntegrationRegistry } from '../../composables/useIntegrationRegistry.js'\nimport { useObjectSubscription } from '../../composables/useObjectSubscription.js'\nimport { pickDeclaredProps } from '../../utils/declaredProps.js'\nimport { labelLang } from '../../utils/manifestTranslate.js'\nimport { CnIcon } from '../CnIcon/index.js'\nimport { CnLeafMountHost } from '../CnLeafMountHost/index.js'\nimport { CnObjectDataWidget } from '../CnObjectDataWidget/index.js'\nimport { CnObjectMetadataWidget } from '../CnObjectMetadataWidget/index.js'\n\n/**\n * Built-in widget registry used by the open-enum `tabs` prop.\n * - `data` → CnObjectDataWidget (schema-driven editable grid)\n * - `metadata` → CnObjectMetadataWidget (read-only system metadata)\n * - `audit` → CnAuditTrailTab (the object's change log / audit trail)\n * - `object-table` → CnWidgetObjectTable (a declarative list scoped to the\n * parent object — the full source / endpointSource / columns / actions\n * contract). Resolves `@objectId` / `@object.<field>` filter tokens against\n * the object context this sidebar `provide`s (see setup), so a detail\n * page's ZGW-style relation tab (e.g. a zaak's besluiten, filtered by\n * `{ zaak: \"@objectId\" }`) renders as a sidebar tab with no bespoke code.\n *\n * Any `widgets[].type` value not in this map falls back to the\n * customComponents registry (prop, then injected `cnCustomComponents`).\n */\nconst BUILTIN_WIDGETS = {\n\tdata: CnObjectDataWidget,\n\tmetadata: CnObjectMetadataWidget,\n\taudit: CnAuditTrailTab,\n\t// Alias matching the dashboard/detail-page widget key `audit-trail` so a\n\t// manifest can declare a sidebar tab with `widgets: [{ type: 'audit-trail' }]`\n\t// (the same key it uses for the detail-page body widget) and get the object's\n\t// change log as a proper sidebar tab.\n\t'audit-trail': CnAuditTrailTab,\n\t// The declarative list widget (same key as the detail-page body widget), so\n\t// a sidebar tab can render a related-object list scoped to the parent\n\t// object via `@objectId` / `@object.<field>` tokens in its `source.filter`.\n\t'object-table': CnWidgetObjectTable,\n}\n\n/**\n * CnObjectSidebar — Right sidebar for entity detail pages.\n *\n * Provides standardized tabs for generic object functionality (Files, Notes, Tags,\n * Tasks, Audit Trail) that integrate with OpenRegister API endpoints bridging to\n * Nextcloud-native APIs. Each tab is a self-contained component.\n *\n * Basic usage\n * ```vue\n * <CnObjectSidebar\n * object-type=\"pipelinq_lead\"\n * :object-id=\"leadId\"\n * :register=\"registerConfig.register\"\n * :schema=\"registerConfig.schema\" />\n * ```\n *\n * Hide specific tabs\n * ```vue\n * <CnObjectSidebar\n * object-type=\"pipelinq_lead\"\n * :object-id=\"leadId\"\n * :hidden-tabs=\"['tasks', 'tags']\" />\n * ```\n *\n * Override a tab\n * ```vue\n * <CnObjectSidebar object-type=\"pipelinq_lead\" :object-id=\"leadId\">\n * <template #tab-notes=\"{ objectId }\">\n * <MyCustomNotesComponent :id=\"objectId\" />\n * </template>\n * </CnObjectSidebar>\n * ```\n */\nexport default {\n\tname: 'CnObjectSidebar',\n\n\tcomponents: {\n\t\tNcAppSidebar,\n\t\tNcAppSidebarTab,\n\t\tPaperclip,\n\t\tCommentTextOutline,\n\t\tTagOutline,\n\t\tCheckboxMarkedOutline,\n\t\tHistory,\n\t\tCnFilesTab,\n\t\tCnNotesTab,\n\t\tCnTagsTab,\n\t\tCnTasksTab,\n\t\tCnAuditTrailTab,\n\t\tCnIcon,\n\t\tCnLeafMountHost,\n\t},\n\n\tinject: {\n\t\tcnCustomComponents: { default: () => ({}) },\n\t\t// v2 component registry (ADR-036). Kind-tagged entries\n\t\t// ({ kind, component }); a sidebar tab's `component` ref resolves\n\t\t// against this first so apps that migrated their tab components to\n\t\t// the registry (e.g. as `kind: 'page'`) still render. Empty default\n\t\t// keeps the legacy `customComponents`-only path unchanged.\n\t\tcnRegistry: { default: () => ({}) },\n\t\t// The label lookup from CnAppRoot, so tab labels and the title show in the user's language.\n\t\tcnTranslate: { default: null },\n\t},\n\n\tprops: {\n\t\t/** The entity type (e.g., \"pipelinq_lead\", \"procest_case\") */\n\t\tobjectType: {\n\t\t\ttype: String,\n\t\t\trequired: true,\n\t\t},\n\n\t\t/** The object UUID */\n\t\tobjectId: {\n\t\t\ttype: String,\n\t\t\trequired: true,\n\t\t},\n\n\t\t/** OpenRegister register ID */\n\t\tregister: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/** OpenRegister schema ID */\n\t\tschema: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/**\n\t\t * The loaded object, forwarded to prop-driven sidebar-tab widgets\n\t\t * (the `data` / `metadata` built-ins) as `objectData`. The sidebar is\n\t\t * otherwise coordinate-based — most tabs self-fetch from\n\t\t * `objectId`/`register`/`schema` — so this is null unless a host (e.g.\n\t\t * CnDetailPage via CnAppRoot) publishes the loaded object.\n\t\t *\n\t\t * @type {object|null}\n\t\t */\n\t\tobjectData: {\n\t\t\ttype: Object,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/**\n\t\t * The resolved JSON Schema OBJECT (with a `properties` field), forwarded\n\t\t * to the `data` built-in tab widget (CnObjectDataWidget), which needs the\n\t\t * schema definition rather than the `schema` slug string. Null unless a\n\t\t * host (e.g. CnDetailPage via CnAppRoot) publishes it.\n\t\t *\n\t\t * @type {object|null}\n\t\t */\n\t\tobjectSchema: {\n\t\t\ttype: Object,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/** Array of tab IDs to hide: 'files', 'notes', 'tags', 'tasks', 'auditTrail' */\n\t\thiddenTabs: {\n\t\t\ttype: Array,\n\t\t\tdefault: () => [],\n\t\t},\n\n\t\t/**\n\t\t * Use the pluggable integration registry to drive the sidebar\n\t\t * tabs. Defaults to `true` (ADR-019): tabs are rendered one per\n\t\t * provider registered on `window.OCA.OpenRegister.integrations`\n\t\t * (and via `useIntegrationRegistry()`). The canonical five\n\t\t * built-ins — files / notes / tags / tasks / audit-trail — are\n\t\t * shipped as providers in `builtinIntegrations` and registered by\n\t\t * OpenRegister's bootstrap (`registerBuiltinIntegrations()`), so\n\t\t * the default surface is unchanged for apps that register them.\n\t\t *\n\t\t * Set `false` to opt back into the legacy hardcoded-tabs path,\n\t\t * which renders the five built-in tabs directly from this\n\t\t * component and supports the `#tab-<id>` slot overrides. Use this\n\t\t * for consumers that do not call `registerBuiltinIntegrations()`\n\t\t * and want the built-in tabs without standing up the registry.\n\t\t *\n\t\t * `hiddenTabs` / `excludeIntegrations` and the `#extra-tabs` slot\n\t\t * apply in both modes.\n\t\t *\n\t\t * Mutually exclusive with the open-enum `tabs` prop — when both\n\t\t * are set, `tabs` wins and a console.warn is logged.\n\t\t *\n\t\t * @type {boolean}\n\t\t */\n\t\tuseRegistry: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: true,\n\t\t},\n\n\t\t/**\n\t\t * Integration ids to exclude when rendering registry-driven\n\t\t * tabs. Mirrors `hiddenTabs` for the legacy mode.\n\t\t *\n\t\t * @type {string[]}\n\t\t */\n\t\texcludeIntegrations: {\n\t\t\ttype: Array,\n\t\t\tdefault: () => [],\n\t\t},\n\n\t\t/** Whether the sidebar is open */\n\t\topen: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: true,\n\t\t},\n\n\t\t/** Sidebar title (defaults to objectType) */\n\t\ttitle: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/** Sidebar subtitle */\n\t\tsubtitle: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/** @deprecated Use `subtitle` instead. Alias kept for backwards compatibility. */\n\t\tsubtitleProp: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/** Base API URL for OpenRegister */\n\t\tapiBase: {\n\t\t\ttype: String,\n\t\t\tdefault: '/apps/openregister/api',\n\t\t},\n\n\t\t/**\n\t\t * Whether to auto-subscribe to live updates for the\n\t\t * current object. Defaults to true. The sidebar calls\n\t\t * `objectStore.subscribe(objectType, objectId)` on mount and\n\t\t * unsubscribes on unmount via `tryOnScopeDispose`.\n\t\t *\n\t\t * @type {boolean}\n\t\t */\n\t\tsubscribe: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: true,\n\t\t},\n\n\t\t/**\n\t\t * Optional explicit Pinia store instance. When omitted,\n\t\t * the sidebar skips auto-subscribe (Pinia not yet active\n\t\t * in the consumer context).\n\t\t *\n\t\t * @type {object|null}\n\t\t */\n\t\tobjectStore: {\n\t\t\ttype: Object,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t// --- Pre-translated labels ---\n\t\t/** Label for the Files tab */\n\t\tfilesLabel: { type: String, default: () => t('nextcloud-vue', 'Files') },\n\t\t/** Label for the Notes tab */\n\t\tnotesLabel: { type: String, default: () => t('nextcloud-vue', 'Notes') },\n\t\t/** Label for the Tags tab */\n\t\ttagsLabel: { type: String, default: () => t('nextcloud-vue', 'Tags') },\n\t\t/** Label for the Tasks tab */\n\t\ttasksLabel: { type: String, default: () => t('nextcloud-vue', 'Tasks') },\n\t\t/**\n\t\t * Source of the Tasks tab: `vtodo` (default, the record's linked Nextcloud\n\t\t * tasks) or `flow-tasks` (the OpenRegister flow tasks anchored on the\n\t\t * record, with create and per-row verbs). Passed to `CnTasksTab`.\n\t\t *\n\t\t * @type {'vtodo'|'flow-tasks'}\n\t\t */\n\t\ttasksSource: { type: String, default: 'vtodo', validator: (v) => ['vtodo', 'flow-tasks'].includes(v) },\n\t\t/** Label for the Audit Trail tab */\n\t\tauditTrailLabel: { type: String, default: () => t('nextcloud-vue', 'Audit trail') },\n\n\t\t/**\n\t\t * Open-enum tab definitions. When provided with at least one\n\t\t * entry, REPLACES the hard-coded built-in tabs (Files, Notes,\n\t\t * Tags, Tasks, Audit Trail). When unset (the default), the\n\t\t * built-in tabs render as today.\n\t\t *\n\t\t * Each entry shape:\n\t\t * - `id` (string, required) — unique tab id, used for active-tab tracking.\n\t\t * - `label` (string, required) — tab display label (caller-resolved i18n).\n\t\t * - `icon` (string, optional) — MDI icon name resolved via CnIcon.\n\t\t * - `widgets` (array, optional) — list of widget specs `{ type, props? }`\n\t\t * to render inside the tab. Built-in types: `data` → CnObjectDataWidget,\n\t\t * `metadata` → CnObjectMetadataWidget, `audit` / `audit-trail` →\n\t\t * CnAuditTrailTab, `object-table` → CnWidgetObjectTable (a declarative\n\t\t * list scoped to the parent object via `@objectId` / `@object.<field>`\n\t\t * filter tokens). Any other `type` resolves against the customComponents\n\t\t * registry.\n\t\t * - `component` (string, optional) — name resolved against the\n\t\t * customComponents registry. Mutually exclusive with `widgets`\n\t\t * (when both are set, `component` wins and a console.warn is logged).\n\t\t * - `order` (number, optional) — explicit order; defaults to array index + 1.\n\t\t *\n\t\t * @type {Array<{ id: string, label: string, icon?: string, widgets?: Array<{ type: string, props?: object }>, component?: string, order?: number }>|null}\n\t\t */\n\t\ttabs: {\n\t\t\ttype: Array,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/**\n\t\t * Custom-component registry. Keys are names referenced by\n\t\t * `tabs[].component` and unknown `tabs[].widgets[].type` values.\n\t\t * Falls back to the injected `cnCustomComponents` from a\n\t\t * CnAppRoot ancestor when omitted.\n\t\t *\n\t\t * @type {object|null}\n\t\t */\n\t\tcustomComponents: {\n\t\t\ttype: Object,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/**\n\t\t * Externally-requested active tab id. When set to a non-null id,\n\t\t * the sidebar switches to that tab — lets a host deep-link into a\n\t\t * specific leaf (e.g. a \"Linked apps\" row on the detail page that\n\t\t * opens the Mails tab). Leave null for normal internal tracking.\n\t\t *\n\t\t * @spec openspec/changes/case-page-and-list-as-a-place/specs/index-page/spec.md\n\t\t */\n\t\trequestedTab: {\n\t\t\ttype: String,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/**\n\t\t * Called with the tab this sidebar actually settled on, and whether\n\t\t * that was a correction rather than a reader's choice. A host that\n\t\t * keeps the tab in the address uses it to write the address, so the\n\t\t * address always names a tab this reader can actually see.\n\t\t *\n\t\t * @type {(tabId: string, canonicalising: boolean) => void}\n\t\t */\n\t\tonTabChange: {\n\t\t\ttype: Function,\n\t\t\tdefault: null,\n\t\t},\n\t},\n\n\temits: [\n\t\t'update:open',\n\t\t/**\n\t\t * The active tab changed. Payload is `{ tabId, canonicalising }`:\n\t\t * `canonicalising` is true when the sidebar corrected an address\n\t\t * naming a tab that does not exist or that this reader may not see,\n\t\t * rather than the reader choosing one.\n\t\t */\n\t\t'tab-change',\n\t\t/**\n\t\t * Forwarded unchanged from the built-in CnNotesTab after a note with\n\t\t * at least one `@mention` was saved. Payload:\n\t\t * `{ objectId, register, schema, noteId, mentionedUserIds }`.\n\t\t */\n\t\t'mention',\n\t],\n\n\tsetup(props) {\n\t\tconst exposed = {}\n\t\t// Integration registry: on by default via the `useRegistry`\n\t\t// prop (ADR-019). We always wire the composable up so consumers\n\t\t// can toggle `useRegistry` reactively without a remount.\n\t\tconst { integrations: registryIntegrations, resolveWidget, resolveTab } = useIntegrationRegistry()\n\t\texposed.registryIntegrations = registryIntegrations\n\t\texposed.resolveRegistryWidget = resolveWidget\n\t\t// `resolveTab` is local-first (LIB_INTEGRATION_COMPONENTS) so the\n\t\t// dispatched sidebar tab component is bound to this rendering\n\t\t// bundle's Vue — sidesteps the dual-runtime ADR-019 trap that\n\t\t// surfaced as `useNcFormBox(...)` undefined on cross-bundle\n\t\t// registrations. See openregister#1958.\n\t\texposed.resolveRegistryTabComponent = resolveTab\n\n\t\t// Object token context for sidebar-tab widgets that resolve `@objectId` /\n\t\t// `@object.<field>` tokens — the `object-table` built-in in particular\n\t\t// (e.g. a detail page's ZGW relation tab listing a zaak's besluiten,\n\t\t// filtered by `{ zaak: \"@objectId\" }`). Mirrors the reactive\n\t\t// `{ objectId, object, register, schema }` ref CnDetailPage provides.\n\t\t//\n\t\t// Provided ONLY when no ancestor already supplies `cnObjectContext`, so\n\t\t// a CnDetailPage parent's richer context (which carries the loaded\n\t\t// `object` for `@object.<field>`) keeps flowing through to the tab\n\t\t// widgets unchanged. When the sidebar is mounted standalone (no detail\n\t\t// page ancestor) it seeds the context from its own props — enough for\n\t\t// `@objectId` + register/schema resolution.\n\t\tconst parentObjectContext = inject('cnObjectContext', null)\n\t\tif (!parentObjectContext) {\n\t\t\tconst cnObjectContext = ref({\n\t\t\t\tobjectId: props.objectId || null,\n\t\t\t\tobject: null,\n\t\t\t\tregister: props.register || '',\n\t\t\t\tschema: props.schema || '',\n\t\t\t})\n\t\t\tprovide('cnObjectContext', cnObjectContext)\n\t\t\twatch(\n\t\t\t\t() => [props.objectId, props.register, props.schema],\n\t\t\t\t() => {\n\t\t\t\t\tcnObjectContext.value = {\n\t\t\t\t\t\tobjectId: props.objectId || null,\n\t\t\t\t\t\tobject: cnObjectContext.value.object || null,\n\t\t\t\t\t\tregister: props.register || '',\n\t\t\t\t\t\tschema: props.schema || '',\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t)\n\t\t}\n\n\t\t// Auto-subscribe to live updates for the active object. No-op\n\t\t// when `objectStore` is null (no Pinia active) or when the\n\t\t// consumer disabled it via `subscribe: false`. The\n\t\t// composable's reactive `id` argument keeps the subscription\n\t\t// in sync as the user navigates between sidebar objects.\n\t\tif (props.objectStore && props.subscribe) {\n\t\t\tuseObjectSubscription(\n\t\t\t\tprops.objectStore,\n\t\t\t\t() => props.objectType,\n\t\t\t\t() => props.objectId,\n\t\t\t\t{ enabled: () => Boolean(props.objectType && props.objectId) },\n\t\t\t)\n\t\t}\n\t\treturn exposed\n\t},\n\n\tdata() {\n\t\treturn {\n\t\t\tactiveTab: this.requestedTab || this.computeInitialActiveTab(),\n\t\t\t// The tab id already warned about, so an address naming a tab the\n\t\t\t// reader cannot see says so once rather than on every render.\n\t\t\twarnedTabId: null,\n\t\t}\n\t},\n\n\tcomputed: {\n\t\tsidebarTitle() {\n\t\t\treturn this.shown(this.title) || this.objectType || 'Details'\n\t\t},\n\n\t\tsidebarSubtitle() {\n\t\t\treturn this.subtitle || this.subtitleProp || ''\n\t\t},\n\n\t\t/** Whether the consumer has supplied a custom `tabs` array. */\n\t\thasCustomTabs() {\n\t\t\treturn Array.isArray(this.tabs) && this.tabs.length > 0\n\t\t},\n\n\t\t/**\n\t\t * Whether registry mode is active. Custom `tabs` always wins\n\t\t * (with a warning at mount) so consumers don't get a surprise\n\t\t * mode switch.\n\t\t */\n\t\tisRegistryMode() {\n\t\t\treturn this.useRegistry === true && this.hasCustomTabs === false\n\t\t},\n\n\t\t/**\n\t\t * Filtered registry snapshot: drops providers whose id is in\n\t\t * `excludeIntegrations` or `hiddenTabs`. Stays reactive on\n\t\t * the underlying registry's `onChange` notifications.\n\t\t */\n\t\tfilteredRegistryIntegrations() {\n\t\t\tconst excluded = new Set([\n\t\t\t\t...(this.excludeIntegrations || []),\n\t\t\t\t...(this.hiddenTabs || []),\n\t\t\t])\n\t\t\tconst all = this.registryIntegrations || []\n\t\t\treturn all.filter((p) => excluded.has(p.id) === false)\n\t\t},\n\n\t\t/** Effective customComponents registry: prop wins, inject fallback. */\n\t\teffectiveCustomComponents() {\n\t\t\treturn this.customComponents || this.cnCustomComponents || {}\n\t\t},\n\n\t\t/**\n\t\t * Effective v2 component registry (ADR-036). Kind-tagged entries\n\t\t * keyed by component name. Consulted by `resolveTabComponent` so a\n\t\t * tab's `component` ref resolves against the registry as well as the\n\t\t * legacy `customComponents` map.\n\t\t */\n\t\teffectiveRegistry() {\n\t\t\treturn this.cnRegistry || {}\n\t\t},\n\n\t\t/**\n\t\t * Shared object context forwarded to every widget / component\n\t\t * mounted inside a custom tab — same context the built-in tabs\n\t\t * receive today.\n\t\t */\n\t\tsharedTabProps() {\n\t\t\treturn {\n\t\t\t\tobjectId: this.objectId,\n\t\t\t\tobjectType: this.objectType,\n\t\t\t\tregister: this.register,\n\t\t\t\tschema: this.schema,\n\t\t\t\tapiBase: this.apiBase,\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Context forwarded to a mount-mode leaf's `mount(el, props)` for the\n\t\t * single-entity sidebar surface — the same shape an SFC tab receives,\n\t\t * plus the `surface` name and an `integrationContext` bag. Reactive\n\t\t * on the object identity so CnLeafMountHost re-mounts on object change.\n\t\t */\n\t\tsidebarMountProps() {\n\t\t\treturn {\n\t\t\t\t...this.sharedTabProps,\n\t\t\t\tsurface: 'single-entity',\n\t\t\t\tintegrationContext: {\n\t\t\t\t\tregister: this.register,\n\t\t\t\t\tschema: this.schema,\n\t\t\t\t\tobjectId: this.objectId,\n\t\t\t\t},\n\t\t\t}\n\t\t},\n\t},\n\n\twatch: {\n\t\ttabs: {\n\t\t\timmediate: false,\n\t\t\t/**\n\t\t\t * Re-anchor the active tab when the tab set changes, so the\n\t\t\t * active id stays one the reader can actually see.\n\t\t\t *\n\t\t\t * @spec openspec/changes/case-page-and-list-as-a-place/specs/index-page/spec.md\n\t\t\t */\n\t\t\thandler() {\n\t\t\t\t// Re-anchor activeTab when the tab set changes so the\n\t\t\t\t// active id stays valid (otherwise NcAppSidebar shows no\n\t\t\t\t// active tab when the consumer swaps in a fresh array).\n\t\t\t\tthis.settleOnTab(this.requestedTab)\n\t\t\t},\n\t\t},\n\n\t\t/**\n\t\t * Host deep-link: settle on the requested tab when it changes, which\n\t\t * is how an address naming a tab reaches the tab strip.\n\t\t *\n\t\t * @param {string} id The tab asked for.\n\t\t * @spec openspec/changes/case-page-and-list-as-a-place/specs/index-page/spec.md\n\t\t */\n\t\trequestedTab(id) {\n\t\t\tif (id) {\n\t\t\t\tthis.settleOnTab(id)\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * The reader clicked a tab. Reported back so a host keeping the tab\n\t\t * in the address writes it there, which is what makes a tab linkable.\n\t\t *\n\t\t * @param {string} id The tab now active.\n\t\t * @param {string} previous The tab before it.\n\t\t * @spec openspec/changes/case-page-and-list-as-a-place/specs/index-page/spec.md\n\t\t */\n\t\tactiveTab(id, previous) {\n\t\t\tif (id && previous !== undefined && id !== previous && typeof this.onTabChange === 'function') {\n\t\t\t\tthis.onTabChange(id, false)\n\t\t\t}\n\t\t},\n\t},\n\n\t/**\n\t * Settle on a tab on arrival, and warn about a tab set the consumer\n\t * declared two ways.\n\t *\n\t * @spec openspec/changes/case-page-and-list-as-a-place/specs/index-page/spec.md\n\t */\n\tmounted() {\n\t\t// Settle on arrival, so an address carrying no tab is corrected to\n\t\t// its canonical form once rather than staying tabless until the\n\t\t// reader happens to click something (ADR-052).\n\t\tif (typeof this.onTabChange === 'function') {\n\t\t\tthis.settleOnTab(this.requestedTab)\n\t\t}\n\t\tif (this.useRegistry === true && this.hasCustomTabs === true) {\n\t\t\t// eslint-disable-next-line no-console\n\t\t\tconsole.warn('[CnObjectSidebar] `useRegistry` is true but `tabs` is also set — falling back to `tabs` (registry mode ignored). Pass one or the other.')\n\t\t}\n\t},\n\n\tmethods: {\n\n\t\t/**\n\t\t * A manifest label through the injected lookup, or as written.\n\t\t *\n\t\t * @param {string} text The label as written.\n\t\t * @return {string} The label in the user's language.\n\t\t */\n\t\tshown(text) {\n\t\t\treturn typeof this.cnTranslate === 'function' && typeof text === 'string' && text !== '' ? this.cnTranslate(text) : text\n\t\t},\n\n\t\t/**\n\t\t * The `lang` of a label that fell back to its written text in another language.\n\t\t *\n\t\t * @param {string} text The label as written.\n\t\t * @return {string|undefined} The source language, or undefined.\n\t\t */\n\t\tlangOf(text) {\n\t\t\treturn labelLang(this.cnTranslate, text) || undefined\n\t\t},\n\n\t\tisTabHidden(tabId) {\n\t\t\treturn this.hiddenTabs.includes(tabId)\n\t\t},\n\n\t\t/**\n\t\t * Resolve a registry provider's tab component, preferring the\n\t\t * LOCAL lib-owned component (rendering-bundle Vue) over the\n\t\t * shared registry's stored object. Falls back to the stored\n\t\t * `provider.tab` for consumer-custom ids (which live in the\n\t\t * consumer's own bundle and therefore render under the same\n\t\t * Vue instance with no mismatch). See openregister#1958.\n\t\t *\n\t\t * @param {object} provider Normalised registry entry.\n\t\t * @return {object|null} Vue component, or null.\n\t\t */\n\t\tresolveRegistryTab(provider) {\n\t\t\tif (!provider || typeof provider.id !== 'string') {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tconst local = this.resolveRegistryTabComponent(provider.id)\n\t\t\tif (local) {\n\t\t\t\treturn local\n\t\t\t}\n\t\t\treturn provider.tab || null\n\t\t},\n\n\t\t/**\n\t\t * Whether a registry provider renders via the mount hand-off\n\t\t * (`renderMode: 'mount'`, openregister#2127) rather than an SFC tab.\n\t\t * Mount-mode leaves carry `mount`/`unmount` functions the host calls\n\t\t * against a bare element via CnLeafMountHost.\n\t\t *\n\t\t * @param {object} provider Normalised registry entry.\n\t\t * @return {boolean} true when the provider is mount-mode.\n\t\t */\n\t\tisMountProvider(provider) {\n\t\t\treturn Boolean(provider)\n\t\t\t\t&& provider.renderMode === 'mount'\n\t\t\t\t&& typeof provider.mount === 'function'\n\t\t\t\t&& typeof provider.unmount === 'function'\n\t\t},\n\n\t\t/**\n\t\t * Pick a sensible default active tab on mount and on tabs[]\n\t\t * changes. When custom tabs are present, the first entry wins.\n\t\t * When unset, the built-in `files` tab is the default (matches\n\t\t * the legacy behavior).\n\t\t */\n\t\tcomputeInitialActiveTab() {\n\t\t\tif (Array.isArray(this.tabs) && this.tabs.length > 0) {\n\t\t\t\treturn this.tabs[0].id\n\t\t\t}\n\t\t\treturn 'files'\n\t\t},\n\n\t\t/**\n\t\t * The tab ids this reader can actually see, in the order shown.\n\t\t *\n\t\t * Three tab sources, one answer. Without this the address could name\n\t\t * a tab that is hidden, excluded or simply not registered, and the\n\t\t * sidebar would show its first tab while the address went on claiming\n\t\t * a different one.\n\t\t *\n\t\t * @return {Array<string>} The visible tab ids.\n\t\t * @spec openspec/changes/case-page-and-list-as-a-place/specs/index-page/spec.md\n\t\t */\n\t\tvisibleTabIds() {\n\t\t\tif (this.isRegistryMode) {\n\t\t\t\treturn (this.filteredRegistryIntegrations || []).map((p) => p.id)\n\t\t\t}\n\t\t\tif (Array.isArray(this.tabs) && this.tabs.length > 0) {\n\t\t\t\treturn this.tabs.filter((tab) => tab && !this.isTabHidden(tab.id)).map((tab) => tab.id)\n\t\t\t}\n\t\t\treturn ['files', 'notes', 'tags', 'tasks', 'auditTrail'].filter((id) => !this.isTabHidden(id))\n\t\t},\n\n\t\t/**\n\t\t * Settle on a tab, and say whether the address had to be corrected.\n\t\t *\n\t\t * An address naming a tab that does not exist, or one this reader may\n\t\t * not see, falls back to the first tab they can see and says so ONCE.\n\t\t * Silently showing a different tab than the address names is the\n\t\t * failure here: the reader then sends a colleague a link that opens\n\t\t * somewhere else again.\n\t\t *\n\t\t * @param {string|null} requested The tab the address asked for.\n\t\t * @return {{ tabId: string, canonicalising: boolean }} The tab to show.\n\t\t * @spec openspec/changes/case-page-and-list-as-a-place/specs/index-page/spec.md\n\t\t */\n\t\tresolveTabRequest(requested) {\n\t\t\tconst visible = this.visibleTabIds\n\t\t\tconst fallback = visible[0] || this.computeInitialActiveTab()\n\t\t\tif (!requested) {\n\t\t\t\treturn { tabId: fallback, canonicalising: true }\n\t\t\t}\n\t\t\tif (visible.length === 0 || visible.includes(requested)) {\n\t\t\t\treturn { tabId: requested, canonicalising: false }\n\t\t\t}\n\t\t\tif (this.warnedTabId !== requested) {\n\t\t\t\tthis.warnedTabId = requested\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.warn(`[CnObjectSidebar] The address asks for the \"${requested}\" tab, which is not available here. Showing \"${fallback}\" instead.`)\n\t\t\t}\n\t\t\treturn { tabId: fallback, canonicalising: true }\n\t\t},\n\n\t\t/**\n\t\t * Show a tab and tell the host, so the address can follow.\n\t\t *\n\t\t * @param {string|null} requested The tab asked for.\n\t\t * @spec openspec/changes/case-page-and-list-as-a-place/specs/index-page/spec.md\n\t\t */\n\t\tsettleOnTab(requested) {\n\t\t\tconst { tabId, canonicalising } = this.resolveTabRequest(requested)\n\t\t\tthis.activeTab = tabId\n\t\t\tif (typeof this.onTabChange === 'function') {\n\t\t\t\tthis.onTabChange(tabId, canonicalising)\n\t\t\t}\n\t\t\t/**\n\t\t\t * @event tab-change Emitted when the active tab settles, including when the sidebar corrected the address.\n\t\t\t * @type {{ tabId: string, canonicalising: boolean }}\n\t\t\t */\n\t\t\tthis.$emit('tab-change', { tabId, canonicalising })\n\t\t},\n\n\t\t/**\n\t\t * Build the prop bag for a widget in the `widgets[]` tab path. All\n\t\t * widgets get the shared coordinate context plus the loaded object\n\t\t * (`objectData`); the prop-driven `data` built-in also gets the schema\n\t\t * OBJECT bound to its `schema` prop (the other tabs use the `schema`\n\t\t * slug string, so the override is scoped to `type: 'data'`). Of a\n\t\t * widget's own `props`, the ones its component declares win on overlap;\n\t\t * an undeclared one would only fall through onto the component's root.\n\t\t *\n\t\t * @spec openspec/changes/declared-props-detail-index-sidebar/specs/widget-hosts/spec.md#requirement-a-widget-host-passes-only-the-keys-a-widget-declares\n\t\t * @param {{ type: string, props?: object }} w Widget spec\n\t\t * @return {object} Props to v-bind onto the resolved widget component\n\t\t */\n\t\twidgetBindings(w) {\n\t\t\tconst bindings = { ...this.sharedTabProps, objectData: this.objectData }\n\t\t\tif (w.type === 'data') {\n\t\t\t\t// CnObjectDataWidget wants the schema OBJECT, never the slug the\n\t\t\t\t// other tabs use. Pass the resolved object (null until it loads —\n\t\t\t\t// the widget renders its empty state meanwhile) so it never sees\n\t\t\t\t// a String `schema`.\n\t\t\t\tbindings.schema = this.objectSchema\n\t\t\t}\n\t\t\treturn { ...bindings, ...pickDeclaredProps(this.resolveWidgetComponent(w.type), w.props || {}, w.type || '') }\n\t\t},\n\n\t\t/**\n\t\t * Resolve a widget type to a component. Built-in types (`data`,\n\t\t * `metadata`, `audit` / `audit-trail`, `object-table`) map to their\n\t\t * lib component; any other type resolves against the v2 registry, then\n\t\t * the legacy customComponents map. Logs a console.warn and returns null when nothing\n\t\t * resolves.\n\t\t *\n\t\t * @param {string} type Widget type identifier\n\t\t * @return {object|null} Vue component, or null when unresolved\n\t\t */\n\t\tresolveWidgetComponent(type) {\n\t\t\tif (BUILTIN_WIDGETS[type]) {\n\t\t\t\treturn BUILTIN_WIDGETS[type]\n\t\t\t}\n\t\t\tconst registryEntry = this.effectiveRegistry[type]\n\t\t\tif (registryEntry && registryEntry.component) {\n\t\t\t\treturn registryEntry.component\n\t\t\t}\n\t\t\tconst reg = this.effectiveCustomComponents\n\t\t\tif (reg && reg[type]) {\n\t\t\t\treturn reg[type]\n\t\t\t}\n\t\t\t// eslint-disable-next-line no-console\n\t\t\tconsole.warn(`[CnObjectSidebar] Unknown widget type \"${type}\" — not in built-ins (data, metadata, audit, audit-trail, object-table), the registry or customComponents.`)\n\t\t\treturn null\n\t\t},\n\n\t\t/**\n\t\t * Resolve a tab's `component` registry name. Logs a\n\t\t * console.warn when both `widgets` and `component` are set\n\t\t * (component wins) or when the registry name is missing.\n\t\t *\n\t\t * @param {object} tab Tab definition\n\t\t * @return {object|null} Vue component, or null when unresolved\n\t\t */\n\t\tresolveTabComponent(tab) {\n\t\t\tif (tab.widgets && tab.widgets.length > 0) {\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.warn(`[CnObjectSidebar] Tab \"${tab.id}\" declares both widgets[] and component — component wins, widgets are ignored.`)\n\t\t\t}\n\t\t\t// v2 registry first (ADR-036): any kind-tagged entry with a\n\t\t\t// `component` field is acceptable for a slot/tab lookup — this\n\t\t\t// is what lets a `kind: 'page'` tab component (the procest\n\t\t\t// pattern) render. Fall back to the legacy customComponents map.\n\t\t\tconst registryEntry = this.effectiveRegistry[tab.component]\n\t\t\tif (registryEntry && registryEntry.component) {\n\t\t\t\treturn registryEntry.component\n\t\t\t}\n\t\t\tconst reg = this.effectiveCustomComponents\n\t\t\tconst resolved = reg && reg[tab.component]\n\t\t\tif (!resolved) {\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.warn(`[CnObjectSidebar] Tab \"${tab.id}\" component \"${tab.component}\" not found in registry or customComponents.`)\n\t\t\t\treturn null\n\t\t\t}\n\t\t\treturn resolved\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n/* NcAppSidebar lays every tab out as an equal share of the sidebar width\n * (`flex: 1 1`) with an ellipsis caption, so an object with many tabs — e.g. a\n * lead's 5+ tabs — shrinks them until the labels truncate. Keep the tabs\n * equal-width (uniform) but stop them shrinking below a readable minimum, and\n * let the strip scroll horizontally once they no longer fit. `flex-basis: 0`\n * + equal grow keeps every tab the same width whether the row fits or scrolls.\n * Apps with longer labels can widen the floor via --cn-sidebar-tab-min-width. */\n:deep(.app-sidebar-tabs__nav) {\n\toverflow-x: auto;\n}\n\n:deep(.app-sidebar-tabs__nav .app-sidebar-tabs__tab) {\n\tflex-grow: 1;\n\tflex-shrink: 0;\n\tflex-basis: 0;\n\t/* !important to beat NcAppSidebar's own min-width on the button variant. */\n\tmin-width: var(--cn-sidebar-tab-min-width, 7rem) !important;\n}\n</style>\n"],"names":["_createBlock","_Fragment","_openBlock","_createElementBlock","_renderList","_resolveDynamicComponent","_createVNode","_renderSlot","_mergeProps"],"mappings":"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"}
1
+ {"version":3,"file":"CnObjectSidebar.vue3.js","sources":["../../../../src/components/CnObjectSidebar/CnObjectSidebar.vue?vue&type=template&id=4cf1a7bc&lang.js"],"sourcesContent":["<!--\n CnObjectSidebar — Right sidebar with standardized tabs for generic object functionality.\n\n Provides Files, Notes, Tags, Tasks, and Audit Trail tabs that integrate with\n OpenRegister API endpoints (which bridge to Nextcloud-native APIs).\n All tabs are optional and overridable via props and slots.\n-->\n<template>\n\t<!-- `subname` is NcAppSidebar's visible secondary line; `subtitle` is only\n\t the tooltip on it, and the line is not rendered at all while subname is\n\t empty — so passing subtitle alone showed nothing. Same pair as\n\t name/title, and as CnIndexSidebar. -->\n\t<NcAppSidebar\n\t\tv-model:active=\"activeTab\"\n\t\t:name=\"sidebarTitle\"\n\t\t:title=\"sidebarTitle\"\n\t\t:subname=\"sidebarSubtitle\"\n\t\t:subtitle=\"sidebarSubtitle\"\n\t\t:open=\"open\"\n\t\tdata-testid=\"cn-object-sidebar\"\n\t\t@update:open=\"$emit('update:open', $event)\"\n\t\t@close=\"$emit('update:open', false)\">\n\t\t<!-- REGISTRY BRANCH: pluggable integration registry-driven.\n\t\t Renders one tab per provider registered on\n\t\t `window.OCA.OpenRegister.integrations`. `hiddenTabs` /\n\t\t `excludeIntegrations` filter the set; the `#extra-tabs`\n\t\t slot still appends consumer-supplied tabs. Per-integration\n\t\t slot overrides aren't supported in registry mode — apps\n\t\t that need to override a built-in tab should register their\n\t\t own provider with the same id (collision policy: first\n\t\t wins) before OpenRegister's bundle loads. -->\n\t\t<template v-if=\"isRegistryMode\">\n\t\t\t<NcAppSidebarTab\n\t\t\t\tv-for=\"(provider, idx) in filteredRegistryIntegrations\"\n\t\t\t\t:id=\"provider.id\"\n\t\t\t\t:key=\"provider.id\"\n\t\t\t\t:name=\"provider.label\"\n\t\t\t\t:order=\"provider.order != null ? provider.order : idx + 1\"\n\t\t\t\t:data-testid=\"`cn-object-sidebar-tab-${provider.id}`\">\n\t\t\t\t<template #icon>\n\t\t\t\t\t<CnIcon v-if=\"provider.icon\" :name=\"provider.icon\" :size=\"20\" />\n\t\t\t\t</template>\n\t\t\t\t<!-- MOUNT BRANCH (openregister#2127): a `renderMode: 'mount'`\n\t\t\t\t leaf renders through CnLeafMountHost — a bare host-owned\n\t\t\t\t element the leaf mounts its own framework into. Mounted\n\t\t\t\t lazily when the tab is active; unmounted on hide/teardown. -->\n\t\t\t\t<CnLeafMountHost\n\t\t\t\t\tv-if=\"isMountProvider(provider)\"\n\t\t\t\t\t:provider=\"provider\"\n\t\t\t\t\t:active=\"activeTab === provider.id\"\n\t\t\t\t\t:mountProps=\"sidebarMountProps\" />\n\t\t\t\t<component\n\t\t\t\t\t:is=\"resolveRegistryTab(provider)\"\n\t\t\t\t\tv-else\n\t\t\t\t\tv-bind=\"sharedTabProps\" />\n\t\t\t</NcAppSidebarTab>\n\t\t\t<slot name=\"extra-tabs\" />\n\t\t</template>\n\n\t\t<!-- BACKWARDS-COMPATIBLE BRANCH: hard-coded built-in tabs.\n\t\t Used when no custom `tabs` prop is provided and the\n\t\t registry mode is not active. The slot overrides\n\t\t (#tab-files etc.) and `hiddenTabs` filtering remain\n\t\t unchanged. -->\n\t\t<template v-else-if=\"!hasCustomTabs\">\n\t\t\t<!-- Files Tab -->\n\t\t\t<NcAppSidebarTab\n\t\t\t\tv-if=\"!isTabHidden('files')\"\n\t\t\t\tid=\"files\"\n\t\t\t\t:name=\"filesLabel\"\n\t\t\t\t:order=\"1\"\n\t\t\t\tdata-testid=\"cn-object-sidebar-tab-files\">\n\t\t\t\t<template #icon>\n\t\t\t\t\t<Paperclip :size=\"20\" />\n\t\t\t\t</template>\n\t\t\t\t<slot name=\"tab-files\" :objectId=\"objectId\" :objectType=\"objectType\">\n\t\t\t\t\t<CnFilesTab\n\t\t\t\t\t\t:objectId=\"objectId\"\n\t\t\t\t\t\t:register=\"register\"\n\t\t\t\t\t\t:schema=\"schema\"\n\t\t\t\t\t\t:apiBase=\"apiBase\" />\n\t\t\t\t</slot>\n\t\t\t</NcAppSidebarTab>\n\n\t\t\t<!-- Notes Tab -->\n\t\t\t<NcAppSidebarTab\n\t\t\t\tv-if=\"!isTabHidden('notes')\"\n\t\t\t\tid=\"notes\"\n\t\t\t\t:name=\"notesLabel\"\n\t\t\t\t:order=\"2\"\n\t\t\t\tdata-testid=\"cn-object-sidebar-tab-notes\">\n\t\t\t\t<template #icon>\n\t\t\t\t\t<CommentTextOutline :size=\"20\" />\n\t\t\t\t</template>\n\t\t\t\t<slot name=\"tab-notes\" :objectId=\"objectId\" :objectType=\"objectType\">\n\t\t\t\t\t<!-- The `mention` passthrough is the notification hook: apps\n\t\t\t\t\t mounting the full sidebar receive the mentioned user ids\n\t\t\t\t\t and dispatch NC notifications from their own backend. -->\n\t\t\t\t\t<CnNotesTab\n\t\t\t\t\t\t:objectId=\"objectId\"\n\t\t\t\t\t\t:register=\"register\"\n\t\t\t\t\t\t:schema=\"schema\"\n\t\t\t\t\t\t:apiBase=\"apiBase\"\n\t\t\t\t\t\t@mention=\"$emit('mention', $event)\" />\n\t\t\t\t</slot>\n\t\t\t</NcAppSidebarTab>\n\n\t\t\t<!-- Tags Tab -->\n\t\t\t<NcAppSidebarTab\n\t\t\t\tv-if=\"!isTabHidden('tags')\"\n\t\t\t\tid=\"tags\"\n\t\t\t\t:name=\"tagsLabel\"\n\t\t\t\t:order=\"3\"\n\t\t\t\tdata-testid=\"cn-object-sidebar-tab-tags\">\n\t\t\t\t<template #icon>\n\t\t\t\t\t<TagOutline :size=\"20\" />\n\t\t\t\t</template>\n\t\t\t\t<slot name=\"tab-tags\" :objectId=\"objectId\" :objectType=\"objectType\">\n\t\t\t\t\t<CnTagsTab\n\t\t\t\t\t\t:objectId=\"objectId\"\n\t\t\t\t\t\t:register=\"register\"\n\t\t\t\t\t\t:schema=\"schema\"\n\t\t\t\t\t\t:apiBase=\"apiBase\" />\n\t\t\t\t</slot>\n\t\t\t</NcAppSidebarTab>\n\n\t\t\t<!-- Tasks Tab -->\n\t\t\t<NcAppSidebarTab\n\t\t\t\tv-if=\"!isTabHidden('tasks')\"\n\t\t\t\tid=\"tasks\"\n\t\t\t\t:name=\"tasksLabel\"\n\t\t\t\t:order=\"4\"\n\t\t\t\tdata-testid=\"cn-object-sidebar-tab-tasks\">\n\t\t\t\t<template #icon>\n\t\t\t\t\t<CheckboxMarkedOutline :size=\"20\" />\n\t\t\t\t</template>\n\t\t\t\t<slot name=\"tab-tasks\" :objectId=\"objectId\" :objectType=\"objectType\">\n\t\t\t\t\t<CnTasksTab\n\t\t\t\t\t\t:objectId=\"objectId\"\n\t\t\t\t\t\t:register=\"register\"\n\t\t\t\t\t\t:schema=\"schema\"\n\t\t\t\t\t\t:apiBase=\"apiBase\"\n\t\t\t\t\t\t:source=\"tasksSource\" />\n\t\t\t\t</slot>\n\t\t\t</NcAppSidebarTab>\n\n\t\t\t<!-- Audit Trail Tab -->\n\t\t\t<NcAppSidebarTab\n\t\t\t\tv-if=\"!isTabHidden('auditTrail')\"\n\t\t\t\tid=\"auditTrail\"\n\t\t\t\t:name=\"auditTrailLabel\"\n\t\t\t\t:order=\"5\"\n\t\t\t\tdata-testid=\"cn-object-sidebar-tab-audit-trail\">\n\t\t\t\t<template #icon>\n\t\t\t\t\t<History :size=\"20\" />\n\t\t\t\t</template>\n\t\t\t\t<slot name=\"tab-audit-trail\" :objectId=\"objectId\" :objectType=\"objectType\">\n\t\t\t\t\t<CnAuditTrailTab\n\t\t\t\t\t\t:objectId=\"objectId\"\n\t\t\t\t\t\t:register=\"register\"\n\t\t\t\t\t\t:schema=\"schema\"\n\t\t\t\t\t\t:apiBase=\"apiBase\" />\n\t\t\t\t</slot>\n\t\t\t</NcAppSidebarTab>\n\n\t\t\t<!-- Custom tabs slot (only relevant in legacy mode) -->\n\t\t\t<slot name=\"extra-tabs\" />\n\t\t</template>\n\n\t\t<!-- OPEN-ENUM BRANCH: render the consumer-supplied `tabs` array.\n\t\t Each tab declares its content via `widgets` (resolved against\n\t\t the built-in widget registry — `data` → CnObjectDataWidget,\n\t\t `metadata` → CnObjectMetadataWidget, `audit`/`audit-trail` →\n\t\t CnAuditTrailTab, `object-table` → CnWidgetObjectTable — with the\n\t\t customComponents registry as the escape hatch) OR `component`\n\t\t (resolved against the customComponents registry directly). -->\n\t\t<template v-else>\n\t\t\t<NcAppSidebarTab\n\t\t\t\tv-for=\"(tab, idx) in tabs\"\n\t\t\t\t:id=\"tab.id\"\n\t\t\t\t:key=\"tab.id\"\n\t\t\t\t:name=\"shown(tab.label)\"\n\t\t\t\t:lang=\"langOf(tab.label)\"\n\t\t\t\t:order=\"tab.order != null ? tab.order : idx + 1\"\n\t\t\t\t:data-testid=\"`cn-object-sidebar-tab-${tab.id}`\">\n\t\t\t\t<template v-if=\"tab.icon\" #icon>\n\t\t\t\t\t<CnIcon :name=\"tab.icon\" :size=\"20\" />\n\t\t\t\t</template>\n\n\t\t\t\t<!-- Component-registry escape hatch wins when `component` is set\n\t\t\t\t (with a console.warn at mount time when widgets is also set). -->\n\t\t\t\t<component\n\t\t\t\t\t:is=\"resolveTabComponent(tab)\"\n\t\t\t\t\tv-if=\"tab.component\"\n\t\t\t\t\tv-bind=\"sharedTabProps\" />\n\n\t\t\t\t<!-- Widget array path. Each widget receives the shared object\n\t\t\t\t context plus its own `props` via `widgetBindings` (which also\n\t\t\t\t hands the prop-driven `data` / `metadata` built-ins the loaded\n\t\t\t\t object and schema); per-widget props win on overlap. -->\n\t\t\t\t<div v-else class=\"cn-object-sidebar__tab-widgets\">\n\t\t\t\t\t<template v-for=\"(w, wIdx) in tab.widgets || []\">\n\t\t\t\t\t\t<component\n\t\t\t\t\t\t\t:is=\"resolveWidgetComponent(w.type)\"\n\t\t\t\t\t\t\tv-if=\"resolveWidgetComponent(w.type)\"\n\t\t\t\t\t\t\t:key=\"wIdx\"\n\t\t\t\t\t\t\tv-bind=\"widgetBindings(w)\" />\n\t\t\t\t\t</template>\n\t\t\t\t</div>\n\t\t\t</NcAppSidebarTab>\n\t\t</template>\n\t</NcAppSidebar>\n</template>\n\n<script>\nimport { translate as t } from '@nextcloud/l10n'\nimport { NcAppSidebar, NcAppSidebarTab } from '@nextcloud/vue'\nimport { inject, provide, ref, watch } from 'vue'\nimport CheckboxMarkedOutline from 'vue-material-design-icons/CheckboxMarkedOutline.vue'\nimport CommentTextOutline from 'vue-material-design-icons/CommentTextOutline.vue'\nimport History from 'vue-material-design-icons/History.vue'\nimport Paperclip from 'vue-material-design-icons/Paperclip.vue'\nimport TagOutline from 'vue-material-design-icons/TagOutline.vue'\nimport CnWidgetObjectTable from '../CnWidgetObjectTable/CnWidgetObjectTable.vue'\nimport CnAuditTrailTab from './CnAuditTrailTab.vue'\nimport CnFilesTab from './CnFilesTab.vue'\nimport CnNotesTab from './CnNotesTab.vue'\nimport CnTagsTab from './CnTagsTab.vue'\nimport CnTasksTab from './CnTasksTab.vue'\nimport { useIntegrationRegistry } from '../../composables/useIntegrationRegistry.js'\nimport { useObjectSubscription } from '../../composables/useObjectSubscription.js'\nimport { pickDeclaredProps } from '../../utils/declaredProps.js'\nimport { labelLang } from '../../utils/manifestTranslate.js'\nimport { CnAiFeaturesWidget } from '../CnAiFeaturesWidget/index.js'\nimport { CnIcon } from '../CnIcon/index.js'\nimport { CnLeafMountHost } from '../CnLeafMountHost/index.js'\nimport { CnObjectDataWidget } from '../CnObjectDataWidget/index.js'\nimport { CnObjectMetadataWidget } from '../CnObjectMetadataWidget/index.js'\nimport { CnObjectPermissionsTab } from '../CnObjectPermissionsTab/index.js'\n\n/**\n * Built-in widget registry used by the open-enum `tabs` prop.\n * - `data` → CnObjectDataWidget (schema-driven editable grid)\n * - `metadata` → CnObjectMetadataWidget (read-only system metadata)\n * - `audit` → CnAuditTrailTab (the object's change log / audit trail)\n * - `object-permissions` → CnObjectPermissionsTab (read-only: who holds which\n * right on the object, where each grant came from, and on a past date)\n * - `object-table` → CnWidgetObjectTable (a declarative list scoped to the\n * parent object — the full source / endpointSource / columns / actions\n * contract). Resolves `@objectId` / `@object.<field>` filter tokens against\n * the object context this sidebar `provide`s (see setup), so a detail\n * page's ZGW-style relation tab (e.g. a zaak's besluiten, filtered by\n * `{ zaak: \"@objectId\" }`) renders as a sidebar tab with no bespoke code.\n *\n * Any `widgets[].type` value not in this map falls back to the\n * customComponents registry (prop, then injected `cnCustomComponents`).\n */\nconst BUILTIN_WIDGETS = {\n\t// The hermiq AI features a record's type switches on (CnAiFeaturesWidget).\n\t'ai-features': CnAiFeaturesWidget,\n\tdata: CnObjectDataWidget,\n\tmetadata: CnObjectMetadataWidget,\n\taudit: CnAuditTrailTab,\n\t// Alias matching the dashboard/detail-page widget key `audit-trail` so a\n\t// manifest can declare a sidebar tab with `widgets: [{ type: 'audit-trail' }]`\n\t// (the same key it uses for the detail-page body widget) and get the object's\n\t// change log as a proper sidebar tab.\n\t'audit-trail': CnAuditTrailTab,\n\t// The declarative list widget (same key as the detail-page body widget), so\n\t// a sidebar tab can render a related-object list scoped to the parent\n\t// object via `@objectId` / `@object.<field>` tokens in its `source.filter`.\n\t'object-table': CnWidgetObjectTable,\n\t'object-permissions': CnObjectPermissionsTab,\n}\n\n/**\n * CnObjectSidebar — Right sidebar for entity detail pages.\n *\n * Provides standardized tabs for generic object functionality (Files, Notes, Tags,\n * Tasks, Audit Trail) that integrate with OpenRegister API endpoints bridging to\n * Nextcloud-native APIs. Each tab is a self-contained component.\n *\n * Basic usage\n * ```vue\n * <CnObjectSidebar\n * object-type=\"pipelinq_lead\"\n * :object-id=\"leadId\"\n * :register=\"registerConfig.register\"\n * :schema=\"registerConfig.schema\" />\n * ```\n *\n * Hide specific tabs\n * ```vue\n * <CnObjectSidebar\n * object-type=\"pipelinq_lead\"\n * :object-id=\"leadId\"\n * :hidden-tabs=\"['tasks', 'tags']\" />\n * ```\n *\n * Override a tab\n * ```vue\n * <CnObjectSidebar object-type=\"pipelinq_lead\" :object-id=\"leadId\">\n * <template #tab-notes=\"{ objectId }\">\n * <MyCustomNotesComponent :id=\"objectId\" />\n * </template>\n * </CnObjectSidebar>\n * ```\n */\nexport default {\n\tname: 'CnObjectSidebar',\n\n\tcomponents: {\n\t\tNcAppSidebar,\n\t\tNcAppSidebarTab,\n\t\tPaperclip,\n\t\tCommentTextOutline,\n\t\tTagOutline,\n\t\tCheckboxMarkedOutline,\n\t\tHistory,\n\t\tCnFilesTab,\n\t\tCnNotesTab,\n\t\tCnTagsTab,\n\t\tCnTasksTab,\n\t\tCnAuditTrailTab,\n\t\tCnIcon,\n\t\tCnLeafMountHost,\n\t},\n\n\tinject: {\n\t\tcnCustomComponents: { default: () => ({}) },\n\t\t// v2 component registry (ADR-036). Kind-tagged entries\n\t\t// ({ kind, component }); a sidebar tab's `component` ref resolves\n\t\t// against this first so apps that migrated their tab components to\n\t\t// the registry (e.g. as `kind: 'page'`) still render. Empty default\n\t\t// keeps the legacy `customComponents`-only path unchanged.\n\t\tcnRegistry: { default: () => ({}) },\n\t\t// The label lookup from CnAppRoot, so tab labels and the title show in the user's language.\n\t\tcnTranslate: { default: null },\n\t},\n\n\tprops: {\n\t\t/** The entity type (e.g., \"pipelinq_lead\", \"procest_case\") */\n\t\tobjectType: {\n\t\t\ttype: String,\n\t\t\trequired: true,\n\t\t},\n\n\t\t/** The object UUID */\n\t\tobjectId: {\n\t\t\ttype: String,\n\t\t\trequired: true,\n\t\t},\n\n\t\t/** OpenRegister register ID */\n\t\tregister: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/** OpenRegister schema ID */\n\t\tschema: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/**\n\t\t * The loaded object, forwarded to prop-driven sidebar-tab widgets\n\t\t * (the `data` / `metadata` built-ins) as `objectData`. The sidebar is\n\t\t * otherwise coordinate-based — most tabs self-fetch from\n\t\t * `objectId`/`register`/`schema` — so this is null unless a host (e.g.\n\t\t * CnDetailPage via CnAppRoot) publishes the loaded object.\n\t\t *\n\t\t * @type {object|null}\n\t\t */\n\t\tobjectData: {\n\t\t\ttype: Object,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/**\n\t\t * The resolved JSON Schema OBJECT (with a `properties` field), forwarded\n\t\t * to the `data` built-in tab widget (CnObjectDataWidget), which needs the\n\t\t * schema definition rather than the `schema` slug string. Null unless a\n\t\t * host (e.g. CnDetailPage via CnAppRoot) publishes it.\n\t\t *\n\t\t * @type {object|null}\n\t\t */\n\t\tobjectSchema: {\n\t\t\ttype: Object,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/** Array of tab IDs to hide: 'files', 'notes', 'tags', 'tasks', 'auditTrail' */\n\t\thiddenTabs: {\n\t\t\ttype: Array,\n\t\t\tdefault: () => [],\n\t\t},\n\n\t\t/**\n\t\t * Use the pluggable integration registry to drive the sidebar\n\t\t * tabs. Defaults to `true` (ADR-019): tabs are rendered one per\n\t\t * provider registered on `window.OCA.OpenRegister.integrations`\n\t\t * (and via `useIntegrationRegistry()`). The canonical five\n\t\t * built-ins — files / notes / tags / tasks / audit-trail — are\n\t\t * shipped as providers in `builtinIntegrations` and registered by\n\t\t * OpenRegister's bootstrap (`registerBuiltinIntegrations()`), so\n\t\t * the default surface is unchanged for apps that register them.\n\t\t *\n\t\t * Set `false` to opt back into the legacy hardcoded-tabs path,\n\t\t * which renders the five built-in tabs directly from this\n\t\t * component and supports the `#tab-<id>` slot overrides. Use this\n\t\t * for consumers that do not call `registerBuiltinIntegrations()`\n\t\t * and want the built-in tabs without standing up the registry.\n\t\t *\n\t\t * `hiddenTabs` / `excludeIntegrations` and the `#extra-tabs` slot\n\t\t * apply in both modes.\n\t\t *\n\t\t * Mutually exclusive with the open-enum `tabs` prop — when both\n\t\t * are set, `tabs` wins and a console.warn is logged.\n\t\t *\n\t\t * @type {boolean}\n\t\t */\n\t\tuseRegistry: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: true,\n\t\t},\n\n\t\t/**\n\t\t * Integration ids to exclude when rendering registry-driven\n\t\t * tabs. Mirrors `hiddenTabs` for the legacy mode.\n\t\t *\n\t\t * @type {string[]}\n\t\t */\n\t\texcludeIntegrations: {\n\t\t\ttype: Array,\n\t\t\tdefault: () => [],\n\t\t},\n\n\t\t/** Whether the sidebar is open */\n\t\topen: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: true,\n\t\t},\n\n\t\t/** Sidebar title (defaults to objectType) */\n\t\ttitle: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/** Sidebar subtitle */\n\t\tsubtitle: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/** @deprecated Use `subtitle` instead. Alias kept for backwards compatibility. */\n\t\tsubtitleProp: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/** Base API URL for OpenRegister */\n\t\tapiBase: {\n\t\t\ttype: String,\n\t\t\tdefault: '/apps/openregister/api',\n\t\t},\n\n\t\t/**\n\t\t * Whether to auto-subscribe to live updates for the\n\t\t * current object. Defaults to true. The sidebar calls\n\t\t * `objectStore.subscribe(objectType, objectId)` on mount and\n\t\t * unsubscribes on unmount via `tryOnScopeDispose`.\n\t\t *\n\t\t * @type {boolean}\n\t\t */\n\t\tsubscribe: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: true,\n\t\t},\n\n\t\t/**\n\t\t * Optional explicit Pinia store instance. When omitted,\n\t\t * the sidebar skips auto-subscribe (Pinia not yet active\n\t\t * in the consumer context).\n\t\t *\n\t\t * @type {object|null}\n\t\t */\n\t\tobjectStore: {\n\t\t\ttype: Object,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t// --- Pre-translated labels ---\n\t\t/** Label for the Files tab */\n\t\tfilesLabel: { type: String, default: () => t('nextcloud-vue', 'Files') },\n\t\t/** Label for the Notes tab */\n\t\tnotesLabel: { type: String, default: () => t('nextcloud-vue', 'Notes') },\n\t\t/** Label for the Tags tab */\n\t\ttagsLabel: { type: String, default: () => t('nextcloud-vue', 'Tags') },\n\t\t/** Label for the Tasks tab */\n\t\ttasksLabel: { type: String, default: () => t('nextcloud-vue', 'Tasks') },\n\t\t/**\n\t\t * Source of the Tasks tab: `vtodo` (default, the record's linked Nextcloud\n\t\t * tasks) or `flow-tasks` (the OpenRegister flow tasks anchored on the\n\t\t * record, with create and per-row verbs). Passed to `CnTasksTab`.\n\t\t *\n\t\t * @type {'vtodo'|'flow-tasks'}\n\t\t */\n\t\ttasksSource: { type: String, default: 'vtodo', validator: (v) => ['vtodo', 'flow-tasks'].includes(v) },\n\t\t/** Label for the Audit Trail tab */\n\t\tauditTrailLabel: { type: String, default: () => t('nextcloud-vue', 'Audit trail') },\n\n\t\t/**\n\t\t * Open-enum tab definitions. When provided with at least one\n\t\t * entry, REPLACES the hard-coded built-in tabs (Files, Notes,\n\t\t * Tags, Tasks, Audit Trail). When unset (the default), the\n\t\t * built-in tabs render as today.\n\t\t *\n\t\t * Each entry shape:\n\t\t * - `id` (string, required) — unique tab id, used for active-tab tracking.\n\t\t * - `label` (string, required) — tab display label (caller-resolved i18n).\n\t\t * - `icon` (string, optional) — MDI icon name resolved via CnIcon.\n\t\t * - `widgets` (array, optional) — list of widget specs `{ type, props? }`\n\t\t * to render inside the tab. Built-in types: `data` → CnObjectDataWidget,\n\t\t * `metadata` → CnObjectMetadataWidget, `audit` / `audit-trail` →\n\t\t * CnAuditTrailTab, `object-table` → CnWidgetObjectTable (a declarative\n\t\t * list scoped to the parent object via `@objectId` / `@object.<field>`\n\t\t * filter tokens). Any other `type` resolves against the customComponents\n\t\t * registry.\n\t\t * - `component` (string, optional) — name resolved against the\n\t\t * customComponents registry. Mutually exclusive with `widgets`\n\t\t * (when both are set, `component` wins and a console.warn is logged).\n\t\t * - `order` (number, optional) — explicit order; defaults to array index + 1.\n\t\t *\n\t\t * @type {Array<{ id: string, label: string, icon?: string, widgets?: Array<{ type: string, props?: object }>, component?: string, order?: number }>|null}\n\t\t */\n\t\ttabs: {\n\t\t\ttype: Array,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/**\n\t\t * Custom-component registry. Keys are names referenced by\n\t\t * `tabs[].component` and unknown `tabs[].widgets[].type` values.\n\t\t * Falls back to the injected `cnCustomComponents` from a\n\t\t * CnAppRoot ancestor when omitted.\n\t\t *\n\t\t * @type {object|null}\n\t\t */\n\t\tcustomComponents: {\n\t\t\ttype: Object,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/**\n\t\t * Externally-requested active tab id. When set to a non-null id,\n\t\t * the sidebar switches to that tab — lets a host deep-link into a\n\t\t * specific leaf (e.g. a \"Linked apps\" row on the detail page that\n\t\t * opens the Mails tab). Leave null for normal internal tracking.\n\t\t *\n\t\t * @spec openspec/changes/case-page-and-list-as-a-place/specs/index-page/spec.md\n\t\t */\n\t\trequestedTab: {\n\t\t\ttype: String,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/**\n\t\t * Called with the tab this sidebar actually settled on, and whether\n\t\t * that was a correction rather than a reader's choice. A host that\n\t\t * keeps the tab in the address uses it to write the address, so the\n\t\t * address always names a tab this reader can actually see.\n\t\t *\n\t\t * @type {(tabId: string, canonicalising: boolean) => void}\n\t\t */\n\t\tonTabChange: {\n\t\t\ttype: Function,\n\t\t\tdefault: null,\n\t\t},\n\t},\n\n\temits: [\n\t\t'update:open',\n\t\t/**\n\t\t * The active tab changed. Payload is `{ tabId, canonicalising }`:\n\t\t * `canonicalising` is true when the sidebar corrected an address\n\t\t * naming a tab that does not exist or that this reader may not see,\n\t\t * rather than the reader choosing one.\n\t\t */\n\t\t'tab-change',\n\t\t/**\n\t\t * Forwarded unchanged from the built-in CnNotesTab after a note with\n\t\t * at least one `@mention` was saved. Payload:\n\t\t * `{ objectId, register, schema, noteId, mentionedUserIds }`.\n\t\t */\n\t\t'mention',\n\t],\n\n\tsetup(props) {\n\t\tconst exposed = {}\n\t\t// Integration registry: on by default via the `useRegistry`\n\t\t// prop (ADR-019). We always wire the composable up so consumers\n\t\t// can toggle `useRegistry` reactively without a remount.\n\t\tconst { integrations: registryIntegrations, resolveWidget, resolveTab } = useIntegrationRegistry()\n\t\texposed.registryIntegrations = registryIntegrations\n\t\texposed.resolveRegistryWidget = resolveWidget\n\t\t// `resolveTab` is local-first (LIB_INTEGRATION_COMPONENTS) so the\n\t\t// dispatched sidebar tab component is bound to this rendering\n\t\t// bundle's Vue — sidesteps the dual-runtime ADR-019 trap that\n\t\t// surfaced as `useNcFormBox(...)` undefined on cross-bundle\n\t\t// registrations. See openregister#1958.\n\t\texposed.resolveRegistryTabComponent = resolveTab\n\n\t\t// Object token context for sidebar-tab widgets that resolve `@objectId` /\n\t\t// `@object.<field>` tokens — the `object-table` built-in in particular\n\t\t// (e.g. a detail page's ZGW relation tab listing a zaak's besluiten,\n\t\t// filtered by `{ zaak: \"@objectId\" }`). Mirrors the reactive\n\t\t// `{ objectId, object, register, schema }` ref CnDetailPage provides.\n\t\t//\n\t\t// Provided ONLY when no ancestor already supplies `cnObjectContext`, so\n\t\t// a CnDetailPage parent's richer context (which carries the loaded\n\t\t// `object` for `@object.<field>`) keeps flowing through to the tab\n\t\t// widgets unchanged. When the sidebar is mounted standalone (no detail\n\t\t// page ancestor) it seeds the context from its own props — enough for\n\t\t// `@objectId` + register/schema resolution.\n\t\tconst parentObjectContext = inject('cnObjectContext', null)\n\t\tif (!parentObjectContext) {\n\t\t\tconst cnObjectContext = ref({\n\t\t\t\tobjectId: props.objectId || null,\n\t\t\t\tobject: null,\n\t\t\t\tregister: props.register || '',\n\t\t\t\tschema: props.schema || '',\n\t\t\t})\n\t\t\tprovide('cnObjectContext', cnObjectContext)\n\t\t\twatch(\n\t\t\t\t() => [props.objectId, props.register, props.schema],\n\t\t\t\t() => {\n\t\t\t\t\tcnObjectContext.value = {\n\t\t\t\t\t\tobjectId: props.objectId || null,\n\t\t\t\t\t\tobject: cnObjectContext.value.object || null,\n\t\t\t\t\t\tregister: props.register || '',\n\t\t\t\t\t\tschema: props.schema || '',\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t)\n\t\t}\n\n\t\t// Auto-subscribe to live updates for the active object. No-op\n\t\t// when `objectStore` is null (no Pinia active) or when the\n\t\t// consumer disabled it via `subscribe: false`. The\n\t\t// composable's reactive `id` argument keeps the subscription\n\t\t// in sync as the user navigates between sidebar objects.\n\t\tif (props.objectStore && props.subscribe) {\n\t\t\tuseObjectSubscription(\n\t\t\t\tprops.objectStore,\n\t\t\t\t() => props.objectType,\n\t\t\t\t() => props.objectId,\n\t\t\t\t{ enabled: () => Boolean(props.objectType && props.objectId) },\n\t\t\t)\n\t\t}\n\t\treturn exposed\n\t},\n\n\tdata() {\n\t\treturn {\n\t\t\tactiveTab: this.requestedTab || this.computeInitialActiveTab(),\n\t\t\t// The tab id already warned about, so an address naming a tab the\n\t\t\t// reader cannot see says so once rather than on every render.\n\t\t\twarnedTabId: null,\n\t\t}\n\t},\n\n\tcomputed: {\n\t\tsidebarTitle() {\n\t\t\treturn this.shown(this.title) || this.objectType || 'Details'\n\t\t},\n\n\t\tsidebarSubtitle() {\n\t\t\treturn this.subtitle || this.subtitleProp || ''\n\t\t},\n\n\t\t/** Whether the consumer has supplied a custom `tabs` array. */\n\t\thasCustomTabs() {\n\t\t\treturn Array.isArray(this.tabs) && this.tabs.length > 0\n\t\t},\n\n\t\t/**\n\t\t * Whether registry mode is active. Custom `tabs` always wins\n\t\t * (with a warning at mount) so consumers don't get a surprise\n\t\t * mode switch.\n\t\t */\n\t\tisRegistryMode() {\n\t\t\treturn this.useRegistry === true && this.hasCustomTabs === false\n\t\t},\n\n\t\t/**\n\t\t * Filtered registry snapshot: drops providers whose id is in\n\t\t * `excludeIntegrations` or `hiddenTabs`. Stays reactive on\n\t\t * the underlying registry's `onChange` notifications.\n\t\t */\n\t\tfilteredRegistryIntegrations() {\n\t\t\tconst excluded = new Set([\n\t\t\t\t...(this.excludeIntegrations || []),\n\t\t\t\t...(this.hiddenTabs || []),\n\t\t\t])\n\t\t\tconst all = this.registryIntegrations || []\n\t\t\treturn all.filter((p) => excluded.has(p.id) === false)\n\t\t},\n\n\t\t/** Effective customComponents registry: prop wins, inject fallback. */\n\t\teffectiveCustomComponents() {\n\t\t\treturn this.customComponents || this.cnCustomComponents || {}\n\t\t},\n\n\t\t/**\n\t\t * Effective v2 component registry (ADR-036). Kind-tagged entries\n\t\t * keyed by component name. Consulted by `resolveTabComponent` so a\n\t\t * tab's `component` ref resolves against the registry as well as the\n\t\t * legacy `customComponents` map.\n\t\t */\n\t\teffectiveRegistry() {\n\t\t\treturn this.cnRegistry || {}\n\t\t},\n\n\t\t/**\n\t\t * Shared object context forwarded to every widget / component\n\t\t * mounted inside a custom tab — same context the built-in tabs\n\t\t * receive today.\n\t\t */\n\t\tsharedTabProps() {\n\t\t\treturn {\n\t\t\t\tobjectId: this.objectId,\n\t\t\t\tobjectType: this.objectType,\n\t\t\t\tregister: this.register,\n\t\t\t\tschema: this.schema,\n\t\t\t\tapiBase: this.apiBase,\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Context forwarded to a mount-mode leaf's `mount(el, props)` for the\n\t\t * single-entity sidebar surface — the same shape an SFC tab receives,\n\t\t * plus the `surface` name and an `integrationContext` bag. Reactive\n\t\t * on the object identity so CnLeafMountHost re-mounts on object change.\n\t\t */\n\t\tsidebarMountProps() {\n\t\t\treturn {\n\t\t\t\t...this.sharedTabProps,\n\t\t\t\tsurface: 'single-entity',\n\t\t\t\tintegrationContext: {\n\t\t\t\t\tregister: this.register,\n\t\t\t\t\tschema: this.schema,\n\t\t\t\t\tobjectId: this.objectId,\n\t\t\t\t},\n\t\t\t}\n\t\t},\n\t},\n\n\twatch: {\n\t\ttabs: {\n\t\t\timmediate: false,\n\t\t\t/**\n\t\t\t * Re-anchor the active tab when the tab set changes, so the\n\t\t\t * active id stays one the reader can actually see.\n\t\t\t *\n\t\t\t * @spec openspec/changes/case-page-and-list-as-a-place/specs/index-page/spec.md\n\t\t\t */\n\t\t\thandler() {\n\t\t\t\t// Re-anchor activeTab when the tab set changes so the\n\t\t\t\t// active id stays valid (otherwise NcAppSidebar shows no\n\t\t\t\t// active tab when the consumer swaps in a fresh array).\n\t\t\t\tthis.settleOnTab(this.requestedTab)\n\t\t\t},\n\t\t},\n\n\t\t/**\n\t\t * Host deep-link: settle on the requested tab when it changes, which\n\t\t * is how an address naming a tab reaches the tab strip.\n\t\t *\n\t\t * @param {string} id The tab asked for.\n\t\t * @spec openspec/changes/case-page-and-list-as-a-place/specs/index-page/spec.md\n\t\t */\n\t\trequestedTab(id) {\n\t\t\tif (id) {\n\t\t\t\tthis.settleOnTab(id)\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * The reader clicked a tab. Reported back so a host keeping the tab\n\t\t * in the address writes it there, which is what makes a tab linkable.\n\t\t *\n\t\t * @param {string} id The tab now active.\n\t\t * @param {string} previous The tab before it.\n\t\t * @spec openspec/changes/case-page-and-list-as-a-place/specs/index-page/spec.md\n\t\t */\n\t\tactiveTab(id, previous) {\n\t\t\tif (id && previous !== undefined && id !== previous && typeof this.onTabChange === 'function') {\n\t\t\t\tthis.onTabChange(id, false)\n\t\t\t}\n\t\t},\n\t},\n\n\t/**\n\t * Settle on a tab on arrival, and warn about a tab set the consumer\n\t * declared two ways.\n\t *\n\t * @spec openspec/changes/case-page-and-list-as-a-place/specs/index-page/spec.md\n\t */\n\tmounted() {\n\t\t// Settle on arrival, so an address carrying no tab is corrected to\n\t\t// its canonical form once rather than staying tabless until the\n\t\t// reader happens to click something (ADR-052).\n\t\tif (typeof this.onTabChange === 'function') {\n\t\t\tthis.settleOnTab(this.requestedTab)\n\t\t}\n\t\tif (this.useRegistry === true && this.hasCustomTabs === true) {\n\t\t\t// eslint-disable-next-line no-console\n\t\t\tconsole.warn('[CnObjectSidebar] `useRegistry` is true but `tabs` is also set — falling back to `tabs` (registry mode ignored). Pass one or the other.')\n\t\t}\n\t},\n\n\tmethods: {\n\n\t\t/**\n\t\t * A manifest label through the injected lookup, or as written.\n\t\t *\n\t\t * @param {string} text The label as written.\n\t\t * @return {string} The label in the user's language.\n\t\t */\n\t\tshown(text) {\n\t\t\treturn typeof this.cnTranslate === 'function' && typeof text === 'string' && text !== '' ? this.cnTranslate(text) : text\n\t\t},\n\n\t\t/**\n\t\t * The `lang` of a label that fell back to its written text in another language.\n\t\t *\n\t\t * @param {string} text The label as written.\n\t\t * @return {string|undefined} The source language, or undefined.\n\t\t */\n\t\tlangOf(text) {\n\t\t\treturn labelLang(this.cnTranslate, text) || undefined\n\t\t},\n\n\t\tisTabHidden(tabId) {\n\t\t\treturn this.hiddenTabs.includes(tabId)\n\t\t},\n\n\t\t/**\n\t\t * Resolve a registry provider's tab component, preferring the\n\t\t * LOCAL lib-owned component (rendering-bundle Vue) over the\n\t\t * shared registry's stored object. Falls back to the stored\n\t\t * `provider.tab` for consumer-custom ids (which live in the\n\t\t * consumer's own bundle and therefore render under the same\n\t\t * Vue instance with no mismatch). See openregister#1958.\n\t\t *\n\t\t * @param {object} provider Normalised registry entry.\n\t\t * @return {object|null} Vue component, or null.\n\t\t */\n\t\tresolveRegistryTab(provider) {\n\t\t\tif (!provider || typeof provider.id !== 'string') {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tconst local = this.resolveRegistryTabComponent(provider.id)\n\t\t\tif (local) {\n\t\t\t\treturn local\n\t\t\t}\n\t\t\treturn provider.tab || null\n\t\t},\n\n\t\t/**\n\t\t * Whether a registry provider renders via the mount hand-off\n\t\t * (`renderMode: 'mount'`, openregister#2127) rather than an SFC tab.\n\t\t * Mount-mode leaves carry `mount`/`unmount` functions the host calls\n\t\t * against a bare element via CnLeafMountHost.\n\t\t *\n\t\t * @param {object} provider Normalised registry entry.\n\t\t * @return {boolean} true when the provider is mount-mode.\n\t\t */\n\t\tisMountProvider(provider) {\n\t\t\treturn Boolean(provider)\n\t\t\t\t&& provider.renderMode === 'mount'\n\t\t\t\t&& typeof provider.mount === 'function'\n\t\t\t\t&& typeof provider.unmount === 'function'\n\t\t},\n\n\t\t/**\n\t\t * Pick a sensible default active tab on mount and on tabs[]\n\t\t * changes. When custom tabs are present, the first entry wins.\n\t\t * When unset, the built-in `files` tab is the default (matches\n\t\t * the legacy behavior).\n\t\t */\n\t\tcomputeInitialActiveTab() {\n\t\t\tif (Array.isArray(this.tabs) && this.tabs.length > 0) {\n\t\t\t\treturn this.tabs[0].id\n\t\t\t}\n\t\t\treturn 'files'\n\t\t},\n\n\t\t/**\n\t\t * The tab ids this reader can actually see, in the order shown.\n\t\t *\n\t\t * Three tab sources, one answer. Without this the address could name\n\t\t * a tab that is hidden, excluded or simply not registered, and the\n\t\t * sidebar would show its first tab while the address went on claiming\n\t\t * a different one.\n\t\t *\n\t\t * @return {Array<string>} The visible tab ids.\n\t\t * @spec openspec/changes/case-page-and-list-as-a-place/specs/index-page/spec.md\n\t\t */\n\t\tvisibleTabIds() {\n\t\t\tif (this.isRegistryMode) {\n\t\t\t\treturn (this.filteredRegistryIntegrations || []).map((p) => p.id)\n\t\t\t}\n\t\t\tif (Array.isArray(this.tabs) && this.tabs.length > 0) {\n\t\t\t\treturn this.tabs.filter((tab) => tab && !this.isTabHidden(tab.id)).map((tab) => tab.id)\n\t\t\t}\n\t\t\treturn ['files', 'notes', 'tags', 'tasks', 'auditTrail'].filter((id) => !this.isTabHidden(id))\n\t\t},\n\n\t\t/**\n\t\t * Settle on a tab, and say whether the address had to be corrected.\n\t\t *\n\t\t * An address naming a tab that does not exist, or one this reader may\n\t\t * not see, falls back to the first tab they can see and says so ONCE.\n\t\t * Silently showing a different tab than the address names is the\n\t\t * failure here: the reader then sends a colleague a link that opens\n\t\t * somewhere else again.\n\t\t *\n\t\t * @param {string|null} requested The tab the address asked for.\n\t\t * @return {{ tabId: string, canonicalising: boolean }} The tab to show.\n\t\t * @spec openspec/changes/case-page-and-list-as-a-place/specs/index-page/spec.md\n\t\t */\n\t\tresolveTabRequest(requested) {\n\t\t\tconst visible = this.visibleTabIds\n\t\t\tconst fallback = visible[0] || this.computeInitialActiveTab()\n\t\t\tif (!requested) {\n\t\t\t\treturn { tabId: fallback, canonicalising: true }\n\t\t\t}\n\t\t\tif (visible.length === 0 || visible.includes(requested)) {\n\t\t\t\treturn { tabId: requested, canonicalising: false }\n\t\t\t}\n\t\t\tif (this.warnedTabId !== requested) {\n\t\t\t\tthis.warnedTabId = requested\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.warn(`[CnObjectSidebar] The address asks for the \"${requested}\" tab, which is not available here. Showing \"${fallback}\" instead.`)\n\t\t\t}\n\t\t\treturn { tabId: fallback, canonicalising: true }\n\t\t},\n\n\t\t/**\n\t\t * Show a tab and tell the host, so the address can follow.\n\t\t *\n\t\t * @param {string|null} requested The tab asked for.\n\t\t * @spec openspec/changes/case-page-and-list-as-a-place/specs/index-page/spec.md\n\t\t */\n\t\tsettleOnTab(requested) {\n\t\t\tconst { tabId, canonicalising } = this.resolveTabRequest(requested)\n\t\t\tthis.activeTab = tabId\n\t\t\tif (typeof this.onTabChange === 'function') {\n\t\t\t\tthis.onTabChange(tabId, canonicalising)\n\t\t\t}\n\t\t\t/**\n\t\t\t * @event tab-change Emitted when the active tab settles, including when the sidebar corrected the address.\n\t\t\t * @type {{ tabId: string, canonicalising: boolean }}\n\t\t\t */\n\t\t\tthis.$emit('tab-change', { tabId, canonicalising })\n\t\t},\n\n\t\t/**\n\t\t * Build the prop bag for a widget in the `widgets[]` tab path. All\n\t\t * widgets get the shared coordinate context plus the loaded object\n\t\t * (`objectData`); the prop-driven `data` built-in also gets the schema\n\t\t * OBJECT bound to its `schema` prop (the other tabs use the `schema`\n\t\t * slug string, so the override is scoped to `type: 'data'`). Of a\n\t\t * widget's own `props`, the ones its component declares win on overlap;\n\t\t * an undeclared one would only fall through onto the component's root.\n\t\t *\n\t\t * @spec openspec/changes/declared-props-detail-index-sidebar/specs/widget-hosts/spec.md#requirement-a-widget-host-passes-only-the-keys-a-widget-declares\n\t\t * @param {{ type: string, props?: object }} w Widget spec\n\t\t * @return {object} Props to v-bind onto the resolved widget component\n\t\t */\n\t\twidgetBindings(w) {\n\t\t\tconst bindings = { ...this.sharedTabProps, objectData: this.objectData }\n\t\t\tif (w.type === 'data') {\n\t\t\t\t// CnObjectDataWidget wants the schema OBJECT, never the slug the\n\t\t\t\t// other tabs use. Pass the resolved object (null until it loads —\n\t\t\t\t// the widget renders its empty state meanwhile) so it never sees\n\t\t\t\t// a String `schema`.\n\t\t\t\tbindings.schema = this.objectSchema\n\t\t\t}\n\t\t\treturn { ...bindings, ...pickDeclaredProps(this.resolveWidgetComponent(w.type), w.props || {}, w.type || '') }\n\t\t},\n\n\t\t/**\n\t\t * Resolve a widget type to a component. Built-in types (`data`,\n\t\t * `metadata`, `audit` / `audit-trail`, `object-table`) map to their\n\t\t * lib component; any other type resolves against the v2 registry, then\n\t\t * the legacy customComponents map. Logs a console.warn and returns null when nothing\n\t\t * resolves.\n\t\t *\n\t\t * @param {string} type Widget type identifier\n\t\t * @return {object|null} Vue component, or null when unresolved\n\t\t */\n\t\tresolveWidgetComponent(type) {\n\t\t\tif (BUILTIN_WIDGETS[type]) {\n\t\t\t\treturn BUILTIN_WIDGETS[type]\n\t\t\t}\n\t\t\tconst registryEntry = this.effectiveRegistry[type]\n\t\t\tif (registryEntry && registryEntry.component) {\n\t\t\t\treturn registryEntry.component\n\t\t\t}\n\t\t\tconst reg = this.effectiveCustomComponents\n\t\t\tif (reg && reg[type]) {\n\t\t\t\treturn reg[type]\n\t\t\t}\n\t\t\t// eslint-disable-next-line no-console\n\t\t\tconsole.warn(`[CnObjectSidebar] Unknown widget type \"${type}\" — not in built-ins (data, metadata, audit, audit-trail, object-table, object-permissions), the registry or customComponents.`)\n\t\t\treturn null\n\t\t},\n\n\t\t/**\n\t\t * Resolve a tab's `component` registry name. Logs a\n\t\t * console.warn when both `widgets` and `component` are set\n\t\t * (component wins) or when the registry name is missing.\n\t\t *\n\t\t * @param {object} tab Tab definition\n\t\t * @return {object|null} Vue component, or null when unresolved\n\t\t */\n\t\tresolveTabComponent(tab) {\n\t\t\tif (tab.widgets && tab.widgets.length > 0) {\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.warn(`[CnObjectSidebar] Tab \"${tab.id}\" declares both widgets[] and component — component wins, widgets are ignored.`)\n\t\t\t}\n\t\t\t// v2 registry first (ADR-036): any kind-tagged entry with a\n\t\t\t// `component` field is acceptable for a slot/tab lookup — this\n\t\t\t// is what lets a `kind: 'page'` tab component (the procest\n\t\t\t// pattern) render. Fall back to the legacy customComponents map.\n\t\t\tconst registryEntry = this.effectiveRegistry[tab.component]\n\t\t\tif (registryEntry && registryEntry.component) {\n\t\t\t\treturn registryEntry.component\n\t\t\t}\n\t\t\tconst reg = this.effectiveCustomComponents\n\t\t\tconst resolved = reg && reg[tab.component]\n\t\t\tif (!resolved) {\n\t\t\t\t// eslint-disable-next-line no-console\n\t\t\t\tconsole.warn(`[CnObjectSidebar] Tab \"${tab.id}\" component \"${tab.component}\" not found in registry or customComponents.`)\n\t\t\t\treturn null\n\t\t\t}\n\t\t\treturn resolved\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n/* NcAppSidebar lays every tab out as an equal share of the sidebar width\n * (`flex: 1 1`) with an ellipsis caption, so an object with many tabs — e.g. a\n * lead's 5+ tabs — shrinks them until the labels truncate. Keep the tabs\n * equal-width (uniform) but stop them shrinking below a readable minimum, and\n * let the strip scroll horizontally once they no longer fit. `flex-basis: 0`\n * + equal grow keeps every tab the same width whether the row fits or scrolls.\n * Apps with longer labels can widen the floor via --cn-sidebar-tab-min-width. */\n:deep(.app-sidebar-tabs__nav) {\n\toverflow-x: auto;\n}\n\n:deep(.app-sidebar-tabs__nav .app-sidebar-tabs__tab) {\n\tflex-grow: 1;\n\tflex-shrink: 0;\n\tflex-basis: 0;\n\t/* !important to beat NcAppSidebar's own min-width on the button variant. */\n\tmin-width: var(--cn-sidebar-tab-min-width, 7rem) !important;\n}\n</style>\n"],"names":["_createBlock","_Fragment","_openBlock","_createElementBlock","_renderList","_resolveDynamicComponent","_createVNode","_renderSlot","_mergeProps"],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import script from './CnObjectTranslationsWidget.vue2.js';
2
+ import { render } from './CnObjectTranslationsWidget.vue3.js';
3
+
4
+ script.render = render;
5
+ script.__scopeId = "data-v-c25058de";
6
+ const __sfc_main = script;
7
+
8
+ export { __sfc_main as default };
9
+ //# sourceMappingURL=CnObjectTranslationsWidget.vue.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CnObjectTranslationsWidget.vue.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;"}