@conduction/nextcloud-vue 2.80.0 → 2.81.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 (290) hide show
  1. package/dist/esm/components/CnActionsBar/CnActionsBar.vue2.js.map +1 -1
  2. package/dist/esm/components/CnActionsBar/CnActionsBar.vue3.js +3 -3
  3. package/dist/esm/components/CnActionsBar/CnActionsBar.vue3.js.map +1 -1
  4. package/dist/esm/components/CnAppRoot/CnAppRoot.vue2.js +80 -4
  5. package/dist/esm/components/CnAppRoot/CnAppRoot.vue2.js.map +1 -1
  6. package/dist/esm/components/CnAppRoot/CnAppRoot.vue3.js +95 -91
  7. package/dist/esm/components/CnAppRoot/CnAppRoot.vue3.js.map +1 -1
  8. package/dist/esm/components/CnBannerWidget/CnBannerWidget.vue2.js +140 -10
  9. package/dist/esm/components/CnBannerWidget/CnBannerWidget.vue2.js.map +1 -1
  10. package/dist/esm/components/CnBannerWidget/CnBannerWidget.vue3.js +52 -16
  11. package/dist/esm/components/CnBannerWidget/CnBannerWidget.vue3.js.map +1 -1
  12. package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue2.js +17 -3
  13. package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue2.js.map +1 -1
  14. package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue3.js +63 -52
  15. package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue3.js.map +1 -1
  16. package/dist/esm/components/CnChipsFieldWidget/CnChipsFieldWidget.vue.js +10 -0
  17. package/dist/esm/components/CnChipsFieldWidget/CnChipsFieldWidget.vue.js.map +1 -0
  18. package/dist/esm/components/CnChipsFieldWidget/CnChipsFieldWidget.vue2.js +252 -0
  19. package/dist/esm/components/CnChipsFieldWidget/CnChipsFieldWidget.vue2.js.map +1 -0
  20. package/dist/esm/components/CnChipsFieldWidget/CnChipsFieldWidget.vue3.js +140 -0
  21. package/dist/esm/components/CnChipsFieldWidget/CnChipsFieldWidget.vue3.js.map +1 -0
  22. package/dist/esm/components/CnChipsFieldWidget/index.js +26 -0
  23. package/dist/esm/components/CnChipsFieldWidget/index.js.map +1 -0
  24. package/dist/esm/components/CnChoicePickerWidget/CnChoicePickerWidget.vue.js +10 -0
  25. package/dist/esm/components/CnChoicePickerWidget/CnChoicePickerWidget.vue.js.map +1 -0
  26. package/dist/esm/components/CnChoicePickerWidget/CnChoicePickerWidget.vue2.js +354 -0
  27. package/dist/esm/components/CnChoicePickerWidget/CnChoicePickerWidget.vue2.js.map +1 -0
  28. package/dist/esm/components/CnChoicePickerWidget/CnChoicePickerWidget.vue3.js +172 -0
  29. package/dist/esm/components/CnChoicePickerWidget/CnChoicePickerWidget.vue3.js.map +1 -0
  30. package/dist/esm/components/CnChoicePickerWidget/index.js +27 -0
  31. package/dist/esm/components/CnChoicePickerWidget/index.js.map +1 -0
  32. package/dist/esm/components/CnConversationThread/CnConversationWidget.vue2.js +1 -1
  33. package/dist/esm/components/CnConversationThread/CnConversationWidget.vue2.js.map +1 -1
  34. package/dist/esm/components/CnConversationThread/CnConversationWidget.vue3.js.map +1 -1
  35. package/dist/esm/components/CnDashboardGrid/CnDashboardGrid.vue2.js +2 -2
  36. package/dist/esm/components/CnDashboardGrid/CnDashboardGrid.vue2.js.map +1 -1
  37. package/dist/esm/components/CnDashboardGrid/CnDashboardGrid.vue3.js.map +1 -1
  38. package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue2.js +65 -5
  39. package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue2.js.map +1 -1
  40. package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue3.js +2 -1
  41. package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue3.js.map +1 -1
  42. package/dist/esm/components/CnDataTable/CnDataTable.vue2.js +19 -11
  43. package/dist/esm/components/CnDataTable/CnDataTable.vue2.js.map +1 -1
  44. package/dist/esm/components/CnDataTable/CnDataTable.vue3.js +3 -2
  45. package/dist/esm/components/CnDataTable/CnDataTable.vue3.js.map +1 -1
  46. package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js +72 -0
  47. package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js.map +1 -1
  48. package/dist/esm/components/CnDetailPage/CnDetailPage.vue3.js +21 -4
  49. package/dist/esm/components/CnDetailPage/CnDetailPage.vue3.js.map +1 -1
  50. package/dist/esm/components/CnDocumentReviewList/CnDocumentReviewWidget.vue2.js +1 -1
  51. package/dist/esm/components/CnDocumentReviewList/CnDocumentReviewWidget.vue2.js.map +1 -1
  52. package/dist/esm/components/CnDocumentReviewList/CnDocumentReviewWidget.vue3.js.map +1 -1
  53. package/dist/esm/components/CnFacetSidebar/CnFacetSidebar.vue2.js +7 -7
  54. package/dist/esm/components/CnFacetSidebar/CnFacetSidebar.vue2.js.map +1 -1
  55. package/dist/esm/components/CnFacetSidebar/CnFacetSidebar.vue3.js.map +1 -1
  56. package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue2.js +131 -0
  57. package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue2.js.map +1 -1
  58. package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue3.js.map +1 -1
  59. package/dist/esm/components/CnFieldListWidget/CnFieldListWidget.vue2.js +80 -5
  60. package/dist/esm/components/CnFieldListWidget/CnFieldListWidget.vue2.js.map +1 -1
  61. package/dist/esm/components/CnFieldListWidget/CnFieldListWidget.vue3.js +282 -69
  62. package/dist/esm/components/CnFieldListWidget/CnFieldListWidget.vue3.js.map +1 -1
  63. package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue2.js +302 -4
  64. package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue2.js.map +1 -1
  65. package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue3.js +417 -244
  66. package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue3.js.map +1 -1
  67. package/dist/esm/components/CnFilesBrowser/filesBrowser.js +101 -1
  68. package/dist/esm/components/CnFilesBrowser/filesBrowser.js.map +1 -1
  69. package/dist/esm/components/CnFilesBrowser/filesBrowserColumns.js +141 -1
  70. package/dist/esm/components/CnFilesBrowser/filesBrowserColumns.js.map +1 -1
  71. package/dist/esm/components/CnFormPage/CnFormPage.vue2.js +60 -0
  72. package/dist/esm/components/CnFormPage/CnFormPage.vue2.js.map +1 -1
  73. package/dist/esm/components/CnFormPage/CnFormPage.vue3.js +74 -49
  74. package/dist/esm/components/CnFormPage/CnFormPage.vue3.js.map +1 -1
  75. package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js +29 -2
  76. package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js.map +1 -1
  77. package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js +48 -4
  78. package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js.map +1 -1
  79. package/dist/esm/components/CnIndexSidebar/CnIndexSidebar.vue2.js +7 -7
  80. package/dist/esm/components/CnIndexSidebar/CnIndexSidebar.vue2.js.map +1 -1
  81. package/dist/esm/components/CnIndexSidebar/CnIndexSidebar.vue3.js.map +1 -1
  82. package/dist/esm/components/CnNextStepCard/CnNextStepWidget.vue2.js +1 -1
  83. package/dist/esm/components/CnNextStepCard/CnNextStepWidget.vue2.js.map +1 -1
  84. package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue2.js +65 -2
  85. package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue2.js.map +1 -1
  86. package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue3.js +6 -2
  87. package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue3.js.map +1 -1
  88. package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue2.js +63 -1
  89. package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue2.js.map +1 -1
  90. package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue3.js +8 -1
  91. package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue3.js.map +1 -1
  92. package/dist/esm/components/CnObjectSidebar/CnNotesTab.vue2.js +14 -0
  93. package/dist/esm/components/CnObjectSidebar/CnNotesTab.vue2.js.map +1 -1
  94. package/dist/esm/components/CnObjectSidebar/CnNotesTab.vue3.js +5 -1
  95. package/dist/esm/components/CnObjectSidebar/CnNotesTab.vue3.js.map +1 -1
  96. package/dist/esm/components/CnRadioCardsWidget/CnRadioCardsWidget.vue.js +10 -0
  97. package/dist/esm/components/CnRadioCardsWidget/CnRadioCardsWidget.vue.js.map +1 -0
  98. package/dist/esm/components/CnRadioCardsWidget/CnRadioCardsWidget.vue2.js +174 -0
  99. package/dist/esm/components/CnRadioCardsWidget/CnRadioCardsWidget.vue2.js.map +1 -0
  100. package/dist/esm/components/CnRadioCardsWidget/CnRadioCardsWidget.vue3.js +75 -0
  101. package/dist/esm/components/CnRadioCardsWidget/CnRadioCardsWidget.vue3.js.map +1 -0
  102. package/dist/esm/components/CnRadioCardsWidget/index.js +28 -0
  103. package/dist/esm/components/CnRadioCardsWidget/index.js.map +1 -0
  104. package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue2.js +30 -6
  105. package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue2.js.map +1 -1
  106. package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue3.js +34 -25
  107. package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue3.js.map +1 -1
  108. package/dist/esm/components/CnSavedViewsWidget/CnSavedViewsWidget.vue.js +10 -0
  109. package/dist/esm/components/CnSavedViewsWidget/CnSavedViewsWidget.vue.js.map +1 -0
  110. package/dist/esm/components/CnSavedViewsWidget/CnSavedViewsWidget.vue2.js +222 -0
  111. package/dist/esm/components/CnSavedViewsWidget/CnSavedViewsWidget.vue2.js.map +1 -0
  112. package/dist/esm/components/CnSavedViewsWidget/CnSavedViewsWidget.vue3.js +64 -0
  113. package/dist/esm/components/CnSavedViewsWidget/CnSavedViewsWidget.vue3.js.map +1 -0
  114. package/dist/esm/components/CnSavedViewsWidget/index.js +30 -0
  115. package/dist/esm/components/CnSavedViewsWidget/index.js.map +1 -0
  116. package/dist/esm/components/CnSegmentedControl/CnSegmentedControl.vue2.js.map +1 -1
  117. package/dist/esm/components/CnSegmentedControl/CnSegmentedControl.vue3.js.map +1 -1
  118. package/dist/esm/components/CnSettingsFormWidget/CnSettingsFormWidget.vue.js +10 -0
  119. package/dist/esm/components/CnSettingsFormWidget/CnSettingsFormWidget.vue.js.map +1 -0
  120. package/dist/esm/components/CnSettingsFormWidget/CnSettingsFormWidget.vue2.js +347 -0
  121. package/dist/esm/components/CnSettingsFormWidget/CnSettingsFormWidget.vue2.js.map +1 -0
  122. package/dist/esm/components/CnSettingsFormWidget/CnSettingsFormWidget.vue3.js +184 -0
  123. package/dist/esm/components/CnSettingsFormWidget/CnSettingsFormWidget.vue3.js.map +1 -0
  124. package/dist/esm/components/CnSettingsFormWidget/index.js +27 -0
  125. package/dist/esm/components/CnSettingsFormWidget/index.js.map +1 -0
  126. package/dist/esm/components/CnStatWidget/CnStatWidget.vue2.js +87 -6
  127. package/dist/esm/components/CnStatWidget/CnStatWidget.vue2.js.map +1 -1
  128. package/dist/esm/components/CnStatWidget/CnStatWidget.vue3.js.map +1 -1
  129. package/dist/esm/components/CnStatsBlockWidget/CnStatsBlockWidget.vue2.js +84 -1
  130. package/dist/esm/components/CnStatsBlockWidget/CnStatsBlockWidget.vue2.js.map +1 -1
  131. package/dist/esm/components/CnStatsBlockWidget/CnStatsBlockWidget.vue3.js +85 -41
  132. package/dist/esm/components/CnStatsBlockWidget/CnStatsBlockWidget.vue3.js.map +1 -1
  133. package/dist/esm/components/CnSwitchRowsWidget/CnSwitchRowsWidget.vue.js +10 -0
  134. package/dist/esm/components/CnSwitchRowsWidget/CnSwitchRowsWidget.vue.js.map +1 -0
  135. package/dist/esm/components/CnSwitchRowsWidget/CnSwitchRowsWidget.vue2.js +159 -0
  136. package/dist/esm/components/CnSwitchRowsWidget/CnSwitchRowsWidget.vue2.js.map +1 -0
  137. package/dist/esm/components/CnSwitchRowsWidget/CnSwitchRowsWidget.vue3.js +60 -0
  138. package/dist/esm/components/CnSwitchRowsWidget/CnSwitchRowsWidget.vue3.js.map +1 -0
  139. package/dist/esm/components/CnSwitchRowsWidget/index.js +26 -0
  140. package/dist/esm/components/CnSwitchRowsWidget/index.js.map +1 -0
  141. package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue2.js +47 -1
  142. package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue2.js.map +1 -1
  143. package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue3.js +16 -14
  144. package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue3.js.map +1 -1
  145. package/dist/esm/components/CnTasksWidget/CnTasksWidget.vue2.js +80 -1
  146. package/dist/esm/components/CnTasksWidget/CnTasksWidget.vue2.js.map +1 -1
  147. package/dist/esm/components/CnTasksWidget/CnTasksWidget.vue3.js +75 -32
  148. package/dist/esm/components/CnTasksWidget/CnTasksWidget.vue3.js.map +1 -1
  149. package/dist/esm/components/CnToggleTableWidget/CnToggleTableWidget.vue.js +10 -0
  150. package/dist/esm/components/CnToggleTableWidget/CnToggleTableWidget.vue.js.map +1 -0
  151. package/dist/esm/components/CnToggleTableWidget/CnToggleTableWidget.vue2.js +269 -0
  152. package/dist/esm/components/CnToggleTableWidget/CnToggleTableWidget.vue2.js.map +1 -0
  153. package/dist/esm/components/CnToggleTableWidget/CnToggleTableWidget.vue3.js +106 -0
  154. package/dist/esm/components/CnToggleTableWidget/CnToggleTableWidget.vue3.js.map +1 -0
  155. package/dist/esm/components/CnToggleTableWidget/index.js +27 -0
  156. package/dist/esm/components/CnToggleTableWidget/index.js.map +1 -0
  157. package/dist/esm/components/CnWidgetGrid/registerDashboardWidgets.js +7 -0
  158. package/dist/esm/components/CnWidgetGrid/registerDashboardWidgets.js.map +1 -1
  159. package/dist/esm/components/CnWidgetObjectTable/CnWidgetObjectTable.vue2.js +7 -2
  160. package/dist/esm/components/CnWidgetObjectTable/CnWidgetObjectTable.vue2.js.map +1 -1
  161. package/dist/esm/components/CnWidgetObjectTable/CnWidgetObjectTable.vue3.js.map +1 -1
  162. package/dist/esm/components/CnWidgetObjectTable/dashboardRegistration.js +5 -0
  163. package/dist/esm/components/CnWidgetObjectTable/dashboardRegistration.js.map +1 -1
  164. package/dist/esm/components/CnWorkspaceFilterWidget/CnWorkspaceFilterWidget.vue2.js +197 -6
  165. package/dist/esm/components/CnWorkspaceFilterWidget/CnWorkspaceFilterWidget.vue2.js.map +1 -1
  166. package/dist/esm/components/CnWorkspaceFilterWidget/CnWorkspaceFilterWidget.vue3.js +96 -50
  167. package/dist/esm/components/CnWorkspaceFilterWidget/CnWorkspaceFilterWidget.vue3.js.map +1 -1
  168. package/dist/esm/composables/useListView.js +4 -4
  169. package/dist/esm/composables/useListView.js.map +1 -1
  170. package/dist/esm/index.js +17 -1
  171. package/dist/esm/index.js.map +1 -1
  172. package/dist/esm/l10n/en.json.js +9 -1
  173. package/dist/esm/l10n/en.json.js.map +1 -1
  174. package/dist/esm/l10n/nl.json.js +55 -1
  175. package/dist/esm/l10n/nl.json.js.map +1 -1
  176. package/dist/esm/nextcloud-vue.css +1041 -12
  177. package/dist/esm/utils/contentHeaderLink.js +51 -0
  178. package/dist/esm/utils/contentHeaderLink.js.map +1 -0
  179. package/dist/esm/utils/facets.js +75 -3
  180. package/dist/esm/utils/facets.js.map +1 -1
  181. package/dist/esm/utils/fetchFilterCounts.js +40 -5
  182. package/dist/esm/utils/fetchFilterCounts.js.map +1 -1
  183. package/dist/esm/utils/fillTemplate.js +7 -1
  184. package/dist/esm/utils/fillTemplate.js.map +1 -1
  185. package/dist/esm/utils/initials.js +32 -0
  186. package/dist/esm/utils/initials.js.map +1 -0
  187. package/dist/esm/utils/libraryWidgetKeys.js +7 -0
  188. package/dist/esm/utils/libraryWidgetKeys.js.map +1 -1
  189. package/dist/esm/utils/objectWrite.js +59 -0
  190. package/dist/esm/utils/objectWrite.js.map +1 -0
  191. package/dist/esm/utils/pageControls.js +81 -0
  192. package/dist/esm/utils/pageControls.js.map +1 -0
  193. package/dist/esm/utils/personalLenses.js +40 -3
  194. package/dist/esm/utils/personalLenses.js.map +1 -1
  195. package/dist/esm/utils/resolveFilterTokens.js +1 -1
  196. package/dist/esm/utils/resolveFilterTokens.js.map +1 -1
  197. package/dist/esm/utils/resolveManifestTokens.js +2 -0
  198. package/dist/esm/utils/resolveManifestTokens.js.map +1 -1
  199. package/dist/esm/utils/sentinelTokens.js +19 -1
  200. package/dist/esm/utils/sentinelTokens.js.map +1 -1
  201. package/dist/esm/utils/userGroupsPeek.js +91 -0
  202. package/dist/esm/utils/userGroupsPeek.js.map +1 -0
  203. package/dist/esm/utils/validateManifestV2.compiled.js +3 -3
  204. package/dist/esm/utils/validateManifestV2.compiled.js.map +1 -1
  205. package/dist/esm/utils/visibleWhen.js +57 -5
  206. package/dist/esm/utils/visibleWhen.js.map +1 -1
  207. package/dist/esm/utils/widgetDispatch.js +1 -1
  208. package/dist/esm/utils/widgetDispatch.js.map +1 -1
  209. package/dist/esm/utils/widgetVisibility.js +4 -57
  210. package/dist/esm/utils/widgetVisibility.js.map +1 -1
  211. package/dist/nextcloud-vue.cjs.js +13589 -7833
  212. package/dist/nextcloud-vue.cjs.js.map +2 -2
  213. package/dist/nextcloud-vue.css +1041 -12
  214. package/l10n/en.json +9 -1
  215. package/l10n/nl.json +55 -1
  216. package/package.json +2 -1
  217. package/scripts/check-docs-mdx.mjs +108 -0
  218. package/src/components/CnActionsBar/CnActionsBar.vue +6 -1
  219. package/src/components/CnAppRoot/CnAppRoot.md +4 -2
  220. package/src/components/CnAppRoot/CnAppRoot.vue +151 -59
  221. package/src/components/CnBannerWidget/CnBannerWidget.vue +205 -20
  222. package/src/components/CnCellRenderer/CnCellRenderer.md +2 -0
  223. package/src/components/CnCellRenderer/CnCellRenderer.vue +47 -4
  224. package/src/components/CnChipsFieldWidget/CnChipsFieldWidget.vue +433 -0
  225. package/src/components/CnChipsFieldWidget/index.js +25 -0
  226. package/src/components/CnChoicePickerWidget/CnChoicePickerWidget.vue +556 -0
  227. package/src/components/CnChoicePickerWidget/index.js +26 -0
  228. package/src/components/CnConversationThread/CnConversationWidget.vue +1 -1
  229. package/src/components/CnDashboardGrid/CnDashboardGrid.vue +2 -2
  230. package/src/components/CnDashboardPage/CnDashboardPage.vue +78 -5
  231. package/src/components/CnDataTable/CnDataTable.vue +21 -12
  232. package/src/components/CnDetailPage/CnDetailPage.vue +89 -3
  233. package/src/components/CnDocumentReviewList/CnDocumentReviewWidget.vue +1 -1
  234. package/src/components/CnFacetSidebar/CnFacetSidebar.vue +7 -7
  235. package/src/components/CnFactsWidget/CnFactsWidget.vue +142 -2
  236. package/src/components/CnFieldListWidget/CnFieldListWidget.vue +268 -6
  237. package/src/components/CnFilesBrowser/CnFilesBrowser.vue +588 -117
  238. package/src/components/CnFilesBrowser/filesBrowser.js +100 -0
  239. package/src/components/CnFilesBrowser/filesBrowserColumns.js +140 -0
  240. package/src/components/CnFormPage/CnFormPage.vue +81 -0
  241. package/src/components/CnIndexPage/CnIndexPage.vue +56 -4
  242. package/src/components/CnIndexSidebar/CnIndexSidebar.vue +7 -7
  243. package/src/components/CnNextStepCard/CnNextStepWidget.vue +1 -1
  244. package/src/components/CnObjectListWidget/CnObjectListWidget.vue +69 -2
  245. package/src/components/CnObjectSidebar/CnFilesTab.vue +70 -1
  246. package/src/components/CnObjectSidebar/CnNotesTab.vue +16 -0
  247. package/src/components/CnRadioCardsWidget/CnRadioCardsWidget.vue +313 -0
  248. package/src/components/CnRadioCardsWidget/index.js +27 -0
  249. package/src/components/CnRecordListWidget/CnRecordListWidget.vue +55 -6
  250. package/src/components/CnSavedViewsWidget/CnSavedViewsWidget.vue +296 -0
  251. package/src/components/CnSavedViewsWidget/index.js +29 -0
  252. package/src/components/CnSegmentedControl/CnSegmentedControl.vue +13 -0
  253. package/src/components/CnSettingsFormWidget/CnSettingsFormWidget.vue +555 -0
  254. package/src/components/CnSettingsFormWidget/index.js +26 -0
  255. package/src/components/CnStatWidget/CnStatWidget.vue +87 -6
  256. package/src/components/CnStatsBlockWidget/CnStatsBlockWidget.vue +180 -3
  257. package/src/components/CnSwitchRowsWidget/CnSwitchRowsWidget.vue +226 -0
  258. package/src/components/CnSwitchRowsWidget/index.js +25 -0
  259. package/src/components/CnTabsWidget/CnTabsWidget.vue +82 -3
  260. package/src/components/CnTasksWidget/CnTasksWidget.vue +175 -15
  261. package/src/components/CnToggleTableWidget/CnToggleTableWidget.vue +386 -0
  262. package/src/components/CnToggleTableWidget/index.js +26 -0
  263. package/src/components/CnWidgetGrid/registerDashboardWidgets.js +7 -0
  264. package/src/components/CnWidgetObjectTable/CnWidgetObjectTable.vue +7 -2
  265. package/src/components/CnWidgetObjectTable/dashboardRegistration.js +5 -0
  266. package/src/components/CnWorkspaceFilterWidget/CnWorkspaceFilterWidget.vue +309 -11
  267. package/src/components/index.js +15 -0
  268. package/src/composables/useListView.js +4 -4
  269. package/src/css/look-board-detail.css +36 -2
  270. package/src/css/look-board-index.css +39 -8
  271. package/src/css/look-board.css +72 -0
  272. package/src/index.js +15 -0
  273. package/src/schemas/app-manifest-v2.schema.json +93 -9
  274. package/src/utils/contentHeaderLink.js +48 -0
  275. package/src/utils/facets.js +74 -2
  276. package/src/utils/fetchFilterCounts.js +39 -4
  277. package/src/utils/fillTemplate.js +7 -1
  278. package/src/utils/initials.js +29 -0
  279. package/src/utils/libraryWidgetKeys.js +7 -0
  280. package/src/utils/objectWrite.js +55 -0
  281. package/src/utils/pageControls.js +78 -0
  282. package/src/utils/personalLenses.js +39 -2
  283. package/src/utils/resolveFilterTokens.js +3 -1
  284. package/src/utils/resolveManifestTokens.js +2 -0
  285. package/src/utils/sentinelTokens.js +19 -1
  286. package/src/utils/userGroupsPeek.js +87 -0
  287. package/src/utils/validateManifestV2.compiled.js +3 -3
  288. package/src/utils/visibleWhen.js +56 -4
  289. package/src/utils/widgetDispatch.js +1 -1
  290. package/src/utils/widgetVisibility.js +7 -56
@@ -0,0 +1,159 @@
1
+ import { NcCheckboxRadioSwitch, NcNoteCard } from '@nextcloud/vue';
2
+ import { objectUrlOf, patchObject } from '../../utils/objectWrite.js';
3
+ import { readPath } from '../../utils/readPath.js';
4
+ import { serverErrorMessage } from '../../utils/serverErrorMessage.js';
5
+
6
+ /**
7
+ * CnSwitchRowsWidget — the `switch-rows` widget: a card of switches, each with
8
+ * a label and a hint, bound to boolean fields of the CURRENT object. A toggle
9
+ * saves at once with ONE PATCH of that field; a refused PATCH puts the switch
10
+ * back and shows the server's words.
11
+ *
12
+ * @spec openspec/changes/abstract-switch-rows/specs/switch-rows/spec.md
13
+ */
14
+ var script = {
15
+ name: 'CnSwitchRowsWidget',
16
+
17
+ components: { NcCheckboxRadioSwitch, NcNoteCard },
18
+
19
+ inject: {
20
+ cnTranslate: { default: () => (key) => key },
21
+ },
22
+
23
+ props: {
24
+ /**
25
+ * The widget configuration.
26
+ *
27
+ * - `rows` (required) — `[{ key, label, hint?, invert? }]`; `key` is a top-level boolean field. `invert` shows the switch on when the field is false (a stored `disabled` read as "enabled").
28
+ * - `readOnly`.
29
+ *
30
+ * @type {object}
31
+ */
32
+ content: {
33
+ type: Object,
34
+ default: () => ({}),
35
+ },
36
+
37
+ /** The current detail-page object. */
38
+ objectData: {
39
+ type: Object,
40
+ default: null,
41
+ },
42
+
43
+ /** The current object id. */
44
+ objectId: {
45
+ type: [String, Number],
46
+ default: '',
47
+ },
48
+
49
+ /** OpenRegister register slug of the surface. */
50
+ register: {
51
+ type: [String, Object],
52
+ default: '',
53
+ },
54
+
55
+ /** OpenRegister schema slug of the surface. */
56
+ schema: {
57
+ type: [String, Object],
58
+ default: '',
59
+ },
60
+ },
61
+
62
+ emits: ['saved'],
63
+
64
+ data() {
65
+ return {
66
+ /** The switch states as last saved (by key, as the switch shows them). */
67
+ saved: {},
68
+ values: {},
69
+ busy: '',
70
+ notice: '',
71
+ }
72
+ },
73
+
74
+ computed: {
75
+ rows() {
76
+ const list = Array.isArray(this.content.rows) ? this.content.rows : [];
77
+ return list
78
+ .filter((row) => row && row.key)
79
+ .map((row) => ({ ...row, label: this.tr(row.label || row.key), hint: this.tr(row.hint || '') }))
80
+ },
81
+
82
+ readOnly() {
83
+ return this.content.readOnly === true
84
+ },
85
+
86
+ objectUrl() {
87
+ return objectUrlOf(this.register, this.schema, this.objectId || (this.objectData && this.objectData.id))
88
+ },
89
+ },
90
+
91
+ watch: {
92
+ objectData() {
93
+ this.adopt();
94
+ },
95
+ },
96
+
97
+ created() {
98
+ this.adopt();
99
+ },
100
+
101
+ methods: {
102
+ tr(text) {
103
+ if (typeof text !== 'string' || text === '') {
104
+ return ''
105
+ }
106
+ return typeof this.cnTranslate === 'function' ? this.cnTranslate(text) : text
107
+ },
108
+
109
+ /** Read every switch off the object. */
110
+ adopt() {
111
+ const values = {};
112
+ for (const row of this.rows) {
113
+ const stored = readPath(this.objectData || {}, row.key) === true;
114
+ values[row.key] = row.invert ? !stored : stored;
115
+ }
116
+ this.saved = values;
117
+ this.values = { ...values };
118
+ },
119
+
120
+ /**
121
+ * Flip one switch and save that one field.
122
+ *
123
+ * @param {object} row The row.
124
+ * @param {boolean} on The new switch state.
125
+ * @return {Promise<void>}
126
+ * @spec openspec/changes/abstract-switch-rows/specs/switch-rows/spec.md#requirement-a-toggle-saves-that-one-field
127
+ */
128
+ async toggle(row, on) {
129
+ if (!this.objectUrl) {
130
+ this.notice = this.tr('This switch cannot be saved here.');
131
+ return
132
+ }
133
+ this.notice = '';
134
+ this.busy = row.key;
135
+ this.values = { ...this.values, [row.key]: on };
136
+ const stored = row.invert ? !on : on;
137
+ try {
138
+ const data = await patchObject(this.objectUrl, { [row.key]: stored });
139
+ const written = data[row.key] !== undefined ? data[row.key] === true : stored;
140
+ const shown = row.invert ? !written : written;
141
+ this.saved = { ...this.saved, [row.key]: shown };
142
+ this.values = { ...this.values, [row.key]: shown };
143
+ /**
144
+ * @event saved A switch was written.
145
+ * @type {{field: string, value: boolean}}
146
+ */
147
+ this.$emit('saved', { field: row.key, value: written });
148
+ } catch (e) {
149
+ this.values = { ...this.values, [row.key]: this.saved[row.key] };
150
+ this.notice = serverErrorMessage(e);
151
+ } finally {
152
+ this.busy = '';
153
+ }
154
+ },
155
+ },
156
+ };
157
+
158
+ export { script as default };
159
+ //# sourceMappingURL=CnSwitchRowsWidget.vue2.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CnSwitchRowsWidget.vue2.js","sources":["../../../../src/components/CnSwitchRowsWidget/CnSwitchRowsWidget.vue"],"sourcesContent":["<!--\n - SPDX-FileCopyrightText: 2026 Conduction B.V.\n - SPDX-License-Identifier: EUPL-1.2\n-->\n\n<template>\n\t<div class=\"cn-switch-rows\" data-testid=\"cn-switch-rows\">\n\t\t<ul class=\"cn-switch-rows__list\">\n\t\t\t<li\n\t\t\t\tv-for=\"row in rows\"\n\t\t\t\t:key=\"row.key\"\n\t\t\t\tclass=\"cn-switch-rows__row\"\n\t\t\t\t:data-testid=\"`cn-switch-rows-row-${row.key}`\">\n\t\t\t\t<NcCheckboxRadioSwitch\n\t\t\t\t\t:modelValue=\"values[row.key] === true\"\n\t\t\t\t\ttype=\"switch\"\n\t\t\t\t\t:disabled=\"readOnly || busy === row.key\"\n\t\t\t\t\t@update:modelValue=\"toggle(row, $event)\">\n\t\t\t\t\t<span class=\"cn-switch-rows__label\">{{ row.label }}</span>\n\t\t\t\t\t<span v-if=\"row.hint\" class=\"cn-switch-rows__hint\">{{ row.hint }}</span>\n\t\t\t\t</NcCheckboxRadioSwitch>\n\t\t\t</li>\n\t\t</ul>\n\t\t<NcNoteCard v-if=\"notice\" type=\"error\" data-testid=\"cn-switch-rows-notice\">\n\t\t\t{{ notice }}\n\t\t</NcNoteCard>\n\t</div>\n</template>\n\n<script>\nimport { NcCheckboxRadioSwitch, NcNoteCard } from '@nextcloud/vue'\nimport { objectUrlOf, patchObject } from '../../utils/objectWrite.js'\nimport { readPath } from '../../utils/readPath.js'\nimport { serverErrorMessage } from '../../utils/serverErrorMessage.js'\n\n/**\n * CnSwitchRowsWidget — the `switch-rows` widget: a card of switches, each with\n * a label and a hint, bound to boolean fields of the CURRENT object. A toggle\n * saves at once with ONE PATCH of that field; a refused PATCH puts the switch\n * back and shows the server's words.\n *\n * @spec openspec/changes/abstract-switch-rows/specs/switch-rows/spec.md\n */\nexport default {\n\tname: 'CnSwitchRowsWidget',\n\n\tcomponents: { NcCheckboxRadioSwitch, NcNoteCard },\n\n\tinject: {\n\t\tcnTranslate: { default: () => (key) => key },\n\t},\n\n\tprops: {\n\t\t/**\n\t\t * The widget configuration.\n\t\t *\n\t\t * - `rows` (required) — `[{ key, label, hint?, invert? }]`; `key` is a top-level boolean field. `invert` shows the switch on when the field is false (a stored `disabled` read as \"enabled\").\n\t\t * - `readOnly`.\n\t\t *\n\t\t * @type {object}\n\t\t */\n\t\tcontent: {\n\t\t\ttype: Object,\n\t\t\tdefault: () => ({}),\n\t\t},\n\n\t\t/** The current detail-page object. */\n\t\tobjectData: {\n\t\t\ttype: Object,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/** The current object id. */\n\t\tobjectId: {\n\t\t\ttype: [String, Number],\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/** OpenRegister register slug of the surface. */\n\t\tregister: {\n\t\t\ttype: [String, Object],\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/** OpenRegister schema slug of the surface. */\n\t\tschema: {\n\t\t\ttype: [String, Object],\n\t\t\tdefault: '',\n\t\t},\n\t},\n\n\temits: ['saved'],\n\n\tdata() {\n\t\treturn {\n\t\t\t/** The switch states as last saved (by key, as the switch shows them). */\n\t\t\tsaved: {},\n\t\t\tvalues: {},\n\t\t\tbusy: '',\n\t\t\tnotice: '',\n\t\t}\n\t},\n\n\tcomputed: {\n\t\trows() {\n\t\t\tconst list = Array.isArray(this.content.rows) ? this.content.rows : []\n\t\t\treturn list\n\t\t\t\t.filter((row) => row && row.key)\n\t\t\t\t.map((row) => ({ ...row, label: this.tr(row.label || row.key), hint: this.tr(row.hint || '') }))\n\t\t},\n\n\t\treadOnly() {\n\t\t\treturn this.content.readOnly === true\n\t\t},\n\n\t\tobjectUrl() {\n\t\t\treturn objectUrlOf(this.register, this.schema, this.objectId || (this.objectData && this.objectData.id))\n\t\t},\n\t},\n\n\twatch: {\n\t\tobjectData() {\n\t\t\tthis.adopt()\n\t\t},\n\t},\n\n\tcreated() {\n\t\tthis.adopt()\n\t},\n\n\tmethods: {\n\t\ttr(text) {\n\t\t\tif (typeof text !== 'string' || text === '') {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t\treturn typeof this.cnTranslate === 'function' ? this.cnTranslate(text) : text\n\t\t},\n\n\t\t/** Read every switch off the object. */\n\t\tadopt() {\n\t\t\tconst values = {}\n\t\t\tfor (const row of this.rows) {\n\t\t\t\tconst stored = readPath(this.objectData || {}, row.key) === true\n\t\t\t\tvalues[row.key] = row.invert ? !stored : stored\n\t\t\t}\n\t\t\tthis.saved = values\n\t\t\tthis.values = { ...values }\n\t\t},\n\n\t\t/**\n\t\t * Flip one switch and save that one field.\n\t\t *\n\t\t * @param {object} row The row.\n\t\t * @param {boolean} on The new switch state.\n\t\t * @return {Promise<void>}\n\t\t * @spec openspec/changes/abstract-switch-rows/specs/switch-rows/spec.md#requirement-a-toggle-saves-that-one-field\n\t\t */\n\t\tasync toggle(row, on) {\n\t\t\tif (!this.objectUrl) {\n\t\t\t\tthis.notice = this.tr('This switch cannot be saved here.')\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.notice = ''\n\t\t\tthis.busy = row.key\n\t\t\tthis.values = { ...this.values, [row.key]: on }\n\t\t\tconst stored = row.invert ? !on : on\n\t\t\ttry {\n\t\t\t\tconst data = await patchObject(this.objectUrl, { [row.key]: stored })\n\t\t\t\tconst written = data[row.key] !== undefined ? data[row.key] === true : stored\n\t\t\t\tconst shown = row.invert ? !written : written\n\t\t\t\tthis.saved = { ...this.saved, [row.key]: shown }\n\t\t\t\tthis.values = { ...this.values, [row.key]: shown }\n\t\t\t\t/**\n\t\t\t\t * @event saved A switch was written.\n\t\t\t\t * @type {{field: string, value: boolean}}\n\t\t\t\t */\n\t\t\t\tthis.$emit('saved', { field: row.key, value: written })\n\t\t\t} catch (e) {\n\t\t\t\tthis.values = { ...this.values, [row.key]: this.saved[row.key] }\n\t\t\t\tthis.notice = serverErrorMessage(e)\n\t\t\t} finally {\n\t\t\t\tthis.busy = ''\n\t\t\t}\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n.cn-switch-rows {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 8px;\n\tmin-width: 0;\n}\n\n.cn-switch-rows__list {\n\tlist-style: none;\n\tmargin: 0;\n\tpadding: 0;\n\tdisplay: flex;\n\tflex-direction: column;\n}\n\n.cn-switch-rows__row {\n\tpadding: 10px 0;\n\tborder-top: 1px solid var(--cn-board-hairline, var(--color-border));\n}\n\n.cn-switch-rows__row:first-child {\n\tborder-top: none;\n\tpadding-top: 0;\n}\n\n.cn-switch-rows__label {\n\tdisplay: block;\n\tfont-weight: 600;\n}\n\n.cn-switch-rows__hint {\n\tdisplay: block;\n\tfont-size: 12px;\n\tfont-weight: 400;\n\tcolor: var(--color-text-maxcontrast);\n}\n</style>\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,60 @@
1
+ import { resolveComponent, openBlock, createElementBlock, createElementVNode, Fragment, renderList, createVNode, withCtx, toDisplayString, createCommentVNode, createBlock, createTextVNode } from 'vue';
2
+
3
+ const _hoisted_1 = {
4
+ class: "cn-switch-rows",
5
+ "data-testid": "cn-switch-rows"
6
+ };
7
+ const _hoisted_2 = { class: "cn-switch-rows__list" };
8
+ const _hoisted_3 = ["data-testid"];
9
+ const _hoisted_4 = { class: "cn-switch-rows__label" };
10
+ const _hoisted_5 = {
11
+ key: 0,
12
+ class: "cn-switch-rows__hint"
13
+ };
14
+
15
+ function render(_ctx, _cache, $props, $setup, $data, $options) {
16
+ const _component_NcCheckboxRadioSwitch = resolveComponent("NcCheckboxRadioSwitch");
17
+ const _component_NcNoteCard = resolveComponent("NcNoteCard");
18
+
19
+ return (openBlock(), createElementBlock("div", _hoisted_1, [
20
+ createElementVNode("ul", _hoisted_2, [
21
+ (openBlock(true), createElementBlock(Fragment, null, renderList($options.rows, (row) => {
22
+ return (openBlock(), createElementBlock("li", {
23
+ key: row.key,
24
+ class: "cn-switch-rows__row",
25
+ "data-testid": `cn-switch-rows-row-${row.key}`
26
+ }, [
27
+ createVNode(_component_NcCheckboxRadioSwitch, {
28
+ modelValue: $data.values[row.key] === true,
29
+ type: "switch",
30
+ disabled: $options.readOnly || $data.busy === row.key,
31
+ "onUpdate:modelValue": $event => ($options.toggle(row, $event))
32
+ }, {
33
+ default: withCtx(() => [
34
+ createElementVNode("span", _hoisted_4, toDisplayString(row.label), 1 /* TEXT */),
35
+ (row.hint)
36
+ ? (openBlock(), createElementBlock("span", _hoisted_5, toDisplayString(row.hint), 1 /* TEXT */))
37
+ : createCommentVNode("v-if", true)
38
+ ]),
39
+ _: 2 /* DYNAMIC */
40
+ }, 1032 /* PROPS, DYNAMIC_SLOTS */, ["modelValue", "disabled", "onUpdate:modelValue"])
41
+ ], 8 /* PROPS */, _hoisted_3))
42
+ }), 128 /* KEYED_FRAGMENT */))
43
+ ]),
44
+ ($data.notice)
45
+ ? (openBlock(), createBlock(_component_NcNoteCard, {
46
+ key: 0,
47
+ type: "error",
48
+ "data-testid": "cn-switch-rows-notice"
49
+ }, {
50
+ default: withCtx(() => [
51
+ createTextVNode(toDisplayString($data.notice), 1 /* TEXT */)
52
+ ]),
53
+ _: 1 /* STABLE */
54
+ }))
55
+ : createCommentVNode("v-if", true)
56
+ ]))
57
+ }
58
+
59
+ export { render };
60
+ //# sourceMappingURL=CnSwitchRowsWidget.vue3.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CnSwitchRowsWidget.vue3.js","sources":["../../../../src/components/CnSwitchRowsWidget/CnSwitchRowsWidget.vue?vue&type=template&id=9dd5b4e2&lang.js"],"sourcesContent":["<!--\n - SPDX-FileCopyrightText: 2026 Conduction B.V.\n - SPDX-License-Identifier: EUPL-1.2\n-->\n\n<template>\n\t<div class=\"cn-switch-rows\" data-testid=\"cn-switch-rows\">\n\t\t<ul class=\"cn-switch-rows__list\">\n\t\t\t<li\n\t\t\t\tv-for=\"row in rows\"\n\t\t\t\t:key=\"row.key\"\n\t\t\t\tclass=\"cn-switch-rows__row\"\n\t\t\t\t:data-testid=\"`cn-switch-rows-row-${row.key}`\">\n\t\t\t\t<NcCheckboxRadioSwitch\n\t\t\t\t\t:modelValue=\"values[row.key] === true\"\n\t\t\t\t\ttype=\"switch\"\n\t\t\t\t\t:disabled=\"readOnly || busy === row.key\"\n\t\t\t\t\t@update:modelValue=\"toggle(row, $event)\">\n\t\t\t\t\t<span class=\"cn-switch-rows__label\">{{ row.label }}</span>\n\t\t\t\t\t<span v-if=\"row.hint\" class=\"cn-switch-rows__hint\">{{ row.hint }}</span>\n\t\t\t\t</NcCheckboxRadioSwitch>\n\t\t\t</li>\n\t\t</ul>\n\t\t<NcNoteCard v-if=\"notice\" type=\"error\" data-testid=\"cn-switch-rows-notice\">\n\t\t\t{{ notice }}\n\t\t</NcNoteCard>\n\t</div>\n</template>\n\n<script>\nimport { NcCheckboxRadioSwitch, NcNoteCard } from '@nextcloud/vue'\nimport { objectUrlOf, patchObject } from '../../utils/objectWrite.js'\nimport { readPath } from '../../utils/readPath.js'\nimport { serverErrorMessage } from '../../utils/serverErrorMessage.js'\n\n/**\n * CnSwitchRowsWidget — the `switch-rows` widget: a card of switches, each with\n * a label and a hint, bound to boolean fields of the CURRENT object. A toggle\n * saves at once with ONE PATCH of that field; a refused PATCH puts the switch\n * back and shows the server's words.\n *\n * @spec openspec/changes/abstract-switch-rows/specs/switch-rows/spec.md\n */\nexport default {\n\tname: 'CnSwitchRowsWidget',\n\n\tcomponents: { NcCheckboxRadioSwitch, NcNoteCard },\n\n\tinject: {\n\t\tcnTranslate: { default: () => (key) => key },\n\t},\n\n\tprops: {\n\t\t/**\n\t\t * The widget configuration.\n\t\t *\n\t\t * - `rows` (required) — `[{ key, label, hint?, invert? }]`; `key` is a top-level boolean field. `invert` shows the switch on when the field is false (a stored `disabled` read as \"enabled\").\n\t\t * - `readOnly`.\n\t\t *\n\t\t * @type {object}\n\t\t */\n\t\tcontent: {\n\t\t\ttype: Object,\n\t\t\tdefault: () => ({}),\n\t\t},\n\n\t\t/** The current detail-page object. */\n\t\tobjectData: {\n\t\t\ttype: Object,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/** The current object id. */\n\t\tobjectId: {\n\t\t\ttype: [String, Number],\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/** OpenRegister register slug of the surface. */\n\t\tregister: {\n\t\t\ttype: [String, Object],\n\t\t\tdefault: '',\n\t\t},\n\n\t\t/** OpenRegister schema slug of the surface. */\n\t\tschema: {\n\t\t\ttype: [String, Object],\n\t\t\tdefault: '',\n\t\t},\n\t},\n\n\temits: ['saved'],\n\n\tdata() {\n\t\treturn {\n\t\t\t/** The switch states as last saved (by key, as the switch shows them). */\n\t\t\tsaved: {},\n\t\t\tvalues: {},\n\t\t\tbusy: '',\n\t\t\tnotice: '',\n\t\t}\n\t},\n\n\tcomputed: {\n\t\trows() {\n\t\t\tconst list = Array.isArray(this.content.rows) ? this.content.rows : []\n\t\t\treturn list\n\t\t\t\t.filter((row) => row && row.key)\n\t\t\t\t.map((row) => ({ ...row, label: this.tr(row.label || row.key), hint: this.tr(row.hint || '') }))\n\t\t},\n\n\t\treadOnly() {\n\t\t\treturn this.content.readOnly === true\n\t\t},\n\n\t\tobjectUrl() {\n\t\t\treturn objectUrlOf(this.register, this.schema, this.objectId || (this.objectData && this.objectData.id))\n\t\t},\n\t},\n\n\twatch: {\n\t\tobjectData() {\n\t\t\tthis.adopt()\n\t\t},\n\t},\n\n\tcreated() {\n\t\tthis.adopt()\n\t},\n\n\tmethods: {\n\t\ttr(text) {\n\t\t\tif (typeof text !== 'string' || text === '') {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t\treturn typeof this.cnTranslate === 'function' ? this.cnTranslate(text) : text\n\t\t},\n\n\t\t/** Read every switch off the object. */\n\t\tadopt() {\n\t\t\tconst values = {}\n\t\t\tfor (const row of this.rows) {\n\t\t\t\tconst stored = readPath(this.objectData || {}, row.key) === true\n\t\t\t\tvalues[row.key] = row.invert ? !stored : stored\n\t\t\t}\n\t\t\tthis.saved = values\n\t\t\tthis.values = { ...values }\n\t\t},\n\n\t\t/**\n\t\t * Flip one switch and save that one field.\n\t\t *\n\t\t * @param {object} row The row.\n\t\t * @param {boolean} on The new switch state.\n\t\t * @return {Promise<void>}\n\t\t * @spec openspec/changes/abstract-switch-rows/specs/switch-rows/spec.md#requirement-a-toggle-saves-that-one-field\n\t\t */\n\t\tasync toggle(row, on) {\n\t\t\tif (!this.objectUrl) {\n\t\t\t\tthis.notice = this.tr('This switch cannot be saved here.')\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.notice = ''\n\t\t\tthis.busy = row.key\n\t\t\tthis.values = { ...this.values, [row.key]: on }\n\t\t\tconst stored = row.invert ? !on : on\n\t\t\ttry {\n\t\t\t\tconst data = await patchObject(this.objectUrl, { [row.key]: stored })\n\t\t\t\tconst written = data[row.key] !== undefined ? data[row.key] === true : stored\n\t\t\t\tconst shown = row.invert ? !written : written\n\t\t\t\tthis.saved = { ...this.saved, [row.key]: shown }\n\t\t\t\tthis.values = { ...this.values, [row.key]: shown }\n\t\t\t\t/**\n\t\t\t\t * @event saved A switch was written.\n\t\t\t\t * @type {{field: string, value: boolean}}\n\t\t\t\t */\n\t\t\t\tthis.$emit('saved', { field: row.key, value: written })\n\t\t\t} catch (e) {\n\t\t\t\tthis.values = { ...this.values, [row.key]: this.saved[row.key] }\n\t\t\t\tthis.notice = serverErrorMessage(e)\n\t\t\t} finally {\n\t\t\t\tthis.busy = ''\n\t\t\t}\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n.cn-switch-rows {\n\tdisplay: flex;\n\tflex-direction: column;\n\tgap: 8px;\n\tmin-width: 0;\n}\n\n.cn-switch-rows__list {\n\tlist-style: none;\n\tmargin: 0;\n\tpadding: 0;\n\tdisplay: flex;\n\tflex-direction: column;\n}\n\n.cn-switch-rows__row {\n\tpadding: 10px 0;\n\tborder-top: 1px solid var(--cn-board-hairline, var(--color-border));\n}\n\n.cn-switch-rows__row:first-child {\n\tborder-top: none;\n\tpadding-top: 0;\n}\n\n.cn-switch-rows__label {\n\tdisplay: block;\n\tfont-weight: 600;\n}\n\n.cn-switch-rows__hint {\n\tdisplay: block;\n\tfont-size: 12px;\n\tfont-weight: 400;\n\tcolor: var(--color-text-maxcontrast);\n}\n</style>\n"],"names":["_createElementBlock","_Fragment","_renderList","_createElementVNode","_toDisplayString"],"mappings":";;;AAWM,EAAA,KAAK,EAAC,gBAAgB;AAAC,EAAA,aAAC,EAAA,gBAAA;;AACxB,MAAA,UAAA,GAAA,EAAA,KAAK,EAAC,sBAAsB,GAAA;;AAWvB,MAAA,UAAA,GAAA,EAAA,KAAK,EAAC,uBAAwB,GAAA;;;AAC3B,EAAA,KAAA,EAAA,sBAAA;;;;;;;;;wBAXVA,kBAaE,CAAAC,QAAA,EAAA,IAAA,EAAAC,UAAA,CAZY,QAAI,CAAA,IAAA,EAAA,CAAX,GAAG,KAAA;6BADVF,kBAaE,CAAA,IAAA,EAAA;UAXD,GAAG,EAAE,GAAG,CAAC,GAAG;AACZ,UAAA,KAAI,EAAC,qBAAqB;UAC1B,aAAW,EAAA,CAAA,mBAAA,EAAwB,GAAG,CAAC,GAAC,CAAA,CAAA;;qBAQ/B,CAAA,gCAAA,EAAA;AANR,YAAA,UAAU,EAAE,KAAA,CAAA,MAAM,CAAC,GAAG,CAAC,GAAG,CAAA,KAAA,IAAA;AAC3B,YAAA,IAAI,EAAC,QAAQ;AACZ,YAAA,QAAC,EAAA,QAAA,CAAA,QAAA,IAAA,UAAA,KAAA,GAAA,CAAA,GAAA;AACD,YAAA,qBAAA,EAAA,MAAA,KAAA,QAAA,CAAA,MAAA,CAAA,GAAA,EAAA,MAAA,CAAA,CAAA;;6BACD,MAA0D;AAA1D,cAAAG,kBAAA,CAA0D,MAA1D,EAAA,UAA0D,EAAnBC,eAAA,CAAA,GAAG,CAAC,KAAK,CAAA,EAAA,CAAA,YAAA;AACvC,cAAA,CAAA,GAAA,CAAA,IAAA;mDAAA,kBAAA,EAAAA,eAAA,CAAA,GAAA,CAAA,IAAA,CAAA,EAAA,CAAA,YAAA;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -0,0 +1,26 @@
1
+ import __sfc_main from './CnSwitchRowsWidget.vue.js';
2
+ import { registerDashboardWidget } from '../CnWidgetGrid/dashboardWidgetRegistry.js';
3
+
4
+ /**
5
+ * SPDX-FileCopyrightText: 2026 Conduction B.V.
6
+ * SPDX-License-Identifier: EUPL-1.2
7
+ *
8
+ * CnSwitchRowsWidget — self-registers the `switch-rows` widget type (a card of
9
+ * switches, each with a label and a hint, bound to boolean fields of the
10
+ * current object and saved on toggle) into the shared dashboardWidgetRegistry.
11
+ */
12
+
13
+
14
+ registerDashboardWidget('switch-rows', {
15
+ renderer: __sfc_main,
16
+ form: null,
17
+ defaultContent: {
18
+ rows: [],
19
+ },
20
+ displayName: 'Switch rows',
21
+ icon: 'ToggleSwitch',
22
+ surfaces: ['detail-page'],
23
+ });
24
+
25
+ export { __sfc_main as CnSwitchRowsWidget, __sfc_main as default };
26
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":["../../../../src/components/CnSwitchRowsWidget/index.js"],"sourcesContent":["/**\n * SPDX-FileCopyrightText: 2026 Conduction B.V.\n * SPDX-License-Identifier: EUPL-1.2\n *\n * CnSwitchRowsWidget — self-registers the `switch-rows` widget type (a card of\n * switches, each with a label and a hint, bound to boolean fields of the\n * current object and saved on toggle) into the shared dashboardWidgetRegistry.\n */\n\nimport CnSwitchRowsWidget from './CnSwitchRowsWidget.vue'\nimport { registerDashboardWidget } from '../CnWidgetGrid/dashboardWidgetRegistry.js'\n\nregisterDashboardWidget('switch-rows', {\n\trenderer: CnSwitchRowsWidget,\n\tform: null,\n\tdefaultContent: {\n\t\trows: [],\n\t},\n\tdisplayName: 'Switch rows',\n\ticon: 'ToggleSwitch',\n\tsurfaces: ['detail-page'],\n})\n\nexport { CnSwitchRowsWidget }\nexport default CnSwitchRowsWidget\n"],"names":["CnSwitchRowsWidget"],"mappings":";;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAGA;AACA,uBAAuB,CAAC,aAAa,EAAE;AACvC,CAAC,QAAQ,EAAEA,UAAkB;AAC7B,CAAC,IAAI,EAAE,IAAI;AACX,CAAC,cAAc,EAAE;AACjB,EAAE,IAAI,EAAE,EAAE;AACV,EAAE;AACF,CAAC,WAAW,EAAE,aAAa;AAC3B,CAAC,IAAI,EAAE,cAAc;AACrB,CAAC,QAAQ,EAAE,CAAC,aAAa,CAAC;AAC1B,CAAC;;;;"}
@@ -170,12 +170,17 @@ var script = {
170
170
  * names the list; `count` and `countField` win over it. `overflow: true`
171
171
  * lists the tab under "More".
172
172
  *
173
+ * A tab with `widgetIds` can lay them out in a grid instead of one under
174
+ * the other: `columns: 4` gives each a quarter of the row, and
175
+ * `layout: [{ widgetId, gridWidth }]` sets a width (of 12) per widget, as
176
+ * the page grid does. Widgets wrap onto the next row.
177
+ *
173
178
  * `maxVisibleTabs` caps the strip: later tabs go under "More".
174
179
  * `hideEmpty: true` moves a tab whose count is 0 there too.
175
180
  * `moreLabel` names that menu. `variant: "segmented"` draws the strip
176
181
  * as a pill switch (CnTabs' segmented variant); `line` is the default.
177
182
  *
178
- * @type {{ tabs?: Array<{widgetId?: string, widgetIds?: string[], label?: string, icon?: string, count?: number, countField?: string, countFrom?: ('widget'|{register: string, schema: string, filter?: object}), overflow?: boolean}>, ariaLabel?: string, maxVisibleTabs?: number, hideEmpty?: boolean, moreLabel?: string, variant?: ('line'|'segmented') }}
183
+ * @type {{ tabs?: Array<{widgetId?: string, widgetIds?: string[], label?: string, icon?: string, count?: number, countField?: string, countFrom?: ('widget'|{register: string, schema: string, filter?: object}), overflow?: boolean, columns?: number, layout?: Array<{widgetId: string, gridWidth: number}>}>, ariaLabel?: string, maxVisibleTabs?: number, hideEmpty?: boolean, moreLabel?: string, variant?: ('line'|'segmented') }}
179
184
  */
180
185
  content: {
181
186
  type: Object,
@@ -392,6 +397,7 @@ var script = {
392
397
  icon: (tab && tab.icon) || widget?.icon || '',
393
398
  widget,
394
399
  stack: widgets.slice(1),
400
+ grid: this.stackGrid(tab, widgets),
395
401
  count,
396
402
  overflow,
397
403
  pending: visibility === 'pending',
@@ -591,6 +597,46 @@ var script = {
591
597
  },
592
598
 
593
599
  methods: {
600
+ /**
601
+ * The grid a stack lays its widgets out in, as one column span (of 12)
602
+ * per widget in order, or null for the plain vertical stack. A tab says
603
+ * `columns: 4` (every widget spans a quarter of the row) and/or
604
+ * `layout: [{ widgetId, gridWidth }]`, the page grid's width key per
605
+ * widget (of 12; a widget it does not name takes the `columns` share, or
606
+ * the whole row). Widgets wrap onto the next row. Heights follow the
607
+ * content.
608
+ *
609
+ * @param {object|string} tab The `content.tabs[]` entry.
610
+ * @param {Array<object>} widgets The widgets of the stack, in order.
611
+ * @return {number[]|null} The column span of each widget, or null.
612
+ */
613
+ stackGrid(tab, widgets) {
614
+ if (!tab || typeof tab !== 'object' || widgets.length < 2) {
615
+ return null
616
+ }
617
+ const clamp = (value) => Math.min(12, Math.max(1, Math.floor(Number(value))));
618
+ const columns = Number(tab.columns);
619
+ const share = Number.isFinite(columns) && columns >= 1 ? clamp(12 / Math.min(12, Math.floor(columns))) : 12;
620
+ const placed = new Map((Array.isArray(tab.layout) ? tab.layout : [])
621
+ .filter((entry) => entry && typeof entry.widgetId === 'string' && Number.isFinite(Number(entry.gridWidth)))
622
+ .map((entry) => [entry.widgetId, clamp(entry.gridWidth)]));
623
+ if (placed.size === 0 && share === 12) {
624
+ return null
625
+ }
626
+ return widgets.map((widget) => placed.get(widget.id) ?? share)
627
+ },
628
+
629
+ /**
630
+ * The inline column span of one widget of a gridded stack.
631
+ *
632
+ * @param {number[]|null} grid The spans of the stack, or null.
633
+ * @param {number} index The widget's position in the stack.
634
+ * @return {object|undefined} The style, or undefined without a grid.
635
+ */
636
+ spanStyle(grid, index) {
637
+ return grid ? { gridColumn: `span ${grid[index] || 12}` } : undefined
638
+ },
639
+
594
640
  /**
595
641
  * The widget ids a tab names: `widgetIds` (a stack) when it holds at
596
642
  * least one id, else `widgetId`, or the bare string.