@conduction/nextcloud-vue 2.75.0 → 2.77.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 (158) hide show
  1. package/dist/esm/components/CnAppNav/CnAppNav.vue2.js +18 -3
  2. package/dist/esm/components/CnAppNav/CnAppNav.vue2.js.map +1 -1
  3. package/dist/esm/components/CnAppNav/CnAppNav.vue3.js +49 -3
  4. package/dist/esm/components/CnAppNav/CnAppNav.vue3.js.map +1 -1
  5. package/dist/esm/components/CnCardGrid/CnCardGrid.vue2.js +6 -0
  6. package/dist/esm/components/CnCardGrid/CnCardGrid.vue2.js.map +1 -1
  7. package/dist/esm/components/CnCardGrid/CnCardGrid.vue3.js +3 -2
  8. package/dist/esm/components/CnCardGrid/CnCardGrid.vue3.js.map +1 -1
  9. package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue2.js +42 -1
  10. package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue2.js.map +1 -1
  11. package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue3.js +228 -203
  12. package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue3.js.map +1 -1
  13. package/dist/esm/components/CnCellRenderer/CnGroupNameCell.vue.js +9 -0
  14. package/dist/esm/components/CnCellRenderer/CnGroupNameCell.vue.js.map +1 -0
  15. package/dist/esm/components/CnCellRenderer/CnGroupNameCell.vue2.js +50 -0
  16. package/dist/esm/components/CnCellRenderer/CnGroupNameCell.vue2.js.map +1 -0
  17. package/dist/esm/components/CnCellRenderer/CnGroupNameCell.vue3.js +13 -0
  18. package/dist/esm/components/CnCellRenderer/CnGroupNameCell.vue3.js.map +1 -0
  19. package/dist/esm/components/CnCredentials/CnCredentials.vue2.js +11 -10
  20. package/dist/esm/components/CnCredentials/CnCredentials.vue2.js.map +1 -1
  21. package/dist/esm/components/CnCredentials/CnCredentials.vue3.js.map +1 -1
  22. package/dist/esm/components/CnDataTable/CnDataTable.vue2.js +41 -4
  23. package/dist/esm/components/CnDataTable/CnDataTable.vue2.js.map +1 -1
  24. package/dist/esm/components/CnDataTable/CnDataTable.vue3.js +90 -51
  25. package/dist/esm/components/CnDataTable/CnDataTable.vue3.js.map +1 -1
  26. package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js +24 -33
  27. package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js.map +1 -1
  28. package/dist/esm/components/CnDetailPage/CnDetailPage.vue3.js +12 -24
  29. package/dist/esm/components/CnDetailPage/CnDetailPage.vue3.js.map +1 -1
  30. package/dist/esm/components/CnFavouriteToggle/CnFavouriteToggle.vue2.js +7 -2
  31. package/dist/esm/components/CnFavouriteToggle/CnFavouriteToggle.vue2.js.map +1 -1
  32. package/dist/esm/components/CnFavouriteToggle/CnFavouriteToggle.vue3.js.map +1 -1
  33. package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue2.js +114 -1
  34. package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue2.js.map +1 -1
  35. package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue3.js +115 -62
  36. package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue3.js.map +1 -1
  37. package/dist/esm/components/CnFollowToggle/CnFollowToggle.vue2.js +89 -7
  38. package/dist/esm/components/CnFollowToggle/CnFollowToggle.vue2.js.map +1 -1
  39. package/dist/esm/components/CnFollowToggle/CnFollowToggle.vue3.js +62 -30
  40. package/dist/esm/components/CnFollowToggle/CnFollowToggle.vue3.js.map +1 -1
  41. package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js +242 -19
  42. package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js.map +1 -1
  43. package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js +25 -20
  44. package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js.map +1 -1
  45. package/dist/esm/components/CnIndexPage/selfModeActions.js +90 -14
  46. package/dist/esm/components/CnIndexPage/selfModeActions.js.map +1 -1
  47. package/dist/esm/components/CnIndexPage/useSelfFetchList.js +15 -3
  48. package/dist/esm/components/CnIndexPage/useSelfFetchList.js.map +1 -1
  49. package/dist/esm/components/CnObjectCard/CnObjectCard.vue2.js +26 -0
  50. package/dist/esm/components/CnObjectCard/CnObjectCard.vue2.js.map +1 -1
  51. package/dist/esm/components/CnObjectCard/CnObjectCard.vue3.js +26 -9
  52. package/dist/esm/components/CnObjectCard/CnObjectCard.vue3.js.map +1 -1
  53. package/dist/esm/components/CnObjectDataWidget/CnObjectDataWidget.vue2.js +199 -7
  54. package/dist/esm/components/CnObjectDataWidget/CnObjectDataWidget.vue2.js.map +1 -1
  55. package/dist/esm/components/CnObjectDataWidget/CnObjectDataWidget.vue3.js +155 -119
  56. package/dist/esm/components/CnObjectDataWidget/CnObjectDataWidget.vue3.js.map +1 -1
  57. package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue2.js +19 -3
  58. package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue2.js.map +1 -1
  59. package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue3.js.map +1 -1
  60. package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue2.js +6 -0
  61. package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue2.js.map +1 -1
  62. package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue3.js +4 -1
  63. package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue3.js.map +1 -1
  64. package/dist/esm/components/CnRelatedObjectsWidget/CnRelatedObjectsWidget.vue2.js +153 -38
  65. package/dist/esm/components/CnRelatedObjectsWidget/CnRelatedObjectsWidget.vue2.js.map +1 -1
  66. package/dist/esm/components/CnRelatedObjectsWidget/CnRelatedObjectsWidget.vue3.js +74 -56
  67. package/dist/esm/components/CnRelatedObjectsWidget/CnRelatedObjectsWidget.vue3.js.map +1 -1
  68. package/dist/esm/components/CnWidgetObjectTable/CnWidgetObjectTable.vue2.js +13 -0
  69. package/dist/esm/components/CnWidgetObjectTable/CnWidgetObjectTable.vue2.js.map +1 -1
  70. package/dist/esm/components/CnWidgetObjectTable/CnWidgetObjectTable.vue3.js.map +1 -1
  71. package/dist/esm/composables/useListView.js +4 -0
  72. package/dist/esm/composables/useListView.js.map +1 -1
  73. package/dist/esm/composables/useObjectLock.js +41 -10
  74. package/dist/esm/composables/useObjectLock.js.map +1 -1
  75. package/dist/esm/index.js +3 -1
  76. package/dist/esm/index.js.map +1 -1
  77. package/dist/esm/l10n/en.json.js +31 -1
  78. package/dist/esm/l10n/en.json.js.map +1 -1
  79. package/dist/esm/l10n/nl.json.js +32 -2
  80. package/dist/esm/l10n/nl.json.js.map +1 -1
  81. package/dist/esm/nextcloud-vue.css +376 -75
  82. package/dist/esm/store/plugins/interactions.js +20 -10
  83. package/dist/esm/store/plugins/interactions.js.map +1 -1
  84. package/dist/esm/store/useObjectStore.js +54 -9
  85. package/dist/esm/store/useObjectStore.js.map +1 -1
  86. package/dist/esm/utils/builtInFormatters.js +15 -7
  87. package/dist/esm/utils/builtInFormatters.js.map +1 -1
  88. package/dist/esm/utils/groupAutocomplete.js +63 -1
  89. package/dist/esm/utils/groupAutocomplete.js.map +1 -1
  90. package/dist/esm/utils/lensAvailability.js +90 -0
  91. package/dist/esm/utils/lensAvailability.js.map +1 -0
  92. package/dist/esm/utils/objectSignals.js +44 -0
  93. package/dist/esm/utils/objectSignals.js.map +1 -0
  94. package/dist/esm/utils/personalLenses.js +13 -6
  95. package/dist/esm/utils/personalLenses.js.map +1 -1
  96. package/dist/esm/utils/recordInteractions.js +31 -13
  97. package/dist/esm/utils/recordInteractions.js.map +1 -1
  98. package/dist/esm/utils/resolveFilterTokens.js +46 -3
  99. package/dist/esm/utils/resolveFilterTokens.js.map +1 -1
  100. package/dist/esm/utils/schema.js +1 -1
  101. package/dist/esm/utils/schema.js.map +1 -1
  102. package/dist/esm/utils/sentinelTokens.js +4 -4
  103. package/dist/esm/utils/sentinelTokens.js.map +1 -1
  104. package/dist/esm/utils/validateManifestV2.compiled.js +2 -2
  105. package/dist/esm/utils/validateManifestV2.compiled.js.map +1 -1
  106. package/dist/esm/utils/widgetVisibility.js +46 -1
  107. package/dist/esm/utils/widgetVisibility.js.map +1 -1
  108. package/dist/nextcloud-vue.cjs.js +4732 -2990
  109. package/dist/nextcloud-vue.cjs.js.map +2 -2
  110. package/dist/nextcloud-vue.css +376 -75
  111. package/l10n/en.json +31 -1
  112. package/l10n/nl.json +32 -2
  113. package/package.json +1 -1
  114. package/src/components/CnAppNav/CnAppNav.vue +44 -5
  115. package/src/components/CnCardGrid/CnCardGrid.md +1 -0
  116. package/src/components/CnCardGrid/CnCardGrid.vue +7 -0
  117. package/src/components/CnCellRenderer/CnCellRenderer.vue +56 -1
  118. package/src/components/CnCellRenderer/CnGroupNameCell.vue +61 -0
  119. package/src/components/CnCredentials/CnCredentials.vue +17 -16
  120. package/src/components/CnDataTable/CnDataTable.md +9 -0
  121. package/src/components/CnDataTable/CnDataTable.vue +80 -20
  122. package/src/components/CnDetailPage/CnDetailPage.vue +18 -32
  123. package/src/components/CnFavouriteToggle/CnFavouriteToggle.vue +7 -2
  124. package/src/components/CnFilesBrowser/CnFilesBrowser.vue +204 -5
  125. package/src/components/CnFollowToggle/CnFollowToggle.vue +118 -13
  126. package/src/components/CnIndexPage/CnIndexPage.md +51 -0
  127. package/src/components/CnIndexPage/CnIndexPage.vue +261 -35
  128. package/src/components/CnIndexPage/selfModeActions.js +89 -13
  129. package/src/components/CnIndexPage/useSelfFetchList.js +15 -3
  130. package/src/components/CnObjectCard/CnObjectCard.md +1 -0
  131. package/src/components/CnObjectCard/CnObjectCard.vue +89 -1
  132. package/src/components/CnObjectDataWidget/CnObjectDataWidget.vue +226 -2
  133. package/src/components/CnObjectListWidget/CnObjectListWidget.vue +19 -3
  134. package/src/components/CnObjectSidebar/CnFilesTab.vue +9 -0
  135. package/src/components/CnRelatedObjectsWidget/CnRelatedObjectsWidget.vue +181 -38
  136. package/src/components/CnWidgetObjectTable/CnWidgetObjectTable.vue +13 -0
  137. package/src/composables/__tests__/useObjectLock.endpoints.spec.js +83 -0
  138. package/src/composables/useListView.js +4 -0
  139. package/src/composables/useObjectLock.js +41 -10
  140. package/src/css/look-board-detail.css +40 -2
  141. package/src/css/look-board-index.css +35 -1
  142. package/src/css/table.css +82 -17
  143. package/src/index.js +3 -1
  144. package/src/schemas/app-manifest-v2.schema.json +11 -7
  145. package/src/store/plugins/interactions.js +20 -10
  146. package/src/store/useObjectStore.js +54 -9
  147. package/src/utils/builtInFormatters.js +15 -7
  148. package/src/utils/groupAutocomplete.js +75 -0
  149. package/src/utils/index.js +2 -1
  150. package/src/utils/lensAvailability.js +86 -0
  151. package/src/utils/objectSignals.js +41 -0
  152. package/src/utils/personalLenses.js +13 -6
  153. package/src/utils/recordInteractions.js +31 -13
  154. package/src/utils/resolveFilterTokens.js +45 -2
  155. package/src/utils/schema.js +1 -1
  156. package/src/utils/sentinelTokens.js +4 -4
  157. package/src/utils/validateManifestV2.compiled.js +2 -2
  158. package/src/utils/widgetVisibility.js +45 -0
@@ -1 +1 @@
1
- {"version":3,"file":"CnFollowToggle.vue2.js","sources":["../../../../src/components/CnFollowToggle/CnFollowToggle.vue"],"sourcesContent":["<!--\n - SPDX-FileCopyrightText: 2026 Conduction B.V.\n - SPDX-License-Identifier: EUPL-1.2\n-->\n<template>\n\t<span class=\"cn-follow-toggle\" data-testid=\"cn-follow-toggle\">\n\t\t<NcButton\n\t\t\t:variant=\"state ? 'secondary' : 'tertiary'\"\n\t\t\t:aria-pressed=\"state ? 'true' : 'false'\"\n\t\t\t:title=\"tooltip\"\n\t\t\t:disabled=\"busy\"\n\t\t\tdata-testid=\"cn-follow-toggle-button\"\n\t\t\t@click.stop=\"toggle\">\n\t\t\t<template #icon>\n\t\t\t\t<Bell v-if=\"state\" :size=\"20\" />\n\t\t\t\t<BellOutline v-else :size=\"20\" />\n\t\t\t</template>\n\t\t\t{{ state ? followingLabel : followLabel }}\n\t\t</NcButton>\n\t\t<NcPopover\n\t\t\tv-if=\"count !== null\"\n\t\t\tv-model:shown=\"open\"\n\t\t\tplacement=\"bottom-start\">\n\t\t\t<template #trigger>\n\t\t\t\t<NcButton\n\t\t\t\t\tvariant=\"tertiary\"\n\t\t\t\t\tclass=\"cn-follow-toggle__count\"\n\t\t\t\t\t:aria-label=\"followersLabel\"\n\t\t\t\t\tdata-testid=\"cn-follow-toggle-count\">\n\t\t\t\t\t{{ count }}\n\t\t\t\t</NcButton>\n\t\t\t</template>\n\t\t\t<div class=\"cn-follow-toggle__popover\" data-testid=\"cn-follow-toggle-popover\">\n\t\t\t\t<NcLoadingIcon v-if=\"loadingWatchers\" :size=\"20\" :name=\"loadingLabel\" />\n\t\t\t\t<ul v-else class=\"cn-follow-toggle__list\">\n\t\t\t\t\t<li v-for=\"watcher in watchers\" :key=\"watcher.userId\" class=\"cn-follow-toggle__row\">\n\t\t\t\t\t\t<NcAvatar :user=\"watcher.userId\"\n\t\t\t\t\t\t\t:displayName=\"watcher.displayName || watcher.userId\"\n\t\t\t\t\t\t\t:size=\"28\"\n\t\t\t\t\t\t\thideStatus />\n\t\t\t\t\t\t<span class=\"cn-follow-toggle__who\">\n\t\t\t\t\t\t\t<span class=\"cn-follow-toggle__name\">{{ watcher.displayName || watcher.userId }}</span>\n\t\t\t\t\t\t\t<span v-if=\"watcher.created\" class=\"cn-follow-toggle__since\">{{ sinceText(watcher.created) }}</span>\n\t\t\t\t\t\t</span>\n\t\t\t\t\t\t<NcButton\n\t\t\t\t\t\t\tv-if=\"canRemove(watcher)\"\n\t\t\t\t\t\t\tvariant=\"tertiary\"\n\t\t\t\t\t\t\t:aria-label=\"removeFollowerLabel(watcher)\"\n\t\t\t\t\t\t\t:title=\"removeFollowerLabel(watcher)\"\n\t\t\t\t\t\t\tdata-testid=\"cn-follow-toggle-remove\"\n\t\t\t\t\t\t\t@click=\"removeWatcher(watcher)\">\n\t\t\t\t\t\t\t<template #icon>\n\t\t\t\t\t\t\t\t<Close :size=\"16\" />\n\t\t\t\t\t\t\t</template>\n\t\t\t\t\t\t</NcButton>\n\t\t\t\t\t</li>\n\t\t\t\t</ul>\n\t\t\t\t<div v-if=\"canManage\" class=\"cn-follow-toggle__picker\">\n\t\t\t\t\t<NcSelect\n\t\t\t\t\t\t:inputLabel=\"addColleagueLabel\"\n\t\t\t\t\t\t:modelValue=\"null\"\n\t\t\t\t\t\t:options=\"pickerOptions\"\n\t\t\t\t\t\t:loading=\"pickerLoading\"\n\t\t\t\t\t\t:filterable=\"false\"\n\t\t\t\t\t\tlabel=\"label\"\n\t\t\t\t\t\tdata-testid=\"cn-follow-toggle-picker\"\n\t\t\t\t\t\t@search=\"onPickerSearch\"\n\t\t\t\t\t\t@update:modelValue=\"addWatcher\" />\n\t\t\t\t</div>\n\t\t\t\t<p v-if=\"popoverError\"\n\t\t\t\t\tclass=\"cn-follow-toggle__error\"\n\t\t\t\t\trole=\"alert\"\n\t\t\t\t\tdata-testid=\"cn-follow-toggle-error\">\n\t\t\t\t\t{{ popoverError }}\n\t\t\t\t</p>\n\t\t\t</div>\n\t\t</NcPopover>\n\t</span>\n</template>\n\n<script>\nimport { translate as t } from '@nextcloud/l10n'\nimport { NcAvatar, NcButton, NcLoadingIcon, NcPopover, NcSelect } from '@nextcloud/vue'\nimport Bell from 'vue-material-design-icons/Bell.vue'\nimport BellOutline from 'vue-material-design-icons/BellOutline.vue'\nimport Close from 'vue-material-design-icons/Close.vue'\nimport { patchStoredSelf } from '../../utils/patchStoredSelf.js'\nimport { listWatchers, setWatcher, setWatching } from '../../utils/recordInteractions.js'\nimport { searchNextcloudUsers } from '../../utils/userAutocomplete.js'\n\n/**\n * CnFollowToggle — a Follow toggle bound to a record's `@self.watching` marker,\n * with the follower count and a followers popover for users who may see them.\n *\n * A click flips the toggle at once and sends `PUT` or `DELETE .../watch`; on\n * failure it flips back and shows the server's message, and a 404 says the\n * user can no longer see the record and emits `not-found`. The count shows\n * only when `watcherCount` is given (OpenRegister sets `@self.watcherCount` for\n * a reader with `update` only); opening the popover then fetches\n * `GET .../watchers`, never before, and a 403 closes it quietly. With\n * `canManage` (`@self.can.manage`) the popover offers an \"Add a colleague\"\n * picker and a remove action on each follower; without it, only the user's own\n * row can be removed.\n *\n * Example:\n * ```vue\n * <CnFollowToggle register=\"pipelinq\" schema=\"ticket\" :object-id=\"id\"\n * :watching=\"self.watching\" :watcher-count=\"self.watcherCount\" :can-manage=\"self.can && self.can.manage\" />\n * ```\n */\nexport default {\n\tname: 'CnFollowToggle',\n\n\tcomponents: { Bell, BellOutline, Close, NcAvatar, NcButton, NcLoadingIcon, NcPopover, NcSelect },\n\n\tprops: {\n\t\t/** Register slug of the record. */\n\t\tregister: {\n\t\t\ttype: String,\n\t\t\trequired: true,\n\t\t},\n\n\t\t/** Schema slug of the record. */\n\t\tschema: {\n\t\t\ttype: String,\n\t\t\trequired: true,\n\t\t},\n\n\t\t/** Id of the record. */\n\t\tobjectId: {\n\t\t\ttype: String,\n\t\t\trequired: true,\n\t\t},\n\n\t\t/** Whether the current user follows the record (`@self.watching`). */\n\t\twatching: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\n\t\t/** Number of followers (`@self.watcherCount`). Null hides the count and the popover. */\n\t\twatcherCount: {\n\t\t\ttype: Number,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/** Whether the user may add and remove other followers (`@self.can.manage`). */\n\t\tcanManage: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\n\t\t/** Whether following sends change notifications. False changes the tooltip to say it does not. */\n\t\tnotifies: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: true,\n\t\t},\n\n\t\t/** User id of the current user. Defaults to Nextcloud's `OC.currentUser`. */\n\t\tcurrentUser: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\t},\n\n\temits: ['change', 'error', 'not-found'],\n\n\tdata() {\n\t\treturn {\n\t\t\tstate: this.watching,\n\t\t\tcount: this.watcherCount,\n\t\t\tbusy: false,\n\t\t\topen: false,\n\t\t\twatchers: [],\n\t\t\tloadingWatchers: false,\n\t\t\tpopoverError: '',\n\t\t\tpickerOptions: [],\n\t\t\tpickerLoading: false,\n\t\t}\n\t},\n\n\tcomputed: {\n\t\tfollowLabel() {\n\t\t\treturn t('nextcloud-vue', 'Follow')\n\t\t},\n\n\t\tfollowingLabel() {\n\t\t\treturn t('nextcloud-vue', 'Following')\n\t\t},\n\n\t\tloadingLabel() {\n\t\t\treturn t('nextcloud-vue', 'Loading …')\n\t\t},\n\n\t\taddColleagueLabel() {\n\t\t\treturn t('nextcloud-vue', 'Add a colleague')\n\t\t},\n\n\t\tfollowersLabel() {\n\t\t\treturn t('nextcloud-vue', '{count} followers', { count: this.count })\n\t\t},\n\n\t\ttooltip() {\n\t\t\treturn this.notifies\n\t\t\t\t? t('nextcloud-vue', 'Follow this record to get its updates')\n\t\t\t\t: t('nextcloud-vue', 'You will see it under Following. This register sends no change notifications.')\n\t\t},\n\n\t\tme() {\n\t\t\treturn this.currentUser || (typeof OC !== 'undefined' && OC ? OC.currentUser : '') || ''\n\t\t},\n\t},\n\n\twatch: {\n\t\twatching(value) {\n\t\t\tthis.state = value\n\t\t},\n\n\t\twatcherCount(value) {\n\t\t\tthis.count = value\n\t\t},\n\n\t\topen(value) {\n\t\t\tif (value) {\n\t\t\t\tthis.loadWatchers()\n\t\t\t}\n\t\t},\n\t},\n\n\tmethods: {\n\t\tsinceText(created) {\n\t\t\tconst d = new Date(created)\n\t\t\treturn Number.isNaN(d.getTime())\n\t\t\t\t? ''\n\t\t\t\t: t('nextcloud-vue', 'Since {date}', { date: d.toLocaleDateString() })\n\t\t},\n\n\t\tremoveFollowerLabel(watcher) {\n\t\t\treturn t('nextcloud-vue', 'Remove {name} as a follower', { name: watcher.displayName || watcher.userId })\n\t\t},\n\n\t\tcanRemove(watcher) {\n\t\t\treturn this.canManage || (this.me !== '' && watcher.userId === this.me)\n\t\t},\n\n\t\tasync toggle() {\n\t\t\tif (this.busy) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst previous = this.state\n\t\t\tthis.state = !previous\n\t\t\tif (this.count !== null) {\n\t\t\t\tthis.count = Math.max(0, this.count + (this.state ? 1 : -1))\n\t\t\t}\n\t\t\tthis.busy = true\n\t\t\tconst result = await setWatching(this.register, this.schema, this.objectId, this.state)\n\t\t\tthis.busy = false\n\t\t\tif (!result.ok) {\n\t\t\t\tthis.state = previous\n\t\t\t\tif (this.count !== null) {\n\t\t\t\t\tthis.count = Math.max(0, this.count + (previous ? 1 : -1))\n\t\t\t\t}\n\t\t\t\tconst message = result.status === 404\n\t\t\t\t\t? t('nextcloud-vue', 'You can no longer see this record.')\n\t\t\t\t\t: (result.message || t('nextcloud-vue', 'Could not change following.'))\n\t\t\t\timport('@nextcloud/dialogs').then(({ showError }) => showError(message)).catch(() => {})\n\t\t\t\t/** @event error Emitted when a call failed; payload is the message shown. */\n\t\t\t\tthis.$emit('error', message)\n\t\t\t\tif (result.status === 404) {\n\t\t\t\t\t/** @event not-found Emitted on a 404: the record went away or access was withdrawn. */\n\t\t\t\t\tthis.$emit('not-found')\n\t\t\t\t}\n\t\t\t\treturn\n\t\t\t}\n\t\t\tpatchStoredSelf(this.register, this.schema, this.objectId, {\n\t\t\t\twatching: this.state,\n\t\t\t\t...(this.count !== null ? { watcherCount: this.count } : {}),\n\t\t\t})\n\t\t\t/** @event change Emitted after a successful call. Payload: `{ watching, count }`. */\n\t\t\tthis.$emit('change', { watching: this.state, count: this.count })\n\t\t},\n\n\t\tasync loadWatchers() {\n\t\t\tthis.popoverError = ''\n\t\t\tthis.loadingWatchers = true\n\t\t\tconst result = await listWatchers(this.register, this.schema, this.objectId)\n\t\t\tthis.loadingWatchers = false\n\t\t\tif (!result.ok) {\n\t\t\t\t// No right to see the list (403) or a failure: close without a toast.\n\t\t\t\tthis.open = false\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst data = result.data || {}\n\t\t\tthis.watchers = Array.isArray(data.results) ? data.results : []\n\t\t\tthis.count = Number.isFinite(data.total) ? data.total : this.watchers.length\n\t\t},\n\n\t\tasync onPickerSearch(query) {\n\t\t\tthis.pickerLoading = true\n\t\t\tconst found = await searchNextcloudUsers(query || '', { limit: 10 })\n\t\t\tconst already = new Set(this.watchers.map((w) => w.userId))\n\t\t\tthis.pickerOptions = found.filter((u) => !already.has(u.id)).map((u) => ({ ...u, label: u.label || u.displayName || u.id }))\n\t\t\tthis.pickerLoading = false\n\t\t},\n\n\t\tasync addWatcher(option) {\n\t\t\tif (!option || !option.id) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.popoverError = ''\n\t\t\tconst result = await setWatcher(this.register, this.schema, this.objectId, option.id, true)\n\t\t\tif (!result.ok) {\n\t\t\t\tthis.popoverError = result.message || t('nextcloud-vue', 'Could not add this colleague.')\n\t\t\t\treturn\n\t\t\t}\n\t\t\tawait this.loadWatchers()\n\t\t},\n\n\t\tasync removeWatcher(watcher) {\n\t\t\tthis.popoverError = ''\n\t\t\tconst result = await setWatcher(this.register, this.schema, this.objectId, watcher.userId, false)\n\t\t\tif (!result.ok) {\n\t\t\t\tthis.popoverError = result.message || t('nextcloud-vue', 'Could not remove this follower.')\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif (watcher.userId === this.me) {\n\t\t\t\tthis.state = false\n\t\t\t\tthis.$emit('change', { watching: false, count: this.count })\n\t\t\t}\n\t\t\tawait this.loadWatchers()\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n.cn-follow-toggle {\n\tdisplay: inline-flex;\n\talign-items: center;\n\tgap: 4px;\n}\n\n.cn-follow-toggle__popover {\n\tmin-width: 260px;\n\tpadding: 12px;\n}\n\n.cn-follow-toggle__list {\n\tlist-style: none;\n\tmargin: 0 0 8px;\n\tpadding: 0;\n}\n\n.cn-follow-toggle__row {\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 8px;\n\tpadding: 4px 0;\n}\n\n.cn-follow-toggle__who {\n\tdisplay: flex;\n\tflex-direction: column;\n\tflex: 1 1 auto;\n\tmin-width: 0;\n}\n\n.cn-follow-toggle__since {\n\tcolor: var(--color-text-maxcontrast);\n\tfont-size: var(--font-size-small, 13px);\n}\n\n.cn-follow-toggle__error {\n\tmargin: 8px 0 0;\n\tcolor: var(--color-error-text);\n}\n</style>\n"],"names":["Bell","t"],"mappings":"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"}
1
+ {"version":3,"file":"CnFollowToggle.vue2.js","sources":["../../../../src/components/CnFollowToggle/CnFollowToggle.vue"],"sourcesContent":["<!--\n - SPDX-FileCopyrightText: 2026 Conduction B.V.\n - SPDX-License-Identifier: EUPL-1.2\n-->\n<template>\n\t<span class=\"cn-follow-toggle\"\n\t\t:class=\"{ 'cn-follow-toggle--compact': compact }\"\n\t\tdata-testid=\"cn-follow-toggle\">\n\t\t<NcButton\n\t\t\t:variant=\"state && !compact ? 'secondary' : 'tertiary'\"\n\t\t\t:aria-pressed=\"state ? 'true' : 'false'\"\n\t\t\t:aria-label=\"compact ? (state ? followingLabel : followLabel) : undefined\"\n\t\t\t:title=\"tooltip\"\n\t\t\t:disabled=\"busy\"\n\t\t\tdata-testid=\"cn-follow-toggle-button\"\n\t\t\t@click.stop=\"toggle\">\n\t\t\t<template #icon>\n\t\t\t\t<Eye v-if=\"state\" :size=\"20\" class=\"cn-follow-toggle__on\" />\n\t\t\t\t<EyeOutline v-else :size=\"20\" />\n\t\t\t</template>\n\t\t\t<template v-if=\"!compact\">\n\t\t\t\t{{ state ? followingLabel : followLabel }}\n\t\t\t</template>\n\t\t</NcButton>\n\t\t<NcButton\n\t\t\tv-if=\"showNotifySwitch\"\n\t\t\tvariant=\"tertiary\"\n\t\t\t:aria-pressed=\"notifyState ? 'true' : 'false'\"\n\t\t\t:aria-label=\"notifyLabel\"\n\t\t\t:title=\"notifyLabel\"\n\t\t\t:disabled=\"busy\"\n\t\t\tdata-testid=\"cn-follow-toggle-notify\"\n\t\t\t@click.stop=\"toggleNotify\">\n\t\t\t<template #icon>\n\t\t\t\t<Bell v-if=\"notifyState\" :size=\"20\" />\n\t\t\t\t<BellOffOutline v-else :size=\"20\" />\n\t\t\t</template>\n\t\t</NcButton>\n\t\t<NcPopover\n\t\t\tv-if=\"count !== null && !compact\"\n\t\t\tv-model:shown=\"open\"\n\t\t\tplacement=\"bottom-start\">\n\t\t\t<template #trigger>\n\t\t\t\t<NcButton\n\t\t\t\t\tvariant=\"tertiary\"\n\t\t\t\t\tclass=\"cn-follow-toggle__count\"\n\t\t\t\t\t:aria-label=\"followersLabel\"\n\t\t\t\t\tdata-testid=\"cn-follow-toggle-count\">\n\t\t\t\t\t{{ count }}\n\t\t\t\t</NcButton>\n\t\t\t</template>\n\t\t\t<div class=\"cn-follow-toggle__popover\" data-testid=\"cn-follow-toggle-popover\">\n\t\t\t\t<NcLoadingIcon v-if=\"loadingWatchers\" :size=\"20\" :name=\"loadingLabel\" />\n\t\t\t\t<ul v-else class=\"cn-follow-toggle__list\">\n\t\t\t\t\t<li v-for=\"watcher in watchers\" :key=\"watcher.userId\" class=\"cn-follow-toggle__row\">\n\t\t\t\t\t\t<NcAvatar :user=\"watcher.userId\"\n\t\t\t\t\t\t\t:displayName=\"watcher.displayName || watcher.userId\"\n\t\t\t\t\t\t\t:size=\"28\"\n\t\t\t\t\t\t\thideStatus />\n\t\t\t\t\t\t<span class=\"cn-follow-toggle__who\">\n\t\t\t\t\t\t\t<span class=\"cn-follow-toggle__name\">{{ watcher.displayName || watcher.userId }}</span>\n\t\t\t\t\t\t\t<span v-if=\"watcher.created\" class=\"cn-follow-toggle__since\">{{ sinceText(watcher.created) }}</span>\n\t\t\t\t\t\t</span>\n\t\t\t\t\t\t<NcButton\n\t\t\t\t\t\t\tv-if=\"canRemove(watcher)\"\n\t\t\t\t\t\t\tvariant=\"tertiary\"\n\t\t\t\t\t\t\t:aria-label=\"removeFollowerLabel(watcher)\"\n\t\t\t\t\t\t\t:title=\"removeFollowerLabel(watcher)\"\n\t\t\t\t\t\t\tdata-testid=\"cn-follow-toggle-remove\"\n\t\t\t\t\t\t\t@click=\"removeWatcher(watcher)\">\n\t\t\t\t\t\t\t<template #icon>\n\t\t\t\t\t\t\t\t<Close :size=\"16\" />\n\t\t\t\t\t\t\t</template>\n\t\t\t\t\t\t</NcButton>\n\t\t\t\t\t</li>\n\t\t\t\t</ul>\n\t\t\t\t<div v-if=\"canManage\" class=\"cn-follow-toggle__picker\">\n\t\t\t\t\t<NcSelect\n\t\t\t\t\t\t:inputLabel=\"addColleagueLabel\"\n\t\t\t\t\t\t:modelValue=\"null\"\n\t\t\t\t\t\t:options=\"pickerOptions\"\n\t\t\t\t\t\t:loading=\"pickerLoading\"\n\t\t\t\t\t\t:filterable=\"false\"\n\t\t\t\t\t\tlabel=\"label\"\n\t\t\t\t\t\tdata-testid=\"cn-follow-toggle-picker\"\n\t\t\t\t\t\t@search=\"onPickerSearch\"\n\t\t\t\t\t\t@update:modelValue=\"addWatcher\" />\n\t\t\t\t</div>\n\t\t\t\t<p v-if=\"popoverError\"\n\t\t\t\t\tclass=\"cn-follow-toggle__error\"\n\t\t\t\t\trole=\"alert\"\n\t\t\t\t\tdata-testid=\"cn-follow-toggle-error\">\n\t\t\t\t\t{{ popoverError }}\n\t\t\t\t</p>\n\t\t\t</div>\n\t\t</NcPopover>\n\t</span>\n</template>\n\n<script>\nimport { translate as t } from '@nextcloud/l10n'\nimport { NcAvatar, NcButton, NcLoadingIcon, NcPopover, NcSelect } from '@nextcloud/vue'\nimport Bell from 'vue-material-design-icons/Bell.vue'\nimport BellOffOutline from 'vue-material-design-icons/BellOffOutline.vue'\nimport Close from 'vue-material-design-icons/Close.vue'\nimport Eye from 'vue-material-design-icons/Eye.vue'\nimport EyeOutline from 'vue-material-design-icons/EyeOutline.vue'\nimport { patchStoredSelf } from '../../utils/patchStoredSelf.js'\nimport { listWatchers, setWatcher, setWatching } from '../../utils/recordInteractions.js'\nimport { searchNextcloudUsers } from '../../utils/userAutocomplete.js'\n\n/**\n * CnFollowToggle — the one Follow control of a record: a Follow toggle bound to\n * `@self.watching`, a notifications switch bound to `@self.watchNotify`, the\n * follower count and a followers popover for users who may see them.\n *\n * Following and favourites are one feature (OpenRegister's\n * `merge-follow-and-favourites`): a favourite is a follow with notifications\n * off, so there is no separate star. While the user follows, a bell beside the\n * toggle turns the follow's notifications on or off (`PUT .../watch` with\n * `{\"notify\": bool}`). With `notifies` false (the register sends no change\n * notifications) the bell is not offered. `compact` renders the toggle as an\n * icon only, without the bell, count or popover, for a column in a list.\n *\n * A click flips the toggle at once and sends `PUT` or `DELETE .../watch`; on\n * failure it flips back and shows the server's message, and a 404 says the\n * user can no longer see the record and emits `not-found`. The count shows\n * only when `watcherCount` is given (OpenRegister sets `@self.watcherCount` for\n * a reader with `update` only); opening the popover then fetches\n * `GET .../watchers`, never before, and a 403 closes it quietly. With\n * `canManage` (`@self.can.manage`) the popover offers an \"Add a colleague\"\n * picker and a remove action on each follower; without it, only the user's own\n * row can be removed.\n *\n * Example:\n * ```vue\n * <CnFollowToggle register=\"pipelinq\" schema=\"ticket\" :object-id=\"id\"\n * :watching=\"self.watching\" :notify=\"self.watchNotify\"\n * :watcher-count=\"self.watcherCount\" :can-manage=\"self.can && self.can.manage\" />\n * ```\n */\nexport default {\n\tname: 'CnFollowToggle',\n\n\tcomponents: { Bell, BellOffOutline, Close, Eye, EyeOutline, NcAvatar, NcButton, NcLoadingIcon, NcPopover, NcSelect },\n\n\tprops: {\n\t\t/** Register slug of the record. */\n\t\tregister: {\n\t\t\ttype: String,\n\t\t\trequired: true,\n\t\t},\n\n\t\t/** Schema slug of the record. */\n\t\tschema: {\n\t\t\ttype: String,\n\t\t\trequired: true,\n\t\t},\n\n\t\t/** Id of the record. */\n\t\tobjectId: {\n\t\t\ttype: String,\n\t\t\trequired: true,\n\t\t},\n\n\t\t/** Whether the current user follows the record (`@self.watching`). */\n\t\twatching: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\n\t\t/**\n\t\t * Whether the user's follow notifies them (`@self.watchNotify`). Null\n\t\t * (an older server, or not following) reads as on.\n\t\t */\n\t\tnotify: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/** Icon only, without the bell, count or popover: for a column in a list. */\n\t\tcompact: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\n\t\t/** Number of followers (`@self.watcherCount`). Null hides the count and the popover. */\n\t\twatcherCount: {\n\t\t\ttype: Number,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/** Whether the user may add and remove other followers (`@self.can.manage`). */\n\t\tcanManage: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\n\t\t/** Whether following sends change notifications. False changes the tooltip to say it does not. */\n\t\tnotifies: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: true,\n\t\t},\n\n\t\t/** User id of the current user. Defaults to Nextcloud's `OC.currentUser`. */\n\t\tcurrentUser: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\t},\n\n\temits: ['change', 'error', 'not-found'],\n\n\tdata() {\n\t\treturn {\n\t\t\tstate: this.watching,\n\t\t\tnotifyState: this.notify !== false,\n\t\t\tcount: this.watcherCount,\n\t\t\tbusy: false,\n\t\t\topen: false,\n\t\t\twatchers: [],\n\t\t\tloadingWatchers: false,\n\t\t\tpopoverError: '',\n\t\t\tpickerOptions: [],\n\t\t\tpickerLoading: false,\n\t\t}\n\t},\n\n\tcomputed: {\n\t\tfollowLabel() {\n\t\t\treturn t('nextcloud-vue', 'Follow')\n\t\t},\n\n\t\tfollowingLabel() {\n\t\t\treturn t('nextcloud-vue', 'Following')\n\t\t},\n\n\t\tloadingLabel() {\n\t\t\treturn t('nextcloud-vue', 'Loading …')\n\t\t},\n\n\t\taddColleagueLabel() {\n\t\t\treturn t('nextcloud-vue', 'Add a colleague')\n\t\t},\n\n\t\tnotifyLabel() {\n\t\t\treturn this.notifyState\n\t\t\t\t? t('nextcloud-vue', 'Turn notifications off')\n\t\t\t\t: t('nextcloud-vue', 'Turn notifications on')\n\t\t},\n\n\t\t/**\n\t\t * Whether the bell renders: following, not compact, and the register notifies.\n\t\t *\n\t\t * @return {boolean}\n\t\t */\n\t\tshowNotifySwitch() {\n\t\t\treturn this.state && !this.compact && this.notifies\n\t\t},\n\n\t\tfollowersLabel() {\n\t\t\treturn t('nextcloud-vue', '{count} followers', { count: this.count })\n\t\t},\n\n\t\ttooltip() {\n\t\t\treturn this.notifies\n\t\t\t\t? t('nextcloud-vue', 'Follow this record to get its updates')\n\t\t\t\t: t('nextcloud-vue', 'You will see it under Following. This register sends no change notifications.')\n\t\t},\n\n\t\tme() {\n\t\t\treturn this.currentUser || (typeof OC !== 'undefined' && OC ? OC.currentUser : '') || ''\n\t\t},\n\t},\n\n\twatch: {\n\t\twatching(value) {\n\t\t\tthis.state = value\n\t\t},\n\n\t\tnotify(value) {\n\t\t\tthis.notifyState = value !== false\n\t\t},\n\n\t\twatcherCount(value) {\n\t\t\tthis.count = value\n\t\t},\n\n\t\topen(value) {\n\t\t\tif (value) {\n\t\t\t\tthis.loadWatchers()\n\t\t\t}\n\t\t},\n\t},\n\n\tmethods: {\n\t\tsinceText(created) {\n\t\t\tconst d = new Date(created)\n\t\t\treturn Number.isNaN(d.getTime())\n\t\t\t\t? ''\n\t\t\t\t: t('nextcloud-vue', 'Since {date}', { date: d.toLocaleDateString() })\n\t\t},\n\n\t\tremoveFollowerLabel(watcher) {\n\t\t\treturn t('nextcloud-vue', 'Remove {name} as a follower', { name: watcher.displayName || watcher.userId })\n\t\t},\n\n\t\tcanRemove(watcher) {\n\t\t\treturn this.canManage || (this.me !== '' && watcher.userId === this.me)\n\t\t},\n\n\t\tasync toggle() {\n\t\t\tif (this.busy) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst previous = this.state\n\t\t\tthis.state = !previous\n\t\t\tif (this.count !== null) {\n\t\t\t\tthis.count = Math.max(0, this.count + (this.state ? 1 : -1))\n\t\t\t}\n\t\t\tthis.busy = true\n\t\t\tconst result = await setWatching(this.register, this.schema, this.objectId, this.state)\n\t\t\tthis.busy = false\n\t\t\tif (!result.ok) {\n\t\t\t\tthis.state = previous\n\t\t\t\tif (this.count !== null) {\n\t\t\t\t\tthis.count = Math.max(0, this.count + (previous ? 1 : -1))\n\t\t\t\t}\n\t\t\t\tconst message = result.status === 404\n\t\t\t\t\t? t('nextcloud-vue', 'You can no longer see this record.')\n\t\t\t\t\t: (result.message || t('nextcloud-vue', 'Could not change following.'))\n\t\t\t\timport('@nextcloud/dialogs').then(({ showError }) => showError(message)).catch(() => {})\n\t\t\t\t/** @event error Emitted when a call failed; payload is the message shown. */\n\t\t\t\tthis.$emit('error', message)\n\t\t\t\tif (result.status === 404) {\n\t\t\t\t\t/** @event not-found Emitted on a 404: the record went away or access was withdrawn. */\n\t\t\t\t\tthis.$emit('not-found')\n\t\t\t\t}\n\t\t\t\treturn\n\t\t\t}\n\t\t\t// A new follow notifies (the server's default); an unfollow has no switch.\n\t\t\tthis.notifyState = this.state\n\t\t\tpatchStoredSelf(this.register, this.schema, this.objectId, {\n\t\t\t\twatching: this.state,\n\t\t\t\tfavourite: this.state,\n\t\t\t\twatchNotify: this.state ? true : undefined,\n\t\t\t\t...(this.count !== null ? { watcherCount: this.count } : {}),\n\t\t\t})\n\t\t\t/** @event change Emitted after a successful call. Payload: `{ watching, notify, count }`. */\n\t\t\tthis.$emit('change', { watching: this.state, notify: this.state ? this.notifyState : null, count: this.count })\n\t\t},\n\n\t\t/**\n\t\t * Turn the follow's notifications on or off, optimistically.\n\t\t *\n\t\t * @return {Promise<void>}\n\t\t * @spec openspec/changes/one-follow-control/specs/record-follow/spec.md#requirement-one-follow-control-with-a-notifications-switch\n\t\t */\n\t\tasync toggleNotify() {\n\t\t\tif (this.busy || !this.state) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst previous = this.notifyState\n\t\t\tthis.notifyState = !previous\n\t\t\tthis.busy = true\n\t\t\tconst result = await setWatching(this.register, this.schema, this.objectId, true, { notify: this.notifyState })\n\t\t\tthis.busy = false\n\t\t\tif (!result.ok) {\n\t\t\t\tthis.notifyState = previous\n\t\t\t\tconst message = result.status === 404\n\t\t\t\t\t? t('nextcloud-vue', 'You can no longer see this record.')\n\t\t\t\t\t: (result.message || t('nextcloud-vue', 'Could not change notifications.'))\n\t\t\t\timport('@nextcloud/dialogs').then(({ showError }) => showError(message)).catch(() => {})\n\t\t\t\tthis.$emit('error', message)\n\t\t\t\tif (result.status === 404) {\n\t\t\t\t\tthis.$emit('not-found')\n\t\t\t\t}\n\t\t\t\treturn\n\t\t\t}\n\t\t\tpatchStoredSelf(this.register, this.schema, this.objectId, { watchNotify: this.notifyState })\n\t\t\tthis.$emit('change', { watching: true, notify: this.notifyState, count: this.count })\n\t\t},\n\n\t\tasync loadWatchers() {\n\t\t\tthis.popoverError = ''\n\t\t\tthis.loadingWatchers = true\n\t\t\tconst result = await listWatchers(this.register, this.schema, this.objectId)\n\t\t\tthis.loadingWatchers = false\n\t\t\tif (!result.ok) {\n\t\t\t\t// No right to see the list (403) or a failure: close without a toast.\n\t\t\t\tthis.open = false\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst data = result.data || {}\n\t\t\tthis.watchers = Array.isArray(data.results) ? data.results : []\n\t\t\tthis.count = Number.isFinite(data.total) ? data.total : this.watchers.length\n\t\t},\n\n\t\tasync onPickerSearch(query) {\n\t\t\tthis.pickerLoading = true\n\t\t\tconst found = await searchNextcloudUsers(query || '', { limit: 10 })\n\t\t\tconst already = new Set(this.watchers.map((w) => w.userId))\n\t\t\tthis.pickerOptions = found.filter((u) => !already.has(u.id)).map((u) => ({ ...u, label: u.label || u.displayName || u.id }))\n\t\t\tthis.pickerLoading = false\n\t\t},\n\n\t\tasync addWatcher(option) {\n\t\t\tif (!option || !option.id) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.popoverError = ''\n\t\t\tconst result = await setWatcher(this.register, this.schema, this.objectId, option.id, true)\n\t\t\tif (!result.ok) {\n\t\t\t\tthis.popoverError = result.message || t('nextcloud-vue', 'Could not add this colleague.')\n\t\t\t\treturn\n\t\t\t}\n\t\t\tawait this.loadWatchers()\n\t\t},\n\n\t\tasync removeWatcher(watcher) {\n\t\t\tthis.popoverError = ''\n\t\t\tconst result = await setWatcher(this.register, this.schema, this.objectId, watcher.userId, false)\n\t\t\tif (!result.ok) {\n\t\t\t\tthis.popoverError = result.message || t('nextcloud-vue', 'Could not remove this follower.')\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif (watcher.userId === this.me) {\n\t\t\t\tthis.state = false\n\t\t\t\tthis.$emit('change', { watching: false, count: this.count })\n\t\t\t}\n\t\t\tawait this.loadWatchers()\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n.cn-follow-toggle {\n\tdisplay: inline-flex;\n\talign-items: center;\n\tgap: 4px;\n}\n\n.cn-follow-toggle__on {\n\tcolor: var(--color-primary-element);\n}\n\n.cn-follow-toggle__popover {\n\tmin-width: 260px;\n\tpadding: 12px;\n}\n\n.cn-follow-toggle__list {\n\tlist-style: none;\n\tmargin: 0 0 8px;\n\tpadding: 0;\n}\n\n.cn-follow-toggle__row {\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 8px;\n\tpadding: 4px 0;\n}\n\n.cn-follow-toggle__who {\n\tdisplay: flex;\n\tflex-direction: column;\n\tflex: 1 1 auto;\n\tmin-width: 0;\n}\n\n.cn-follow-toggle__since {\n\tcolor: var(--color-text-maxcontrast);\n\tfont-size: var(--font-size-small, 13px);\n}\n\n.cn-follow-toggle__error {\n\tmargin: 8px 0 0;\n\tcolor: var(--color-error-text);\n}\n</style>\n"],"names":["Bell","t"],"mappings":"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"}
@@ -1,28 +1,24 @@
1
- import { resolveComponent, openBlock, createElementBlock, createVNode, withModifiers, withCtx, createBlock, createTextVNode, toDisplayString, createElementVNode, Fragment, renderList, createCommentVNode } from 'vue';
1
+ import { resolveComponent, openBlock, createElementBlock, normalizeClass, createVNode, withModifiers, withCtx, createBlock, Fragment, createTextVNode, toDisplayString, createCommentVNode, createElementVNode, renderList } from 'vue';
2
2
 
3
3
  const _hoisted_1 = {
4
- class: "cn-follow-toggle",
5
- "data-testid": "cn-follow-toggle"
6
- };
7
- const _hoisted_2 = {
8
4
  class: "cn-follow-toggle__popover",
9
5
  "data-testid": "cn-follow-toggle-popover"
10
6
  };
11
- const _hoisted_3 = {
7
+ const _hoisted_2 = {
12
8
  key: 1,
13
9
  class: "cn-follow-toggle__list"
14
10
  };
15
- const _hoisted_4 = { class: "cn-follow-toggle__who" };
16
- const _hoisted_5 = { class: "cn-follow-toggle__name" };
17
- const _hoisted_6 = {
11
+ const _hoisted_3 = { class: "cn-follow-toggle__who" };
12
+ const _hoisted_4 = { class: "cn-follow-toggle__name" };
13
+ const _hoisted_5 = {
18
14
  key: 0,
19
15
  class: "cn-follow-toggle__since"
20
16
  };
21
- const _hoisted_7 = {
17
+ const _hoisted_6 = {
22
18
  key: 2,
23
19
  class: "cn-follow-toggle__picker"
24
20
  };
25
- const _hoisted_8 = {
21
+ const _hoisted_7 = {
26
22
  key: 3,
27
23
  class: "cn-follow-toggle__error",
28
24
  role: "alert",
@@ -30,19 +26,25 @@ const _hoisted_8 = {
30
26
  };
31
27
 
32
28
  function render(_ctx, _cache, $props, $setup, $data, $options) {
33
- const _component_Bell = resolveComponent("Bell");
34
- const _component_BellOutline = resolveComponent("BellOutline");
29
+ const _component_Eye = resolveComponent("Eye");
30
+ const _component_EyeOutline = resolveComponent("EyeOutline");
35
31
  const _component_NcButton = resolveComponent("NcButton");
32
+ const _component_Bell = resolveComponent("Bell");
33
+ const _component_BellOffOutline = resolveComponent("BellOffOutline");
36
34
  const _component_NcLoadingIcon = resolveComponent("NcLoadingIcon");
37
35
  const _component_NcAvatar = resolveComponent("NcAvatar");
38
36
  const _component_Close = resolveComponent("Close");
39
37
  const _component_NcSelect = resolveComponent("NcSelect");
40
38
  const _component_NcPopover = resolveComponent("NcPopover");
41
39
 
42
- return (openBlock(), createElementBlock("span", _hoisted_1, [
40
+ return (openBlock(), createElementBlock("span", {
41
+ class: normalizeClass(["cn-follow-toggle", { 'cn-follow-toggle--compact': $props.compact }]),
42
+ "data-testid": "cn-follow-toggle"
43
+ }, [
43
44
  createVNode(_component_NcButton, {
44
- variant: $data.state ? 'secondary' : 'tertiary',
45
+ variant: $data.state && !$props.compact ? 'secondary' : 'tertiary',
45
46
  "aria-pressed": $data.state ? 'true' : 'false',
47
+ "aria-label": $props.compact ? ($data.state ? $options.followingLabel : $options.followLabel) : undefined,
46
48
  title: $options.tooltip,
47
49
  disabled: $data.busy,
48
50
  "data-testid": "cn-follow-toggle-button",
@@ -50,23 +52,53 @@ function render(_ctx, _cache, $props, $setup, $data, $options) {
50
52
  }, {
51
53
  icon: withCtx(() => [
52
54
  ($data.state)
53
- ? (openBlock(), createBlock(_component_Bell, {
55
+ ? (openBlock(), createBlock(_component_Eye, {
54
56
  key: 0,
55
- size: 20
57
+ size: 20,
58
+ class: "cn-follow-toggle__on"
56
59
  }))
57
- : (openBlock(), createBlock(_component_BellOutline, {
60
+ : (openBlock(), createBlock(_component_EyeOutline, {
58
61
  key: 1,
59
62
  size: 20
60
63
  }))
61
64
  ]),
62
65
  default: withCtx(() => [
63
- createTextVNode(" " + toDisplayString($data.state ? $options.followingLabel : $options.followLabel), 1 /* TEXT */)
66
+ (!$props.compact)
67
+ ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [
68
+ createTextVNode(toDisplayString($data.state ? $options.followingLabel : $options.followLabel), 1 /* TEXT */)
69
+ ], 64 /* STABLE_FRAGMENT */))
70
+ : createCommentVNode("v-if", true)
64
71
  ]),
65
72
  _: 1 /* STABLE */
66
- }, 8 /* PROPS */, ["variant", "aria-pressed", "title", "disabled", "onClick"]),
67
- ($data.count !== null)
68
- ? (openBlock(), createBlock(_component_NcPopover, {
73
+ }, 8 /* PROPS */, ["variant", "aria-pressed", "aria-label", "title", "disabled", "onClick"]),
74
+ ($options.showNotifySwitch)
75
+ ? (openBlock(), createBlock(_component_NcButton, {
69
76
  key: 0,
77
+ variant: "tertiary",
78
+ "aria-pressed": $data.notifyState ? 'true' : 'false',
79
+ "aria-label": $options.notifyLabel,
80
+ title: $options.notifyLabel,
81
+ disabled: $data.busy,
82
+ "data-testid": "cn-follow-toggle-notify",
83
+ onClick: withModifiers($options.toggleNotify, ["stop"])
84
+ }, {
85
+ icon: withCtx(() => [
86
+ ($data.notifyState)
87
+ ? (openBlock(), createBlock(_component_Bell, {
88
+ key: 0,
89
+ size: 20
90
+ }))
91
+ : (openBlock(), createBlock(_component_BellOffOutline, {
92
+ key: 1,
93
+ size: 20
94
+ }))
95
+ ]),
96
+ _: 1 /* STABLE */
97
+ }, 8 /* PROPS */, ["aria-pressed", "aria-label", "title", "disabled", "onClick"]))
98
+ : createCommentVNode("v-if", true),
99
+ ($data.count !== null && !$props.compact)
100
+ ? (openBlock(), createBlock(_component_NcPopover, {
101
+ key: 1,
70
102
  shown: $data.open,
71
103
  "onUpdate:shown": _cache[0] || (_cache[0] = $event => (($data.open) = $event)),
72
104
  placement: "bottom-start"
@@ -85,14 +117,14 @@ function render(_ctx, _cache, $props, $setup, $data, $options) {
85
117
  }, 8 /* PROPS */, ["aria-label"])
86
118
  ]),
87
119
  default: withCtx(() => [
88
- createElementVNode("div", _hoisted_2, [
120
+ createElementVNode("div", _hoisted_1, [
89
121
  ($data.loadingWatchers)
90
122
  ? (openBlock(), createBlock(_component_NcLoadingIcon, {
91
123
  key: 0,
92
124
  size: 20,
93
125
  name: $options.loadingLabel
94
126
  }, null, 8 /* PROPS */, ["name"]))
95
- : (openBlock(), createElementBlock("ul", _hoisted_3, [
127
+ : (openBlock(), createElementBlock("ul", _hoisted_2, [
96
128
  (openBlock(true), createElementBlock(Fragment, null, renderList($data.watchers, (watcher) => {
97
129
  return (openBlock(), createElementBlock("li", {
98
130
  key: watcher.userId,
@@ -104,10 +136,10 @@ function render(_ctx, _cache, $props, $setup, $data, $options) {
104
136
  size: 28,
105
137
  hideStatus: ""
106
138
  }, null, 8 /* PROPS */, ["user", "displayName"]),
107
- createElementVNode("span", _hoisted_4, [
108
- createElementVNode("span", _hoisted_5, toDisplayString(watcher.displayName || watcher.userId), 1 /* TEXT */),
139
+ createElementVNode("span", _hoisted_3, [
140
+ createElementVNode("span", _hoisted_4, toDisplayString(watcher.displayName || watcher.userId), 1 /* TEXT */),
109
141
  (watcher.created)
110
- ? (openBlock(), createElementBlock("span", _hoisted_6, toDisplayString($options.sinceText(watcher.created)), 1 /* TEXT */))
142
+ ? (openBlock(), createElementBlock("span", _hoisted_5, toDisplayString($options.sinceText(watcher.created)), 1 /* TEXT */))
111
143
  : createCommentVNode("v-if", true)
112
144
  ]),
113
145
  ($options.canRemove(watcher))
@@ -129,7 +161,7 @@ function render(_ctx, _cache, $props, $setup, $data, $options) {
129
161
  }), 128 /* KEYED_FRAGMENT */))
130
162
  ])),
131
163
  ($props.canManage)
132
- ? (openBlock(), createElementBlock("div", _hoisted_7, [
164
+ ? (openBlock(), createElementBlock("div", _hoisted_6, [
133
165
  createVNode(_component_NcSelect, {
134
166
  inputLabel: $options.addColleagueLabel,
135
167
  modelValue: null,
@@ -144,14 +176,14 @@ function render(_ctx, _cache, $props, $setup, $data, $options) {
144
176
  ]))
145
177
  : createCommentVNode("v-if", true),
146
178
  ($data.popoverError)
147
- ? (openBlock(), createElementBlock("p", _hoisted_8, toDisplayString($data.popoverError), 1 /* TEXT */))
179
+ ? (openBlock(), createElementBlock("p", _hoisted_7, toDisplayString($data.popoverError), 1 /* TEXT */))
148
180
  : createCommentVNode("v-if", true)
149
181
  ])
150
182
  ]),
151
183
  _: 1 /* STABLE */
152
184
  }, 8 /* PROPS */, ["shown"]))
153
185
  : createCommentVNode("v-if", true)
154
- ]))
186
+ ], 2 /* CLASS */))
155
187
  }
156
188
 
157
189
  export { render };
@@ -1 +1 @@
1
- {"version":3,"file":"CnFollowToggle.vue3.js","sources":["../../../../src/components/CnFollowToggle/CnFollowToggle.vue?vue&type=template&id=eec896e2&lang.js"],"sourcesContent":["<!--\n - SPDX-FileCopyrightText: 2026 Conduction B.V.\n - SPDX-License-Identifier: EUPL-1.2\n-->\n<template>\n\t<span class=\"cn-follow-toggle\" data-testid=\"cn-follow-toggle\">\n\t\t<NcButton\n\t\t\t:variant=\"state ? 'secondary' : 'tertiary'\"\n\t\t\t:aria-pressed=\"state ? 'true' : 'false'\"\n\t\t\t:title=\"tooltip\"\n\t\t\t:disabled=\"busy\"\n\t\t\tdata-testid=\"cn-follow-toggle-button\"\n\t\t\t@click.stop=\"toggle\">\n\t\t\t<template #icon>\n\t\t\t\t<Bell v-if=\"state\" :size=\"20\" />\n\t\t\t\t<BellOutline v-else :size=\"20\" />\n\t\t\t</template>\n\t\t\t{{ state ? followingLabel : followLabel }}\n\t\t</NcButton>\n\t\t<NcPopover\n\t\t\tv-if=\"count !== null\"\n\t\t\tv-model:shown=\"open\"\n\t\t\tplacement=\"bottom-start\">\n\t\t\t<template #trigger>\n\t\t\t\t<NcButton\n\t\t\t\t\tvariant=\"tertiary\"\n\t\t\t\t\tclass=\"cn-follow-toggle__count\"\n\t\t\t\t\t:aria-label=\"followersLabel\"\n\t\t\t\t\tdata-testid=\"cn-follow-toggle-count\">\n\t\t\t\t\t{{ count }}\n\t\t\t\t</NcButton>\n\t\t\t</template>\n\t\t\t<div class=\"cn-follow-toggle__popover\" data-testid=\"cn-follow-toggle-popover\">\n\t\t\t\t<NcLoadingIcon v-if=\"loadingWatchers\" :size=\"20\" :name=\"loadingLabel\" />\n\t\t\t\t<ul v-else class=\"cn-follow-toggle__list\">\n\t\t\t\t\t<li v-for=\"watcher in watchers\" :key=\"watcher.userId\" class=\"cn-follow-toggle__row\">\n\t\t\t\t\t\t<NcAvatar :user=\"watcher.userId\"\n\t\t\t\t\t\t\t:displayName=\"watcher.displayName || watcher.userId\"\n\t\t\t\t\t\t\t:size=\"28\"\n\t\t\t\t\t\t\thideStatus />\n\t\t\t\t\t\t<span class=\"cn-follow-toggle__who\">\n\t\t\t\t\t\t\t<span class=\"cn-follow-toggle__name\">{{ watcher.displayName || watcher.userId }}</span>\n\t\t\t\t\t\t\t<span v-if=\"watcher.created\" class=\"cn-follow-toggle__since\">{{ sinceText(watcher.created) }}</span>\n\t\t\t\t\t\t</span>\n\t\t\t\t\t\t<NcButton\n\t\t\t\t\t\t\tv-if=\"canRemove(watcher)\"\n\t\t\t\t\t\t\tvariant=\"tertiary\"\n\t\t\t\t\t\t\t:aria-label=\"removeFollowerLabel(watcher)\"\n\t\t\t\t\t\t\t:title=\"removeFollowerLabel(watcher)\"\n\t\t\t\t\t\t\tdata-testid=\"cn-follow-toggle-remove\"\n\t\t\t\t\t\t\t@click=\"removeWatcher(watcher)\">\n\t\t\t\t\t\t\t<template #icon>\n\t\t\t\t\t\t\t\t<Close :size=\"16\" />\n\t\t\t\t\t\t\t</template>\n\t\t\t\t\t\t</NcButton>\n\t\t\t\t\t</li>\n\t\t\t\t</ul>\n\t\t\t\t<div v-if=\"canManage\" class=\"cn-follow-toggle__picker\">\n\t\t\t\t\t<NcSelect\n\t\t\t\t\t\t:inputLabel=\"addColleagueLabel\"\n\t\t\t\t\t\t:modelValue=\"null\"\n\t\t\t\t\t\t:options=\"pickerOptions\"\n\t\t\t\t\t\t:loading=\"pickerLoading\"\n\t\t\t\t\t\t:filterable=\"false\"\n\t\t\t\t\t\tlabel=\"label\"\n\t\t\t\t\t\tdata-testid=\"cn-follow-toggle-picker\"\n\t\t\t\t\t\t@search=\"onPickerSearch\"\n\t\t\t\t\t\t@update:modelValue=\"addWatcher\" />\n\t\t\t\t</div>\n\t\t\t\t<p v-if=\"popoverError\"\n\t\t\t\t\tclass=\"cn-follow-toggle__error\"\n\t\t\t\t\trole=\"alert\"\n\t\t\t\t\tdata-testid=\"cn-follow-toggle-error\">\n\t\t\t\t\t{{ popoverError }}\n\t\t\t\t</p>\n\t\t\t</div>\n\t\t</NcPopover>\n\t</span>\n</template>\n\n<script>\nimport { translate as t } from '@nextcloud/l10n'\nimport { NcAvatar, NcButton, NcLoadingIcon, NcPopover, NcSelect } from '@nextcloud/vue'\nimport Bell from 'vue-material-design-icons/Bell.vue'\nimport BellOutline from 'vue-material-design-icons/BellOutline.vue'\nimport Close from 'vue-material-design-icons/Close.vue'\nimport { patchStoredSelf } from '../../utils/patchStoredSelf.js'\nimport { listWatchers, setWatcher, setWatching } from '../../utils/recordInteractions.js'\nimport { searchNextcloudUsers } from '../../utils/userAutocomplete.js'\n\n/**\n * CnFollowToggle — a Follow toggle bound to a record's `@self.watching` marker,\n * with the follower count and a followers popover for users who may see them.\n *\n * A click flips the toggle at once and sends `PUT` or `DELETE .../watch`; on\n * failure it flips back and shows the server's message, and a 404 says the\n * user can no longer see the record and emits `not-found`. The count shows\n * only when `watcherCount` is given (OpenRegister sets `@self.watcherCount` for\n * a reader with `update` only); opening the popover then fetches\n * `GET .../watchers`, never before, and a 403 closes it quietly. With\n * `canManage` (`@self.can.manage`) the popover offers an \"Add a colleague\"\n * picker and a remove action on each follower; without it, only the user's own\n * row can be removed.\n *\n * Example:\n * ```vue\n * <CnFollowToggle register=\"pipelinq\" schema=\"ticket\" :object-id=\"id\"\n * :watching=\"self.watching\" :watcher-count=\"self.watcherCount\" :can-manage=\"self.can && self.can.manage\" />\n * ```\n */\nexport default {\n\tname: 'CnFollowToggle',\n\n\tcomponents: { Bell, BellOutline, Close, NcAvatar, NcButton, NcLoadingIcon, NcPopover, NcSelect },\n\n\tprops: {\n\t\t/** Register slug of the record. */\n\t\tregister: {\n\t\t\ttype: String,\n\t\t\trequired: true,\n\t\t},\n\n\t\t/** Schema slug of the record. */\n\t\tschema: {\n\t\t\ttype: String,\n\t\t\trequired: true,\n\t\t},\n\n\t\t/** Id of the record. */\n\t\tobjectId: {\n\t\t\ttype: String,\n\t\t\trequired: true,\n\t\t},\n\n\t\t/** Whether the current user follows the record (`@self.watching`). */\n\t\twatching: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\n\t\t/** Number of followers (`@self.watcherCount`). Null hides the count and the popover. */\n\t\twatcherCount: {\n\t\t\ttype: Number,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/** Whether the user may add and remove other followers (`@self.can.manage`). */\n\t\tcanManage: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\n\t\t/** Whether following sends change notifications. False changes the tooltip to say it does not. */\n\t\tnotifies: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: true,\n\t\t},\n\n\t\t/** User id of the current user. Defaults to Nextcloud's `OC.currentUser`. */\n\t\tcurrentUser: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\t},\n\n\temits: ['change', 'error', 'not-found'],\n\n\tdata() {\n\t\treturn {\n\t\t\tstate: this.watching,\n\t\t\tcount: this.watcherCount,\n\t\t\tbusy: false,\n\t\t\topen: false,\n\t\t\twatchers: [],\n\t\t\tloadingWatchers: false,\n\t\t\tpopoverError: '',\n\t\t\tpickerOptions: [],\n\t\t\tpickerLoading: false,\n\t\t}\n\t},\n\n\tcomputed: {\n\t\tfollowLabel() {\n\t\t\treturn t('nextcloud-vue', 'Follow')\n\t\t},\n\n\t\tfollowingLabel() {\n\t\t\treturn t('nextcloud-vue', 'Following')\n\t\t},\n\n\t\tloadingLabel() {\n\t\t\treturn t('nextcloud-vue', 'Loading …')\n\t\t},\n\n\t\taddColleagueLabel() {\n\t\t\treturn t('nextcloud-vue', 'Add a colleague')\n\t\t},\n\n\t\tfollowersLabel() {\n\t\t\treturn t('nextcloud-vue', '{count} followers', { count: this.count })\n\t\t},\n\n\t\ttooltip() {\n\t\t\treturn this.notifies\n\t\t\t\t? t('nextcloud-vue', 'Follow this record to get its updates')\n\t\t\t\t: t('nextcloud-vue', 'You will see it under Following. This register sends no change notifications.')\n\t\t},\n\n\t\tme() {\n\t\t\treturn this.currentUser || (typeof OC !== 'undefined' && OC ? OC.currentUser : '') || ''\n\t\t},\n\t},\n\n\twatch: {\n\t\twatching(value) {\n\t\t\tthis.state = value\n\t\t},\n\n\t\twatcherCount(value) {\n\t\t\tthis.count = value\n\t\t},\n\n\t\topen(value) {\n\t\t\tif (value) {\n\t\t\t\tthis.loadWatchers()\n\t\t\t}\n\t\t},\n\t},\n\n\tmethods: {\n\t\tsinceText(created) {\n\t\t\tconst d = new Date(created)\n\t\t\treturn Number.isNaN(d.getTime())\n\t\t\t\t? ''\n\t\t\t\t: t('nextcloud-vue', 'Since {date}', { date: d.toLocaleDateString() })\n\t\t},\n\n\t\tremoveFollowerLabel(watcher) {\n\t\t\treturn t('nextcloud-vue', 'Remove {name} as a follower', { name: watcher.displayName || watcher.userId })\n\t\t},\n\n\t\tcanRemove(watcher) {\n\t\t\treturn this.canManage || (this.me !== '' && watcher.userId === this.me)\n\t\t},\n\n\t\tasync toggle() {\n\t\t\tif (this.busy) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst previous = this.state\n\t\t\tthis.state = !previous\n\t\t\tif (this.count !== null) {\n\t\t\t\tthis.count = Math.max(0, this.count + (this.state ? 1 : -1))\n\t\t\t}\n\t\t\tthis.busy = true\n\t\t\tconst result = await setWatching(this.register, this.schema, this.objectId, this.state)\n\t\t\tthis.busy = false\n\t\t\tif (!result.ok) {\n\t\t\t\tthis.state = previous\n\t\t\t\tif (this.count !== null) {\n\t\t\t\t\tthis.count = Math.max(0, this.count + (previous ? 1 : -1))\n\t\t\t\t}\n\t\t\t\tconst message = result.status === 404\n\t\t\t\t\t? t('nextcloud-vue', 'You can no longer see this record.')\n\t\t\t\t\t: (result.message || t('nextcloud-vue', 'Could not change following.'))\n\t\t\t\timport('@nextcloud/dialogs').then(({ showError }) => showError(message)).catch(() => {})\n\t\t\t\t/** @event error Emitted when a call failed; payload is the message shown. */\n\t\t\t\tthis.$emit('error', message)\n\t\t\t\tif (result.status === 404) {\n\t\t\t\t\t/** @event not-found Emitted on a 404: the record went away or access was withdrawn. */\n\t\t\t\t\tthis.$emit('not-found')\n\t\t\t\t}\n\t\t\t\treturn\n\t\t\t}\n\t\t\tpatchStoredSelf(this.register, this.schema, this.objectId, {\n\t\t\t\twatching: this.state,\n\t\t\t\t...(this.count !== null ? { watcherCount: this.count } : {}),\n\t\t\t})\n\t\t\t/** @event change Emitted after a successful call. Payload: `{ watching, count }`. */\n\t\t\tthis.$emit('change', { watching: this.state, count: this.count })\n\t\t},\n\n\t\tasync loadWatchers() {\n\t\t\tthis.popoverError = ''\n\t\t\tthis.loadingWatchers = true\n\t\t\tconst result = await listWatchers(this.register, this.schema, this.objectId)\n\t\t\tthis.loadingWatchers = false\n\t\t\tif (!result.ok) {\n\t\t\t\t// No right to see the list (403) or a failure: close without a toast.\n\t\t\t\tthis.open = false\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst data = result.data || {}\n\t\t\tthis.watchers = Array.isArray(data.results) ? data.results : []\n\t\t\tthis.count = Number.isFinite(data.total) ? data.total : this.watchers.length\n\t\t},\n\n\t\tasync onPickerSearch(query) {\n\t\t\tthis.pickerLoading = true\n\t\t\tconst found = await searchNextcloudUsers(query || '', { limit: 10 })\n\t\t\tconst already = new Set(this.watchers.map((w) => w.userId))\n\t\t\tthis.pickerOptions = found.filter((u) => !already.has(u.id)).map((u) => ({ ...u, label: u.label || u.displayName || u.id }))\n\t\t\tthis.pickerLoading = false\n\t\t},\n\n\t\tasync addWatcher(option) {\n\t\t\tif (!option || !option.id) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.popoverError = ''\n\t\t\tconst result = await setWatcher(this.register, this.schema, this.objectId, option.id, true)\n\t\t\tif (!result.ok) {\n\t\t\t\tthis.popoverError = result.message || t('nextcloud-vue', 'Could not add this colleague.')\n\t\t\t\treturn\n\t\t\t}\n\t\t\tawait this.loadWatchers()\n\t\t},\n\n\t\tasync removeWatcher(watcher) {\n\t\t\tthis.popoverError = ''\n\t\t\tconst result = await setWatcher(this.register, this.schema, this.objectId, watcher.userId, false)\n\t\t\tif (!result.ok) {\n\t\t\t\tthis.popoverError = result.message || t('nextcloud-vue', 'Could not remove this follower.')\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif (watcher.userId === this.me) {\n\t\t\t\tthis.state = false\n\t\t\t\tthis.$emit('change', { watching: false, count: this.count })\n\t\t\t}\n\t\t\tawait this.loadWatchers()\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n.cn-follow-toggle {\n\tdisplay: inline-flex;\n\talign-items: center;\n\tgap: 4px;\n}\n\n.cn-follow-toggle__popover {\n\tmin-width: 260px;\n\tpadding: 12px;\n}\n\n.cn-follow-toggle__list {\n\tlist-style: none;\n\tmargin: 0 0 8px;\n\tpadding: 0;\n}\n\n.cn-follow-toggle__row {\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 8px;\n\tpadding: 4px 0;\n}\n\n.cn-follow-toggle__who {\n\tdisplay: flex;\n\tflex-direction: column;\n\tflex: 1 1 auto;\n\tmin-width: 0;\n}\n\n.cn-follow-toggle__since {\n\tcolor: var(--color-text-maxcontrast);\n\tfont-size: var(--font-size-small, 13px);\n}\n\n.cn-follow-toggle__error {\n\tmargin: 8px 0 0;\n\tcolor: var(--color-error-text);\n}\n</style>\n"],"names":["_openBlock","_createElementBlock","_createVNode","_createBlock","_createTextVNode","_toDisplayString","_createElementVNode","_Fragment","_renderList"],"mappings":"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"}
1
+ {"version":3,"file":"CnFollowToggle.vue3.js","sources":["../../../../src/components/CnFollowToggle/CnFollowToggle.vue?vue&type=template&id=eec896e2&lang.js"],"sourcesContent":["<!--\n - SPDX-FileCopyrightText: 2026 Conduction B.V.\n - SPDX-License-Identifier: EUPL-1.2\n-->\n<template>\n\t<span class=\"cn-follow-toggle\"\n\t\t:class=\"{ 'cn-follow-toggle--compact': compact }\"\n\t\tdata-testid=\"cn-follow-toggle\">\n\t\t<NcButton\n\t\t\t:variant=\"state && !compact ? 'secondary' : 'tertiary'\"\n\t\t\t:aria-pressed=\"state ? 'true' : 'false'\"\n\t\t\t:aria-label=\"compact ? (state ? followingLabel : followLabel) : undefined\"\n\t\t\t:title=\"tooltip\"\n\t\t\t:disabled=\"busy\"\n\t\t\tdata-testid=\"cn-follow-toggle-button\"\n\t\t\t@click.stop=\"toggle\">\n\t\t\t<template #icon>\n\t\t\t\t<Eye v-if=\"state\" :size=\"20\" class=\"cn-follow-toggle__on\" />\n\t\t\t\t<EyeOutline v-else :size=\"20\" />\n\t\t\t</template>\n\t\t\t<template v-if=\"!compact\">\n\t\t\t\t{{ state ? followingLabel : followLabel }}\n\t\t\t</template>\n\t\t</NcButton>\n\t\t<NcButton\n\t\t\tv-if=\"showNotifySwitch\"\n\t\t\tvariant=\"tertiary\"\n\t\t\t:aria-pressed=\"notifyState ? 'true' : 'false'\"\n\t\t\t:aria-label=\"notifyLabel\"\n\t\t\t:title=\"notifyLabel\"\n\t\t\t:disabled=\"busy\"\n\t\t\tdata-testid=\"cn-follow-toggle-notify\"\n\t\t\t@click.stop=\"toggleNotify\">\n\t\t\t<template #icon>\n\t\t\t\t<Bell v-if=\"notifyState\" :size=\"20\" />\n\t\t\t\t<BellOffOutline v-else :size=\"20\" />\n\t\t\t</template>\n\t\t</NcButton>\n\t\t<NcPopover\n\t\t\tv-if=\"count !== null && !compact\"\n\t\t\tv-model:shown=\"open\"\n\t\t\tplacement=\"bottom-start\">\n\t\t\t<template #trigger>\n\t\t\t\t<NcButton\n\t\t\t\t\tvariant=\"tertiary\"\n\t\t\t\t\tclass=\"cn-follow-toggle__count\"\n\t\t\t\t\t:aria-label=\"followersLabel\"\n\t\t\t\t\tdata-testid=\"cn-follow-toggle-count\">\n\t\t\t\t\t{{ count }}\n\t\t\t\t</NcButton>\n\t\t\t</template>\n\t\t\t<div class=\"cn-follow-toggle__popover\" data-testid=\"cn-follow-toggle-popover\">\n\t\t\t\t<NcLoadingIcon v-if=\"loadingWatchers\" :size=\"20\" :name=\"loadingLabel\" />\n\t\t\t\t<ul v-else class=\"cn-follow-toggle__list\">\n\t\t\t\t\t<li v-for=\"watcher in watchers\" :key=\"watcher.userId\" class=\"cn-follow-toggle__row\">\n\t\t\t\t\t\t<NcAvatar :user=\"watcher.userId\"\n\t\t\t\t\t\t\t:displayName=\"watcher.displayName || watcher.userId\"\n\t\t\t\t\t\t\t:size=\"28\"\n\t\t\t\t\t\t\thideStatus />\n\t\t\t\t\t\t<span class=\"cn-follow-toggle__who\">\n\t\t\t\t\t\t\t<span class=\"cn-follow-toggle__name\">{{ watcher.displayName || watcher.userId }}</span>\n\t\t\t\t\t\t\t<span v-if=\"watcher.created\" class=\"cn-follow-toggle__since\">{{ sinceText(watcher.created) }}</span>\n\t\t\t\t\t\t</span>\n\t\t\t\t\t\t<NcButton\n\t\t\t\t\t\t\tv-if=\"canRemove(watcher)\"\n\t\t\t\t\t\t\tvariant=\"tertiary\"\n\t\t\t\t\t\t\t:aria-label=\"removeFollowerLabel(watcher)\"\n\t\t\t\t\t\t\t:title=\"removeFollowerLabel(watcher)\"\n\t\t\t\t\t\t\tdata-testid=\"cn-follow-toggle-remove\"\n\t\t\t\t\t\t\t@click=\"removeWatcher(watcher)\">\n\t\t\t\t\t\t\t<template #icon>\n\t\t\t\t\t\t\t\t<Close :size=\"16\" />\n\t\t\t\t\t\t\t</template>\n\t\t\t\t\t\t</NcButton>\n\t\t\t\t\t</li>\n\t\t\t\t</ul>\n\t\t\t\t<div v-if=\"canManage\" class=\"cn-follow-toggle__picker\">\n\t\t\t\t\t<NcSelect\n\t\t\t\t\t\t:inputLabel=\"addColleagueLabel\"\n\t\t\t\t\t\t:modelValue=\"null\"\n\t\t\t\t\t\t:options=\"pickerOptions\"\n\t\t\t\t\t\t:loading=\"pickerLoading\"\n\t\t\t\t\t\t:filterable=\"false\"\n\t\t\t\t\t\tlabel=\"label\"\n\t\t\t\t\t\tdata-testid=\"cn-follow-toggle-picker\"\n\t\t\t\t\t\t@search=\"onPickerSearch\"\n\t\t\t\t\t\t@update:modelValue=\"addWatcher\" />\n\t\t\t\t</div>\n\t\t\t\t<p v-if=\"popoverError\"\n\t\t\t\t\tclass=\"cn-follow-toggle__error\"\n\t\t\t\t\trole=\"alert\"\n\t\t\t\t\tdata-testid=\"cn-follow-toggle-error\">\n\t\t\t\t\t{{ popoverError }}\n\t\t\t\t</p>\n\t\t\t</div>\n\t\t</NcPopover>\n\t</span>\n</template>\n\n<script>\nimport { translate as t } from '@nextcloud/l10n'\nimport { NcAvatar, NcButton, NcLoadingIcon, NcPopover, NcSelect } from '@nextcloud/vue'\nimport Bell from 'vue-material-design-icons/Bell.vue'\nimport BellOffOutline from 'vue-material-design-icons/BellOffOutline.vue'\nimport Close from 'vue-material-design-icons/Close.vue'\nimport Eye from 'vue-material-design-icons/Eye.vue'\nimport EyeOutline from 'vue-material-design-icons/EyeOutline.vue'\nimport { patchStoredSelf } from '../../utils/patchStoredSelf.js'\nimport { listWatchers, setWatcher, setWatching } from '../../utils/recordInteractions.js'\nimport { searchNextcloudUsers } from '../../utils/userAutocomplete.js'\n\n/**\n * CnFollowToggle — the one Follow control of a record: a Follow toggle bound to\n * `@self.watching`, a notifications switch bound to `@self.watchNotify`, the\n * follower count and a followers popover for users who may see them.\n *\n * Following and favourites are one feature (OpenRegister's\n * `merge-follow-and-favourites`): a favourite is a follow with notifications\n * off, so there is no separate star. While the user follows, a bell beside the\n * toggle turns the follow's notifications on or off (`PUT .../watch` with\n * `{\"notify\": bool}`). With `notifies` false (the register sends no change\n * notifications) the bell is not offered. `compact` renders the toggle as an\n * icon only, without the bell, count or popover, for a column in a list.\n *\n * A click flips the toggle at once and sends `PUT` or `DELETE .../watch`; on\n * failure it flips back and shows the server's message, and a 404 says the\n * user can no longer see the record and emits `not-found`. The count shows\n * only when `watcherCount` is given (OpenRegister sets `@self.watcherCount` for\n * a reader with `update` only); opening the popover then fetches\n * `GET .../watchers`, never before, and a 403 closes it quietly. With\n * `canManage` (`@self.can.manage`) the popover offers an \"Add a colleague\"\n * picker and a remove action on each follower; without it, only the user's own\n * row can be removed.\n *\n * Example:\n * ```vue\n * <CnFollowToggle register=\"pipelinq\" schema=\"ticket\" :object-id=\"id\"\n * :watching=\"self.watching\" :notify=\"self.watchNotify\"\n * :watcher-count=\"self.watcherCount\" :can-manage=\"self.can && self.can.manage\" />\n * ```\n */\nexport default {\n\tname: 'CnFollowToggle',\n\n\tcomponents: { Bell, BellOffOutline, Close, Eye, EyeOutline, NcAvatar, NcButton, NcLoadingIcon, NcPopover, NcSelect },\n\n\tprops: {\n\t\t/** Register slug of the record. */\n\t\tregister: {\n\t\t\ttype: String,\n\t\t\trequired: true,\n\t\t},\n\n\t\t/** Schema slug of the record. */\n\t\tschema: {\n\t\t\ttype: String,\n\t\t\trequired: true,\n\t\t},\n\n\t\t/** Id of the record. */\n\t\tobjectId: {\n\t\t\ttype: String,\n\t\t\trequired: true,\n\t\t},\n\n\t\t/** Whether the current user follows the record (`@self.watching`). */\n\t\twatching: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\n\t\t/**\n\t\t * Whether the user's follow notifies them (`@self.watchNotify`). Null\n\t\t * (an older server, or not following) reads as on.\n\t\t */\n\t\tnotify: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/** Icon only, without the bell, count or popover: for a column in a list. */\n\t\tcompact: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\n\t\t/** Number of followers (`@self.watcherCount`). Null hides the count and the popover. */\n\t\twatcherCount: {\n\t\t\ttype: Number,\n\t\t\tdefault: null,\n\t\t},\n\n\t\t/** Whether the user may add and remove other followers (`@self.can.manage`). */\n\t\tcanManage: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: false,\n\t\t},\n\n\t\t/** Whether following sends change notifications. False changes the tooltip to say it does not. */\n\t\tnotifies: {\n\t\t\ttype: Boolean,\n\t\t\tdefault: true,\n\t\t},\n\n\t\t/** User id of the current user. Defaults to Nextcloud's `OC.currentUser`. */\n\t\tcurrentUser: {\n\t\t\ttype: String,\n\t\t\tdefault: '',\n\t\t},\n\t},\n\n\temits: ['change', 'error', 'not-found'],\n\n\tdata() {\n\t\treturn {\n\t\t\tstate: this.watching,\n\t\t\tnotifyState: this.notify !== false,\n\t\t\tcount: this.watcherCount,\n\t\t\tbusy: false,\n\t\t\topen: false,\n\t\t\twatchers: [],\n\t\t\tloadingWatchers: false,\n\t\t\tpopoverError: '',\n\t\t\tpickerOptions: [],\n\t\t\tpickerLoading: false,\n\t\t}\n\t},\n\n\tcomputed: {\n\t\tfollowLabel() {\n\t\t\treturn t('nextcloud-vue', 'Follow')\n\t\t},\n\n\t\tfollowingLabel() {\n\t\t\treturn t('nextcloud-vue', 'Following')\n\t\t},\n\n\t\tloadingLabel() {\n\t\t\treturn t('nextcloud-vue', 'Loading …')\n\t\t},\n\n\t\taddColleagueLabel() {\n\t\t\treturn t('nextcloud-vue', 'Add a colleague')\n\t\t},\n\n\t\tnotifyLabel() {\n\t\t\treturn this.notifyState\n\t\t\t\t? t('nextcloud-vue', 'Turn notifications off')\n\t\t\t\t: t('nextcloud-vue', 'Turn notifications on')\n\t\t},\n\n\t\t/**\n\t\t * Whether the bell renders: following, not compact, and the register notifies.\n\t\t *\n\t\t * @return {boolean}\n\t\t */\n\t\tshowNotifySwitch() {\n\t\t\treturn this.state && !this.compact && this.notifies\n\t\t},\n\n\t\tfollowersLabel() {\n\t\t\treturn t('nextcloud-vue', '{count} followers', { count: this.count })\n\t\t},\n\n\t\ttooltip() {\n\t\t\treturn this.notifies\n\t\t\t\t? t('nextcloud-vue', 'Follow this record to get its updates')\n\t\t\t\t: t('nextcloud-vue', 'You will see it under Following. This register sends no change notifications.')\n\t\t},\n\n\t\tme() {\n\t\t\treturn this.currentUser || (typeof OC !== 'undefined' && OC ? OC.currentUser : '') || ''\n\t\t},\n\t},\n\n\twatch: {\n\t\twatching(value) {\n\t\t\tthis.state = value\n\t\t},\n\n\t\tnotify(value) {\n\t\t\tthis.notifyState = value !== false\n\t\t},\n\n\t\twatcherCount(value) {\n\t\t\tthis.count = value\n\t\t},\n\n\t\topen(value) {\n\t\t\tif (value) {\n\t\t\t\tthis.loadWatchers()\n\t\t\t}\n\t\t},\n\t},\n\n\tmethods: {\n\t\tsinceText(created) {\n\t\t\tconst d = new Date(created)\n\t\t\treturn Number.isNaN(d.getTime())\n\t\t\t\t? ''\n\t\t\t\t: t('nextcloud-vue', 'Since {date}', { date: d.toLocaleDateString() })\n\t\t},\n\n\t\tremoveFollowerLabel(watcher) {\n\t\t\treturn t('nextcloud-vue', 'Remove {name} as a follower', { name: watcher.displayName || watcher.userId })\n\t\t},\n\n\t\tcanRemove(watcher) {\n\t\t\treturn this.canManage || (this.me !== '' && watcher.userId === this.me)\n\t\t},\n\n\t\tasync toggle() {\n\t\t\tif (this.busy) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst previous = this.state\n\t\t\tthis.state = !previous\n\t\t\tif (this.count !== null) {\n\t\t\t\tthis.count = Math.max(0, this.count + (this.state ? 1 : -1))\n\t\t\t}\n\t\t\tthis.busy = true\n\t\t\tconst result = await setWatching(this.register, this.schema, this.objectId, this.state)\n\t\t\tthis.busy = false\n\t\t\tif (!result.ok) {\n\t\t\t\tthis.state = previous\n\t\t\t\tif (this.count !== null) {\n\t\t\t\t\tthis.count = Math.max(0, this.count + (previous ? 1 : -1))\n\t\t\t\t}\n\t\t\t\tconst message = result.status === 404\n\t\t\t\t\t? t('nextcloud-vue', 'You can no longer see this record.')\n\t\t\t\t\t: (result.message || t('nextcloud-vue', 'Could not change following.'))\n\t\t\t\timport('@nextcloud/dialogs').then(({ showError }) => showError(message)).catch(() => {})\n\t\t\t\t/** @event error Emitted when a call failed; payload is the message shown. */\n\t\t\t\tthis.$emit('error', message)\n\t\t\t\tif (result.status === 404) {\n\t\t\t\t\t/** @event not-found Emitted on a 404: the record went away or access was withdrawn. */\n\t\t\t\t\tthis.$emit('not-found')\n\t\t\t\t}\n\t\t\t\treturn\n\t\t\t}\n\t\t\t// A new follow notifies (the server's default); an unfollow has no switch.\n\t\t\tthis.notifyState = this.state\n\t\t\tpatchStoredSelf(this.register, this.schema, this.objectId, {\n\t\t\t\twatching: this.state,\n\t\t\t\tfavourite: this.state,\n\t\t\t\twatchNotify: this.state ? true : undefined,\n\t\t\t\t...(this.count !== null ? { watcherCount: this.count } : {}),\n\t\t\t})\n\t\t\t/** @event change Emitted after a successful call. Payload: `{ watching, notify, count }`. */\n\t\t\tthis.$emit('change', { watching: this.state, notify: this.state ? this.notifyState : null, count: this.count })\n\t\t},\n\n\t\t/**\n\t\t * Turn the follow's notifications on or off, optimistically.\n\t\t *\n\t\t * @return {Promise<void>}\n\t\t * @spec openspec/changes/one-follow-control/specs/record-follow/spec.md#requirement-one-follow-control-with-a-notifications-switch\n\t\t */\n\t\tasync toggleNotify() {\n\t\t\tif (this.busy || !this.state) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst previous = this.notifyState\n\t\t\tthis.notifyState = !previous\n\t\t\tthis.busy = true\n\t\t\tconst result = await setWatching(this.register, this.schema, this.objectId, true, { notify: this.notifyState })\n\t\t\tthis.busy = false\n\t\t\tif (!result.ok) {\n\t\t\t\tthis.notifyState = previous\n\t\t\t\tconst message = result.status === 404\n\t\t\t\t\t? t('nextcloud-vue', 'You can no longer see this record.')\n\t\t\t\t\t: (result.message || t('nextcloud-vue', 'Could not change notifications.'))\n\t\t\t\timport('@nextcloud/dialogs').then(({ showError }) => showError(message)).catch(() => {})\n\t\t\t\tthis.$emit('error', message)\n\t\t\t\tif (result.status === 404) {\n\t\t\t\t\tthis.$emit('not-found')\n\t\t\t\t}\n\t\t\t\treturn\n\t\t\t}\n\t\t\tpatchStoredSelf(this.register, this.schema, this.objectId, { watchNotify: this.notifyState })\n\t\t\tthis.$emit('change', { watching: true, notify: this.notifyState, count: this.count })\n\t\t},\n\n\t\tasync loadWatchers() {\n\t\t\tthis.popoverError = ''\n\t\t\tthis.loadingWatchers = true\n\t\t\tconst result = await listWatchers(this.register, this.schema, this.objectId)\n\t\t\tthis.loadingWatchers = false\n\t\t\tif (!result.ok) {\n\t\t\t\t// No right to see the list (403) or a failure: close without a toast.\n\t\t\t\tthis.open = false\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst data = result.data || {}\n\t\t\tthis.watchers = Array.isArray(data.results) ? data.results : []\n\t\t\tthis.count = Number.isFinite(data.total) ? data.total : this.watchers.length\n\t\t},\n\n\t\tasync onPickerSearch(query) {\n\t\t\tthis.pickerLoading = true\n\t\t\tconst found = await searchNextcloudUsers(query || '', { limit: 10 })\n\t\t\tconst already = new Set(this.watchers.map((w) => w.userId))\n\t\t\tthis.pickerOptions = found.filter((u) => !already.has(u.id)).map((u) => ({ ...u, label: u.label || u.displayName || u.id }))\n\t\t\tthis.pickerLoading = false\n\t\t},\n\n\t\tasync addWatcher(option) {\n\t\t\tif (!option || !option.id) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tthis.popoverError = ''\n\t\t\tconst result = await setWatcher(this.register, this.schema, this.objectId, option.id, true)\n\t\t\tif (!result.ok) {\n\t\t\t\tthis.popoverError = result.message || t('nextcloud-vue', 'Could not add this colleague.')\n\t\t\t\treturn\n\t\t\t}\n\t\t\tawait this.loadWatchers()\n\t\t},\n\n\t\tasync removeWatcher(watcher) {\n\t\t\tthis.popoverError = ''\n\t\t\tconst result = await setWatcher(this.register, this.schema, this.objectId, watcher.userId, false)\n\t\t\tif (!result.ok) {\n\t\t\t\tthis.popoverError = result.message || t('nextcloud-vue', 'Could not remove this follower.')\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif (watcher.userId === this.me) {\n\t\t\t\tthis.state = false\n\t\t\t\tthis.$emit('change', { watching: false, count: this.count })\n\t\t\t}\n\t\t\tawait this.loadWatchers()\n\t\t},\n\t},\n}\n</script>\n\n<style scoped>\n.cn-follow-toggle {\n\tdisplay: inline-flex;\n\talign-items: center;\n\tgap: 4px;\n}\n\n.cn-follow-toggle__on {\n\tcolor: var(--color-primary-element);\n}\n\n.cn-follow-toggle__popover {\n\tmin-width: 260px;\n\tpadding: 12px;\n}\n\n.cn-follow-toggle__list {\n\tlist-style: none;\n\tmargin: 0 0 8px;\n\tpadding: 0;\n}\n\n.cn-follow-toggle__row {\n\tdisplay: flex;\n\talign-items: center;\n\tgap: 8px;\n\tpadding: 4px 0;\n}\n\n.cn-follow-toggle__who {\n\tdisplay: flex;\n\tflex-direction: column;\n\tflex: 1 1 auto;\n\tmin-width: 0;\n}\n\n.cn-follow-toggle__since {\n\tcolor: var(--color-text-maxcontrast);\n\tfont-size: var(--font-size-small, 13px);\n}\n\n.cn-follow-toggle__error {\n\tmargin: 8px 0 0;\n\tcolor: var(--color-error-text);\n}\n</style>\n"],"names":["_normalizeClass","_createVNode","_createBlock","_createElementBlock","_Fragment","_createElementVNode","_openBlock","_renderList","_toDisplayString"],"mappings":";;;AAuDQ,EAAA,KAAK,EAAC,2BAAuB;AAAA,EAAA,aAAA,EAAA,0BAAA;;;;AAEtB,EAAA,KAAC,EAAA,wBAAA;;AAMJ,MAAA,UAAA,GAAA,EAAA,KAAE,EAAA,uBAAA,GAAA;AACD,MAAA,UAAA,GAAA,EAAA,KAAK,EAAC,wBAAY,GAAA;;;AACP,EAAA,KAAA,EAAA,yBAAA;;;;AAeE,EAAA,KAAG,EAAA,0BAAA;;;;AAaxB,EAAA,KAAE,EAAA,yBAAA;AACF,EAAA,IAAG,EAAA,OAAA;AACH,EAAA,aAAQ,EAAA,wBAAA;;;;;;;;;;;;;;;;IAtFN,KAAK,EAAAA,cAAA,CAAA,CAAC,kBAAkB,EAAA,EAAA,2BAAA,EACU,MAAC,CAAA,OAAA,EAAA,CAAA,CAAA;AACvC,IAAA,aAAU,EAAC,kBAAiB;;IAC5BC,WAeU,CAAA,mBAAA,EAAA;MAdT,OAAO,EAAE,KAAK,CAAA,KAAA,IAAA,CAAA,MAAA,CAAA,OAAA,GAAA,WAAA,GAAA,UAAA;AACd,MAAA,cAAY,EAAE,KAAK,CAAA,KAAA,GAAA,MAAA,GAAA,OAAA;MACnB,YAAU,EAAE,cAAO,IAAA,KAAA,CAAA,KAAA,GAAA,QAAA,CAAA,cAAA,GAAA,QAAA,CAAA,WAAA,IAAA,SAAA;AACnB,MAAA,KAAK,EAAE,QAAO,CAAA,OAAA;AACd,MAAA,QAAQ,EAAE,KAAI,CAAA,IAAA;mBACJ,EAAE,yBAAmB;AAC/B,MAAA,OAAK,gBAAI,QAAA,CAAA,MAAA,EAAA,CAAA,MAAA,CAAA,CAAA;;AACC,MAAA,IAAI,UACd,MAAyC;SAA9B,KAAK,CAAA,KAAA;0BAAhBC,WAAyC,CAAA,cAAA,EAAA;;AAAtB,cAAA,IAAI,EAAG,EAAA;AAAG,cAAA,KAAK,EAAC,sBAAM;;0BACzCA,WAAS,CAAA,qBAAA,EAAA;;AAAA,cAAA,IAAA,EAAA,EAAA;;;uBAEV,MAEW;UAFJ,MAAA,CAAA,OAAA;0BAAPC,kBAEW,CAAAC,QAAA,EAAA,EAAA,GAAA,EAAA,CAAA,EAAA,EAAA;8CADP,KAAK,CAAA,KAAA,GAAG,QAAU,CAAA,cAAA,GAAA,QAAA,CAAA,WAAA,CAAA,EAAA,CAAA,YAAA;;;;;;KAIhB,QAAa,CAAA,gBAAA;iCAYT,CAAA,mBAAA,EAAA;;AAXV,UAAA,OAAO,EAAC,UAAO;AACd,UAAA,cAAY,EAAE,KAAW,CAAA,WAAA,GAAA,MAAA,GAAA,OAAA;AACzB,UAAA,YAAU,EAAE,QAAW,CAAA,WAAA;AACvB,UAAA,KAAK,EAAE,QAAO,CAAA,WAAA;AACd,UAAA,QAAQ,EAAE,KAAI,CAAA,IAAA;AACd,UAAA,aAAU,EAAC,yBAAwB;AACnC,UAAA,OAAK,gBAAI,QAAA,CAAA,YAAA,EAAA,CAAA,MAAA,CAAA,CAAA;;AACD,UAAA,IAAA,UACR,MAAO;aAAA,KAAA,CAAA,WAAA;8BAAPF,WAAO,CAAA,eAAA,EAAA;;AAAA,kBAAA,IAAA,EAAA,EAAA;;8BACPA,WAA+B,CAAA,yBAAA,EAAA;;AAAP,kBAAA,IAAI,EAAE,EAAC;;;;;;AAI1B,IAAA,CAAA,KAAA,CAAA,KAAG,cAAA,MAAA,CAAA,OAAA;sBADTA;;AAEQ,UAAA,KAAK,EAAE,KAAI,CAAA,IAAA;kEAAJ,KAAI,CAAA,IAAA,IAAA,MAAA,CAAA,CAAA;AACjB,UAAA,SAAO,EAAC,cAAc;;AACb,UAAA,OAAO,UAChB,MAMU;YANVD,WAMU,CAAA,mBAAA,EAAA;AALV,cAAA,OAAO,YAAG;AACV,cAAA,KAAK,EAAC,yBAAG;AACR,cAAA,YAAO,EAAA,QAAA,CAAA,cAAA;AACR,cAAA,aAAW,EAAC,wBAAuB;;+BACnC,MAAW;gDAAR,KAAK,CAAA,KAAA,CAAA,EAAA,CAAA,YAAA;;;;;2BAGP;AAAA,YAAAI,kBAAA,QAAA;eACmB,KAAc,CAAA,eAAA;2CAAmB,CAAA,wBAAA,EAAA;;AAAhB,oBAAA,IAAK,EAAE,EAAE;AAAG,oBAAA,IAAI,EAAA,QAAA,CAAA,YAAA;;AACnD,mBAAAC,SAAA,EAAA,EAAAH,kBAAA,CAsBE,MAtBF,UAsBE,EAAA;wDADC,CAAAC,QAAA,EAAA,IAAA,EAAAG,UAAA,CApBS,KAAA,CAAA,QAAA,EAAA,CAAH,OAAG,KAAA;6DAoBT,CAAA,IAAA,EAAA;wBApBS,GAAA,EAAA,OAAA,CAAA,MAAA;AAAA,wBAAA,KAAA,EAAA,uBAAA;;wBACbN,WAGM,CAAA,mBAAA,EAAA;0BAHK,IAAI,EAAE,OAAO,CAAC,MAAM;AAC7B,0BAAA,WAAW,EAAE,OAAO,CAAC,WAAW,IAAI,OAAO,CAAC,MAAM;AAClD,0BAAA,IAAG,EAAG,EAAE;AACT,0BAAA,UAAK,EAAL,EAAK;;AACN,wBAAAI,kBAAA,CAGO,QAHP,UAGO,EAAA;0BAFNA,kBAAwB,CAAA,MAAA,EAAxB,UAAwB,EAAAG,eAAA,CAAA,OAAA,CAAA,WAAA,IAAA,OAAA,CAAA,MAAA,CAAA,EAAA,CAAA,YAAA;AACZ,0BAAA,CAAA,OAAK,CAAA,OAAA;AAAjB,+BAAAF,SAAA,EAAA,EAAAH,kBAAA,CAAiB,QAAjB,UAAiB,EAAAK,eAAA,CAAA,kBAAA,CAAA,OAAA,CAAA,OAAA,CAAA,CAAA,EAAA,CAAA,YAAA;;;AAGX,wBAAA,CAAA,QAAA,CAAA,SAAS,CAAC,OAAO,CAAA;0CADvBN,WAUM,CAAA,mBAAA,EAAA;;AARN,8BAAA,OAAO,EAAC,UAAU;8BACjB,YAAU,EAAE,QAAE,CAAA,mBAAA,CAAA,OAAA,CAAA;8BACd,KAAK,EAAE,QAAY,CAAA,mBAAA,CAAA,OAAA,CAAA;AACpB,8BAAA,aAAU,EAAA,yBAAA;8BACT,OAAK,EAAA,MAAA,KAAE,QAAC,CAAA,aAAA,CAAA,OAAA,CAAA,CAAA;;AACP,8BAAA,IAAA,UACD,MAAA;gCAAAD,WAAA,CAAA,gBAAA,EAAA,EAAA,IAAA,EAAA,EAAA,EAAA,CAAA;;;;;;;;eAKO,MAAS,CAAA,SAAA;mDAWd,iBAAA,EAAA;+BADM,CAAA,mBAAA,EAAA;AART,sBAAA,UAAU,EAAE,QAAK,CAAA,iBAAA;AACjB,sBAAA,UAAU,EAAC,IAAA;AACX,sBAAA,OAAO,EAAE,KAAa,CAAA,aAAA;AACtB,sBAAA,OAAO,EAAE,KAAa,CAAA,aAAA;AACtB,sBAAA,UAAU,EAAE,KAAK;AAClB,sBAAA,KAAG,EAAA,OAAA;mCACQ,EAAC,yBAAO;AAClB,sBAAA,QAAM,EAAE,QAAc,CAAA,cAAA;AACtB,sBAAA,qBAAS,EAAA,QAAA,CAAA,UAAA;;;;eAEH,KAAS,CAAA,YAAA;gCAAjBE,wBAAA,4BAIE,KAAA,CAAA,YAAA,CAAA,EAAA,CAAA,YAAA;;;;;;;;;;;;"}