@conduction/nextcloud-vue 2.83.0 → 2.85.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 (246) hide show
  1. package/dist/esm/components/CnAdminSettingsShell/CnAdminSettingsShell.vue.js +1 -1
  2. package/dist/esm/components/CnAdminSettingsShell/CnAdminSettingsShell.vue2.js +131 -3
  3. package/dist/esm/components/CnAdminSettingsShell/CnAdminSettingsShell.vue2.js.map +1 -1
  4. package/dist/esm/components/CnAdminSettingsShell/CnAdminSettingsShell.vue3.js +54 -18
  5. package/dist/esm/components/CnAdminSettingsShell/CnAdminSettingsShell.vue3.js.map +1 -1
  6. package/dist/esm/components/CnAuditTrailCard/CnAuditTrailCard.vue.js +1 -1
  7. package/dist/esm/components/CnAuditTrailCard/CnAuditTrailCard.vue2.js +1 -1
  8. package/dist/esm/components/CnAuditTrailCard/CnAuditTrailCard.vue2.js.map +1 -1
  9. package/dist/esm/components/CnAuditTrailCard/CnAuditTrailCard.vue3.js.map +1 -1
  10. package/dist/esm/components/CnBoardView/CnBoardView.vue.js +1 -1
  11. package/dist/esm/components/CnBoardView/CnBoardView.vue2.js +232 -4
  12. package/dist/esm/components/CnBoardView/CnBoardView.vue2.js.map +1 -1
  13. package/dist/esm/components/CnBoardView/CnBoardView.vue3.js +95 -51
  14. package/dist/esm/components/CnBoardView/CnBoardView.vue3.js.map +1 -1
  15. package/dist/esm/components/CnBodySections/CnBodySections.vue.js +1 -1
  16. package/dist/esm/components/CnBodySections/CnBodySections.vue2.js +22 -1
  17. package/dist/esm/components/CnBodySections/CnBodySections.vue2.js.map +1 -1
  18. package/dist/esm/components/CnBodySections/CnBodySections.vue3.js.map +1 -1
  19. package/dist/esm/components/CnCountdownWidget/CnCountdownWidget.vue.js +1 -1
  20. package/dist/esm/components/CnCountdownWidget/CnCountdownWidget.vue2.js +47 -4
  21. package/dist/esm/components/CnCountdownWidget/CnCountdownWidget.vue2.js.map +1 -1
  22. package/dist/esm/components/CnCountdownWidget/CnCountdownWidget.vue3.js.map +1 -1
  23. package/dist/esm/components/CnDashboardGrid/CnDashboardGrid.vue.js +1 -1
  24. package/dist/esm/components/CnDashboardGrid/CnDashboardGrid.vue2.js +239 -3
  25. package/dist/esm/components/CnDashboardGrid/CnDashboardGrid.vue2.js.map +1 -1
  26. package/dist/esm/components/CnDashboardGrid/CnDashboardGrid.vue3.js +5 -5
  27. package/dist/esm/components/CnDashboardGrid/CnDashboardGrid.vue3.js.map +1 -1
  28. package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue.js +1 -1
  29. package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue2.js +50 -0
  30. package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue2.js.map +1 -1
  31. package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue3.js +22 -12
  32. package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue3.js.map +1 -1
  33. package/dist/esm/components/CnDeltaWidget/CnDeltaWidget.vue.js +1 -1
  34. package/dist/esm/components/CnDeltaWidget/CnDeltaWidget.vue2.js +1 -1
  35. package/dist/esm/components/CnDeltaWidget/CnDeltaWidget.vue2.js.map +1 -1
  36. package/dist/esm/components/CnDeltaWidget/CnDeltaWidget.vue3.js.map +1 -1
  37. package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js +226 -8
  38. package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js.map +1 -1
  39. package/dist/esm/components/CnDetailPage/CnDetailPage.vue3.js.map +1 -1
  40. package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue.js +1 -1
  41. package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue2.js +3 -1
  42. package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue2.js.map +1 -1
  43. package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue3.js.map +1 -1
  44. package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue.js +1 -1
  45. package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue2.js +18 -5
  46. package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue2.js.map +1 -1
  47. package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue3.js.map +1 -1
  48. package/dist/esm/components/CnFieldListWidget/CnFieldListWidget.vue.js +1 -1
  49. package/dist/esm/components/CnFieldListWidget/CnFieldListWidget.vue2.js +38 -1
  50. package/dist/esm/components/CnFieldListWidget/CnFieldListWidget.vue2.js.map +1 -1
  51. package/dist/esm/components/CnFieldListWidget/CnFieldListWidget.vue3.js +45 -5
  52. package/dist/esm/components/CnFieldListWidget/CnFieldListWidget.vue3.js.map +1 -1
  53. package/dist/esm/components/CnGaugeWidget/CnGaugeWidget.vue.js +1 -1
  54. package/dist/esm/components/CnGaugeWidget/CnGaugeWidget.vue2.js +1 -1
  55. package/dist/esm/components/CnGaugeWidget/CnGaugeWidget.vue2.js.map +1 -1
  56. package/dist/esm/components/CnGaugeWidget/CnGaugeWidget.vue3.js.map +1 -1
  57. package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js +548 -77
  58. package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js.map +1 -1
  59. package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js +191 -82
  60. package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js.map +1 -1
  61. package/dist/esm/components/CnIndexPage/useSelfFetchList.js +11 -2
  62. package/dist/esm/components/CnIndexPage/useSelfFetchList.js.map +1 -1
  63. package/dist/esm/components/CnInteractionFormWidget/CnInteractionFormWidget.vue2.js +29 -6
  64. package/dist/esm/components/CnInteractionFormWidget/CnInteractionFormWidget.vue2.js.map +1 -1
  65. package/dist/esm/components/CnInteractionFormWidget/CnInteractionFormWidget.vue3.js.map +1 -1
  66. package/dist/esm/components/CnObjectDataWidget/CnObjectDataWidget.vue.js +1 -1
  67. package/dist/esm/components/CnObjectDataWidget/CnObjectDataWidget.vue2.js +126 -2
  68. package/dist/esm/components/CnObjectDataWidget/CnObjectDataWidget.vue2.js.map +1 -1
  69. package/dist/esm/components/CnObjectDataWidget/CnObjectDataWidget.vue3.js +24 -2
  70. package/dist/esm/components/CnObjectDataWidget/CnObjectDataWidget.vue3.js.map +1 -1
  71. package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue.js +1 -1
  72. package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue2.js +106 -3
  73. package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue2.js.map +1 -1
  74. package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue3.js.map +1 -1
  75. package/dist/esm/components/CnRegisterMapping/CnRegisterMapping.vue.js +1 -1
  76. package/dist/esm/components/CnRegisterMapping/CnRegisterMapping.vue2.js +67 -5
  77. package/dist/esm/components/CnRegisterMapping/CnRegisterMapping.vue2.js.map +1 -1
  78. package/dist/esm/components/CnRegisterMapping/CnRegisterMapping.vue3.js +181 -124
  79. package/dist/esm/components/CnRegisterMapping/CnRegisterMapping.vue3.js.map +1 -1
  80. package/dist/esm/components/CnReportsPage/CnReportsPage.vue.js +1 -1
  81. package/dist/esm/components/CnReportsPage/CnReportsPage.vue2.js +135 -2
  82. package/dist/esm/components/CnReportsPage/CnReportsPage.vue2.js.map +1 -1
  83. package/dist/esm/components/CnReportsPage/CnReportsPage.vue3.js +95 -43
  84. package/dist/esm/components/CnReportsPage/CnReportsPage.vue3.js.map +1 -1
  85. package/dist/esm/components/CnSettingsPage/CnSettingsPage.vue.js +1 -1
  86. package/dist/esm/components/CnSettingsPage/CnSettingsPage.vue2.js +5 -1
  87. package/dist/esm/components/CnSettingsPage/CnSettingsPage.vue2.js.map +1 -1
  88. package/dist/esm/components/CnSettingsPage/CnSettingsPage.vue3.js.map +1 -1
  89. package/dist/esm/components/CnStagesWidget/CnStagesWidget.vue.js +1 -1
  90. package/dist/esm/components/CnStagesWidget/CnStagesWidget.vue2.js +72 -5
  91. package/dist/esm/components/CnStagesWidget/CnStagesWidget.vue2.js.map +1 -1
  92. package/dist/esm/components/CnStagesWidget/CnStagesWidget.vue3.js +33 -8
  93. package/dist/esm/components/CnStagesWidget/CnStagesWidget.vue3.js.map +1 -1
  94. package/dist/esm/components/CnStatWidget/CnStatWidget.vue.js +1 -1
  95. package/dist/esm/components/CnStatWidget/CnStatWidget.vue2.js +135 -11
  96. package/dist/esm/components/CnStatWidget/CnStatWidget.vue2.js.map +1 -1
  97. package/dist/esm/components/CnStatWidget/CnStatWidget.vue3.js +6 -2
  98. package/dist/esm/components/CnStatWidget/CnStatWidget.vue3.js.map +1 -1
  99. package/dist/esm/components/CnStatsBlockWidget/CnStatsBlockWidget.vue.js +1 -1
  100. package/dist/esm/components/CnStatsBlockWidget/CnStatsBlockWidget.vue2.js +17 -2
  101. package/dist/esm/components/CnStatsBlockWidget/CnStatsBlockWidget.vue2.js.map +1 -1
  102. package/dist/esm/components/CnStatsBlockWidget/CnStatsBlockWidget.vue3.js +1 -1
  103. package/dist/esm/components/CnStatsBlockWidget/CnStatsBlockWidget.vue3.js.map +1 -1
  104. package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue.js +1 -1
  105. package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue2.js +39 -6
  106. package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue2.js.map +1 -1
  107. package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue3.js.map +1 -1
  108. package/dist/esm/components/CnToggleTableWidget/CnToggleTableWidget.vue.js +1 -1
  109. package/dist/esm/components/CnToggleTableWidget/CnToggleTableWidget.vue2.js +140 -7
  110. package/dist/esm/components/CnToggleTableWidget/CnToggleTableWidget.vue2.js.map +1 -1
  111. package/dist/esm/components/CnToggleTableWidget/CnToggleTableWidget.vue3.js.map +1 -1
  112. package/dist/esm/components/CnVersionInfoCard/CnVersionInfoCard.vue.js +1 -1
  113. package/dist/esm/components/CnVersionInfoCard/CnVersionInfoCard.vue2.js +37 -9
  114. package/dist/esm/components/CnVersionInfoCard/CnVersionInfoCard.vue2.js.map +1 -1
  115. package/dist/esm/components/CnVersionInfoCard/CnVersionInfoCard.vue3.js +6 -5
  116. package/dist/esm/components/CnVersionInfoCard/CnVersionInfoCard.vue3.js.map +1 -1
  117. package/dist/esm/components/CnWalkthrough/CnWalkthrough.vue.js +1 -1
  118. package/dist/esm/components/CnWalkthrough/CnWalkthrough.vue2.js +16 -0
  119. package/dist/esm/components/CnWalkthrough/CnWalkthrough.vue2.js.map +1 -1
  120. package/dist/esm/components/CnWalkthrough/CnWalkthrough.vue3.js.map +1 -1
  121. package/dist/esm/components/CnWeekStripWidget/CnWeekStripWidget.vue.js +1 -1
  122. package/dist/esm/components/CnWeekStripWidget/CnWeekStripWidget.vue2.js +2 -1
  123. package/dist/esm/components/CnWeekStripWidget/CnWeekStripWidget.vue2.js.map +1 -1
  124. package/dist/esm/components/CnWeekStripWidget/CnWeekStripWidget.vue3.js.map +1 -1
  125. package/dist/esm/components/CnWidgetCardGrid/CnWidgetCardGrid.vue2.js +53 -1
  126. package/dist/esm/components/CnWidgetCardGrid/CnWidgetCardGrid.vue2.js.map +1 -1
  127. package/dist/esm/components/CnWidgetCardGrid/CnWidgetCardGrid.vue3.js +3 -2
  128. package/dist/esm/components/CnWidgetCardGrid/CnWidgetCardGrid.vue3.js.map +1 -1
  129. package/dist/esm/components/CnWidgetObjectTable/CnWidgetObjectTable.vue.js +1 -1
  130. package/dist/esm/components/CnWidgetObjectTable/CnWidgetObjectTable.vue2.js +135 -0
  131. package/dist/esm/components/CnWidgetObjectTable/CnWidgetObjectTable.vue2.js.map +1 -1
  132. package/dist/esm/components/CnWidgetObjectTable/CnWidgetObjectTable.vue3.js.map +1 -1
  133. package/dist/esm/components/CnWidgetWrapper/CnWidgetWrapper.vue.js +1 -1
  134. package/dist/esm/components/CnWidgetWrapper/CnWidgetWrapper.vue2.js +19 -0
  135. package/dist/esm/components/CnWidgetWrapper/CnWidgetWrapper.vue2.js.map +1 -1
  136. package/dist/esm/components/CnWidgetWrapper/CnWidgetWrapper.vue3.js +37 -19
  137. package/dist/esm/components/CnWidgetWrapper/CnWidgetWrapper.vue3.js.map +1 -1
  138. package/dist/esm/composables/useListView.js +21 -0
  139. package/dist/esm/composables/useListView.js.map +1 -1
  140. package/dist/esm/dialogs/CnTransitionInputDialog.vue.js +1 -1
  141. package/dist/esm/dialogs/CnTransitionInputDialog.vue2.js +68 -6
  142. package/dist/esm/dialogs/CnTransitionInputDialog.vue2.js.map +1 -1
  143. package/dist/esm/dialogs/CnTransitionInputDialog.vue3.js +133 -105
  144. package/dist/esm/dialogs/CnTransitionInputDialog.vue3.js.map +1 -1
  145. package/dist/esm/index.js +1 -0
  146. package/dist/esm/index.js.map +1 -1
  147. package/dist/esm/l10n/en.json.js +38 -1
  148. package/dist/esm/l10n/en.json.js.map +1 -1
  149. package/dist/esm/l10n/nl.json.js +78 -1
  150. package/dist/esm/l10n/nl.json.js.map +1 -1
  151. package/dist/esm/library-style.js +1 -1
  152. package/dist/esm/nextcloud-vue.css +1030 -533
  153. package/dist/esm/store/useObjectStore.js +16 -2
  154. package/dist/esm/store/useObjectStore.js.map +1 -1
  155. package/dist/esm/utils/boardColumns.js +8 -1
  156. package/dist/esm/utils/boardColumns.js.map +1 -1
  157. package/dist/esm/utils/boardReferenceColumns.js +278 -0
  158. package/dist/esm/utils/boardReferenceColumns.js.map +1 -0
  159. package/dist/esm/utils/buildManifest.js +41 -4
  160. package/dist/esm/utils/buildManifest.js.map +1 -1
  161. package/dist/esm/utils/detailWidgetVisibility.js +149 -0
  162. package/dist/esm/utils/detailWidgetVisibility.js.map +1 -0
  163. package/dist/esm/utils/formatMetric.js +39 -3
  164. package/dist/esm/utils/formatMetric.js.map +1 -1
  165. package/dist/esm/utils/gridStack.js +40 -1
  166. package/dist/esm/utils/gridStack.js.map +1 -1
  167. package/dist/esm/utils/humaniseKey.js +41 -0
  168. package/dist/esm/utils/humaniseKey.js.map +1 -0
  169. package/dist/esm/utils/notificationRuleLabel.js +6 -23
  170. package/dist/esm/utils/notificationRuleLabel.js.map +1 -1
  171. package/dist/esm/utils/resolveManifestTokens.js +1 -0
  172. package/dist/esm/utils/resolveManifestTokens.js.map +1 -1
  173. package/dist/esm/utils/sentinelTokens.js +9 -0
  174. package/dist/esm/utils/sentinelTokens.js.map +1 -1
  175. package/dist/esm/utils/validateManifestV2.compiled.js +3 -3
  176. package/dist/esm/utils/validateManifestV2.compiled.js.map +1 -1
  177. package/dist/esm/utils/widgetDispatch.js +8 -2
  178. package/dist/esm/utils/widgetDispatch.js.map +1 -1
  179. package/dist/nextcloud-vue.cjs.js +17159 -13422
  180. package/dist/nextcloud-vue.cjs.js.map +2 -2
  181. package/dist/nextcloud-vue.css +1030 -533
  182. package/l10n/en.json +38 -1
  183. package/l10n/nl.json +78 -1
  184. package/package.json +1 -1
  185. package/src/components/CnAdminSettingsShell/CnAdminSettingsShell.vue +160 -8
  186. package/src/components/CnAuditTrailCard/CnAuditTrailCard.vue +1 -1
  187. package/src/components/CnBoardView/CnBoardView.vue +262 -6
  188. package/src/components/CnBodySections/CnBodySections.vue +22 -1
  189. package/src/components/CnCountdownWidget/CnCountdownWidget.vue +47 -4
  190. package/src/components/CnDashboardGrid/CnDashboardGrid.vue +244 -8
  191. package/src/components/CnDashboardPage/CnDashboardPage.vue +62 -2
  192. package/src/components/CnDeltaWidget/CnDeltaWidget.vue +1 -1
  193. package/src/components/CnDetailPage/CnDetailPage.md +3 -1
  194. package/src/components/CnDetailPage/CnDetailPage.vue +226 -8
  195. package/src/components/CnDetailWidgetHost/CnDetailWidgetHost.vue +3 -1
  196. package/src/components/CnFactsWidget/CnFactsWidget.vue +18 -5
  197. package/src/components/CnFieldListWidget/CnFieldListWidget.vue +63 -1
  198. package/src/components/CnGaugeWidget/CnGaugeWidget.vue +1 -1
  199. package/src/components/CnIndexPage/CnIndexPage.vue +586 -25
  200. package/src/components/CnIndexPage/useSelfFetchList.js +10 -1
  201. package/src/components/CnInteractionFormWidget/CnInteractionFormWidget.vue +29 -6
  202. package/src/components/CnObjectDataWidget/CnObjectDataWidget.md +1 -1
  203. package/src/components/CnObjectDataWidget/CnObjectDataWidget.vue +154 -5
  204. package/src/components/CnRecordListWidget/CnRecordListWidget.vue +106 -3
  205. package/src/components/CnRegisterMapping/CnRegisterMapping.md +5 -0
  206. package/src/components/CnRegisterMapping/CnRegisterMapping.vue +231 -96
  207. package/src/components/CnReportsPage/CnReportsPage.vue +179 -1
  208. package/src/components/CnSettingsPage/CnSettingsPage.vue +5 -1
  209. package/src/components/CnStagesWidget/CnStagesWidget.vue +103 -6
  210. package/src/components/CnStatWidget/CnStatWidget.vue +137 -12
  211. package/src/components/CnStatsBlockWidget/CnStatsBlockWidget.vue +34 -3
  212. package/src/components/CnTabsWidget/CnTabsWidget.vue +39 -6
  213. package/src/components/CnToggleTableWidget/CnToggleTableWidget.vue +140 -7
  214. package/src/components/CnVersionInfoCard/CnVersionInfoCard.md +2 -1
  215. package/src/components/CnVersionInfoCard/CnVersionInfoCard.vue +42 -13
  216. package/src/components/CnWalkthrough/CnWalkthrough.vue +16 -0
  217. package/src/components/CnWeekStripWidget/CnWeekStripWidget.vue +2 -1
  218. package/src/components/CnWidgetCardGrid/CnWidgetCardGrid.vue +55 -2
  219. package/src/components/CnWidgetObjectTable/CnWidgetObjectTable.vue +135 -0
  220. package/src/components/CnWidgetWrapper/CnWidgetWrapper.md +10 -0
  221. package/src/components/CnWidgetWrapper/CnWidgetWrapper.vue +44 -1
  222. package/src/composables/useListView.js +21 -0
  223. package/src/css/board.css +65 -4
  224. package/src/css/dialog.css +4 -2
  225. package/src/css/form-field.css +14 -0
  226. package/src/css/form-widget.css +11 -0
  227. package/src/css/index-page.css +49 -0
  228. package/src/css/kpi-card.css +13 -0
  229. package/src/css/look-board-reports.css +58 -0
  230. package/src/css/look-board.css +108 -7
  231. package/src/dialogs/CnTransitionInputDialog.vue +87 -7
  232. package/src/index.js +2 -0
  233. package/src/schemas/app-manifest-v2.schema.json +137 -6
  234. package/src/store/useObjectStore.js +16 -2
  235. package/src/utils/boardColumns.js +8 -1
  236. package/src/utils/boardReferenceColumns.js +274 -0
  237. package/src/utils/buildManifest.js +40 -3
  238. package/src/utils/detailWidgetVisibility.js +145 -0
  239. package/src/utils/formatMetric.js +38 -2
  240. package/src/utils/gridStack.js +39 -0
  241. package/src/utils/humaniseKey.js +38 -0
  242. package/src/utils/notificationRuleLabel.js +5 -23
  243. package/src/utils/resolveManifestTokens.js +1 -0
  244. package/src/utils/sentinelTokens.js +9 -0
  245. package/src/utils/validateManifestV2.compiled.js +3 -3
  246. package/src/utils/widgetDispatch.js +8 -2
@@ -46,6 +46,12 @@ var script = {
46
46
  * draws the screens' board anatomy (screens-kanban-parity).
47
47
  */
48
48
  cnLook: { default: 'nextcloud' },
49
+ /**
50
+ * The app's cell-formatter registry, provided by CnAppRoot. A card
51
+ * role named in `cardRoles.formatters` shows its value through it, as
52
+ * the table's cells do (screens-board-reference-columns).
53
+ */
54
+ cnFormatters: { default: () => ({}) },
49
55
  },
50
56
 
51
57
  props: {
@@ -186,9 +192,72 @@ var script = {
186
192
  type: Number,
187
193
  default: 0,
188
194
  },
195
+
196
+ /**
197
+ * The column a row belongs in, for a status whose raw value is not
198
+ * the column key: a reference whose rows are merged by name
199
+ * (screens-board-reference-columns). Absent, the row's `statusField`
200
+ * value is the key.
201
+ *
202
+ * @type {((row: object) => string)|null}
203
+ * @spec openspec/changes/screens-board-reference-columns/specs/board-view/spec.md#requirement-columns-can-be-the-rows-a-field-references
204
+ */
205
+ columnKeyOf: {
206
+ type: Function,
207
+ default: null,
208
+ },
209
+
210
+ /**
211
+ * Wrap the columns onto more rows, as many to a row as fit at 240px,
212
+ * instead of one row that scrolls sideways (manifest
213
+ * `config.board.wrap`). For a board with more stages than fit.
214
+ *
215
+ * @spec openspec/changes/screens-board-reference-columns/specs/board-view/spec.md#requirement-a-wide-board-can-wrap-its-columns
216
+ */
217
+ wrapColumns: {
218
+ type: Boolean,
219
+ default: false,
220
+ },
221
+
222
+ /**
223
+ * Offer a checkbox on every card, so cards can be selected for the
224
+ * list's bulk actions (the same selection the table holds).
225
+ *
226
+ * @spec openspec/changes/screens-board-reference-columns/specs/board-view/spec.md#requirement-cards-can-be-selected-for-bulk-actions
227
+ */
228
+ selectable: {
229
+ type: Boolean,
230
+ default: false,
231
+ },
232
+
233
+ /**
234
+ * The selected cards, by row key.
235
+ *
236
+ * @type {Array<string|number>}
237
+ */
238
+ selectedIds: {
239
+ type: Array,
240
+ default: () => [],
241
+ },
242
+
243
+ /**
244
+ * The columns one card may move to, asked when its menu opens or its
245
+ * drag starts: `(card) => Promise<Array<string>|null>`, column keys,
246
+ * `null` for every column. A column the card cannot reach is greyed
247
+ * during the drag and marked "not allowed" in the menu, and a drop on
248
+ * it is refused without asking the host. Absent, every column is
249
+ * offered and the host's move decides.
250
+ *
251
+ * @type {((card: object) => Promise<Array<string>|null>)|null}
252
+ * @spec openspec/changes/screens-board-reference-columns/specs/board-view/spec.md#requirement-the-board-shows-where-a-card-can-go
253
+ */
254
+ allowedMoves: {
255
+ type: Function,
256
+ default: null,
257
+ },
189
258
  },
190
259
 
191
- emits: ['card-click', 'card-aux-click', 'moved', 'refused', 'stale', 'load-more'],
260
+ emits: ['card-click', 'card-aux-click', 'moved', 'refused', 'stale', 'load-more', 'select'],
192
261
 
193
262
  data() {
194
263
  return {
@@ -204,6 +273,10 @@ var script = {
204
273
  expanded: [],
205
274
  /** The card whose menu is open (board look), by card key. */
206
275
  openMenuKey: null,
276
+ /** Column keys each card may move to (`allowedMoves`), by card key; absent = not asked yet. */
277
+ allowedByCard: {},
278
+ /** The column keys the dragged card may reach, or null for all. */
279
+ dragAllowed: null,
207
280
  }
208
281
  },
209
282
 
@@ -221,6 +294,7 @@ var script = {
221
294
  statusField: this.statusField,
222
295
  offBoardLabel: translate('nextcloud-vue', 'Elsewhere'),
223
296
  colorField: this.colorField,
297
+ keyOf: this.columnKeyOf,
224
298
  })
225
299
  },
226
300
 
@@ -248,9 +322,20 @@ var script = {
248
322
  due: (given && given.due) || '',
249
323
  owner: (given && given.owner) || '',
250
324
  pillColors: (given && given.pillColors) || {},
325
+ formatters: (given && given.formatters && typeof given.formatters === 'object') ? given.formatters : {},
251
326
  }
252
327
  },
253
328
 
329
+ /** @return {string} The note on a menu target the card cannot reach. */
330
+ notAllowedLabel() {
331
+ return translate('nextcloud-vue', 'not allowed')
332
+ },
333
+
334
+ /** @return {Array<string>} The selected row keys as strings. */
335
+ selectedKeys() {
336
+ return (Array.isArray(this.selectedIds) ? this.selectedIds : []).map(String)
337
+ },
338
+
254
339
  /** @return {string} The Open in new tab menu item. */
255
340
  openInNewTabLabel() {
256
341
  return translate('nextcloud-vue', 'Open in new tab')
@@ -309,6 +394,97 @@ var script = {
309
394
 
310
395
  preventMiddleClickAutoscroll,
311
396
 
397
+ /**
398
+ * Whether a card is selected.
399
+ *
400
+ * @param {object} card The card.
401
+ * @return {boolean} True when selected.
402
+ */
403
+ isSelected(card) {
404
+ return this.selectedKeys.includes(this.cardKey(card))
405
+ },
406
+
407
+ /**
408
+ * The checkbox's accessible name.
409
+ *
410
+ * @param {object} card The card.
411
+ * @return {string} "Select <name>".
412
+ */
413
+ selectLabel(card) {
414
+ const name = this.roleText(card, this.roles.title) || this.cardKey(card);
415
+ return translate('nextcloud-vue', 'Select {name}', { name })
416
+ },
417
+
418
+ /**
419
+ * Select a card, or unselect it.
420
+ *
421
+ * @param {object} card The card.
422
+ * @return {void}
423
+ * @spec openspec/changes/screens-board-reference-columns/specs/board-view/spec.md#requirement-cards-can-be-selected-for-bulk-actions
424
+ */
425
+ toggleSelected(card) {
426
+ const key = this.cardKey(card);
427
+ const next = this.isSelected(card)
428
+ ? this.selectedIds.filter((id) => String(id) !== key)
429
+ : [...this.selectedIds, card?.[this.rowKey]];
430
+ /**
431
+ * @event select Emitted when a card's checkbox changes. Payload: the selected row keys.
432
+ */
433
+ this.$emit('select', next);
434
+ },
435
+
436
+ /**
437
+ * Ask the host where one card may go (`allowedMoves`), once per card.
438
+ *
439
+ * @param {object} card The card.
440
+ * @return {Promise<Array<string>|null>} The column keys, or null for all.
441
+ * @spec openspec/changes/screens-board-reference-columns/specs/board-view/spec.md#requirement-the-board-shows-where-a-card-can-go
442
+ */
443
+ async loadAllowed(card) {
444
+ if (typeof this.allowedMoves !== 'function') {
445
+ return null
446
+ }
447
+ const key = this.cardKey(card);
448
+ if (Object.hasOwn(this.allowedByCard, key)) {
449
+ return this.allowedByCard[key]
450
+ }
451
+ let allowed;
452
+ try {
453
+ const answer = await this.allowedMoves(card);
454
+ allowed = Array.isArray(answer) ? answer.map(String) : null;
455
+ } catch {
456
+ // Unknown is not "nowhere": the host's move stays the authority.
457
+ allowed = null;
458
+ }
459
+ this.allowedByCard = { ...this.allowedByCard, [key]: allowed };
460
+ return allowed
461
+ },
462
+
463
+ /**
464
+ * Whether a card may move to a column, as far as the board knows.
465
+ *
466
+ * @param {object} card The card.
467
+ * @param {object} target The column.
468
+ * @return {boolean} False only when the host said it cannot.
469
+ */
470
+ isMoveAllowed(card, target) {
471
+ const allowed = this.allowedByCard[this.cardKey(card)];
472
+ return !Array.isArray(allowed) || allowed.includes(String(target.key))
473
+ },
474
+
475
+ /**
476
+ * Whether a column is out of reach for the card being dragged.
477
+ *
478
+ * @param {object} column The column.
479
+ * @return {boolean} True while a drag is on and the card cannot go there.
480
+ */
481
+ isUnreachable(column) {
482
+ return this.dragging !== null
483
+ && Array.isArray(this.dragAllowed)
484
+ && column.key !== this.dragging.fromKey
485
+ && !this.dragAllowed.includes(String(column.key))
486
+ },
487
+
312
488
  /**
313
489
  * A card's due state under `dueRule`.
314
490
  *
@@ -350,11 +526,35 @@ var script = {
350
526
  const fields = Array.isArray(role) ? role : [role];
351
527
  return fields
352
528
  .filter((field) => typeof field === 'string' && field !== '')
353
- .map((field) => this.textOf(readPath(card, field)))
529
+ .map((field) => this.fieldText(card, field))
354
530
  .filter((value) => value !== '')
355
531
  .join(' \u00b7 ')
356
532
  },
357
533
 
534
+ /**
535
+ * One card field as text: through the formatter `cardRoles.formatters`
536
+ * names for it, else the value itself.
537
+ *
538
+ * @param {object} card The card's row.
539
+ * @param {string} field The dot-path.
540
+ * @return {string} The text.
541
+ * @spec openspec/changes/screens-board-reference-columns/specs/board-view/spec.md#requirement-a-card-field-can-show-through-a-formatter
542
+ */
543
+ fieldText(card, field) {
544
+ const raw = readPath(card, field);
545
+ const id = this.roles.formatters[field];
546
+ const fn = id && this.cnFormatters ? this.cnFormatters[id] : null;
547
+ if (typeof fn === 'function') {
548
+ try {
549
+ const out = fn(raw, card, null);
550
+ return out === null || out === undefined ? '' : String(out).trim()
551
+ } catch {
552
+ return this.textOf(raw)
553
+ }
554
+ }
555
+ return this.textOf(raw)
556
+ },
557
+
358
558
  /**
359
559
  * A value as text: a string or number as is, an object by its label.
360
560
  *
@@ -379,7 +579,7 @@ var script = {
379
579
  * @return {string} A CnStatusBadge variant.
380
580
  */
381
581
  pillVariant(card) {
382
- const raw = this.textOf(readPath(card, this.roles.pill));
582
+ const raw = this.fieldText(card, this.roles.pill);
383
583
  const variant = this.roles.pillColors[raw] ?? this.roles.pillColors[raw.toLowerCase()];
384
584
  return isBadgeVariant(variant) ? variant : 'default'
385
585
  },
@@ -419,7 +619,7 @@ var script = {
419
619
  * @return {string} The name, '' when there is none.
420
620
  */
421
621
  ownerName(card) {
422
- return this.roles.owner === '' ? '' : this.textOf(readPath(card, this.roles.owner))
622
+ return this.roles.owner === '' ? '' : this.fieldText(card, this.roles.owner)
423
623
  },
424
624
 
425
625
  /**
@@ -571,6 +771,7 @@ var script = {
571
771
  const key = this.cardKey(card);
572
772
  this.openMenuKey = this.openMenuKey === key ? null : key;
573
773
  if (this.openMenuKey !== null) {
774
+ this.loadAllowed(card);
574
775
  this.focusMenuItem(card, 0);
575
776
  }
576
777
  },
@@ -659,6 +860,7 @@ var script = {
659
860
  event.preventDefault();
660
861
  if (!this.isMenuOpen(card)) {
661
862
  this.openMenuKey = this.cardKey(card);
863
+ this.loadAllowed(card);
662
864
  this.focusMenuItem(card, 0);
663
865
  }
664
866
  }
@@ -805,8 +1007,27 @@ var script = {
805
1007
  */
806
1008
  onDragStart(card, column, event) {
807
1009
  this.dragging = { card, fromKey: column.key };
1010
+ this.dragAllowed = null;
808
1011
  // Firefox drops a drag that carries no data.
809
1012
  event?.dataTransfer?.setData?.('text/plain', this.cardKey(card));
1013
+ if (typeof this.allowedMoves === 'function') {
1014
+ this.loadAllowed(card).then((allowed) => {
1015
+ if (this.dragging && this.dragging.card === card) {
1016
+ this.dragAllowed = allowed;
1017
+ }
1018
+ });
1019
+ }
1020
+ },
1021
+
1022
+ /**
1023
+ * The drag ended (dropped anywhere, or cancelled): no column stays
1024
+ * greyed. A drop on a column has already run by now.
1025
+ *
1026
+ * @return {void}
1027
+ */
1028
+ onDragEnd() {
1029
+ this.dragging = null;
1030
+ this.dragAllowed = null;
810
1031
  },
811
1032
 
812
1033
  /**
@@ -821,6 +1042,13 @@ var script = {
821
1042
  }
822
1043
  const { card, fromKey } = this.dragging;
823
1044
  this.dragging = null;
1045
+ this.dragAllowed = null;
1046
+ if (column.key !== fromKey && !this.isMoveAllowed(card, column)) {
1047
+ const name = this.roleText(card, this.roles.title) || this.cardKey(card);
1048
+ this.refusal = translate('nextcloud-vue', '{name} cannot move to {column}.', { name, column: column.label });
1049
+ this.$emit('refused', { card, message: this.refusal });
1050
+ return
1051
+ }
824
1052
  await this.move(card, fromKey, column.key);
825
1053
  },
826
1054