@conduction/nextcloud-vue 2.56.0-beta.31 → 2.56.0-beta.32

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 (178) hide show
  1. package/dist/esm/components/CnBannerWidget/CnBannerWidget.vue2.js +55 -4
  2. package/dist/esm/components/CnBannerWidget/CnBannerWidget.vue2.js.map +1 -1
  3. package/dist/esm/components/CnBannerWidget/CnBannerWidget.vue3.js +51 -15
  4. package/dist/esm/components/CnBannerWidget/CnBannerWidget.vue3.js.map +1 -1
  5. package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue2.js +13 -2
  6. package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue2.js.map +1 -1
  7. package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue3.js +63 -52
  8. package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue3.js.map +1 -1
  9. package/dist/esm/components/CnChipsFieldWidget/CnChipsFieldWidget.vue.js +10 -0
  10. package/dist/esm/components/CnChipsFieldWidget/CnChipsFieldWidget.vue.js.map +1 -0
  11. package/dist/esm/components/CnChipsFieldWidget/CnChipsFieldWidget.vue2.js +252 -0
  12. package/dist/esm/components/CnChipsFieldWidget/CnChipsFieldWidget.vue2.js.map +1 -0
  13. package/dist/esm/components/CnChipsFieldWidget/CnChipsFieldWidget.vue3.js +140 -0
  14. package/dist/esm/components/CnChipsFieldWidget/CnChipsFieldWidget.vue3.js.map +1 -0
  15. package/dist/esm/components/CnChipsFieldWidget/index.js +26 -0
  16. package/dist/esm/components/CnChipsFieldWidget/index.js.map +1 -0
  17. package/dist/esm/components/CnChoicePickerWidget/CnChoicePickerWidget.vue.js +10 -0
  18. package/dist/esm/components/CnChoicePickerWidget/CnChoicePickerWidget.vue.js.map +1 -0
  19. package/dist/esm/components/CnChoicePickerWidget/CnChoicePickerWidget.vue2.js +354 -0
  20. package/dist/esm/components/CnChoicePickerWidget/CnChoicePickerWidget.vue2.js.map +1 -0
  21. package/dist/esm/components/CnChoicePickerWidget/CnChoicePickerWidget.vue3.js +172 -0
  22. package/dist/esm/components/CnChoicePickerWidget/CnChoicePickerWidget.vue3.js.map +1 -0
  23. package/dist/esm/components/CnChoicePickerWidget/index.js +27 -0
  24. package/dist/esm/components/CnChoicePickerWidget/index.js.map +1 -0
  25. package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue2.js +25 -2
  26. package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue2.js.map +1 -1
  27. package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue3.js +2 -1
  28. package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue3.js.map +1 -1
  29. package/dist/esm/components/CnDataTable/CnDataTable.vue2.js.map +1 -1
  30. package/dist/esm/components/CnDataTable/CnDataTable.vue3.js +3 -2
  31. package/dist/esm/components/CnDataTable/CnDataTable.vue3.js.map +1 -1
  32. package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js +29 -0
  33. package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js.map +1 -1
  34. package/dist/esm/components/CnDetailPage/CnDetailPage.vue3.js +20 -3
  35. package/dist/esm/components/CnDetailPage/CnDetailPage.vue3.js.map +1 -1
  36. package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue2.js +7 -1
  37. package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue2.js.map +1 -1
  38. package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue3.js.map +1 -1
  39. package/dist/esm/components/CnFieldListWidget/CnFieldListWidget.vue2.js +77 -3
  40. package/dist/esm/components/CnFieldListWidget/CnFieldListWidget.vue2.js.map +1 -1
  41. package/dist/esm/components/CnFieldListWidget/CnFieldListWidget.vue3.js +282 -69
  42. package/dist/esm/components/CnFieldListWidget/CnFieldListWidget.vue3.js.map +1 -1
  43. package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js +0 -1
  44. package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js.map +1 -1
  45. package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js.map +1 -1
  46. package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue2.js +65 -2
  47. package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue2.js.map +1 -1
  48. package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue3.js +6 -2
  49. package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue3.js.map +1 -1
  50. package/dist/esm/components/CnRadioCardsWidget/CnRadioCardsWidget.vue.js +10 -0
  51. package/dist/esm/components/CnRadioCardsWidget/CnRadioCardsWidget.vue.js.map +1 -0
  52. package/dist/esm/components/CnRadioCardsWidget/CnRadioCardsWidget.vue2.js +174 -0
  53. package/dist/esm/components/CnRadioCardsWidget/CnRadioCardsWidget.vue2.js.map +1 -0
  54. package/dist/esm/components/CnRadioCardsWidget/CnRadioCardsWidget.vue3.js +75 -0
  55. package/dist/esm/components/CnRadioCardsWidget/CnRadioCardsWidget.vue3.js.map +1 -0
  56. package/dist/esm/components/CnRadioCardsWidget/index.js +28 -0
  57. package/dist/esm/components/CnRadioCardsWidget/index.js.map +1 -0
  58. package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue2.js +18 -1
  59. package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue2.js.map +1 -1
  60. package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue3.js +34 -25
  61. package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue3.js.map +1 -1
  62. package/dist/esm/components/CnSavedViewsWidget/CnSavedViewsWidget.vue.js +10 -0
  63. package/dist/esm/components/CnSavedViewsWidget/CnSavedViewsWidget.vue.js.map +1 -0
  64. package/dist/esm/components/CnSavedViewsWidget/CnSavedViewsWidget.vue2.js +222 -0
  65. package/dist/esm/components/CnSavedViewsWidget/CnSavedViewsWidget.vue2.js.map +1 -0
  66. package/dist/esm/components/CnSavedViewsWidget/CnSavedViewsWidget.vue3.js +64 -0
  67. package/dist/esm/components/CnSavedViewsWidget/CnSavedViewsWidget.vue3.js.map +1 -0
  68. package/dist/esm/components/CnSavedViewsWidget/index.js +30 -0
  69. package/dist/esm/components/CnSavedViewsWidget/index.js.map +1 -0
  70. package/dist/esm/components/CnSegmentedControl/CnSegmentedControl.vue2.js.map +1 -1
  71. package/dist/esm/components/CnSegmentedControl/CnSegmentedControl.vue3.js.map +1 -1
  72. package/dist/esm/components/CnSettingsFormWidget/CnSettingsFormWidget.vue.js +10 -0
  73. package/dist/esm/components/CnSettingsFormWidget/CnSettingsFormWidget.vue.js.map +1 -0
  74. package/dist/esm/components/CnSettingsFormWidget/CnSettingsFormWidget.vue2.js +347 -0
  75. package/dist/esm/components/CnSettingsFormWidget/CnSettingsFormWidget.vue2.js.map +1 -0
  76. package/dist/esm/components/CnSettingsFormWidget/CnSettingsFormWidget.vue3.js +184 -0
  77. package/dist/esm/components/CnSettingsFormWidget/CnSettingsFormWidget.vue3.js.map +1 -0
  78. package/dist/esm/components/CnSettingsFormWidget/index.js +27 -0
  79. package/dist/esm/components/CnSettingsFormWidget/index.js.map +1 -0
  80. package/dist/esm/components/CnStatWidget/CnStatWidget.vue2.js +87 -6
  81. package/dist/esm/components/CnStatWidget/CnStatWidget.vue2.js.map +1 -1
  82. package/dist/esm/components/CnStatWidget/CnStatWidget.vue3.js.map +1 -1
  83. package/dist/esm/components/CnSwitchRowsWidget/CnSwitchRowsWidget.vue.js +10 -0
  84. package/dist/esm/components/CnSwitchRowsWidget/CnSwitchRowsWidget.vue.js.map +1 -0
  85. package/dist/esm/components/CnSwitchRowsWidget/CnSwitchRowsWidget.vue2.js +159 -0
  86. package/dist/esm/components/CnSwitchRowsWidget/CnSwitchRowsWidget.vue2.js.map +1 -0
  87. package/dist/esm/components/CnSwitchRowsWidget/CnSwitchRowsWidget.vue3.js +60 -0
  88. package/dist/esm/components/CnSwitchRowsWidget/CnSwitchRowsWidget.vue3.js.map +1 -0
  89. package/dist/esm/components/CnSwitchRowsWidget/index.js +26 -0
  90. package/dist/esm/components/CnSwitchRowsWidget/index.js.map +1 -0
  91. package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue2.js +47 -1
  92. package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue2.js.map +1 -1
  93. package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue3.js +16 -14
  94. package/dist/esm/components/CnTabsWidget/CnTabsWidget.vue3.js.map +1 -1
  95. package/dist/esm/components/CnTasksWidget/CnTasksWidget.vue2.js +80 -1
  96. package/dist/esm/components/CnTasksWidget/CnTasksWidget.vue2.js.map +1 -1
  97. package/dist/esm/components/CnTasksWidget/CnTasksWidget.vue3.js +75 -32
  98. package/dist/esm/components/CnTasksWidget/CnTasksWidget.vue3.js.map +1 -1
  99. package/dist/esm/components/CnToggleTableWidget/CnToggleTableWidget.vue.js +10 -0
  100. package/dist/esm/components/CnToggleTableWidget/CnToggleTableWidget.vue.js.map +1 -0
  101. package/dist/esm/components/CnToggleTableWidget/CnToggleTableWidget.vue2.js +269 -0
  102. package/dist/esm/components/CnToggleTableWidget/CnToggleTableWidget.vue2.js.map +1 -0
  103. package/dist/esm/components/CnToggleTableWidget/CnToggleTableWidget.vue3.js +106 -0
  104. package/dist/esm/components/CnToggleTableWidget/CnToggleTableWidget.vue3.js.map +1 -0
  105. package/dist/esm/components/CnToggleTableWidget/index.js +27 -0
  106. package/dist/esm/components/CnToggleTableWidget/index.js.map +1 -0
  107. package/dist/esm/components/CnWidgetGrid/registerDashboardWidgets.js +7 -0
  108. package/dist/esm/components/CnWidgetGrid/registerDashboardWidgets.js.map +1 -1
  109. package/dist/esm/components/CnWorkspaceFilterWidget/CnWorkspaceFilterWidget.vue2.js.map +1 -1
  110. package/dist/esm/components/CnWorkspaceFilterWidget/CnWorkspaceFilterWidget.vue3.js +4 -2
  111. package/dist/esm/components/CnWorkspaceFilterWidget/CnWorkspaceFilterWidget.vue3.js.map +1 -1
  112. package/dist/esm/index.js +7 -0
  113. package/dist/esm/index.js.map +1 -1
  114. package/dist/esm/l10n/en.json.js +1 -0
  115. package/dist/esm/l10n/en.json.js.map +1 -1
  116. package/dist/esm/l10n/nl.json.js +1 -0
  117. package/dist/esm/l10n/nl.json.js.map +1 -1
  118. package/dist/esm/nextcloud-vue.css +843 -4
  119. package/dist/esm/utils/contentHeaderLink.js +51 -0
  120. package/dist/esm/utils/contentHeaderLink.js.map +1 -0
  121. package/dist/esm/utils/fetchFilterCounts.js +40 -5
  122. package/dist/esm/utils/fetchFilterCounts.js.map +1 -1
  123. package/dist/esm/utils/initials.js +32 -0
  124. package/dist/esm/utils/initials.js.map +1 -0
  125. package/dist/esm/utils/libraryWidgetKeys.js +7 -0
  126. package/dist/esm/utils/libraryWidgetKeys.js.map +1 -1
  127. package/dist/esm/utils/objectWrite.js +59 -0
  128. package/dist/esm/utils/objectWrite.js.map +1 -0
  129. package/dist/esm/utils/widgetDispatch.js +1 -1
  130. package/dist/esm/utils/widgetDispatch.js.map +1 -1
  131. package/dist/nextcloud-vue.cjs.js +10510 -6830
  132. package/dist/nextcloud-vue.cjs.js.map +2 -2
  133. package/dist/nextcloud-vue.css +843 -4
  134. package/l10n/en.json +1 -0
  135. package/l10n/nl.json +1 -0
  136. package/package.json +1 -1
  137. package/src/components/CnBannerWidget/CnBannerWidget.vue +93 -13
  138. package/src/components/CnCellRenderer/CnCellRenderer.md +2 -0
  139. package/src/components/CnCellRenderer/CnCellRenderer.vue +43 -3
  140. package/src/components/CnChipsFieldWidget/CnChipsFieldWidget.vue +433 -0
  141. package/src/components/CnChipsFieldWidget/index.js +25 -0
  142. package/src/components/CnChoicePickerWidget/CnChoicePickerWidget.vue +556 -0
  143. package/src/components/CnChoicePickerWidget/index.js +26 -0
  144. package/src/components/CnDashboardPage/CnDashboardPage.vue +38 -2
  145. package/src/components/CnDataTable/CnDataTable.vue +2 -1
  146. package/src/components/CnDetailPage/CnDetailPage.vue +45 -2
  147. package/src/components/CnFactsWidget/CnFactsWidget.vue +18 -3
  148. package/src/components/CnFieldListWidget/CnFieldListWidget.vue +265 -4
  149. package/src/components/CnIndexPage/CnIndexPage.vue +0 -1
  150. package/src/components/CnObjectListWidget/CnObjectListWidget.vue +69 -2
  151. package/src/components/CnRadioCardsWidget/CnRadioCardsWidget.vue +313 -0
  152. package/src/components/CnRadioCardsWidget/index.js +27 -0
  153. package/src/components/CnRecordListWidget/CnRecordListWidget.vue +43 -1
  154. package/src/components/CnSavedViewsWidget/CnSavedViewsWidget.vue +296 -0
  155. package/src/components/CnSavedViewsWidget/index.js +29 -0
  156. package/src/components/CnSegmentedControl/CnSegmentedControl.vue +13 -0
  157. package/src/components/CnSettingsFormWidget/CnSettingsFormWidget.vue +555 -0
  158. package/src/components/CnSettingsFormWidget/index.js +26 -0
  159. package/src/components/CnStatWidget/CnStatWidget.vue +87 -6
  160. package/src/components/CnSwitchRowsWidget/CnSwitchRowsWidget.vue +226 -0
  161. package/src/components/CnSwitchRowsWidget/index.js +25 -0
  162. package/src/components/CnTabsWidget/CnTabsWidget.vue +82 -3
  163. package/src/components/CnTasksWidget/CnTasksWidget.vue +175 -15
  164. package/src/components/CnToggleTableWidget/CnToggleTableWidget.vue +386 -0
  165. package/src/components/CnToggleTableWidget/index.js +26 -0
  166. package/src/components/CnWidgetGrid/registerDashboardWidgets.js +7 -0
  167. package/src/components/CnWorkspaceFilterWidget/CnWorkspaceFilterWidget.vue +28 -1
  168. package/src/components/index.js +7 -0
  169. package/src/css/look-board-detail.css +36 -2
  170. package/src/css/look-board-index.css +23 -0
  171. package/src/css/look-board.css +72 -0
  172. package/src/index.js +7 -0
  173. package/src/utils/contentHeaderLink.js +48 -0
  174. package/src/utils/fetchFilterCounts.js +39 -4
  175. package/src/utils/initials.js +29 -0
  176. package/src/utils/libraryWidgetKeys.js +7 -0
  177. package/src/utils/objectWrite.js +55 -0
  178. package/src/utils/widgetDispatch.js +1 -1
package/l10n/en.json CHANGED
@@ -54,6 +54,7 @@
54
54
  "Could not update the view \"{name}\"": "Could not update the view \"{name}\"",
55
55
  "Unread": "Unread",
56
56
  "Mark as unread": "Mark as unread",
57
+ "Open sidebar": "Open sidebar",
57
58
  "Could not mark this record as unread.": "Could not mark this record as unread.",
58
59
  "Add to favourites": "Add to favourites",
59
60
  "Remove from favourites": "Remove from favourites",
package/l10n/nl.json CHANGED
@@ -54,6 +54,7 @@
54
54
  "Could not update the view \"{name}\"": "Weergave \"{name}\" kon niet worden bijgewerkt",
55
55
  "Unread": "Ongelezen",
56
56
  "Mark as unread": "Markeren als ongelezen",
57
+ "Open sidebar": "Zijbalk openen",
57
58
  "Could not mark this record as unread.": "Dit dossier kon niet als ongelezen worden gemarkeerd.",
58
59
  "Add to favourites": "Aan favorieten toevoegen",
59
60
  "Remove from favourites": "Uit favorieten verwijderen",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@conduction/nextcloud-vue",
3
- "version": "2.56.0-beta.31",
3
+ "version": "2.56.0-beta.32",
4
4
  "description": "Shared Vue component library for Conduction Nextcloud apps — complements @nextcloud/vue with higher-level components, OpenRegister integration, and NL Design System support",
5
5
  "homepage": "https://github.com/ConductionNL/nextcloud-vue#readme",
6
6
  "bugs": {
@@ -48,15 +48,27 @@
48
48
  </p>
49
49
  <div v-else-if="visible" class="cn-banner-widget">
50
50
  <NcNoteCard :type="resolvedVariant" class="cn-banner-widget__card">
51
- <component
52
- :is="clickable ? 'a' : 'span'"
53
- class="cn-banner-widget__text"
54
- :class="{ 'cn-banner-widget__text--clickable': clickable }"
55
- :href="clickable ? routeHref : null"
56
- data-testid="cn-banner-widget-text"
57
- @click="onClick">
58
- {{ displayText }}
59
- </component>
51
+ <!-- A named icon replaces the variant's own glyph. -->
52
+ <template v-if="resolvedIcon" #icon>
53
+ <CnIcon :name="resolvedIcon" :size="22" data-testid="cn-banner-widget-icon" />
54
+ </template>
55
+ <span class="cn-banner-widget__line">
56
+ <component
57
+ :is="clickable ? 'a' : 'span'"
58
+ class="cn-banner-widget__text"
59
+ :class="{ 'cn-banner-widget__text--clickable': clickable }"
60
+ :href="clickable ? routeHref : null"
61
+ data-testid="cn-banner-widget-text"
62
+ @click="onClick"><strong v-if="displayLead" class="cn-banner-widget__lead" data-testid="cn-banner-widget-lead">{{ displayLead }}</strong>{{ displayLead && displayText ? ' ' : '' }}{{ displayText }}</component>
63
+ <!-- Board look: the actions as links at the end of the line. -->
64
+ <a
65
+ v-for="action in noteActions"
66
+ :key="action.key"
67
+ class="cn-banner-widget__link"
68
+ :href="action.href || null"
69
+ data-testid="cn-banner-widget-link"
70
+ @click="onActionClick($event, action)">{{ action.label }}</a>
71
+ </span>
60
72
  </NcNoteCard>
61
73
  </div>
62
74
  </template>
@@ -64,6 +76,7 @@
64
76
  <script>
65
77
  import { translate as t } from '@nextcloud/l10n'
66
78
  import { NcNoteCard } from '@nextcloud/vue'
79
+ import CnIcon from '../CnIcon/CnIcon.vue'
67
80
  import { normalizeLook } from '../../composables/useLook.js'
68
81
  import { fillTemplate } from '../../utils/fillTemplate.js'
69
82
  import { followLinkClick, resolveHref } from '../../utils/linkNavigation.js'
@@ -149,7 +162,7 @@ const MAX_ACTIONS_BOARD = 4
149
162
  export default {
150
163
  name: 'CnBannerWidget',
151
164
 
152
- components: { NcNoteCard },
165
+ components: { CnIcon, NcNoteCard },
153
166
 
154
167
  inject: {
155
168
  /**
@@ -179,6 +192,27 @@ export default {
179
192
  default: '',
180
193
  },
181
194
 
195
+ /**
196
+ * A bold lead in front of the text ("2 aanmeldingen wachten op
197
+ * goedkeuring." before the rest of the sentence). `{value}` is replaced
198
+ * like in `text`, and it goes through the app's translate. Empty falls
199
+ * back to the `content` blob.
200
+ */
201
+ lead: {
202
+ type: String,
203
+ default: '',
204
+ },
205
+
206
+ /**
207
+ * A named icon (`AccountPlus`, `AlertOutline`, ...) drawn before the
208
+ * text instead of the variant's own glyph. Empty falls back to the
209
+ * `content` blob, then to the variant glyph.
210
+ */
211
+ icon: {
212
+ type: String,
213
+ default: '',
214
+ },
215
+
182
216
  /**
183
217
  * Optional visibility condition. Shape:
184
218
  * `{ endpoint?, source?, field?, op?, value }` — exactly one of
@@ -360,9 +394,38 @@ export default {
360
394
  return VARIANTS.includes(v) ? v : 'info'
361
395
  },
362
396
 
363
- /** The effective banner text (prop → content → ''). */
397
+ /** The effective banner text (prop → content → ''), through the app's translate. */
364
398
  resolvedText() {
365
- return this.text || (this.content && this.content.text) || ''
399
+ const text = this.text || (this.content && this.content.text) || ''
400
+ return text ? this.tl(text) : ''
401
+ },
402
+
403
+ /** The effective bold lead (prop → content → ''), through the app's translate. */
404
+ resolvedLead() {
405
+ const lead = this.lead || (this.content && this.content.lead) || ''
406
+ return lead ? this.tl(lead) : ''
407
+ },
408
+
409
+ /** The lead with `{value}` filled in. */
410
+ displayLead() {
411
+ return this.fillValue(this.resolvedLead)
412
+ },
413
+
414
+ /** The effective icon name (prop → content → ''). */
415
+ resolvedIcon() {
416
+ return this.icon || (this.content && this.content.icon) || ''
417
+ },
418
+
419
+ /**
420
+ * The note card's actions as links, under the board look only: the
421
+ * first resolved action of `actions`, as the board draws "Beleid
422
+ * wijzigen" at the end of the line. Without the look the note card
423
+ * ignores `actions`, as it always did.
424
+ *
425
+ * @return {Array<object>} The resolved actions (at most one).
426
+ */
427
+ noteActions() {
428
+ return normalizeLook(this.cnLook) === 'board' ? this.resolvedActions.slice(0, 1) : []
366
429
  },
367
430
 
368
431
  /** The effective visibleWhen condition (prop → content → null). */
@@ -513,7 +576,7 @@ export default {
513
576
  */
514
577
  visible() {
515
578
  const title = this.title || (this.content && this.content.title) || ''
516
- if (this.resolvedText === '' && !(this.isAttention && title !== '')) {
579
+ if (this.resolvedText === '' && this.resolvedLead === '' && !(this.isAttention && title !== '')) {
517
580
  return false
518
581
  }
519
582
  if (!this.resolvedVisibleWhen) {
@@ -772,6 +835,23 @@ export default {
772
835
  margin: 0;
773
836
  }
774
837
 
838
+ .cn-banner-widget__line {
839
+ display: flex;
840
+ flex-wrap: wrap;
841
+ align-items: baseline;
842
+ gap: 4px 20px;
843
+ }
844
+
845
+ .cn-banner-widget__lead {
846
+ font-weight: 700;
847
+ }
848
+
849
+ .cn-banner-widget__link {
850
+ margin-inline-start: auto;
851
+ font-size: 14px;
852
+ font-weight: 600;
853
+ }
854
+
775
855
  .cn-banner-widget__text--clickable {
776
856
  cursor: pointer;
777
857
  text-decoration: underline;
@@ -86,6 +86,8 @@ fall back to the normal rendering. See `docs/migrating-to-manifest.md` →
86
86
  > `cnFormatters: { automationTrigger: v => ({ 'lead.created': 'Lead created' }[v] ?? v) }`);
87
87
  > standalone (no provider) it falls back to rendering the raw value.
88
88
 
89
+ The `secondary` prop is the column's secondary line: the `avatar` widget draws it under the name, beside the picture (`CnDataTable` passes it for an avatar column); other cells ignore it.
90
+
89
91
  Column widget — `widget="badge"`, `widget="fkResolve"` (uuid → related object label via the shared object store with per-schema caching; config `widgetProps { register, schema, labelField }`), and `widget="link"` are built-in; any other id resolves against the app's `cellWidgets` registry (`CnAppRoot`'s `cellWidgets` prop → `cnCellWidgets`), and that component receives `{ value, row, property, formatted, ...widgetProps }`. `widget` takes precedence over `formatter`; when both are set the widget gets the formatter-shaped value as `formatted`. See `docs/migrating-to-manifest.md` → "Column widgets" + "Built-in cell formatters / widgets".
90
92
 
91
93
  - `widget="badge"` — `CnStatusBadge` pill; `widgetProps.variant` picks the colour.
@@ -113,7 +113,14 @@
113
113
  class="cn-cell-renderer__avatar-initials"
114
114
  :style="{ width: avatarSize + 'px', height: avatarSize + 'px' }"
115
115
  aria-hidden="true">{{ avatarInitials }}</span>
116
- <span class="cn-cell-renderer__avatar-name" :title="avatarName || avatarUserId">{{ avatarName || avatarUserId }}</span>
116
+ <span class="cn-cell-renderer__avatar-text">
117
+ <span class="cn-cell-renderer__avatar-name" :title="avatarName || avatarUserId">{{ avatarName || avatarUserId }}</span>
118
+ <!-- The column's secondary line (e-mail), under the name and beside the picture. -->
119
+ <span
120
+ v-if="secondary"
121
+ class="cn-cell-renderer__avatar-secondary"
122
+ data-testid="cn-cell-secondary">{{ secondary }}</span>
123
+ </span>
117
124
  </span>
118
125
  <span v-else class="cn-cell-renderer__dash">—</span>
119
126
  </template>
@@ -406,6 +413,16 @@ export default {
406
413
  default: () => ({}),
407
414
  },
408
415
 
416
+ /**
417
+ * The column's secondary line (a muted second line under the value).
418
+ * The `avatar` widget draws it under the name, beside the picture;
419
+ * other cells ignore it, because the table draws it under the cell.
420
+ */
421
+ secondary: {
422
+ type: String,
423
+ default: '',
424
+ },
425
+
409
426
  /**
410
427
  * Optional declarative cell-format spec — a no-code alternative to a
411
428
  * registry `formatter`. Recognised `style` values:
@@ -560,14 +577,15 @@ export default {
560
577
  },
561
578
 
562
579
  /**
563
- * `avatar` widget: the picture size in pixels (`widgetProps.size`, default 24).
580
+ * `avatar` widget: the picture size in pixels (`widgetProps.size`, default 24,
581
+ * 32 under the board look).
564
582
  *
565
583
  * @return {number}
566
584
  * @spec openspec/changes/workplace-dashboard-primitives/specs/workplace-dashboard-primitives/spec.md#requirement-avatar-and-date-cells
567
585
  */
568
586
  avatarSize() {
569
587
  const size = Number(this.widgetProps && this.widgetProps.size)
570
- return Number.isFinite(size) && size > 0 ? size : 24
588
+ return Number.isFinite(size) && size > 0 ? size : (this.isBoardLook ? 32 : 24)
571
589
  },
572
590
 
573
591
  /**
@@ -1319,11 +1337,33 @@ export default {
1319
1337
  line-height: 1;
1320
1338
  }
1321
1339
 
1340
+ .cn-cell-renderer__avatar-text {
1341
+ display: flex;
1342
+ flex-direction: column;
1343
+ min-width: 0;
1344
+ }
1345
+
1322
1346
  .cn-cell-renderer__avatar-name {
1323
1347
  min-width: 0;
1324
1348
  overflow: hidden;
1325
1349
  text-overflow: ellipsis;
1326
1350
  white-space: nowrap;
1351
+ /* The name is the cell's text: it keeps the weight, size and colour the
1352
+ cell sets, as a plain value does. */
1353
+ font: inherit;
1354
+ color: inherit;
1355
+ }
1356
+
1357
+ .cn-cell-renderer__avatar-secondary {
1358
+ min-width: 0;
1359
+ overflow: hidden;
1360
+ color: var(--color-text-maxcontrast);
1361
+ font-size: 13px;
1362
+ font-weight: 400;
1363
+ line-height: 1.35;
1364
+ text-overflow: ellipsis;
1365
+ text-decoration: none;
1366
+ white-space: nowrap;
1327
1367
  }
1328
1368
 
1329
1369
  /* A date that matched a rule is also set in a heavier weight, so the signal