@conduction/nextcloud-vue 2.59.0 → 2.61.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 (254) hide show
  1. package/dist/esm/components/CnActionsMenu/CnActionsMenu.vue2.js +14 -1
  2. package/dist/esm/components/CnActionsMenu/CnActionsMenu.vue2.js.map +1 -1
  3. package/dist/esm/components/CnActionsMenu/CnActionsMenu.vue3.js.map +1 -1
  4. package/dist/esm/components/CnAppNav/CnAppNav.vue2.js +80 -1
  5. package/dist/esm/components/CnAppNav/CnAppNav.vue2.js.map +1 -1
  6. package/dist/esm/components/CnAppNav/CnAppNav.vue3.js +46 -4
  7. package/dist/esm/components/CnAppNav/CnAppNav.vue3.js.map +1 -1
  8. package/dist/esm/components/CnBannerWidget/CnBannerWidget.vue2.js +232 -10
  9. package/dist/esm/components/CnBannerWidget/CnBannerWidget.vue2.js.map +1 -1
  10. package/dist/esm/components/CnBannerWidget/CnBannerWidget.vue3.js +79 -25
  11. package/dist/esm/components/CnBannerWidget/CnBannerWidget.vue3.js.map +1 -1
  12. package/dist/esm/components/CnBannerWidgetForm/CnBannerWidgetForm.vue2.js +42 -3
  13. package/dist/esm/components/CnBannerWidgetForm/CnBannerWidgetForm.vue2.js.map +1 -1
  14. package/dist/esm/components/CnBannerWidgetForm/CnBannerWidgetForm.vue3.js +39 -6
  15. package/dist/esm/components/CnBannerWidgetForm/CnBannerWidgetForm.vue3.js.map +1 -1
  16. package/dist/esm/components/CnBoardView/CnBoardView.vue2.js +46 -0
  17. package/dist/esm/components/CnBoardView/CnBoardView.vue2.js.map +1 -1
  18. package/dist/esm/components/CnBoardView/CnBoardView.vue3.js +11 -4
  19. package/dist/esm/components/CnBoardView/CnBoardView.vue3.js.map +1 -1
  20. package/dist/esm/components/CnBrandStripe/CnBrandStripe.vue.js +10 -0
  21. package/dist/esm/components/CnBrandStripe/CnBrandStripe.vue.js.map +1 -0
  22. package/dist/esm/components/CnBrandStripe/CnBrandStripe.vue2.js +39 -0
  23. package/dist/esm/components/CnBrandStripe/CnBrandStripe.vue2.js.map +1 -0
  24. package/dist/esm/components/CnBrandStripe/CnBrandStripe.vue3.js +16 -0
  25. package/dist/esm/components/CnBrandStripe/CnBrandStripe.vue3.js.map +1 -0
  26. package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue2.js +117 -1
  27. package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue2.js.map +1 -1
  28. package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue3.js +147 -89
  29. package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue3.js.map +1 -1
  30. package/dist/esm/components/CnConversationThread/CnConversationThread.vue.js +10 -0
  31. package/dist/esm/components/CnConversationThread/CnConversationThread.vue.js.map +1 -0
  32. package/dist/esm/components/CnConversationThread/CnConversationThread.vue2.js +259 -0
  33. package/dist/esm/components/CnConversationThread/CnConversationThread.vue2.js.map +1 -0
  34. package/dist/esm/components/CnConversationThread/CnConversationThread.vue3.js +131 -0
  35. package/dist/esm/components/CnConversationThread/CnConversationThread.vue3.js.map +1 -0
  36. package/dist/esm/components/CnConversationThread/CnConversationWidget.vue.js +10 -0
  37. package/dist/esm/components/CnConversationThread/CnConversationWidget.vue.js.map +1 -0
  38. package/dist/esm/components/CnConversationThread/CnConversationWidget.vue2.js +116 -0
  39. package/dist/esm/components/CnConversationThread/CnConversationWidget.vue2.js.map +1 -0
  40. package/dist/esm/components/CnConversationThread/CnConversationWidget.vue3.js +24 -0
  41. package/dist/esm/components/CnConversationThread/CnConversationWidget.vue3.js.map +1 -0
  42. package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue2.js +10 -2
  43. package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue2.js.map +1 -1
  44. package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue3.js.map +1 -1
  45. package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js +503 -28
  46. package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js.map +1 -1
  47. package/dist/esm/components/CnDetailPage/CnDetailPage.vue3.js +303 -144
  48. package/dist/esm/components/CnDetailPage/CnDetailPage.vue3.js.map +1 -1
  49. package/dist/esm/components/CnDocumentReviewList/CnDocumentReviewList.vue.js +10 -0
  50. package/dist/esm/components/CnDocumentReviewList/CnDocumentReviewList.vue.js.map +1 -0
  51. package/dist/esm/components/CnDocumentReviewList/CnDocumentReviewList.vue2.js +237 -0
  52. package/dist/esm/components/CnDocumentReviewList/CnDocumentReviewList.vue2.js.map +1 -0
  53. package/dist/esm/components/CnDocumentReviewList/CnDocumentReviewList.vue3.js +120 -0
  54. package/dist/esm/components/CnDocumentReviewList/CnDocumentReviewList.vue3.js.map +1 -0
  55. package/dist/esm/components/CnDocumentReviewList/CnDocumentReviewWidget.vue.js +10 -0
  56. package/dist/esm/components/CnDocumentReviewList/CnDocumentReviewWidget.vue.js.map +1 -0
  57. package/dist/esm/components/CnDocumentReviewList/CnDocumentReviewWidget.vue2.js +77 -0
  58. package/dist/esm/components/CnDocumentReviewList/CnDocumentReviewWidget.vue2.js.map +1 -0
  59. package/dist/esm/components/CnDocumentReviewList/CnDocumentReviewWidget.vue3.js +27 -0
  60. package/dist/esm/components/CnDocumentReviewList/CnDocumentReviewWidget.vue3.js.map +1 -0
  61. package/dist/esm/components/CnHeaderWidget/CnHeaderWidget.vue2.js +171 -12
  62. package/dist/esm/components/CnHeaderWidget/CnHeaderWidget.vue2.js.map +1 -1
  63. package/dist/esm/components/CnHeaderWidget/CnHeaderWidget.vue3.js +15 -7
  64. package/dist/esm/components/CnHeaderWidget/CnHeaderWidget.vue3.js.map +1 -1
  65. package/dist/esm/components/CnHeaderWidgetForm/CnHeaderWidgetForm.vue2.js +37 -3
  66. package/dist/esm/components/CnHeaderWidgetForm/CnHeaderWidgetForm.vue2.js.map +1 -1
  67. package/dist/esm/components/CnHeaderWidgetForm/CnHeaderWidgetForm.vue3.js +44 -16
  68. package/dist/esm/components/CnHeaderWidgetForm/CnHeaderWidgetForm.vue3.js.map +1 -1
  69. package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js +132 -3
  70. package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js.map +1 -1
  71. package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js +6 -3
  72. package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js.map +1 -1
  73. package/dist/esm/components/CnLinkCardsPage/CnLinkCardsPage.vue.js +10 -0
  74. package/dist/esm/components/CnLinkCardsPage/CnLinkCardsPage.vue.js.map +1 -0
  75. package/dist/esm/components/CnLinkCardsPage/CnLinkCardsPage.vue2.js +316 -0
  76. package/dist/esm/components/CnLinkCardsPage/CnLinkCardsPage.vue2.js.map +1 -0
  77. package/dist/esm/components/CnLinkCardsPage/CnLinkCardsPage.vue3.js +105 -0
  78. package/dist/esm/components/CnLinkCardsPage/CnLinkCardsPage.vue3.js.map +1 -0
  79. package/dist/esm/components/CnNextStepCard/CnNextStepCard.vue.js +10 -0
  80. package/dist/esm/components/CnNextStepCard/CnNextStepCard.vue.js.map +1 -0
  81. package/dist/esm/components/CnNextStepCard/CnNextStepCard.vue2.js +150 -0
  82. package/dist/esm/components/CnNextStepCard/CnNextStepCard.vue2.js.map +1 -0
  83. package/dist/esm/components/CnNextStepCard/CnNextStepCard.vue3.js +106 -0
  84. package/dist/esm/components/CnNextStepCard/CnNextStepCard.vue3.js.map +1 -0
  85. package/dist/esm/components/CnNextStepCard/CnNextStepWidget.vue.js +9 -0
  86. package/dist/esm/components/CnNextStepCard/CnNextStepWidget.vue.js.map +1 -0
  87. package/dist/esm/components/CnNextStepCard/CnNextStepWidget.vue2.js +47 -0
  88. package/dist/esm/components/CnNextStepCard/CnNextStepWidget.vue2.js.map +1 -0
  89. package/dist/esm/components/CnNextStepCard/CnNextStepWidget.vue3.js +17 -0
  90. package/dist/esm/components/CnNextStepCard/CnNextStepWidget.vue3.js.map +1 -0
  91. package/dist/esm/components/CnObjectDataWidget/CnObjectDataWidget.vue2.js +49 -0
  92. package/dist/esm/components/CnObjectDataWidget/CnObjectDataWidget.vue2.js.map +1 -1
  93. package/dist/esm/components/CnObjectDataWidget/CnObjectDataWidget.vue3.js.map +1 -1
  94. package/dist/esm/components/CnObjectDataWidgetForm/CnObjectDataWidgetForm.vue2.js +6 -0
  95. package/dist/esm/components/CnObjectDataWidgetForm/CnObjectDataWidgetForm.vue2.js.map +1 -1
  96. package/dist/esm/components/CnObjectDataWidgetForm/CnObjectDataWidgetForm.vue3.js.map +1 -1
  97. package/dist/esm/components/CnObjectKanban/CnObjectKanban.vue2.js +46 -0
  98. package/dist/esm/components/CnObjectKanban/CnObjectKanban.vue2.js.map +1 -1
  99. package/dist/esm/components/CnObjectKanban/CnObjectKanban.vue3.js +15 -3
  100. package/dist/esm/components/CnObjectKanban/CnObjectKanban.vue3.js.map +1 -1
  101. package/dist/esm/components/CnPageRenderer/pageTypes.js +1 -0
  102. package/dist/esm/components/CnPageRenderer/pageTypes.js.map +1 -1
  103. package/dist/esm/components/CnQuickFilterBar/CnQuickFilterBar.vue2.js +37 -1
  104. package/dist/esm/components/CnQuickFilterBar/CnQuickFilterBar.vue2.js.map +1 -1
  105. package/dist/esm/components/CnQuickFilterBar/CnQuickFilterBar.vue3.js +29 -13
  106. package/dist/esm/components/CnQuickFilterBar/CnQuickFilterBar.vue3.js.map +1 -1
  107. package/dist/esm/components/CnSavedViewsControl/CnSavedViewsControl.vue2.js +50 -3
  108. package/dist/esm/components/CnSavedViewsControl/CnSavedViewsControl.vue2.js.map +1 -1
  109. package/dist/esm/components/CnSavedViewsControl/CnSavedViewsControl.vue3.js.map +1 -1
  110. package/dist/esm/components/CnSegmentedControl/CnSegmentedControl.vue.js +10 -0
  111. package/dist/esm/components/CnSegmentedControl/CnSegmentedControl.vue.js.map +1 -0
  112. package/dist/esm/components/CnSegmentedControl/CnSegmentedControl.vue2.js +186 -0
  113. package/dist/esm/components/CnSegmentedControl/CnSegmentedControl.vue2.js.map +1 -0
  114. package/dist/esm/components/CnSegmentedControl/CnSegmentedControl.vue3.js +46 -0
  115. package/dist/esm/components/CnSegmentedControl/CnSegmentedControl.vue3.js.map +1 -0
  116. package/dist/esm/components/CnStackedBarWidget/CnStackedBarWidget.vue.js +11 -0
  117. package/dist/esm/components/CnStackedBarWidget/CnStackedBarWidget.vue.js.map +1 -0
  118. package/dist/esm/components/CnStackedBarWidget/CnStackedBarWidget.vue2.js +298 -0
  119. package/dist/esm/components/CnStackedBarWidget/CnStackedBarWidget.vue2.js.map +1 -0
  120. package/dist/esm/components/CnStackedBarWidget/CnStackedBarWidget.vue3.js +77 -0
  121. package/dist/esm/components/CnStackedBarWidget/CnStackedBarWidget.vue3.js.map +1 -0
  122. package/dist/esm/components/CnStackedBarWidgetForm/CnStackedBarWidgetForm.vue.js +10 -0
  123. package/dist/esm/components/CnStackedBarWidgetForm/CnStackedBarWidgetForm.vue.js.map +1 -0
  124. package/dist/esm/components/CnStackedBarWidgetForm/CnStackedBarWidgetForm.vue2.js +169 -0
  125. package/dist/esm/components/CnStackedBarWidgetForm/CnStackedBarWidgetForm.vue2.js.map +1 -0
  126. package/dist/esm/components/CnStackedBarWidgetForm/CnStackedBarWidgetForm.vue3.js +48 -0
  127. package/dist/esm/components/CnStackedBarWidgetForm/CnStackedBarWidgetForm.vue3.js.map +1 -0
  128. package/dist/esm/components/CnTabs/CnTab.vue2.js +35 -0
  129. package/dist/esm/components/CnTabs/CnTab.vue2.js.map +1 -1
  130. package/dist/esm/components/CnTabs/CnTab.vue3.js.map +1 -1
  131. package/dist/esm/components/CnTabs/CnTabs.vue2.js +120 -7
  132. package/dist/esm/components/CnTabs/CnTabs.vue2.js.map +1 -1
  133. package/dist/esm/components/CnTabs/CnTabs.vue3.js +57 -5
  134. package/dist/esm/components/CnTabs/CnTabs.vue3.js.map +1 -1
  135. package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue2.js +59 -4
  136. package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue2.js.map +1 -1
  137. package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue3.js +6 -2
  138. package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue3.js.map +1 -1
  139. package/dist/esm/components/CnWeekStripWidget/CnWeekStripWidget.vue.js +10 -0
  140. package/dist/esm/components/CnWeekStripWidget/CnWeekStripWidget.vue.js.map +1 -0
  141. package/dist/esm/components/CnWeekStripWidget/CnWeekStripWidget.vue2.js +484 -0
  142. package/dist/esm/components/CnWeekStripWidget/CnWeekStripWidget.vue2.js.map +1 -0
  143. package/dist/esm/components/CnWeekStripWidget/CnWeekStripWidget.vue3.js +115 -0
  144. package/dist/esm/components/CnWeekStripWidget/CnWeekStripWidget.vue3.js.map +1 -0
  145. package/dist/esm/components/CnWeekStripWidgetForm/CnWeekStripWidgetForm.vue.js +10 -0
  146. package/dist/esm/components/CnWeekStripWidgetForm/CnWeekStripWidgetForm.vue.js.map +1 -0
  147. package/dist/esm/components/CnWeekStripWidgetForm/CnWeekStripWidgetForm.vue2.js +189 -0
  148. package/dist/esm/components/CnWeekStripWidgetForm/CnWeekStripWidgetForm.vue2.js.map +1 -0
  149. package/dist/esm/components/CnWeekStripWidgetForm/CnWeekStripWidgetForm.vue3.js +74 -0
  150. package/dist/esm/components/CnWeekStripWidgetForm/CnWeekStripWidgetForm.vue3.js.map +1 -0
  151. package/dist/esm/components/CnWidgetGrid/registerDashboardWidgets.js +82 -8
  152. package/dist/esm/components/CnWidgetGrid/registerDashboardWidgets.js.map +1 -1
  153. package/dist/esm/index.js +16 -0
  154. package/dist/esm/index.js.map +1 -1
  155. package/dist/esm/l10n/en.json.js +55 -1
  156. package/dist/esm/l10n/en.json.js.map +1 -1
  157. package/dist/esm/l10n/nl.json.js +55 -1
  158. package/dist/esm/l10n/nl.json.js.map +1 -1
  159. package/dist/esm/nextcloud-vue.css +1036 -19
  160. package/dist/esm/utils/dateVariant.js +124 -0
  161. package/dist/esm/utils/dateVariant.js.map +1 -0
  162. package/dist/esm/utils/detailActionModel.js +260 -0
  163. package/dist/esm/utils/detailActionModel.js.map +1 -0
  164. package/dist/esm/utils/dueRule.js +84 -0
  165. package/dist/esm/utils/dueRule.js.map +1 -0
  166. package/dist/esm/utils/fetchAggregate.js +37 -1
  167. package/dist/esm/utils/fetchAggregate.js.map +1 -1
  168. package/dist/esm/utils/fetchFilterCounts.js +186 -0
  169. package/dist/esm/utils/fetchFilterCounts.js.map +1 -0
  170. package/dist/esm/utils/headers.js +28 -2
  171. package/dist/esm/utils/headers.js.map +1 -1
  172. package/dist/esm/utils/libraryWidgetKeys.js +5 -0
  173. package/dist/esm/utils/libraryWidgetKeys.js.map +1 -1
  174. package/dist/esm/utils/readPath.js +30 -0
  175. package/dist/esm/utils/readPath.js.map +1 -0
  176. package/dist/esm/utils/validateManifestV2.compiled.js +2 -2
  177. package/dist/esm/utils/validateManifestV2.compiled.js.map +1 -1
  178. package/dist/nextcloud-vue.cjs.js +16019 -9528
  179. package/dist/nextcloud-vue.cjs.js.map +2 -2
  180. package/dist/nextcloud-vue.css +1036 -19
  181. package/l10n/en.json +55 -1
  182. package/l10n/nl.json +55 -1
  183. package/package.json +1 -1
  184. package/scripts/.jsdoc-baselines.json +4 -0
  185. package/src/components/CnActionsMenu/CnActionsMenu.vue +14 -1
  186. package/src/components/CnAppNav/CnAppNav.md +26 -0
  187. package/src/components/CnAppNav/CnAppNav.vue +145 -2
  188. package/src/components/CnBannerWidget/CnBannerWidget.vue +373 -11
  189. package/src/components/CnBannerWidgetForm/CnBannerWidgetForm.vue +65 -3
  190. package/src/components/CnBoardView/CnBoardView.vue +77 -0
  191. package/src/components/CnBrandStripe/CnBrandStripe.md +22 -0
  192. package/src/components/CnBrandStripe/CnBrandStripe.vue +100 -0
  193. package/src/components/CnBrandStripe/index.js +4 -0
  194. package/src/components/CnCellRenderer/CnCellRenderer.vue +207 -1
  195. package/src/components/CnConversationThread/CnConversationThread.md +51 -0
  196. package/src/components/CnConversationThread/CnConversationThread.vue +457 -0
  197. package/src/components/CnConversationThread/CnConversationWidget.vue +144 -0
  198. package/src/components/CnConversationThread/index.js +4 -0
  199. package/src/components/CnDashboardPage/CnDashboardPage.vue +10 -2
  200. package/src/components/CnDetailPage/CnDetailPage.md +16 -0
  201. package/src/components/CnDetailPage/CnDetailPage.vue +687 -49
  202. package/src/components/CnDocumentReviewList/CnDocumentReviewList.md +55 -0
  203. package/src/components/CnDocumentReviewList/CnDocumentReviewList.vue +384 -0
  204. package/src/components/CnDocumentReviewList/CnDocumentReviewWidget.vue +108 -0
  205. package/src/components/CnDocumentReviewList/index.js +4 -0
  206. package/src/components/CnHeaderWidget/CnHeaderWidget.vue +191 -14
  207. package/src/components/CnHeaderWidgetForm/CnHeaderWidgetForm.vue +53 -3
  208. package/src/components/CnIndexPage/CnIndexPage.vue +135 -3
  209. package/src/components/CnLinkCardsPage/CnLinkCardsPage.vue +484 -0
  210. package/src/components/CnLinkCardsPage/index.js +4 -0
  211. package/src/components/CnNextStepCard/CnNextStepCard.md +40 -0
  212. package/src/components/CnNextStepCard/CnNextStepCard.vue +319 -0
  213. package/src/components/CnNextStepCard/CnNextStepWidget.vue +59 -0
  214. package/src/components/CnNextStepCard/index.js +4 -0
  215. package/src/components/CnObjectDataWidget/CnObjectDataWidget.vue +49 -0
  216. package/src/components/CnObjectDataWidgetForm/CnObjectDataWidgetForm.vue +6 -0
  217. package/src/components/CnObjectKanban/CnObjectKanban.vue +86 -2
  218. package/src/components/CnPageRenderer/pageTypes.js +1 -0
  219. package/src/components/CnQuickFilterBar/CnQuickFilterBar.md +3 -0
  220. package/src/components/CnQuickFilterBar/CnQuickFilterBar.vue +60 -1
  221. package/src/components/CnSavedViewsControl/CnSavedViewsControl.vue +50 -3
  222. package/src/components/CnSegmentedControl/CnSegmentedControl.md +46 -0
  223. package/src/components/CnSegmentedControl/CnSegmentedControl.vue +291 -0
  224. package/src/components/CnSegmentedControl/index.js +4 -0
  225. package/src/components/CnStackedBarWidget/CnStackedBarWidget.md +15 -0
  226. package/src/components/CnStackedBarWidget/CnStackedBarWidget.vue +414 -0
  227. package/src/components/CnStackedBarWidget/index.js +14 -0
  228. package/src/components/CnStackedBarWidgetForm/CnStackedBarWidgetForm.vue +224 -0
  229. package/src/components/CnStackedBarWidgetForm/index.js +4 -0
  230. package/src/components/CnTabs/CnTab.vue +35 -0
  231. package/src/components/CnTabs/CnTabs.vue +244 -10
  232. package/src/components/CnTabsWidget/CnTabsWidget.vue +63 -4
  233. package/src/components/CnWeekStripWidget/CnWeekStripWidget.md +31 -0
  234. package/src/components/CnWeekStripWidget/CnWeekStripWidget.vue +668 -0
  235. package/src/components/CnWeekStripWidget/index.js +14 -0
  236. package/src/components/CnWeekStripWidgetForm/CnWeekStripWidgetForm.vue +265 -0
  237. package/src/components/CnWeekStripWidgetForm/index.js +4 -0
  238. package/src/components/CnWidgetGrid/registerDashboardWidgets.js +74 -0
  239. package/src/components/index.js +12 -0
  240. package/src/css/detail-page.css +57 -2
  241. package/src/index.js +16 -0
  242. package/src/schemas/app-manifest-v2.schema.json +433 -3
  243. package/src/schemas/app-manifest.schema.json +2 -1
  244. package/src/types/manifest.d.ts +1 -1
  245. package/src/utils/dateVariant.js +120 -0
  246. package/src/utils/detailActionModel.js +256 -0
  247. package/src/utils/dueRule.js +94 -0
  248. package/src/utils/fetchAggregate.js +36 -0
  249. package/src/utils/fetchFilterCounts.js +182 -0
  250. package/src/utils/headers.js +28 -2
  251. package/src/utils/index.js +1 -0
  252. package/src/utils/libraryWidgetKeys.js +5 -0
  253. package/src/utils/readPath.js +27 -0
  254. package/src/utils/validateManifestV2.compiled.js +2 -2
@@ -0,0 +1,22 @@
1
+ The brand stripe of the organisation. A theme sets its colours, shares and height through the `--cn-brand-stripe-*` custom properties. Without a theme it is one band in the primary colour.
2
+
3
+ ```vue
4
+ <CnBrandStripe />
5
+ ```
6
+
7
+ With the properties a theme would set:
8
+
9
+ ```vue
10
+ <div style="--cn-brand-stripe-color-1: #cc0000; --cn-brand-stripe-color-2: #3669a5; --cn-brand-stripe-color-3: #cc0000; --cn-brand-stripe-ratio-1: 6; --cn-brand-stripe-ratio-2: 3; --cn-brand-stripe-ratio-3: 1; --cn-brand-stripe-height: 5px">
11
+ <CnBrandStripe />
12
+ </div>
13
+ ```
14
+
15
+ Down the side of a panel, with `orientation="vertical"`:
16
+
17
+ ```vue
18
+ <div style="display: flex; height: 80px; gap: 12px;">
19
+ <CnBrandStripe orientation="vertical" />
20
+ <span>Content beside the stripe</span>
21
+ </div>
22
+ ```
@@ -0,0 +1,100 @@
1
+ <!--
2
+ SPDX-FileCopyrightText: 2026 Conduction B.V.
3
+ SPDX-License-Identifier: EUPL-1.2
4
+ -->
5
+ <template>
6
+ <div
7
+ class="cn-brand-stripe"
8
+ :class="{ 'cn-brand-stripe--vertical': orientation === 'vertical' }"
9
+ aria-hidden="true"
10
+ data-testid="cn-brand-stripe">
11
+ <span class="cn-brand-stripe__band cn-brand-stripe__band--1" />
12
+ <span class="cn-brand-stripe__band cn-brand-stripe__band--2" />
13
+ <span class="cn-brand-stripe__band cn-brand-stripe__band--3" />
14
+ </div>
15
+ </template>
16
+
17
+ <script>
18
+ /**
19
+ * CnBrandStripe draws the organisation's brand stripe: up to three coloured
20
+ * bands next to each other, for the top of a page, a card or a sidebar.
21
+ *
22
+ * The theme decides what it looks like, through the library's own custom
23
+ * properties: `--cn-brand-stripe-color-1/2/3` (the colours, start to end),
24
+ * `--cn-brand-stripe-ratio-1/2/3` (unitless shares, such as 6, 3 and 1)
25
+ * and `--cn-brand-stripe-height` (such as 5px). A theming app maps its own
26
+ * tokens onto these; the library never reads a theme's tokens. Without them the
27
+ * stripe is one band in the Nextcloud primary colour, 4px high.
28
+ *
29
+ * The stripe is decoration: it carries no meaning and is hidden from
30
+ * assistive technology.
31
+ *
32
+ * ```vue
33
+ * <CnBrandStripe />
34
+ * ```
35
+ */
36
+ export default {
37
+ name: 'CnBrandStripe',
38
+
39
+ props: {
40
+ /**
41
+ * The direction the stripe runs in: `horizontal` (the default, a bar
42
+ * across the top) or `vertical` (a bar down the side; the height
43
+ * token then sets its width).
44
+ *
45
+ * @type {'horizontal'|'vertical'}
46
+ */
47
+ orientation: {
48
+ type: String,
49
+ default: 'horizontal',
50
+ validator: (v) => ['horizontal', 'vertical'].includes(v),
51
+ },
52
+ },
53
+ }
54
+ </script>
55
+
56
+ <!--
57
+ The stripe reads the library's own `--cn-brand-stripe-*` properties, each
58
+ with a Nextcloud fallback. A theming app sets them from its own tokens.
59
+ -->
60
+ <style scoped>
61
+ .cn-brand-stripe {
62
+ display: flex;
63
+ flex: none;
64
+ width: 100%;
65
+ height: var(--cn-brand-stripe-height, 4px);
66
+ }
67
+
68
+ .cn-brand-stripe--vertical {
69
+ flex-direction: column;
70
+ width: var(--cn-brand-stripe-height, 4px);
71
+ height: 100%;
72
+ }
73
+
74
+ .cn-brand-stripe__band {
75
+ flex-basis: 0;
76
+ flex-shrink: 1;
77
+ }
78
+
79
+ .cn-brand-stripe__band--1 {
80
+ flex-grow: var(--cn-brand-stripe-ratio-1, 1);
81
+ background-color: var(--cn-brand-stripe-color-1, var(--color-primary-element));
82
+ }
83
+
84
+ .cn-brand-stripe__band--2 {
85
+ flex-grow: var(--cn-brand-stripe-ratio-2, 1);
86
+ background-color: var(--cn-brand-stripe-color-2, var(--color-primary-element));
87
+ }
88
+
89
+ .cn-brand-stripe__band--3 {
90
+ flex-grow: var(--cn-brand-stripe-ratio-3, 1);
91
+ background-color: var(--cn-brand-stripe-color-3, var(--color-primary-element));
92
+ }
93
+
94
+ @media print {
95
+ .cn-brand-stripe {
96
+ print-color-adjust: exact;
97
+ -webkit-print-color-adjust: exact;
98
+ }
99
+ }
100
+ </style>
@@ -0,0 +1,4 @@
1
+ import CnBrandStripe from './CnBrandStripe.vue'
2
+
3
+ export default CnBrandStripe
4
+ export { CnBrandStripe }
@@ -55,6 +55,43 @@
55
55
  <span v-else :title="rawTitle">{{ formattedValue }}</span>
56
56
  </template>
57
57
 
58
+ <!-- Built-in "avatar" widget: a person as an avatar with the name beside
59
+ it. A user id (widgetProps.userField, or widgetProps.user for a cell
60
+ that holds the id itself) gets the Nextcloud avatar; a free name
61
+ gets its initials. The picture is decoration: the name is the text. -->
62
+ <template v-else-if="widget === 'avatar'">
63
+ <span v-if="avatarName || avatarUserId" class="cn-cell-renderer__avatar">
64
+ <span v-if="avatarUserId" class="cn-cell-renderer__avatar-picture" aria-hidden="true">
65
+ <NcAvatar
66
+ :user="avatarUserId"
67
+ :displayName="avatarName || avatarUserId"
68
+ :size="avatarSize"
69
+ :disableMenu="true"
70
+ :disableTooltip="true" />
71
+ </span>
72
+ <span
73
+ v-else
74
+ class="cn-cell-renderer__avatar-initials"
75
+ :style="{ width: avatarSize + 'px', height: avatarSize + 'px' }"
76
+ aria-hidden="true">{{ avatarInitials }}</span>
77
+ <span class="cn-cell-renderer__avatar-name" :title="avatarName || avatarUserId">{{ avatarName || avatarUserId }}</span>
78
+ </span>
79
+ <span v-else class="cn-cell-renderer__dash">—</span>
80
+ </template>
81
+
82
+ <!-- Built-in "date" widget: a date whose colour follows
83
+ widgetProps.variantWhen, rules on the number of days until it
84
+ (0 = today, negative = overdue). -->
85
+ <template v-else-if="widget === 'date'">
86
+ <time
87
+ v-if="dateTimestamp"
88
+ class="cn-cell-renderer__date"
89
+ :class="dateVariant ? 'cn-cell-renderer__date--' + dateVariant : null"
90
+ :datetime="dateTimestamp.toISOString()"
91
+ :title="rawTitle">{{ dateLabel }}</time>
92
+ <span v-else class="cn-cell-renderer__dash">—</span>
93
+ </template>
94
+
58
95
  <!-- Explicit column formatter — overrides the type-aware paths below -->
59
96
  <template v-else-if="hasFormatter">
60
97
  <span :title="rawTitle">{{ formattedValue }}</span>
@@ -129,10 +166,13 @@
129
166
  </template>
130
167
 
131
168
  <script>
132
- import { NcDateTime } from '@nextcloud/vue'
169
+ import { getCanonicalLocale } from '@nextcloud/l10n'
170
+ import { NcAvatar, NcDateTime } from '@nextcloud/vue'
133
171
  import CheckBold from 'vue-material-design-icons/CheckBold.vue'
134
172
  import CnFkResolveCell from '../CnFkResolveCell/CnFkResolveCell.vue'
173
+ import { parseDateValue, resolveDateVariant } from '../../utils/dateVariant.js'
135
174
  import { safeCurrencyCode } from '../../utils/formatMetric.js'
175
+ import { objectFieldValue } from '../../utils/objectName.js'
136
176
  import { safeHref } from '../../utils/safeHref.js'
137
177
  import { formatValue } from '../../utils/schema.js'
138
178
  import { CnStatusBadge } from '../CnStatusBadge/index.js'
@@ -162,6 +202,7 @@ export default {
162
202
  CnStatusBadge,
163
203
  CnFkResolveCell,
164
204
  CheckBold,
205
+ NcAvatar,
165
206
  NcDateTime,
166
207
  },
167
208
 
@@ -232,6 +273,12 @@ export default {
232
273
  * the built-in id `"badge"` renders `CnStatusBadge` and the built-in
233
274
  * id `"fkResolve"` renders `CnFkResolveCell` (uuid → related object
234
275
  * label, config via `widgetProps { register, schema, labelField }`).
276
+ * The built-in id `"avatar"` renders a person as an avatar with the
277
+ * name beside it (`widgetProps { userField?, user?, nameField?, size? }`;
278
+ * a free name gets its initials), and the built-in id `"date"` renders
279
+ * a date whose colour follows `widgetProps.variantWhen`, rules on the
280
+ * number of days until the date (`[{ op: "lt", value: 0, variant:
281
+ * "error" }, { op: "lte", value: 5, variant: "warning" }]`).
235
282
  * Takes precedence over `formatter`/the type-aware rendering, but the
236
283
  * value handed to the widget is the formatter-shaped `formatted` when
237
284
  * `formatter` is also set.
@@ -350,6 +397,112 @@ export default {
350
397
  return Number.isNaN(date.getTime()) ? null : date
351
398
  },
352
399
 
400
+ /**
401
+ * `avatar` widget: the Nextcloud user id whose avatar to show, or ''
402
+ * for a free name. Read from the row field `widgetProps.userField`,
403
+ * or from the cell value itself when `widgetProps.user` is true.
404
+ *
405
+ * @return {string}
406
+ * @spec openspec/changes/workplace-dashboard-primitives/specs/workplace-dashboard-primitives/spec.md#requirement-avatar-and-date-cells
407
+ */
408
+ avatarUserId() {
409
+ const props = this.widgetProps || {}
410
+ let id = ''
411
+ if (typeof props.userField === 'string' && props.userField !== '') {
412
+ id = objectFieldValue(this.row, props.userField)
413
+ } else if (props.user === true) {
414
+ id = this.value
415
+ }
416
+ return (typeof id === 'string' || typeof id === 'number') ? String(id) : ''
417
+ },
418
+
419
+ /**
420
+ * `avatar` widget: the name shown beside the picture. Read from the
421
+ * row field `widgetProps.nameField` when set, else the cell value.
422
+ *
423
+ * @return {string}
424
+ * @spec openspec/changes/workplace-dashboard-primitives/specs/workplace-dashboard-primitives/spec.md#requirement-avatar-and-date-cells
425
+ */
426
+ avatarName() {
427
+ const props = this.widgetProps || {}
428
+ if (typeof props.nameField === 'string' && props.nameField !== '') {
429
+ const name = objectFieldValue(this.row, props.nameField)
430
+ if (typeof name === 'string' && name !== '') {
431
+ return name
432
+ }
433
+ }
434
+ if (!this.hasValue || typeof this.value === 'object') {
435
+ return ''
436
+ }
437
+ return String(this.hasFormatter ? this.formattedValue : this.value)
438
+ },
439
+
440
+ /**
441
+ * `avatar` widget: the initials of a free name, at most two letters
442
+ * (first and last word).
443
+ *
444
+ * @return {string}
445
+ * @spec openspec/changes/workplace-dashboard-primitives/specs/workplace-dashboard-primitives/spec.md#requirement-avatar-and-date-cells
446
+ */
447
+ avatarInitials() {
448
+ const words = this.avatarName.trim().split(/\s+/).filter((word) => word !== '')
449
+ if (words.length === 0) {
450
+ return ''
451
+ }
452
+ const first = Array.from(words[0])[0] || ''
453
+ const last = words.length > 1 ? (Array.from(words[words.length - 1])[0] || '') : ''
454
+ return (first + last).toLocaleUpperCase()
455
+ },
456
+
457
+ /**
458
+ * `avatar` widget: the picture size in pixels (`widgetProps.size`, default 24).
459
+ *
460
+ * @return {number}
461
+ * @spec openspec/changes/workplace-dashboard-primitives/specs/workplace-dashboard-primitives/spec.md#requirement-avatar-and-date-cells
462
+ */
463
+ avatarSize() {
464
+ const size = Number(this.widgetProps && this.widgetProps.size)
465
+ return Number.isFinite(size) && size > 0 ? size : 24
466
+ },
467
+
468
+ /**
469
+ * `date` widget: the variant of the first `widgetProps.variantWhen`
470
+ * rule the date matches, or '' for none.
471
+ *
472
+ * @return {string}
473
+ * @spec openspec/changes/workplace-dashboard-primitives/specs/workplace-dashboard-primitives/spec.md#requirement-avatar-and-date-cells
474
+ */
475
+ dateVariant() {
476
+ const rules = this.widgetProps && this.widgetProps.variantWhen
477
+ const variant = resolveDateVariant(this.value, rules)
478
+ return variant === 'default' ? '' : variant
479
+ },
480
+
481
+ /**
482
+ * `date` widget: the date written out in the user's locale.
483
+ *
484
+ * @return {string}
485
+ * @spec openspec/changes/workplace-dashboard-primitives/specs/workplace-dashboard-primitives/spec.md#requirement-avatar-and-date-cells
486
+ */
487
+ dateLabel() {
488
+ const date = parseDateValue(this.value)
489
+ if (date === null) {
490
+ return ''
491
+ }
492
+ const options = { day: 'numeric', month: 'short', year: 'numeric' }
493
+ let locale
494
+ try {
495
+ locale = getCanonicalLocale()
496
+ } catch {
497
+ locale = undefined
498
+ }
499
+ try {
500
+ return new Intl.DateTimeFormat(locale || undefined, options).format(date)
501
+ } catch {
502
+ return new Intl.DateTimeFormat(undefined, options).format(date)
503
+ }
504
+ },
505
+
353
506
  /** True when the property is a URI / URL (rendered as an external link). */
354
507
  isUri() {
355
508
  return this.property?.format === 'uri' || this.property?.format === 'url'
@@ -750,6 +903,59 @@ export default {
750
903
  color: var(--color-text-maxcontrast);
751
904
  }
752
905
 
906
+ .cn-cell-renderer__avatar {
907
+ display: inline-flex;
908
+ align-items: center;
909
+ gap: 8px;
910
+ max-width: 100%;
911
+ vertical-align: middle;
912
+ }
913
+
914
+ .cn-cell-renderer__avatar-picture {
915
+ display: inline-flex;
916
+ flex: none;
917
+ }
918
+
919
+ .cn-cell-renderer__avatar-initials {
920
+ display: inline-flex;
921
+ flex: none;
922
+ align-items: center;
923
+ justify-content: center;
924
+ border-radius: 50%;
925
+ background-color: var(--color-primary-element-light);
926
+ color: var(--color-primary-element-light-text);
927
+ font-size: 0.75em;
928
+ font-weight: 700;
929
+ line-height: 1;
930
+ }
931
+
932
+ .cn-cell-renderer__avatar-name {
933
+ min-width: 0;
934
+ overflow: hidden;
935
+ text-overflow: ellipsis;
936
+ white-space: nowrap;
937
+ }
938
+
939
+ /* A date that matched a rule is also set in a heavier weight, so the signal
940
+ does not rest on colour alone. */
941
+ .cn-cell-renderer__date--success,
942
+ .cn-cell-renderer__date--warning,
943
+ .cn-cell-renderer__date--error {
944
+ font-weight: 600;
945
+ }
946
+
947
+ .cn-cell-renderer__date--success {
948
+ color: var(--color-text-success, var(--color-success-text));
949
+ }
950
+
951
+ .cn-cell-renderer__date--warning {
952
+ color: var(--color-text-warning, var(--color-warning-text));
953
+ }
954
+
955
+ .cn-cell-renderer__date--error {
956
+ color: var(--color-text-error, var(--color-error-text));
957
+ }
958
+
753
959
  .cn-cell-renderer__icon--success {
754
960
  color: var(--color-success);
755
961
  }
@@ -0,0 +1,51 @@
1
+ A thread with a reply box:
2
+
3
+ ```vue
4
+ <CnConversationThread
5
+ title="Contact with the resident"
6
+ reply-label="Answer to the resident"
7
+ :messages="[
8
+ { id: 1, author: 'Sanne de Vries', time: '2026-10-04T10:52:00', side: 'them',
9
+ text: 'Thank you. I would like to see all documents about the lighting.' },
10
+ { id: 2, time: '2026-10-04T10:24:00', side: 'us',
11
+ text: 'Construction starts in March. There will be lighting along the whole cycle path.' },
12
+ ]" />
13
+ ```
14
+
15
+ Read-only, for a closed record:
16
+
17
+ ```vue
18
+ <CnConversationThread
19
+ title="Contact"
20
+ :allow-reply="false"
21
+ :messages="[
22
+ { id: 1, author: 'Sanne de Vries', time: '4 Oct, 10:52', side: 'them', text: 'Thank you.' },
23
+ ]" />
24
+ ```
25
+
26
+ No messages yet:
27
+
28
+ ```vue
29
+ <CnConversationThread title="Contact" :messages="[]" />
30
+ ```
31
+
32
+ Posting to an endpoint. The reply goes out as `{ message, ...payload }`. `title-tag`, `placeholder`, `send-label`, `us-label` and `empty-text` adjust the wording, and the `reply-actions` slot adds buttons before Send:
33
+
34
+ ```vue
35
+ <CnConversationThread
36
+ title="Contact"
37
+ title-tag="h2"
38
+ placeholder="Write your answer"
39
+ send-label="Send to resident"
40
+ us-label="Municipality"
41
+ empty-text="Nobody has written yet."
42
+ endpoint="/apps/example/api/cases/42/messages"
43
+ :payload="{ channel: 'portal' }"
44
+ :messages="[
45
+ { id: 1, time: '2026-10-04T11:00:00', side: 'us', text: 'We received your request.' },
46
+ ]">
47
+ <template #reply-actions="{ draft }">
48
+ <NcButton :disabled="!draft">Save draft</NcButton>
49
+ </template>
50
+ </CnConversationThread>
51
+ ```