@conduction/nextcloud-vue 2.79.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 (390) hide show
  1. package/dist/esm/components/CnActionButtons/CnActionButtons.vue2.js.map +1 -1
  2. package/dist/esm/components/CnActionButtons/CnActionButtons.vue3.js +3 -1
  3. package/dist/esm/components/CnActionButtons/CnActionButtons.vue3.js.map +1 -1
  4. package/dist/esm/components/CnActionsBar/CnActionsBar.vue2.js +32 -3
  5. package/dist/esm/components/CnActionsBar/CnActionsBar.vue2.js.map +1 -1
  6. package/dist/esm/components/CnActionsBar/CnActionsBar.vue3.js +13 -11
  7. package/dist/esm/components/CnActionsBar/CnActionsBar.vue3.js.map +1 -1
  8. package/dist/esm/components/CnAppRoot/CnAppRoot.vue2.js +80 -4
  9. package/dist/esm/components/CnAppRoot/CnAppRoot.vue2.js.map +1 -1
  10. package/dist/esm/components/CnAppRoot/CnAppRoot.vue3.js +95 -91
  11. package/dist/esm/components/CnAppRoot/CnAppRoot.vue3.js.map +1 -1
  12. package/dist/esm/components/CnBannerWidget/CnBannerWidget.vue2.js +179 -13
  13. package/dist/esm/components/CnBannerWidget/CnBannerWidget.vue2.js.map +1 -1
  14. package/dist/esm/components/CnBannerWidget/CnBannerWidget.vue3.js +52 -16
  15. package/dist/esm/components/CnBannerWidget/CnBannerWidget.vue3.js.map +1 -1
  16. package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue2.js +96 -4
  17. package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue2.js.map +1 -1
  18. package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue3.js +158 -110
  19. package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue3.js.map +1 -1
  20. package/dist/esm/components/CnChipsFieldWidget/CnChipsFieldWidget.vue.js +10 -0
  21. package/dist/esm/components/CnChipsFieldWidget/CnChipsFieldWidget.vue.js.map +1 -0
  22. package/dist/esm/components/CnChipsFieldWidget/CnChipsFieldWidget.vue2.js +252 -0
  23. package/dist/esm/components/CnChipsFieldWidget/CnChipsFieldWidget.vue2.js.map +1 -0
  24. package/dist/esm/components/CnChipsFieldWidget/CnChipsFieldWidget.vue3.js +140 -0
  25. package/dist/esm/components/CnChipsFieldWidget/CnChipsFieldWidget.vue3.js.map +1 -0
  26. package/dist/esm/components/CnChipsFieldWidget/index.js +26 -0
  27. package/dist/esm/components/CnChipsFieldWidget/index.js.map +1 -0
  28. package/dist/esm/components/CnChoicePickerWidget/CnChoicePickerWidget.vue.js +10 -0
  29. package/dist/esm/components/CnChoicePickerWidget/CnChoicePickerWidget.vue.js.map +1 -0
  30. package/dist/esm/components/CnChoicePickerWidget/CnChoicePickerWidget.vue2.js +354 -0
  31. package/dist/esm/components/CnChoicePickerWidget/CnChoicePickerWidget.vue2.js.map +1 -0
  32. package/dist/esm/components/CnChoicePickerWidget/CnChoicePickerWidget.vue3.js +172 -0
  33. package/dist/esm/components/CnChoicePickerWidget/CnChoicePickerWidget.vue3.js.map +1 -0
  34. package/dist/esm/components/CnChoicePickerWidget/index.js +27 -0
  35. package/dist/esm/components/CnChoicePickerWidget/index.js.map +1 -0
  36. package/dist/esm/components/CnConversationThread/CnConversationWidget.vue2.js +1 -1
  37. package/dist/esm/components/CnConversationThread/CnConversationWidget.vue2.js.map +1 -1
  38. package/dist/esm/components/CnConversationThread/CnConversationWidget.vue3.js.map +1 -1
  39. package/dist/esm/components/CnDashboardGrid/CnDashboardGrid.vue2.js +2 -2
  40. package/dist/esm/components/CnDashboardGrid/CnDashboardGrid.vue2.js.map +1 -1
  41. package/dist/esm/components/CnDashboardGrid/CnDashboardGrid.vue3.js.map +1 -1
  42. package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue2.js +65 -5
  43. package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue2.js.map +1 -1
  44. package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue3.js +2 -1
  45. package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue3.js.map +1 -1
  46. package/dist/esm/components/CnDataTable/CnDataTable.vue2.js +19 -11
  47. package/dist/esm/components/CnDataTable/CnDataTable.vue2.js.map +1 -1
  48. package/dist/esm/components/CnDataTable/CnDataTable.vue3.js +4 -2
  49. package/dist/esm/components/CnDataTable/CnDataTable.vue3.js.map +1 -1
  50. package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js +134 -4
  51. package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js.map +1 -1
  52. package/dist/esm/components/CnDetailPage/CnDetailPage.vue3.js +21 -4
  53. package/dist/esm/components/CnDetailPage/CnDetailPage.vue3.js.map +1 -1
  54. package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue2.js +24 -0
  55. package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue2.js.map +1 -1
  56. package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue3.js +43 -4
  57. package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue3.js.map +1 -1
  58. package/dist/esm/components/CnDocumentReviewList/CnDocumentReviewWidget.vue2.js +1 -1
  59. package/dist/esm/components/CnDocumentReviewList/CnDocumentReviewWidget.vue2.js.map +1 -1
  60. package/dist/esm/components/CnDocumentReviewList/CnDocumentReviewWidget.vue3.js.map +1 -1
  61. package/dist/esm/components/CnFacetSidebar/CnFacetSidebar.vue2.js +7 -7
  62. package/dist/esm/components/CnFacetSidebar/CnFacetSidebar.vue2.js.map +1 -1
  63. package/dist/esm/components/CnFacetSidebar/CnFacetSidebar.vue3.js.map +1 -1
  64. package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue.js +11 -0
  65. package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue.js.map +1 -0
  66. package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue2.js +867 -0
  67. package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue2.js.map +1 -0
  68. package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue3.js +238 -0
  69. package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue3.js.map +1 -0
  70. package/dist/esm/components/CnFactsWidget/index.js +30 -0
  71. package/dist/esm/components/CnFactsWidget/index.js.map +1 -0
  72. package/dist/esm/components/CnFieldListWidget/CnFieldListWidget.vue.js +10 -0
  73. package/dist/esm/components/CnFieldListWidget/CnFieldListWidget.vue.js.map +1 -0
  74. package/dist/esm/components/CnFieldListWidget/CnFieldListWidget.vue2.js +626 -0
  75. package/dist/esm/components/CnFieldListWidget/CnFieldListWidget.vue2.js.map +1 -0
  76. package/dist/esm/components/CnFieldListWidget/CnFieldListWidget.vue3.js +396 -0
  77. package/dist/esm/components/CnFieldListWidget/CnFieldListWidget.vue3.js.map +1 -0
  78. package/dist/esm/components/CnFieldListWidget/index.js +29 -0
  79. package/dist/esm/components/CnFieldListWidget/index.js.map +1 -0
  80. package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue2.js +302 -4
  81. package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue2.js.map +1 -1
  82. package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue3.js +417 -244
  83. package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue3.js.map +1 -1
  84. package/dist/esm/components/CnFilesBrowser/filesBrowser.js +101 -1
  85. package/dist/esm/components/CnFilesBrowser/filesBrowser.js.map +1 -1
  86. package/dist/esm/components/CnFilesBrowser/filesBrowserColumns.js +141 -1
  87. package/dist/esm/components/CnFilesBrowser/filesBrowserColumns.js.map +1 -1
  88. package/dist/esm/components/CnFormDialog/CnFormDialog.vue2.js +65 -17
  89. package/dist/esm/components/CnFormDialog/CnFormDialog.vue2.js.map +1 -1
  90. package/dist/esm/components/CnFormDialog/CnFormDialog.vue3.js +4 -4
  91. package/dist/esm/components/CnFormDialog/CnFormDialog.vue3.js.map +1 -1
  92. package/dist/esm/components/CnFormPage/CnFormPage.vue2.js +78 -3
  93. package/dist/esm/components/CnFormPage/CnFormPage.vue2.js.map +1 -1
  94. package/dist/esm/components/CnFormPage/CnFormPage.vue3.js +74 -49
  95. package/dist/esm/components/CnFormPage/CnFormPage.vue3.js.map +1 -1
  96. package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js +333 -73
  97. package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js.map +1 -1
  98. package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js +79 -17
  99. package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js.map +1 -1
  100. package/dist/esm/components/CnIndexPage/CnIndexPageWidgets.vue.js +10 -0
  101. package/dist/esm/components/CnIndexPage/CnIndexPageWidgets.vue.js.map +1 -0
  102. package/dist/esm/components/CnIndexPage/CnIndexPageWidgets.vue2.js +99 -0
  103. package/dist/esm/components/CnIndexPage/CnIndexPageWidgets.vue2.js.map +1 -0
  104. package/dist/esm/components/CnIndexPage/CnIndexPageWidgets.vue3.js +48 -0
  105. package/dist/esm/components/CnIndexPage/CnIndexPageWidgets.vue3.js.map +1 -0
  106. package/dist/esm/components/CnIndexSidebar/CnIndexSidebar.vue2.js +7 -7
  107. package/dist/esm/components/CnIndexSidebar/CnIndexSidebar.vue2.js.map +1 -1
  108. package/dist/esm/components/CnIndexSidebar/CnIndexSidebar.vue3.js.map +1 -1
  109. package/dist/esm/components/CnNextStepCard/CnNextStepWidget.vue2.js +1 -1
  110. package/dist/esm/components/CnNextStepCard/CnNextStepWidget.vue2.js.map +1 -1
  111. package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue2.js +65 -2
  112. package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue2.js.map +1 -1
  113. package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue3.js +6 -2
  114. package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue3.js.map +1 -1
  115. package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue2.js +63 -1
  116. package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue2.js.map +1 -1
  117. package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue3.js +8 -1
  118. package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue3.js.map +1 -1
  119. package/dist/esm/components/CnObjectSidebar/CnNotesTab.vue2.js +14 -0
  120. package/dist/esm/components/CnObjectSidebar/CnNotesTab.vue2.js.map +1 -1
  121. package/dist/esm/components/CnObjectSidebar/CnNotesTab.vue3.js +5 -1
  122. package/dist/esm/components/CnObjectSidebar/CnNotesTab.vue3.js.map +1 -1
  123. package/dist/esm/components/CnPageRenderer/CnPageRenderer.vue2.js +29 -1
  124. package/dist/esm/components/CnPageRenderer/CnPageRenderer.vue2.js.map +1 -1
  125. package/dist/esm/components/CnPageRenderer/CnPageRenderer.vue3.js.map +1 -1
  126. package/dist/esm/components/CnRadioCardsWidget/CnRadioCardsWidget.vue.js +10 -0
  127. package/dist/esm/components/CnRadioCardsWidget/CnRadioCardsWidget.vue.js.map +1 -0
  128. package/dist/esm/components/CnRadioCardsWidget/CnRadioCardsWidget.vue2.js +174 -0
  129. package/dist/esm/components/CnRadioCardsWidget/CnRadioCardsWidget.vue2.js.map +1 -0
  130. package/dist/esm/components/CnRadioCardsWidget/CnRadioCardsWidget.vue3.js +75 -0
  131. package/dist/esm/components/CnRadioCardsWidget/CnRadioCardsWidget.vue3.js.map +1 -0
  132. package/dist/esm/components/CnRadioCardsWidget/index.js +28 -0
  133. package/dist/esm/components/CnRadioCardsWidget/index.js.map +1 -0
  134. package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue.js +10 -0
  135. package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue.js.map +1 -0
  136. package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue2.js +411 -0
  137. package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue2.js.map +1 -0
  138. package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue3.js +178 -0
  139. package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue3.js.map +1 -0
  140. package/dist/esm/components/CnRecordListWidget/index.js +31 -0
  141. package/dist/esm/components/CnRecordListWidget/index.js.map +1 -0
  142. package/dist/esm/components/CnSavedViewsWidget/CnSavedViewsWidget.vue.js +10 -0
  143. package/dist/esm/components/CnSavedViewsWidget/CnSavedViewsWidget.vue.js.map +1 -0
  144. package/dist/esm/components/CnSavedViewsWidget/CnSavedViewsWidget.vue2.js +222 -0
  145. package/dist/esm/components/CnSavedViewsWidget/CnSavedViewsWidget.vue2.js.map +1 -0
  146. package/dist/esm/components/CnSavedViewsWidget/CnSavedViewsWidget.vue3.js +64 -0
  147. package/dist/esm/components/CnSavedViewsWidget/CnSavedViewsWidget.vue3.js.map +1 -0
  148. package/dist/esm/components/CnSavedViewsWidget/index.js +30 -0
  149. package/dist/esm/components/CnSavedViewsWidget/index.js.map +1 -0
  150. package/dist/esm/components/CnSectionsWidget/CnSectionsWidget.vue.js +10 -0
  151. package/dist/esm/components/CnSectionsWidget/CnSectionsWidget.vue.js.map +1 -0
  152. package/dist/esm/components/CnSectionsWidget/CnSectionsWidget.vue2.js +351 -0
  153. package/dist/esm/components/CnSectionsWidget/CnSectionsWidget.vue2.js.map +1 -0
  154. package/dist/esm/components/CnSectionsWidget/CnSectionsWidget.vue3.js +71 -0
  155. package/dist/esm/components/CnSectionsWidget/CnSectionsWidget.vue3.js.map +1 -0
  156. package/dist/esm/components/CnSectionsWidget/index.js +35 -0
  157. package/dist/esm/components/CnSectionsWidget/index.js.map +1 -0
  158. package/dist/esm/components/CnSegmentedControl/CnSegmentedControl.vue2.js.map +1 -1
  159. package/dist/esm/components/CnSegmentedControl/CnSegmentedControl.vue3.js.map +1 -1
  160. package/dist/esm/components/CnSettingsFormWidget/CnSettingsFormWidget.vue.js +10 -0
  161. package/dist/esm/components/CnSettingsFormWidget/CnSettingsFormWidget.vue.js.map +1 -0
  162. package/dist/esm/components/CnSettingsFormWidget/CnSettingsFormWidget.vue2.js +347 -0
  163. package/dist/esm/components/CnSettingsFormWidget/CnSettingsFormWidget.vue2.js.map +1 -0
  164. package/dist/esm/components/CnSettingsFormWidget/CnSettingsFormWidget.vue3.js +184 -0
  165. package/dist/esm/components/CnSettingsFormWidget/CnSettingsFormWidget.vue3.js.map +1 -0
  166. package/dist/esm/components/CnSettingsFormWidget/index.js +27 -0
  167. package/dist/esm/components/CnSettingsFormWidget/index.js.map +1 -0
  168. package/dist/esm/components/CnStagesWidget/CnStagesWidget.vue2.js +81 -2
  169. package/dist/esm/components/CnStagesWidget/CnStagesWidget.vue2.js.map +1 -1
  170. package/dist/esm/components/CnStagesWidget/CnStagesWidget.vue3.js.map +1 -1
  171. package/dist/esm/components/CnStatWidget/CnStatWidget.vue2.js +87 -6
  172. package/dist/esm/components/CnStatWidget/CnStatWidget.vue2.js.map +1 -1
  173. package/dist/esm/components/CnStatWidget/CnStatWidget.vue3.js +1 -0
  174. package/dist/esm/components/CnStatWidget/CnStatWidget.vue3.js.map +1 -1
  175. package/dist/esm/components/CnStatsBlockWidget/CnStatsBlockWidget.vue2.js +84 -1
  176. package/dist/esm/components/CnStatsBlockWidget/CnStatsBlockWidget.vue2.js.map +1 -1
  177. package/dist/esm/components/CnStatsBlockWidget/CnStatsBlockWidget.vue3.js +85 -41
  178. package/dist/esm/components/CnStatsBlockWidget/CnStatsBlockWidget.vue3.js.map +1 -1
  179. package/dist/esm/components/CnSwitchRowsWidget/CnSwitchRowsWidget.vue.js +10 -0
  180. package/dist/esm/components/CnSwitchRowsWidget/CnSwitchRowsWidget.vue.js.map +1 -0
  181. package/dist/esm/components/CnSwitchRowsWidget/CnSwitchRowsWidget.vue2.js +159 -0
  182. package/dist/esm/components/CnSwitchRowsWidget/CnSwitchRowsWidget.vue2.js.map +1 -0
  183. package/dist/esm/components/CnSwitchRowsWidget/CnSwitchRowsWidget.vue3.js +60 -0
  184. package/dist/esm/components/CnSwitchRowsWidget/CnSwitchRowsWidget.vue3.js.map +1 -0
  185. package/dist/esm/components/CnSwitchRowsWidget/index.js +26 -0
  186. package/dist/esm/components/CnSwitchRowsWidget/index.js.map +1 -0
  187. package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue2.js +168 -7
  188. package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue2.js.map +1 -1
  189. package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue3.js +86 -23
  190. package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue3.js.map +1 -1
  191. package/dist/esm/components/CnTasksWidget/CnTasksWidget.vue2.js +80 -1
  192. package/dist/esm/components/CnTasksWidget/CnTasksWidget.vue2.js.map +1 -1
  193. package/dist/esm/components/CnTasksWidget/CnTasksWidget.vue3.js +75 -32
  194. package/dist/esm/components/CnTasksWidget/CnTasksWidget.vue3.js.map +1 -1
  195. package/dist/esm/components/CnToggleTableWidget/CnToggleTableWidget.vue.js +10 -0
  196. package/dist/esm/components/CnToggleTableWidget/CnToggleTableWidget.vue.js.map +1 -0
  197. package/dist/esm/components/CnToggleTableWidget/CnToggleTableWidget.vue2.js +269 -0
  198. package/dist/esm/components/CnToggleTableWidget/CnToggleTableWidget.vue2.js.map +1 -0
  199. package/dist/esm/components/CnToggleTableWidget/CnToggleTableWidget.vue3.js +106 -0
  200. package/dist/esm/components/CnToggleTableWidget/CnToggleTableWidget.vue3.js.map +1 -0
  201. package/dist/esm/components/CnToggleTableWidget/index.js +27 -0
  202. package/dist/esm/components/CnToggleTableWidget/index.js.map +1 -0
  203. package/dist/esm/components/CnWidgetGrid/registerDashboardWidgets.js +11 -0
  204. package/dist/esm/components/CnWidgetGrid/registerDashboardWidgets.js.map +1 -1
  205. package/dist/esm/components/CnWidgetObjectTable/CnWidgetObjectTable.vue2.js +7 -2
  206. package/dist/esm/components/CnWidgetObjectTable/CnWidgetObjectTable.vue2.js.map +1 -1
  207. package/dist/esm/components/CnWidgetObjectTable/CnWidgetObjectTable.vue3.js.map +1 -1
  208. package/dist/esm/components/CnWidgetObjectTable/dashboardRegistration.js +5 -0
  209. package/dist/esm/components/CnWidgetObjectTable/dashboardRegistration.js.map +1 -1
  210. package/dist/esm/components/CnWorkspaceFilterWidget/CnWorkspaceFilterWidget.vue2.js +301 -6
  211. package/dist/esm/components/CnWorkspaceFilterWidget/CnWorkspaceFilterWidget.vue2.js.map +1 -1
  212. package/dist/esm/components/CnWorkspaceFilterWidget/CnWorkspaceFilterWidget.vue3.js +153 -55
  213. package/dist/esm/components/CnWorkspaceFilterWidget/CnWorkspaceFilterWidget.vue3.js.map +1 -1
  214. package/dist/esm/composables/useFormDraft.js +140 -9
  215. package/dist/esm/composables/useFormDraft.js.map +1 -1
  216. package/dist/esm/composables/useListView.js +4 -4
  217. package/dist/esm/composables/useListView.js.map +1 -1
  218. package/dist/esm/index.js +21 -1
  219. package/dist/esm/index.js.map +1 -1
  220. package/dist/esm/integrations/builtin/field-inspection/CnFieldInspectionCard.vue2.js +28 -20
  221. package/dist/esm/integrations/builtin/field-inspection/CnFieldInspectionCard.vue2.js.map +1 -1
  222. package/dist/esm/integrations/builtin/field-inspection/CnFieldInspectionCard.vue3.js +9 -0
  223. package/dist/esm/integrations/builtin/field-inspection/CnFieldInspectionCard.vue3.js.map +1 -1
  224. package/dist/esm/integrations/builtin/field-inspection.js +21 -0
  225. package/dist/esm/integrations/builtin/field-inspection.js.map +1 -1
  226. package/dist/esm/integrations/offline/checklistSubmission.js +141 -0
  227. package/dist/esm/integrations/offline/checklistSubmission.js.map +1 -0
  228. package/dist/esm/integrations/offline/fieldCollectionHelpers.js +70 -5
  229. package/dist/esm/integrations/offline/fieldCollectionHelpers.js.map +1 -1
  230. package/dist/esm/integrations/offline/index.js +2 -1
  231. package/dist/esm/integrations/offline/index.js.map +1 -1
  232. package/dist/esm/integrations/offline/offlineDb.js +6 -1
  233. package/dist/esm/integrations/offline/offlineDb.js.map +1 -1
  234. package/dist/esm/integrations/offline/syncReplayService.js +8 -2
  235. package/dist/esm/integrations/offline/syncReplayService.js.map +1 -1
  236. package/dist/esm/l10n/en.json.js +20 -1
  237. package/dist/esm/l10n/en.json.js.map +1 -1
  238. package/dist/esm/l10n/nl.json.js +70 -2
  239. package/dist/esm/l10n/nl.json.js.map +1 -1
  240. package/dist/esm/nextcloud-vue.css +2192 -222
  241. package/dist/esm/utils/contentHeaderLink.js +51 -0
  242. package/dist/esm/utils/contentHeaderLink.js.map +1 -0
  243. package/dist/esm/utils/detailActionModel.js +60 -3
  244. package/dist/esm/utils/detailActionModel.js.map +1 -1
  245. package/dist/esm/utils/facets.js +75 -3
  246. package/dist/esm/utils/facets.js.map +1 -1
  247. package/dist/esm/utils/fetchFilterCounts.js +40 -5
  248. package/dist/esm/utils/fetchFilterCounts.js.map +1 -1
  249. package/dist/esm/utils/fillTemplate.js +120 -0
  250. package/dist/esm/utils/fillTemplate.js.map +1 -0
  251. package/dist/esm/utils/initials.js +32 -0
  252. package/dist/esm/utils/initials.js.map +1 -0
  253. package/dist/esm/utils/libraryWidgetKeys.js +11 -0
  254. package/dist/esm/utils/libraryWidgetKeys.js.map +1 -1
  255. package/dist/esm/utils/objectWrite.js +59 -0
  256. package/dist/esm/utils/objectWrite.js.map +1 -0
  257. package/dist/esm/utils/pageControls.js +81 -0
  258. package/dist/esm/utils/pageControls.js.map +1 -0
  259. package/dist/esm/utils/personalLenses.js +40 -3
  260. package/dist/esm/utils/personalLenses.js.map +1 -1
  261. package/dist/esm/utils/queryPresets.js +96 -0
  262. package/dist/esm/utils/queryPresets.js.map +1 -0
  263. package/dist/esm/utils/resolveFilterTokens.js +12 -1
  264. package/dist/esm/utils/resolveFilterTokens.js.map +1 -1
  265. package/dist/esm/utils/resolveManifestTokens.js +2 -0
  266. package/dist/esm/utils/resolveManifestTokens.js.map +1 -1
  267. package/dist/esm/utils/schema.js +21 -0
  268. package/dist/esm/utils/schema.js.map +1 -1
  269. package/dist/esm/utils/sentinelTokens.js +22 -4
  270. package/dist/esm/utils/sentinelTokens.js.map +1 -1
  271. package/dist/esm/utils/userGroupsPeek.js +91 -0
  272. package/dist/esm/utils/userGroupsPeek.js.map +1 -0
  273. package/dist/esm/utils/validateManifestV2.compiled.js +3 -3
  274. package/dist/esm/utils/validateManifestV2.compiled.js.map +1 -1
  275. package/dist/esm/utils/visibleWhen.js +57 -5
  276. package/dist/esm/utils/visibleWhen.js.map +1 -1
  277. package/dist/esm/utils/widgetDispatch.js +7 -1
  278. package/dist/esm/utils/widgetDispatch.js.map +1 -1
  279. package/dist/esm/utils/widgetVisibility.js +4 -57
  280. package/dist/esm/utils/widgetVisibility.js.map +1 -1
  281. package/dist/nextcloud-vue.cjs.js +19708 -9301
  282. package/dist/nextcloud-vue.cjs.js.map +2 -2
  283. package/dist/nextcloud-vue.css +2192 -222
  284. package/l10n/en.json +20 -1
  285. package/l10n/nl.json +70 -2
  286. package/package.json +2 -1
  287. package/scripts/check-docs-mdx.mjs +108 -0
  288. package/src/components/CnActionButtons/CnActionButtons.vue +2 -0
  289. package/src/components/CnActionsBar/CnActionsBar.md +4 -0
  290. package/src/components/CnActionsBar/CnActionsBar.vue +48 -11
  291. package/src/components/CnAppRoot/CnAppRoot.md +4 -2
  292. package/src/components/CnAppRoot/CnAppRoot.vue +151 -59
  293. package/src/components/CnBannerWidget/CnBannerWidget.vue +244 -23
  294. package/src/components/CnCellRenderer/CnCellRenderer.md +2 -0
  295. package/src/components/CnCellRenderer/CnCellRenderer.vue +235 -5
  296. package/src/components/CnChipsFieldWidget/CnChipsFieldWidget.vue +433 -0
  297. package/src/components/CnChipsFieldWidget/index.js +25 -0
  298. package/src/components/CnChoicePickerWidget/CnChoicePickerWidget.vue +556 -0
  299. package/src/components/CnChoicePickerWidget/index.js +26 -0
  300. package/src/components/CnConversationThread/CnConversationWidget.vue +1 -1
  301. package/src/components/CnDashboardGrid/CnDashboardGrid.vue +2 -2
  302. package/src/components/CnDashboardPage/CnDashboardPage.vue +78 -5
  303. package/src/components/CnDataTable/CnDataTable.vue +22 -12
  304. package/src/components/CnDetailPage/CnDetailPage.md +1 -1
  305. package/src/components/CnDetailPage/CnDetailPage.vue +152 -6
  306. package/src/components/CnDetailWidgetHost/CnDetailWidgetHost.vue +66 -0
  307. package/src/components/CnDocumentReviewList/CnDocumentReviewWidget.vue +1 -1
  308. package/src/components/CnFacetSidebar/CnFacetSidebar.vue +7 -7
  309. package/src/components/CnFactsWidget/CnFactsWidget.vue +1190 -0
  310. package/src/components/CnFactsWidget/index.js +29 -0
  311. package/src/components/CnFieldListWidget/CnFieldListWidget.vue +1008 -0
  312. package/src/components/CnFieldListWidget/index.js +28 -0
  313. package/src/components/CnFilesBrowser/CnFilesBrowser.vue +588 -117
  314. package/src/components/CnFilesBrowser/filesBrowser.js +100 -0
  315. package/src/components/CnFilesBrowser/filesBrowserColumns.js +140 -0
  316. package/src/components/CnFormDialog/CnFormDialog.md +9 -3
  317. package/src/components/CnFormDialog/CnFormDialog.vue +69 -21
  318. package/src/components/CnFormPage/CnFormPage.vue +99 -3
  319. package/src/components/CnIndexPage/CnIndexPage.vue +309 -9
  320. package/src/components/CnIndexPage/CnIndexPageWidgets.vue +169 -0
  321. package/src/components/CnIndexSidebar/CnIndexSidebar.vue +7 -7
  322. package/src/components/CnNextStepCard/CnNextStepWidget.vue +1 -1
  323. package/src/components/CnObjectListWidget/CnObjectListWidget.vue +69 -2
  324. package/src/components/CnObjectSidebar/CnFilesTab.vue +70 -1
  325. package/src/components/CnObjectSidebar/CnNotesTab.vue +16 -0
  326. package/src/components/CnPageRenderer/CnPageRenderer.vue +29 -1
  327. package/src/components/CnRadioCardsWidget/CnRadioCardsWidget.vue +313 -0
  328. package/src/components/CnRadioCardsWidget/index.js +27 -0
  329. package/src/components/CnRecordListWidget/CnRecordListWidget.vue +652 -0
  330. package/src/components/CnRecordListWidget/index.js +30 -0
  331. package/src/components/CnSavedViewsWidget/CnSavedViewsWidget.vue +296 -0
  332. package/src/components/CnSavedViewsWidget/index.js +29 -0
  333. package/src/components/CnSectionsWidget/CnSectionsWidget.vue +489 -0
  334. package/src/components/CnSectionsWidget/index.js +34 -0
  335. package/src/components/CnSegmentedControl/CnSegmentedControl.vue +13 -0
  336. package/src/components/CnSettingsFormWidget/CnSettingsFormWidget.vue +555 -0
  337. package/src/components/CnSettingsFormWidget/index.js +26 -0
  338. package/src/components/CnStagesWidget/CnStagesWidget.vue +81 -2
  339. package/src/components/CnStatWidget/CnStatWidget.vue +88 -7
  340. package/src/components/CnStatsBlockWidget/CnStatsBlockWidget.vue +180 -3
  341. package/src/components/CnSwitchRowsWidget/CnSwitchRowsWidget.vue +226 -0
  342. package/src/components/CnSwitchRowsWidget/index.js +25 -0
  343. package/src/components/CnTabsWidget/CnTabsWidget.vue +263 -8
  344. package/src/components/CnTasksWidget/CnTasksWidget.vue +175 -15
  345. package/src/components/CnToggleTableWidget/CnToggleTableWidget.vue +386 -0
  346. package/src/components/CnToggleTableWidget/index.js +26 -0
  347. package/src/components/CnWidgetGrid/registerDashboardWidgets.js +11 -0
  348. package/src/components/CnWidgetObjectTable/CnWidgetObjectTable.vue +7 -2
  349. package/src/components/CnWidgetObjectTable/dashboardRegistration.js +5 -0
  350. package/src/components/CnWorkspaceFilterWidget/CnWorkspaceFilterWidget.vue +493 -11
  351. package/src/components/index.js +19 -0
  352. package/src/composables/__tests__/useFormDraft.spec.js +69 -0
  353. package/src/composables/useFormDraft.js +139 -8
  354. package/src/composables/useListView.js +4 -4
  355. package/src/css/form-field.css +14 -0
  356. package/src/css/index-page.css +71 -0
  357. package/src/css/kpi-card.css +32 -0
  358. package/src/css/look-board-detail.css +113 -2
  359. package/src/css/look-board-index.css +90 -8
  360. package/src/css/look-board.css +109 -2
  361. package/src/css/table.css +19 -0
  362. package/src/index.js +19 -0
  363. package/src/integrations/builtin/field-inspection/CnFieldInspectionCard.vue +35 -20
  364. package/src/integrations/builtin/field-inspection.js +21 -0
  365. package/src/integrations/offline/checklistSubmission.js +137 -0
  366. package/src/integrations/offline/fieldCollectionHelpers.js +69 -4
  367. package/src/integrations/offline/index.js +3 -0
  368. package/src/integrations/offline/offlineDb.js +6 -1
  369. package/src/integrations/offline/syncReplayService.js +8 -2
  370. package/src/schemas/app-manifest-v2.schema.json +196 -13
  371. package/src/utils/contentHeaderLink.js +48 -0
  372. package/src/utils/detailActionModel.js +59 -2
  373. package/src/utils/facets.js +74 -2
  374. package/src/utils/fetchFilterCounts.js +39 -4
  375. package/src/utils/fillTemplate.js +116 -0
  376. package/src/utils/initials.js +29 -0
  377. package/src/utils/libraryWidgetKeys.js +11 -0
  378. package/src/utils/objectWrite.js +55 -0
  379. package/src/utils/pageControls.js +78 -0
  380. package/src/utils/personalLenses.js +39 -2
  381. package/src/utils/queryPresets.js +93 -0
  382. package/src/utils/resolveFilterTokens.js +14 -1
  383. package/src/utils/resolveManifestTokens.js +2 -0
  384. package/src/utils/schema.js +21 -0
  385. package/src/utils/sentinelTokens.js +22 -4
  386. package/src/utils/userGroupsPeek.js +87 -0
  387. package/src/utils/validateManifestV2.compiled.js +3 -3
  388. package/src/utils/visibleWhen.js +56 -4
  389. package/src/utils/widgetDispatch.js +7 -1
  390. package/src/utils/widgetVisibility.js +7 -56
@@ -1 +1 @@
1
- {"version":3,"file":"CnStatWidget.vue2.js","sources":["../../../../src/components/CnStatWidget/CnStatWidget.vue"],"sourcesContent":["<!--\n SPDX-FileCopyrightText: 2026 Conduction B.V.\n SPDX-License-Identifier: EUPL-1.2\n\n CnStatWidget renders the CANONICAL KPI card (src/css/kpi-card.css). This tile\n and CnStatsBlock used to be two different-looking KPIs — a transparent\n icon-beside-number row here, a grey card with a circular icon and a large\n coloured number there — so OpenCatalogi's and dossiq's dashboards did not\n match. Both now render the same `cn-kpi-card` markup from the same\n stylesheet. The legacy `cn-stat-widget*` classes stay on the same elements so\n app CSS targeting them keeps working.\n\n Keep this comment OUT of <template>: a comment node beside the root element\n makes the component multi-root in Vue 3, and a multi-root component has no\n root for its class bindings to land on.\n-->\n<template>\n\t<component\n\t\t:is=\"linkTag\"\n\t\tclass=\"cn-kpi-card cn-stat-widget\"\n\t\t:class=\"[\n\t\t\t{ 'cn-kpi-card--clickable': isLinked, 'cn-stat-widget--linked': isLinked },\n\t\t\t'cn-kpi-card--' + cardLayout,\n\t\t\t{ 'cn-kpi-card--board': isBoardLook },\n\t\t\tflat ? 'cn-kpi-card--flat' : 'cn-kpi-card--filled',\n\t\t]\"\n\t\tv-bind=\"linkAttrs\">\n\t\t<div\n\t\t\tv-if=\"resolvedIcon && !isStacked && !isBoardLook\"\n\t\t\tclass=\"cn-kpi-card__icon cn-stat-widget__icon\"\n\t\t\t:style=\"iconCircleStyle\">\n\t\t\t<CnWidgetIcon :name=\"resolvedIcon\" :size=\"24\" />\n\t\t</div>\n\n\t\t<div class=\"cn-kpi-card__body cn-stat-widget__body\">\n\t\t\t<div\n\t\t\t\tv-if=\"content.label || rangePresets.length\"\n\t\t\t\tclass=\"cn-kpi-card__title cn-stat-widget__label\"\n\t\t\t\t:class=\"{ 'cn-kpi-card__title--badge-end': hasEndBadge }\">\n\t\t\t\t<!-- Board look: the icon is an 18px glyph before the label, and\n\t\t\t\t only when the tile links to a filtered list. -->\n\t\t\t\t<span\n\t\t\t\t\tv-if=\"isBoardLook && isLinked && resolvedIcon && !hasEndBadge\"\n\t\t\t\t\tclass=\"cn-kpi-card__glyph cn-stat-widget__glyph\"\n\t\t\t\t\tdata-testid=\"cn-stat-widget-glyph\"\n\t\t\t\t\taria-hidden=\"true\">\n\t\t\t\t\t<CnWidgetIcon :name=\"resolvedIcon\" :size=\"18\" />\n\t\t\t\t</span>\n\t\t\t\t<span v-if=\"content.label\" :title=\"resolvedLabel\">{{ resolvedLabel }}</span>\n\n\t\t\t\t<!-- Per-tile range override. Rendered ONLY when the tile declares its\n\t\t\t\t own `content.dateRange.presets`; a tile that merely follows the\n\t\t\t\t dashboard range shows no control, because the page already has one\n\t\t\t\t and two controls for one range read as two ranges. Stops click\n\t\t\t\t propagation so choosing a range inside a linked tile does not also\n\t\t\t\t navigate. -->\n\t\t\t\t<select\n\t\t\t\t\tv-if=\"rangePresets.length\"\n\t\t\t\t\tclass=\"cn-stat-widget__range\"\n\t\t\t\t\tdata-testid=\"cn-stat-widget-range\"\n\t\t\t\t\t:aria-label=\"rangeAriaLabel\"\n\t\t\t\t\t:value=\"activeRangePreset\"\n\t\t\t\t\t@click.stop.prevent\n\t\t\t\t\t@change=\"selectRange($event.target.value)\">\n\t\t\t\t\t<option\n\t\t\t\t\t\tv-for=\"preset in rangePresets\"\n\t\t\t\t\t\t:key=\"preset.id\"\n\t\t\t\t\t\t:value=\"preset.id\">\n\t\t\t\t\t\t{{ effectiveTranslate(preset.label || preset.id) }}\n\t\t\t\t\t</option>\n\t\t\t\t</select>\n\t\t\t\t<!-- Board look, `content.iconPlacement: \"end\"`: the icon sits in a\n\t\t\t\t 32px circle at the right of the label row, tinted by the\n\t\t\t\t tile's state (DqDashboard). -->\n\t\t\t\t<span\n\t\t\t\t\tv-if=\"hasEndBadge\"\n\t\t\t\t\tclass=\"cn-kpi-card__badge cn-stat-widget__badge-icon\"\n\t\t\t\t\t:class=\"'cn-kpi-card__badge--' + stateTone\"\n\t\t\t\t\tdata-testid=\"cn-stat-widget-icon-badge\"\n\t\t\t\t\taria-hidden=\"true\">\n\t\t\t\t\t<CnWidgetIcon :name=\"resolvedIcon\" :size=\"18\" />\n\t\t\t\t</span>\n\t\t\t</div>\n\n\t\t\t<div class=\"cn-kpi-card__value-row cn-stat-widget__value-row\">\n\t\t\t\t<NcLoadingIcon v-if=\"displayLoading\" :size=\"22\" />\n\t\t\t\t<span v-else-if=\"displayError\" class=\"cn-stat-widget__error\" :title=\"displayError\">—</span>\n\t\t\t\t<template v-else>\n\t\t\t\t\t<!-- Badge mode: the value is a state name, so it reads as the\n\t\t\t\t\t library's status pill rather than as a headline number. -->\n\t\t\t\t\t<CnStatusBadge\n\t\t\t\t\t\tv-if=\"isBadge\"\n\t\t\t\t\t\tclass=\"cn-stat-widget__badge\"\n\t\t\t\t\t\tdata-testid=\"cn-stat-widget-badge\"\n\t\t\t\t\t\t:label=\"shownValue\"\n\t\t\t\t\t\t:variant=\"badgeVariant\" />\n\t\t\t\t\t<span\n\t\t\t\t\t\tv-else\n\t\t\t\t\t\tclass=\"cn-kpi-card__value cn-stat-widget__value\"\n\t\t\t\t\t\t:data-testid=\"isCountdown ? 'cn-stat-widget-countdown' : null\"\n\t\t\t\t\t\t:class=\"{ 'cn-kpi-card__value--text': isTextValue || shownValueIsText }\"\n\t\t\t\t\t\t:title=\"shownValueIsText ? shownValue : (isTextValue ? String(displayValue) : null)\"\n\t\t\t\t\t\t:style=\"valueStyle\">\n\t\t\t\t\t\t{{ shownValue }}\n\t\t\t\t\t</span>\n\t\t\t\t\t<span\n\t\t\t\t\t\tv-if=\"formattedLimit !== ''\"\n\t\t\t\t\t\tclass=\"cn-stat-widget__limit\"\n\t\t\t\t\t\tdata-testid=\"cn-stat-widget-limit\">\n\t\t\t\t\t\t/ {{ formattedLimit }}\n\t\t\t\t\t</span>\n\t\t\t\t\t<span\n\t\t\t\t\t\tv-if=\"trendPct !== null\"\n\t\t\t\t\t\tclass=\"cn-stat-widget__trend\"\n\t\t\t\t\t\tdata-testid=\"cn-stat-widget-trend\"\n\t\t\t\t\t\t:style=\"{ color: trendColor }\">\n\t\t\t\t\t\t<component :is=\"trendIcon\" :size=\"14\" />\n\t\t\t\t\t\t{{ formattedTrend }}\n\t\t\t\t\t</span>\n\t\t\t\t</template>\n\t\t\t\t<span\n\t\t\t\t\tv-if=\"!isStacked && !displayLoading && !displayError && resolvedCaption\"\n\t\t\t\t\tclass=\"cn-kpi-card__label cn-stat-widget__caption\"\n\t\t\t\t\t:class=\"captionVariantClass\"\n\t\t\t\t\tdata-testid=\"cn-stat-widget-caption\">\n\t\t\t\t\t{{ resolvedCaption }}\n\t\t\t\t</span>\n\t\t\t</div>\n\t\t\t<!-- Stacked (`content.layout: \"stacked\"`): the caption is a line of\n\t\t\t its own under the number, as the board's \"3 new this week\". -->\n\t\t\t<span\n\t\t\t\tv-if=\"isStacked && !displayLoading && !displayError && resolvedCaption\"\n\t\t\t\tclass=\"cn-kpi-card__label cn-stat-widget__caption cn-kpi-card__caption-line\"\n\t\t\t\t:class=\"captionVariantClass\"\n\t\t\t\tdata-testid=\"cn-stat-widget-caption\">\n\t\t\t\t{{ resolvedCaption }}\n\t\t\t</span>\n\t\t\t<!-- A second caption line (`content.note`), as LpStart's \"3\n\t\t\t deadlines this week\" under the count. Static text for now. -->\n\t\t\t<span\n\t\t\t\tv-if=\"!displayLoading && !displayError && resolvedNote\"\n\t\t\t\tclass=\"cn-kpi-card__label cn-stat-widget__note cn-kpi-card__caption-line\"\n\t\t\t\t:class=\"noteVariantClass\"\n\t\t\t\tdata-testid=\"cn-stat-widget-note\">\n\t\t\t\t{{ resolvedNote }}\n\t\t\t</span>\n\t\t</div>\n\t</component>\n</template>\n\n<script>\nimport { subscribe, unsubscribe } from '@nextcloud/event-bus'\nimport { NcLoadingIcon } from '@nextcloud/vue'\nimport { inject, ref } from 'vue'\nimport TrendingDown from 'vue-material-design-icons/TrendingDown.vue'\nimport TrendingNeutral from 'vue-material-design-icons/TrendingNeutral.vue'\nimport TrendingUp from 'vue-material-design-icons/TrendingUp.vue'\nimport CnStatusBadge from '../CnStatusBadge/CnStatusBadge.vue'\nimport CnWidgetIcon from '../CnWidgetGrid/CnWidgetIcon.vue'\nimport { fetchSharedResponse, getByPath, useEndpointSource } from '../../composables/useEndpointSource.js'\nimport { normalizeLook } from '../../composables/useLook.js'\nimport widgetLink from '../../mixins/widgetLink.js'\nimport { useObjectStore } from '../../store/useObjectStore.js'\nimport { resolveObjectOpType } from '../../utils/actionsDispatcher.js'\nimport { resolveObjectTokenContext } from '../../utils/detailObjectContext.js'\nimport { formatMetricValue, unwrapAppConfig } from '../../utils/formatMetric.js'\nimport { dropOptionalUnresolved, resolveFilterTokens } from '../../utils/resolveFilterTokens.js'\nimport { STATUS_TEXT_COLORS } from '../../utils/statusColors.js'\nimport { evaluateVisibleWhenLocal, readVisibleWhenPath } from '../../utils/visibleWhen.js'\n\n// The canonical KPI look lives in one shared stylesheet, imported by BOTH\n// this component and CnStatsBlock, so the two cannot drift apart again.\n// Importing it here also means the look arrives without the consuming app\n// having pulled in the library's global css/index.css.\nimport '../../css/kpi-card.css'\n// Badge mode renders CnStatusBadge, whose colours live in the global badge\n// stylesheet. Imported here for the same reason as kpi-card.css above.\nimport '../../css/badge.css'\n\nconst PAGE_REFRESH_CHANNEL = 'cn:page:refresh'\n\n/**\n * Variant → CSS colour token map for the `variantWhen` threshold rules.\n * `danger` is accepted as an alias of `error` (the doriath KPI-card\n * vocabulary); `default` keeps the widget's configured colours.\n *\n * @type {Record<string, string>}\n */\n// These paint the number, so they take the text-on-background tokens.\nconst VARIANT_COLORS = {\n\tdefault: '',\n\tprimary: 'var(--color-primary-element)',\n\tsuccess: STATUS_TEXT_COLORS.success,\n\twarning: STATUS_TEXT_COLORS.warning,\n\terror: STATUS_TEXT_COLORS.error,\n\tdanger: STATUS_TEXT_COLORS.error,\n}\n\n/**\n * The variants CnStatusBadge accepts. Badge mode normalises every tile\n * variant onto this list: `danger` becomes `error`, anything unknown is\n * skipped so the next rule in line decides.\n *\n * @type {string[]}\n */\nconst BADGE_VARIANTS = ['default', 'primary', 'success', 'warning', 'error', 'info']\n\n/**\n * A bare `YYYY-MM-DD`, the shape OpenRegister stores a date property in.\n *\n * It is matched BEFORE `new Date()` sees it on purpose. `new Date('2026-09-26')`\n * is specified to parse a date-only string as UTC midnight, so west of\n * Greenwich it lands on the 25th local and every countdown built on it is a\n * day short. A date the schema calls a date has no time and no zone, so it is\n * read as the local calendar day it names.\n *\n * @type {RegExp}\n */\nconst DATE_ONLY = /^(\\d{4})-(\\d{2})-(\\d{2})$/\n\n/** Milliseconds in a day, used only between two UTC-normalised midnights. */\nconst DAY_MS = 86400000\n\n/**\n * The local calendar day a value names, as a UTC midnight timestamp.\n *\n * WHY CALENDAR DAYS AND NOT ELAPSED MILLISECONDS. A deadline is a day on a\n * calendar, not an instant. Subtracting timestamps makes a deadline at 23:00\n * today read as \"0 days\" and one at 01:00 tomorrow read as \"0 days\" as well\n * (two hours apart), while 09:00 tomorrow reads as \"1 day\" — the same calendar\n * distance rendering as two different answers because of the time somebody\n * happened to type. So both ends are collapsed to the LOCAL calendar day they\n * fall on, and the difference is taken between those days.\n *\n * The collapse goes through `Date.UTC` rather than a local `Date`, because two\n * UTC midnights are always exactly `DAY_MS` apart, while two local midnights\n * across a DST change are 23 or 25 hours apart and a plain division then\n * rounds to the wrong day twice a year.\n *\n * @param {unknown} value A date string, a `Date`, or an epoch-milliseconds number.\n * @return {number|null} The UTC-midnight timestamp of that local day, or null when there is no readable date.\n */\nfunction calendarDay(value) {\n\tif (value === null || value === undefined || value === '') {\n\t\treturn null\n\t}\n\tif (typeof value === 'string') {\n\t\tconst parts = DATE_ONLY.exec(value.trim())\n\t\tif (parts) {\n\t\t\treturn Date.UTC(Number(parts[1]), Number(parts[2]) - 1, Number(parts[3]))\n\t\t}\n\t}\n\tconst isDate = value instanceof Date\n\tif (!isDate && typeof value !== 'string' && !Number.isFinite(value)) {\n\t\t// A boolean or an object is not a mis-typed date, it is not a date at\n\t\t// all; `new Date(true)` would happily answer 1 January 1970.\n\t\treturn null\n\t}\n\tconst parsed = isDate ? value : new Date(value)\n\tif (Number.isNaN(parsed.getTime())) {\n\t\treturn null\n\t}\n\treturn Date.UTC(parsed.getFullYear(), parsed.getMonth(), parsed.getDate())\n}\n\n/**\n * CnStatWidget — an abstract, manifest-configured KPI / single-statistic tile.\n *\n * Reads ONE scalar value from OpenRegister's ad-hoc aggregation endpoint\n * (`/apps/openregister/api/objects/aggregations/{register}/{schema}/value`)\n * given a `source` config (register, schema, metric, field, filter) and renders\n * it with a configurable label, icon, value colour, and number format. Nothing\n * about the data or presentation is hard-coded — every fleet app gets the same\n * editable KPI tile, replacing per-app coded KPI components (ADR-041).\n *\n * The widget is resolved by its registry type key `stat` (see\n * `CnStatWidget/index.js`); apps reference it from a manifest placement, e.g.\n * `{ id, widgetKey: 'stat', type: 'stat', content: { label, source, ... } }`.\n *\n * Example content blob:\n * ```js\n * content: {\n * label: 'Revenue',\n * icon: 'Cash',\n * valueColor: '#0082c9',\n * format: { style: 'currency', currency: 'EUR', decimals: 0 },\n * source: { register: 'pipelinq', schema: 'lead', metric: 'sum', field: 'value', filter: { status: 'won' } },\n * }\n * ```\n *\n * ENDPOINT BINDING (Wave 2, #91) — instead of an OpenRegister `source`, the\n * tile can bind to an arbitrary app REST endpoint through the shared\n * `useEndpointSource` engine (token-resolved params, per-(url+params)\n * request dedup + short-TTL cache, `cn:page:refresh` / `cn:widget:refresh`\n * subscription). Exactly ONE of `source` | `endpointSource` may be\n * configured (validator-enforced); when both slip through, `endpointSource`\n * wins. The pipelinq analytics-KPI contract in full:\n * ```js\n * content: {\n * label: 'Revenue',\n * icon: 'CashMultiple',\n * format: { style: 'currency', currency: 'EUR', decimals: 0 },\n * endpointSource: {\n * url: '/apps/pipelinq/api/analytics/commercial',\n * params: { period: '@workspace.datePreset?' },\n * },\n * valueField: 'revenue', // dot-path into the payload\n * previousField: 'previousPeriod.revenue', // → trend sublabel (arrow + % vs previous)\n * // deltaField: 'revenueDeltaPct', // OR a server-computed delta percent\n * goodDirection: 'up', // tints the trend good/bad (default 'up')\n * variantWhen: [ // first-match threshold styling\n * { op: 'gte', value: 100000, variant: 'success' },\n * { op: 'lt', value: 10000, variant: 'warning', icon: 'AlertOutline' },\n * ],\n * clickRoute: 'leads', // whole-tile click-through (alias of route)\n * }\n * ```\n *\n * BADGE MODE. `display: 'badge'` renders the value as a `CnStatusBadge` pill,\n * for a tile whose value is a state name rather than a count. The badge colour\n * can come from the RESOLVED ROW of an `objectField` reference, not only from\n * the displayed text: `resolve.variantField` names a field on the looked-up\n * row, and `resolve.variantMap` maps its value to a variant (without a map the\n * field value itself must be a variant name). `emptyText` replaces the dash\n * when the value is empty or its reference does not resolve. `overrides` test\n * the BOUND RECORD, first match wins, and replace the label, variant and icon,\n * so a record in a special state reads as that state:\n * ```js\n * content: {\n * label: 'Status',\n * display: 'badge',\n * emptyText: 'Unknown',\n * objectField: {\n * field: 'status',\n * resolve: {\n * register: 'dossiq',\n * schema: 'statusType',\n * labelField: 'name',\n * variantField: 'isFinal',\n * variantMap: { true: 'success', false: 'info' },\n * },\n * },\n * overrides: [\n * { when: { field: 'suspended' }, label: 'Suspended', variant: 'warning' },\n * ],\n * }\n * ```\n *\n * COUNTDOWN MODE. `display: 'countdown'` reads a DATE off the record (or off an\n * endpoint payload) and renders the time remaining, so a deadline is a\n * configured KPI tile rather than a component an app writes by hand:\n * ```js\n * content: {\n * label: 'Deadline',\n * display: 'countdown',\n * objectField: 'dueDate',\n * countdown: {\n * unit: 'days', // the only unit; anything else is read as days\n * warnAt: 14, // warning at or below this many days left\n * dangerAt: 5, // error at or below, and it wins over warnAt\n * pastLabel: 'Overdue by {n} days', // a date that has passed\n * emptyText: 'No deadline', // absent or unreadable date\n * },\n * }\n * ```\n * A passed date NEVER renders as a negative number: it renders `pastLabel` with\n * `{n}` as the number of days it is past, and it is always the error colour\n * whether or not `dangerAt` is set. Today is 0, not 1 and not −1, and renders\n * `todayLabel` (\"Today\"). The thresholds are INCLUSIVE. An absent or unreadable\n * date renders `countdown.emptyText`, falling back to `content.emptyText` and\n * then to the dash, never `NaN` or `Invalid Date`. `overrides` outrank the\n * countdown's own label and colour exactly as they outrank a badge's.\n */\nexport default {\n\tname: 'CnStatWidget',\n\n\tcomponents: {\n\t\tNcLoadingIcon,\n\t\tCnWidgetIcon,\n\t\tCnStatusBadge,\n\t\tTrendingUp,\n\t\tTrendingDown,\n\t\tTrendingNeutral,\n\t},\n\n\tmixins: [widgetLink],\n\n\tinject: {\n\t\t/**\n\t\t * Detail-page object context (`{ objectId, object, register, schema }`)\n\t\t * provided by CnDetailPage — enables `@objectId` / `@object.<field>`\n\t\t * filter tokens so a detail-page KPI can be scoped to the current\n\t\t * object. Null on dashboards (tokens then pass through unresolved).\n\t\t */\n\t\tcnObjectContext: { default: null },\n\t\t/**\n\t\t * The look the app is drawn in (`board` or `nextcloud`), provided by\n\t\t * CnAppRoot. The board look draws the screens' KPI tile.\n\t\t *\n\t\t * @spec openspec/changes/screens-dashboard-parity/specs/dashboard-page/spec.md#requirement-the-board-kpi-tile\n\t\t */\n\t\tcnLook: { default: 'nextcloud' },\n\t\t/**\n\t\t * v2 slot-grid detail context holder (`{ value: { objectData, schema,\n\t\t * objectType, objectId, register, store } | null }`) provided by\n\t\t * CnPageRenderer — backfills the object token context so\n\t\t * `@objectId` / `@object.<field>` resolve on detail surfaces where\n\t\t * CnDetailPage is not an ancestor (#91 Wave 3).\n\t\t */\n\t\tcnDetailObjectContext: { default: null },\n\t\t/**\n\t\t * Page-level workspace context (a reactive `{ <key>: value }` map)\n\t\t * provided by CnDashboardPage. Drives `@page.<param>` / `@workspace.<param>`\n\t\t * tokens in an `endpoint` source's URL / params (e.g. a period selector\n\t\t * the page renders that every endpoint KPI reads). Empty `{}` when no\n\t\t * dashboard ancestor provides one.\n\t\t */\n\t\tcnWorkspaceContext: { default: () => ({}) },\n\t\t/**\n\t\t * Page-level app config (a reactive `{ <key>: value }` map) provided by\n\t\t * CnDashboardPage / CnDetailPage. Drives `@config.<key>` tokens in an\n\t\t * `endpoint` source's URL / params AND in the `format.currency` /\n\t\t * `format.suffix` / `format.prefix` strings (e.g. the reporting currency\n\t\t * the setup wizard captures). Empty `{}` when no ancestor provides one.\n\t\t */\n\t\tcnAppConfig: { default: () => ({}) },\n\t\t/**\n\t\t * Translate function provided by CnAppRoot (the host app's\n\t\t * `translate`, scoped to its app id). Applied to the manifest-authored\n\t\t * `content.label` / `content.caption` so a KPI tile renders in the\n\t\t * user's Nextcloud language instead of the raw source string. Defaults\n\t\t * to an identity function so the widget stays usable standalone.\n\t\t *\n\t\t * @type {(key: string) => string}\n\t\t */\n\t\tcnTranslate: { default: () => (key) => key },\n\t\t/**\n\t\t * Reactive date range provided by an ancestor `CnDashboardPage` when its\n\t\t * `dateRange.enabled` is true — `{ from, to, preset }`, else null. Same\n\t\t * ref `CnChartWidget` injects, so a tile and a chart on one dashboard\n\t\t * always agree on the period. A tile follows it only once it declares\n\t\t * `content.dateRange` (see the `content` prop docs for why).\n\t\t *\n\t\t * @type {{value: ({from: string, to: string, preset: string}|null)}}\n\t\t */\n\t\tcnDashboardDateRange: { default: () => ref(null) },\n\t},\n\n\tprops: {\n\t\t/**\n\t\t * The widget's persisted configuration blob. An optional `route`\n\t\t * (vue-router location), `clickRoute` (Wave-2 alias), or `link`\n\t\t * (external href) turns the whole tile into a click-through target\n\t\t * (see the widgetLink mixin).\n\t\t * The `source` resolves the value. Besides the OpenRegister-backed kinds\n\t\t * (plain aggregate / `ratio` / `computed` / `weighted`), an\n\t\t * `{ kind: 'endpoint', url, path?, params? }` source reads an arbitrary\n\t\t * app REST endpoint and extracts the value at the dot-`path` of the\n\t\t * response (default = whole body). The `url` and any string `params`\n\t\t * value interpolate `@page.<param>` / `@workspace.<param>` tokens from the\n\t\t * page-level context (and `@objectId` / `@object.<field>` on a detail\n\t\t * page) — so a page-rendered period selector can drive every endpoint KPI.\n\t\t *\n\t\t * Wave 2 (#91): `endpointSource` (`{ url, method?, params?,\n\t\t * responsePath? }`) binds the tile to an arbitrary endpoint through the\n\t\t * shared `useEndpointSource` engine — exactly one of `source` |\n\t\t * `endpointSource`. `valueField` plucks the displayed value from the\n\t\t * payload; `previousField` (previous-period value) or `deltaField`\n\t\t * (server-computed percent) renders the trend sublabel (arrow +\n\t\t * percent-vs-previous, tinted by `goodDirection`, default `'up'`);\n\t\t * `variantWhen` (`[{ op, value, variant, icon? }]`, first match wins)\n\t\t * re-tints the value/icon by threshold.\n\t\t *\n\t\t * `limitField` (dot-path into the payload) or a static `limit` renders the\n\t\t * tile as a capacity pair — `0 / 100` — and tints it `warning` once the\n\t\t * value reaches the limit, unless a `variantWhen` rule already claims the\n\t\t * colour. Use `limitField` for a server-configured quota so the ceiling is\n\t\t * read live rather than duplicated in the manifest.\n\t\t *\n\t\t * `dateRange` opts the tile into the dashboard's period. Present and empty\n\t\t * (`{}`) = follow the ancestor `CnDashboardPage` range; add `presets`\n\t\t * (`[{ id, label?, from?, to? }]`) to render a per-tile picker that\n\t\t * overrides it. With presets and no page range, the tile starts on\n\t\t * `dateRange.default` (a preset id), else on the first preset, so the\n\t\t * picker never opens blank and the first request already carries a\n\t\t * range. The active range is exposed to `endpointSource` (and to the\n\t\t * tile's `route`) as `@range.from` / `@range.to` / `@range.preset`\n\t\t * tokens. A tile that\n\t\t * declares no `dateRange` is unaffected by the page range — that is\n\t\t * deliberate, so adding a range to a dashboard cannot silently change what\n\t\t * an existing tile requests.\n\t\t *\n\t\t * `display: 'badge'` renders the value as a `CnStatusBadge`. On an\n\t\t * `objectField` reference, `resolve.variantField` (a dot-path on the\n\t\t * looked-up row) plus `resolve.variantMap` (`{ rowValue: variant }`)\n\t\t * colour it from the row; without a map the row value must itself be a\n\t\t * variant name. `emptyText` replaces the dash for an empty value, and\n\t\t * for a reference that does not resolve. `overrides`\n\t\t * (`[{ when: { field, op?, value? }, label?, variant?, icon? }]`, first\n\t\t * match wins) test the bound record: `when` is the local `visibleWhen`\n\t\t * grammar, and a `when` with neither `op` nor `value` tests the field\n\t\t * for truthiness. A match replaces the shown label, the colour and the\n\t\t * icon. Precedence of the colour: override, `variantWhen`, the countdown\n\t\t * threshold, the at-limit warning, the resolved row, the static\n\t\t * `variant`.\n\t\t *\n\t\t * `display: 'countdown'` reads the value as a DATE and renders the days\n\t\t * remaining. `countdown.warnAt` / `countdown.dangerAt` are inclusive day\n\t\t * thresholds and `dangerAt` wins; `countdown.pastLabel` (with `{n}`)\n\t\t * words a date that has passed, which is always the error colour and is\n\t\t * never shown as a negative number; `countdown.todayLabel` words a date\n\t\t * due today, which counts as 0; `countdown.futureLabel` (with `{n}`)\n\t\t * words the ordinary case; `countdown.emptyText` words an absent or\n\t\t * unreadable date, falling back to the top-level `emptyText`. Days are\n\t\t * counted between LOCAL CALENDAR DAYS, not as elapsed milliseconds, so\n\t\t * the time of day on a deadline never moves the answer.\n\t\t *\n\t\t * @type {{label?: string, icon?: string, iconColor?: string, valueColor?: string, caption?: string, route?: (object|string), clickRoute?: (object|string), link?: string, format?: {style?: string, currency?: string, decimals?: number, prefix?: string, suffix?: string}, source?: {kind?: string, register?: string, schema?: string, metric?: string, field?: string, filter?: object, url?: string, path?: string, params?: object}, endpointSource?: {url: string, method?: string, params?: object, responsePath?: string}, valueField?: string, limitField?: string, limit?: number, dateRange?: {presets?: Array<{id: string, label?: string, from?: string, to?: string}>, default?: string}, previousField?: string, deltaField?: string, goodDirection?: ('up'|'down'), variant?: ('default'|'primary'|'success'|'warning'|'error'|'danger'), variantWhen?: Array<{op: string, value: unknown, variant: string, icon?: string}>, objectField?: (string|{field: string, resolve?: {register: string, schema: string, labelField?: string, variantField?: string, variantMap?: {[key: string]: string}}}), display?: ('text'|'badge'|'countdown'), countdown?: {unit?: 'days', warnAt?: number, dangerAt?: number, futureLabel?: string, todayLabel?: string, pastLabel?: string, emptyText?: string}, emptyText?: string, captionVariant?: ('default'|'primary'|'success'|'warning'|'error'|'danger'), captionVariantWhen?: Array<{op: string, value: unknown, variant: string}>, overrides?: Array<{when: {field: string, op?: string, value?: unknown}, label?: string, variant?: string, icon?: string, caption?: string, captionVariant?: string}>}}\n\t\t */\n\t\tcontent: {\n\t\t\ttype: Object,\n\t\t\tdefault: () => ({}),\n\t\t},\n\n\t\t/**\n\t\t * Translate function. Falls back to the injected `cnTranslate`\n\t\t * (itself an identity function by default). Provide explicitly when\n\t\t * mounting CnStatWidget outside a CnAppRoot ancestor.\n\t\t *\n\t\t * @type {((key: string) => string)|null}\n\t\t */\n\t\ttranslate: {\n\t\t\ttype: Function,\n\t\t\tdefault: null,\n\t\t},\n\t},\n\n\tsetup(props) {\n\t\t// Endpoint binding (Wave 2): the shared useEndpointSource engine owns\n\t\t// token resolution, request dedup + TTL caching, and the\n\t\t// cn:page:refresh / cn:widget:refresh subscriptions. It is a no-op\n\t\t// while `content.endpointSource` is absent, so the OpenRegister\n\t\t// `source` path below is untouched. The injects are re-read here in\n\t\t// setup — Vue 2.7 resolves them identically to the Options `inject`\n\t\t// block (same precedent as CnChartWidget's date-range ref).\n\t\tconst objectCtxRaw = inject('cnObjectContext', null)\n\t\tconst detailCtxRaw = inject('cnDetailObjectContext', null)\n\t\tconst workspaceRaw = inject('cnWorkspaceContext', ref({}))\n\t\tconst appConfigRaw = inject('cnAppConfig', ref({}))\n\t\tconst pageRangeRaw = inject('cnDashboardDateRange', ref(null))\n\t\tconst unwrap = (v) => ((v && typeof v === 'object' && 'value' in v) ? v.value : v)\n\n\t\t// The per-tile range override. Null = follow the dashboard range; set by\n\t\t// selectRange() when the tile renders its own preset picker. It lives in\n\t\t// setup, not data(), because the ctx closure below must read it reactively\n\t\t// — a data() property would be resolved once and never refetch.\n\t\tconst tileRange = ref(null)\n\t\t// With its own presets and no page range, the tile starts on\n\t\t// `dateRange.default`, else the first preset. Without this the picker\n\t\t// opened blank (its value '' matched no option unless an app added a\n\t\t// preset with id '') and the first request carried no range. Only a\n\t\t// tile that declares presets gets a default: one that merely follows\n\t\t// the dashboard (`dateRange: {}`) keeps following it.\n\t\tconst defaultRange = () => {\n\t\t\tconst dr = props.content && props.content.dateRange\n\t\t\tconst presets = (dr && Array.isArray(dr.presets)) ? dr.presets.filter(Boolean) : []\n\t\t\tif (presets.length === 0) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tconst chosen = (dr.default !== undefined && presets.find((p) => p.id === dr.default)) || presets[0]\n\t\t\treturn { preset: chosen.id, from: chosen.from ?? null, to: chosen.to ?? null }\n\t\t}\n\t\tconst activeRange = () => (tileRange.value || unwrap(pageRangeRaw) || defaultRange())\n\n\t\tconst { data, loading, error, refetch } = useEndpointSource(\n\t\t\t() => (props.content && props.content.endpointSource) || null,\n\t\t\t{\n\t\t\t\tctx: () => ({\n\t\t\t\t\t...(resolveObjectTokenContext(objectCtxRaw, detailCtxRaw) || {}),\n\t\t\t\t\tworkspace: unwrap(workspaceRaw) || {},\n\t\t\t\t\tconfig: unwrap(appConfigRaw) || {},\n\t\t\t\t\t// `@range.from` / `@range.to` / `@range.preset` tokens, usable in the\n\t\t\t\t\t// endpointSource url and params exactly like `@workspace.*`.\n\t\t\t\t\trange: activeRange() || {},\n\t\t\t\t}),\n\t\t\t},\n\t\t)\n\t\treturn { epData: data, epLoading: loading, epError: error, epRefetch: refetch, tileRange, activeRange }\n\t},\n\n\tdata() {\n\t\treturn {\n\t\t\t// Resolved display label for an `objectField` that holds a reference\n\t\t\t// uuid. Null until resolved, and null forever when it cannot be.\n\t\t\treferenceLabel: null,\n\t\t\t// The looked-up row behind `referenceLabel`, read by\n\t\t\t// `resolve.variantField` to colour the tile from the row itself.\n\t\t\treferenceRow: null,\n\t\t\t// True once a configured lookup ran and found no usable label.\n\t\t\treferenceFailed: false,\n\t\t\t// True while a configured lookup is in flight. Without it, \"not\n\t\t\t// resolved yet\" and \"cannot be resolved\" were the same state, so the\n\t\t\t// tile showed the RAW UUID for the length of the request and then\n\t\t\t// replaced it with the label or the empty text. A person watching a\n\t\t\t// status badge saw `4f2b9c10-…` flash past where a state belonged.\n\t\t\treferencePending: false,\n\t\t\tvalue: null,\n\t\t\tloading: false,\n\t\t\terror: '',\n\t\t}\n\t},\n\n\tcomputed: {\n\t\t/**\n\t\t * Whether the app takes the board look (`cnLook` is `board`).\n\t\t *\n\t\t * @spec openspec/changes/screens-dashboard-parity/specs/dashboard-page/spec.md#requirement-the-board-kpi-tile\n\t\t * @return {boolean}\n\t\t */\n\t\tisBoardLook() {\n\t\t\treturn normalizeLook(this.cnLook) === 'board'\n\t\t},\n\n\t\t/**\n\t\t * Effective translate function: the explicit `translate` prop when\n\t\t * given, else the injected `cnTranslate` (identity by default).\n\t\t *\n\t\t * @return {(key: string) => string}\n\t\t */\n\t\teffectiveTranslate() {\n\t\t\treturn this.translate ?? this.cnTranslate\n\t\t},\n\n\t\t/**\n\t\t * The tile label, run through the host translate function so a\n\t\t * manifest-authored source string localises to the user's language.\n\t\t *\n\t\t * @return {string}\n\t\t */\n\t\tresolvedLabel() {\n\t\t\tconst label = this.content.label\n\t\t\treturn label ? this.effectiveTranslate(label) : ''\n\t\t},\n\n\t\t/**\n\t\t * The tile caption, translated and then interpolated with the fetched\n\t\t * payload.\n\t\t *\n\t\t * `{field}` tokens are replaced from the endpoint payload by dot-path,\n\t\t * using the same {@link getByPath} that resolves `valueField` — so a\n\t\t * caption can say what the number MEANS rather than repeating it:\n\t\t *\n\t\t * caption: '{levelName} · {currentStreakDays}-day streak'\n\t\t *\n\t\t * WHY THIS EXISTS. Without it a tile needing a secondary line had to be\n\t\t * a bespoke component: it could not be expressed as config, so apps\n\t\t * wrote their own card, and that card then re-implemented fetching,\n\t\t * loading and error handling too. Every one of those re-implementations\n\t\t * observed so far swallowed its errors into a zero.\n\t\t *\n\t\t * Translation runs FIRST, so a translator sees `{levelName}` as a\n\t\t * placeholder in the source string and can move it within the sentence —\n\t\t * the same contract as Nextcloud's own `t()` parameters.\n\t\t *\n\t\t * A token with no matching field resolves to the empty string rather\n\t\t * than being left as `{levelName}` on screen: a caption is decoration,\n\t\t * and showing a reader a raw token is worse than showing them less.\n\t\t *\n\t\t * @return {string}\n\t\t */\n\t\tresolvedCaption() {\n\t\t\tconst override = this.activeOverride\n\t\t\tconst caption = (override && typeof override.caption === 'string' && override.caption !== '')\n\t\t\t\t? override.caption\n\t\t\t\t: this.content.caption\n\t\t\tif (!caption) {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t\tconst translated = this.effectiveTranslate(caption)\n\t\t\tif (translated.indexOf('{') === -1) {\n\t\t\t\treturn translated\n\t\t\t}\n\t\t\tconst payload = this.endpointMode ? this.epData : null\n\t\t\treturn translated.replace(/\\{([A-Za-z0-9_.]+)\\}/g, (whole, path) => {\n\t\t\t\t// `{value}` is the tile's own number, so a caption can read\n\t\t\t\t// \"{value} due today\" on a register-counted tile that has no\n\t\t\t\t// payload to read fields from.\n\t\t\t\tif (path === 'value' && (payload === null || getByPath(payload, path) === undefined)) {\n\t\t\t\t\treturn this.formattedValue === undefined || this.formattedValue === null ? '' : String(this.formattedValue)\n\t\t\t\t}\n\t\t\t\tconst v = getByPath(payload, path)\n\t\t\t\treturn (v === undefined || v === null) ? '' : String(v)\n\t\t\t}).replace(/\\s{2,}/g, ' ').trim()\n\t\t},\n\n\t\t/**\n\t\t * The first `content.captionVariantWhen` rule the tile's value\n\t\t * matches (`[{ op, value, variant }]`, the `variantWhen` shape), or\n\t\t * null. Colours the caption on the value without recolouring the\n\t\t * tile: \"1 due today\" turns red while the number stays ink.\n\t\t *\n\t\t * @spec openspec/changes/zuiddrecht-pixel-gaps/specs/zuiddrecht-pixel-gaps/spec.md#requirement-a-stat-tile-colours-its-caption-by-rule\n\t\t * @return {object|null}\n\t\t */\n\t\tactiveCaptionRule() {\n\t\t\tconst rules = this.content.captionVariantWhen\n\t\t\tif (!Array.isArray(rules) || rules.length === 0) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tconst current = this.displayValue\n\t\t\tif (current === null || current === undefined) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\treturn rules.find((r) => r && this.matchesRule(current, r)) || null\n\t\t},\n\n\t\t/**\n\t\t * The second caption line: `content.note` through the host translate\n\t\t * function, or '' without it.\n\t\t *\n\t\t * @spec openspec/changes/zuiddrecht-pixel-gaps-3/specs/zuiddrecht-pixel-gaps-3/spec.md#requirement-a-stat-tile-can-carry-a-second-caption-line\n\t\t * @return {string}\n\t\t */\n\t\tresolvedNote() {\n\t\t\tconst note = this.content && this.content.note\n\t\t\treturn typeof note === 'string' && note !== '' ? this.effectiveTranslate(note) : ''\n\t\t},\n\n\t\t/**\n\t\t * The colour class of the second caption line (`content.noteVariant`,\n\t\t * the same names as `captionVariant`), or '' for the muted default.\n\t\t *\n\t\t * @spec openspec/changes/zuiddrecht-pixel-gaps-3/specs/zuiddrecht-pixel-gaps-3/spec.md#requirement-a-stat-tile-can-carry-a-second-caption-line\n\t\t * @return {string}\n\t\t */\n\t\tnoteVariantClass() {\n\t\t\tconst variant = this.content && this.content.noteVariant\n\t\t\tif (!variant || variant === 'default' || !Object.hasOwn(VARIANT_COLORS, variant)) {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t\treturn `cn-kpi-card__label--${variant === 'danger' ? 'error' : variant}`\n\t\t},\n\n\t\t/**\n\t\t * The caption's colour class: the matching override's\n\t\t * `captionVariant`, else `content.captionVariant`, as\n\t\t * `cn-kpi-card__label--<variant>`. '' for `default` or an unknown\n\t\t * variant, so an uncoloured caption is what it always was.\n\t\t *\n\t\t * @spec openspec/changes/zuiddrecht-pixel-gaps/specs/zuiddrecht-pixel-gaps/spec.md#requirement-a-stat-tile-colours-its-caption-by-rule\n\t\t * @return {string}\n\t\t */\n\t\tcaptionVariantClass() {\n\t\t\tconst override = this.activeOverride\n\t\t\tconst variant = (override && override.captionVariant)\n\t\t\t\t|| (this.activeCaptionRule && this.activeCaptionRule.variant)\n\t\t\t\t|| this.content.captionVariant\n\t\t\tif (!variant || variant === 'default' || !Object.hasOwn(VARIANT_COLORS, variant)) {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t\t// Board look: colour in a tile means a warning and nothing else.\n\t\t\tif (this.isBoardLook && !['warning', 'error', 'danger'].includes(variant)) {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t\treturn `cn-kpi-card__label--${variant === 'danger' ? 'error' : variant}`\n\t\t},\n\n\t\t/**\n\t\t * The unwrapped detail-page object context for token resolution, or null\n\t\t * on surfaces (dashboards) that don't provide one.\n\t\t *\n\t\t * @return {object|null}\n\t\t */\n\t\tobjectCtx() {\n\t\t\treturn resolveObjectTokenContext(this.cnObjectContext, this.cnDetailObjectContext)\n\t\t},\n\n\t\t/**\n\t\t * The unwrapped page-level workspace context map for `@page.*` /\n\t\t * `@workspace.*` token resolution. Always an object (defaults to `{}`).\n\t\t *\n\t\t * @return {object}\n\t\t */\n\t\tpageCtx() {\n\t\t\tconst c = this.cnWorkspaceContext\n\t\t\tconst unwrapped = (c && typeof c === 'object' && 'value' in c) ? c.value : c\n\t\t\treturn (unwrapped && typeof unwrapped === 'object') ? unwrapped : {}\n\t\t},\n\n\t\t/**\n\t\t * The unwrapped page-level app config map for `@config.*` token\n\t\t * resolution. Always an object (defaults to `{}`).\n\t\t *\n\t\t * @return {object}\n\t\t */\n\t\tconfigCtx() {\n\t\t\treturn unwrapAppConfig(this.cnAppConfig)\n\t\t},\n\n\t\t/**\n\t\t * Whether the tile is endpoint-bound (Wave 2): a `content.endpointSource`\n\t\t * with a `url` switches the value/loading/error surface to the shared\n\t\t * `useEndpointSource` engine. Exactly one of `source` | `endpointSource`\n\t\t * is allowed (validator-enforced); endpointSource wins when both slip\n\t\t * through.\n\t\t *\n\t\t * @return {boolean}\n\t\t */\n\t\tendpointMode() {\n\t\t\tconst es = this.content.endpointSource\n\t\t\treturn !!(es && es.url)\n\t\t},\n\n\t\t/**\n\t\t * The raw display value: in endpoint mode, the payload value plucked at\n\t\t * `content.valueField` (dot-path; omitted = the payload itself);\n\t\t * otherwise the OpenRegister-aggregated `value`.\n\t\t *\n\t\t * @return {unknown}\n\t\t */\n\t\tdisplayValue() {\n\t\t\tif (this.objectFieldMode) {\n\t\t\t\treturn this.objectFieldValue\n\t\t\t}\n\t\t\tif (!this.endpointMode) {\n\t\t\t\treturn this.value\n\t\t\t}\n\t\t\tconst v = getByPath(this.epData, this.content.valueField)\n\t\t\treturn v === undefined ? null : v\n\t\t},\n\n\t\t/**\n\t\t * Whether the headline is text rather than a number.\n\t\t *\n\t\t * The KPI card is built around a number: it never wraps and never\n\t\t * shrinks, because in a narrow tile the decoration should give way and\n\t\t * the figure should not. A NAME needs the opposite, so it gets a variant\n\t\t * that wraps and clamps, plus a title attribute for the full string.\n\t\t *\n\t\t * @return {boolean} true when the value is not numeric.\n\t\t */\n\t\tisTextValue() {\n\t\t\tconst v = this.displayValue\n\t\t\tif (v === null || v === undefined || v === '') {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\treturn !Number.isFinite(Number(v))\n\t\t},\n\n\t\t/**\n\t\t * Whether the tile renders its value as a status badge.\n\t\t *\n\t\t * @return {boolean} true when `content.display` is `'badge'`.\n\t\t */\n\t\tisBadge() {\n\t\t\treturn this.content.display === 'badge'\n\t\t},\n\n\t\t/**\n\t\t * Whether the tile renders its value as a time-remaining countdown.\n\t\t *\n\t\t * @return {boolean} true when `content.display` is `'countdown'`.\n\t\t */\n\t\tisCountdown() {\n\t\t\treturn this.content.display === 'countdown'\n\t\t},\n\n\t\t/**\n\t\t * The countdown block, or `{}`. `unit` is accepted and ignored: days is\n\t\t * the only unit this renders, and saying so is better than pretending\n\t\t * an hours or weeks mode exists.\n\t\t *\n\t\t * @return {object} The countdown config.\n\t\t */\n\t\tcountdownConfig() {\n\t\t\tconst cfg = this.content.countdown\n\t\t\treturn (cfg && typeof cfg === 'object') ? cfg : {}\n\t\t},\n\n\t\t/**\n\t\t * Whole LOCAL CALENDAR DAYS from today to the tile's value read as a\n\t\t * date. Positive is still to come, 0 is today, negative has passed.\n\t\t *\n\t\t * Zero is today because both ends are collapsed onto the calendar day\n\t\t * they fall on and then subtracted: a deadline dated today is the same\n\t\t * day as today, and the same day is a distance of nothing. Not 1 (which\n\t\t * would claim a day that is already being spent) and not −1 (which\n\t\t * would call a deadline that has not passed overdue).\n\t\t *\n\t\t * Null when the tile is not in countdown mode, or when the value holds\n\t\t * no readable date — which is what keeps `NaN` off the tile.\n\t\t *\n\t\t * @return {number|null} The signed day count, or null.\n\t\t */\n\t\tcountdownDays() {\n\t\t\tif (!this.isCountdown) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tconst due = calendarDay(this.displayValue)\n\t\t\tif (due === null) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tconst now = new Date()\n\t\t\tconst today = Date.UTC(now.getFullYear(), now.getMonth(), now.getDate())\n\t\t\treturn Math.round((due - today) / DAY_MS)\n\t\t},\n\n\t\t/**\n\t\t * The countdown sentence: the past wording for a date that has gone by,\n\t\t * the today wording for today, the future wording otherwise. `{n}` is\n\t\t * the number of days, never signed — \"−3 days left\" is exactly the\n\t\t * reading this mode exists to prevent.\n\t\t *\n\t\t * The built-in wordings carry their own singular, so a tile that\n\t\t * configures nothing still reads \"1 day left\" rather than \"1 days\n\t\t * left\". A configured `futureLabel` / `pastLabel` replaces both forms,\n\t\t * because a manifest author writing their own wording is the one who\n\t\t * knows how their language counts.\n\t\t *\n\t\t * @return {string} The sentence, or '' when there is nothing to count.\n\t\t */\n\t\tcountdownText() {\n\t\t\tconst days = this.countdownDays\n\t\t\tif (days === null) {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t\tconst cfg = this.countdownConfig\n\t\t\tif (days === 0) {\n\t\t\t\treturn this.effectiveTranslate(cfg.todayLabel || 'Today')\n\t\t\t}\n\t\t\tconst n = Math.abs(days)\n\t\t\tconst past = days < 0\n\t\t\tlet template = past ? cfg.pastLabel : cfg.futureLabel\n\t\t\tif (typeof template !== 'string' || template === '') {\n\t\t\t\tif (past) {\n\t\t\t\t\ttemplate = n === 1 ? 'Overdue by {n} day' : 'Overdue by {n} days'\n\t\t\t\t} else {\n\t\t\t\t\ttemplate = n === 1 ? '{n} day left' : '{n} days left'\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn this.effectiveTranslate(template).replace(/\\{n\\}/g, String(n))\n\t\t},\n\n\t\t/**\n\t\t * The colour the countdown itself asks for: error once the date has\n\t\t * passed or the day count is at or below `dangerAt`, warning at or\n\t\t * below `warnAt`, else ''.\n\t\t *\n\t\t * A passed date is the danger colour whether or not `dangerAt` is\n\t\t * configured: overdue is not a threshold anybody has to opt into. Both\n\t\t * thresholds are INCLUSIVE, and `dangerAt` is tested first, so exactly\n\t\t * 5 days with `dangerAt: 5` is danger and not warning even when\n\t\t * `warnAt` also matches.\n\t\t *\n\t\t * @return {string} 'error', 'warning', or ''.\n\t\t */\n\t\tcountdownVariant() {\n\t\t\tconst days = this.countdownDays\n\t\t\tif (days === null) {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t\tif (days < 0) {\n\t\t\t\treturn 'error'\n\t\t\t}\n\t\t\tconst cfg = this.countdownConfig\n\t\t\tif (Number.isFinite(cfg.dangerAt) && days <= cfg.dangerAt) {\n\t\t\t\treturn 'error'\n\t\t\t}\n\t\t\tif (Number.isFinite(cfg.warnAt) && days <= cfg.warnAt) {\n\t\t\t\treturn 'warning'\n\t\t\t}\n\t\t\treturn ''\n\t\t},\n\n\t\t/**\n\t\t * The first `content.overrides` entry whose `when` matches the BOUND\n\t\t * RECORD, or null. Needs a detail-page record: on a dashboard there is\n\t\t * nothing to test, so no override applies.\n\t\t *\n\t\t * @return {object|null} The matching override.\n\t\t */\n\t\tactiveOverride() {\n\t\t\tconst rules = this.content.overrides\n\t\t\tif (!Array.isArray(rules) || rules.length === 0) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tconst record = this.objectCtx?.object\n\t\t\tif (!record || typeof record !== 'object') {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\treturn rules.find((rule) => rule && this.matchesOverride(record, rule.when)) || null\n\t\t},\n\n\t\t/**\n\t\t * The translated `content.emptyText` when it applies, else ''.\n\t\t *\n\t\t * It applies to an empty value, and to an `objectField` reference whose\n\t\t * lookup found nothing. Without `emptyText` an unresolvable reference\n\t\t * keeps showing its raw value, as it always has.\n\t\t *\n\t\t * In countdown mode it applies to an UNREADABLE date as well, not only\n\t\t * to an absent one. `'not yet planned'` is a perfectly non-empty value\n\t\t * and there is no countdown to be had from it, so without this the tile\n\t\t * would print the raw string where a deadline belongs.\n\t\t *\n\t\t * @return {string} The text to show instead of the value, or ''.\n\t\t */\n\t\temptyValueText() {\n\t\t\tconst text = this.isCountdown\n\t\t\t\t? (this.countdownConfig.emptyText || this.content.emptyText)\n\t\t\t\t: this.content.emptyText\n\t\t\tif (typeof text !== 'string' || text === '') {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t\tconst v = this.displayValue\n\t\t\tconst empty = v === null || v === undefined || v === ''\n\t\t\tif (empty || (this.objectFieldMode && this.referenceFailed) || (this.isCountdown && this.countdownDays === null)) {\n\t\t\t\treturn this.effectiveTranslate(text)\n\t\t\t}\n\t\t\treturn ''\n\t\t},\n\n\t\t/**\n\t\t * The text the tile shows: an override's label, else the countdown\n\t\t * sentence, else the empty text, else the formatted value.\n\t\t *\n\t\t * The override sits above the countdown for the same reason it sits\n\t\t * above a badge's status: a suspended case is not waiting for its\n\t\t * deadline, so it reads as suspended.\n\t\t *\n\t\t * @return {string} The shown text.\n\t\t */\n\t\tshownValue() {\n\t\t\tconst override = this.activeOverride\n\t\t\tif (override && typeof override.label === 'string' && override.label !== '') {\n\t\t\t\treturn this.effectiveTranslate(override.label)\n\t\t\t}\n\t\t\treturn this.countdownText || this.emptyValueText || this.formattedValue\n\t\t},\n\n\t\t/**\n\t\t * Whether the shown text replaced the formatted value. Such a text is a\n\t\t * word, so it takes the wrapping text style of a name.\n\t\t *\n\t\t * @return {boolean} true when an override or the empty text is shown.\n\t\t */\n\t\tshownValueIsText() {\n\t\t\treturn this.shownValue !== this.formattedValue\n\t\t},\n\n\t\t/**\n\t\t * The variant the RESOLVED ROW asks for through\n\t\t * `objectField.resolve.variantField` / `variantMap`, or ''.\n\t\t *\n\t\t * @return {string} The variant name, or ''.\n\t\t */\n\t\trowVariant() {\n\t\t\tconst cfg = this.content.objectField\n\t\t\tconst resolve = (cfg && typeof cfg === 'object') ? cfg.resolve : null\n\t\t\tif (!resolve || !resolve.variantField || !this.referenceRow) {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t\tconst raw = getByPath(this.referenceRow, resolve.variantField)\n\t\t\tif (raw === undefined || raw === null) {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t\tconst map = resolve.variantMap\n\t\t\tif (map && typeof map === 'object') {\n\t\t\t\tconst hit = map[String(raw)]\n\t\t\t\treturn typeof hit === 'string' ? hit : ''\n\t\t\t}\n\t\t\treturn typeof raw === 'string' ? raw : ''\n\t\t},\n\n\t\t/**\n\t\t * The CnStatusBadge variant in badge mode. Same precedence as the text\n\t\t * colour: override, `variantWhen`, at-limit, resolved row, static\n\t\t * `variant`. The first one that names a badge variant wins.\n\t\t *\n\t\t * @return {string} A CnStatusBadge variant.\n\t\t */\n\t\tbadgeVariant() {\n\t\t\tconst rule = this.activeVariantRule\n\t\t\tconst candidates = [\n\t\t\t\tthis.activeOverride?.variant,\n\t\t\t\trule?.variant,\n\t\t\t\tthis.atLimit ? 'warning' : '',\n\t\t\t\tthis.rowVariant,\n\t\t\t\tthis.content.variant,\n\t\t\t]\n\t\t\tfor (const candidate of candidates) {\n\t\t\t\tconst variant = candidate === 'danger' ? 'error' : candidate\n\t\t\t\tif (BADGE_VARIANTS.includes(variant)) {\n\t\t\t\t\treturn variant\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn 'default'\n\t\t},\n\n\t\t/**\n\t\t * Whether the tile reads a field off the BOUND RECORD rather than\n\t\t * aggregating or calling an endpoint (`content.objectField`).\n\t\t *\n\t\t * The record is already loaded by the detail page, so this costs no\n\t\t * request at all. It is what lets a KPI row headline a case's type or\n\t\t * its assignee beside the counts, instead of those facts being buried\n\t\t * three rows down in the properties grid.\n\t\t *\n\t\t * @return {boolean} true in object-field mode.\n\t\t */\n\t\tobjectFieldMode() {\n\t\t\tconst of = this.content.objectField\n\t\t\treturn !!(of && (typeof of === 'string' || of.field))\n\t\t},\n\n\t\t/**\n\t\t * The bound record's value for `content.objectField`.\n\t\t *\n\t\t * A reference field holds a uuid, which is not something to show a\n\t\t * person, so `resolve` names the register/schema to look the label up in.\n\t\t * The resolved label replaces the uuid; an unresolvable id falls back to\n\t\t * the raw value rather than blanking, exactly as CnFkResolveCell does.\n\t\t *\n\t\t * @return {unknown} The field's value, or null.\n\t\t */\n\t\t/**\n\t\t * The bound record's raw value for `content.objectField`, before any\n\t\t * reference resolution.\n\t\t *\n\t\t * @return {unknown} The raw field value, or null.\n\t\t */\n\t\tobjectFieldRaw() {\n\t\t\tconst cfg = this.content.objectField\n\t\t\tconst field = typeof cfg === 'string' ? cfg : cfg?.field\n\t\t\tconst record = this.objectCtx?.object\n\t\t\tif (!record || !field) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tconst raw = getByPath(record, field)\n\t\t\treturn (raw === undefined || raw === '') ? null : raw\n\t\t},\n\n\t\t/**\n\t\t * @return {unknown} The field's value, or null.\n\t\t */\n\t\tobjectFieldValue() {\n\t\t\tif (this.objectFieldRaw === null) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\t// An unresolved or unresolvable reference falls back to the raw value\n\t\t\t// rather than blanking, the same way CnFkResolveCell does.\n\t\t\treturn this.referenceLabel !== null ? this.referenceLabel : this.objectFieldRaw\n\t\t},\n\n\t\t/**\n\t\t * Loading state for the active source (endpoint or OpenRegister).\n\t\t *\n\t\t * @return {boolean}\n\t\t */\n\t\tdisplayLoading() {\n\t\t\t// A reference lookup is a request like any other, and it is the only\n\t\t\t// one the record mode makes. Leaving it out meant the tile rendered\n\t\t\t// the raw uuid as if it were the answer while the request was still\n\t\t\t// out.\n\t\t\tif (this.objectFieldMode) {\n\t\t\t\treturn this.referencePending\n\t\t\t}\n\t\t\treturn this.endpointMode ? this.epLoading : this.loading\n\t\t},\n\n\t\t/**\n\t\t * Error message for the active source ('' = none).\n\t\t *\n\t\t * @return {string}\n\t\t */\n\t\tdisplayError() {\n\t\t\treturn this.endpointMode ? this.epError : this.error\n\t\t},\n\n\t\t/**\n\t\t * The previous-period value plucked at `content.previousField`\n\t\t * (endpoint mode only), or null when not configured / not numeric.\n\t\t *\n\t\t * @return {number|null}\n\t\t */\n\t\tpreviousValue() {\n\t\t\tif (!this.endpointMode || !this.content.previousField) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tconst v = Number(getByPath(this.epData, this.content.previousField))\n\t\t\treturn Number.isFinite(v) ? v : null\n\t\t},\n\n\t\t/**\n\t\t * Trend percent for the sublabel (the pipelinq KPI contract): a\n\t\t * server-computed percent plucked at `content.deltaField` when set,\n\t\t * else the client-computed change vs `previousField`\n\t\t * (`(current − previous) ÷ |previous| × 100`). Null when the trend is\n\t\t * not configured or not computable (previous of 0, non-numeric values).\n\t\t *\n\t\t * @return {number|null}\n\t\t */\n\t\ttrendPct() {\n\t\t\tif (!this.endpointMode) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tif (this.content.deltaField) {\n\t\t\t\tconst v = Number(getByPath(this.epData, this.content.deltaField))\n\t\t\t\treturn Number.isFinite(v) ? v : null\n\t\t\t}\n\t\t\tconst prev = this.previousValue\n\t\t\tconst cur = Number(this.displayValue)\n\t\t\tif (prev === null || prev === 0 || !Number.isFinite(cur)) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\treturn ((cur - prev) / Math.abs(prev)) * 100\n\t\t},\n\n\t\t/** The signed trend percent, e.g. \"+12.3%\". */\n\t\tformattedTrend() {\n\t\t\tif (this.trendPct === null) {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t\tconst sign = this.trendPct > 0 ? '+' : ''\n\t\t\treturn `${sign}${this.trendPct.toFixed(1)}%`\n\t\t},\n\n\t\t/** The arrow component for the trend direction. */\n\t\ttrendIcon() {\n\t\t\tif (this.trendPct === null || Math.abs(this.trendPct) < 0.05) {\n\t\t\t\treturn 'TrendingNeutral'\n\t\t\t}\n\t\t\treturn this.trendPct > 0 ? 'TrendingUp' : 'TrendingDown'\n\t\t},\n\n\t\t/**\n\t\t * Green when the trend moves in `content.goodDirection` (default\n\t\t * 'up'), red otherwise, neutral for a ~0 change — the CnDeltaWidget\n\t\t * convention.\n\t\t *\n\t\t * @return {string}\n\t\t */\n\t\ttrendColor() {\n\t\t\tif (this.trendPct === null || Math.abs(this.trendPct) < 0.05) {\n\t\t\t\treturn 'var(--color-text-maxcontrast)'\n\t\t\t}\n\t\t\tconst good = this.content.goodDirection || 'up'\n\t\t\tconst rising = this.trendPct > 0\n\t\t\tconst isGood = good === 'up' ? rising : !rising\n\t\t\treturn isGood ? STATUS_TEXT_COLORS.success : STATUS_TEXT_COLORS.error\n\t\t},\n\n\t\t/**\n\t\t * The first `content.variantWhen` rule matching the current display\n\t\t * value (first-match wins), or null. Each rule is\n\t\t * `{ op: eq|neq|gt|gte|lt|lte, value, variant, icon? }`.\n\t\t *\n\t\t * @return {object|null}\n\t\t */\n\t\tactiveVariantRule() {\n\t\t\tconst rules = this.content.variantWhen\n\t\t\tif (!Array.isArray(rules) || rules.length === 0) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tconst current = this.displayValue\n\t\t\tif (current === null || current === undefined) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\treturn rules.find((r) => r && this.matchesRule(current, r)) || null\n\t\t},\n\n\t\t/**\n\t\t * The CSS colour for the matched variant rule ('' = keep the\n\t\t * configured colours).\n\t\t *\n\t\t * @return {string}\n\t\t */\n\t\tvariantColor() {\n\t\t\t// An override describes the RECORD's state (a suspended case), which\n\t\t\t// outranks anything the value itself suggests.\n\t\t\tconst override = this.activeOverride\n\t\t\tif (override && override.variant) {\n\t\t\t\treturn VARIANT_COLORS[override.variant] || ''\n\t\t\t}\n\t\t\tconst rule = this.activeVariantRule\n\t\t\tif (rule && rule.variant) {\n\t\t\t\treturn VARIANT_COLORS[rule.variant] || ''\n\t\t\t}\n\t\t\t// The countdown's own threshold sits below `variantWhen`, which is\n\t\t\t// the author naming a colour outright, and above the at-limit tint,\n\t\t\t// which is the generic one. A passed date reports `error` from here\n\t\t\t// whether or not a threshold was configured.\n\t\t\tif (this.countdownVariant) {\n\t\t\t\treturn VARIANT_COLORS[this.countdownVariant] || ''\n\t\t\t}\n\t\t\t// An explicit variantWhen rule always wins: a tile that says how it\n\t\t\t// wants to be coloured is not overruled by the generic at-limit tint.\n\t\t\tif (this.atLimit) {\n\t\t\t\treturn VARIANT_COLORS.warning || ''\n\t\t\t}\n\t\t\t// The resolved row's colour sits just above the static floor. An\n\t\t\t// unknown name falls through rather than blanking the tile.\n\t\t\tif (this.rowVariant && VARIANT_COLORS[this.rowVariant]) {\n\t\t\t\treturn VARIANT_COLORS[this.rowVariant]\n\t\t\t}\n\t\t\t// A STATIC `variant` is the floor, below both of the above: it is the\n\t\t\t// tile's resting colour, not a signal about the current value, so a\n\t\t\t// threshold rule or an at-limit warning must be able to override it.\n\t\t\t//\n\t\t\t// It exists because that is how CnStatsBlock has always been coloured\n\t\t\t// (`variant=\"success\"`), and a tile migrating from a bespoke card to\n\t\t\t// this component would otherwise silently lose its colour — a change\n\t\t\t// nothing would report, on a dashboard where colour is the fastest\n\t\t\t// thing a reader takes in.\n\t\t\tif (this.content.variant) {\n\t\t\t\treturn VARIANT_COLORS[this.content.variant] || ''\n\t\t\t}\n\t\t\treturn ''\n\t\t},\n\n\t\t/**\n\t\t * The icon shown in the circle: a matched variant rule's `icon`\n\t\t * override, else `content.icon`.\n\t\t *\n\t\t * @return {string}\n\t\t */\n\t\tresolvedIcon() {\n\t\t\tconst override = this.activeOverride\n\t\t\tconst rule = this.activeVariantRule\n\t\t\treturn (override && override.icon) || (rule && rule.icon) || this.content.icon || ''\n\t\t},\n\n\t\t/**\n\t\t * Card orientation. Horizontal (icon beside the number) is the\n\t\t * canonical KPI card; `content.layout: 'vertical'` stacks the icon\n\t\t * above a centred number for a tile taller than it is wide;\n\t\t * `content.layout: 'stacked'` is the board look (see `isStacked`).\n\t\t *\n\t\t * @spec openspec/changes/zuiddrecht-pixel-gaps-2/specs/zuiddrecht-pixel-gaps-2/spec.md#requirement-a-stat-tile-can-take-the-stacked-board-look\n\t\t * @return {'horizontal'|'vertical'|'stacked'}\n\t\t */\n\t\tcardLayout() {\n\t\t\tconst layout = (this.content || {}).layout\n\t\t\tif (layout === 'vertical' || layout === 'stacked') {\n\t\t\t\treturn layout\n\t\t\t}\n\t\t\t// Board look: every KPI tile on the screens is stacked, so a tile\n\t\t\t// that names no layout takes it. An explicit `horizontal` stays.\n\t\t\tif (this.isBoardLook && layout === undefined) {\n\t\t\t\treturn 'stacked'\n\t\t\t}\n\t\t\treturn 'horizontal'\n\t\t},\n\n\t\t/**\n\t\t * Whether the board look draws the icon in a tinted circle at the\n\t\t * right of the label row (`content.iconPlacement: \"end\"`), as the\n\t\t * DqDashboard tiles. Off without the board look and without an icon.\n\t\t *\n\t\t * @spec openspec/changes/screens-stat-tile-parity/specs/dashboard-page/spec.md#requirement-the-board-kpi-tile-can-carry-its-icon-at-the-end\n\t\t * @return {boolean}\n\t\t */\n\t\thasEndBadge() {\n\t\t\treturn this.isBoardLook\n\t\t\t\t&& (this.content || {}).iconPlacement === 'end'\n\t\t\t\t&& Boolean(this.resolvedIcon)\n\t\t},\n\n\t\t/**\n\t\t * The tile's state as a tone name for the end badge: the variant the\n\t\t * value colour comes from (`success`, `warning`, `error`), else\n\t\t * `primary`. A custom `valueColor` has no tone and reads as primary.\n\t\t *\n\t\t * @spec openspec/changes/screens-stat-tile-parity/specs/dashboard-page/spec.md#requirement-the-board-kpi-tile-can-carry-its-icon-at-the-end\n\t\t * @return {'primary'|'success'|'warning'|'error'}\n\t\t */\n\t\tstateTone() {\n\t\t\tconst color = this.variantColor\n\t\t\tif (!color) {\n\t\t\t\treturn 'primary'\n\t\t\t}\n\t\t\tconst tone = ['success', 'warning', 'error'].find((name) => VARIANT_COLORS[name] === color)\n\t\t\treturn tone || 'primary'\n\t\t},\n\n\t\t/**\n\t\t * Whether the tile takes the stacked board look (`content.layout:\n\t\t * \"stacked\"`): a plain muted label, the number at 34px in the text\n\t\t * colour, the caption on a line of its own, and no icon circle. Off by\n\t\t * default.\n\t\t *\n\t\t * @spec openspec/changes/zuiddrecht-pixel-gaps-2/specs/zuiddrecht-pixel-gaps-2/spec.md#requirement-a-stat-tile-can-take-the-stacked-board-look\n\t\t * @return {boolean}\n\t\t */\n\t\tisStacked() {\n\t\t\treturn this.cardLayout === 'stacked'\n\t\t},\n\n\t\t/**\n\t\t * Whether the card draws no box of its own. On by default: every stat\n\t\t * tile is rendered inside a CnWidgetWrapper that already draws a card,\n\t\t * so a second box is a card inside a card. Set `content.flat: false`\n\t\t * for a tile mounted somewhere with no wrapper around it.\n\t\t *\n\t\t * @return {boolean}\n\t\t */\n\t\tflat() {\n\t\t\treturn (this.content || {}).flat !== false\n\t\t},\n\n\t\t/** Inline style for the icon circle (variant rule wins over iconColor). */\n\t\ticonCircleStyle() {\n\t\t\tconst color = this.variantColor || this.content.iconColor || this.content.valueColor || 'var(--color-primary-element)'\n\t\t\treturn { color, backgroundColor: this.tint(color) }\n\t\t},\n\n\t\t/** Inline style for the value text (variant rule wins over valueColor). */\n\t\tvalueStyle() {\n\t\t\tconst color = this.variantColor || this.content.valueColor\n\t\t\treturn color ? { color } : {}\n\t\t},\n\n\t\t/**\n\t\t * The formatted value string per the `content.format` spec. Resolves\n\t\t * `@config.<key>` tokens (e.g. `currency: '@config.currency'`) against the\n\t\t * page-level app config and guards the currency code, so an unresolved\n\t\t * token or invalid currency falls back to a safe default instead of\n\t\t * throwing. See `formatMetricValue`.\n\t\t *\n\t\t * @return {string}\n\t\t */\n\t\tformattedValue() {\n\t\t\treturn formatMetricValue(this.displayValue, this.content.format, this.configCtx, this.objectCtx?.object || null)\n\t\t},\n\n\t\t/**\n\t\t * The capacity this tile is measured against — `content.limitField`\n\t\t * (dot-path into the endpoint payload, so a server-configured quota is\n\t\t * read live) or a static `content.limit`. Null when neither is set or\n\t\t * the resolved value is not a finite number, which is what keeps the\n\t\t * \"value / limit\" rendering off every tile that has no limit.\n\t\t *\n\t\t * @return {number|null}\n\t\t */\n\t\tlimitValue() {\n\t\t\tlet raw = this.content.limit\n\t\t\tif (this.endpointMode && this.content.limitField) {\n\t\t\t\traw = getByPath(this.epData, this.content.limitField)\n\t\t\t}\n\t\t\tconst n = Number(raw)\n\t\t\treturn Number.isFinite(n) ? n : null\n\t\t},\n\n\t\t/**\n\t\t * The limit rendered beside the value, e.g. the \"100\" in \"0 / 100\".\n\t\t * Formatted with the value's own `format` spec minus prefix/suffix —\n\t\t * a suffix belongs to the pair, not to each half, so \"0 % / 100 %\" is\n\t\t * never produced.\n\t\t *\n\t\t * @return {string}\n\t\t */\n\t\tformattedLimit() {\n\t\t\tif (this.limitValue === null) {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t\tconst { prefix, suffix, ...rest } = (this.content.format || {})\n\t\t\treturn formatMetricValue(this.limitValue, rest, this.configCtx, this.objectCtx?.object || null)\n\t\t},\n\n\t\t/**\n\t\t * Whether the tile has reached or passed its limit. Drives the warning\n\t\t * tint when no explicit `variantWhen` rule already claims the colour.\n\t\t *\n\t\t * @return {boolean}\n\t\t */\n\t\tatLimit() {\n\t\t\tif (this.limitValue === null) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\tconst current = Number(this.displayValue)\n\t\t\treturn Number.isFinite(current) && current >= this.limitValue\n\t\t},\n\n\t\t/**\n\t\t * The tile's own range presets (`content.dateRange.presets`). Empty when\n\t\t * the tile has no override, which is also what hides the picker.\n\t\t *\n\t\t * @return {Array<{id: string, label?: string, from?: string, to?: string}>}\n\t\t */\n\t\trangePresets() {\n\t\t\tconst presets = this.content.dateRange?.presets\n\t\t\treturn Array.isArray(presets) ? presets.filter(Boolean) : []\n\t\t},\n\n\t\t/**\n\t\t * The preset id currently selected — the tile's own override when set,\n\t\t * else whatever the dashboard range reports, so the picker opens showing\n\t\t * the page's period rather than a stale default.\n\t\t *\n\t\t * @return {string}\n\t\t */\n\t\tactiveRangePreset() {\n\t\t\treturn (this.tileRange || this.activeRange() || {}).preset || ''\n\t\t},\n\n\t\t/** Accessible name for the range picker (no visible label on a compact tile). */\n\t\trangeAriaLabel() {\n\t\t\tconst label = this.resolvedLabel || this.effectiveTranslate('Date range')\n\t\t\treturn `${label} — ${this.effectiveTranslate('date range')}`\n\t\t},\n\n\t\t/** Stable signature of the data source so the watcher only refetches on real change. */\n\t\tsourceKey() {\n\t\t\treturn JSON.stringify({\n\t\t\t\ts: this.content.source || {},\n\t\t\t\to: this.objectCtx ? this.objectCtx.objectId : null,\n\t\t\t\tp: this.pageCtx,\n\t\t\t\tc: this.configCtx,\n\t\t\t})\n\t\t},\n\t},\n\n\twatch: {\n\t\tsourceKey() {\n\t\t\tthis.fetchValue()\n\t\t},\n\n\t\tobjectFieldRaw: {\n\t\t\timmediate: true,\n\t\t\thandler() {\n\t\t\t\tthis.resolveReference()\n\t\t\t},\n\t\t},\n\t},\n\n\tmounted() {\n\t\tthis.fetchValue()\n\t\t// The `endpointSource` path refreshes through useEndpointSource; this\n\t\t// covers the `source` path, which otherwise never re-read on Refresh.\n\t\tthis._onPageRefresh = (payload) => {\n\t\t\tif (this.endpointMode) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst done = this.fetchValue(payload)\n\t\t\tpayload?.waitUntil?.(done)\n\t\t}\n\t\tsubscribe(PAGE_REFRESH_CHANNEL, this._onPageRefresh)\n\t},\n\n\tbeforeUnmount() {\n\t\tunsubscribe(PAGE_REFRESH_CHANNEL, this._onPageRefresh)\n\t},\n\n\tmethods: {\n\t\t/**\n\t\t * Resolve an `objectField` that holds a reference uuid to the referenced\n\t\t * object's label, through the shared object store (per-schema caching and\n\t\t * in-flight dedup come for free).\n\t\t *\n\t\t * Does nothing unless `objectField.resolve` names a register and schema:\n\t\t * a plain scalar field needs no lookup, and guessing that a string looks\n\t\t * like a uuid would turn a legitimate identifier into a failed fetch.\n\t\t *\n\t\t * @return {Promise<void>}\n\t\t */\n\t\tasync resolveReference() {\n\t\t\tthis.referenceLabel = null\n\t\t\tthis.referenceRow = null\n\t\t\tthis.referenceFailed = false\n\t\t\tthis.referencePending = false\n\t\t\tconst cfg = this.content.objectField\n\t\t\tconst resolve = (cfg && typeof cfg === 'object') ? cfg.resolve : null\n\t\t\tconst raw = this.objectFieldRaw\n\t\t\tif (!resolve || !resolve.register || !resolve.schema || !raw) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\t// Assigned by the try below, and the catch returns rather than falling\n\t\t\t// through, so an initialiser here would never be read.\n\t\t\tlet store\n\t\t\ttry {\n\t\t\t\tstore = useObjectStore()\n\t\t\t} catch {\n\t\t\t\t// No active Pinia: the tile shows the raw value, which is correct\n\t\t\t\t// and never blank.\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif (!store) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tconst type = resolveObjectOpType(store, { register: resolve.register, schema: resolve.schema })\n\t\t\tconst id = String(raw)\n\t\t\tconst cached = store.objects && store.objects[type] && store.objects[type][id]\n\t\t\t// Only an actual request pends. A cache hit resolves in the same\n\t\t\t// tick, and flagging it would flicker a loading icon for nothing.\n\t\t\tif (!cached) {\n\t\t\t\tthis.referencePending = true\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tconst obj = cached || await store.fetchObject(type, id)\n\t\t\t\t// The record may have moved on while the lookup was in flight.\n\t\t\t\t// The newer call owns the state, so this one touches nothing.\n\t\t\t\tif (String(this.objectFieldRaw) !== id) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tthis.referencePending = false\n\t\t\t\tif (obj && typeof obj === 'object') {\n\t\t\t\t\tthis.referenceRow = obj\n\t\t\t\t}\n\t\t\t\tconst label = this.pickReferenceLabel(obj, resolve.labelField)\n\t\t\t\tif (label) {\n\t\t\t\t\tthis.referenceLabel = label\n\t\t\t\t} else {\n\t\t\t\t\tthis.referenceFailed = true\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\t// Leave the raw value showing, unless `emptyText` says otherwise.\n\t\t\t\tif (String(this.objectFieldRaw) === id) {\n\t\t\t\t\tthis.referencePending = false\n\t\t\t\t\tthis.referenceFailed = true\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Whether an override's `when` matches the bound record. Uses the local\n\t\t * `visibleWhen` grammar (`{ field, op, value }`); a `when` with neither\n\t\t * `op` nor `value` is a truthiness test on the field.\n\t\t *\n\t\t * @param {object} record The bound record.\n\t\t * @param {{field: string, op?: string, value?: unknown}} when The condition.\n\t\t * @return {boolean} True when the override applies.\n\t\t */\n\t\tmatchesOverride(record, when) {\n\t\t\tif (!when || typeof when !== 'object' || typeof when.field !== 'string' || when.field === '') {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\tconst compares = Object.hasOwn(when, 'value') || Boolean(when.op)\n\t\t\tif (!compares) {\n\t\t\t\treturn Boolean(readVisibleWhenPath(record, when.field))\n\t\t\t}\n\t\t\treturn evaluateVisibleWhenLocal(when, record)\n\t\t},\n\n\t\t/**\n\t\t * Pick a display label off a resolved reference: the configured field\n\t\t * first, then `title`, then `@self.name`. A per-language map collapses to\n\t\t * its first non-empty value.\n\t\t *\n\t\t * @param {object|null} obj The referenced object.\n\t\t * @param {string} [labelField] The preferred label property.\n\t\t * @return {string} The label, or '' when none is usable.\n\t\t */\n\t\tpickReferenceLabel(obj, labelField) {\n\t\t\tif (!obj || typeof obj !== 'object') {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t\tconst candidates = [obj[labelField || 'title'], obj.title, obj.name, obj['@self'] && obj['@self'].name]\n\t\t\tfor (const value of candidates) {\n\t\t\t\tif (typeof value === 'string' && value !== '') {\n\t\t\t\t\treturn value\n\t\t\t\t}\n\t\t\t\tif (typeof value === 'number') {\n\t\t\t\t\treturn String(value)\n\t\t\t\t}\n\t\t\t\tif (value && typeof value === 'object' && !Array.isArray(value)) {\n\t\t\t\t\tconst first = Object.values(value).find((v) => typeof v === 'string' && v !== '')\n\t\t\t\t\tif (first) {\n\t\t\t\t\t\treturn first\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn ''\n\t\t},\n\n\t\t/**\n\t\t * Derive a faint background tint for the icon circle from a colour.\n\t\t * Falls back to the NC light primary token for CSS variables / unknowns.\n\t\t *\n\t\t * @param {string} color The base colour (hex or CSS var).\n\t\t * @return {string} A translucent or token background.\n\t\t */\n\t\t/**\n\t\t * Apply a per-tile range preset. Writes the tile override, which the\n\t\t * endpoint ctx reads, so the tile refetches on its own period while the\n\t\t * rest of the dashboard stays on the page range.\n\t\t *\n\t\t * @param {string} presetId The chosen preset's id.\n\t\t * @return {void}\n\t\t */\n\t\tselectRange(presetId) {\n\t\t\tconst preset = this.rangePresets.find((p) => p.id === presetId)\n\t\t\tif (!preset) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.tileRange = { preset: preset.id, from: preset.from ?? null, to: preset.to ?? null }\n\t\t},\n\n\t\ttint(color) {\n\t\t\tif (typeof color === 'string' && /^#([0-9a-f]{6})$/i.test(color)) {\n\t\t\t\treturn color + '1f' // ~12% alpha\n\t\t\t}\n\t\t\treturn 'var(--color-primary-element-light, rgba(0,130,201,0.1))'\n\t\t},\n\n\t\t/**\n\t\t * Whether a `variantWhen` rule matches the current value. Numeric\n\t\t * comparison when both sides coerce to numbers; `eq` / `neq` fall back\n\t\t * to strict string equality for non-numeric values.\n\t\t *\n\t\t * @param {unknown} current The current display value.\n\t\t * @param {{op: string, value: unknown}} rule The threshold rule.\n\t\t * @return {boolean} True when the rule matches.\n\t\t */\n\t\tmatchesRule(current, rule) {\n\t\t\tconst a = Number(current)\n\t\t\tconst b = Number(rule.value)\n\t\t\tconst numeric = Number.isFinite(a) && Number.isFinite(b)\n\t\t\tswitch (rule.op) {\n\t\t\t\tcase 'eq': return numeric ? a === b : String(current) === String(rule.value)\n\t\t\t\tcase 'neq': return numeric ? a !== b : String(current) !== String(rule.value)\n\t\t\t\tcase 'gt': return numeric && a > b\n\t\t\t\tcase 'gte': return numeric && a >= b\n\t\t\t\tcase 'lt': return numeric && a < b\n\t\t\t\tcase 'lte': return numeric && a <= b\n\t\t\t\tdefault: return false\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Flatten a filter map into `filter[key]=value` / `filter[key][op]=value`\n\t\t * query params (operator-aware, matching the OpenRegister vocabulary).\n\t\t *\n\t\t * @param {object} target The params object to write into.\n\t\t * @param {object} filter The filter map.\n\t\t * @return {void}\n\t\t */\n\t\tflattenFilter(target, filter) {\n\t\t\tif (!filter || typeof filter !== 'object') {\n\t\t\t\treturn\n\t\t\t}\n\t\t\t// Resolve `@objectId` / `@object.*` (detail page), `@workspace.*`\n\t\t\t// (page-level context — e.g. the dashboard date-range pills publish\n\t\t\t// `dateFrom` / `dateTo`) AND `@config.*` (page-level app config), then\n\t\t\t// drop any optional `@workspace.<key>?` / `@config.<key>?` that stayed\n\t\t\t// unresolved so an unset value omits the filter (show all) instead of\n\t\t\t// sending a literal token.\n\t\t\tconst ctx = { ...(this.objectCtx || {}), workspace: this.pageCtx, config: this.configCtx }\n\t\t\tfilter = dropOptionalUnresolved(resolveFilterTokens(filter, ctx))\n\t\t\tfor (const [k, v] of Object.entries(filter)) {\n\t\t\t\tif (v && typeof v === 'object') {\n\t\t\t\t\tfor (const [op, ov] of Object.entries(v)) {\n\t\t\t\t\t\ttarget[`filter[${k}][${op}]`] = ov\n\t\t\t\t\t}\n\t\t\t\t} else if (v !== '' && v !== null && v !== undefined) {\n\t\t\t\t\ttarget[`filter[${k}]`] = v\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Fetch one scalar from the OpenRegister `/value` aggregation endpoint.\n\t\t *\n\t\t * @param {object} axios The axios instance.\n\t\t * @param {(url: string, params?: object) => string} generateUrl The router helper.\n\t\t * @param {object} s The source (register/schema).\n\t\t * @param {string} metric The aggregation metric.\n\t\t * @param {?string} field The numeric field (non-count metrics).\n\t\t * @param {object} filter The filter map.\n\t\t * @return {Promise<number|null>} The aggregated value.\n\t\t */\n\t\tasync fetchAggregate(axios, generateUrl, s, metric, field, filter) {\n\t\t\tconst url = generateUrl(\n\t\t\t\t'/apps/openregister/api/objects/aggregations/{register}/{schema}/value',\n\t\t\t\t{ register: s.register, schema: s.schema },\n\t\t\t)\n\t\t\tconst params = { metric: metric || 'count' }\n\t\t\tif (field) {\n\t\t\t\tparams.field = field\n\t\t\t}\n\t\t\tthis.flattenFilter(params, filter)\n\t\t\tconst res = await axios.get(url, { params })\n\t\t\treturn res?.data?.value ?? null\n\t\t},\n\n\t\t/**\n\t\t * Resolve the widget's value from its `source`. Supports three source\n\t\t * kinds (ADR-041): a plain `aggregate` (count/sum/avg/min/max with\n\t\t * operator filters), a `ratio` (numerator ÷ denominator × 100, e.g. a\n\t\t * win-rate), and a `weighted` sum (Σ field × weightField ÷ divisor,\n\t\t * computed client-side over the fetched objects). Lazily imports\n\t\t * axios/router (same pattern as CnFilesWidget).\n\t\t *\n\t\t * @param {object} [refresh] The page refresh event's payload, when this is one.\n\t\t * @return {Promise<void>}\n\t\t */\n\t\tasync fetchValue(refresh) {\n\t\t\t// Endpoint-bound tiles are fetched by the shared useEndpointSource\n\t\t\t// engine (see setup) — the OpenRegister paths below must not fire.\n\t\t\tif (this.endpointMode) {\n\t\t\t\tthis.value = null\n\t\t\t\tthis.error = ''\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst s = this.content.source || {}\n\t\t\t// An `endpoint` source reads an arbitrary app REST endpoint instead\n\t\t\t// of OpenRegister's per-schema aggregation, so it needs no register/schema.\n\t\t\tif (s.kind !== 'endpoint' && (!s.register || !s.schema)) {\n\t\t\t\tthis.value = null\n\t\t\t\tthis.error = ''\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif (s.kind === 'endpoint' && !s.url) {\n\t\t\t\tthis.value = null\n\t\t\t\tthis.error = ''\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.loading = true\n\t\t\tthis.error = ''\n\t\t\ttry {\n\t\t\t\tconst [{ default: axios }, { generateUrl }] = await Promise.all([\n\t\t\t\t\timport('@nextcloud/axios'),\n\t\t\t\t\timport('@nextcloud/router'),\n\t\t\t\t])\n\n\t\t\t\tif (s.kind === 'endpoint') {\n\t\t\t\t\tthis.value = await this.fetchEndpoint(s, refresh)\n\t\t\t\t} else if (s.kind === 'ratio') {\n\t\t\t\t\tconst num = await this.fetchAggregate(axios, generateUrl, s, s.metric, s.field, (s.numerator && s.numerator.filter) || {})\n\t\t\t\t\tconst den = await this.fetchAggregate(axios, generateUrl, s, s.metric, s.field, (s.denominator && s.denominator.filter) || {})\n\t\t\t\t\tthis.value = (den && Number(den) !== 0) ? (Number(num) / Number(den)) * 100 : null\n\t\t\t\t} else if (s.kind === 'computed') {\n\t\t\t\t\t// Fetch each named part, then evaluate the formula over them.\n\t\t\t\t\tconst { evalFormula } = await import('../../utils/evalFormula.js')\n\t\t\t\t\tconst parts = s.parts || {}\n\t\t\t\t\tconst vars = {}\n\t\t\t\t\tfor (const [name, p] of Object.entries(parts)) {\n\t\t\t\t\t\tvars[name] = Number(await this.fetchAggregate(axios, generateUrl, s, p.metric || 'count', p.field, p.filter || {})) || 0\n\t\t\t\t\t}\n\t\t\t\t\tthis.value = evalFormula(s.formula || '', vars)\n\t\t\t\t} else if (s.kind === 'weighted') {\n\t\t\t\t\tthis.value = await this.fetchWeighted(axios, generateUrl, s)\n\t\t\t\t} else {\n\t\t\t\t\tthis.value = await this.fetchAggregate(axios, generateUrl, s, s.metric, s.field, s.filter || {})\n\t\t\t\t}\n\t\t\t} catch (e) {\n\t\t\t\tthis.error = (e && e.message) || 'error'\n\t\t\t\tthis.value = null\n\t\t\t} finally {\n\t\t\t\tthis.loading = false\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Compute a weighted sum `Σ (field × weightField) ÷ divisor` client-side\n\t\t * (no OpenRegister expression-aggregation primitive yet). Pulls the\n\t\t * matching objects (capped at `limit`, default 1000) and folds them.\n\t\t *\n\t\t * @param {object} axios The axios instance.\n\t\t * @param {(url: string, params?: object) => string} generateUrl The router helper.\n\t\t * @param {object} s The weighted source `{ field, weightField, divisor?, filter?, limit? }`.\n\t\t * @return {Promise<number|null>} The weighted sum.\n\t\t */\n\t\tasync fetchWeighted(axios, generateUrl, s) {\n\t\t\tif (!s.field || !s.weightField) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tconst url = generateUrl(\n\t\t\t\t'/apps/openregister/api/objects/{register}/{schema}',\n\t\t\t\t{ register: s.register, schema: s.schema },\n\t\t\t)\n\t\t\tconst params = { _limit: s.limit || 1000 }\n\t\t\tthis.flattenFilter(params, s.filter || {})\n\t\t\tconst res = await axios.get(url, { params })\n\t\t\tconst rows = (res && res.data && res.data.results) || []\n\t\t\tconst divisor = Number(s.divisor) || 1\n\t\t\tlet sum = 0\n\t\t\tfor (const r of rows) {\n\t\t\t\tconst v = Number(r[s.field])\n\t\t\t\tconst w = Number(r[s.weightField])\n\t\t\t\tif (Number.isFinite(v) && Number.isFinite(w)) {\n\t\t\t\t\tsum += (v * w) / divisor\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn sum\n\t\t},\n\n\t\t/**\n\t\t * Resolve `@page.<key>` / `@workspace.<key>` / `@config.<key>` /\n\t\t * `@objectId` / `@object.<field>` tokens inside a string against the page\n\t\t * + config + object contexts. `@page.*` is an alias for `@workspace.*`\n\t\t * (both read the page-level context); `@config.*` reads the page-level app\n\t\t * config. Unresolved tokens collapse to an empty string so a half-built\n\t\t * URL never sends a literal `@page.period`.\n\t\t *\n\t\t * @param {string} str The raw string (URL or param value).\n\t\t * @return {string} The interpolated string.\n\t\t */\n\t\tinterpolateTokens(str) {\n\t\t\tif (typeof str !== 'string') {\n\t\t\t\treturn str\n\t\t\t}\n\t\t\treturn str.replace(/@(page|workspace)\\.([A-Za-z0-9_]+)/g, (_, _ns, key) => {\n\t\t\t\tconst v = this.pageCtx[key]\n\t\t\t\treturn (v === undefined || v === null) ? '' : String(v)\n\t\t\t}).replace(/@config\\.([A-Za-z0-9_]+)/g, (_, key) => {\n\t\t\t\tconst v = this.configCtx[key]\n\t\t\t\treturn (v === undefined || v === null) ? '' : String(v)\n\t\t\t}).replace(/@objectId/g, () => {\n\t\t\t\tconst id = this.objectCtx && this.objectCtx.objectId\n\t\t\t\treturn (id === undefined || id === null) ? '' : String(id)\n\t\t\t}).replace(/@object\\.([A-Za-z0-9_]+)/g, (_, field) => {\n\t\t\t\tconst v = this.objectCtx && this.objectCtx.object && this.objectCtx.object[field]\n\t\t\t\treturn (v === undefined || v === null) ? '' : String(v)\n\t\t\t})\n\t\t},\n\n\t\t/**\n\t\t * Read a dot-path off an object (e.g. `\"data.totalLeads\"`, `\"summary.0.count\"`).\n\t\t * Returns undefined when any segment is missing.\n\t\t *\n\t\t * @param {object} obj The source object.\n\t\t * @param {string} path The dot-path.\n\t\t * @return {unknown} The resolved value or undefined.\n\t\t */\n\t\tgetByPath(obj, path) {\n\t\t\t// Delegates to the shared useEndpointSource util so the legacy\n\t\t\t// `source.kind: 'endpoint'` path and the Wave-2 `endpointSource`\n\t\t\t// path pluck identically.\n\t\t\treturn getByPath(obj, path)\n\t\t},\n\n\t\t/**\n\t\t * Fetch a single value from an arbitrary app REST endpoint. The `url` and\n\t\t * any string `params` value are token-interpolated (`@page.*` etc.), the\n\t\t * response is read at `path` (dot-path; default = whole body), and the\n\t\t * result is coerced to a number when numeric. Lets a dashboard KPI bind\n\t\t * to a custom-aggregation endpoint (e.g. `/api/analytics/summary`) that\n\t\t * OpenRegister's per-schema aggregation can't express.\n\t\t *\n\t\t * Never served from the settled shared cache, so a tile never shows a\n\t\t * count from before a write. Tiles loading at once, or reached by one\n\t\t * page refresh, share a single request per endpoint and params.\n\t\t *\n\t\t * @param {object} s The endpoint source `{ url, path?, params?, method? }`.\n\t\t * @param {object} [refresh] The page refresh event's payload, when this is one.\n\t\t * @return {Promise<number|null>} The extracted value.\n\t\t */\n\t\tasync fetchEndpoint(s, refresh) {\n\t\t\tconst params = {}\n\t\t\tfor (const [k, v] of Object.entries(s.params || {})) {\n\t\t\t\tparams[k] = typeof v === 'string' ? this.interpolateTokens(v) : v\n\t\t\t}\n\t\t\tconst body = await fetchSharedResponse(\n\t\t\t\t{ url: this.interpolateTokens(s.url), method: 'GET', params },\n\t\t\t\trefresh ? { force: true, refresh } : { fresh: true },\n\t\t\t)\n\t\t\tconst extracted = this.getByPath(body, s.path)\n\t\t\tif (extracted === undefined || extracted === null) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tconst num = Number(extracted)\n\t\t\treturn Number.isFinite(num) ? num : extracted\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n/*\n * The card itself — its box, body stack, icon circle, title and value\n * typography — is the CANONICAL KPI card in src/css/kpi-card.css, shared with\n * CnStatsBlock. What remains here is only what is specific to THIS widget: the\n * range select, the \"/ limit\" denominator, the trend chip and the error glyph.\n *\n * Every size below is expressed against the shared `--cn-kpi-*` scale rather\n * than as its own number, so the widget's extras re-scale with the card they\n * sit in. Resist adding card styling back, and resist restating a value the\n * scale already holds; that is what split the two KPI looks apart in the first\n * place.\n */\n\n/* The title row carries an optional range select beside the label, which the\n canonical `__title` (a plain truncating heading) does not account for. */\n.cn-stat-widget__label {\n\tdisplay: flex;\n\talign-items: center;\n\tjustify-content: space-between;\n\tgap: 8px;\n\twidth: 100%;\n}\n\n/* Stacked tile: the label and its range select centre over the number rather\n than spreading to the card's edges. */\n.cn-kpi-card--vertical .cn-stat-widget__label {\n\tjustify-content: center;\n\twidth: auto;\n}\n\n/* Sized down to sit inside the label row without pushing the tile taller —\n the tile's height is fixed by its grid cell (ADR-062). */\n.cn-stat-widget__range {\n\tflex: 0 0 auto;\n\tmax-width: 50%;\n\tpadding: 0 4px;\n\tborder: none;\n\tborder-radius: var(--border-radius);\n\tbackground: transparent;\n\tcolor: var(--cn-kpi-label-color, var(--color-text-maxcontrast));\n\tfont-size: var(--cn-kpi-label-size, 13px);\n\tfont-weight: normal;\n\tcursor: pointer;\n}\n\n.cn-stat-widget__range:hover,\n.cn-stat-widget__range:focus-visible {\n\tbackground: var(--color-background-hover);\n\tcolor: var(--color-main-text);\n}\n\n/* Badge mode: the pill takes the value's place in the row. Sized to the\n card's label scale so it sits in the row without pushing the tile taller. */\n.cn-stat-widget__badge {\n\tflex: 0 1 auto;\n\tmin-width: 0;\n\tmax-width: 100%;\n\toverflow: hidden;\n\ttext-overflow: ellipsis;\n\tfont-size: var(--cn-kpi-label-size, 13px);\n}\n\n/* The denominator of a \"value / limit\" pair. Deliberately quieter and smaller\n than the value: the tile's subject is what the number IS, not what it is\n allowed to reach. Shares the value's `nowrap` so the pair never breaks. */\n.cn-stat-widget__limit {\n\tflex: 0 0 auto;\n\tfont-size: var(--cn-kpi-value-size-compact, 1.25rem);\n\tfont-weight: var(--cn-kpi-title-weight, 600);\n\tline-height: var(--cn-kpi-value-line, 1.1);\n\tcolor: var(--cn-kpi-label-color, var(--color-text-maxcontrast));\n\twhite-space: nowrap;\n}\n\n.cn-stat-widget__trend {\n\tdisplay: inline-flex;\n\talign-items: center;\n\tgap: 2px;\n\tfont-size: var(--cn-kpi-label-size, 13px);\n\tfont-weight: var(--cn-kpi-title-weight, 600);\n}\n\n/* The dash shown when the number could not be fetched. It stands where the\n value stands, so it takes the value's size and weight — CnStatsBlock's own\n error dash is literally a `cn-kpi-card__value`, and two components showing\n the same failure at two different sizes is the drift this consolidation\n exists to remove. Only the colour differs: a failure is not a number. */\n.cn-stat-widget__error {\n\tfont-size: var(--cn-kpi-value-size, 2rem);\n\tfont-weight: var(--cn-kpi-value-weight, 700);\n\tline-height: var(--cn-kpi-value-line, 1.1);\n\tcolor: var(--cn-kpi-label-color, var(--color-text-maxcontrast));\n}\n</style>\n"],"names":["CnWidgetIcon","CnStatusBadge","TrendingUp"],"mappings":"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"}
1
+ {"version":3,"file":"CnStatWidget.vue2.js","sources":["../../../../src/components/CnStatWidget/CnStatWidget.vue"],"sourcesContent":["<!--\n SPDX-FileCopyrightText: 2026 Conduction B.V.\n SPDX-License-Identifier: EUPL-1.2\n\n CnStatWidget renders the CANONICAL KPI card (src/css/kpi-card.css). This tile\n and CnStatsBlock used to be two different-looking KPIs — a transparent\n icon-beside-number row here, a grey card with a circular icon and a large\n coloured number there — so OpenCatalogi's and dossiq's dashboards did not\n match. Both now render the same `cn-kpi-card` markup from the same\n stylesheet. The legacy `cn-stat-widget*` classes stay on the same elements so\n app CSS targeting them keeps working.\n\n Keep this comment OUT of <template>: a comment node beside the root element\n makes the component multi-root in Vue 3, and a multi-root component has no\n root for its class bindings to land on.\n-->\n<template>\n\t<component\n\t\t:is=\"linkTag\"\n\t\tclass=\"cn-kpi-card cn-stat-widget\"\n\t\t:class=\"[\n\t\t\t{ 'cn-kpi-card--clickable': isLinked, 'cn-stat-widget--linked': isLinked },\n\t\t\t'cn-kpi-card--' + cardLayout,\n\t\t\t{ 'cn-kpi-card--board': isBoardLook },\n\t\t\tflat ? 'cn-kpi-card--flat' : 'cn-kpi-card--filled',\n\t\t]\"\n\t\tv-bind=\"linkAttrs\">\n\t\t<div\n\t\t\tv-if=\"resolvedIcon && !isStacked && !isBoardLook\"\n\t\t\tclass=\"cn-kpi-card__icon cn-stat-widget__icon\"\n\t\t\t:style=\"iconCircleStyle\">\n\t\t\t<CnWidgetIcon :name=\"resolvedIcon\" :size=\"24\" />\n\t\t</div>\n\n\t\t<div class=\"cn-kpi-card__body cn-stat-widget__body\">\n\t\t\t<div\n\t\t\t\tv-if=\"content.label || rangePresets.length\"\n\t\t\t\tclass=\"cn-kpi-card__title cn-stat-widget__label\"\n\t\t\t\t:class=\"{ 'cn-kpi-card__title--badge-end': hasEndBadge }\">\n\t\t\t\t<!-- Board look: the icon is an 18px glyph before the label, and\n\t\t\t\t only when the tile links to a filtered list. -->\n\t\t\t\t<span\n\t\t\t\t\tv-if=\"isBoardLook && isLinked && resolvedIcon && !hasEndBadge\"\n\t\t\t\t\tclass=\"cn-kpi-card__glyph cn-stat-widget__glyph\"\n\t\t\t\t\tdata-testid=\"cn-stat-widget-glyph\"\n\t\t\t\t\taria-hidden=\"true\">\n\t\t\t\t\t<CnWidgetIcon :name=\"resolvedIcon\" :size=\"18\" />\n\t\t\t\t</span>\n\t\t\t\t<span v-if=\"content.label\" class=\"cn-kpi-card__title-text\" :title=\"resolvedLabel\">{{ resolvedLabel }}</span>\n\n\t\t\t\t<!-- Per-tile range override. Rendered ONLY when the tile declares its\n\t\t\t\t own `content.dateRange.presets`; a tile that merely follows the\n\t\t\t\t dashboard range shows no control, because the page already has one\n\t\t\t\t and two controls for one range read as two ranges. Stops click\n\t\t\t\t propagation so choosing a range inside a linked tile does not also\n\t\t\t\t navigate. -->\n\t\t\t\t<select\n\t\t\t\t\tv-if=\"rangePresets.length\"\n\t\t\t\t\tclass=\"cn-stat-widget__range\"\n\t\t\t\t\tdata-testid=\"cn-stat-widget-range\"\n\t\t\t\t\t:aria-label=\"rangeAriaLabel\"\n\t\t\t\t\t:value=\"activeRangePreset\"\n\t\t\t\t\t@click.stop.prevent\n\t\t\t\t\t@change=\"selectRange($event.target.value)\">\n\t\t\t\t\t<option\n\t\t\t\t\t\tv-for=\"preset in rangePresets\"\n\t\t\t\t\t\t:key=\"preset.id\"\n\t\t\t\t\t\t:value=\"preset.id\">\n\t\t\t\t\t\t{{ effectiveTranslate(preset.label || preset.id) }}\n\t\t\t\t\t</option>\n\t\t\t\t</select>\n\t\t\t\t<!-- Board look, `content.iconPlacement: \"end\"`: the icon sits in a\n\t\t\t\t 32px circle at the right of the label row, tinted by the\n\t\t\t\t tile's state (DqDashboard). -->\n\t\t\t\t<span\n\t\t\t\t\tv-if=\"hasEndBadge\"\n\t\t\t\t\tclass=\"cn-kpi-card__badge cn-stat-widget__badge-icon\"\n\t\t\t\t\t:class=\"'cn-kpi-card__badge--' + stateTone\"\n\t\t\t\t\tdata-testid=\"cn-stat-widget-icon-badge\"\n\t\t\t\t\taria-hidden=\"true\">\n\t\t\t\t\t<CnWidgetIcon :name=\"resolvedIcon\" :size=\"18\" />\n\t\t\t\t</span>\n\t\t\t</div>\n\n\t\t\t<div class=\"cn-kpi-card__value-row cn-stat-widget__value-row\">\n\t\t\t\t<NcLoadingIcon v-if=\"displayLoading\" :size=\"22\" />\n\t\t\t\t<span v-else-if=\"displayError\" class=\"cn-stat-widget__error\" :title=\"displayError\">—</span>\n\t\t\t\t<template v-else>\n\t\t\t\t\t<!-- Badge mode: the value is a state name, so it reads as the\n\t\t\t\t\t library's status pill rather than as a headline number. -->\n\t\t\t\t\t<CnStatusBadge\n\t\t\t\t\t\tv-if=\"isBadge\"\n\t\t\t\t\t\tclass=\"cn-stat-widget__badge\"\n\t\t\t\t\t\tdata-testid=\"cn-stat-widget-badge\"\n\t\t\t\t\t\t:label=\"shownValue\"\n\t\t\t\t\t\t:variant=\"badgeVariant\" />\n\t\t\t\t\t<span\n\t\t\t\t\t\tv-else\n\t\t\t\t\t\tclass=\"cn-kpi-card__value cn-stat-widget__value\"\n\t\t\t\t\t\t:data-testid=\"isCountdown ? 'cn-stat-widget-countdown' : null\"\n\t\t\t\t\t\t:class=\"{ 'cn-kpi-card__value--text': isTextValue || shownValueIsText }\"\n\t\t\t\t\t\t:title=\"shownValueIsText ? shownValue : (isTextValue ? String(displayValue) : null)\"\n\t\t\t\t\t\t:style=\"valueStyle\">\n\t\t\t\t\t\t{{ shownValue }}\n\t\t\t\t\t</span>\n\t\t\t\t\t<span\n\t\t\t\t\t\tv-if=\"formattedLimit !== ''\"\n\t\t\t\t\t\tclass=\"cn-stat-widget__limit\"\n\t\t\t\t\t\tdata-testid=\"cn-stat-widget-limit\">\n\t\t\t\t\t\t/ {{ formattedLimit }}\n\t\t\t\t\t</span>\n\t\t\t\t\t<span\n\t\t\t\t\t\tv-if=\"trendPct !== null\"\n\t\t\t\t\t\tclass=\"cn-stat-widget__trend\"\n\t\t\t\t\t\tdata-testid=\"cn-stat-widget-trend\"\n\t\t\t\t\t\t:style=\"{ color: trendColor }\">\n\t\t\t\t\t\t<component :is=\"trendIcon\" :size=\"14\" />\n\t\t\t\t\t\t{{ formattedTrend }}\n\t\t\t\t\t</span>\n\t\t\t\t</template>\n\t\t\t\t<span\n\t\t\t\t\tv-if=\"!isStacked && !displayLoading && !displayError && resolvedCaption\"\n\t\t\t\t\tclass=\"cn-kpi-card__label cn-stat-widget__caption\"\n\t\t\t\t\t:class=\"captionVariantClass\"\n\t\t\t\t\tdata-testid=\"cn-stat-widget-caption\">\n\t\t\t\t\t{{ resolvedCaption }}\n\t\t\t\t</span>\n\t\t\t</div>\n\t\t\t<!-- Stacked (`content.layout: \"stacked\"`): the caption is a line of\n\t\t\t its own under the number, as the board's \"3 new this week\". -->\n\t\t\t<span\n\t\t\t\tv-if=\"isStacked && !displayLoading && !displayError && resolvedCaption\"\n\t\t\t\tclass=\"cn-kpi-card__label cn-stat-widget__caption cn-kpi-card__caption-line\"\n\t\t\t\t:class=\"captionVariantClass\"\n\t\t\t\tdata-testid=\"cn-stat-widget-caption\">\n\t\t\t\t{{ resolvedCaption }}\n\t\t\t</span>\n\t\t\t<!-- A second caption line (`content.note`), as LpStart's \"3\n\t\t\t deadlines this week\" under the count. Static text for now. -->\n\t\t\t<span\n\t\t\t\tv-if=\"!displayLoading && !displayError && resolvedNote\"\n\t\t\t\tclass=\"cn-kpi-card__label cn-stat-widget__note cn-kpi-card__caption-line\"\n\t\t\t\t:class=\"noteVariantClass\"\n\t\t\t\tdata-testid=\"cn-stat-widget-note\">\n\t\t\t\t{{ resolvedNote }}\n\t\t\t</span>\n\t\t</div>\n\t</component>\n</template>\n\n<script>\nimport { subscribe, unsubscribe } from '@nextcloud/event-bus'\nimport { NcLoadingIcon } from '@nextcloud/vue'\nimport { inject, ref } from 'vue'\nimport TrendingDown from 'vue-material-design-icons/TrendingDown.vue'\nimport TrendingNeutral from 'vue-material-design-icons/TrendingNeutral.vue'\nimport TrendingUp from 'vue-material-design-icons/TrendingUp.vue'\nimport CnStatusBadge from '../CnStatusBadge/CnStatusBadge.vue'\nimport CnWidgetIcon from '../CnWidgetGrid/CnWidgetIcon.vue'\nimport { fetchSharedResponse, getByPath, useEndpointSource } from '../../composables/useEndpointSource.js'\nimport { normalizeLook } from '../../composables/useLook.js'\nimport widgetLink from '../../mixins/widgetLink.js'\nimport { useObjectStore } from '../../store/useObjectStore.js'\nimport { resolveObjectOpType } from '../../utils/actionsDispatcher.js'\nimport { resolveObjectTokenContext } from '../../utils/detailObjectContext.js'\nimport { fetchListTotal, needsListEndpoint } from '../../utils/fetchFilterCounts.js'\nimport { formatMetricValue, unwrapAppConfig } from '../../utils/formatMetric.js'\nimport { dropOptionalUnresolved, resolveFilterTokens } from '../../utils/resolveFilterTokens.js'\nimport { STATUS_TEXT_COLORS } from '../../utils/statusColors.js'\nimport { evaluateVisibleWhenLocal, readVisibleWhenPath } from '../../utils/visibleWhen.js'\n\n// The canonical KPI look lives in one shared stylesheet, imported by BOTH\n// this component and CnStatsBlock, so the two cannot drift apart again.\n// Importing it here also means the look arrives without the consuming app\n// having pulled in the library's global css/index.css.\nimport '../../css/kpi-card.css'\n// Badge mode renders CnStatusBadge, whose colours live in the global badge\n// stylesheet. Imported here for the same reason as kpi-card.css above.\nimport '../../css/badge.css'\n\nconst PAGE_REFRESH_CHANNEL = 'cn:page:refresh'\n\n/**\n * Variant → CSS colour token map for the `variantWhen` threshold rules.\n * `danger` is accepted as an alias of `error` (the doriath KPI-card\n * vocabulary); `default` keeps the widget's configured colours.\n *\n * @type {Record<string, string>}\n */\n// These paint the number, so they take the text-on-background tokens.\nconst VARIANT_COLORS = {\n\tdefault: '',\n\tprimary: 'var(--color-primary-element)',\n\tsuccess: STATUS_TEXT_COLORS.success,\n\twarning: STATUS_TEXT_COLORS.warning,\n\terror: STATUS_TEXT_COLORS.error,\n\tdanger: STATUS_TEXT_COLORS.error,\n}\n\n/**\n * The variants CnStatusBadge accepts. Badge mode normalises every tile\n * variant onto this list: `danger` becomes `error`, anything unknown is\n * skipped so the next rule in line decides.\n *\n * @type {string[]}\n */\nconst BADGE_VARIANTS = ['default', 'primary', 'success', 'warning', 'error', 'info']\n\n/**\n * A bare `YYYY-MM-DD`, the shape OpenRegister stores a date property in.\n *\n * It is matched BEFORE `new Date()` sees it on purpose. `new Date('2026-09-26')`\n * is specified to parse a date-only string as UTC midnight, so west of\n * Greenwich it lands on the 25th local and every countdown built on it is a\n * day short. A date the schema calls a date has no time and no zone, so it is\n * read as the local calendar day it names.\n *\n * @type {RegExp}\n */\nconst DATE_ONLY = /^(\\d{4})-(\\d{2})-(\\d{2})$/\n\n/** Milliseconds in a day, used only between two UTC-normalised midnights. */\nconst DAY_MS = 86400000\n\n/**\n * The local calendar day a value names, as a UTC midnight timestamp.\n *\n * WHY CALENDAR DAYS AND NOT ELAPSED MILLISECONDS. A deadline is a day on a\n * calendar, not an instant. Subtracting timestamps makes a deadline at 23:00\n * today read as \"0 days\" and one at 01:00 tomorrow read as \"0 days\" as well\n * (two hours apart), while 09:00 tomorrow reads as \"1 day\" — the same calendar\n * distance rendering as two different answers because of the time somebody\n * happened to type. So both ends are collapsed to the LOCAL calendar day they\n * fall on, and the difference is taken between those days.\n *\n * The collapse goes through `Date.UTC` rather than a local `Date`, because two\n * UTC midnights are always exactly `DAY_MS` apart, while two local midnights\n * across a DST change are 23 or 25 hours apart and a plain division then\n * rounds to the wrong day twice a year.\n *\n * @param {unknown} value A date string, a `Date`, or an epoch-milliseconds number.\n * @return {number|null} The UTC-midnight timestamp of that local day, or null when there is no readable date.\n */\nfunction calendarDay(value) {\n\tif (value === null || value === undefined || value === '') {\n\t\treturn null\n\t}\n\tif (typeof value === 'string') {\n\t\tconst parts = DATE_ONLY.exec(value.trim())\n\t\tif (parts) {\n\t\t\treturn Date.UTC(Number(parts[1]), Number(parts[2]) - 1, Number(parts[3]))\n\t\t}\n\t}\n\tconst isDate = value instanceof Date\n\tif (!isDate && typeof value !== 'string' && !Number.isFinite(value)) {\n\t\t// A boolean or an object is not a mis-typed date, it is not a date at\n\t\t// all; `new Date(true)` would happily answer 1 January 1970.\n\t\treturn null\n\t}\n\tconst parsed = isDate ? value : new Date(value)\n\tif (Number.isNaN(parsed.getTime())) {\n\t\treturn null\n\t}\n\treturn Date.UTC(parsed.getFullYear(), parsed.getMonth(), parsed.getDate())\n}\n\n/**\n * CnStatWidget — an abstract, manifest-configured KPI / single-statistic tile.\n *\n * Reads ONE scalar value from OpenRegister's ad-hoc aggregation endpoint\n * (`/apps/openregister/api/objects/aggregations/{register}/{schema}/value`)\n * given a `source` config (register, schema, metric, field, filter) and renders\n * it with a configurable label, icon, value colour, and number format. Nothing\n * about the data or presentation is hard-coded — every fleet app gets the same\n * editable KPI tile, replacing per-app coded KPI components (ADR-041).\n *\n * The widget is resolved by its registry type key `stat` (see\n * `CnStatWidget/index.js`); apps reference it from a manifest placement, e.g.\n * `{ id, widgetKey: 'stat', type: 'stat', content: { label, source, ... } }`.\n *\n * Example content blob:\n * ```js\n * content: {\n * label: 'Revenue',\n * icon: 'Cash',\n * valueColor: '#0082c9',\n * format: { style: 'currency', currency: 'EUR', decimals: 0 },\n * source: { register: 'pipelinq', schema: 'lead', metric: 'sum', field: 'value', filter: { status: 'won' } },\n * }\n * ```\n *\n * ENDPOINT BINDING (Wave 2, #91) — instead of an OpenRegister `source`, the\n * tile can bind to an arbitrary app REST endpoint through the shared\n * `useEndpointSource` engine (token-resolved params, per-(url+params)\n * request dedup + short-TTL cache, `cn:page:refresh` / `cn:widget:refresh`\n * subscription). Exactly ONE of `source` | `endpointSource` may be\n * configured (validator-enforced); when both slip through, `endpointSource`\n * wins. The pipelinq analytics-KPI contract in full:\n * ```js\n * content: {\n * label: 'Revenue',\n * icon: 'CashMultiple',\n * format: { style: 'currency', currency: 'EUR', decimals: 0 },\n * endpointSource: {\n * url: '/apps/pipelinq/api/analytics/commercial',\n * params: { period: '@workspace.datePreset?' },\n * },\n * valueField: 'revenue', // dot-path into the payload\n * previousField: 'previousPeriod.revenue', // → trend sublabel (arrow + % vs previous)\n * // deltaField: 'revenueDeltaPct', // OR a server-computed delta percent\n * goodDirection: 'up', // tints the trend good/bad (default 'up')\n * variantWhen: [ // first-match threshold styling\n * { op: 'gte', value: 100000, variant: 'success' },\n * { op: 'lt', value: 10000, variant: 'warning', icon: 'AlertOutline' },\n * ],\n * clickRoute: 'leads', // whole-tile click-through (alias of route)\n * }\n * ```\n *\n * BADGE MODE. `display: 'badge'` renders the value as a `CnStatusBadge` pill,\n * for a tile whose value is a state name rather than a count. The badge colour\n * can come from the RESOLVED ROW of an `objectField` reference, not only from\n * the displayed text: `resolve.variantField` names a field on the looked-up\n * row, and `resolve.variantMap` maps its value to a variant (without a map the\n * field value itself must be a variant name). `emptyText` replaces the dash\n * when the value is empty or its reference does not resolve. `overrides` test\n * the BOUND RECORD, first match wins, and replace the label, variant and icon,\n * so a record in a special state reads as that state:\n * ```js\n * content: {\n * label: 'Status',\n * display: 'badge',\n * emptyText: 'Unknown',\n * objectField: {\n * field: 'status',\n * resolve: {\n * register: 'dossiq',\n * schema: 'statusType',\n * labelField: 'name',\n * variantField: 'isFinal',\n * variantMap: { true: 'success', false: 'info' },\n * },\n * },\n * overrides: [\n * { when: { field: 'suspended' }, label: 'Suspended', variant: 'warning' },\n * ],\n * }\n * ```\n *\n * COUNTDOWN MODE. `display: 'countdown'` reads a DATE off the record (or off an\n * endpoint payload) and renders the time remaining, so a deadline is a\n * configured KPI tile rather than a component an app writes by hand:\n * ```js\n * content: {\n * label: 'Deadline',\n * display: 'countdown',\n * objectField: 'dueDate',\n * countdown: {\n * unit: 'days', // the only unit; anything else is read as days\n * warnAt: 14, // warning at or below this many days left\n * dangerAt: 5, // error at or below, and it wins over warnAt\n * pastLabel: 'Overdue by {n} days', // a date that has passed\n * emptyText: 'No deadline', // absent or unreadable date\n * },\n * }\n * ```\n * A passed date NEVER renders as a negative number: it renders `pastLabel` with\n * `{n}` as the number of days it is past, and it is always the error colour\n * whether or not `dangerAt` is set. Today is 0, not 1 and not −1, and renders\n * `todayLabel` (\"Today\"). The thresholds are INCLUSIVE. An absent or unreadable\n * date renders `countdown.emptyText`, falling back to `content.emptyText` and\n * then to the dash, never `NaN` or `Invalid Date`. `overrides` outrank the\n * countdown's own label and colour exactly as they outrank a badge's.\n */\nexport default {\n\tname: 'CnStatWidget',\n\n\tcomponents: {\n\t\tNcLoadingIcon,\n\t\tCnWidgetIcon,\n\t\tCnStatusBadge,\n\t\tTrendingUp,\n\t\tTrendingDown,\n\t\tTrendingNeutral,\n\t},\n\n\tmixins: [widgetLink],\n\n\tinject: {\n\t\t/**\n\t\t * Detail-page object context (`{ objectId, object, register, schema }`)\n\t\t * provided by CnDetailPage — enables `@objectId` / `@object.<field>`\n\t\t * filter tokens so a detail-page KPI can be scoped to the current\n\t\t * object. Null on dashboards (tokens then pass through unresolved).\n\t\t */\n\t\tcnObjectContext: { default: null },\n\t\t/**\n\t\t * The look the app is drawn in (`board` or `nextcloud`), provided by\n\t\t * CnAppRoot. The board look draws the screens' KPI tile.\n\t\t *\n\t\t * @spec openspec/changes/screens-dashboard-parity/specs/dashboard-page/spec.md#requirement-the-board-kpi-tile\n\t\t */\n\t\tcnLook: { default: 'nextcloud' },\n\t\t/**\n\t\t * v2 slot-grid detail context holder (`{ value: { objectData, schema,\n\t\t * objectType, objectId, register, store } | null }`) provided by\n\t\t * CnPageRenderer — backfills the object token context so\n\t\t * `@objectId` / `@object.<field>` resolve on detail surfaces where\n\t\t * CnDetailPage is not an ancestor (#91 Wave 3).\n\t\t */\n\t\tcnDetailObjectContext: { default: null },\n\t\t/**\n\t\t * Page-level workspace context (a reactive `{ <key>: value }` map)\n\t\t * provided by CnDashboardPage. Drives `@page.<param>` / `@workspace.<param>`\n\t\t * tokens in an `endpoint` source's URL / params (e.g. a period selector\n\t\t * the page renders that every endpoint KPI reads). Empty `{}` when no\n\t\t * dashboard ancestor provides one.\n\t\t */\n\t\tcnWorkspaceContext: { default: () => ({}) },\n\t\t/**\n\t\t * Page-level app config (a reactive `{ <key>: value }` map) provided by\n\t\t * CnDashboardPage / CnDetailPage. Drives `@config.<key>` tokens in an\n\t\t * `endpoint` source's URL / params AND in the `format.currency` /\n\t\t * `format.suffix` / `format.prefix` strings (e.g. the reporting currency\n\t\t * the setup wizard captures). Empty `{}` when no ancestor provides one.\n\t\t */\n\t\tcnAppConfig: { default: () => ({}) },\n\t\t/**\n\t\t * Translate function provided by CnAppRoot (the host app's\n\t\t * `translate`, scoped to its app id). Applied to the manifest-authored\n\t\t * `content.label` / `content.caption` so a KPI tile renders in the\n\t\t * user's Nextcloud language instead of the raw source string. Defaults\n\t\t * to an identity function so the widget stays usable standalone.\n\t\t *\n\t\t * @type {(key: string) => string}\n\t\t */\n\t\tcnTranslate: { default: () => (key) => key },\n\t\t/**\n\t\t * Reactive date range provided by an ancestor `CnDashboardPage` when its\n\t\t * `dateRange.enabled` is true — `{ from, to, preset }`, else null. Same\n\t\t * ref `CnChartWidget` injects, so a tile and a chart on one dashboard\n\t\t * always agree on the period. A tile follows it only once it declares\n\t\t * `content.dateRange` (see the `content` prop docs for why).\n\t\t *\n\t\t * @type {{value: ({from: string, to: string, preset: string}|null)}}\n\t\t */\n\t\tcnDashboardDateRange: { default: () => ref(null) },\n\t},\n\n\tprops: {\n\t\t/**\n\t\t * The widget's persisted configuration blob. An optional `route`\n\t\t * (vue-router location), `clickRoute` (Wave-2 alias), or `link`\n\t\t * (external href) turns the whole tile into a click-through target\n\t\t * (see the widgetLink mixin).\n\t\t * The `source` resolves the value. Besides the OpenRegister-backed kinds\n\t\t * (plain aggregate / `ratio` / `computed` / `weighted`), an\n\t\t * `{ kind: 'endpoint', url, path?, params? }` source reads an arbitrary\n\t\t * app REST endpoint and extracts the value at the dot-`path` of the\n\t\t * response (default = whole body). The `url` and any string `params`\n\t\t * value interpolate `@page.<param>` / `@workspace.<param>` tokens from the\n\t\t * page-level context (and `@objectId` / `@object.<field>` on a detail\n\t\t * page) — so a page-rendered period selector can drive every endpoint KPI.\n\t\t *\n\t\t * Wave 2 (#91): `endpointSource` (`{ url, method?, params?,\n\t\t * responsePath? }`) binds the tile to an arbitrary endpoint through the\n\t\t * shared `useEndpointSource` engine — exactly one of `source` |\n\t\t * `endpointSource`. `valueField` plucks the displayed value from the\n\t\t * payload; `previousField` (previous-period value) or `deltaField`\n\t\t * (server-computed percent) renders the trend sublabel (arrow +\n\t\t * percent-vs-previous, tinted by `goodDirection`, default `'up'`);\n\t\t * `variantWhen` (`[{ op, value, variant, icon? }]`, first match wins)\n\t\t * re-tints the value/icon by threshold.\n\t\t *\n\t\t * `limitField` (dot-path into the payload) or a static `limit` renders the\n\t\t * tile as a capacity pair — `0 / 100` — and tints it `warning` once the\n\t\t * value reaches the limit, unless a `variantWhen` rule already claims the\n\t\t * colour. Use `limitField` for a server-configured quota so the ceiling is\n\t\t * read live rather than duplicated in the manifest.\n\t\t *\n\t\t * `dateRange` opts the tile into the dashboard's period. Present and empty\n\t\t * (`{}`) = follow the ancestor `CnDashboardPage` range; add `presets`\n\t\t * (`[{ id, label?, from?, to? }]`) to render a per-tile picker that\n\t\t * overrides it. With presets and no page range, the tile starts on\n\t\t * `dateRange.default` (a preset id), else on the first preset, so the\n\t\t * picker never opens blank and the first request already carries a\n\t\t * range. The active range is exposed to `endpointSource` (and to the\n\t\t * tile's `route`) as `@range.from` / `@range.to` / `@range.preset`\n\t\t * tokens. A tile that\n\t\t * declares no `dateRange` is unaffected by the page range — that is\n\t\t * deliberate, so adding a range to a dashboard cannot silently change what\n\t\t * an existing tile requests.\n\t\t *\n\t\t * `display: 'badge'` renders the value as a `CnStatusBadge`. On an\n\t\t * `objectField` reference, `resolve.variantField` (a dot-path on the\n\t\t * looked-up row) plus `resolve.variantMap` (`{ rowValue: variant }`)\n\t\t * colour it from the row; without a map the row value must itself be a\n\t\t * variant name. `emptyText` replaces the dash for an empty value, and\n\t\t * for a reference that does not resolve. `overrides`\n\t\t * (`[{ when: { field, op?, value? }, label?, variant?, icon? }]`, first\n\t\t * match wins) test the bound record: `when` is the local `visibleWhen`\n\t\t * grammar, and a `when` with neither `op` nor `value` tests the field\n\t\t * for truthiness. A match replaces the shown label, the colour and the\n\t\t * icon. Precedence of the colour: override, `variantWhen`, the countdown\n\t\t * threshold, the at-limit warning, the resolved row, the static\n\t\t * `variant`.\n\t\t *\n\t\t * `display: 'countdown'` reads the value as a DATE and renders the days\n\t\t * remaining. `countdown.warnAt` / `countdown.dangerAt` are inclusive day\n\t\t * thresholds and `dangerAt` wins; `countdown.pastLabel` (with `{n}`)\n\t\t * words a date that has passed, which is always the error colour and is\n\t\t * never shown as a negative number; `countdown.todayLabel` words a date\n\t\t * due today, which counts as 0; `countdown.futureLabel` (with `{n}`)\n\t\t * words the ordinary case; `countdown.emptyText` words an absent or\n\t\t * unreadable date, falling back to the top-level `emptyText`. Days are\n\t\t * counted between LOCAL CALENDAR DAYS, not as elapsed milliseconds, so\n\t\t * the time of day on a deadline never moves the answer.\n\t\t *\n\t\t * @type {{label?: string, icon?: string, iconColor?: string, valueColor?: string, caption?: string, route?: (object|string), clickRoute?: (object|string), link?: string, format?: {style?: string, currency?: string, decimals?: number, prefix?: string, suffix?: string}, source?: {kind?: string, register?: string, schema?: string, metric?: string, field?: string, filter?: object, url?: string, path?: string, params?: object}, endpointSource?: {url: string, method?: string, params?: object, responsePath?: string}, valueField?: string, limitField?: string, limit?: number, dateRange?: {presets?: Array<{id: string, label?: string, from?: string, to?: string}>, default?: string}, previousField?: string, deltaField?: string, goodDirection?: ('up'|'down'), variant?: ('default'|'primary'|'success'|'warning'|'error'|'danger'), variantWhen?: Array<{op: string, value: unknown, variant: string, icon?: string}>, objectField?: (string|{field: string, resolve?: {register: string, schema: string, labelField?: string, variantField?: string, variantMap?: {[key: string]: string}}}), display?: ('text'|'badge'|'countdown'), countdown?: {unit?: 'days', warnAt?: number, dangerAt?: number, futureLabel?: string, todayLabel?: string, pastLabel?: string, emptyText?: string}, emptyText?: string, captionVariant?: ('default'|'primary'|'success'|'warning'|'error'|'danger'), captionVariantWhen?: Array<{op: string, value: unknown, variant: string}>, overrides?: Array<{when: {field: string, op?: string, value?: unknown}, label?: string, variant?: string, icon?: string, caption?: string, captionVariant?: string}>}}\n\t\t */\n\t\tcontent: {\n\t\t\ttype: Object,\n\t\t\tdefault: () => ({}),\n\t\t},\n\n\t\t/**\n\t\t * Translate function. Falls back to the injected `cnTranslate`\n\t\t * (itself an identity function by default). Provide explicitly when\n\t\t * mounting CnStatWidget outside a CnAppRoot ancestor.\n\t\t *\n\t\t * @type {((key: string) => string)|null}\n\t\t */\n\t\ttranslate: {\n\t\t\ttype: Function,\n\t\t\tdefault: null,\n\t\t},\n\t},\n\n\tsetup(props) {\n\t\t// Endpoint binding (Wave 2): the shared useEndpointSource engine owns\n\t\t// token resolution, request dedup + TTL caching, and the\n\t\t// cn:page:refresh / cn:widget:refresh subscriptions. It is a no-op\n\t\t// while `content.endpointSource` is absent, so the OpenRegister\n\t\t// `source` path below is untouched. The injects are re-read here in\n\t\t// setup — Vue 2.7 resolves them identically to the Options `inject`\n\t\t// block (same precedent as CnChartWidget's date-range ref).\n\t\tconst objectCtxRaw = inject('cnObjectContext', null)\n\t\tconst detailCtxRaw = inject('cnDetailObjectContext', null)\n\t\tconst workspaceRaw = inject('cnWorkspaceContext', ref({}))\n\t\tconst appConfigRaw = inject('cnAppConfig', ref({}))\n\t\tconst pageRangeRaw = inject('cnDashboardDateRange', ref(null))\n\t\tconst unwrap = (v) => ((v && typeof v === 'object' && 'value' in v) ? v.value : v)\n\n\t\t// The per-tile range override. Null = follow the dashboard range; set by\n\t\t// selectRange() when the tile renders its own preset picker. It lives in\n\t\t// setup, not data(), because the ctx closure below must read it reactively\n\t\t// — a data() property would be resolved once and never refetch.\n\t\tconst tileRange = ref(null)\n\t\t// With its own presets and no page range, the tile starts on\n\t\t// `dateRange.default`, else the first preset. Without this the picker\n\t\t// opened blank (its value '' matched no option unless an app added a\n\t\t// preset with id '') and the first request carried no range. Only a\n\t\t// tile that declares presets gets a default: one that merely follows\n\t\t// the dashboard (`dateRange: {}`) keeps following it.\n\t\tconst defaultRange = () => {\n\t\t\tconst dr = props.content && props.content.dateRange\n\t\t\tconst presets = (dr && Array.isArray(dr.presets)) ? dr.presets.filter(Boolean) : []\n\t\t\tif (presets.length === 0) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tconst chosen = (dr.default !== undefined && presets.find((p) => p.id === dr.default)) || presets[0]\n\t\t\treturn { preset: chosen.id, from: chosen.from ?? null, to: chosen.to ?? null }\n\t\t}\n\t\tconst activeRange = () => (tileRange.value || unwrap(pageRangeRaw) || defaultRange())\n\n\t\tconst { data, loading, error, refetch } = useEndpointSource(\n\t\t\t() => (props.content && props.content.endpointSource) || null,\n\t\t\t{\n\t\t\t\tctx: () => ({\n\t\t\t\t\t...(resolveObjectTokenContext(objectCtxRaw, detailCtxRaw) || {}),\n\t\t\t\t\tworkspace: unwrap(workspaceRaw) || {},\n\t\t\t\t\tconfig: unwrap(appConfigRaw) || {},\n\t\t\t\t\t// `@range.from` / `@range.to` / `@range.preset` tokens, usable in the\n\t\t\t\t\t// endpointSource url and params exactly like `@workspace.*`.\n\t\t\t\t\trange: activeRange() || {},\n\t\t\t\t}),\n\t\t\t},\n\t\t)\n\t\treturn { epData: data, epLoading: loading, epError: error, epRefetch: refetch, tileRange, activeRange }\n\t},\n\n\tdata() {\n\t\treturn {\n\t\t\t// Resolved display label for an `objectField` that holds a reference\n\t\t\t// uuid. Null until resolved, and null forever when it cannot be.\n\t\t\treferenceLabel: null,\n\t\t\t// The looked-up row behind `referenceLabel`, read by\n\t\t\t// `resolve.variantField` to colour the tile from the row itself.\n\t\t\treferenceRow: null,\n\t\t\t// True once a configured lookup ran and found no usable label.\n\t\t\treferenceFailed: false,\n\t\t\t// True while a configured lookup is in flight. Without it, \"not\n\t\t\t// resolved yet\" and \"cannot be resolved\" were the same state, so the\n\t\t\t// tile showed the RAW UUID for the length of the request and then\n\t\t\t// replaced it with the label or the empty text. A person watching a\n\t\t\t// status badge saw `4f2b9c10-…` flash past where a state belonged.\n\t\t\treferencePending: false,\n\t\t\tvalue: null,\n\t\t\tloading: false,\n\t\t\terror: '',\n\t\t}\n\t},\n\n\tcomputed: {\n\t\t/**\n\t\t * Whether the app takes the board look (`cnLook` is `board`).\n\t\t *\n\t\t * @spec openspec/changes/screens-dashboard-parity/specs/dashboard-page/spec.md#requirement-the-board-kpi-tile\n\t\t * @return {boolean}\n\t\t */\n\t\tisBoardLook() {\n\t\t\treturn normalizeLook(this.cnLook) === 'board'\n\t\t},\n\n\t\t/**\n\t\t * Effective translate function: the explicit `translate` prop when\n\t\t * given, else the injected `cnTranslate` (identity by default).\n\t\t *\n\t\t * @return {(key: string) => string}\n\t\t */\n\t\teffectiveTranslate() {\n\t\t\treturn this.translate ?? this.cnTranslate\n\t\t},\n\n\t\t/**\n\t\t * The tile label, run through the host translate function so a\n\t\t * manifest-authored source string localises to the user's language.\n\t\t *\n\t\t * @return {string}\n\t\t */\n\t\tresolvedLabel() {\n\t\t\tconst label = this.content.label\n\t\t\treturn label ? this.effectiveTranslate(label) : ''\n\t\t},\n\n\t\t/**\n\t\t * The tile caption, translated and then interpolated with the fetched\n\t\t * payload.\n\t\t *\n\t\t * `{field}` tokens are replaced from the endpoint payload by dot-path,\n\t\t * using the same {@link getByPath} that resolves `valueField` — so a\n\t\t * caption can say what the number MEANS rather than repeating it:\n\t\t *\n\t\t * caption: '{levelName} · {currentStreakDays}-day streak'\n\t\t *\n\t\t * WHY THIS EXISTS. Without it a tile needing a secondary line had to be\n\t\t * a bespoke component: it could not be expressed as config, so apps\n\t\t * wrote their own card, and that card then re-implemented fetching,\n\t\t * loading and error handling too. Every one of those re-implementations\n\t\t * observed so far swallowed its errors into a zero.\n\t\t *\n\t\t * Translation runs FIRST, so a translator sees `{levelName}` as a\n\t\t * placeholder in the source string and can move it within the sentence —\n\t\t * the same contract as Nextcloud's own `t()` parameters.\n\t\t *\n\t\t * A token with no matching field resolves to the empty string rather\n\t\t * than being left as `{levelName}` on screen: a caption is decoration,\n\t\t * and showing a reader a raw token is worse than showing them less.\n\t\t *\n\t\t * @return {string}\n\t\t */\n\t\tresolvedCaption() {\n\t\t\tconst override = this.activeOverride\n\t\t\tconst caption = (override && typeof override.caption === 'string' && override.caption !== '')\n\t\t\t\t? override.caption\n\t\t\t\t: this.content.caption\n\t\t\tif (!caption) {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t\tconst translated = this.effectiveTranslate(caption)\n\t\t\tif (translated.indexOf('{') === -1) {\n\t\t\t\treturn translated\n\t\t\t}\n\t\t\tconst payload = this.endpointMode ? this.epData : null\n\t\t\treturn translated.replace(/\\{([A-Za-z0-9_.]+)\\}/g, (whole, path) => {\n\t\t\t\t// `{value}` is the tile's own number, so a caption can read\n\t\t\t\t// \"{value} due today\" on a register-counted tile that has no\n\t\t\t\t// payload to read fields from.\n\t\t\t\tif (path === 'value' && (payload === null || getByPath(payload, path) === undefined)) {\n\t\t\t\t\treturn this.formattedValue === undefined || this.formattedValue === null ? '' : String(this.formattedValue)\n\t\t\t\t}\n\t\t\t\tconst v = getByPath(payload, path)\n\t\t\t\treturn (v === undefined || v === null) ? '' : String(v)\n\t\t\t}).replace(/\\s{2,}/g, ' ').trim()\n\t\t},\n\n\t\t/**\n\t\t * The first `content.captionVariantWhen` rule the tile's value\n\t\t * matches (`[{ op, value, variant }]`, the `variantWhen` shape), or\n\t\t * null. Colours the caption on the value without recolouring the\n\t\t * tile: \"1 due today\" turns red while the number stays ink.\n\t\t *\n\t\t * @spec openspec/changes/zuiddrecht-pixel-gaps/specs/zuiddrecht-pixel-gaps/spec.md#requirement-a-stat-tile-colours-its-caption-by-rule\n\t\t * @return {object|null}\n\t\t */\n\t\tactiveCaptionRule() {\n\t\t\tconst rules = this.content.captionVariantWhen\n\t\t\tif (!Array.isArray(rules) || rules.length === 0) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tconst current = this.displayValue\n\t\t\tif (current === null || current === undefined) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\treturn rules.find((r) => r && this.matchesRule(current, r)) || null\n\t\t},\n\n\t\t/**\n\t\t * The second caption line: `content.note` through the host translate\n\t\t * function, or '' without it.\n\t\t *\n\t\t * @spec openspec/changes/zuiddrecht-pixel-gaps-3/specs/zuiddrecht-pixel-gaps-3/spec.md#requirement-a-stat-tile-can-carry-a-second-caption-line\n\t\t * @return {string}\n\t\t */\n\t\tresolvedNote() {\n\t\t\tconst note = this.content && this.content.note\n\t\t\treturn typeof note === 'string' && note !== '' ? this.effectiveTranslate(note) : ''\n\t\t},\n\n\t\t/**\n\t\t * The colour class of the second caption line (`content.noteVariant`,\n\t\t * the same names as `captionVariant`), or '' for the muted default.\n\t\t *\n\t\t * @spec openspec/changes/zuiddrecht-pixel-gaps-3/specs/zuiddrecht-pixel-gaps-3/spec.md#requirement-a-stat-tile-can-carry-a-second-caption-line\n\t\t * @return {string}\n\t\t */\n\t\tnoteVariantClass() {\n\t\t\tconst variant = this.content && this.content.noteVariant\n\t\t\tif (!variant || variant === 'default' || !Object.hasOwn(VARIANT_COLORS, variant)) {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t\treturn `cn-kpi-card__label--${variant === 'danger' ? 'error' : variant}`\n\t\t},\n\n\t\t/**\n\t\t * The caption's colour class: the matching override's\n\t\t * `captionVariant`, else `content.captionVariant`, as\n\t\t * `cn-kpi-card__label--<variant>`. '' for `default` or an unknown\n\t\t * variant, so an uncoloured caption is what it always was.\n\t\t *\n\t\t * @spec openspec/changes/zuiddrecht-pixel-gaps/specs/zuiddrecht-pixel-gaps/spec.md#requirement-a-stat-tile-colours-its-caption-by-rule\n\t\t * @return {string}\n\t\t */\n\t\tcaptionVariantClass() {\n\t\t\tconst override = this.activeOverride\n\t\t\tconst variant = (override && override.captionVariant)\n\t\t\t\t|| (this.activeCaptionRule && this.activeCaptionRule.variant)\n\t\t\t\t|| this.content.captionVariant\n\t\t\tif (!variant || variant === 'default' || !Object.hasOwn(VARIANT_COLORS, variant)) {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t\t// Board look: colour in a tile means a warning and nothing else.\n\t\t\tif (this.isBoardLook && !['warning', 'error', 'danger'].includes(variant)) {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t\treturn `cn-kpi-card__label--${variant === 'danger' ? 'error' : variant}`\n\t\t},\n\n\t\t/**\n\t\t * The unwrapped detail-page object context for token resolution, or null\n\t\t * on surfaces (dashboards) that don't provide one.\n\t\t *\n\t\t * @return {object|null}\n\t\t */\n\t\tobjectCtx() {\n\t\t\treturn resolveObjectTokenContext(this.cnObjectContext, this.cnDetailObjectContext)\n\t\t},\n\n\t\t/**\n\t\t * The unwrapped page-level workspace context map for `@page.*` /\n\t\t * `@workspace.*` token resolution. Always an object (defaults to `{}`).\n\t\t *\n\t\t * @return {object}\n\t\t */\n\t\tpageCtx() {\n\t\t\tconst c = this.cnWorkspaceContext\n\t\t\tconst unwrapped = (c && typeof c === 'object' && 'value' in c) ? c.value : c\n\t\t\treturn (unwrapped && typeof unwrapped === 'object') ? unwrapped : {}\n\t\t},\n\n\t\t/**\n\t\t * The unwrapped page-level app config map for `@config.*` token\n\t\t * resolution. Always an object (defaults to `{}`).\n\t\t *\n\t\t * @return {object}\n\t\t */\n\t\tconfigCtx() {\n\t\t\treturn unwrapAppConfig(this.cnAppConfig)\n\t\t},\n\n\t\t/**\n\t\t * Whether the tile is endpoint-bound (Wave 2): a `content.endpointSource`\n\t\t * with a `url` switches the value/loading/error surface to the shared\n\t\t * `useEndpointSource` engine. Exactly one of `source` | `endpointSource`\n\t\t * is allowed (validator-enforced); endpointSource wins when both slip\n\t\t * through.\n\t\t *\n\t\t * @return {boolean}\n\t\t */\n\t\tendpointMode() {\n\t\t\tconst es = this.content.endpointSource\n\t\t\treturn !!(es && es.url)\n\t\t},\n\n\t\t/**\n\t\t * The raw display value: in endpoint mode, the payload value plucked at\n\t\t * `content.valueField` (dot-path; omitted = the payload itself);\n\t\t * otherwise the OpenRegister-aggregated `value`.\n\t\t *\n\t\t * @return {unknown}\n\t\t */\n\t\tdisplayValue() {\n\t\t\tif (this.objectFieldMode) {\n\t\t\t\treturn this.objectFieldValue\n\t\t\t}\n\t\t\tif (!this.endpointMode) {\n\t\t\t\treturn this.value\n\t\t\t}\n\t\t\tconst v = getByPath(this.epData, this.content.valueField)\n\t\t\treturn v === undefined ? null : v\n\t\t},\n\n\t\t/**\n\t\t * Whether the headline is text rather than a number.\n\t\t *\n\t\t * The KPI card is built around a number: it never wraps and never\n\t\t * shrinks, because in a narrow tile the decoration should give way and\n\t\t * the figure should not. A NAME needs the opposite, so it gets a variant\n\t\t * that wraps and clamps, plus a title attribute for the full string.\n\t\t *\n\t\t * @return {boolean} true when the value is not numeric.\n\t\t */\n\t\tisTextValue() {\n\t\t\tconst v = this.displayValue\n\t\t\tif (v === null || v === undefined || v === '') {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\treturn !Number.isFinite(Number(v))\n\t\t},\n\n\t\t/**\n\t\t * Whether the tile renders its value as a status badge.\n\t\t *\n\t\t * @return {boolean} true when `content.display` is `'badge'`.\n\t\t */\n\t\tisBadge() {\n\t\t\treturn this.content.display === 'badge'\n\t\t},\n\n\t\t/**\n\t\t * Whether the tile renders its value as a time-remaining countdown.\n\t\t *\n\t\t * @return {boolean} true when `content.display` is `'countdown'`.\n\t\t */\n\t\tisCountdown() {\n\t\t\treturn this.content.display === 'countdown'\n\t\t},\n\n\t\t/**\n\t\t * The countdown block, or `{}`. `unit` is accepted and ignored: days is\n\t\t * the only unit this renders, and saying so is better than pretending\n\t\t * an hours or weeks mode exists.\n\t\t *\n\t\t * @return {object} The countdown config.\n\t\t */\n\t\tcountdownConfig() {\n\t\t\tconst cfg = this.content.countdown\n\t\t\treturn (cfg && typeof cfg === 'object') ? cfg : {}\n\t\t},\n\n\t\t/**\n\t\t * Whole LOCAL CALENDAR DAYS from today to the tile's value read as a\n\t\t * date. Positive is still to come, 0 is today, negative has passed.\n\t\t *\n\t\t * Zero is today because both ends are collapsed onto the calendar day\n\t\t * they fall on and then subtracted: a deadline dated today is the same\n\t\t * day as today, and the same day is a distance of nothing. Not 1 (which\n\t\t * would claim a day that is already being spent) and not −1 (which\n\t\t * would call a deadline that has not passed overdue).\n\t\t *\n\t\t * Null when the tile is not in countdown mode, or when the value holds\n\t\t * no readable date — which is what keeps `NaN` off the tile.\n\t\t *\n\t\t * @return {number|null} The signed day count, or null.\n\t\t */\n\t\tcountdownDays() {\n\t\t\tif (!this.isCountdown) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tconst due = calendarDay(this.displayValue)\n\t\t\tif (due === null) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tconst now = new Date()\n\t\t\tconst today = Date.UTC(now.getFullYear(), now.getMonth(), now.getDate())\n\t\t\treturn Math.round((due - today) / DAY_MS)\n\t\t},\n\n\t\t/**\n\t\t * The countdown sentence: the past wording for a date that has gone by,\n\t\t * the today wording for today, the future wording otherwise. `{n}` is\n\t\t * the number of days, never signed — \"−3 days left\" is exactly the\n\t\t * reading this mode exists to prevent.\n\t\t *\n\t\t * The built-in wordings carry their own singular, so a tile that\n\t\t * configures nothing still reads \"1 day left\" rather than \"1 days\n\t\t * left\". A configured `futureLabel` / `pastLabel` replaces both forms,\n\t\t * because a manifest author writing their own wording is the one who\n\t\t * knows how their language counts.\n\t\t *\n\t\t * @return {string} The sentence, or '' when there is nothing to count.\n\t\t */\n\t\tcountdownText() {\n\t\t\tconst days = this.countdownDays\n\t\t\tif (days === null) {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t\tconst cfg = this.countdownConfig\n\t\t\tif (days === 0) {\n\t\t\t\treturn this.effectiveTranslate(cfg.todayLabel || 'Today')\n\t\t\t}\n\t\t\tconst n = Math.abs(days)\n\t\t\tconst past = days < 0\n\t\t\tlet template = past ? cfg.pastLabel : cfg.futureLabel\n\t\t\tif (typeof template !== 'string' || template === '') {\n\t\t\t\tif (past) {\n\t\t\t\t\ttemplate = n === 1 ? 'Overdue by {n} day' : 'Overdue by {n} days'\n\t\t\t\t} else {\n\t\t\t\t\ttemplate = n === 1 ? '{n} day left' : '{n} days left'\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn this.effectiveTranslate(template).replace(/\\{n\\}/g, String(n))\n\t\t},\n\n\t\t/**\n\t\t * The colour the countdown itself asks for: error once the date has\n\t\t * passed or the day count is at or below `dangerAt`, warning at or\n\t\t * below `warnAt`, else ''.\n\t\t *\n\t\t * A passed date is the danger colour whether or not `dangerAt` is\n\t\t * configured: overdue is not a threshold anybody has to opt into. Both\n\t\t * thresholds are INCLUSIVE, and `dangerAt` is tested first, so exactly\n\t\t * 5 days with `dangerAt: 5` is danger and not warning even when\n\t\t * `warnAt` also matches.\n\t\t *\n\t\t * @return {string} 'error', 'warning', or ''.\n\t\t */\n\t\tcountdownVariant() {\n\t\t\tconst days = this.countdownDays\n\t\t\tif (days === null) {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t\tif (days < 0) {\n\t\t\t\treturn 'error'\n\t\t\t}\n\t\t\tconst cfg = this.countdownConfig\n\t\t\tif (Number.isFinite(cfg.dangerAt) && days <= cfg.dangerAt) {\n\t\t\t\treturn 'error'\n\t\t\t}\n\t\t\tif (Number.isFinite(cfg.warnAt) && days <= cfg.warnAt) {\n\t\t\t\treturn 'warning'\n\t\t\t}\n\t\t\treturn ''\n\t\t},\n\n\t\t/**\n\t\t * The first `content.overrides` entry whose `when` matches the BOUND\n\t\t * RECORD, or null. Needs a detail-page record: on a dashboard there is\n\t\t * nothing to test, so no override applies.\n\t\t *\n\t\t * @return {object|null} The matching override.\n\t\t */\n\t\tactiveOverride() {\n\t\t\tconst rules = this.content.overrides\n\t\t\tif (!Array.isArray(rules) || rules.length === 0) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tconst record = this.objectCtx?.object\n\t\t\tif (!record || typeof record !== 'object') {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\treturn rules.find((rule) => rule && this.matchesOverride(record, rule.when)) || null\n\t\t},\n\n\t\t/**\n\t\t * The translated `content.emptyText` when it applies, else ''.\n\t\t *\n\t\t * It applies to an empty value, and to an `objectField` reference whose\n\t\t * lookup found nothing. Without `emptyText` an unresolvable reference\n\t\t * keeps showing its raw value, as it always has.\n\t\t *\n\t\t * In countdown mode it applies to an UNREADABLE date as well, not only\n\t\t * to an absent one. `'not yet planned'` is a perfectly non-empty value\n\t\t * and there is no countdown to be had from it, so without this the tile\n\t\t * would print the raw string where a deadline belongs.\n\t\t *\n\t\t * @return {string} The text to show instead of the value, or ''.\n\t\t */\n\t\temptyValueText() {\n\t\t\tconst text = this.isCountdown\n\t\t\t\t? (this.countdownConfig.emptyText || this.content.emptyText)\n\t\t\t\t: this.content.emptyText\n\t\t\tif (typeof text !== 'string' || text === '') {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t\tconst v = this.displayValue\n\t\t\tconst empty = v === null || v === undefined || v === ''\n\t\t\tif (empty || (this.objectFieldMode && this.referenceFailed) || (this.isCountdown && this.countdownDays === null)) {\n\t\t\t\treturn this.effectiveTranslate(text)\n\t\t\t}\n\t\t\treturn ''\n\t\t},\n\n\t\t/**\n\t\t * The text the tile shows: an override's label, else the countdown\n\t\t * sentence, else the empty text, else the formatted value.\n\t\t *\n\t\t * The override sits above the countdown for the same reason it sits\n\t\t * above a badge's status: a suspended case is not waiting for its\n\t\t * deadline, so it reads as suspended.\n\t\t *\n\t\t * @return {string} The shown text.\n\t\t */\n\t\tshownValue() {\n\t\t\tconst override = this.activeOverride\n\t\t\tif (override && typeof override.label === 'string' && override.label !== '') {\n\t\t\t\treturn this.effectiveTranslate(override.label)\n\t\t\t}\n\t\t\treturn this.countdownText || this.emptyValueText || this.formattedValue\n\t\t},\n\n\t\t/**\n\t\t * Whether the shown text replaced the formatted value. Such a text is a\n\t\t * word, so it takes the wrapping text style of a name.\n\t\t *\n\t\t * @return {boolean} true when an override or the empty text is shown.\n\t\t */\n\t\tshownValueIsText() {\n\t\t\treturn this.shownValue !== this.formattedValue\n\t\t},\n\n\t\t/**\n\t\t * The variant the RESOLVED ROW asks for through\n\t\t * `objectField.resolve.variantField` / `variantMap`, or ''.\n\t\t *\n\t\t * @return {string} The variant name, or ''.\n\t\t */\n\t\trowVariant() {\n\t\t\tconst cfg = this.content.objectField\n\t\t\tconst resolve = (cfg && typeof cfg === 'object') ? cfg.resolve : null\n\t\t\tif (!resolve || !resolve.variantField || !this.referenceRow) {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t\tconst raw = getByPath(this.referenceRow, resolve.variantField)\n\t\t\tif (raw === undefined || raw === null) {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t\tconst map = resolve.variantMap\n\t\t\tif (map && typeof map === 'object') {\n\t\t\t\tconst hit = map[String(raw)]\n\t\t\t\treturn typeof hit === 'string' ? hit : ''\n\t\t\t}\n\t\t\treturn typeof raw === 'string' ? raw : ''\n\t\t},\n\n\t\t/**\n\t\t * The CnStatusBadge variant in badge mode. Same precedence as the text\n\t\t * colour: override, `variantWhen`, at-limit, resolved row, static\n\t\t * `variant`. The first one that names a badge variant wins.\n\t\t *\n\t\t * @return {string} A CnStatusBadge variant.\n\t\t */\n\t\tbadgeVariant() {\n\t\t\tconst rule = this.activeVariantRule\n\t\t\tconst candidates = [\n\t\t\t\tthis.activeOverride?.variant,\n\t\t\t\trule?.variant,\n\t\t\t\tthis.atLimit ? 'warning' : '',\n\t\t\t\tthis.rowVariant,\n\t\t\t\tthis.content.variant,\n\t\t\t]\n\t\t\tfor (const candidate of candidates) {\n\t\t\t\tconst variant = candidate === 'danger' ? 'error' : candidate\n\t\t\t\tif (BADGE_VARIANTS.includes(variant)) {\n\t\t\t\t\treturn variant\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn 'default'\n\t\t},\n\n\t\t/**\n\t\t * Whether the tile reads a field off the BOUND RECORD rather than\n\t\t * aggregating or calling an endpoint (`content.objectField`).\n\t\t *\n\t\t * The record is already loaded by the detail page, so this costs no\n\t\t * request at all. It is what lets a KPI row headline a case's type or\n\t\t * its assignee beside the counts, instead of those facts being buried\n\t\t * three rows down in the properties grid.\n\t\t *\n\t\t * @return {boolean} true in object-field mode.\n\t\t */\n\t\tobjectFieldMode() {\n\t\t\tconst of = this.content.objectField\n\t\t\treturn !!(of && (typeof of === 'string' || of.field))\n\t\t},\n\n\t\t/**\n\t\t * The bound record's value for `content.objectField`.\n\t\t *\n\t\t * A reference field holds a uuid, which is not something to show a\n\t\t * person, so `resolve` names the register/schema to look the label up in.\n\t\t * The resolved label replaces the uuid; an unresolvable id falls back to\n\t\t * the raw value rather than blanking, exactly as CnFkResolveCell does.\n\t\t *\n\t\t * @return {unknown} The field's value, or null.\n\t\t */\n\t\t/**\n\t\t * The bound record's raw value for `content.objectField`, before any\n\t\t * reference resolution.\n\t\t *\n\t\t * @return {unknown} The raw field value, or null.\n\t\t */\n\t\tobjectFieldRaw() {\n\t\t\tconst cfg = this.content.objectField\n\t\t\tconst field = typeof cfg === 'string' ? cfg : cfg?.field\n\t\t\tconst record = this.objectCtx?.object\n\t\t\tif (!record || !field) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tconst raw = getByPath(record, field)\n\t\t\treturn (raw === undefined || raw === '') ? null : raw\n\t\t},\n\n\t\t/**\n\t\t * @return {unknown} The field's value, or null.\n\t\t */\n\t\tobjectFieldValue() {\n\t\t\tif (this.objectFieldRaw === null) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\t// An unresolved or unresolvable reference falls back to the raw value\n\t\t\t// rather than blanking, the same way CnFkResolveCell does.\n\t\t\treturn this.referenceLabel !== null ? this.referenceLabel : this.objectFieldRaw\n\t\t},\n\n\t\t/**\n\t\t * Loading state for the active source (endpoint or OpenRegister).\n\t\t *\n\t\t * @return {boolean}\n\t\t */\n\t\tdisplayLoading() {\n\t\t\t// A reference lookup is a request like any other, and it is the only\n\t\t\t// one the record mode makes. Leaving it out meant the tile rendered\n\t\t\t// the raw uuid as if it were the answer while the request was still\n\t\t\t// out.\n\t\t\tif (this.objectFieldMode) {\n\t\t\t\treturn this.referencePending\n\t\t\t}\n\t\t\treturn this.endpointMode ? this.epLoading : this.loading\n\t\t},\n\n\t\t/**\n\t\t * Error message for the active source ('' = none).\n\t\t *\n\t\t * @return {string}\n\t\t */\n\t\tdisplayError() {\n\t\t\treturn this.endpointMode ? this.epError : this.error\n\t\t},\n\n\t\t/**\n\t\t * The previous-period value plucked at `content.previousField`\n\t\t * (endpoint mode only), or null when not configured / not numeric.\n\t\t *\n\t\t * @return {number|null}\n\t\t */\n\t\tpreviousValue() {\n\t\t\tif (!this.endpointMode || !this.content.previousField) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tconst v = Number(getByPath(this.epData, this.content.previousField))\n\t\t\treturn Number.isFinite(v) ? v : null\n\t\t},\n\n\t\t/**\n\t\t * Trend percent for the sublabel (the pipelinq KPI contract): a\n\t\t * server-computed percent plucked at `content.deltaField` when set,\n\t\t * else the client-computed change vs `previousField`\n\t\t * (`(current − previous) ÷ |previous| × 100`). Null when the trend is\n\t\t * not configured or not computable (previous of 0, non-numeric values).\n\t\t *\n\t\t * @return {number|null}\n\t\t */\n\t\ttrendPct() {\n\t\t\tif (!this.endpointMode) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tif (this.content.deltaField) {\n\t\t\t\tconst v = Number(getByPath(this.epData, this.content.deltaField))\n\t\t\t\treturn Number.isFinite(v) ? v : null\n\t\t\t}\n\t\t\tconst prev = this.previousValue\n\t\t\tconst cur = Number(this.displayValue)\n\t\t\tif (prev === null || prev === 0 || !Number.isFinite(cur)) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\treturn ((cur - prev) / Math.abs(prev)) * 100\n\t\t},\n\n\t\t/** The signed trend percent, e.g. \"+12.3%\". */\n\t\tformattedTrend() {\n\t\t\tif (this.trendPct === null) {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t\tconst sign = this.trendPct > 0 ? '+' : ''\n\t\t\treturn `${sign}${this.trendPct.toFixed(1)}%`\n\t\t},\n\n\t\t/** The arrow component for the trend direction. */\n\t\ttrendIcon() {\n\t\t\tif (this.trendPct === null || Math.abs(this.trendPct) < 0.05) {\n\t\t\t\treturn 'TrendingNeutral'\n\t\t\t}\n\t\t\treturn this.trendPct > 0 ? 'TrendingUp' : 'TrendingDown'\n\t\t},\n\n\t\t/**\n\t\t * Green when the trend moves in `content.goodDirection` (default\n\t\t * 'up'), red otherwise, neutral for a ~0 change — the CnDeltaWidget\n\t\t * convention.\n\t\t *\n\t\t * @return {string}\n\t\t */\n\t\ttrendColor() {\n\t\t\tif (this.trendPct === null || Math.abs(this.trendPct) < 0.05) {\n\t\t\t\treturn 'var(--color-text-maxcontrast)'\n\t\t\t}\n\t\t\tconst good = this.content.goodDirection || 'up'\n\t\t\tconst rising = this.trendPct > 0\n\t\t\tconst isGood = good === 'up' ? rising : !rising\n\t\t\treturn isGood ? STATUS_TEXT_COLORS.success : STATUS_TEXT_COLORS.error\n\t\t},\n\n\t\t/**\n\t\t * The first `content.variantWhen` rule matching the current display\n\t\t * value (first-match wins), or null. Each rule is\n\t\t * `{ op: eq|neq|gt|gte|lt|lte, value, variant, icon? }`.\n\t\t *\n\t\t * @return {object|null}\n\t\t */\n\t\tactiveVariantRule() {\n\t\t\tconst rules = this.content.variantWhen\n\t\t\tif (!Array.isArray(rules) || rules.length === 0) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tconst current = this.displayValue\n\t\t\tif (current === null || current === undefined) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\treturn rules.find((r) => r && this.matchesRule(current, r)) || null\n\t\t},\n\n\t\t/**\n\t\t * The CSS colour for the matched variant rule ('' = keep the\n\t\t * configured colours).\n\t\t *\n\t\t * @return {string}\n\t\t */\n\t\tvariantColor() {\n\t\t\t// An override describes the RECORD's state (a suspended case), which\n\t\t\t// outranks anything the value itself suggests.\n\t\t\tconst override = this.activeOverride\n\t\t\tif (override && override.variant) {\n\t\t\t\treturn VARIANT_COLORS[override.variant] || ''\n\t\t\t}\n\t\t\tconst rule = this.activeVariantRule\n\t\t\tif (rule && rule.variant) {\n\t\t\t\treturn VARIANT_COLORS[rule.variant] || ''\n\t\t\t}\n\t\t\t// The countdown's own threshold sits below `variantWhen`, which is\n\t\t\t// the author naming a colour outright, and above the at-limit tint,\n\t\t\t// which is the generic one. A passed date reports `error` from here\n\t\t\t// whether or not a threshold was configured.\n\t\t\tif (this.countdownVariant) {\n\t\t\t\treturn VARIANT_COLORS[this.countdownVariant] || ''\n\t\t\t}\n\t\t\t// An explicit variantWhen rule always wins: a tile that says how it\n\t\t\t// wants to be coloured is not overruled by the generic at-limit tint.\n\t\t\tif (this.atLimit) {\n\t\t\t\treturn VARIANT_COLORS.warning || ''\n\t\t\t}\n\t\t\t// The resolved row's colour sits just above the static floor. An\n\t\t\t// unknown name falls through rather than blanking the tile.\n\t\t\tif (this.rowVariant && VARIANT_COLORS[this.rowVariant]) {\n\t\t\t\treturn VARIANT_COLORS[this.rowVariant]\n\t\t\t}\n\t\t\t// A STATIC `variant` is the floor, below both of the above: it is the\n\t\t\t// tile's resting colour, not a signal about the current value, so a\n\t\t\t// threshold rule or an at-limit warning must be able to override it.\n\t\t\t//\n\t\t\t// It exists because that is how CnStatsBlock has always been coloured\n\t\t\t// (`variant=\"success\"`), and a tile migrating from a bespoke card to\n\t\t\t// this component would otherwise silently lose its colour — a change\n\t\t\t// nothing would report, on a dashboard where colour is the fastest\n\t\t\t// thing a reader takes in.\n\t\t\tif (this.content.variant) {\n\t\t\t\treturn VARIANT_COLORS[this.content.variant] || ''\n\t\t\t}\n\t\t\treturn ''\n\t\t},\n\n\t\t/**\n\t\t * The icon shown in the circle: a matched variant rule's `icon`\n\t\t * override, else `content.icon`.\n\t\t *\n\t\t * @return {string}\n\t\t */\n\t\tresolvedIcon() {\n\t\t\tconst override = this.activeOverride\n\t\t\tconst rule = this.activeVariantRule\n\t\t\treturn (override && override.icon) || (rule && rule.icon) || this.content.icon || ''\n\t\t},\n\n\t\t/**\n\t\t * Card orientation. Horizontal (icon beside the number) is the\n\t\t * canonical KPI card; `content.layout: 'vertical'` stacks the icon\n\t\t * above a centred number for a tile taller than it is wide;\n\t\t * `content.layout: 'stacked'` is the board look (see `isStacked`).\n\t\t *\n\t\t * @spec openspec/changes/zuiddrecht-pixel-gaps-2/specs/zuiddrecht-pixel-gaps-2/spec.md#requirement-a-stat-tile-can-take-the-stacked-board-look\n\t\t * @return {'horizontal'|'vertical'|'stacked'}\n\t\t */\n\t\tcardLayout() {\n\t\t\tconst layout = (this.content || {}).layout\n\t\t\tif (layout === 'vertical' || layout === 'stacked') {\n\t\t\t\treturn layout\n\t\t\t}\n\t\t\t// Board look: every KPI tile on the screens is stacked, so a tile\n\t\t\t// that names no layout takes it. An explicit `horizontal` stays.\n\t\t\tif (this.isBoardLook && layout === undefined) {\n\t\t\t\treturn 'stacked'\n\t\t\t}\n\t\t\treturn 'horizontal'\n\t\t},\n\n\t\t/**\n\t\t * Whether the board look draws the icon in a tinted circle at the\n\t\t * right of the label row (`content.iconPlacement: \"end\"`), as the\n\t\t * DqDashboard tiles. Off without the board look and without an icon.\n\t\t *\n\t\t * @spec openspec/changes/screens-stat-tile-parity/specs/dashboard-page/spec.md#requirement-the-board-kpi-tile-can-carry-its-icon-at-the-end\n\t\t * @return {boolean}\n\t\t */\n\t\thasEndBadge() {\n\t\t\treturn this.isBoardLook\n\t\t\t\t&& (this.content || {}).iconPlacement === 'end'\n\t\t\t\t&& Boolean(this.resolvedIcon)\n\t\t},\n\n\t\t/**\n\t\t * The tile's state as a tone name for the end badge: the variant the\n\t\t * value colour comes from (`success`, `warning`, `error`), else\n\t\t * `primary`. A custom `valueColor` has no tone and reads as primary.\n\t\t *\n\t\t * @spec openspec/changes/screens-stat-tile-parity/specs/dashboard-page/spec.md#requirement-the-board-kpi-tile-can-carry-its-icon-at-the-end\n\t\t * @return {'primary'|'success'|'warning'|'error'}\n\t\t */\n\t\tstateTone() {\n\t\t\tconst color = this.variantColor\n\t\t\tif (!color) {\n\t\t\t\treturn 'primary'\n\t\t\t}\n\t\t\tconst tone = ['success', 'warning', 'error'].find((name) => VARIANT_COLORS[name] === color)\n\t\t\treturn tone || 'primary'\n\t\t},\n\n\t\t/**\n\t\t * Whether the tile takes the stacked board look (`content.layout:\n\t\t * \"stacked\"`): a plain muted label, the number at 34px in the text\n\t\t * colour, the caption on a line of its own, and no icon circle. Off by\n\t\t * default.\n\t\t *\n\t\t * @spec openspec/changes/zuiddrecht-pixel-gaps-2/specs/zuiddrecht-pixel-gaps-2/spec.md#requirement-a-stat-tile-can-take-the-stacked-board-look\n\t\t * @return {boolean}\n\t\t */\n\t\tisStacked() {\n\t\t\treturn this.cardLayout === 'stacked'\n\t\t},\n\n\t\t/**\n\t\t * Whether the card draws no box of its own. On by default: every stat\n\t\t * tile is rendered inside a CnWidgetWrapper that already draws a card,\n\t\t * so a second box is a card inside a card. Set `content.flat: false`\n\t\t * for a tile mounted somewhere with no wrapper around it.\n\t\t *\n\t\t * @return {boolean}\n\t\t */\n\t\tflat() {\n\t\t\treturn (this.content || {}).flat !== false\n\t\t},\n\n\t\t/** Inline style for the icon circle (variant rule wins over iconColor). */\n\t\ticonCircleStyle() {\n\t\t\tconst color = this.variantColor || this.content.iconColor || this.content.valueColor || 'var(--color-primary-element)'\n\t\t\treturn { color, backgroundColor: this.tint(color) }\n\t\t},\n\n\t\t/** Inline style for the value text (variant rule wins over valueColor). */\n\t\tvalueStyle() {\n\t\t\tconst color = this.variantColor || this.content.valueColor\n\t\t\treturn color ? { color } : {}\n\t\t},\n\n\t\t/**\n\t\t * The formatted value string per the `content.format` spec. Resolves\n\t\t * `@config.<key>` tokens (e.g. `currency: '@config.currency'`) against the\n\t\t * page-level app config and guards the currency code, so an unresolved\n\t\t * token or invalid currency falls back to a safe default instead of\n\t\t * throwing. See `formatMetricValue`.\n\t\t *\n\t\t * @return {string}\n\t\t */\n\t\tformattedValue() {\n\t\t\treturn formatMetricValue(this.displayValue, this.content.format, this.configCtx, this.objectCtx?.object || null)\n\t\t},\n\n\t\t/**\n\t\t * The capacity this tile is measured against — `content.limitField`\n\t\t * (dot-path into the endpoint payload, so a server-configured quota is\n\t\t * read live) or a static `content.limit`. Null when neither is set or\n\t\t * the resolved value is not a finite number, which is what keeps the\n\t\t * \"value / limit\" rendering off every tile that has no limit.\n\t\t *\n\t\t * @return {number|null}\n\t\t */\n\t\tlimitValue() {\n\t\t\tlet raw = this.content.limit\n\t\t\tif (this.endpointMode && this.content.limitField) {\n\t\t\t\traw = getByPath(this.epData, this.content.limitField)\n\t\t\t}\n\t\t\tconst n = Number(raw)\n\t\t\treturn Number.isFinite(n) ? n : null\n\t\t},\n\n\t\t/**\n\t\t * The limit rendered beside the value, e.g. the \"100\" in \"0 / 100\".\n\t\t * Formatted with the value's own `format` spec minus prefix/suffix —\n\t\t * a suffix belongs to the pair, not to each half, so \"0 % / 100 %\" is\n\t\t * never produced.\n\t\t *\n\t\t * @return {string}\n\t\t */\n\t\tformattedLimit() {\n\t\t\tif (this.limitValue === null) {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t\tconst { prefix, suffix, ...rest } = (this.content.format || {})\n\t\t\treturn formatMetricValue(this.limitValue, rest, this.configCtx, this.objectCtx?.object || null)\n\t\t},\n\n\t\t/**\n\t\t * Whether the tile has reached or passed its limit. Drives the warning\n\t\t * tint when no explicit `variantWhen` rule already claims the colour.\n\t\t *\n\t\t * @return {boolean}\n\t\t */\n\t\tatLimit() {\n\t\t\tif (this.limitValue === null) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\tconst current = Number(this.displayValue)\n\t\t\treturn Number.isFinite(current) && current >= this.limitValue\n\t\t},\n\n\t\t/**\n\t\t * The tile's own range presets (`content.dateRange.presets`). Empty when\n\t\t * the tile has no override, which is also what hides the picker.\n\t\t *\n\t\t * @return {Array<{id: string, label?: string, from?: string, to?: string}>}\n\t\t */\n\t\trangePresets() {\n\t\t\tconst presets = this.content.dateRange?.presets\n\t\t\treturn Array.isArray(presets) ? presets.filter(Boolean) : []\n\t\t},\n\n\t\t/**\n\t\t * The preset id currently selected — the tile's own override when set,\n\t\t * else whatever the dashboard range reports, so the picker opens showing\n\t\t * the page's period rather than a stale default.\n\t\t *\n\t\t * @return {string}\n\t\t */\n\t\tactiveRangePreset() {\n\t\t\treturn (this.tileRange || this.activeRange() || {}).preset || ''\n\t\t},\n\n\t\t/** Accessible name for the range picker (no visible label on a compact tile). */\n\t\trangeAriaLabel() {\n\t\t\tconst label = this.resolvedLabel || this.effectiveTranslate('Date range')\n\t\t\treturn `${label} — ${this.effectiveTranslate('date range')}`\n\t\t},\n\n\t\t/** Stable signature of the data source so the watcher only refetches on real change. */\n\t\tsourceKey() {\n\t\t\treturn JSON.stringify({\n\t\t\t\ts: this.content.source || {},\n\t\t\t\to: this.objectCtx ? this.objectCtx.objectId : null,\n\t\t\t\tp: this.pageCtx,\n\t\t\t\tc: this.configCtx,\n\t\t\t})\n\t\t},\n\t},\n\n\twatch: {\n\t\tsourceKey() {\n\t\t\tthis.fetchValue()\n\t\t},\n\n\t\tobjectFieldRaw: {\n\t\t\timmediate: true,\n\t\t\thandler() {\n\t\t\t\tthis.resolveReference()\n\t\t\t},\n\t\t},\n\t},\n\n\tmounted() {\n\t\tthis.fetchValue()\n\t\t// The `endpointSource` path refreshes through useEndpointSource; this\n\t\t// covers the `source` path, which otherwise never re-read on Refresh.\n\t\tthis._onPageRefresh = (payload) => {\n\t\t\tif (this.endpointMode) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst done = this.fetchValue(payload)\n\t\t\tpayload?.waitUntil?.(done)\n\t\t}\n\t\tsubscribe(PAGE_REFRESH_CHANNEL, this._onPageRefresh)\n\t},\n\n\tbeforeUnmount() {\n\t\tunsubscribe(PAGE_REFRESH_CHANNEL, this._onPageRefresh)\n\t},\n\n\tmethods: {\n\t\t/**\n\t\t * Resolve an `objectField` that holds a reference uuid to the referenced\n\t\t * object's label, through the shared object store (per-schema caching and\n\t\t * in-flight dedup come for free).\n\t\t *\n\t\t * Does nothing unless `objectField.resolve` names a register and schema:\n\t\t * a plain scalar field needs no lookup, and guessing that a string looks\n\t\t * like a uuid would turn a legitimate identifier into a failed fetch.\n\t\t *\n\t\t * @return {Promise<void>}\n\t\t */\n\t\tasync resolveReference() {\n\t\t\tthis.referenceLabel = null\n\t\t\tthis.referenceRow = null\n\t\t\tthis.referenceFailed = false\n\t\t\tthis.referencePending = false\n\t\t\tconst cfg = this.content.objectField\n\t\t\tconst resolve = (cfg && typeof cfg === 'object') ? cfg.resolve : null\n\t\t\tconst raw = this.objectFieldRaw\n\t\t\tif (!resolve || !resolve.register || !resolve.schema || !raw) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\t// Assigned by the try below, and the catch returns rather than falling\n\t\t\t// through, so an initialiser here would never be read.\n\t\t\tlet store\n\t\t\ttry {\n\t\t\t\tstore = useObjectStore()\n\t\t\t} catch {\n\t\t\t\t// No active Pinia: the tile shows the raw value, which is correct\n\t\t\t\t// and never blank.\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif (!store) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tconst type = resolveObjectOpType(store, { register: resolve.register, schema: resolve.schema })\n\t\t\tconst id = String(raw)\n\t\t\tconst cached = store.objects && store.objects[type] && store.objects[type][id]\n\t\t\t// Only an actual request pends. A cache hit resolves in the same\n\t\t\t// tick, and flagging it would flicker a loading icon for nothing.\n\t\t\tif (!cached) {\n\t\t\t\tthis.referencePending = true\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tconst obj = cached || await store.fetchObject(type, id)\n\t\t\t\t// The record may have moved on while the lookup was in flight.\n\t\t\t\t// The newer call owns the state, so this one touches nothing.\n\t\t\t\tif (String(this.objectFieldRaw) !== id) {\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t\tthis.referencePending = false\n\t\t\t\tif (obj && typeof obj === 'object') {\n\t\t\t\t\tthis.referenceRow = obj\n\t\t\t\t}\n\t\t\t\tconst label = this.pickReferenceLabel(obj, resolve.labelField)\n\t\t\t\tif (label) {\n\t\t\t\t\tthis.referenceLabel = label\n\t\t\t\t} else {\n\t\t\t\t\tthis.referenceFailed = true\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\t// Leave the raw value showing, unless `emptyText` says otherwise.\n\t\t\t\tif (String(this.objectFieldRaw) === id) {\n\t\t\t\t\tthis.referencePending = false\n\t\t\t\t\tthis.referenceFailed = true\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Whether an override's `when` matches the bound record. Uses the local\n\t\t * `visibleWhen` grammar (`{ field, op, value }`); a `when` with neither\n\t\t * `op` nor `value` is a truthiness test on the field.\n\t\t *\n\t\t * @param {object} record The bound record.\n\t\t * @param {{field: string, op?: string, value?: unknown}} when The condition.\n\t\t * @return {boolean} True when the override applies.\n\t\t */\n\t\tmatchesOverride(record, when) {\n\t\t\tif (!when || typeof when !== 'object' || typeof when.field !== 'string' || when.field === '') {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\tconst compares = Object.hasOwn(when, 'value') || Boolean(when.op)\n\t\t\tif (!compares) {\n\t\t\t\treturn Boolean(readVisibleWhenPath(record, when.field))\n\t\t\t}\n\t\t\treturn evaluateVisibleWhenLocal(when, record)\n\t\t},\n\n\t\t/**\n\t\t * Pick a display label off a resolved reference: the configured field\n\t\t * first, then `title`, then `@self.name`. A per-language map collapses to\n\t\t * its first non-empty value.\n\t\t *\n\t\t * @param {object|null} obj The referenced object.\n\t\t * @param {string} [labelField] The preferred label property.\n\t\t * @return {string} The label, or '' when none is usable.\n\t\t */\n\t\tpickReferenceLabel(obj, labelField) {\n\t\t\tif (!obj || typeof obj !== 'object') {\n\t\t\t\treturn ''\n\t\t\t}\n\t\t\tconst candidates = [obj[labelField || 'title'], obj.title, obj.name, obj['@self'] && obj['@self'].name]\n\t\t\tfor (const value of candidates) {\n\t\t\t\tif (typeof value === 'string' && value !== '') {\n\t\t\t\t\treturn value\n\t\t\t\t}\n\t\t\t\tif (typeof value === 'number') {\n\t\t\t\t\treturn String(value)\n\t\t\t\t}\n\t\t\t\tif (value && typeof value === 'object' && !Array.isArray(value)) {\n\t\t\t\t\tconst first = Object.values(value).find((v) => typeof v === 'string' && v !== '')\n\t\t\t\t\tif (first) {\n\t\t\t\t\t\treturn first\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn ''\n\t\t},\n\n\t\t/**\n\t\t * Derive a faint background tint for the icon circle from a colour.\n\t\t * Falls back to the NC light primary token for CSS variables / unknowns.\n\t\t *\n\t\t * @param {string} color The base colour (hex or CSS var).\n\t\t * @return {string} A translucent or token background.\n\t\t */\n\t\t/**\n\t\t * Apply a per-tile range preset. Writes the tile override, which the\n\t\t * endpoint ctx reads, so the tile refetches on its own period while the\n\t\t * rest of the dashboard stays on the page range.\n\t\t *\n\t\t * @param {string} presetId The chosen preset's id.\n\t\t * @return {void}\n\t\t */\n\t\tselectRange(presetId) {\n\t\t\tconst preset = this.rangePresets.find((p) => p.id === presetId)\n\t\t\tif (!preset) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.tileRange = { preset: preset.id, from: preset.from ?? null, to: preset.to ?? null }\n\t\t},\n\n\t\ttint(color) {\n\t\t\tif (typeof color === 'string' && /^#([0-9a-f]{6})$/i.test(color)) {\n\t\t\t\treturn color + '1f' // ~12% alpha\n\t\t\t}\n\t\t\treturn 'var(--color-primary-element-light, rgba(0,130,201,0.1))'\n\t\t},\n\n\t\t/**\n\t\t * Whether a `variantWhen` rule matches the current value. Numeric\n\t\t * comparison when both sides coerce to numbers; `eq` / `neq` fall back\n\t\t * to strict string equality for non-numeric values.\n\t\t *\n\t\t * @param {unknown} current The current display value.\n\t\t * @param {{op: string, value: unknown}} rule The threshold rule.\n\t\t * @return {boolean} True when the rule matches.\n\t\t */\n\t\tmatchesRule(current, rule) {\n\t\t\tconst a = Number(current)\n\t\t\tconst b = Number(rule.value)\n\t\t\tconst numeric = Number.isFinite(a) && Number.isFinite(b)\n\t\t\tswitch (rule.op) {\n\t\t\t\tcase 'eq': return numeric ? a === b : String(current) === String(rule.value)\n\t\t\t\tcase 'neq': return numeric ? a !== b : String(current) !== String(rule.value)\n\t\t\t\tcase 'gt': return numeric && a > b\n\t\t\t\tcase 'gte': return numeric && a >= b\n\t\t\t\tcase 'lt': return numeric && a < b\n\t\t\t\tcase 'lte': return numeric && a <= b\n\t\t\t\tdefault: return false\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * Flatten a filter map into `filter[key]=value` / `filter[key][op]=value`\n\t\t * query params (operator-aware, matching the OpenRegister vocabulary).\n\t\t *\n\t\t * @param {object} target The params object to write into.\n\t\t * @param {object} filter The filter map.\n\t\t * @return {void}\n\t\t */\n\t\tflattenFilter(target, filter) {\n\t\t\tif (!filter || typeof filter !== 'object') {\n\t\t\t\treturn\n\t\t\t}\n\t\t\t// Resolve `@objectId` / `@object.*` (detail page), `@workspace.*`\n\t\t\t// (page-level context — e.g. the dashboard date-range pills publish\n\t\t\t// `dateFrom` / `dateTo`) AND `@config.*` (page-level app config), then\n\t\t\t// drop any optional `@workspace.<key>?` / `@config.<key>?` that stayed\n\t\t\t// unresolved so an unset value omits the filter (show all) instead of\n\t\t\t// sending a literal token.\n\t\t\tfilter = this.resolveSourceFilter(filter)\n\t\t\tfor (const [k, v] of Object.entries(filter)) {\n\t\t\t\tif (v && typeof v === 'object') {\n\t\t\t\t\tfor (const [op, ov] of Object.entries(v)) {\n\t\t\t\t\t\ttarget[`filter[${k}][${op}]`] = ov\n\t\t\t\t\t}\n\t\t\t\t} else if (v !== '' && v !== null && v !== undefined) {\n\t\t\t\t\ttarget[`filter[${k}]`] = v\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * A source filter with its @-tokens resolved against the object, page\n\t\t * and config contexts, and unresolved optional clauses dropped.\n\t\t *\n\t\t * @param {object} filter The raw filter map.\n\t\t * @return {object} The resolved filter.\n\t\t */\n\t\tresolveSourceFilter(filter) {\n\t\t\tif (!filter || typeof filter !== 'object') {\n\t\t\t\treturn {}\n\t\t\t}\n\t\t\tconst ctx = { ...(this.objectCtx || {}), workspace: this.pageCtx, config: this.configCtx }\n\t\t\treturn dropOptionalUnresolved(resolveFilterTokens(filter, ctx))\n\t\t},\n\n\t\t/**\n\t\t * Fetch one scalar from the OpenRegister `/value` aggregation endpoint.\n\t\t *\n\t\t * @param {object} axios The axios instance.\n\t\t * @param {(url: string, params?: object) => string} generateUrl The router helper.\n\t\t * @param {object} s The source (register/schema).\n\t\t * @param {string} metric The aggregation metric.\n\t\t * @param {?string} field The numeric field (non-count metrics).\n\t\t * @param {object} filter The filter map.\n\t\t * @param {string} [via] `\"list\"` counts through the list endpoint's total.\n\t\t * @return {Promise<number|null>} The aggregated value.\n\t\t */\n\t\tasync fetchAggregate(axios, generateUrl, s, metric, field, filter, via) {\n\t\t\t// A count the aggregation endpoint cannot express (a filter holding a\n\t\t\t// list of values, a test for no value (`null` or `{ isnull: true }`),\n\t\t\t// or `via: \"list\"`) reads the list endpoint's total instead, because\n\t\t\t// the aggregation endpoint has no null operator.\n\t\t\tconst resolved = this.resolveSourceFilter(filter)\n\t\t\tconst listed = Object.values(resolved).some((v) => Array.isArray(v) || (v && typeof v === 'object' && Object.values(v).some(Array.isArray)))\n\t\t\tif ((!metric || metric === 'count') && (via === 'list' || listed || needsListEndpoint(resolved))) {\n\t\t\t\treturn fetchListTotal(s.register, s.schema, resolved, {})\n\t\t\t}\n\t\t\tconst url = generateUrl(\n\t\t\t\t'/apps/openregister/api/objects/aggregations/{register}/{schema}/value',\n\t\t\t\t{ register: s.register, schema: s.schema },\n\t\t\t)\n\t\t\tconst params = { metric: metric || 'count' }\n\t\t\tif (field) {\n\t\t\t\tparams.field = field\n\t\t\t}\n\t\t\tthis.flattenFilter(params, filter)\n\t\t\tconst res = await axios.get(url, { params })\n\t\t\treturn res?.data?.value ?? null\n\t\t},\n\n\t\t/**\n\t\t * Resolve the widget's value from its `source`. Supports three source\n\t\t * kinds (ADR-041): a plain `aggregate` (count/sum/avg/min/max with\n\t\t * operator filters), a `ratio` (numerator ÷ denominator × 100, e.g. a\n\t\t * win-rate), and a `weighted` sum (Σ field × weightField ÷ divisor,\n\t\t * computed client-side over the fetched objects). Lazily imports\n\t\t * axios/router (same pattern as CnFilesWidget).\n\t\t *\n\t\t * @param {object} [refresh] The page refresh event's payload, when this is one.\n\t\t * @return {Promise<void>}\n\t\t */\n\t\tasync fetchValue(refresh) {\n\t\t\t// Endpoint-bound tiles are fetched by the shared useEndpointSource\n\t\t\t// engine (see setup) — the OpenRegister paths below must not fire.\n\t\t\tif (this.endpointMode) {\n\t\t\t\tthis.value = null\n\t\t\t\tthis.error = ''\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst s = this.content.source || {}\n\t\t\t// An `endpoint` source reads an arbitrary app REST endpoint instead\n\t\t\t// of OpenRegister's per-schema aggregation, so it needs no register/schema.\n\t\t\tif (s.kind !== 'endpoint' && (!s.register || !s.schema)) {\n\t\t\t\tthis.value = null\n\t\t\t\tthis.error = ''\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif (s.kind === 'endpoint' && !s.url) {\n\t\t\t\tthis.value = null\n\t\t\t\tthis.error = ''\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.loading = true\n\t\t\tthis.error = ''\n\t\t\ttry {\n\t\t\t\tconst [{ default: axios }, { generateUrl }] = await Promise.all([\n\t\t\t\t\timport('@nextcloud/axios'),\n\t\t\t\t\timport('@nextcloud/router'),\n\t\t\t\t])\n\n\t\t\t\tif (s.kind === 'endpoint') {\n\t\t\t\t\tthis.value = await this.fetchEndpoint(s, refresh)\n\t\t\t\t} else if (s.kind === 'ratio') {\n\t\t\t\t\t// Each part may name its own metric, field and `via`, so \"answered\n\t\t\t\t\t// in time\" over \"answered\" is two counts, and a share of a sum is\n\t\t\t\t\t// two sums.\n\t\t\t\t\tconst part = (p) => this.fetchAggregate(axios, generateUrl, s, (p && p.metric) || s.metric, (p && p.field) || s.field, (p && p.filter) || {}, (p && p.via) || s.via)\n\t\t\t\t\tconst num = await part(s.numerator)\n\t\t\t\t\tconst den = await part(s.denominator)\n\t\t\t\t\tthis.value = (den && Number(den) !== 0) ? (Number(num) / Number(den)) * 100 : null\n\t\t\t\t} else if (s.kind === 'elapsed') {\n\t\t\t\t\tthis.value = await this.fetchElapsed(axios, generateUrl, s)\n\t\t\t\t} else if (s.kind === 'computed') {\n\t\t\t\t\t// Fetch each named part, then evaluate the formula over them.\n\t\t\t\t\tconst { evalFormula } = await import('../../utils/evalFormula.js')\n\t\t\t\t\tconst parts = s.parts || {}\n\t\t\t\t\tconst vars = {}\n\t\t\t\t\tfor (const [name, p] of Object.entries(parts)) {\n\t\t\t\t\t\tvars[name] = Number(await this.fetchAggregate(axios, generateUrl, s, p.metric || 'count', p.field, p.filter || {})) || 0\n\t\t\t\t\t}\n\t\t\t\t\tthis.value = evalFormula(s.formula || '', vars)\n\t\t\t\t} else if (s.kind === 'weighted') {\n\t\t\t\t\tthis.value = await this.fetchWeighted(axios, generateUrl, s)\n\t\t\t\t} else {\n\t\t\t\t\tthis.value = await this.fetchAggregate(axios, generateUrl, s, s.metric, s.field, s.filter || {}, s.via)\n\t\t\t\t}\n\t\t\t} catch (e) {\n\t\t\t\tthis.error = (e && e.message) || 'error'\n\t\t\t\tthis.value = null\n\t\t\t} finally {\n\t\t\t\tthis.loading = false\n\t\t\t}\n\t\t},\n\n\t\t/**\n\t\t * The average time between two date fields of the matching objects\n\t\t * (`{ from, to, unit?, filter?, limit? }`): an average answer time is\n\t\t * `occurredAt` to `resolvedAt`. Computed client-side over the fetched\n\t\t * objects (capped at `limit`, default 1000), because the aggregation\n\t\t * endpoint averages one numeric field, not a difference. Objects missing\n\t\t * either date, or with `to` before `from`, are left out; null when none\n\t\t * is left. `unit` is `days` (default), `hours` or `minutes`.\n\t\t *\n\t\t * @param {object} axios The axios instance.\n\t\t * @param {(url: string, params?: object) => string} generateUrl The router helper.\n\t\t * @param {object} s The elapsed source.\n\t\t * @return {Promise<number|null>} The average, in `unit`.\n\t\t * @spec openspec/changes/screens-ratio-stat/specs/ratio-stat/spec.md#requirement-a-stat-can-average-the-time-between-two-dates\n\t\t */\n\t\tasync fetchElapsed(axios, generateUrl, s) {\n\t\t\tif (!s.from || !s.to) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tconst url = generateUrl(\n\t\t\t\t'/apps/openregister/api/objects/{register}/{schema}',\n\t\t\t\t{ register: s.register, schema: s.schema },\n\t\t\t)\n\t\t\tconst params = { _limit: s.limit || 1000 }\n\t\t\tconst filter = this.resolveSourceFilter(s.filter || {})\n\t\t\tfor (const [k, v] of Object.entries(filter)) {\n\t\t\t\tif (v && typeof v === 'object' && !Array.isArray(v)) {\n\t\t\t\t\tfor (const [op, operand] of Object.entries(v)) {\n\t\t\t\t\t\tparams[`${k}[${op}]`] = operand\n\t\t\t\t\t}\n\t\t\t\t} else if (v !== '' && v !== null && v !== undefined) {\n\t\t\t\t\tparams[k] = v\n\t\t\t\t}\n\t\t\t}\n\t\t\tconst res = await axios.get(url, { params })\n\t\t\tconst rows = (res && res.data && res.data.results) || []\n\t\t\tconst per = { minutes: 60000, hours: 3600000, days: 86400000 }[s.unit] || 86400000\n\t\t\tlet sum = 0\n\t\t\tlet n = 0\n\t\t\tfor (const r of rows) {\n\t\t\t\tconst from = Date.parse(r && r[s.from])\n\t\t\t\tconst to = Date.parse(r && r[s.to])\n\t\t\t\tif (Number.isFinite(from) && Number.isFinite(to) && to >= from) {\n\t\t\t\t\tsum += (to - from) / per\n\t\t\t\t\tn += 1\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn n > 0 ? sum / n : null\n\t\t},\n\n\t\t/**\n\t\t * Compute a weighted sum `Σ (field × weightField) ÷ divisor` client-side\n\t\t * (no OpenRegister expression-aggregation primitive yet). Pulls the\n\t\t * matching objects (capped at `limit`, default 1000) and folds them.\n\t\t *\n\t\t * @param {object} axios The axios instance.\n\t\t * @param {(url: string, params?: object) => string} generateUrl The router helper.\n\t\t * @param {object} s The weighted source `{ field, weightField, divisor?, filter?, limit? }`.\n\t\t * @return {Promise<number|null>} The weighted sum.\n\t\t */\n\t\tasync fetchWeighted(axios, generateUrl, s) {\n\t\t\tif (!s.field || !s.weightField) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tconst url = generateUrl(\n\t\t\t\t'/apps/openregister/api/objects/{register}/{schema}',\n\t\t\t\t{ register: s.register, schema: s.schema },\n\t\t\t)\n\t\t\tconst params = { _limit: s.limit || 1000 }\n\t\t\tthis.flattenFilter(params, s.filter || {})\n\t\t\tconst res = await axios.get(url, { params })\n\t\t\tconst rows = (res && res.data && res.data.results) || []\n\t\t\tconst divisor = Number(s.divisor) || 1\n\t\t\tlet sum = 0\n\t\t\tfor (const r of rows) {\n\t\t\t\tconst v = Number(r[s.field])\n\t\t\t\tconst w = Number(r[s.weightField])\n\t\t\t\tif (Number.isFinite(v) && Number.isFinite(w)) {\n\t\t\t\t\tsum += (v * w) / divisor\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn sum\n\t\t},\n\n\t\t/**\n\t\t * Resolve `@page.<key>` / `@workspace.<key>` / `@config.<key>` /\n\t\t * `@objectId` / `@object.<field>` tokens inside a string against the page\n\t\t * + config + object contexts. `@page.*` is an alias for `@workspace.*`\n\t\t * (both read the page-level context); `@config.*` reads the page-level app\n\t\t * config. Unresolved tokens collapse to an empty string so a half-built\n\t\t * URL never sends a literal `@page.period`.\n\t\t *\n\t\t * @param {string} str The raw string (URL or param value).\n\t\t * @return {string} The interpolated string.\n\t\t */\n\t\tinterpolateTokens(str) {\n\t\t\tif (typeof str !== 'string') {\n\t\t\t\treturn str\n\t\t\t}\n\t\t\treturn str.replace(/@(page|workspace)\\.([A-Za-z0-9_]+)/g, (_, _ns, key) => {\n\t\t\t\tconst v = this.pageCtx[key]\n\t\t\t\treturn (v === undefined || v === null) ? '' : String(v)\n\t\t\t}).replace(/@config\\.([A-Za-z0-9_]+)/g, (_, key) => {\n\t\t\t\tconst v = this.configCtx[key]\n\t\t\t\treturn (v === undefined || v === null) ? '' : String(v)\n\t\t\t}).replace(/@objectId/g, () => {\n\t\t\t\tconst id = this.objectCtx && this.objectCtx.objectId\n\t\t\t\treturn (id === undefined || id === null) ? '' : String(id)\n\t\t\t}).replace(/@object\\.([A-Za-z0-9_]+)/g, (_, field) => {\n\t\t\t\tconst v = this.objectCtx && this.objectCtx.object && this.objectCtx.object[field]\n\t\t\t\treturn (v === undefined || v === null) ? '' : String(v)\n\t\t\t})\n\t\t},\n\n\t\t/**\n\t\t * Read a dot-path off an object (e.g. `\"data.totalLeads\"`, `\"summary.0.count\"`).\n\t\t * Returns undefined when any segment is missing.\n\t\t *\n\t\t * @param {object} obj The source object.\n\t\t * @param {string} path The dot-path.\n\t\t * @return {unknown} The resolved value or undefined.\n\t\t */\n\t\tgetByPath(obj, path) {\n\t\t\t// Delegates to the shared useEndpointSource util so the legacy\n\t\t\t// `source.kind: 'endpoint'` path and the Wave-2 `endpointSource`\n\t\t\t// path pluck identically.\n\t\t\treturn getByPath(obj, path)\n\t\t},\n\n\t\t/**\n\t\t * Fetch a single value from an arbitrary app REST endpoint. The `url` and\n\t\t * any string `params` value are token-interpolated (`@page.*` etc.), the\n\t\t * response is read at `path` (dot-path; default = whole body), and the\n\t\t * result is coerced to a number when numeric. Lets a dashboard KPI bind\n\t\t * to a custom-aggregation endpoint (e.g. `/api/analytics/summary`) that\n\t\t * OpenRegister's per-schema aggregation can't express.\n\t\t *\n\t\t * Never served from the settled shared cache, so a tile never shows a\n\t\t * count from before a write. Tiles loading at once, or reached by one\n\t\t * page refresh, share a single request per endpoint and params.\n\t\t *\n\t\t * @param {object} s The endpoint source `{ url, path?, params?, method? }`.\n\t\t * @param {object} [refresh] The page refresh event's payload, when this is one.\n\t\t * @return {Promise<number|null>} The extracted value.\n\t\t */\n\t\tasync fetchEndpoint(s, refresh) {\n\t\t\tconst params = {}\n\t\t\tfor (const [k, v] of Object.entries(s.params || {})) {\n\t\t\t\tparams[k] = typeof v === 'string' ? this.interpolateTokens(v) : v\n\t\t\t}\n\t\t\tconst body = await fetchSharedResponse(\n\t\t\t\t{ url: this.interpolateTokens(s.url), method: 'GET', params },\n\t\t\t\trefresh ? { force: true, refresh } : { fresh: true },\n\t\t\t)\n\t\t\tconst extracted = this.getByPath(body, s.path)\n\t\t\tif (extracted === undefined || extracted === null) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tconst num = Number(extracted)\n\t\t\treturn Number.isFinite(num) ? num : extracted\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n/*\n * The card itself — its box, body stack, icon circle, title and value\n * typography — is the CANONICAL KPI card in src/css/kpi-card.css, shared with\n * CnStatsBlock. What remains here is only what is specific to THIS widget: the\n * range select, the \"/ limit\" denominator, the trend chip and the error glyph.\n *\n * Every size below is expressed against the shared `--cn-kpi-*` scale rather\n * than as its own number, so the widget's extras re-scale with the card they\n * sit in. Resist adding card styling back, and resist restating a value the\n * scale already holds; that is what split the two KPI looks apart in the first\n * place.\n */\n\n/* The title row carries an optional range select beside the label, which the\n canonical `__title` (a plain truncating heading) does not account for. */\n.cn-stat-widget__label {\n\tdisplay: flex;\n\talign-items: center;\n\tjustify-content: space-between;\n\tgap: 8px;\n\twidth: 100%;\n}\n\n/* Stacked tile: the label and its range select centre over the number rather\n than spreading to the card's edges. */\n.cn-kpi-card--vertical .cn-stat-widget__label {\n\tjustify-content: center;\n\twidth: auto;\n}\n\n/* Sized down to sit inside the label row without pushing the tile taller —\n the tile's height is fixed by its grid cell (ADR-062). */\n.cn-stat-widget__range {\n\tflex: 0 0 auto;\n\tmax-width: 50%;\n\tpadding: 0 4px;\n\tborder: none;\n\tborder-radius: var(--border-radius);\n\tbackground: transparent;\n\tcolor: var(--cn-kpi-label-color, var(--color-text-maxcontrast));\n\tfont-size: var(--cn-kpi-label-size, 13px);\n\tfont-weight: normal;\n\tcursor: pointer;\n}\n\n.cn-stat-widget__range:hover,\n.cn-stat-widget__range:focus-visible {\n\tbackground: var(--color-background-hover);\n\tcolor: var(--color-main-text);\n}\n\n/* Badge mode: the pill takes the value's place in the row. Sized to the\n card's label scale so it sits in the row without pushing the tile taller. */\n.cn-stat-widget__badge {\n\tflex: 0 1 auto;\n\tmin-width: 0;\n\tmax-width: 100%;\n\toverflow: hidden;\n\ttext-overflow: ellipsis;\n\tfont-size: var(--cn-kpi-label-size, 13px);\n}\n\n/* The denominator of a \"value / limit\" pair. Deliberately quieter and smaller\n than the value: the tile's subject is what the number IS, not what it is\n allowed to reach. Shares the value's `nowrap` so the pair never breaks. */\n.cn-stat-widget__limit {\n\tflex: 0 0 auto;\n\tfont-size: var(--cn-kpi-value-size-compact, 1.25rem);\n\tfont-weight: var(--cn-kpi-title-weight, 600);\n\tline-height: var(--cn-kpi-value-line, 1.1);\n\tcolor: var(--cn-kpi-label-color, var(--color-text-maxcontrast));\n\twhite-space: nowrap;\n}\n\n.cn-stat-widget__trend {\n\tdisplay: inline-flex;\n\talign-items: center;\n\tgap: 2px;\n\tfont-size: var(--cn-kpi-label-size, 13px);\n\tfont-weight: var(--cn-kpi-title-weight, 600);\n}\n\n/* The dash shown when the number could not be fetched. It stands where the\n value stands, so it takes the value's size and weight — CnStatsBlock's own\n error dash is literally a `cn-kpi-card__value`, and two components showing\n the same failure at two different sizes is the drift this consolidation\n exists to remove. Only the colour differs: a failure is not a number. */\n.cn-stat-widget__error {\n\tfont-size: var(--cn-kpi-value-size, 2rem);\n\tfont-weight: var(--cn-kpi-value-weight, 700);\n\tline-height: var(--cn-kpi-value-line, 1.1);\n\tcolor: var(--cn-kpi-label-color, var(--color-text-maxcontrast));\n}\n</style>\n"],"names":["CnWidgetIcon","CnStatusBadge","TrendingUp"],"mappings":"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"}