@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,668 @@
1
+ <!--
2
+ SPDX-FileCopyrightText: 2026 Conduction B.V.
3
+ SPDX-License-Identifier: EUPL-1.2
4
+ -->
5
+ <template>
6
+ <div class="cn-week-strip" data-testid="cn-week-strip">
7
+ <div v-if="loading" class="cn-week-strip__state" role="status">
8
+ <NcLoadingIcon :size="20" />
9
+ <span class="cn-week-strip__state-text">{{ loadingLabel }}</span>
10
+ </div>
11
+ <p v-else-if="error" class="cn-week-strip__state" role="status">
12
+ {{ errorLabel }}
13
+ </p>
14
+ <!-- A scroll container a keyboard user cannot focus cannot be scrolled,
15
+ so the region is focusable and named. -->
16
+ <div
17
+ v-else
18
+ class="cn-week-strip__scroll"
19
+ role="region"
20
+ tabindex="0"
21
+ :aria-label="regionLabel">
22
+ <ol class="cn-week-strip__days" :style="{ '--cn-week-strip-columns': dayColumns.length }">
23
+ <li
24
+ v-for="day in dayColumns"
25
+ :key="day.key"
26
+ class="cn-week-strip__day"
27
+ :class="{ 'cn-week-strip__day--today': day.today }"
28
+ :aria-current="day.today ? 'date' : null"
29
+ :data-day="day.key">
30
+ <span class="cn-week-strip__head">
31
+ <span class="cn-week-strip__label">{{ day.label }}</span>
32
+ <span v-if="day.today" class="cn-week-strip__today">{{ todayLabel }}</span>
33
+ </span>
34
+ <ul v-if="day.items.length > 0" class="cn-week-strip__items">
35
+ <li v-for="item in day.items" :key="item.key" class="cn-week-strip__item-row">
36
+ <component
37
+ :is="item.href ? 'a' : 'div'"
38
+ class="cn-week-strip__item"
39
+ :class="{ 'cn-week-strip__item--late': item.late, 'cn-week-strip__item--link': !!item.href }"
40
+ :href="item.href || null"
41
+ data-testid="cn-week-strip-item"
42
+ @click="onItemClick($event, item)">
43
+ <strong class="cn-week-strip__title">{{ item.title }}</strong>
44
+ <span v-if="item.meta" class="cn-week-strip__meta">{{ item.meta }}</span>
45
+ <span v-if="item.late" class="cn-week-strip__late">{{ lateLabel }}</span>
46
+ </component>
47
+ </li>
48
+ </ul>
49
+ <span v-else class="cn-week-strip__empty">{{ emptyLabel }}</span>
50
+ </li>
51
+ </ol>
52
+ </div>
53
+ </div>
54
+ </template>
55
+
56
+ <script>
57
+ import { getCanonicalLocale, translate as t } from '@nextcloud/l10n'
58
+ import { NcLoadingIcon } from '@nextcloud/vue'
59
+ import { dayKey, daysUntil, parseDateValue } from '../../utils/dateVariant.js'
60
+ import { followLinkClick, resolveHref } from '../../utils/linkNavigation.js'
61
+ import { objectDisplayName, objectFieldValue } from '../../utils/objectName.js'
62
+ import { resolveFilterTokens } from '../../utils/resolveFilterTokens.js'
63
+ import { safeHref } from '../../utils/safeHref.js'
64
+ import { compareVisibleWhen } from '../../utils/visibleWhen.js'
65
+
66
+ const DEFAULT_LIMIT = 100
67
+
68
+ /**
69
+ * CnWeekStripWidget shows the current week as day columns, with the items
70
+ * that fall on each day listed under it. Use it for deadlines, appointments
71
+ * or anything else that has a date and that somebody should see coming.
72
+ *
73
+ * It renders the five working days by default (`days: 7` adds the weekend),
74
+ * highlights today, marks items that are late, and says so when a day has
75
+ * nothing. On a narrow screen the strip scrolls sideways.
76
+ *
77
+ * Items come from an OpenRegister source (one request for the whole week) or
78
+ * from static `items`. Resolved by its registry type key `week-strip`.
79
+ *
80
+ * ```json
81
+ * {
82
+ * "widgetKey": "week-strip",
83
+ * "props": {
84
+ * "content": {
85
+ * "source": { "register": "dossiq", "schema": "case", "filter": { "assignee": "@me" } },
86
+ * "dateField": "deadline",
87
+ * "titleField": "title",
88
+ * "metaFields": ["identifier", "caseType"],
89
+ * "itemRoute": "CaseDetail",
90
+ * "emptyText": "No deadlines"
91
+ * }
92
+ * }
93
+ * }
94
+ * ```
95
+ */
96
+ export default {
97
+ name: 'CnWeekStripWidget',
98
+
99
+ components: { NcLoadingIcon },
100
+
101
+ inject: {
102
+ /**
103
+ * Host translate function provided by CnAppRoot. The manifest-authored
104
+ * `emptyText` and static item texts run through it. Identity by default.
105
+ */
106
+ cnTranslate: { default: () => (key) => key },
107
+ },
108
+
109
+ props: {
110
+ /**
111
+ * The widget's configuration. `days` is `5` (working days, the
112
+ * default) or `7`. `source` names the OpenRegister register and schema,
113
+ * with an optional `filter` (the shared @-token grammar) and `limit`.
114
+ * `dateField` is the field the items are bucketed by. `titleField` and
115
+ * `metaFields` pick what each item shows. `itemRoute` is the route name
116
+ * an item links to (with the record id as `params.id`). `lateWhen` is a
117
+ * `{ op, value }` rule on the days until the date (default: before
118
+ * today), `lateField` a boolean field that marks a record late.
119
+ * `items` are static entries `{ title, meta?, date, route?, href?, late? }`.
120
+ * `emptyText` is the text of a day without items. `weekOffset` moves
121
+ * the strip whole weeks from the current one.
122
+ *
123
+ * @type {{days?: (5|7), source?: {register?: string, schema?: string, filter?: object, limit?: number}, dateField?: string, titleField?: string, metaFields?: Array<string>, itemRoute?: string, lateWhen?: {op?: string, value?: number}, lateField?: string, items?: Array<{title: string, meta?: string, date: string, route?: (string|object), href?: string, late?: boolean}>, emptyText?: string, weekOffset?: number}}
124
+ */
125
+ content: {
126
+ type: Object,
127
+ default: () => ({}),
128
+ },
129
+
130
+ /**
131
+ * Translate function. Falls back to the injected `cnTranslate`. Pass it
132
+ * when mounting the widget outside a CnAppRoot.
133
+ *
134
+ * @type {((key: string) => string)|null}
135
+ */
136
+ translate: {
137
+ type: Function,
138
+ default: null,
139
+ },
140
+
141
+ /**
142
+ * The moment the strip treats as "now". Leave empty for the current
143
+ * time; set it to render another week or to test.
144
+ *
145
+ * @type {Date|null}
146
+ */
147
+ now: {
148
+ type: Date,
149
+ default: null,
150
+ },
151
+ },
152
+
153
+ data() {
154
+ return {
155
+ rows: [],
156
+ loading: false,
157
+ error: '',
158
+ }
159
+ },
160
+
161
+ computed: {
162
+ /**
163
+ * The translate function in use.
164
+ *
165
+ * @return {(key: string) => string}
166
+ * @spec openspec/changes/workplace-dashboard-primitives/specs/workplace-dashboard-primitives/spec.md#requirement-week-strip-widget
167
+ */
168
+ effectiveTranslate() {
169
+ return this.translate ?? this.cnTranslate
170
+ },
171
+
172
+ /**
173
+ * The reference moment.
174
+ *
175
+ * @return {Date}
176
+ * @spec openspec/changes/workplace-dashboard-primitives/specs/workplace-dashboard-primitives/spec.md#requirement-week-strip-widget
177
+ */
178
+ reference() {
179
+ return this.now instanceof Date ? this.now : new Date()
180
+ },
181
+
182
+ /**
183
+ * How many day columns render: 7, or 5 for anything else.
184
+ *
185
+ * @return {number}
186
+ * @spec openspec/changes/workplace-dashboard-primitives/specs/workplace-dashboard-primitives/spec.md#requirement-week-strip-widget
187
+ */
188
+ dayCount() {
189
+ return Number(this.content.days) === 7 ? 7 : 5
190
+ },
191
+
192
+ /**
193
+ * The days of the strip, Monday first.
194
+ *
195
+ * @return {Array<Date>}
196
+ * @spec openspec/changes/workplace-dashboard-primitives/specs/workplace-dashboard-primitives/spec.md#requirement-week-strip-widget
197
+ */
198
+ weekDays() {
199
+ const ref = this.reference
200
+ const offset = Number.isInteger(this.content.weekOffset) ? this.content.weekOffset : 0
201
+ const mondayDelta = (ref.getDay() + 6) % 7
202
+ const days = []
203
+ for (let i = 0; i < this.dayCount; i++) {
204
+ days.push(new Date(ref.getFullYear(), ref.getMonth(), ref.getDate() - mondayDelta + (offset * 7) + i))
205
+ }
206
+ return days
207
+ },
208
+
209
+ /**
210
+ * The field the items are bucketed by.
211
+ *
212
+ * @return {string}
213
+ * @spec openspec/changes/workplace-dashboard-primitives/specs/workplace-dashboard-primitives/spec.md#requirement-week-strip-widget
214
+ */
215
+ dateField() {
216
+ return typeof this.content.dateField === 'string' ? this.content.dateField : ''
217
+ },
218
+
219
+ /**
220
+ * Whether the items come from OpenRegister.
221
+ *
222
+ * @return {boolean}
223
+ * @spec openspec/changes/workplace-dashboard-primitives/specs/workplace-dashboard-primitives/spec.md#requirement-week-strip-widget
224
+ */
225
+ hasSource() {
226
+ const s = this.content.source || {}
227
+ return Boolean(s.register && s.schema && this.dateField)
228
+ },
229
+
230
+ /**
231
+ * Every item, from the source rows or the static list, in one shape.
232
+ *
233
+ * @return {Array<{key: string, title: string, meta: string, date: (Date|null), late: boolean, href: string, target: (object|string|null)}>}
234
+ * @spec openspec/changes/workplace-dashboard-primitives/specs/workplace-dashboard-primitives/spec.md#requirement-week-strip-widget
235
+ */
236
+ normalizedItems() {
237
+ if (this.hasSource) {
238
+ return this.rows.map((row, index) => this.itemFromRow(row, index))
239
+ }
240
+ const items = Array.isArray(this.content.items) ? this.content.items : []
241
+ return items
242
+ .filter((item) => item && typeof item === 'object')
243
+ .map((item, index) => this.itemFromStatic(item, index))
244
+ },
245
+
246
+ /**
247
+ * The columns: one per day, each with its items.
248
+ *
249
+ * @return {Array<{key: string, label: string, today: boolean, items: Array<object>}>}
250
+ * @spec openspec/changes/workplace-dashboard-primitives/specs/workplace-dashboard-primitives/spec.md#requirement-week-strip-widget
251
+ */
252
+ dayColumns() {
253
+ const todayKey = dayKey(this.reference)
254
+ const buckets = {}
255
+ for (const item of this.normalizedItems) {
256
+ if (item.date === null) {
257
+ continue
258
+ }
259
+ const key = dayKey(item.date)
260
+ ;(buckets[key] = buckets[key] || []).push(item)
261
+ }
262
+ const formatter = this.dayFormatter
263
+ return this.weekDays.map((day) => {
264
+ const key = dayKey(day)
265
+ return {
266
+ key,
267
+ label: formatter.format(day),
268
+ today: key === todayKey,
269
+ items: buckets[key] || [],
270
+ }
271
+ })
272
+ },
273
+
274
+ /**
275
+ * Formats a day as a short weekday and a day number ("Mon 5").
276
+ *
277
+ * @return {Intl.DateTimeFormat}
278
+ * @spec openspec/changes/workplace-dashboard-primitives/specs/workplace-dashboard-primitives/spec.md#requirement-week-strip-widget
279
+ */
280
+ dayFormatter() {
281
+ let locale
282
+ try {
283
+ locale = getCanonicalLocale()
284
+ } catch {
285
+ locale = undefined
286
+ }
287
+ try {
288
+ return new Intl.DateTimeFormat(locale || undefined, { weekday: 'short', day: 'numeric' })
289
+ } catch {
290
+ return new Intl.DateTimeFormat(undefined, { weekday: 'short', day: 'numeric' })
291
+ }
292
+ },
293
+
294
+ /**
295
+ * The text of a day without items.
296
+ *
297
+ * @return {string}
298
+ * @spec openspec/changes/workplace-dashboard-primitives/specs/workplace-dashboard-primitives/spec.md#requirement-week-strip-widget
299
+ */
300
+ emptyLabel() {
301
+ const text = this.content.emptyText
302
+ return (typeof text === 'string' && text !== '')
303
+ ? this.effectiveTranslate(text)
304
+ : t('nextcloud-vue', 'Nothing planned')
305
+ },
306
+
307
+ /**
308
+ * @return {string} The badge on today's column.
309
+ *
310
+ * @spec openspec/changes/workplace-dashboard-primitives/specs/workplace-dashboard-primitives/spec.md#requirement-week-strip-widget
311
+ */
312
+ todayLabel() {
313
+ return t('nextcloud-vue', 'today')
314
+ },
315
+
316
+ /**
317
+ * @return {string} The marker on a late item.
318
+ *
319
+ * @spec openspec/changes/workplace-dashboard-primitives/specs/workplace-dashboard-primitives/spec.md#requirement-week-strip-widget
320
+ */
321
+ lateLabel() {
322
+ return t('nextcloud-vue', 'Late')
323
+ },
324
+
325
+ /**
326
+ * @return {string} The accessible name of the scrolling region.
327
+ *
328
+ * @spec openspec/changes/workplace-dashboard-primitives/specs/workplace-dashboard-primitives/spec.md#requirement-week-strip-widget
329
+ */
330
+ regionLabel() {
331
+ return t('nextcloud-vue', 'This week, day by day')
332
+ },
333
+
334
+ /**
335
+ * @return {string} The loading text.
336
+ *
337
+ * @spec openspec/changes/workplace-dashboard-primitives/specs/workplace-dashboard-primitives/spec.md#requirement-week-strip-widget
338
+ */
339
+ loadingLabel() {
340
+ return t('nextcloud-vue', 'Loading…')
341
+ },
342
+
343
+ /**
344
+ * @return {string} The text shown when the items could not be loaded.
345
+ *
346
+ * @spec openspec/changes/workplace-dashboard-primitives/specs/workplace-dashboard-primitives/spec.md#requirement-week-strip-widget
347
+ */
348
+ errorLabel() {
349
+ return t('nextcloud-vue', 'The items for this week could not be loaded.')
350
+ },
351
+
352
+ /**
353
+ * Changes whenever a new fetch is needed.
354
+ *
355
+ * @return {string}
356
+ * @spec openspec/changes/workplace-dashboard-primitives/specs/workplace-dashboard-primitives/spec.md#requirement-week-strip-widget
357
+ */
358
+ sourceKey() {
359
+ return JSON.stringify({
360
+ s: this.content.source || {},
361
+ f: this.dateField,
362
+ d: this.weekDays.length > 0 ? [dayKey(this.weekDays[0]), this.weekDays.length] : [],
363
+ })
364
+ },
365
+ },
366
+
367
+ watch: {
368
+ /** @spec openspec/changes/workplace-dashboard-primitives/specs/workplace-dashboard-primitives/spec.md#requirement-week-strip-widget */
369
+ sourceKey() {
370
+ this.fetchItems()
371
+ },
372
+ },
373
+
374
+ mounted() {
375
+ this.fetchItems()
376
+ },
377
+
378
+ methods: {
379
+ /**
380
+ * Whether a date counts as late under `content.lateWhen` (default:
381
+ * before today).
382
+ *
383
+ * @param {Date|null} date The item's date.
384
+ * @return {boolean}
385
+ * @spec openspec/changes/workplace-dashboard-primitives/specs/workplace-dashboard-primitives/spec.md#requirement-week-strip-widget
386
+ */
387
+ isLateDate(date) {
388
+ if (date === null) {
389
+ return false
390
+ }
391
+ const rule = (this.content.lateWhen && typeof this.content.lateWhen === 'object')
392
+ ? this.content.lateWhen
393
+ : { op: 'lt', value: 0 }
394
+ return compareVisibleWhen(daysUntil(date, this.reference), rule.op || 'lt', rule.value ?? 0)
395
+ },
396
+
397
+ /**
398
+ * One OpenRegister record as a strip item.
399
+ *
400
+ * @param {object} row The record.
401
+ * @param {number} index Its position, used as a key of last resort.
402
+ * @return {object} The item.
403
+ * @spec openspec/changes/workplace-dashboard-primitives/specs/workplace-dashboard-primitives/spec.md#requirement-week-strip-widget
404
+ */
405
+ itemFromRow(row, index) {
406
+ const c = this.content
407
+ const id = row && (row.id || (row['@self'] && row['@self'].id))
408
+ const date = parseDateValue(objectFieldValue(row, this.dateField))
409
+ const titleValue = c.titleField ? objectFieldValue(row, c.titleField) : undefined
410
+ const title = (titleValue !== undefined && titleValue !== null && titleValue !== '')
411
+ ? String(titleValue)
412
+ : objectDisplayName(row)
413
+ const metaFields = Array.isArray(c.metaFields) ? c.metaFields : []
414
+ const meta = metaFields
415
+ .map((field) => objectFieldValue(row, field))
416
+ .filter((value) => value !== undefined && value !== null && value !== '' && typeof value !== 'object')
417
+ .map(String)
418
+ .join(' · ')
419
+ const flagged = c.lateField ? objectFieldValue(row, c.lateField) === true : false
420
+ const target = (c.itemRoute && id) ? { name: c.itemRoute, params: { id } } : null
421
+ return {
422
+ key: String(id || `row-${index}`),
423
+ title,
424
+ meta,
425
+ date,
426
+ late: flagged || this.isLateDate(date),
427
+ target,
428
+ href: target ? resolveHref(target, this.$router) : '',
429
+ }
430
+ },
431
+
432
+ /**
433
+ * One static manifest entry as a strip item.
434
+ *
435
+ * @param {object} item The entry.
436
+ * @param {number} index Its position.
437
+ * @return {object} The item.
438
+ * @spec openspec/changes/workplace-dashboard-primitives/specs/workplace-dashboard-primitives/spec.md#requirement-week-strip-widget
439
+ */
440
+ itemFromStatic(item, index) {
441
+ const date = parseDateValue(item.date)
442
+ let target = null
443
+ let href = ''
444
+ if (item.route) {
445
+ target = typeof item.route === 'string' ? { name: item.route } : item.route
446
+ href = resolveHref(target, this.$router)
447
+ } else if (typeof item.href === 'string' && item.href !== '') {
448
+ const safe = safeHref(item.href)
449
+ href = safe === '#' ? '' : safe
450
+ }
451
+ return {
452
+ key: `item-${index}`,
453
+ title: typeof item.title === 'string' ? this.effectiveTranslate(item.title) : '',
454
+ meta: typeof item.meta === 'string' ? this.effectiveTranslate(item.meta) : '',
455
+ date,
456
+ late: item.late === true || (item.late !== false && this.isLateDate(date)),
457
+ target,
458
+ href,
459
+ }
460
+ },
461
+
462
+ /**
463
+ * Load the week's records in one request.
464
+ *
465
+ * @return {Promise<void>}
466
+ * @spec openspec/changes/workplace-dashboard-primitives/specs/workplace-dashboard-primitives/spec.md#requirement-week-strip-widget
467
+ */
468
+ async fetchItems() {
469
+ if (!this.hasSource) {
470
+ this.rows = []
471
+ this.error = ''
472
+ return
473
+ }
474
+ const s = this.content.source
475
+ const requestKey = this.sourceKey
476
+ const first = this.weekDays[0]
477
+ const last = this.weekDays[this.weekDays.length - 1]
478
+ const dayAfter = new Date(last.getFullYear(), last.getMonth(), last.getDate() + 1)
479
+ this.loading = true
480
+ this.error = ''
481
+ try {
482
+ const [{ default: axios }, { generateUrl }] = await Promise.all([
483
+ import('@nextcloud/axios'),
484
+ import('@nextcloud/router'),
485
+ ])
486
+ const url = generateUrl(
487
+ '/apps/openregister/api/objects/{register}/{schema}',
488
+ { register: s.register, schema: s.schema },
489
+ )
490
+ const params = {
491
+ _limit: Number.isInteger(s.limit) && s.limit > 0 ? s.limit : DEFAULT_LIMIT,
492
+ [`_order[${this.dateField}]`]: 'asc',
493
+ }
494
+ const filter = resolveFilterTokens(s.filter || {}, {})
495
+ for (const [k, v] of Object.entries(filter || {})) {
496
+ if (v && typeof v === 'object') {
497
+ for (const [op, ov] of Object.entries(v)) {
498
+ params[`${k}[${op}]`] = ov
499
+ }
500
+ } else if (v !== '' && v !== null && v !== undefined) {
501
+ params[k] = v
502
+ }
503
+ }
504
+ // The week window goes last, so a manifest filter on the date
505
+ // field cannot widen the strip beyond the days it shows.
506
+ params[`${this.dateField}[gte]`] = dayKey(first)
507
+ params[`${this.dateField}[lt]`] = dayKey(dayAfter)
508
+ const res = await axios.get(url, { params })
509
+ if (requestKey !== this.sourceKey) {
510
+ return
511
+ }
512
+ this.rows = (res && res.data && Array.isArray(res.data.results)) ? res.data.results : []
513
+ } catch (e) {
514
+ // eslint-disable-next-line no-console
515
+ console.warn('[CnWeekStripWidget] failed to load items:', e)
516
+ this.error = (e && e.message) || 'error'
517
+ this.rows = []
518
+ } finally {
519
+ this.loading = false
520
+ }
521
+ },
522
+
523
+ /**
524
+ * Route a plain click on an in-app item; the browser handles the rest.
525
+ *
526
+ * @param {MouseEvent} event The click.
527
+ * @param {object} item The clicked item.
528
+ * @return {void}
529
+ * @spec openspec/changes/workplace-dashboard-primitives/specs/workplace-dashboard-primitives/spec.md#requirement-week-strip-widget
530
+ */
531
+ onItemClick(event, item) {
532
+ if (item.target) {
533
+ followLinkClick(event, item.target, this.$router)
534
+ }
535
+ },
536
+ },
537
+ }
538
+ </script>
539
+
540
+ <style scoped>
541
+ .cn-week-strip {
542
+ width: 100%;
543
+ }
544
+
545
+ .cn-week-strip__state {
546
+ display: flex;
547
+ align-items: center;
548
+ gap: 8px;
549
+ margin: 0;
550
+ padding: 12px 4px;
551
+ color: var(--color-text-maxcontrast);
552
+ }
553
+
554
+ .cn-week-strip__scroll {
555
+ overflow-x: auto;
556
+ border-radius: var(--border-radius-large, 8px);
557
+ }
558
+
559
+ .cn-week-strip__scroll:focus-visible {
560
+ outline: 2px solid var(--color-primary-element);
561
+ outline-offset: 2px;
562
+ }
563
+
564
+ .cn-week-strip__days {
565
+ display: grid;
566
+ grid-template-columns: repeat(var(--cn-week-strip-columns, 5), minmax(128px, 1fr));
567
+ gap: 10px;
568
+ /* 5 columns of 128px plus gaps: below this the region scrolls sideways. */
569
+ min-width: calc(var(--cn-week-strip-columns, 5) * 136px);
570
+ margin: 0;
571
+ padding: 0;
572
+ list-style: none;
573
+ }
574
+
575
+ .cn-week-strip__day {
576
+ display: flex;
577
+ flex-direction: column;
578
+ gap: 8px;
579
+ min-width: 0;
580
+ padding: 10px;
581
+ border: 1px solid var(--color-border);
582
+ border-radius: var(--border-radius-large, 8px);
583
+ background: var(--color-background-hover);
584
+ }
585
+
586
+ .cn-week-strip__day--today {
587
+ border-color: var(--color-primary-element);
588
+ background: var(--color-primary-element-light);
589
+ }
590
+
591
+ .cn-week-strip__head {
592
+ display: flex;
593
+ align-items: center;
594
+ justify-content: space-between;
595
+ gap: 6px;
596
+ font-size: 0.85em;
597
+ font-weight: 600;
598
+ color: var(--color-main-text);
599
+ }
600
+
601
+ .cn-week-strip__today {
602
+ padding: 1px 8px;
603
+ border-radius: var(--border-radius-pill, 10px);
604
+ background: var(--color-primary-element);
605
+ color: var(--color-primary-element-text);
606
+ font-size: 0.85em;
607
+ font-weight: 700;
608
+ }
609
+
610
+ .cn-week-strip__items {
611
+ display: flex;
612
+ flex-direction: column;
613
+ gap: 6px;
614
+ margin: 0;
615
+ padding: 0;
616
+ list-style: none;
617
+ }
618
+
619
+ .cn-week-strip__item {
620
+ display: flex;
621
+ flex-direction: column;
622
+ gap: 4px;
623
+ padding: 10px 12px;
624
+ border: 1px solid var(--color-border);
625
+ border-radius: var(--border-radius-large, 8px);
626
+ background: var(--color-main-background);
627
+ color: var(--color-main-text);
628
+ text-decoration: none;
629
+ }
630
+
631
+ .cn-week-strip__item--link:hover {
632
+ border-color: var(--color-primary-element);
633
+ }
634
+
635
+ .cn-week-strip__item--link:focus-visible {
636
+ outline: 2px solid var(--color-primary-element);
637
+ outline-offset: 2px;
638
+ }
639
+
640
+ /* The edge is drawn inside the box, so a late item is as wide as the others. */
641
+ .cn-week-strip__item--late {
642
+ border-color: var(--color-element-error, var(--color-error));
643
+ box-shadow: inset 3px 0 0 0 var(--color-element-error, var(--color-error));
644
+ }
645
+
646
+ .cn-week-strip__title {
647
+ font-size: 0.95em;
648
+ line-height: 1.3;
649
+ overflow-wrap: anywhere;
650
+ }
651
+
652
+ .cn-week-strip__meta {
653
+ font-size: 0.85em;
654
+ color: var(--color-text-maxcontrast);
655
+ overflow-wrap: anywhere;
656
+ }
657
+
658
+ .cn-week-strip__late {
659
+ font-size: 0.8em;
660
+ font-weight: 600;
661
+ color: var(--color-text-error, var(--color-error-text));
662
+ }
663
+
664
+ .cn-week-strip__empty {
665
+ font-size: 0.9em;
666
+ color: var(--color-text-maxcontrast);
667
+ }
668
+ </style>
@@ -0,0 +1,14 @@
1
+ /**
2
+ * SPDX-FileCopyrightText: 2026 Conduction B.V.
3
+ * SPDX-License-Identifier: EUPL-1.2
4
+ *
5
+ * CnWeekStripWidget: the `week-strip` dashboard widget (the current week as
6
+ * day columns with the dated items under each day). It is registered in
7
+ * `CnWidgetGrid/registerDashboardWidgets.js`, inline, because a bare
8
+ * side-effect import of this module may be tree-shaken away.
9
+ */
10
+
11
+ import CnWeekStripWidget from './CnWeekStripWidget.vue'
12
+
13
+ export { CnWeekStripWidget }
14
+ export default CnWeekStripWidget