@conduction/nextcloud-vue 2.141.0 → 2.143.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 (140) hide show
  1. package/dist/esm/components/CnAdminSettingsShell/CnAdminSettingsShell.vue.js +1 -1
  2. package/dist/esm/components/CnAdminSettingsShell/CnAdminSettingsShell.vue2.js +27 -0
  3. package/dist/esm/components/CnAdminSettingsShell/CnAdminSettingsShell.vue2.js.map +1 -1
  4. package/dist/esm/components/CnAdminSettingsShell/CnAdminSettingsShell.vue3.js +1 -1
  5. package/dist/esm/components/CnAdminSettingsShell/CnAdminSettingsShell.vue3.js.map +1 -1
  6. package/dist/esm/components/CnAiCompanion/CnAiChatPanel.vue2.js.map +1 -1
  7. package/dist/esm/components/CnAiCompanion/CnAiChatPanel.vue3.js +2 -1
  8. package/dist/esm/components/CnAiCompanion/CnAiChatPanel.vue3.js.map +1 -1
  9. package/dist/esm/components/CnAiCompanion/CnAiInput.vue2.js +9 -0
  10. package/dist/esm/components/CnAiCompanion/CnAiInput.vue2.js.map +1 -1
  11. package/dist/esm/components/CnAiCompanion/CnAiInput.vue3.js +21 -22
  12. package/dist/esm/components/CnAiCompanion/CnAiInput.vue3.js.map +1 -1
  13. package/dist/esm/components/CnAuditTrailCard/CnAuditTrailCard.vue.js +1 -1
  14. package/dist/esm/components/CnAuditTrailCard/CnAuditTrailCard.vue2.js +29 -1
  15. package/dist/esm/components/CnAuditTrailCard/CnAuditTrailCard.vue2.js.map +1 -1
  16. package/dist/esm/components/CnAuditTrailCard/CnAuditTrailCard.vue3.js +28 -13
  17. package/dist/esm/components/CnAuditTrailCard/CnAuditTrailCard.vue3.js.map +1 -1
  18. package/dist/esm/components/CnAuditTrailWidget/CnAuditTrailWidget.vue.js +1 -1
  19. package/dist/esm/components/CnAuditTrailWidget/CnAuditTrailWidget.vue2.js.map +1 -1
  20. package/dist/esm/components/CnAuditTrailWidget/CnAuditTrailWidget.vue3.js +2 -1
  21. package/dist/esm/components/CnAuditTrailWidget/CnAuditTrailWidget.vue3.js.map +1 -1
  22. package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue.js +1 -1
  23. package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue2.js +13 -0
  24. package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue2.js.map +1 -1
  25. package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue3.js +3 -3
  26. package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue3.js.map +1 -1
  27. package/dist/esm/components/CnChecklistRunWidget/CnChecklistRunWidget.vue.js +1 -1
  28. package/dist/esm/components/CnChecklistRunWidget/CnChecklistRunWidget.vue2.js.map +1 -1
  29. package/dist/esm/components/CnChecklistRunWidget/CnChecklistRunWidget.vue3.js.map +1 -1
  30. package/dist/esm/components/CnChoiceCards/CnChoiceCards.vue.js +1 -1
  31. package/dist/esm/components/CnChoiceCards/CnChoiceCards.vue2.js.map +1 -1
  32. package/dist/esm/components/CnChoiceCards/CnChoiceCards.vue3.js.map +1 -1
  33. package/dist/esm/components/CnDataTable/CnDataTable.vue2.js +21 -0
  34. package/dist/esm/components/CnDataTable/CnDataTable.vue2.js.map +1 -1
  35. package/dist/esm/components/CnDataTable/CnDataTable.vue3.js +1 -1
  36. package/dist/esm/components/CnDataTable/CnDataTable.vue3.js.map +1 -1
  37. package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue.js +1 -1
  38. package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue2.js.map +1 -1
  39. package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue3.js +2 -1
  40. package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue3.js.map +1 -1
  41. package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue.js +1 -1
  42. package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue2.js +34 -3
  43. package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue2.js.map +1 -1
  44. package/dist/esm/components/CnFactsWidget/CnFactsWidget.vue3.js.map +1 -1
  45. package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue.js +1 -1
  46. package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue2.js +70 -5
  47. package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue2.js.map +1 -1
  48. package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue3.js +5 -3
  49. package/dist/esm/components/CnFilesBrowser/CnFilesBrowser.vue3.js.map +1 -1
  50. package/dist/esm/components/CnFilesBrowser/filesBrowser.js +17 -4
  51. package/dist/esm/components/CnFilesBrowser/filesBrowser.js.map +1 -1
  52. package/dist/esm/components/CnFilesBrowser/filesBrowserColumns.js +21 -1
  53. package/dist/esm/components/CnFilesBrowser/filesBrowserColumns.js.map +1 -1
  54. package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js +36 -2
  55. package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js.map +1 -1
  56. package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js +2 -1
  57. package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js.map +1 -1
  58. package/dist/esm/components/CnIndexPage/useSelfFetchList.js +14 -0
  59. package/dist/esm/components/CnIndexPage/useSelfFetchList.js.map +1 -1
  60. package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue.js +1 -1
  61. package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue2.js +3 -1
  62. package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue2.js.map +1 -1
  63. package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue3.js +2 -1
  64. package/dist/esm/components/CnObjectSidebar/CnFilesTab.vue3.js.map +1 -1
  65. package/dist/esm/components/CnPageHeader/CnHeaderTrail.vue2.js +6 -1
  66. package/dist/esm/components/CnPageHeader/CnHeaderTrail.vue2.js.map +1 -1
  67. package/dist/esm/components/CnPageHeader/CnHeaderTrail.vue3.js.map +1 -1
  68. package/dist/esm/components/CnPartyPicker/CnPartyPicker.vue.js +1 -1
  69. package/dist/esm/components/CnPartyPicker/CnPartyPicker.vue2.js +31 -1
  70. package/dist/esm/components/CnPartyPicker/CnPartyPicker.vue2.js.map +1 -1
  71. package/dist/esm/components/CnPartyPicker/CnPartyPicker.vue3.js.map +1 -1
  72. package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue.js +1 -1
  73. package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue2.js +12 -1
  74. package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue2.js.map +1 -1
  75. package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue3.js +2 -2
  76. package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue3.js.map +1 -1
  77. package/dist/esm/components/CnSavedViewAlertWidget/CnSavedViewAlertWidget.vue.js +1 -1
  78. package/dist/esm/components/CnSavedViewAlertWidget/CnSavedViewAlertWidget.vue2.js.map +1 -1
  79. package/dist/esm/components/CnSavedViewAlertWidget/CnSavedViewAlertWidget.vue3.js.map +1 -1
  80. package/dist/esm/components/CnTimelineWidget/CnTimelineManage.vue.js +1 -1
  81. package/dist/esm/components/CnTimelineWidget/CnTimelineManage.vue2.js +4 -0
  82. package/dist/esm/components/CnTimelineWidget/CnTimelineManage.vue2.js.map +1 -1
  83. package/dist/esm/components/CnTimelineWidget/CnTimelineManage.vue3.js +18 -8
  84. package/dist/esm/components/CnTimelineWidget/CnTimelineManage.vue3.js.map +1 -1
  85. package/dist/esm/integrations/builtin/contacts/CnContactsTab.vue.js +1 -1
  86. package/dist/esm/integrations/builtin/contacts/CnContactsTab.vue2.js +52 -1
  87. package/dist/esm/integrations/builtin/contacts/CnContactsTab.vue2.js.map +1 -1
  88. package/dist/esm/integrations/builtin/contacts/CnContactsTab.vue3.js +119 -65
  89. package/dist/esm/integrations/builtin/contacts/CnContactsTab.vue3.js.map +1 -1
  90. package/dist/esm/integrations/builtin/deck/CnDeckCard.vue.js +1 -1
  91. package/dist/esm/integrations/builtin/deck/CnDeckCard.vue2.js +86 -4
  92. package/dist/esm/integrations/builtin/deck/CnDeckCard.vue2.js.map +1 -1
  93. package/dist/esm/integrations/builtin/deck/CnDeckCard.vue3.js +67 -5
  94. package/dist/esm/integrations/builtin/deck/CnDeckCard.vue3.js.map +1 -1
  95. package/dist/esm/l10n/en.json.js +10 -1
  96. package/dist/esm/l10n/en.json.js.map +1 -1
  97. package/dist/esm/l10n/nl.json.js +12 -3
  98. package/dist/esm/l10n/nl.json.js.map +1 -1
  99. package/dist/esm/library-style.js +1 -1
  100. package/dist/esm/nextcloud-vue.css +976 -592
  101. package/dist/esm/utils/buildViewTree.js +23 -8
  102. package/dist/esm/utils/buildViewTree.js.map +1 -1
  103. package/dist/nextcloud-vue.cjs.js +1363 -734
  104. package/dist/nextcloud-vue.cjs.js.map +2 -2
  105. package/dist/nextcloud-vue.css +976 -592
  106. package/l10n/en.json +10 -1
  107. package/l10n/nl.json +12 -3
  108. package/package.json +1 -1
  109. package/src/components/CnAdminSettingsShell/CnAdminSettingsShell.vue +28 -1
  110. package/src/components/CnAiCompanion/CnAiChatPanel.vue +12 -0
  111. package/src/components/CnAiCompanion/CnAiInput.vue +32 -1
  112. package/src/components/CnAuditTrailCard/CnAuditTrailCard.vue +34 -4
  113. package/src/components/CnAuditTrailWidget/CnAuditTrailWidget.vue +1 -0
  114. package/src/components/CnCellRenderer/CnCellRenderer.vue +15 -1
  115. package/src/components/CnChecklistRunWidget/CnChecklistRunWidget.vue +8 -0
  116. package/src/components/CnChoiceCards/CnChoiceCards.vue +1 -0
  117. package/src/components/CnDataTable/CnDataTable.md +1 -0
  118. package/src/components/CnDataTable/CnDataTable.vue +22 -1
  119. package/src/components/CnDetailWidgetHost/CnDetailWidgetHost.vue +1 -0
  120. package/src/components/CnFactsWidget/CnFactsWidget.vue +34 -3
  121. package/src/components/CnFilesBrowser/CnFilesBrowser.vue +72 -7
  122. package/src/components/CnFilesBrowser/filesBrowser.js +17 -4
  123. package/src/components/CnFilesBrowser/filesBrowserColumns.js +20 -1
  124. package/src/components/CnIndexPage/CnIndexPage.vue +37 -2
  125. package/src/components/CnIndexPage/useSelfFetchList.js +14 -0
  126. package/src/components/CnObjectSidebar/CnFilesTab.vue +4 -1
  127. package/src/components/CnPageHeader/CnHeaderTrail.vue +6 -1
  128. package/src/components/CnPartyPicker/CnPartyPicker.vue +31 -1
  129. package/src/components/CnRecordListWidget/CnRecordListWidget.vue +21 -1
  130. package/src/components/CnSavedViewAlertWidget/CnSavedViewAlertWidget.vue +6 -0
  131. package/src/components/CnTimelineWidget/CnTimelineManage.vue +10 -1
  132. package/src/css/dialog.css +18 -0
  133. package/src/css/look-board-detail.css +126 -0
  134. package/src/css/look-board-index.css +95 -1
  135. package/src/css/look-board.css +90 -1
  136. package/src/integrations/builtin/contacts/CnContactsTab.vue +101 -26
  137. package/src/integrations/builtin/contacts/__tests__/CnContactsTabBoardRows.spec.js +67 -0
  138. package/src/integrations/builtin/deck/CnDeckCard.vue +121 -2
  139. package/src/integrations/builtin/deck/__tests__/CnDeckCardHeaderActions.spec.js +68 -0
  140. package/src/utils/buildViewTree.js +23 -8
@@ -3606,7 +3606,16 @@ var translations$s = {
3606
3606
  "Open profile": "Open profile",
3607
3607
  "Link a contact from your address book.": "Link a contact from your address book.",
3608
3608
  "The value could not be shown.": "The value could not be shown.",
3609
- "No value": "No value"
3609
+ "No value": "No value",
3610
+ "Link an existing card": "Link an existing card",
3611
+ "New card": "New card",
3612
+ "Could not link card.": "Could not link card.",
3613
+ "Could not create card.": "Could not create card.",
3614
+ "This card is already linked.": "This card is already linked.",
3615
+ "From {date}": "From {date}",
3616
+ "Until {date}": "Until {date}",
3617
+ "More actions for {name}": "More actions for {name}",
3618
+ "Unlink contact": "Unlink contact"
3610
3619
  };
3611
3620
  var plurals$1 = {
3612
3621
  "{count} member": [
@@ -5898,7 +5907,7 @@ var translations$c = {
5898
5907
  Now: "Nu",
5899
5908
  "Tell me above a number": "Melden vanaf een aantal",
5900
5909
  Threshold: "Grens",
5901
- "A message to you when there are {threshold} or more": "Bericht aan u als er {threshold} of meer zijn",
5910
+ "A message to you when there are {threshold} or more": "Bericht aan u als er {threshold} of meer open zijn",
5902
5911
  "Save this search or open a saved one to set an alert on it.": "Sla deze zoekopdracht op of open een opgeslagen zoekopdracht om er een melding op te zetten.",
5903
5912
  "The alert could not be saved.": "De melding kon niet worden opgeslagen.",
5904
5913
  "Your exports could not be loaded.": "Uw exports konden niet worden geladen.",
@@ -5977,7 +5986,7 @@ var translations$c = {
5977
5986
  "Save current view": "Huidige weergave opslaan",
5978
5987
  "Share view: {name}": "Weergave delen: {name}",
5979
5988
  "The view \"{name}\" leaves your list and the menu on the left.": "De weergave \"{name}\" verdwijnt uit uw lijst en uit het menu links.",
5980
- "Whoever gets the view sees it under Shared with me. It is yours and stays yours.": "Wie de weergave krijgt, ziet die onder Gedeeld met mij. Die is van u en blijft dat.",
5989
+ "Whoever gets the view sees it under Shared with me. It is yours and stays yours.": "Wie de weergave krijgt, ziet hem onder Gedeeld met mij. Hij is van u en blijft dat.",
5981
5990
  "Whoever you share the view with sees the change at once.": "Iedereen met wie u de weergave deelt, ziet de wijziging meteen.",
5982
5991
  Reason: "Reden",
5983
5992
  "Could not be read": "Kon niet worden gelezen",
@@ -6623,7 +6632,16 @@ var translations$c = {
6623
6632
  "Save as draft": "Opslaan als concept",
6624
6633
  "Draft saved at {time}": "Concept opgeslagen om {time}",
6625
6634
  "The draft could not be saved": "Het concept kon niet worden opgeslagen",
6626
- "No value": "Geen waarde"
6635
+ "No value": "Geen waarde",
6636
+ "Link an existing card": "Bestaande kaart koppelen",
6637
+ "New card": "Nieuwe kaart",
6638
+ "Could not link card.": "De kaart kon niet worden gekoppeld.",
6639
+ "Could not create card.": "De kaart kon niet worden gemaakt.",
6640
+ "This card is already linked.": "Deze kaart is al gekoppeld.",
6641
+ "From {date}": "Vanaf {date}",
6642
+ "Until {date}": "Tot {date}",
6643
+ "More actions for {name}": "Meer acties voor {name}",
6644
+ "Unlink contact": "Contact ontkoppelen"
6627
6645
  };
6628
6646
  var plurals = {
6629
6647
  "{count} member": [
@@ -7291,7 +7309,7 @@ const _hoisted_8$4i = {
7291
7309
  key: 0,
7292
7310
  class: "cn-ai-history-list__item-desc"
7293
7311
  };
7294
- const _hoisted_9$3Y = { class: "cn-ai-history-list__item-time" };
7312
+ const _hoisted_9$3X = { class: "cn-ai-history-list__item-time" };
7295
7313
  const _hoisted_10$3t = ["aria-label", "title", "onClick"];
7296
7314
 
7297
7315
  function render$8G(_ctx, _cache, $props, $setup, $data, $options) {
@@ -7393,7 +7411,7 @@ function render$8G(_ctx, _cache, $props, $setup, $data, $options) {
7393
7411
  (conv.description)
7394
7412
  ? (vue$1.openBlock(), vue$1.createElementBlock("span", _hoisted_8$4i, vue$1.toDisplayString(conv.description), 1 /* TEXT */))
7395
7413
  : vue$1.createCommentVNode("v-if", true),
7396
- vue$1.createElementVNode("span", _hoisted_9$3Y, vue$1.toDisplayString($options.formatRelative(conv.updatedAt || conv.createdAt)), 1 /* TEXT */)
7414
+ vue$1.createElementVNode("span", _hoisted_9$3X, vue$1.toDisplayString($options.formatRelative(conv.updatedAt || conv.createdAt)), 1 /* TEXT */)
7397
7415
  ], 8 /* PROPS */, _hoisted_6$5c),
7398
7416
  vue$1.createElementVNode("button", {
7399
7417
  type: "button",
@@ -9216,6 +9234,15 @@ var script$8G = {
9216
9234
  default: '',
9217
9235
  },
9218
9236
 
9237
+ /**
9238
+ * The narrow layout of a card: the text box and the send button on the
9239
+ * first line, dictation and attach on a line under it.
9240
+ */
9241
+ stacked: {
9242
+ type: Boolean,
9243
+ default: false,
9244
+ },
9245
+
9219
9246
  /**
9220
9247
  * Backend app id the attach control uploads files to
9221
9248
  * (`POST /index.php/apps/{chatAppId}/api/chat/attachments`). See
@@ -10023,21 +10050,17 @@ var script$8G = {
10023
10050
  };
10024
10051
 
10025
10052
  const _hoisted_1$8e = {
10026
- class: "cn-ai-input",
10027
- "data-testid": "cn-ai-input"
10028
- };
10029
- const _hoisted_2$7U = {
10030
10053
  key: 2,
10031
10054
  class: "cn-ai-input__chips",
10032
10055
  "data-testid": "cn-ai-input-chips"
10033
10056
  };
10034
- const _hoisted_3$73 = { class: "cn-ai-input__chip-name" };
10035
- const _hoisted_4$6l = ["aria-label", "disabled", "data-testid", "onClick"];
10036
- const _hoisted_5$5C = { class: "cn-ai-input__row" };
10037
- const _hoisted_6$5b = ["aria-label", "title", "aria-pressed", "aria-disabled", "disabled", "data-engine"];
10038
- const _hoisted_7$4J = ["aria-label", "title", "aria-pressed", "disabled"];
10039
- const _hoisted_8$4h = ["aria-label", "disabled", "placeholder"];
10040
- const _hoisted_9$3X = ["aria-label", "disabled"];
10057
+ const _hoisted_2$7U = { class: "cn-ai-input__chip-name" };
10058
+ const _hoisted_3$73 = ["aria-label", "disabled", "data-testid", "onClick"];
10059
+ const _hoisted_4$6l = { class: "cn-ai-input__row" };
10060
+ const _hoisted_5$5C = ["aria-label", "title", "aria-pressed", "aria-disabled", "disabled", "data-engine"];
10061
+ const _hoisted_6$5b = ["aria-label", "title", "aria-pressed", "disabled"];
10062
+ const _hoisted_7$4J = ["aria-label", "disabled", "placeholder"];
10063
+ const _hoisted_8$4h = ["aria-label", "disabled"];
10041
10064
 
10042
10065
  function render$8F(_ctx, _cache, $props, $setup, $data, $options) {
10043
10066
  const _component_NcNoteCard = vue$1.resolveComponent("NcNoteCard");
@@ -10054,7 +10077,10 @@ function render$8F(_ctx, _cache, $props, $setup, $data, $options) {
10054
10077
  const _component_NcActions = vue$1.resolveComponent("NcActions");
10055
10078
  const _component_Send = vue$1.resolveComponent("Send");
10056
10079
 
10057
- return (vue$1.openBlock(), vue$1.createElementBlock("div", _hoisted_1$8e, [
10080
+ return (vue$1.openBlock(), vue$1.createElementBlock("div", {
10081
+ class: vue$1.normalizeClass(["cn-ai-input", { 'cn-ai-input--stacked': $props.stacked }]),
10082
+ "data-testid": "cn-ai-input"
10083
+ }, [
10058
10084
  ($data.uploadError)
10059
10085
  ? (vue$1.openBlock(), vue$1.createBlock(_component_NcNoteCard, {
10060
10086
  key: 0,
@@ -10082,7 +10108,7 @@ function render$8F(_ctx, _cache, $props, $setup, $data, $options) {
10082
10108
  }))
10083
10109
  : vue$1.createCommentVNode("v-if", true),
10084
10110
  ($data.attachments.length)
10085
- ? (vue$1.openBlock(), vue$1.createElementBlock("ul", _hoisted_2$7U, [
10111
+ ? (vue$1.openBlock(), vue$1.createElementBlock("ul", _hoisted_1$8e, [
10086
10112
  (vue$1.openBlock(true), vue$1.createElementBlock(vue$1.Fragment, null, vue$1.renderList($data.attachments, (attachment, index) => {
10087
10113
  return (vue$1.openBlock(), vue$1.createElementBlock("li", {
10088
10114
  key: attachment.fileId !== undefined ? 'f' + attachment.fileId : attachment.path,
@@ -10092,7 +10118,7 @@ function render$8F(_ctx, _cache, $props, $setup, $data, $options) {
10092
10118
  size: 14,
10093
10119
  class: "cn-ai-input__chip-icon"
10094
10120
  }),
10095
- vue$1.createElementVNode("span", _hoisted_3$73, vue$1.toDisplayString(attachment.name), 1 /* TEXT */),
10121
+ vue$1.createElementVNode("span", _hoisted_2$7U, vue$1.toDisplayString(attachment.name), 1 /* TEXT */),
10096
10122
  vue$1.createElementVNode("button", {
10097
10123
  type: "button",
10098
10124
  class: "cn-ai-input__chip-remove",
@@ -10102,12 +10128,12 @@ function render$8F(_ctx, _cache, $props, $setup, $data, $options) {
10102
10128
  onClick: $event => ($options.removeAttachment(index))
10103
10129
  }, [
10104
10130
  vue$1.createVNode(_component_Close, { size: 14 })
10105
- ], 8 /* PROPS */, _hoisted_4$6l)
10131
+ ], 8 /* PROPS */, _hoisted_3$73)
10106
10132
  ]))
10107
10133
  }), 128 /* KEYED_FRAGMENT */))
10108
10134
  ]))
10109
10135
  : vue$1.createCommentVNode("v-if", true),
10110
- vue$1.createElementVNode("div", _hoisted_5$5C, [
10136
+ vue$1.createElementVNode("div", _hoisted_4$6l, [
10111
10137
  ($options.speechButtonVisible)
10112
10138
  ? (vue$1.openBlock(), vue$1.createElementBlock("button", {
10113
10139
  key: 0,
@@ -10140,7 +10166,7 @@ function render$8F(_ctx, _cache, $props, $setup, $data, $options) {
10140
10166
  key: 2,
10141
10167
  size: 20
10142
10168
  }))
10143
- ], 10 /* CLASS, PROPS */, _hoisted_6$5b))
10169
+ ], 10 /* CLASS, PROPS */, _hoisted_5$5C))
10144
10170
  : vue$1.createCommentVNode("v-if", true),
10145
10171
  ($options.conversationButtonVisible)
10146
10172
  ? (vue$1.openBlock(), vue$1.createElementBlock("button", {
@@ -10163,7 +10189,7 @@ function render$8F(_ctx, _cache, $props, $setup, $data, $options) {
10163
10189
  key: 1,
10164
10190
  size: 20
10165
10191
  }))
10166
- ], 10 /* CLASS, PROPS */, _hoisted_7$4J))
10192
+ ], 10 /* CLASS, PROPS */, _hoisted_6$5b))
10167
10193
  : vue$1.createCommentVNode("v-if", true),
10168
10194
  vue$1.createVNode(_component_NcActions, {
10169
10195
  class: "cn-ai-input__attach-menu",
@@ -10234,7 +10260,7 @@ function render$8F(_ctx, _cache, $props, $setup, $data, $options) {
10234
10260
  _cache[5] || (_cache[5] = vue$1.withKeys(vue$1.withModifiers((...args) => ($options.handleShiftEnter && $options.handleShiftEnter(...args)), ["shift","exact"]), ["enter"]))
10235
10261
  ],
10236
10262
  onInput: _cache[6] || (_cache[6] = (...args) => ($options.autoGrow && $options.autoGrow(...args)))
10237
- }, null, 40 /* PROPS, NEED_HYDRATION */, _hoisted_8$4h), [
10263
+ }, null, 40 /* PROPS, NEED_HYDRATION */, _hoisted_7$4J), [
10238
10264
  [vue$1.vModelText, $data.inputText]
10239
10265
  ]),
10240
10266
  vue$1.createElementVNode("button", {
@@ -10258,9 +10284,9 @@ function render$8F(_ctx, _cache, $props, $setup, $data, $options) {
10258
10284
  key: 2,
10259
10285
  size: 20
10260
10286
  }))
10261
- ], 10 /* CLASS, PROPS */, _hoisted_9$3X)
10287
+ ], 10 /* CLASS, PROPS */, _hoisted_8$4h)
10262
10288
  ])
10263
- ]))
10289
+ ], 2 /* CLASS */))
10264
10290
  }
10265
10291
 
10266
10292
  script$8G.render = render$8F;
@@ -10481,7 +10507,7 @@ const _hoisted_10$3s = {
10481
10507
  "data-testid": "cn-ai-message-attachments"
10482
10508
  };
10483
10509
  const _hoisted_11$36 = ["href"];
10484
- const _hoisted_12$2O = ["src", "alt"];
10510
+ const _hoisted_12$2P = ["src", "alt"];
10485
10511
  const _hoisted_13$2w = ["href"];
10486
10512
  const _hoisted_14$2m = {
10487
10513
  key: 2,
@@ -10507,7 +10533,7 @@ const _hoisted_20$1g = {
10507
10533
  "data-testid": "cn-ai-thinking"
10508
10534
  };
10509
10535
  const _hoisted_21$1e = ["aria-label"];
10510
- const _hoisted_22$1b = { class: "cn-ai-message-list__thinking-text" };
10536
+ const _hoisted_22$1c = { class: "cn-ai-message-list__thinking-text" };
10511
10537
 
10512
10538
  function render$8E(_ctx, _cache, $props, $setup, $data, $options) {
10513
10539
  const _component_NcRichText = vue$1.resolveComponent("NcRichText");
@@ -10585,7 +10611,7 @@ function render$8E(_ctx, _cache, $props, $setup, $data, $options) {
10585
10611
  src: $options.previewSrc(file),
10586
10612
  alt: file.name,
10587
10613
  loading: "lazy"
10588
- }, null, 8 /* PROPS */, _hoisted_12$2O)
10614
+ }, null, 8 /* PROPS */, _hoisted_12$2P)
10589
10615
  ], 8 /* PROPS */, _hoisted_11$36))
10590
10616
  : ($options.fileHref(file))
10591
10617
  ? (vue$1.openBlock(), vue$1.createElementBlock("a", {
@@ -10646,7 +10672,7 @@ function render$8E(_ctx, _cache, $props, $setup, $data, $options) {
10646
10672
  role: "status",
10647
10673
  "aria-live": "polite"
10648
10674
  }, [
10649
- vue$1.createElementVNode("span", _hoisted_22$1b, vue$1.toDisplayString($options.cnTranslate('Thinking')), 1 /* TEXT */),
10675
+ vue$1.createElementVNode("span", _hoisted_22$1c, vue$1.toDisplayString($options.cnTranslate('Thinking')), 1 /* TEXT */),
10650
10676
  _cache[0] || (_cache[0] = vue$1.createElementVNode("span", {
10651
10677
  class: "cn-ai-message-list__thinking-dots",
10652
10678
  "aria-hidden": "true"
@@ -11752,7 +11778,7 @@ const _hoisted_9$3V = {
11752
11778
  };
11753
11779
  const _hoisted_10$3r = { class: "cn-ai-approval__head" };
11754
11780
  const _hoisted_11$35 = { class: "cn-ai-approval__title" };
11755
- const _hoisted_12$2N = { class: "cn-ai-approval__reach" };
11781
+ const _hoisted_12$2O = { class: "cn-ai-approval__reach" };
11756
11782
  const _hoisted_13$2v = {
11757
11783
  key: 0,
11758
11784
  class: "cn-ai-approval__reason"
@@ -12013,7 +12039,7 @@ function render$8D(_ctx, _cache, $props, $setup, $data, $options) {
12013
12039
  }, [
12014
12040
  vue$1.createElementVNode("div", _hoisted_10$3r, [
12015
12041
  vue$1.createElementVNode("span", _hoisted_11$35, vue$1.toDisplayString(approval.title), 1 /* TEXT */),
12016
- vue$1.createElementVNode("span", _hoisted_12$2N, vue$1.toDisplayString(approval.reach), 1 /* TEXT */)
12042
+ vue$1.createElementVNode("span", _hoisted_12$2O, vue$1.toDisplayString(approval.reach), 1 /* TEXT */)
12017
12043
  ]),
12018
12044
  (approval.reason)
12019
12045
  ? (vue$1.openBlock(), vue$1.createElementBlock("p", _hoisted_13$2v, vue$1.toDisplayString(approval.reason), 1 /* TEXT */))
@@ -12064,6 +12090,7 @@ function render$8D(_ctx, _cache, $props, $setup, $data, $options) {
12064
12090
  disabled: $props.streamState.isStreaming,
12065
12091
  placeholder: $props.inputPlaceholder,
12066
12092
  sendLabel: $props.sendLabel,
12093
+ stacked: $props.titled,
12067
12094
  chatAppId: $props.chatAppId,
12068
12095
  speechInputEngine: $options.speechPolicy.inputEngine,
12069
12096
  dictationSilenceTimeout: $options.speechPolicy.silenceTimeout,
@@ -12071,7 +12098,7 @@ function render$8D(_ctx, _cache, $props, $setup, $data, $options) {
12071
12098
  conversationEnabled: $options.speechPolicy.conversationEnabled,
12072
12099
  onSend: $options.onSend,
12073
12100
  onConversationState: $options.onConversationTurn
12074
- }, null, 8 /* PROPS */, ["disabled", "placeholder", "sendLabel", "chatAppId", "speechInputEngine", "dictationSilenceTimeout", "localSpeechAvailable", "conversationEnabled", "onSend", "onConversationState"])
12101
+ }, null, 8 /* PROPS */, ["disabled", "placeholder", "sendLabel", "stacked", "chatAppId", "speechInputEngine", "dictationSilenceTimeout", "localSpeechAvailable", "conversationEnabled", "onSend", "onConversationState"])
12075
12102
  ])
12076
12103
  ]))
12077
12104
  : (vue$1.openBlock(), vue$1.createElementBlock("div", _hoisted_18$1v, [
@@ -26790,7 +26817,7 @@ const _hoisted_11$34 = {
26790
26817
  class: "cn-chart-widget__html",
26791
26818
  "data-testid": "cn-chart-widget-matrix"
26792
26819
  };
26793
- const _hoisted_12$2M = ["aria-label"];
26820
+ const _hoisted_12$2N = ["aria-label"];
26794
26821
  const _hoisted_13$2u = {
26795
26822
  role: "row",
26796
26823
  class: "cn-chart-widget__matrix-row"
@@ -26819,7 +26846,7 @@ const _hoisted_20$1e = {
26819
26846
  "data-testid": "cn-chart-widget-footnote"
26820
26847
  };
26821
26848
  const _hoisted_21$1c = { class: "cn-chart-widget__notice-text" };
26822
- const _hoisted_22$1a = { key: 0 };
26849
+ const _hoisted_22$1b = { key: 0 };
26823
26850
 
26824
26851
  function render$8y(_ctx, _cache, $props, $setup, $data, $options) {
26825
26852
  const _component_CnEndpointNotice = vue$1.resolveComponent("CnEndpointNotice");
@@ -26957,7 +26984,7 @@ function render$8y(_ctx, _cache, $props, $setup, $data, $options) {
26957
26984
  }), 128 /* KEYED_FRAGMENT */))
26958
26985
  ]))
26959
26986
  }), 128 /* KEYED_FRAGMENT */))
26960
- ], 12 /* STYLE, PROPS */, _hoisted_12$2M),
26987
+ ], 12 /* STYLE, PROPS */, _hoisted_12$2N),
26961
26988
  ($props.footnote)
26962
26989
  ? (vue$1.openBlock(), vue$1.createElementBlock("p", _hoisted_16$1W, vue$1.toDisplayString($options.hostTranslate($props.footnote)), 1 /* TEXT */))
26963
26990
  : vue$1.createCommentVNode("v-if", true)
@@ -26992,7 +27019,7 @@ function render$8y(_ctx, _cache, $props, $setup, $data, $options) {
26992
27019
  default: vue$1.withCtx(() => [
26993
27020
  vue$1.createElementVNode("p", _hoisted_21$1c, [
26994
27021
  ($options.noticeParts.lead)
26995
- ? (vue$1.openBlock(), vue$1.createElementBlock("strong", _hoisted_22$1a, vue$1.toDisplayString($options.noticeParts.lead), 1 /* TEXT */))
27022
+ ? (vue$1.openBlock(), vue$1.createElementBlock("strong", _hoisted_22$1b, vue$1.toDisplayString($options.noticeParts.lead), 1 /* TEXT */))
26996
27023
  : vue$1.createCommentVNode("v-if", true),
26997
27024
  vue$1.createTextVNode(vue$1.toDisplayString($options.noticeParts.lead && $options.noticeParts.text ? ' ' : '') + vue$1.toDisplayString($options.noticeParts.text), 1 /* TEXT */)
26998
27025
  ])
@@ -29431,7 +29458,7 @@ const _hoisted_11$33 = {
29431
29458
  key: 0,
29432
29459
  class: "cn-quick-filter-bar__label"
29433
29460
  };
29434
- const _hoisted_12$2L = { class: "cn-quick-filter-bar__more-heading" };
29461
+ const _hoisted_12$2M = { class: "cn-quick-filter-bar__more-heading" };
29435
29462
  const _hoisted_13$2t = { class: "cn-quick-filter-bar__more-list" };
29436
29463
  const _hoisted_14$2j = ["aria-pressed", "onClick"];
29437
29464
  const _hoisted_15$26 = { class: "cn-quick-filter-bar__label" };
@@ -29564,7 +29591,7 @@ function render$8r(_ctx, _cache, $props, $setup, $data, $options) {
29564
29591
  class: "cn-quick-filter-bar__more-panel",
29565
29592
  onKeydown: _cache[1] || (_cache[1] = vue$1.withKeys(vue$1.withModifiers($event => ($data.moreOpen = false), ["stop"]), ["escape"]))
29566
29593
  }, [
29567
- vue$1.createElementVNode("p", _hoisted_12$2L, vue$1.toDisplayString($options.moreHeading), 1 /* TEXT */),
29594
+ vue$1.createElementVNode("p", _hoisted_12$2M, vue$1.toDisplayString($options.moreHeading), 1 /* TEXT */),
29568
29595
  vue$1.createElementVNode("div", _hoisted_13$2t, [
29569
29596
  (vue$1.openBlock(true), vue$1.createElementBlock(vue$1.Fragment, null, vue$1.renderList($options.overflowEntries, (entry) => {
29570
29597
  return (vue$1.openBlock(), vue$1.createElementBlock("button", {
@@ -30074,7 +30101,7 @@ const _hoisted_11$32 = {
30074
30101
  class: "cn-conversation-thread__avatar",
30075
30102
  "aria-hidden": "true"
30076
30103
  };
30077
- const _hoisted_12$2K = { class: "cn-conversation-thread__bubble" };
30104
+ const _hoisted_12$2L = { class: "cn-conversation-thread__bubble" };
30078
30105
  const _hoisted_13$2s = { class: "cn-conversation-thread__meta" };
30079
30106
  const _hoisted_14$2i = { class: "hidden-visually" };
30080
30107
  const _hoisted_15$25 = { class: "cn-conversation-thread__author" };
@@ -30101,12 +30128,12 @@ const _hoisted_21$1b = {
30101
30128
  class: "cn-conversation-thread__note",
30102
30129
  "data-testid": "cn-conversation-note"
30103
30130
  };
30104
- const _hoisted_22$19 = {
30131
+ const _hoisted_22$1a = {
30105
30132
  key: 1,
30106
30133
  class: "cn-conversation-thread__message-actions"
30107
30134
  };
30108
- const _hoisted_23$_ = { class: "cn-conversation-thread__reply-head" };
30109
- const _hoisted_24$U = ["for"];
30135
+ const _hoisted_23$$ = { class: "cn-conversation-thread__reply-head" };
30136
+ const _hoisted_24$V = ["for"];
30110
30137
  const _hoisted_25$N = {
30111
30138
  key: 0,
30112
30139
  class: "cn-conversation-thread__reply-hint",
@@ -30184,7 +30211,7 @@ function render$8q(_ctx, _cache, $props, $setup, $data, $options) {
30184
30211
  "data-side": row.side
30185
30212
  }, [
30186
30213
  vue$1.createElementVNode("span", _hoisted_11$32, vue$1.toDisplayString(row.initials), 1 /* TEXT */),
30187
- vue$1.createElementVNode("div", _hoisted_12$2K, [
30214
+ vue$1.createElementVNode("div", _hoisted_12$2L, [
30188
30215
  vue$1.createElementVNode("span", _hoisted_13$2s, [
30189
30216
  vue$1.createElementVNode("span", _hoisted_14$2i, vue$1.toDisplayString(row.directionLabel), 1 /* TEXT */),
30190
30217
  vue$1.createElementVNode("span", _hoisted_15$25, vue$1.toDisplayString(row.author), 1 /* TEXT */),
@@ -30209,7 +30236,7 @@ function render$8q(_ctx, _cache, $props, $setup, $data, $options) {
30209
30236
  ? (vue$1.openBlock(), vue$1.createElementBlock("span", _hoisted_21$1b, vue$1.toDisplayString(row.note), 1 /* TEXT */))
30210
30237
  : vue$1.createCommentVNode("v-if", true),
30211
30238
  (row.actions.length > 0)
30212
- ? (vue$1.openBlock(), vue$1.createElementBlock("span", _hoisted_22$19, [
30239
+ ? (vue$1.openBlock(), vue$1.createElementBlock("span", _hoisted_22$1a, [
30213
30240
  (vue$1.openBlock(true), vue$1.createElementBlock(vue$1.Fragment, null, vue$1.renderList(row.actions, (action) => {
30214
30241
  return (vue$1.openBlock(), vue$1.createBlock(_component_NcButton, {
30215
30242
  key: action.id,
@@ -30238,11 +30265,11 @@ function render$8q(_ctx, _cache, $props, $setup, $data, $options) {
30238
30265
  onSubmit: _cache[4] || (_cache[4] = vue$1.withModifiers((...args) => ($options.onSend && $options.onSend(...args)), ["prevent"]))
30239
30266
  }, [
30240
30267
  vue$1.renderSlot(_ctx.$slots, "reply-tools", { setDraft: $options.setDraft }),
30241
- vue$1.createElementVNode("div", _hoisted_23$_, [
30268
+ vue$1.createElementVNode("div", _hoisted_23$$, [
30242
30269
  vue$1.createElementVNode("label", {
30243
30270
  for: $data.inputId,
30244
30271
  class: "cn-conversation-thread__reply-label"
30245
- }, vue$1.toDisplayString($props.replyLabel), 9 /* TEXT, PROPS */, _hoisted_24$U),
30272
+ }, vue$1.toDisplayString($props.replyLabel), 9 /* TEXT, PROPS */, _hoisted_24$V),
30246
30273
  ($props.replyHint)
30247
30274
  ? (vue$1.openBlock(), vue$1.createElementBlock("span", _hoisted_25$N, vue$1.toDisplayString($props.replyHint), 1 /* TEXT */))
30248
30275
  : vue$1.createCommentVNode("v-if", true)
@@ -37308,7 +37335,7 @@ const _hoisted_9$3P = {
37308
37335
  };
37309
37336
  const _hoisted_10$3n = { class: "cn-calendar-event-picker__breadcrumb" };
37310
37337
  const _hoisted_11$31 = { class: "cn-calendar-event-picker__breadcrumb-calendar" };
37311
- const _hoisted_12$2J = {
37338
+ const _hoisted_12$2K = {
37312
37339
  key: 1,
37313
37340
  class: "cn-calendar-event-picker__banner cn-calendar-event-picker__banner--error",
37314
37341
  role: "alert"
@@ -37428,7 +37455,7 @@ function render$8h(_ctx, _cache, $props, $setup, $data, $options) {
37428
37455
  size: 32
37429
37456
  }))
37430
37457
  : ($data.errorEvents)
37431
- ? (vue$1.openBlock(), vue$1.createElementBlock("div", _hoisted_12$2J, vue$1.toDisplayString($data.errorEvents), 1 /* TEXT */))
37458
+ ? (vue$1.openBlock(), vue$1.createElementBlock("div", _hoisted_12$2K, vue$1.toDisplayString($data.errorEvents), 1 /* TEXT */))
37432
37459
  : ($options.filteredEvents.length > 0)
37433
37460
  ? (vue$1.openBlock(), vue$1.createElementBlock("ul", _hoisted_13$2r, [
37434
37461
  (vue$1.openBlock(true), vue$1.createElementBlock(vue$1.Fragment, null, vue$1.renderList($options.filteredEvents, (ev) => {
@@ -42388,7 +42415,7 @@ const _hoisted_11$30 = {
42388
42415
  key: 4,
42389
42416
  class: "cn-pagination__page-size"
42390
42417
  };
42391
- const _hoisted_12$2I = ["for"];
42418
+ const _hoisted_12$2J = ["for"];
42392
42419
 
42393
42420
  function render$88(_ctx, _cache, $props, $setup, $data, $options) {
42394
42421
  const _component_ChevronLeft = vue$1.resolveComponent("ChevronLeft");
@@ -42541,7 +42568,7 @@ function render$88(_ctx, _cache, $props, $setup, $data, $options) {
42541
42568
  : vue$1.createCommentVNode("v-if", true),
42542
42569
  (!$props.compact && !$options.isBoardVariant)
42543
42570
  ? (vue$1.openBlock(), vue$1.createElementBlock("div", _hoisted_11$30, [
42544
- vue$1.createElementVNode("label", { for: $options.pageSizeId }, vue$1.toDisplayString($props.itemsPerPageLabel), 9 /* TEXT, PROPS */, _hoisted_12$2I),
42571
+ vue$1.createElementVNode("label", { for: $options.pageSizeId }, vue$1.toDisplayString($props.itemsPerPageLabel), 9 /* TEXT, PROPS */, _hoisted_12$2J),
42545
42572
  vue$1.createVNode(_component_NcSelect, {
42546
42573
  inputId: $options.pageSizeId,
42547
42574
  class: "cn-pagination__page-size-select",
@@ -42885,7 +42912,7 @@ const _hoisted_11$2$ = {
42885
42912
  key: 1,
42886
42913
  class: "cn-column-filter__options"
42887
42914
  };
42888
- const _hoisted_12$2H = { class: "cn-column-filter__sr-only" };
42915
+ const _hoisted_12$2I = { class: "cn-column-filter__sr-only" };
42889
42916
  const _hoisted_13$2q = ["name", "value", "checked", "onChange"];
42890
42917
  const _hoisted_14$2g = {
42891
42918
  key: 2,
@@ -42901,8 +42928,8 @@ const _hoisted_21$1a = {
42901
42928
  key: 3,
42902
42929
  class: "cn-column-filter__field"
42903
42930
  };
42904
- const _hoisted_22$18 = { class: "cn-column-filter__label" };
42905
- const _hoisted_23$Z = { class: "cn-column-filter__actions" };
42931
+ const _hoisted_22$19 = { class: "cn-column-filter__label" };
42932
+ const _hoisted_23$_ = { class: "cn-column-filter__actions" };
42906
42933
 
42907
42934
  function render$87(_ctx, _cache, $props, $setup, $data, $options) {
42908
42935
  return (vue$1.openBlock(), vue$1.createBlock(vue$1.Teleport, {
@@ -42970,7 +42997,7 @@ function render$87(_ctx, _cache, $props, $setup, $data, $options) {
42970
42997
  ], 64 /* STABLE_FRAGMENT */))
42971
42998
  : ($props.def.kind === 'boolean')
42972
42999
  ? (vue$1.openBlock(), vue$1.createElementBlock("fieldset", _hoisted_11$2$, [
42973
- vue$1.createElementVNode("legend", _hoisted_12$2H, vue$1.toDisplayString($options.headingText), 1 /* TEXT */),
43000
+ vue$1.createElementVNode("legend", _hoisted_12$2I, vue$1.toDisplayString($options.headingText), 1 /* TEXT */),
42974
43001
  (vue$1.openBlock(true), vue$1.createElementBlock(vue$1.Fragment, null, vue$1.renderList($options.booleanOptions, (option) => {
42975
43002
  return (vue$1.openBlock(), vue$1.createElementBlock("label", {
42976
43003
  key: option.value,
@@ -43014,7 +43041,7 @@ function render$87(_ctx, _cache, $props, $setup, $data, $options) {
43014
43041
  ])
43015
43042
  ]))
43016
43043
  : (vue$1.openBlock(), vue$1.createElementBlock("label", _hoisted_21$1a, [
43017
- vue$1.createElementVNode("span", _hoisted_22$18, vue$1.toDisplayString($options.containsLabel), 1 /* TEXT */),
43044
+ vue$1.createElementVNode("span", _hoisted_22$19, vue$1.toDisplayString($options.containsLabel), 1 /* TEXT */),
43018
43045
  vue$1.withDirectives(vue$1.createElementVNode("input", {
43019
43046
  "onUpdate:modelValue": _cache[4] || (_cache[4] = $event => (($data.draft.value) = $event)),
43020
43047
  class: "cn-column-filter__input",
@@ -43024,7 +43051,7 @@ function render$87(_ctx, _cache, $props, $setup, $data, $options) {
43024
43051
  [vue$1.vModelText, $data.draft.value]
43025
43052
  ])
43026
43053
  ])),
43027
- vue$1.createElementVNode("div", _hoisted_23$Z, [
43054
+ vue$1.createElementVNode("div", _hoisted_23$_, [
43028
43055
  vue$1.createElementVNode("button", {
43029
43056
  type: "button",
43030
43057
  class: "cn-column-filter__button",
@@ -45202,6 +45229,19 @@ var script$85 = {
45202
45229
  * @return {number}
45203
45230
  * @spec openspec/changes/workplace-dashboard-primitives/specs/workplace-dashboard-primitives/spec.md#requirement-avatar-and-date-cells
45204
45231
  */
45232
+ /**
45233
+ * `avatar` widget: the chip's tone class in the board look,
45234
+ * `widgetProps.tone` `neutral` (DqContacten's grey chip) or the
45235
+ * default light primary.
45236
+ *
45237
+ * @return {string}
45238
+ * @spec openspec/changes/board-avatar-chip/specs/data-table/spec.md#requirement-a-board-avatar-cell-draws-the-initials-chip
45239
+ */
45240
+ avatarToneClass() {
45241
+ const tone = this.widgetProps && this.widgetProps.tone;
45242
+ return tone === 'neutral' ? 'cn-cell-renderer__avatar-initials--neutral' : ''
45243
+ },
45244
+
45205
45245
  avatarSize() {
45206
45246
  const size = Number(this.widgetProps && this.widgetProps.size);
45207
45247
  return Number.isFinite(size) && size > 0 ? size : (this.isBoardLook ? 32 : 24)
@@ -46309,7 +46349,7 @@ const _hoisted_11$2_ = {
46309
46349
  key: 0,
46310
46350
  class: "cn-cell-renderer__dash"
46311
46351
  };
46312
- const _hoisted_12$2G = {
46352
+ const _hoisted_12$2H = {
46313
46353
  key: 1,
46314
46354
  class: "cn-cell-renderer__ref-labels",
46315
46355
  "data-testid": "cn-cell-ref-labels"
@@ -46336,13 +46376,13 @@ const _hoisted_21$19 = {
46336
46376
  key: 0,
46337
46377
  class: "cn-cell-renderer__avatar"
46338
46378
  };
46339
- const _hoisted_22$17 = {
46379
+ const _hoisted_22$18 = {
46340
46380
  key: 0,
46341
46381
  class: "cn-cell-renderer__avatar-picture",
46342
46382
  "aria-hidden": "true"
46343
46383
  };
46344
- const _hoisted_23$Y = { class: "cn-cell-renderer__avatar-text" };
46345
- const _hoisted_24$T = ["title"];
46384
+ const _hoisted_23$Z = { class: "cn-cell-renderer__avatar-text" };
46385
+ const _hoisted_24$U = ["title"];
46346
46386
  const _hoisted_25$M = {
46347
46387
  key: 0,
46348
46388
  class: "cn-cell-renderer__avatar-secondary",
@@ -46364,7 +46404,7 @@ const _hoisted_30$s = {
46364
46404
  "data-testid": "cn-cell-renderer-due"
46365
46405
  };
46366
46406
  const _hoisted_31$q = ["datetime", "title"];
46367
- const _hoisted_32$p = { class: "cn-cell-renderer__date-tile" };
46407
+ const _hoisted_32$q = { class: "cn-cell-renderer__date-tile" };
46368
46408
  const _hoisted_33$o = { class: "cn-cell-renderer__date-day" };
46369
46409
  const _hoisted_34$o = { class: "cn-cell-renderer__date-month" };
46370
46410
  const _hoisted_35$m = { class: "cn-cell-renderer__date-lines" };
@@ -46566,7 +46606,7 @@ function render$84(_ctx, _cache, $props, $setup, $data, $options) {
46566
46606
  ? (vue$1.openBlock(), vue$1.createElementBlock(vue$1.Fragment, { key: 7 }, [
46567
46607
  (!$options.refLabelItems.length)
46568
46608
  ? (vue$1.openBlock(), vue$1.createElementBlock("span", _hoisted_11$2_, "—"))
46569
- : (vue$1.openBlock(), vue$1.createElementBlock("span", _hoisted_12$2G, [
46609
+ : (vue$1.openBlock(), vue$1.createElementBlock("span", _hoisted_12$2H, [
46570
46610
  (vue$1.openBlock(true), vue$1.createElementBlock(vue$1.Fragment, null, vue$1.renderList($options.refLabelItems, (item, i) => {
46571
46611
  return (vue$1.openBlock(), vue$1.createElementBlock(vue$1.Fragment, {
46572
46612
  key: item.id
@@ -46650,8 +46690,8 @@ function render$84(_ctx, _cache, $props, $setup, $data, $options) {
46650
46690
  ? (vue$1.openBlock(), vue$1.createElementBlock(vue$1.Fragment, { key: 10 }, [
46651
46691
  ($options.avatarName || $options.avatarUserId)
46652
46692
  ? (vue$1.openBlock(), vue$1.createElementBlock("span", _hoisted_21$19, [
46653
- ($options.avatarUserId)
46654
- ? (vue$1.openBlock(), vue$1.createElementBlock("span", _hoisted_22$17, [
46693
+ ($options.avatarUserId && !$options.isBoardLook)
46694
+ ? (vue$1.openBlock(), vue$1.createElementBlock("span", _hoisted_22$18, [
46655
46695
  vue$1.createVNode(_component_NcAvatar, {
46656
46696
  user: $options.avatarUserId,
46657
46697
  displayName: $options.avatarName || $options.avatarUserId,
@@ -46662,15 +46702,15 @@ function render$84(_ctx, _cache, $props, $setup, $data, $options) {
46662
46702
  ]))
46663
46703
  : (vue$1.openBlock(), vue$1.createElementBlock("span", {
46664
46704
  key: 1,
46665
- class: "cn-cell-renderer__avatar-initials",
46705
+ class: vue$1.normalizeClass(["cn-cell-renderer__avatar-initials", $options.avatarToneClass]),
46666
46706
  style: vue$1.normalizeStyle({ width: $options.avatarSize + 'px', height: $options.avatarSize + 'px' }),
46667
46707
  "aria-hidden": "true"
46668
- }, vue$1.toDisplayString($options.avatarInitials), 5 /* TEXT, STYLE */)),
46669
- vue$1.createElementVNode("span", _hoisted_23$Y, [
46708
+ }, vue$1.toDisplayString($options.avatarInitials), 7 /* TEXT, CLASS, STYLE */)),
46709
+ vue$1.createElementVNode("span", _hoisted_23$Z, [
46670
46710
  vue$1.createElementVNode("span", {
46671
46711
  class: "cn-cell-renderer__avatar-name",
46672
46712
  title: $options.avatarName || $options.avatarUserId
46673
- }, vue$1.toDisplayString($options.avatarName || $options.avatarUserId), 9 /* TEXT, PROPS */, _hoisted_24$T),
46713
+ }, vue$1.toDisplayString($options.avatarName || $options.avatarUserId), 9 /* TEXT, PROPS */, _hoisted_24$U),
46674
46714
  ($props.secondary)
46675
46715
  ? (vue$1.openBlock(), vue$1.createElementBlock("span", _hoisted_25$M, vue$1.toDisplayString($props.secondary), 1 /* TEXT */))
46676
46716
  : vue$1.createCommentVNode("v-if", true)
@@ -46711,7 +46751,7 @@ function render$84(_ctx, _cache, $props, $setup, $data, $options) {
46711
46751
  title: $options.absoluteDateLabel,
46712
46752
  "data-testid": "cn-cell-date-block"
46713
46753
  }, [
46714
- vue$1.createElementVNode("span", _hoisted_32$p, [
46754
+ vue$1.createElementVNode("span", _hoisted_32$q, [
46715
46755
  vue$1.createElementVNode("strong", _hoisted_33$o, vue$1.toDisplayString($options.dateBlock.day), 1 /* TEXT */),
46716
46756
  vue$1.createElementVNode("span", _hoisted_34$o, vue$1.toDisplayString($options.dateBlock.month), 1 /* TEXT */)
46717
46757
  ]),
@@ -46934,7 +46974,7 @@ function render$84(_ctx, _cache, $props, $setup, $data, $options) {
46934
46974
  }
46935
46975
 
46936
46976
  script$85.render = render$84;
46937
- script$85.__scopeId = "data-v-abd08d9e";
46977
+ script$85.__scopeId = "data-v-16a6d8b8";
46938
46978
  const __sfc_main$7$ = script$85;
46939
46979
 
46940
46980
  /**
@@ -47266,6 +47306,17 @@ var script$82 = {
47266
47306
  default: null,
47267
47307
  },
47268
47308
 
47309
+ /**
47310
+ * The tone of the leading icon's tile in the board look: `primary`
47311
+ * (default), `teal` or `neutral` (DqOrganisaties draws a teal tile).
47312
+ *
47313
+ * @type {string}
47314
+ */
47315
+ rowIconTone: {
47316
+ type: String,
47317
+ default: 'primary',
47318
+ },
47319
+
47269
47320
  /**
47270
47321
  * State indicators a page declares for its rows. Each entry is
47271
47322
  * `{ id, field, equals?, in?, icon, text, tooltip? }`: `field` is a
@@ -47792,6 +47843,16 @@ var script$82 = {
47792
47843
  },
47793
47844
 
47794
47845
  computed: {
47846
+ /**
47847
+ * The leading icon tile's tone, one the board look draws.
47848
+ *
47849
+ * @return {string} `primary`, `teal` or `neutral`.
47850
+ * @spec openspec/changes/board-row-icon-tile/specs/data-table/spec.md#requirement-a-board-tables-leading-icon-sits-on-a-tile
47851
+ */
47852
+ iconTone() {
47853
+ return ['primary', 'teal', 'neutral'].includes(this.rowIconTone) ? this.rowIconTone : 'primary'
47854
+ },
47855
+
47795
47856
  /**
47796
47857
  * Whether the table is drawn as the board look's white card.
47797
47858
  *
@@ -49407,7 +49468,7 @@ const _hoisted_10$3j = {
49407
49468
  scope: "col"
49408
49469
  };
49409
49470
  const _hoisted_11$2Z = { class: "hidden-visually" };
49410
- const _hoisted_12$2F = {
49471
+ const _hoisted_12$2G = {
49411
49472
  key: 2,
49412
49473
  scope: "col"
49413
49474
  };
@@ -49435,15 +49496,15 @@ const _hoisted_21$18 = {
49435
49496
  class: "cn-table-header__filter-dot",
49436
49497
  "data-testid": "cn-table-header-filter-dot"
49437
49498
  };
49438
- const _hoisted_22$16 = {
49499
+ const _hoisted_22$17 = {
49439
49500
  key: 2,
49440
49501
  class: "cn-table-col--actions"
49441
49502
  };
49442
- const _hoisted_23$X = {
49503
+ const _hoisted_23$Y = {
49443
49504
  key: 0,
49444
49505
  class: "hidden-visually"
49445
49506
  };
49446
- const _hoisted_24$S = {
49507
+ const _hoisted_24$T = {
49447
49508
  key: 0,
49448
49509
  class: "cn-table-empty",
49449
49510
  "data-testid": "cn-object-list-empty"
@@ -49463,7 +49524,7 @@ const _hoisted_29$s = {
49463
49524
  };
49464
49525
  const _hoisted_30$r = ["title", "data-testid"];
49465
49526
  const _hoisted_31$p = { class: "hidden-visually" };
49466
- const _hoisted_32$o = {
49527
+ const _hoisted_32$p = {
49467
49528
  key: 4,
49468
49529
  class: "cn-table-cell__overline",
49469
49530
  "data-testid": "cn-cell-overline"
@@ -49603,7 +49664,7 @@ function render$81(_ctx, _cache, $props, $setup, $data, $options) {
49603
49664
  ]))
49604
49665
  }), 128 /* KEYED_FRAGMENT */)),
49605
49666
  (_ctx.$slots['row-actions'])
49606
- ? (vue$1.openBlock(), vue$1.createElementBlock("th", _hoisted_12$2F, [
49667
+ ? (vue$1.openBlock(), vue$1.createElementBlock("th", _hoisted_12$2G, [
49607
49668
  vue$1.createElementVNode("span", _hoisted_13$2o, vue$1.toDisplayString($options.actionsColumnLabel), 1 /* TEXT */)
49608
49669
  ]))
49609
49670
  : vue$1.createCommentVNode("v-if", true)
@@ -49704,9 +49765,9 @@ function render$81(_ctx, _cache, $props, $setup, $data, $options) {
49704
49765
  ], 46 /* CLASS, STYLE, PROPS, NEED_HYDRATION */, _hoisted_15$21))
49705
49766
  }), 128 /* KEYED_FRAGMENT */)),
49706
49767
  (_ctx.$slots['row-actions'])
49707
- ? (vue$1.openBlock(), vue$1.createElementBlock("th", _hoisted_22$16, [
49768
+ ? (vue$1.openBlock(), vue$1.createElementBlock("th", _hoisted_22$17, [
49708
49769
  ($options.isBoardLook)
49709
- ? (vue$1.openBlock(), vue$1.createElementBlock("span", _hoisted_23$X, vue$1.toDisplayString($options.actionsColumnLabel), 1 /* TEXT */))
49770
+ ? (vue$1.openBlock(), vue$1.createElementBlock("span", _hoisted_23$Y, vue$1.toDisplayString($options.actionsColumnLabel), 1 /* TEXT */))
49710
49771
  : vue$1.createCommentVNode("v-if", true),
49711
49772
  vue$1.renderSlot(_ctx.$slots, "actions-header")
49712
49773
  ]))
@@ -49715,7 +49776,7 @@ function render$81(_ctx, _cache, $props, $setup, $data, $options) {
49715
49776
  ])),
49716
49777
  vue$1.createElementVNode("tbody", null, [
49717
49778
  ($options.effectiveRows.length === 0)
49718
- ? (vue$1.openBlock(), vue$1.createElementBlock("tr", _hoisted_24$S, [
49779
+ ? (vue$1.openBlock(), vue$1.createElementBlock("tr", _hoisted_24$T, [
49719
49780
  vue$1.createElementVNode("td", { colspan: $options.totalColumns }, [
49720
49781
  vue$1.renderSlot(_ctx.$slots, "empty", {}, () => [
49721
49782
  ($options.lensReasonText)
@@ -49770,7 +49831,7 @@ function render$81(_ctx, _cache, $props, $setup, $data, $options) {
49770
49831
  ($props.rowIcon)
49771
49832
  ? (vue$1.openBlock(), vue$1.createElementBlock("td", {
49772
49833
  key: 1,
49773
- class: vue$1.normalizeClass(["cn-table-col--icon", $options.pinClass($props.selectable ? 1 : 0)]),
49834
+ class: vue$1.normalizeClass(["cn-table-col--icon", [$options.pinClass($props.selectable ? 1 : 0), 'cn-table-col--icon-' + $options.iconTone]]),
49774
49835
  style: vue$1.normalizeStyle($options.pinStyle($props.selectable ? 1 : 0))
49775
49836
  }, [
49776
49837
  vue$1.createVNode(_component_CnIcon, {
@@ -49827,7 +49888,7 @@ function render$81(_ctx, _cache, $props, $setup, $data, $options) {
49827
49888
  ]))
49828
49889
  : vue$1.createCommentVNode("v-if", true),
49829
49890
  ($options.overlineValue(row, col))
49830
- ? (vue$1.openBlock(), vue$1.createElementBlock("span", _hoisted_32$o, vue$1.toDisplayString($options.overlineValue(row, col)), 1 /* TEXT */))
49891
+ ? (vue$1.openBlock(), vue$1.createElementBlock("span", _hoisted_32$p, vue$1.toDisplayString($options.overlineValue(row, col)), 1 /* TEXT */))
49831
49892
  : vue$1.createCommentVNode("v-if", true),
49832
49893
  vue$1.renderSlot(_ctx.$slots, 'column-' + col.key, {
49833
49894
  row: row,
@@ -50518,7 +50579,7 @@ const _hoisted_11$2Y = {
50518
50579
  class: "cn-child-records-field__more",
50519
50580
  "data-testid": "cn-child-records-more"
50520
50581
  };
50521
- const _hoisted_12$2E = ["href"];
50582
+ const _hoisted_12$2F = ["href"];
50522
50583
  const _hoisted_13$2n = {
50523
50584
  key: 3,
50524
50585
  class: "cn-child-records-field__error",
@@ -50633,7 +50694,7 @@ function render$7$(_ctx, _cache, $props, $setup, $data, $options) {
50633
50694
  ? (vue$1.openBlock(), vue$1.createElementBlock("a", {
50634
50695
  key: 0,
50635
50696
  href: $options.listUrl
50636
- }, vue$1.toDisplayString($options.moreLabel), 9 /* TEXT, PROPS */, _hoisted_12$2E))
50697
+ }, vue$1.toDisplayString($options.moreLabel), 9 /* TEXT, PROPS */, _hoisted_12$2F))
50637
50698
  : (vue$1.openBlock(), vue$1.createElementBlock(vue$1.Fragment, { key: 1 }, [
50638
50699
  vue$1.createTextVNode(vue$1.toDisplayString($options.moreLabel), 1 /* TEXT */)
50639
50700
  ], 64 /* STABLE_FRAGMENT */))
@@ -85528,7 +85589,7 @@ const _hoisted_8$3$ = ["title", "aria-label"];
85528
85589
  const _hoisted_9$3G = ["aria-label"];
85529
85590
  const _hoisted_10$3g = ["id", "aria-selected", "aria-controls", "tabindex", "onClick", "onKeydown"];
85530
85591
  const _hoisted_11$2W = ["id", "role", "aria-labelledby"];
85531
- const _hoisted_12$2D = ["placeholder", "aria-label"];
85592
+ const _hoisted_12$2E = ["placeholder", "aria-label"];
85532
85593
  const _hoisted_13$2m = {
85533
85594
  key: 0,
85534
85595
  class: "cn-icon-browser-panel__grid"
@@ -85550,13 +85611,13 @@ const _hoisted_21$17 = {
85550
85611
  key: 0,
85551
85612
  class: "cn-icon-browser-panel__hint"
85552
85613
  };
85553
- const _hoisted_22$15 = {
85614
+ const _hoisted_22$16 = {
85554
85615
  key: 1,
85555
85616
  class: "cn-icon-browser-panel__error",
85556
85617
  role: "alert"
85557
85618
  };
85558
- const _hoisted_23$W = ["placeholder", "aria-label"];
85559
- const _hoisted_24$R = {
85619
+ const _hoisted_23$X = ["placeholder", "aria-label"];
85620
+ const _hoisted_24$S = {
85560
85621
  key: 3,
85561
85622
  class: "cn-icon-browser-panel__grid"
85562
85623
  };
@@ -85576,7 +85637,7 @@ const _hoisted_31$o = {
85576
85637
  key: 1,
85577
85638
  class: "cn-icon-browser-panel__grid"
85578
85639
  };
85579
- const _hoisted_32$n = ["title", "aria-label", "onClick"];
85640
+ const _hoisted_32$o = ["title", "aria-label", "onClick"];
85580
85641
  const _hoisted_33$m = ["src", "alt"];
85581
85642
  const _hoisted_34$m = {
85582
85643
  key: 0,
@@ -85677,7 +85738,7 @@ function render$7S(_ctx, _cache, $props, $setup, $data, $options) {
85677
85738
  class: "cn-icon-browser-panel__search",
85678
85739
  placeholder: $options.t('nextcloud-vue', 'Search icons…'),
85679
85740
  "aria-label": $options.t('nextcloud-vue', 'Search icons')
85680
- }, null, 8 /* PROPS */, _hoisted_12$2D), [
85741
+ }, null, 8 /* PROPS */, _hoisted_12$2E), [
85681
85742
  [vue$1.vModelText, $data.query]
85682
85743
  ]),
85683
85744
  ($options.visibleIcons.length > 0)
@@ -85741,7 +85802,7 @@ function render$7S(_ctx, _cache, $props, $setup, $data, $options) {
85741
85802
  ($data.groupLoading[group.key])
85742
85803
  ? (vue$1.openBlock(), vue$1.createElementBlock("p", _hoisted_21$17, vue$1.toDisplayString($options.t('nextcloud-vue', 'Loading icon set…')), 1 /* TEXT */))
85743
85804
  : ($data.groupError[group.key])
85744
- ? (vue$1.openBlock(), vue$1.createElementBlock("p", _hoisted_22$15, vue$1.toDisplayString($data.groupError[group.key]), 1 /* TEXT */))
85805
+ ? (vue$1.openBlock(), vue$1.createElementBlock("p", _hoisted_22$16, vue$1.toDisplayString($data.groupError[group.key]), 1 /* TEXT */))
85745
85806
  : vue$1.createCommentVNode("v-if", true),
85746
85807
  (group.icons.length > $props.maxResults)
85747
85808
  ? vue$1.withDirectives((vue$1.openBlock(), vue$1.createElementBlock("input", {
@@ -85751,12 +85812,12 @@ function render$7S(_ctx, _cache, $props, $setup, $data, $options) {
85751
85812
  class: "cn-icon-browser-panel__search",
85752
85813
  placeholder: $options.t('nextcloud-vue', 'Search icons…'),
85753
85814
  "aria-label": $options.t('nextcloud-vue', 'Search icons')
85754
- }, null, 8 /* PROPS */, _hoisted_23$W)), [
85815
+ }, null, 8 /* PROPS */, _hoisted_23$X)), [
85755
85816
  [vue$1.vModelText, $data.customQuery]
85756
85817
  ])
85757
85818
  : vue$1.createCommentVNode("v-if", true),
85758
85819
  ($options.customVisibleIcons.length > 0)
85759
- ? (vue$1.openBlock(), vue$1.createElementBlock("div", _hoisted_24$R, [
85820
+ ? (vue$1.openBlock(), vue$1.createElementBlock("div", _hoisted_24$S, [
85760
85821
  (vue$1.openBlock(true), vue$1.createElementBlock(vue$1.Fragment, null, vue$1.renderList($options.customVisibleIcons, (icon) => {
85761
85822
  return (vue$1.openBlock(), vue$1.createElementBlock("button", {
85762
85823
  key: icon.id || icon.url,
@@ -85827,7 +85888,7 @@ function render$7S(_ctx, _cache, $props, $setup, $data, $options) {
85827
85888
  ($props.showLabels)
85828
85889
  ? (vue$1.openBlock(), vue$1.createElementBlock("span", _hoisted_34$m, vue$1.toDisplayString(icon.label), 1 /* TEXT */))
85829
85890
  : vue$1.createCommentVNode("v-if", true)
85830
- ], 10 /* CLASS, PROPS */, _hoisted_32$n))
85891
+ ], 10 /* CLASS, PROPS */, _hoisted_32$o))
85831
85892
  }), 128 /* KEYED_FRAGMENT */))
85832
85893
  ]))
85833
85894
  : vue$1.createCommentVNode("v-if", true),
@@ -88435,7 +88496,9 @@ const SEARCH_DELAY$3 = 250;
88435
88496
  * Organisatie · KvK …"). Built on CnSearchSelect.
88436
88497
  *
88437
88498
  * `sources`: each `{ id, register, schema, label?, title?, secondary?,
88438
- * limit?, icon? }` searches OpenRegister with `_search`; `title` and
88499
+ * limit?, icon?, lookup? }` searches OpenRegister with `_search`; `lookup`
88500
+ * (`{ url, when }`) sends a term matching `when` to the app's exact lookup
88501
+ * instead (a POST of `{ term }` answering `{ results }`); `title` and
88439
88502
  * `secondary` are templates filled from the row (default `{name}` / none),
88440
88503
  * `label` names the kind ("Resident") and starts the second line; `label`
88441
88504
  * and `secondary` go through the host translate, so a manifest can write
@@ -88667,6 +88730,10 @@ var script$7Q = {
88667
88730
  const { data } = await axios$1.post(router.generateUrl('/contactsmenu/contacts'), { filter: term });
88668
88731
  return (data && Array.isArray(data.contacts) ? data.contacts : []).map((c) => this.contactOptionOf(source, c))
88669
88732
  }
88733
+ if (this.isExactLookup(source, term) === true) {
88734
+ const { data } = await axios$1.post(router.generateUrl(source.lookup.url), { term });
88735
+ return (data && Array.isArray(data.results) ? data.results : []).map((row) => this.optionOf(source, row))
88736
+ }
88670
88737
  if (!source.register || !source.schema) {
88671
88738
  return []
88672
88739
  }
@@ -88694,6 +88761,30 @@ var script$7Q = {
88694
88761
  this.searching = false;
88695
88762
  },
88696
88763
 
88764
+ /**
88765
+ * Whether a typed term goes to the source's exact lookup instead of the
88766
+ * free-text search: `source.lookup` is `{ url, when }`, `when` a regular
88767
+ * expression the whole term must match ("^[0-9]{9}$" for a BSN). The
88768
+ * lookup is a POST, so the term never sits in a URL or a server log line,
88769
+ * and the app behind it may check and record who looked whom up.
88770
+ *
88771
+ * @param {object} source The source.
88772
+ * @param {string} term The typed term.
88773
+ * @return {boolean}
88774
+ * @spec openspec/changes/party-picker-exact-lookup/specs/party-picker/spec.md#requirement-a-party-source-can-look-a-term-up-exactly
88775
+ */
88776
+ isExactLookup(source, term) {
88777
+ const lookup = source && source.lookup;
88778
+ if (!lookup || typeof lookup.url !== 'string' || lookup.url === '' || typeof lookup.when !== 'string') {
88779
+ return false
88780
+ }
88781
+ try {
88782
+ return new RegExp(lookup.when).test(term)
88783
+ } catch {
88784
+ return false
88785
+ }
88786
+ },
88787
+
88697
88788
  /**
88698
88789
  * Name a value the list does not hold: the first OpenRegister source
88699
88790
  * that has an object with that id.
@@ -88775,7 +88866,7 @@ function render$7P(_ctx, _cache, $props, $setup, $data, $options) {
88775
88866
  }
88776
88867
 
88777
88868
  script$7Q.render = render$7P;
88778
- script$7Q.__scopeId = "data-v-44764194";
88869
+ script$7Q.__scopeId = "data-v-1b4d732c";
88779
88870
  const __sfc_main$7K = script$7Q;
88780
88871
 
88781
88872
  const BASE = '/apps/integriq/api/property-sources';
@@ -95694,7 +95785,7 @@ const _hoisted_10$3f = {
95694
95785
  class: "cn-activity-card__headline-recent"
95695
95786
  };
95696
95787
  const _hoisted_11$2V = { class: "cn-activity-card__headline-actor" };
95697
- const _hoisted_12$2C = { class: "cn-activity-card__headline-subject" };
95788
+ const _hoisted_12$2D = { class: "cn-activity-card__headline-subject" };
95698
95789
  const _hoisted_13$2l = { class: "cn-activity-card__headline-time" };
95699
95790
  const _hoisted_14$2c = {
95700
95791
  key: 0,
@@ -95713,7 +95804,7 @@ const _hoisted_18$1n = { class: "cn-activity-card__day-count" };
95713
95804
  const _hoisted_19$1h = { class: "cn-activity-card__list" };
95714
95805
  const _hoisted_20$18 = { class: "cn-activity-card__row-main" };
95715
95806
  const _hoisted_21$16 = { class: "cn-activity-card__row-subject" };
95716
- const _hoisted_22$14 = { class: "cn-activity-card__row-meta" };
95807
+ const _hoisted_22$15 = { class: "cn-activity-card__row-meta" };
95717
95808
 
95718
95809
  function render$7I(_ctx, _cache, $props, $setup, $data, $options) {
95719
95810
  const _component_NcLoadingIcon = vue$1.resolveComponent("NcLoadingIcon");
@@ -95761,7 +95852,7 @@ function render$7I(_ctx, _cache, $props, $setup, $data, $options) {
95761
95852
  (vue$1.openBlock(), vue$1.createBlock(vue$1.resolveDynamicComponent($options.iconFor($options.mostRecent)), { size: 14 })),
95762
95853
  vue$1.createElementVNode("span", _hoisted_11$2V, vue$1.toDisplayString($options.actorFor($options.mostRecent)), 1 /* TEXT */),
95763
95854
  _cache[1] || (_cache[1] = vue$1.createElementVNode("span", { class: "cn-activity-card__chip-sep" }, "·", -1 /* CACHED */)),
95764
- vue$1.createElementVNode("span", _hoisted_12$2C, vue$1.toDisplayString($options.subjectFor($options.mostRecent)), 1 /* TEXT */),
95855
+ vue$1.createElementVNode("span", _hoisted_12$2D, vue$1.toDisplayString($options.subjectFor($options.mostRecent)), 1 /* TEXT */),
95765
95856
  _cache[2] || (_cache[2] = vue$1.createElementVNode("span", { class: "cn-activity-card__chip-sep" }, "·", -1 /* CACHED */)),
95766
95857
  vue$1.createElementVNode("span", _hoisted_13$2l, vue$1.toDisplayString($options.relativeTime($options.mostRecent)), 1 /* TEXT */)
95767
95858
  ]))
@@ -95793,7 +95884,7 @@ function render$7I(_ctx, _cache, $props, $setup, $data, $options) {
95793
95884
  (vue$1.openBlock(), vue$1.createBlock(vue$1.resolveDynamicComponent($options.iconFor(entry)), { size: 14 })),
95794
95885
  vue$1.createElementVNode("div", _hoisted_20$18, [
95795
95886
  vue$1.createElementVNode("span", _hoisted_21$16, vue$1.toDisplayString($options.subjectFor(entry)), 1 /* TEXT */),
95796
- vue$1.createElementVNode("span", _hoisted_22$14, vue$1.toDisplayString($options.actorFor(entry)) + " · " + vue$1.toDisplayString($options.relativeTime(entry)), 1 /* TEXT */),
95887
+ vue$1.createElementVNode("span", _hoisted_22$15, vue$1.toDisplayString($options.actorFor(entry)) + " · " + vue$1.toDisplayString($options.relativeTime(entry)), 1 /* TEXT */),
95797
95888
  ($props.showVisibility)
95798
95889
  ? (vue$1.openBlock(), vue$1.createBlock(_component_CnVisibilityChip, {
95799
95890
  key: 0,
@@ -96681,7 +96772,7 @@ const _hoisted_8$3Y = ["aria-label"];
96681
96772
  const _hoisted_9$3E = ["aria-pressed", "data-testid", "onClick"];
96682
96773
  const _hoisted_10$3e = ["data-testid"];
96683
96774
  const _hoisted_11$2U = { class: "cn-activity-tab__filter-row" };
96684
- const _hoisted_12$2B = {
96775
+ const _hoisted_12$2C = {
96685
96776
  key: 0,
96686
96777
  class: "cn-activity-tab__filter"
96687
96778
  };
@@ -96702,12 +96793,12 @@ const _hoisted_21$15 = {
96702
96793
  class: "cn-activity-tab__visibility-fixed",
96703
96794
  "data-testid": "cn-activity-visibility-fixed"
96704
96795
  };
96705
- const _hoisted_22$13 = {
96796
+ const _hoisted_22$14 = {
96706
96797
  key: 1,
96707
96798
  class: "cn-activity-tab__filter"
96708
96799
  };
96709
- const _hoisted_23$V = { class: "cn-activity-tab__filter-label" };
96710
- const _hoisted_24$Q = { value: "" };
96800
+ const _hoisted_23$W = { class: "cn-activity-tab__filter-label" };
96801
+ const _hoisted_24$R = { value: "" };
96711
96802
  const _hoisted_25$J = { value: "internal" };
96712
96803
  const _hoisted_26$D = { value: "public" };
96713
96804
  const _hoisted_27$u = {
@@ -96721,7 +96812,7 @@ const _hoisted_31$n = {
96721
96812
  key: 3,
96722
96813
  class: "cn-activity-tab__dates"
96723
96814
  };
96724
- const _hoisted_32$m = { class: "cn-activity-tab__filter" };
96815
+ const _hoisted_32$n = { class: "cn-activity-tab__filter" };
96725
96816
  const _hoisted_33$l = { class: "cn-activity-tab__filter-label" };
96726
96817
  const _hoisted_34$l = ["value"];
96727
96818
  const _hoisted_35$j = { class: "cn-activity-tab__filter" };
@@ -96860,7 +96951,7 @@ function render$7H(_ctx, _cache, $props, $setup, $data, $options) {
96860
96951
  : vue$1.createCommentVNode("v-if", true),
96861
96952
  vue$1.createElementVNode("div", _hoisted_11$2U, [
96862
96953
  ($data.legacy)
96863
- ? (vue$1.openBlock(), vue$1.createElementBlock("label", _hoisted_12$2B, [
96954
+ ? (vue$1.openBlock(), vue$1.createElementBlock("label", _hoisted_12$2C, [
96864
96955
  vue$1.createElementVNode("span", _hoisted_13$2k, vue$1.toDisplayString($data.typeLabel), 1 /* TEXT */),
96865
96956
  vue$1.withDirectives(vue$1.createElementVNode("select", {
96866
96957
  "onUpdate:modelValue": _cache[1] || (_cache[1] = $event => (($data.selectedType) = $event)),
@@ -96905,15 +96996,15 @@ function render$7H(_ctx, _cache, $props, $setup, $data, $options) {
96905
96996
  vue$1.createVNode(_component_CnVisibilityChip, { visibility: "public" }),
96906
96997
  vue$1.createTextVNode(" " + vue$1.toDisplayString($data.publicOnlyLabel), 1 /* TEXT */)
96907
96998
  ]))
96908
- : (vue$1.openBlock(), vue$1.createElementBlock("label", _hoisted_22$13, [
96909
- vue$1.createElementVNode("span", _hoisted_23$V, vue$1.toDisplayString($data.visibilityLabel), 1 /* TEXT */),
96999
+ : (vue$1.openBlock(), vue$1.createElementBlock("label", _hoisted_22$14, [
97000
+ vue$1.createElementVNode("span", _hoisted_23$W, vue$1.toDisplayString($data.visibilityLabel), 1 /* TEXT */),
96910
97001
  vue$1.withDirectives(vue$1.createElementVNode("select", {
96911
97002
  "onUpdate:modelValue": _cache[5] || (_cache[5] = $event => (($data.selectedVisibility) = $event)),
96912
97003
  class: "cn-activity-tab__select",
96913
97004
  "data-testid": "cn-activity-visibility-select",
96914
97005
  onChange: _cache[6] || (_cache[6] = (...args) => ($options.resetAndFetch && $options.resetAndFetch(...args)))
96915
97006
  }, [
96916
- vue$1.createElementVNode("option", _hoisted_24$Q, vue$1.toDisplayString($data.allVisibilityLabel), 1 /* TEXT */),
97007
+ vue$1.createElementVNode("option", _hoisted_24$R, vue$1.toDisplayString($data.allVisibilityLabel), 1 /* TEXT */),
96917
97008
  vue$1.createElementVNode("option", _hoisted_25$J, vue$1.toDisplayString($data.internalLabel), 1 /* TEXT */),
96918
97009
  vue$1.createElementVNode("option", _hoisted_26$D, vue$1.toDisplayString($data.publicLabel), 1 /* TEXT */)
96919
97010
  ], 544 /* NEED_HYDRATION, NEED_PATCH */), [
@@ -96949,7 +97040,7 @@ function render$7H(_ctx, _cache, $props, $setup, $data, $options) {
96949
97040
  ], 8 /* PROPS */, _hoisted_29$q),
96950
97041
  (!$data.legacy)
96951
97042
  ? (vue$1.openBlock(), vue$1.createElementBlock("div", _hoisted_31$n, [
96952
- vue$1.createElementVNode("label", _hoisted_32$m, [
97043
+ vue$1.createElementVNode("label", _hoisted_32$n, [
96953
97044
  vue$1.createElementVNode("span", _hoisted_33$l, vue$1.toDisplayString($data.fromLabel), 1 /* TEXT */),
96954
97045
  vue$1.createElementVNode("input", {
96955
97046
  type: "date",
@@ -97482,7 +97573,7 @@ const _hoisted_10$3d = {
97482
97573
  class: "cn-analytics-card__view-all"
97483
97574
  };
97484
97575
  const _hoisted_11$2T = ["href"];
97485
- const _hoisted_12$2A = {
97576
+ const _hoisted_12$2B = {
97486
97577
  key: 0,
97487
97578
  class: "cn-analytics-card__empty"
97488
97579
  };
@@ -97569,7 +97660,7 @@ function render$7G(_ctx, _cache, $props, $setup, $data, $options) {
97569
97660
  ], 64 /* STABLE_FRAGMENT */))
97570
97661
  : (vue$1.openBlock(), vue$1.createElementBlock(vue$1.Fragment, { key: 3 }, [
97571
97662
  ($data.degraded)
97572
- ? (vue$1.openBlock(), vue$1.createElementBlock("div", _hoisted_12$2A, vue$1.toDisplayString($data.degraded), 1 /* TEXT */))
97663
+ ? (vue$1.openBlock(), vue$1.createElementBlock("div", _hoisted_12$2B, vue$1.toDisplayString($data.degraded), 1 /* TEXT */))
97573
97664
  : ($data.reports.length === 0)
97574
97665
  ? (vue$1.openBlock(), vue$1.createElementBlock("div", _hoisted_13$2j, vue$1.toDisplayString($props.emptyLabel), 1 /* TEXT */))
97575
97666
  : (vue$1.openBlock(), vue$1.createElementBlock("ul", _hoisted_14$2a, [
@@ -98751,6 +98842,12 @@ var script$7D = {
98751
98842
 
98752
98843
  /** Maximum rows to render. */
98753
98844
  maxDisplay: { type: Number, default: 5 },
98845
+ /**
98846
+ * `stacked` (DqTaak "Historie"): the action, then one muted line under
98847
+ * it with the moment ("6 okt 09:05") and who, when the action does not
98848
+ * already name them. Default: the moment beside the action, who under it.
98849
+ */
98850
+ layout: { type: String, default: '' },
98754
98851
  /**
98755
98852
  * Actions the card leaves out (case-insensitive), such as `['read']`
98756
98853
  * for a history of what changed. It then reads more entries than it
@@ -99037,7 +99134,27 @@ var script$7D = {
99037
99134
  * @return {string} Who did it, by name where the entry carries one.
99038
99135
  */
99039
99136
  actorName(entry) {
99040
- return entry.actorDisplayName || entry.actor || entry.userId || entry.user || ''
99137
+ if (entry.actorDisplayName) {
99138
+ return entry.actorDisplayName
99139
+ }
99140
+ const id = entry.actor || entry.userId || entry.user || '';
99141
+ // A person's user id reads as their display name once it is known.
99142
+ return (id && (!entry.performerType || entry.performerType === 'user') && userDisplayName(String(id))) || id
99143
+ },
99144
+
99145
+ /**
99146
+ * The muted line of a stacked row: the moment in the board's short
99147
+ * form ("6 okt 09:05") and who, unless the action names them already.
99148
+ *
99149
+ * @param {object} entry The entry.
99150
+ * @return {string} The line.
99151
+ * @spec openspec/changes/audit-card-stacked-rows/specs/audit-trail/spec.md#requirement-an-audit-row-can-put-its-moment-under-the-action
99152
+ */
99153
+ stackedLine(entry) {
99154
+ const raw = entry.creationDateTime || entry.created || entry.timestamp;
99155
+ const date = raw ? new Date(raw) : null;
99156
+ const when = date && !Number.isNaN(date.getTime()) ? `${formatBoardDate(date)} ${formatTimeOfDay(date)}` : '';
99157
+ return [when, this.formatActor(entry)].filter((part) => part !== '').join(' · ')
99041
99158
  },
99042
99159
 
99043
99160
  /**
@@ -99089,19 +99206,30 @@ const _hoisted_3$6o = {
99089
99206
  };
99090
99207
  const _hoisted_4$5N = { class: "cn-audit-card__row-head" };
99091
99208
  const _hoisted_5$56 = { class: "cn-audit-card__action" };
99092
- const _hoisted_6$4K = { class: "cn-audit-card__when" };
99209
+ const _hoisted_6$4K = {
99210
+ key: 0,
99211
+ class: "cn-audit-card__when"
99212
+ };
99093
99213
  const _hoisted_7$4j = { class: "cn-audit-card__row-body" };
99094
- const _hoisted_8$3U = { class: "cn-audit-card__actor" };
99095
- const _hoisted_9$3A = {
99214
+ const _hoisted_8$3U = {
99096
99215
  key: 0,
99216
+ class: "cn-audit-card__when",
99217
+ "data-testid": "cn-audit-card-when-below"
99218
+ };
99219
+ const _hoisted_9$3A = {
99220
+ key: 1,
99221
+ class: "cn-audit-card__actor"
99222
+ };
99223
+ const _hoisted_10$3b = {
99224
+ key: 2,
99097
99225
  class: "cn-audit-card__refused",
99098
99226
  "data-testid": "cn-audit-card-refused"
99099
99227
  };
99100
- const _hoisted_10$3b = {
99228
+ const _hoisted_11$2R = {
99101
99229
  key: 0,
99102
99230
  class: "cn-audit-card__reason"
99103
99231
  };
99104
- const _hoisted_11$2R = {
99232
+ const _hoisted_12$2A = {
99105
99233
  key: 4,
99106
99234
  class: "cn-audit-card__footnote",
99107
99235
  "data-testid": "cn-audit-trail-widget-footnote"
@@ -99128,26 +99256,30 @@ function render$7C(_ctx, _cache, $props, $setup, $data, $options) {
99128
99256
  (vue$1.openBlock(true), vue$1.createElementBlock(vue$1.Fragment, null, vue$1.renderList($options.displayedEntries, (entry) => {
99129
99257
  return (vue$1.openBlock(), vue$1.createElementBlock("li", {
99130
99258
  key: entry.id,
99131
- class: "cn-audit-card__row"
99259
+ class: vue$1.normalizeClass(["cn-audit-card__row", { 'cn-audit-card__row--stacked': $props.layout === 'stacked' }])
99132
99260
  }, [
99133
99261
  vue$1.createElementVNode("div", _hoisted_4$5N, [
99134
99262
  vue$1.createElementVNode("strong", _hoisted_5$56, vue$1.toDisplayString($options.formatAction(entry)), 1 /* TEXT */),
99135
- vue$1.createElementVNode("span", _hoisted_6$4K, vue$1.toDisplayString($options.formatWhen(entry)), 1 /* TEXT */)
99263
+ ($props.layout !== 'stacked')
99264
+ ? (vue$1.openBlock(), vue$1.createElementBlock("span", _hoisted_6$4K, vue$1.toDisplayString($options.formatWhen(entry)), 1 /* TEXT */))
99265
+ : vue$1.createCommentVNode("v-if", true)
99136
99266
  ]),
99137
99267
  vue$1.createElementVNode("div", _hoisted_7$4j, [
99138
- vue$1.createElementVNode("span", _hoisted_8$3U, vue$1.toDisplayString($options.formatActor(entry)), 1 /* TEXT */),
99268
+ ($props.layout === 'stacked')
99269
+ ? (vue$1.openBlock(), vue$1.createElementBlock("span", _hoisted_8$3U, vue$1.toDisplayString($options.stackedLine(entry)), 1 /* TEXT */))
99270
+ : (vue$1.openBlock(), vue$1.createElementBlock("span", _hoisted_9$3A, vue$1.toDisplayString($options.formatActor(entry)), 1 /* TEXT */)),
99139
99271
  (entry.authorized === false)
99140
- ? (vue$1.openBlock(), vue$1.createElementBlock("span", _hoisted_9$3A, vue$1.toDisplayString($props.refusedLabel), 1 /* TEXT */))
99272
+ ? (vue$1.openBlock(), vue$1.createElementBlock("span", _hoisted_10$3b, vue$1.toDisplayString($props.refusedLabel), 1 /* TEXT */))
99141
99273
  : vue$1.createCommentVNode("v-if", true)
99142
99274
  ]),
99143
99275
  (entry.reason)
99144
- ? (vue$1.openBlock(), vue$1.createElementBlock("p", _hoisted_10$3b, vue$1.toDisplayString(entry.reason), 1 /* TEXT */))
99276
+ ? (vue$1.openBlock(), vue$1.createElementBlock("p", _hoisted_11$2R, vue$1.toDisplayString(entry.reason), 1 /* TEXT */))
99145
99277
  : vue$1.createCommentVNode("v-if", true)
99146
- ]))
99278
+ ], 2 /* CLASS */))
99147
99279
  }), 128 /* KEYED_FRAGMENT */))
99148
99280
  ])),
99149
99281
  ($props.footnote)
99150
- ? (vue$1.openBlock(), vue$1.createElementBlock("p", _hoisted_11$2R, vue$1.toDisplayString($props.footnote), 1 /* TEXT */))
99282
+ ? (vue$1.openBlock(), vue$1.createElementBlock("p", _hoisted_12$2A, vue$1.toDisplayString($props.footnote), 1 /* TEXT */))
99151
99283
  : vue$1.createCommentVNode("v-if", true)
99152
99284
  ]),
99153
99285
  _: 2 /* DYNAMIC */
@@ -99168,7 +99300,7 @@ function render$7C(_ctx, _cache, $props, $setup, $data, $options) {
99168
99300
  }
99169
99301
 
99170
99302
  script$7D.render = render$7C;
99171
- script$7D.__scopeId = "data-v-834a0068";
99303
+ script$7D.__scopeId = "data-v-401394d1";
99172
99304
  const __sfc_main$7x = script$7D;
99173
99305
 
99174
99306
  // SPDX-FileCopyrightText: 2026 Conduction B.V.
@@ -100140,7 +100272,7 @@ const _hoisted_20$16 = {
100140
100272
  class: "cn-audit-details__values"
100141
100273
  };
100142
100274
  const _hoisted_21$14 = { class: "cn-audit-details__mono" };
100143
- const _hoisted_22$12 = {
100275
+ const _hoisted_22$13 = {
100144
100276
  key: 2,
100145
100277
  class: "cn-sidebar-tab__empty"
100146
100278
  };
@@ -100324,7 +100456,7 @@ function render$7z(_ctx, _cache, $props, $setup, $data, $options) {
100324
100456
  : vue$1.createCommentVNode("v-if", true)
100325
100457
  ]))
100326
100458
  ], 64 /* STABLE_FRAGMENT */))
100327
- : (vue$1.openBlock(), vue$1.createElementBlock("div", _hoisted_22$12, vue$1.toDisplayString($props.noAuditTrailLabel), 1 /* TEXT */)),
100459
+ : (vue$1.openBlock(), vue$1.createElementBlock("div", _hoisted_22$13, vue$1.toDisplayString($props.noAuditTrailLabel), 1 /* TEXT */)),
100328
100460
  ($data.restoreEntry)
100329
100461
  ? (vue$1.openBlock(), vue$1.createBlock(_component_CnConfirmDialog, {
100330
100462
  key: 3,
@@ -100632,12 +100764,12 @@ const _hoisted_18$1j = {
100632
100764
  const _hoisted_19$1d = { class: "cn-bookmarks-card__row-icon" };
100633
100765
  const _hoisted_20$15 = ["src", "onError"];
100634
100766
  const _hoisted_21$13 = { class: "cn-bookmarks-card__row-main" };
100635
- const _hoisted_22$11 = ["href"];
100636
- const _hoisted_23$U = {
100767
+ const _hoisted_22$12 = ["href"];
100768
+ const _hoisted_23$V = {
100637
100769
  key: 1,
100638
100770
  class: "cn-bookmarks-card__title"
100639
100771
  };
100640
- const _hoisted_24$P = {
100772
+ const _hoisted_24$Q = {
100641
100773
  key: 3,
100642
100774
  class: "cn-bookmarks-card__view-all"
100643
100775
  };
@@ -100765,14 +100897,14 @@ function render$7y(_ctx, _cache, $props, $setup, $data, $options) {
100765
100897
  target: "_blank",
100766
100898
  rel: "noopener noreferrer",
100767
100899
  class: "cn-bookmarks-card__title"
100768
- }, vue$1.toDisplayString($options.bookmarkTitle(bookmark)), 9 /* TEXT, PROPS */, _hoisted_22$11))
100769
- : (vue$1.openBlock(), vue$1.createElementBlock("span", _hoisted_23$U, vue$1.toDisplayString($options.bookmarkTitle(bookmark)), 1 /* TEXT */))
100900
+ }, vue$1.toDisplayString($options.bookmarkTitle(bookmark)), 9 /* TEXT, PROPS */, _hoisted_22$12))
100901
+ : (vue$1.openBlock(), vue$1.createElementBlock("span", _hoisted_23$V, vue$1.toDisplayString($options.bookmarkTitle(bookmark)), 1 /* TEXT */))
100770
100902
  ])
100771
100903
  ]))
100772
100904
  }), 128 /* KEYED_FRAGMENT */))
100773
100905
  ])),
100774
100906
  ($data.bookmarks.length > $data.COMPACT_LIMIT)
100775
- ? (vue$1.openBlock(), vue$1.createElementBlock("div", _hoisted_24$P, [
100907
+ ? (vue$1.openBlock(), vue$1.createElementBlock("div", _hoisted_24$Q, [
100776
100908
  vue$1.createElementVNode("a", {
100777
100909
  href: $props.bookmarksAppUrl,
100778
100910
  target: "_blank",
@@ -102728,12 +102860,12 @@ const _hoisted_21$12 = {
102728
102860
  key: 1,
102729
102861
  class: "cn-calendar-tab__group"
102730
102862
  };
102731
- const _hoisted_22$10 = { class: "cn-calendar-tab__group-title cn-calendar-tab__group-title--past" };
102732
- const _hoisted_23$T = {
102863
+ const _hoisted_22$11 = { class: "cn-calendar-tab__group-title cn-calendar-tab__group-title--past" };
102864
+ const _hoisted_23$U = {
102733
102865
  class: "cn-calendar-tab__date cn-calendar-tab__date--past",
102734
102866
  "aria-hidden": "true"
102735
102867
  };
102736
- const _hoisted_24$O = { class: "cn-calendar-tab__date-month" };
102868
+ const _hoisted_24$P = { class: "cn-calendar-tab__date-month" };
102737
102869
  const _hoisted_25$H = { class: "cn-calendar-tab__date-day" };
102738
102870
  const _hoisted_26$C = { class: "cn-calendar-tab__main" };
102739
102871
  const _hoisted_27$t = { class: "cn-calendar-tab__title-row" };
@@ -102744,7 +102876,7 @@ const _hoisted_30$o = {
102744
102876
  class: "cn-calendar-tab__location"
102745
102877
  };
102746
102878
  const _hoisted_31$m = { class: "cn-calendar-tab__location-text" };
102747
- const _hoisted_32$l = {
102879
+ const _hoisted_32$m = {
102748
102880
  key: 1,
102749
102881
  class: "cn-calendar-tab__attendees"
102750
102882
  };
@@ -102908,14 +103040,14 @@ function render$7t(_ctx, _cache, $props, $setup, $data, $options) {
102908
103040
  : vue$1.createCommentVNode("v-if", true),
102909
103041
  ($options.pastEvents.length > 0)
102910
103042
  ? (vue$1.openBlock(), vue$1.createElementBlock("div", _hoisted_21$12, [
102911
- vue$1.createElementVNode("h4", _hoisted_22$10, vue$1.toDisplayString($props.pastLabel), 1 /* TEXT */),
103043
+ vue$1.createElementVNode("h4", _hoisted_22$11, vue$1.toDisplayString($props.pastLabel), 1 /* TEXT */),
102912
103044
  (vue$1.openBlock(true), vue$1.createElementBlock(vue$1.Fragment, null, vue$1.renderList($options.pastEvents, (ev) => {
102913
103045
  return (vue$1.openBlock(), vue$1.createElementBlock("div", {
102914
103046
  key: $options.rowKey(ev),
102915
103047
  class: "cn-calendar-tab__event cn-calendar-tab__event--past"
102916
103048
  }, [
102917
- vue$1.createElementVNode("div", _hoisted_23$T, [
102918
- vue$1.createElementVNode("span", _hoisted_24$O, vue$1.toDisplayString($options.monthOf(ev)), 1 /* TEXT */),
103049
+ vue$1.createElementVNode("div", _hoisted_23$U, [
103050
+ vue$1.createElementVNode("span", _hoisted_24$P, vue$1.toDisplayString($options.monthOf(ev)), 1 /* TEXT */),
102919
103051
  vue$1.createElementVNode("span", _hoisted_25$H, vue$1.toDisplayString($options.dayOf(ev)), 1 /* TEXT */)
102920
103052
  ]),
102921
103053
  vue$1.createElementVNode("div", _hoisted_26$C, [
@@ -102947,7 +103079,7 @@ function render$7t(_ctx, _cache, $props, $setup, $data, $options) {
102947
103079
  ]))
102948
103080
  : vue$1.createCommentVNode("v-if", true),
102949
103081
  ($options.attendeeList(ev).length > 0)
102950
- ? (vue$1.openBlock(), vue$1.createElementBlock("div", _hoisted_32$l, [
103082
+ ? (vue$1.openBlock(), vue$1.createElementBlock("div", _hoisted_32$m, [
102951
103083
  (vue$1.openBlock(true), vue$1.createElementBlock(vue$1.Fragment, null, vue$1.renderList($options.visibleAttendees(ev), (att, idx) => {
102952
103084
  return (vue$1.openBlock(), vue$1.createElementBlock("span", {
102953
103085
  key: idx,
@@ -103429,12 +103561,12 @@ const _hoisted_20$13 = {
103429
103561
  "aria-hidden": true
103430
103562
  };
103431
103563
  const _hoisted_21$11 = { class: "cn-collectives-card__row-main" };
103432
- const _hoisted_22$$ = ["href"];
103433
- const _hoisted_23$S = {
103564
+ const _hoisted_22$10 = ["href"];
103565
+ const _hoisted_23$T = {
103434
103566
  key: 0,
103435
103567
  class: "cn-collectives-card__row-collective"
103436
103568
  };
103437
- const _hoisted_24$N = {
103569
+ const _hoisted_24$O = {
103438
103570
  key: 3,
103439
103571
  class: "cn-collectives-card__view-all"
103440
103572
  };
@@ -103557,16 +103689,16 @@ function render$7s(_ctx, _cache, $props, $setup, $data, $options) {
103557
103689
  target: "_blank",
103558
103690
  rel: "noopener",
103559
103691
  class: "cn-collectives-card__title"
103560
- }, vue$1.toDisplayString($options.pageTitle(page)), 9 /* TEXT, PROPS */, _hoisted_22$$),
103692
+ }, vue$1.toDisplayString($options.pageTitle(page)), 9 /* TEXT, PROPS */, _hoisted_22$10),
103561
103693
  ($options.collectiveLabel(page))
103562
- ? (vue$1.openBlock(), vue$1.createElementBlock("span", _hoisted_23$S, vue$1.toDisplayString($options.collectiveLabel(page)), 1 /* TEXT */))
103694
+ ? (vue$1.openBlock(), vue$1.createElementBlock("span", _hoisted_23$T, vue$1.toDisplayString($options.collectiveLabel(page)), 1 /* TEXT */))
103563
103695
  : vue$1.createCommentVNode("v-if", true)
103564
103696
  ])
103565
103697
  ]))
103566
103698
  }), 128 /* KEYED_FRAGMENT */))
103567
103699
  ])),
103568
103700
  ($data.pages.length > $data.COMPACT_LIMIT)
103569
- ? (vue$1.openBlock(), vue$1.createElementBlock("div", _hoisted_24$N, [
103701
+ ? (vue$1.openBlock(), vue$1.createElementBlock("div", _hoisted_24$O, [
103570
103702
  vue$1.createElementVNode("a", {
103571
103703
  href: $props.collectivesAppUrl,
103572
103704
  target: "_blank",
@@ -106144,6 +106276,8 @@ var script$7k = {
106144
106276
  name: 'CnContactsTab',
106145
106277
 
106146
106278
  components: {
106279
+ NcActionButton: vue.NcActionButton,
106280
+ NcActions: vue.NcActions,
106147
106281
  NcAvatar: vue.NcAvatar,
106148
106282
  NcButton: vue.NcButton,
106149
106283
  NcEmptyContent: vue.NcEmptyContent,
@@ -106234,6 +106368,11 @@ var script$7k = {
106234
106368
  },
106235
106369
 
106236
106370
  computed: {
106371
+ /** @return {boolean} The board look draws the rows as DqZaakBetrokkenen does. */
106372
+ isBoard() {
106373
+ return normalizeLook(this.cnLook) === 'board'
106374
+ },
106375
+
106237
106376
  /**
106238
106377
  * The two header buttons in the order and weight of the look: the
106239
106378
  * board look draws Link contact then New contact, both outlined; the
@@ -106526,6 +106665,49 @@ var script$7k = {
106526
106665
  *
106527
106666
  * @return {string} The window.
106528
106667
  */
106668
+ /**
106669
+ * A person's details on one line for the board look: e-mail, phone,
106670
+ * organisation and note, separated by middots.
106671
+ *
106672
+ * @param {object} contact The contact link.
106673
+ * @return {string}
106674
+ */
106675
+ boardMetaOf(contact) {
106676
+ return [contact?.email, contact?.phone, contact?.org, contact?.note].filter((part) => typeof part === 'string' && part !== '').join(' · ')
106677
+ },
106678
+
106679
+ /**
106680
+ * The validity window in the board's short dates: "Vanaf 3 okt",
106681
+ * "Tot 31 okt" or "3 okt – 31 okt".
106682
+ *
106683
+ * @param {object} contact The contact link.
106684
+ * @return {string}
106685
+ */
106686
+ boardPeriodOf(contact) {
106687
+ const from = formatBoardDate(contact?.validFrom || '');
106688
+ const until = formatBoardDate(contact?.validUntil || '');
106689
+ if (from === '' && until === '') {
106690
+ return ''
106691
+ }
106692
+ if (until === '') {
106693
+ return l10n.translate('nextcloud-vue', 'From {date}', { date: from })
106694
+ }
106695
+ if (from === '') {
106696
+ return l10n.translate('nextcloud-vue', 'Until {date}', { date: until })
106697
+ }
106698
+ return `${from} – ${until}`
106699
+ },
106700
+
106701
+ /**
106702
+ * The label of a person's actions menu.
106703
+ *
106704
+ * @param {object} contact The contact link.
106705
+ * @return {string}
106706
+ */
106707
+ moreActionsLabel(contact) {
106708
+ return l10n.translate('nextcloud-vue', 'More actions for {name}', { name: contact?.displayName || this.unknownLabel })
106709
+ },
106710
+
106529
106711
  periodOf(contact) {
106530
106712
  const from = contact?.validFrom || '';
106531
106713
  const until = contact?.validUntil || '';
@@ -106633,7 +106815,10 @@ const _hoisted_3$68 = {
106633
106815
  class: "cn-contacts-tab__groups"
106634
106816
  };
106635
106817
  const _hoisted_4$5z = { class: "cn-contacts-tab__group-title" };
106636
- const _hoisted_5$4V = { class: "cn-contacts-tab__group-count" };
106818
+ const _hoisted_5$4V = {
106819
+ key: 0,
106820
+ class: "cn-contacts-tab__group-count"
106821
+ };
106637
106822
  const _hoisted_6$4x = { class: "cn-contacts-tab__list" };
106638
106823
  const _hoisted_7$46 = ["onClick"];
106639
106824
  const _hoisted_8$3H = { class: "cn-contacts-tab__avatar" };
@@ -106641,32 +106826,42 @@ const _hoisted_9$3n = { class: "cn-contacts-tab__details" };
106641
106826
  const _hoisted_10$2$ = { class: "cn-contacts-tab__name-row" };
106642
106827
  const _hoisted_11$2G = { class: "cn-contacts-tab__name" };
106643
106828
  const _hoisted_12$2p = {
106829
+ key: 0,
106830
+ class: "cn-contacts-tab__meta",
106831
+ "data-testid": "cn-contacts-tab-meta"
106832
+ };
106833
+ const _hoisted_13$29 = {
106644
106834
  key: 0,
106645
106835
  class: "cn-contacts-tab__sub"
106646
106836
  };
106647
- const _hoisted_13$29 = { class: "cn-contacts-tab__sub-text" };
106648
- const _hoisted_14$22 = {
106837
+ const _hoisted_14$22 = { class: "cn-contacts-tab__sub-text" };
106838
+ const _hoisted_15$1T = {
106649
106839
  key: 1,
106650
106840
  class: "cn-contacts-tab__sub"
106651
106841
  };
106652
- const _hoisted_15$1T = { class: "cn-contacts-tab__sub-text" };
106653
- const _hoisted_16$1H = {
106842
+ const _hoisted_16$1H = { class: "cn-contacts-tab__sub-text" };
106843
+ const _hoisted_17$1u = {
106654
106844
  key: 2,
106655
106845
  class: "cn-contacts-tab__sub"
106656
106846
  };
106657
- const _hoisted_17$1u = { class: "cn-contacts-tab__sub-text" };
106658
- const _hoisted_18$1g = {
106847
+ const _hoisted_18$1g = { class: "cn-contacts-tab__sub-text" };
106848
+ const _hoisted_19$1a = {
106659
106849
  key: 3,
106660
106850
  class: "cn-contacts-tab__sub",
106661
106851
  "data-testid": "cn-contacts-tab-period"
106662
106852
  };
106663
- const _hoisted_19$1a = { class: "cn-contacts-tab__sub-text" };
106664
- const _hoisted_20$12 = {
106853
+ const _hoisted_20$12 = { class: "cn-contacts-tab__sub-text" };
106854
+ const _hoisted_21$10 = {
106665
106855
  key: 4,
106666
106856
  class: "cn-contacts-tab__sub"
106667
106857
  };
106668
- const _hoisted_21$10 = { class: "cn-contacts-tab__sub-text" };
106669
- const _hoisted_22$_ = ["aria-label", "title", "onClick"];
106858
+ const _hoisted_22$$ = { class: "cn-contacts-tab__sub-text" };
106859
+ const _hoisted_23$S = {
106860
+ key: 0,
106861
+ class: "cn-contacts-tab__period",
106862
+ "data-testid": "cn-contacts-tab-board-period"
106863
+ };
106864
+ const _hoisted_24$N = ["aria-label", "title", "onClick"];
106670
106865
 
106671
106866
  function render$7j(_ctx, _cache, $props, $setup, $data, $options) {
106672
106867
  const _component_LinkVariant = vue$1.resolveComponent("LinkVariant");
@@ -106684,6 +106879,8 @@ function render$7j(_ctx, _cache, $props, $setup, $data, $options) {
106684
106879
  const _component_OfficeBuildingOutline = vue$1.resolveComponent("OfficeBuildingOutline");
106685
106880
  const _component_CalendarRange = vue$1.resolveComponent("CalendarRange");
106686
106881
  const _component_Close = vue$1.resolveComponent("Close");
106882
+ const _component_NcActionButton = vue$1.resolveComponent("NcActionButton");
106883
+ const _component_NcActions = vue$1.resolveComponent("NcActions");
106687
106884
  const _component_CnContactPicker = vue$1.resolveComponent("CnContactPicker");
106688
106885
  const _component_CnContactCreate = vue$1.resolveComponent("CnContactCreate");
106689
106886
 
@@ -106752,7 +106949,9 @@ function render$7j(_ctx, _cache, $props, $setup, $data, $options) {
106752
106949
  }, [
106753
106950
  vue$1.createElementVNode("h3", _hoisted_4$5z, [
106754
106951
  vue$1.createTextVNode(vue$1.toDisplayString(group.label) + " ", 1 /* TEXT */),
106755
- vue$1.createElementVNode("span", _hoisted_5$4V, vue$1.toDisplayString(group.items.length), 1 /* TEXT */)
106952
+ (!$options.isBoard)
106953
+ ? (vue$1.openBlock(), vue$1.createElementBlock("span", _hoisted_5$4V, vue$1.toDisplayString(group.items.length), 1 /* TEXT */))
106954
+ : vue$1.createCommentVNode("v-if", true)
106756
106955
  ]),
106757
106956
  vue$1.createElementVNode("ul", _hoisted_6$4x, [
106758
106957
  (vue$1.openBlock(true), vue$1.createElementBlock(vue$1.Fragment, null, vue$1.renderList(group.items, (contact) => {
@@ -106763,7 +106962,7 @@ function render$7j(_ctx, _cache, $props, $setup, $data, $options) {
106763
106962
  }, [
106764
106963
  vue$1.createElementVNode("div", _hoisted_8$3H, [
106765
106964
  vue$1.createVNode(_component_NcAvatar, {
106766
- size: 40,
106965
+ size: $options.isBoard ? 32 : 40,
106767
106966
  displayName: contact.displayName || $props.unknownLabel,
106768
106967
  user: $options.avatarSeed(contact),
106769
106968
  url: contact.avatarUrl || undefined,
@@ -106771,12 +106970,12 @@ function render$7j(_ctx, _cache, $props, $setup, $data, $options) {
106771
106970
  disableMenu: true,
106772
106971
  disableTooltip: true,
106773
106972
  hideStatus: ""
106774
- }, null, 8 /* PROPS */, ["displayName", "user", "url"])
106973
+ }, null, 8 /* PROPS */, ["size", "displayName", "user", "url"])
106775
106974
  ]),
106776
106975
  vue$1.createElementVNode("div", _hoisted_9$3n, [
106777
106976
  vue$1.createElementVNode("div", _hoisted_10$2$, [
106778
106977
  vue$1.createElementVNode("span", _hoisted_11$2G, vue$1.toDisplayString(contact.displayName || $props.unknownLabel), 1 /* TEXT */),
106779
- (contact.role)
106978
+ (contact.role && !$options.isBoard)
106780
106979
  ? (vue$1.openBlock(), vue$1.createBlock(_component_CnStatusBadge, {
106781
106980
  key: 0,
106782
106981
  label: $options.roleLabel(contact),
@@ -106794,57 +106993,94 @@ function render$7j(_ctx, _cache, $props, $setup, $data, $options) {
106794
106993
  }, null, 8 /* PROPS */, ["label"]))
106795
106994
  : vue$1.createCommentVNode("v-if", true)
106796
106995
  ]),
106797
- (contact.email)
106798
- ? (vue$1.openBlock(), vue$1.createElementBlock("div", _hoisted_12$2p, [
106799
- vue$1.createVNode(_component_Email, {
106800
- size: 14,
106801
- class: "cn-contacts-tab__sub-icon"
106802
- }),
106803
- vue$1.createElementVNode("span", _hoisted_13$29, vue$1.toDisplayString(contact.email), 1 /* TEXT */)
106804
- ]))
106805
- : vue$1.createCommentVNode("v-if", true),
106806
- (contact.phone)
106807
- ? (vue$1.openBlock(), vue$1.createElementBlock("div", _hoisted_14$22, [
106808
- vue$1.createVNode(_component_Phone, {
106809
- size: 14,
106810
- class: "cn-contacts-tab__sub-icon"
106811
- }),
106812
- vue$1.createElementVNode("span", _hoisted_15$1T, vue$1.toDisplayString(contact.phone), 1 /* TEXT */)
106813
- ]))
106814
- : vue$1.createCommentVNode("v-if", true),
106815
- (contact.org)
106816
- ? (vue$1.openBlock(), vue$1.createElementBlock("div", _hoisted_16$1H, [
106817
- vue$1.createVNode(_component_OfficeBuildingOutline, {
106818
- size: 14,
106819
- class: "cn-contacts-tab__sub-icon"
106820
- }),
106821
- vue$1.createElementVNode("span", _hoisted_17$1u, vue$1.toDisplayString(contact.org), 1 /* TEXT */)
106822
- ]))
106996
+ ($options.isBoard && $options.boardMetaOf(contact))
106997
+ ? (vue$1.openBlock(), vue$1.createElementBlock("span", _hoisted_12$2p, vue$1.toDisplayString($options.boardMetaOf(contact)), 1 /* TEXT */))
106823
106998
  : vue$1.createCommentVNode("v-if", true),
106824
- ($options.periodOf(contact))
106825
- ? (vue$1.openBlock(), vue$1.createElementBlock("div", _hoisted_18$1g, [
106826
- vue$1.createVNode(_component_CalendarRange, {
106827
- size: 14,
106828
- class: "cn-contacts-tab__sub-icon"
106829
- }),
106830
- vue$1.createElementVNode("span", _hoisted_19$1a, vue$1.toDisplayString($options.periodOf(contact)), 1 /* TEXT */)
106831
- ]))
106832
- : vue$1.createCommentVNode("v-if", true),
106833
- (contact.note)
106834
- ? (vue$1.openBlock(), vue$1.createElementBlock("div", _hoisted_20$12, [
106835
- vue$1.createElementVNode("span", _hoisted_21$10, vue$1.toDisplayString(contact.note), 1 /* TEXT */)
106836
- ]))
106999
+ (!$options.isBoard)
107000
+ ? (vue$1.openBlock(), vue$1.createElementBlock(vue$1.Fragment, { key: 1 }, [
107001
+ (contact.email)
107002
+ ? (vue$1.openBlock(), vue$1.createElementBlock("div", _hoisted_13$29, [
107003
+ vue$1.createVNode(_component_Email, {
107004
+ size: 14,
107005
+ class: "cn-contacts-tab__sub-icon"
107006
+ }),
107007
+ vue$1.createElementVNode("span", _hoisted_14$22, vue$1.toDisplayString(contact.email), 1 /* TEXT */)
107008
+ ]))
107009
+ : vue$1.createCommentVNode("v-if", true),
107010
+ (contact.phone)
107011
+ ? (vue$1.openBlock(), vue$1.createElementBlock("div", _hoisted_15$1T, [
107012
+ vue$1.createVNode(_component_Phone, {
107013
+ size: 14,
107014
+ class: "cn-contacts-tab__sub-icon"
107015
+ }),
107016
+ vue$1.createElementVNode("span", _hoisted_16$1H, vue$1.toDisplayString(contact.phone), 1 /* TEXT */)
107017
+ ]))
107018
+ : vue$1.createCommentVNode("v-if", true),
107019
+ (contact.org)
107020
+ ? (vue$1.openBlock(), vue$1.createElementBlock("div", _hoisted_17$1u, [
107021
+ vue$1.createVNode(_component_OfficeBuildingOutline, {
107022
+ size: 14,
107023
+ class: "cn-contacts-tab__sub-icon"
107024
+ }),
107025
+ vue$1.createElementVNode("span", _hoisted_18$1g, vue$1.toDisplayString(contact.org), 1 /* TEXT */)
107026
+ ]))
107027
+ : vue$1.createCommentVNode("v-if", true),
107028
+ ($options.periodOf(contact))
107029
+ ? (vue$1.openBlock(), vue$1.createElementBlock("div", _hoisted_19$1a, [
107030
+ vue$1.createVNode(_component_CalendarRange, {
107031
+ size: 14,
107032
+ class: "cn-contacts-tab__sub-icon"
107033
+ }),
107034
+ vue$1.createElementVNode("span", _hoisted_20$12, vue$1.toDisplayString($options.periodOf(contact)), 1 /* TEXT */)
107035
+ ]))
107036
+ : vue$1.createCommentVNode("v-if", true),
107037
+ (contact.note)
107038
+ ? (vue$1.openBlock(), vue$1.createElementBlock("div", _hoisted_21$10, [
107039
+ vue$1.createElementVNode("span", _hoisted_22$$, vue$1.toDisplayString(contact.note), 1 /* TEXT */)
107040
+ ]))
107041
+ : vue$1.createCommentVNode("v-if", true)
107042
+ ], 64 /* STABLE_FRAGMENT */))
106837
107043
  : vue$1.createCommentVNode("v-if", true)
106838
107044
  ]),
106839
- vue$1.createElementVNode("button", {
106840
- type: "button",
106841
- class: "cn-contacts-tab__unlink",
106842
- "aria-label": $props.unlinkLabel,
106843
- title: $props.unlinkLabel,
106844
- onClick: vue$1.withModifiers($event => ($options.unlink(contact)), ["stop"])
106845
- }, [
106846
- vue$1.createVNode(_component_Close, { size: 18 })
106847
- ], 8 /* PROPS */, _hoisted_22$_)
107045
+ ($options.isBoard)
107046
+ ? (vue$1.openBlock(), vue$1.createElementBlock(vue$1.Fragment, { key: 0 }, [
107047
+ ($options.boardPeriodOf(contact))
107048
+ ? (vue$1.openBlock(), vue$1.createElementBlock("span", _hoisted_23$S, vue$1.toDisplayString($options.boardPeriodOf(contact)), 1 /* TEXT */))
107049
+ : vue$1.createCommentVNode("v-if", true),
107050
+ vue$1.createVNode(_component_NcActions, {
107051
+ class: "cn-contacts-tab__menu",
107052
+ variant: "secondary",
107053
+ "aria-label": $options.moreActionsLabel(contact),
107054
+ "data-testid": "cn-contacts-tab-menu",
107055
+ onClick: _cache[0] || (_cache[0] = vue$1.withModifiers(() => {}, ["stop"]))
107056
+ }, {
107057
+ default: vue$1.withCtx(() => [
107058
+ vue$1.createVNode(_component_NcActionButton, {
107059
+ closeAfterClick: true,
107060
+ onClick: $event => ($options.unlink(contact))
107061
+ }, {
107062
+ icon: vue$1.withCtx(() => [
107063
+ vue$1.createVNode(_component_Close, { size: 20 })
107064
+ ]),
107065
+ default: vue$1.withCtx(() => [
107066
+ vue$1.createTextVNode(" " + vue$1.toDisplayString($props.unlinkLabel), 1 /* TEXT */)
107067
+ ]),
107068
+ _: 1 /* STABLE */
107069
+ }, 8 /* PROPS */, ["onClick"])
107070
+ ]),
107071
+ _: 2 /* DYNAMIC */
107072
+ }, 1032 /* PROPS, DYNAMIC_SLOTS */, ["aria-label"])
107073
+ ], 64 /* STABLE_FRAGMENT */))
107074
+ : (vue$1.openBlock(), vue$1.createElementBlock("button", {
107075
+ key: 1,
107076
+ type: "button",
107077
+ class: "cn-contacts-tab__unlink",
107078
+ "aria-label": $props.unlinkLabel,
107079
+ title: $props.unlinkLabel,
107080
+ onClick: vue$1.withModifiers($event => ($options.unlink(contact)), ["stop"])
107081
+ }, [
107082
+ vue$1.createVNode(_component_Close, { size: 18 })
107083
+ ], 8 /* PROPS */, _hoisted_24$N))
106848
107084
  ], 8 /* PROPS */, _hoisted_7$46))
106849
107085
  }), 128 /* KEYED_FRAGMENT */))
106850
107086
  ])
@@ -106857,7 +107093,7 @@ function render$7j(_ctx, _cache, $props, $setup, $data, $options) {
106857
107093
  apiBase: $props.apiBase
106858
107094
  }, $options.pickerRoleOptions, {
106859
107095
  onLink: $options.onPickerLink,
106860
- onClose: _cache[0] || (_cache[0] = $event => ($data.showLinkDialog = false))
107096
+ onClose: _cache[1] || (_cache[1] = $event => ($data.showLinkDialog = false))
106861
107097
  }), null, 16 /* FULL_PROPS */, ["apiBase", "onLink"]))
106862
107098
  : vue$1.createCommentVNode("v-if", true),
106863
107099
  ($data.showCreateDialog)
@@ -106865,14 +107101,14 @@ function render$7j(_ctx, _cache, $props, $setup, $data, $options) {
106865
107101
  key: 5,
106866
107102
  loading: $data.createLoading,
106867
107103
  onCreate: $options.onCreateSubmit,
106868
- onClose: _cache[1] || (_cache[1] = $event => ($data.showCreateDialog = false))
107104
+ onClose: _cache[2] || (_cache[2] = $event => ($data.showCreateDialog = false))
106869
107105
  }, null, 8 /* PROPS */, ["loading", "onCreate"]))
106870
107106
  : vue$1.createCommentVNode("v-if", true)
106871
107107
  ]))
106872
107108
  }
106873
107109
 
106874
107110
  script$7k.render = render$7j;
106875
- script$7k.__scopeId = "data-v-ec6b0008";
107111
+ script$7k.__scopeId = "data-v-a0d90184";
106876
107112
  const __sfc_main$7e = script$7k;
106877
107113
 
106878
107114
  /**
@@ -108377,422 +108613,7 @@ const cospendIntegration = {
108377
108613
  defaultSize: { w: 3, h: 3 },
108378
108614
  };
108379
108615
 
108380
- const VALID_SURFACES$e = ['user-dashboard', 'app-dashboard', 'detail-page', 'single-entity'];
108381
-
108382
- /**
108383
- * CnDeckCard — bespoke surface-aware widget for the `deck` integration.
108384
- *
108385
- * Renders Deck-aware metadata across all four surfaces. See the
108386
- * file-level docblock for surface-by-surface behaviour.
108387
- */
108388
108616
  var script$7f = {
108389
- name: 'CnDeckCard',
108390
-
108391
- components: { CnDetailCard: __sfc_main$7F, NcLoadingIcon: vue.NcLoadingIcon, ViewColumnOutline },
108392
-
108393
- props: {
108394
- /** Stable integration id (forwarded from the registry — always `'deck'`). */
108395
- integrationId: { type: String, default: 'deck' },
108396
- /** OpenRegister register id (slug or uuid). */
108397
- register: { type: String, required: true },
108398
- /** OpenRegister schema id (slug or uuid). */
108399
- schema: { type: String, required: true },
108400
- /** Parent object id. */
108401
- objectId: { type: String, required: true },
108402
- /** Rendering surface (AD-19). */
108403
- surface: {
108404
- type: String,
108405
- default: 'detail-page',
108406
- validator: (s) => VALID_SURFACES$e.includes(s),
108407
- },
108408
-
108409
- /** Optional single-entity reference (card id). */
108410
- value: { type: [String, Number], default: '' },
108411
- /** Pre-translated card title. */
108412
- title: { type: String, default: () => l10n.translate('nextcloud-vue', 'Cards') },
108413
- /** Optional Material Design Icon component. */
108414
- icon: { type: Object, default: () => ViewColumnOutline },
108415
- /** Base API URL. */
108416
- apiBase: { type: String, default: '/apps/openregister/api' },
108417
- /** Whether the card body is collapsible. */
108418
- collapsible: { type: Boolean, default: true },
108419
- /** Pre-translated empty-state label. */
108420
- emptyLabel: { type: String, default: () => l10n.translate('nextcloud-vue', 'No cards linked yet') },
108421
- /** Pre-translated unavailable label. */
108422
- unavailableLabel: { type: String, default: () => l10n.translate('nextcloud-vue', 'NC Deck is currently unavailable.') },
108423
- /** URL of the NC Deck app entry. */
108424
- deckAppUrl: { type: String, default: '/index.php/apps/deck' },
108425
- },
108426
-
108427
- data() {
108428
- return {
108429
- cards: [],
108430
- entity: null,
108431
- loading: false,
108432
- degraded: '',
108433
- }
108434
- },
108435
-
108436
- computed: {
108437
- cardHeaderTitle() {
108438
- return this.title || this.integrationId
108439
- },
108440
-
108441
- cardIcon() {
108442
- return this.icon
108443
- },
108444
-
108445
- /**
108446
- * Cards grouped by stack for both the mini-kanban (detail-page)
108447
- * and the stack-distribution list (dashboard surfaces).
108448
- *
108449
- * @return {Array<{key: string, label: string, cards: Array}>}
108450
- */
108451
- columns() {
108452
- const groups = new Map();
108453
- for (const card of this.cards) {
108454
- const stackId = card.stackId ?? card.stack?.id ?? 'unstacked';
108455
- const stackLabel = card.stackTitle
108456
- ?? card.stack?.title
108457
- ?? (stackId === 'unstacked'
108458
- ? l10n.translate('nextcloud-vue', 'No stack')
108459
- : l10n.translate('nextcloud-vue', 'Stack {n}', { n: stackId }));
108460
- const key = String(stackId);
108461
- if (!groups.has(key)) {
108462
- groups.set(key, { key, label: stackLabel, cards: [] });
108463
- }
108464
- groups.get(key).cards.push(card);
108465
- }
108466
- return Array.from(groups.values())
108467
- },
108468
-
108469
- /**
108470
- * Up to three columns for the mini-kanban view on `detail-page`.
108471
- *
108472
- * Per AD-2 (design.md): when the linked card has its own stack
108473
- * we always include that stack; otherwise the first three stacks
108474
- * by first-seen order are surfaced.
108475
- *
108476
- * @return {Array<{key: string, label: string, cards: Array}>}
108477
- */
108478
- miniColumns() {
108479
- return this.columns.slice(0, 3)
108480
- },
108481
-
108482
- stackDistribution() {
108483
- return this.columns.map((col) => ({
108484
- key: col.key,
108485
- label: col.label,
108486
- count: col.cards.length,
108487
- }))
108488
- },
108489
-
108490
- countHeadline() {
108491
- const total = this.cards.length;
108492
- const stackCount = this.columns.length;
108493
- if (stackCount <= 1) {
108494
- return l10n.translatePlural('nextcloud-vue', '{count} card', '{count} cards', total, { count: total })
108495
- }
108496
- const cardFragment = l10n.translatePlural('nextcloud-vue', '{count} card', '{count} cards', total, { count: total });
108497
- const stacksFragment = l10n.translatePlural('nextcloud-vue', 'across {count} stack', 'across {count} stacks', stackCount, { count: stackCount });
108498
- return `${cardFragment} ${stacksFragment}`
108499
- },
108500
-
108501
- mostRecent() {
108502
- if (this.cards.length === 0) {
108503
- return null
108504
- }
108505
- const sorted = [...this.cards].sort((a, b) => {
108506
- const ta = Date.parse(a.linkedAt ?? a.lastActivity ?? '') || 0;
108507
- const tb = Date.parse(b.linkedAt ?? b.lastActivity ?? '') || 0;
108508
- return tb - ta
108509
- });
108510
- return sorted[0]
108511
- },
108512
- },
108513
-
108514
- watch: {
108515
- objectId: { immediate: true, handler() {
108516
- this.fetch();
108517
- } },
108518
-
108519
- surface() {
108520
- this.fetch();
108521
- },
108522
-
108523
- value() {
108524
- if (this.surface === 'single-entity') {
108525
- this.fetchSingle();
108526
- }
108527
- },
108528
- },
108529
-
108530
- methods: {
108531
- baseUrl() {
108532
- return `${this.apiBase}/objects/${this.register}/${this.schema}/${this.objectId}/integrations/${this.integrationId}`
108533
- },
108534
-
108535
- cardKey(card) {
108536
- return card.cardId ?? card.id ?? ''
108537
- },
108538
-
108539
- cardTitle(card) {
108540
- return card.cardTitle ?? card.title ?? this.cardKey(card)
108541
- },
108542
-
108543
- cardUrl(card) {
108544
- if (card.url && safeHref(card.url) !== '#') {
108545
- return card.url
108546
- }
108547
- const boardId = card.boardId ?? card.board?.id ?? '';
108548
- const cardId = card.cardId ?? card.id ?? '';
108549
- if (boardId && cardId) {
108550
- return `/index.php/apps/deck/board/${boardId}/card/${cardId}`
108551
- }
108552
- return this.deckAppUrl
108553
- },
108554
-
108555
- stackTitle(card) {
108556
- return card.stackTitle ?? card.stack?.title ?? ''
108557
- },
108558
-
108559
- isLinked(card) {
108560
- if (!this.value) {
108561
- return false
108562
- }
108563
- return String(this.cardKey(card)) === String(this.value)
108564
- },
108565
-
108566
- chipSubtitle(card) {
108567
- return this.stackTitle(card) || this.cardTitle(card)
108568
- },
108569
-
108570
- fetch() {
108571
- if (this.surface === 'single-entity') {
108572
- this.fetchSingle();
108573
- return
108574
- }
108575
- this.fetchList();
108576
- },
108577
-
108578
- async fetchList() {
108579
- if (!this.register || !this.schema || !this.objectId) {
108580
- return
108581
- }
108582
- this.loading = true;
108583
- this.degraded = '';
108584
- try {
108585
- const response = await fetch(prefixUrl(this.baseUrl()), { headers: buildHeaders() });
108586
- if (response.ok) {
108587
- const data = await response.json();
108588
- this.cards = data.results || data.items || (Array.isArray(data) ? data : []) || [];
108589
- } else if (response.status === 503) {
108590
- this.cards = [];
108591
- this.degraded = this.unavailableLabel;
108592
- } else {
108593
- this.cards = [];
108594
- }
108595
- } catch (err) {
108596
- // eslint-disable-next-line no-console
108597
- console.error('[CnDeckCard] failed to fetch cards', err);
108598
- this.cards = [];
108599
- } finally {
108600
- this.loading = false;
108601
- }
108602
- },
108603
-
108604
- async fetchSingle() {
108605
- if (!this.value || !this.register || !this.schema || !this.objectId) {
108606
- this.entity = null;
108607
- return
108608
- }
108609
- this.loading = true;
108610
- this.degraded = '';
108611
- try {
108612
- const response = await fetch(prefixUrl(`${this.baseUrl()}/${encodeURIComponent(this.value)}`), { headers: buildHeaders() });
108613
- if (response.ok) {
108614
- this.entity = await response.json();
108615
- } else if (response.status === 503) {
108616
- this.entity = null;
108617
- this.degraded = this.unavailableLabel;
108618
- } else {
108619
- this.entity = null;
108620
- }
108621
- } catch (err) {
108622
- // eslint-disable-next-line no-console
108623
- console.error('[CnDeckCard] failed to fetch single card', err);
108624
- this.entity = null;
108625
- } finally {
108626
- this.loading = false;
108627
- }
108628
- },
108629
- },
108630
- };
108631
-
108632
- const _hoisted_1$6Y = ["title"];
108633
- const _hoisted_2$6K = ["href"];
108634
- const _hoisted_3$64 = {
108635
- key: 0,
108636
- class: "cn-deck-card__chip-stack"
108637
- };
108638
- const _hoisted_4$5v = {
108639
- key: 1,
108640
- class: "cn-deck-card__empty"
108641
- };
108642
- const _hoisted_5$4R = {
108643
- key: 0,
108644
- class: "cn-deck-card__empty"
108645
- };
108646
- const _hoisted_6$4t = {
108647
- key: 1,
108648
- class: "cn-deck-card__empty"
108649
- };
108650
- const _hoisted_7$42 = {
108651
- key: 2,
108652
- class: "cn-deck-card__headline"
108653
- };
108654
- const _hoisted_8$3E = { class: "cn-deck-card__headline-line" };
108655
- const _hoisted_9$3k = {
108656
- key: 0,
108657
- class: "cn-deck-card__distribution"
108658
- };
108659
- const _hoisted_10$2Y = { class: "cn-deck-card__distribution-label" };
108660
- const _hoisted_11$2D = { class: "cn-deck-card__distribution-count" };
108661
- const _hoisted_12$2m = {
108662
- key: 1,
108663
- class: "cn-deck-card__headline-recent"
108664
- };
108665
- const _hoisted_13$26 = ["href"];
108666
- const _hoisted_14$1$ = {
108667
- key: 0,
108668
- class: "cn-deck-card__empty"
108669
- };
108670
- const _hoisted_15$1R = {
108671
- key: 1,
108672
- class: "cn-deck-card__empty"
108673
- };
108674
- const _hoisted_16$1F = {
108675
- key: 2,
108676
- class: "cn-deck-card__kanban"
108677
- };
108678
- const _hoisted_17$1s = { class: "cn-deck-card__column-header" };
108679
- const _hoisted_18$1f = { class: "cn-deck-card__column-title" };
108680
- const _hoisted_19$19 = { class: "cn-deck-card__column-count" };
108681
- const _hoisted_20$11 = { class: "cn-deck-card__column-list" };
108682
- const _hoisted_21$$ = ["href"];
108683
-
108684
- function render$7e(_ctx, _cache, $props, $setup, $data, $options) {
108685
- const _component_NcLoadingIcon = vue$1.resolveComponent("NcLoadingIcon");
108686
- const _component_ViewColumnOutline = vue$1.resolveComponent("ViewColumnOutline");
108687
- const _component_CnDetailCard = vue$1.resolveComponent("CnDetailCard");
108688
-
108689
- return (vue$1.openBlock(), vue$1.createBlock(_component_CnDetailCard, {
108690
- title: $options.cardHeaderTitle,
108691
- icon: $options.cardIcon,
108692
- collapsible: $props.collapsible
108693
- }, {
108694
- default: vue$1.withCtx(() => [
108695
- ($data.loading)
108696
- ? (vue$1.openBlock(), vue$1.createBlock(_component_NcLoadingIcon, { key: 0 }))
108697
- : ($props.surface === 'single-entity')
108698
- ? (vue$1.openBlock(), vue$1.createElementBlock(vue$1.Fragment, { key: 1 }, [
108699
- ($data.entity)
108700
- ? (vue$1.openBlock(), vue$1.createElementBlock("span", {
108701
- key: 0,
108702
- class: "cn-deck-card__chip",
108703
- title: $options.chipSubtitle($data.entity)
108704
- }, [
108705
- vue$1.createVNode(_component_ViewColumnOutline, { size: 14 }),
108706
- vue$1.createElementVNode("a", {
108707
- href: $options.cardUrl($data.entity),
108708
- target: "_blank",
108709
- rel: "noopener"
108710
- }, vue$1.toDisplayString($options.cardTitle($data.entity)), 9 /* TEXT, PROPS */, _hoisted_2$6K),
108711
- ($options.stackTitle($data.entity))
108712
- ? (vue$1.openBlock(), vue$1.createElementBlock("span", _hoisted_3$64, " · " + vue$1.toDisplayString($options.stackTitle($data.entity)), 1 /* TEXT */))
108713
- : vue$1.createCommentVNode("v-if", true)
108714
- ], 8 /* PROPS */, _hoisted_1$6Y))
108715
- : (vue$1.openBlock(), vue$1.createElementBlock("span", _hoisted_4$5v, vue$1.toDisplayString($props.emptyLabel), 1 /* TEXT */))
108716
- ], 64 /* STABLE_FRAGMENT */))
108717
- : ($props.surface === 'user-dashboard' || $props.surface === 'app-dashboard')
108718
- ? (vue$1.openBlock(), vue$1.createElementBlock(vue$1.Fragment, { key: 2 }, [
108719
- ($data.degraded)
108720
- ? (vue$1.openBlock(), vue$1.createElementBlock("div", _hoisted_5$4R, vue$1.toDisplayString($data.degraded), 1 /* TEXT */))
108721
- : ($data.cards.length === 0)
108722
- ? (vue$1.openBlock(), vue$1.createElementBlock("div", _hoisted_6$4t, vue$1.toDisplayString($props.emptyLabel), 1 /* TEXT */))
108723
- : (vue$1.openBlock(), vue$1.createElementBlock("div", _hoisted_7$42, [
108724
- vue$1.createElementVNode("div", _hoisted_8$3E, [
108725
- vue$1.createElementVNode("strong", null, vue$1.toDisplayString($options.countHeadline), 1 /* TEXT */)
108726
- ]),
108727
- ($options.stackDistribution.length > 0)
108728
- ? (vue$1.openBlock(), vue$1.createElementBlock("ul", _hoisted_9$3k, [
108729
- (vue$1.openBlock(true), vue$1.createElementBlock(vue$1.Fragment, null, vue$1.renderList($options.stackDistribution, (bucket) => {
108730
- return (vue$1.openBlock(), vue$1.createElementBlock("li", {
108731
- key: bucket.key,
108732
- class: "cn-deck-card__distribution-row"
108733
- }, [
108734
- vue$1.createElementVNode("span", _hoisted_10$2Y, vue$1.toDisplayString(bucket.label), 1 /* TEXT */),
108735
- vue$1.createElementVNode("span", _hoisted_11$2D, vue$1.toDisplayString(bucket.count), 1 /* TEXT */)
108736
- ]))
108737
- }), 128 /* KEYED_FRAGMENT */))
108738
- ]))
108739
- : vue$1.createCommentVNode("v-if", true),
108740
- ($options.mostRecent)
108741
- ? (vue$1.openBlock(), vue$1.createElementBlock("div", _hoisted_12$2m, [
108742
- vue$1.createVNode(_component_ViewColumnOutline, { size: 14 }),
108743
- vue$1.createElementVNode("a", {
108744
- href: $options.cardUrl($options.mostRecent),
108745
- target: "_blank",
108746
- rel: "noopener"
108747
- }, vue$1.toDisplayString($options.cardTitle($options.mostRecent)), 9 /* TEXT, PROPS */, _hoisted_13$26)
108748
- ]))
108749
- : vue$1.createCommentVNode("v-if", true)
108750
- ]))
108751
- ], 64 /* STABLE_FRAGMENT */))
108752
- : (vue$1.openBlock(), vue$1.createElementBlock(vue$1.Fragment, { key: 3 }, [
108753
- ($data.degraded)
108754
- ? (vue$1.openBlock(), vue$1.createElementBlock("div", _hoisted_14$1$, vue$1.toDisplayString($data.degraded), 1 /* TEXT */))
108755
- : ($data.cards.length === 0)
108756
- ? (vue$1.openBlock(), vue$1.createElementBlock("div", _hoisted_15$1R, vue$1.toDisplayString($props.emptyLabel), 1 /* TEXT */))
108757
- : (vue$1.openBlock(), vue$1.createElementBlock("div", _hoisted_16$1F, [
108758
- (vue$1.openBlock(true), vue$1.createElementBlock(vue$1.Fragment, null, vue$1.renderList($options.miniColumns, (stack) => {
108759
- return (vue$1.openBlock(), vue$1.createElementBlock("section", {
108760
- key: stack.key,
108761
- class: "cn-deck-card__column"
108762
- }, [
108763
- vue$1.createElementVNode("header", _hoisted_17$1s, [
108764
- vue$1.createElementVNode("span", _hoisted_18$1f, vue$1.toDisplayString(stack.label), 1 /* TEXT */),
108765
- vue$1.createElementVNode("span", _hoisted_19$19, vue$1.toDisplayString(stack.cards.length), 1 /* TEXT */)
108766
- ]),
108767
- vue$1.createElementVNode("ul", _hoisted_20$11, [
108768
- (vue$1.openBlock(true), vue$1.createElementBlock(vue$1.Fragment, null, vue$1.renderList(stack.cards, (card) => {
108769
- return (vue$1.openBlock(), vue$1.createElementBlock("li", {
108770
- key: $options.cardKey(card),
108771
- class: vue$1.normalizeClass(["cn-deck-card__row", { 'cn-deck-card__row--highlight': $options.isLinked(card) }])
108772
- }, [
108773
- vue$1.createElementVNode("a", {
108774
- href: $options.cardUrl(card),
108775
- target: "_blank",
108776
- rel: "noopener",
108777
- class: "cn-deck-card__title"
108778
- }, vue$1.toDisplayString($options.cardTitle(card)), 9 /* TEXT, PROPS */, _hoisted_21$$)
108779
- ], 2 /* CLASS */))
108780
- }), 128 /* KEYED_FRAGMENT */))
108781
- ])
108782
- ]))
108783
- }), 128 /* KEYED_FRAGMENT */))
108784
- ]))
108785
- ], 64 /* STABLE_FRAGMENT */))
108786
- ]),
108787
- _: 1 /* STABLE */
108788
- }, 8 /* PROPS */, ["title", "icon", "collapsible"]))
108789
- }
108790
-
108791
- script$7f.render = render$7e;
108792
- script$7f.__scopeId = "data-v-13f7eff5";
108793
- const __sfc_main$79 = script$7f;
108794
-
108795
- var script$7e = {
108796
108617
  name: 'CnDeckCardCreate',
108797
108618
 
108798
108619
  components: { NcButton: vue.NcButton, NcDialog: vue.NcDialog, NcNoteCard: vue.NcNoteCard, NcSelect: vue.NcSelect, NcTextArea: vue.NcTextArea, NcTextField: vue.NcTextField },
@@ -108924,10 +108745,10 @@ var script$7e = {
108924
108745
  },
108925
108746
  };
108926
108747
 
108927
- const _hoisted_1$6X = { class: "cn-deck-card-create__date" };
108928
- const _hoisted_2$6J = { class: "cn-deck-card-create__date-label" };
108748
+ const _hoisted_1$6Y = { class: "cn-deck-card-create__date" };
108749
+ const _hoisted_2$6K = { class: "cn-deck-card-create__date-label" };
108929
108750
 
108930
- function render$7d(_ctx, _cache, $props, $setup, $data, $options) {
108751
+ function render$7e(_ctx, _cache, $props, $setup, $data, $options) {
108931
108752
  const _component_NcNoteCard = vue$1.resolveComponent("NcNoteCard");
108932
108753
  const _component_NcSelect = vue$1.resolveComponent("NcSelect");
108933
108754
  const _component_NcTextField = vue$1.resolveComponent("NcTextField");
@@ -109013,8 +108834,8 @@ function render$7d(_ctx, _cache, $props, $setup, $data, $options) {
109013
108834
  maxlength: 4000,
109014
108835
  rows: 4
109015
108836
  }, null, 8 /* PROPS */, ["modelValue", "label"]),
109016
- vue$1.createElementVNode("label", _hoisted_1$6X, [
109017
- vue$1.createElementVNode("span", _hoisted_2$6J, vue$1.toDisplayString($options.t('nextcloud-vue', 'Due date (optional)')), 1 /* TEXT */),
108837
+ vue$1.createElementVNode("label", _hoisted_1$6Y, [
108838
+ vue$1.createElementVNode("span", _hoisted_2$6K, vue$1.toDisplayString($options.t('nextcloud-vue', 'Due date (optional)')), 1 /* TEXT */),
109018
108839
  vue$1.withDirectives(vue$1.createElementVNode("input", {
109019
108840
  "onUpdate:modelValue": _cache[4] || (_cache[4] = $event => (($data.duedate) = $event)),
109020
108841
  type: "date",
@@ -109029,11 +108850,11 @@ function render$7d(_ctx, _cache, $props, $setup, $data, $options) {
109029
108850
  }, 8 /* PROPS */, ["name", "onClosing"]))
109030
108851
  }
109031
108852
 
109032
- script$7e.render = render$7d;
109033
- script$7e.__scopeId = "data-v-7b2335ba";
109034
- const __sfc_main$78 = script$7e;
108853
+ script$7f.render = render$7e;
108854
+ script$7f.__scopeId = "data-v-7b2335ba";
108855
+ const __sfc_main$79 = script$7f;
109035
108856
 
109036
- var script$7d = {
108857
+ var script$7e = {
109037
108858
  name: 'CnDeckCardPicker',
109038
108859
 
109039
108860
  components: { NcButton: vue.NcButton, NcDialog: vue.NcDialog, NcEmptyContent: vue.NcEmptyContent, NcLoadingIcon: vue.NcLoadingIcon, NcNoteCard: vue.NcNoteCard, ViewColumnOutline },
@@ -109221,40 +109042,40 @@ var script$7d = {
109221
109042
  },
109222
109043
  };
109223
109044
 
109224
- const _hoisted_1$6W = { class: "cn-deck-card-picker" };
109225
- const _hoisted_2$6I = { class: "cn-deck-card-picker__steps" };
109226
- const _hoisted_3$63 = {
109045
+ const _hoisted_1$6X = { class: "cn-deck-card-picker" };
109046
+ const _hoisted_2$6J = { class: "cn-deck-card-picker__steps" };
109047
+ const _hoisted_3$64 = {
109227
109048
  key: 1,
109228
109049
  class: "cn-deck-card-picker__panel"
109229
109050
  };
109230
- const _hoisted_4$5u = {
109051
+ const _hoisted_4$5v = {
109231
109052
  key: 2,
109232
109053
  class: "cn-deck-card-picker__list"
109233
109054
  };
109234
- const _hoisted_5$4Q = ["onClick"];
109235
- const _hoisted_6$4s = { class: "cn-deck-card-picker__row-label" };
109236
- const _hoisted_7$41 = {
109055
+ const _hoisted_5$4R = ["onClick"];
109056
+ const _hoisted_6$4t = { class: "cn-deck-card-picker__row-label" };
109057
+ const _hoisted_7$42 = {
109237
109058
  key: 2,
109238
109059
  class: "cn-deck-card-picker__panel"
109239
109060
  };
109240
- const _hoisted_8$3D = {
109061
+ const _hoisted_8$3E = {
109241
109062
  key: 2,
109242
109063
  class: "cn-deck-card-picker__list"
109243
109064
  };
109244
- const _hoisted_9$3j = ["onClick"];
109245
- const _hoisted_10$2X = { class: "cn-deck-card-picker__row-label" };
109246
- const _hoisted_11$2C = {
109065
+ const _hoisted_9$3k = ["onClick"];
109066
+ const _hoisted_10$2Y = { class: "cn-deck-card-picker__row-label" };
109067
+ const _hoisted_11$2D = {
109247
109068
  key: 3,
109248
109069
  class: "cn-deck-card-picker__panel"
109249
109070
  };
109250
- const _hoisted_12$2l = {
109071
+ const _hoisted_12$2m = {
109251
109072
  key: 2,
109252
109073
  class: "cn-deck-card-picker__list"
109253
109074
  };
109254
- const _hoisted_13$25 = ["onClick"];
109255
- const _hoisted_14$1_ = { class: "cn-deck-card-picker__row-label" };
109075
+ const _hoisted_13$26 = ["onClick"];
109076
+ const _hoisted_14$1$ = { class: "cn-deck-card-picker__row-label" };
109256
109077
 
109257
- function render$7c(_ctx, _cache, $props, $setup, $data, $options) {
109078
+ function render$7d(_ctx, _cache, $props, $setup, $data, $options) {
109258
109079
  const _component_NcNoteCard = vue$1.resolveComponent("NcNoteCard");
109259
109080
  const _component_NcLoadingIcon = vue$1.resolveComponent("NcLoadingIcon");
109260
109081
  const _component_NcEmptyContent = vue$1.resolveComponent("NcEmptyContent");
@@ -109301,8 +109122,8 @@ function render$7c(_ctx, _cache, $props, $setup, $data, $options) {
109301
109122
  : vue$1.createCommentVNode("v-if", true)
109302
109123
  ]),
109303
109124
  default: vue$1.withCtx(() => [
109304
- vue$1.createElementVNode("div", _hoisted_1$6W, [
109305
- vue$1.createElementVNode("ol", _hoisted_2$6I, [
109125
+ vue$1.createElementVNode("div", _hoisted_1$6X, [
109126
+ vue$1.createElementVNode("ol", _hoisted_2$6J, [
109306
109127
  vue$1.createElementVNode("li", {
109307
109128
  class: vue$1.normalizeClass($options.stepClass(1))
109308
109129
  }, vue$1.toDisplayString($options.t('nextcloud-vue', '1. Board')), 3 /* TEXT, CLASS */),
@@ -109326,7 +109147,7 @@ function render$7c(_ctx, _cache, $props, $setup, $data, $options) {
109326
109147
  }))
109327
109148
  : vue$1.createCommentVNode("v-if", true),
109328
109149
  ($data.step === 1)
109329
- ? (vue$1.openBlock(), vue$1.createElementBlock("section", _hoisted_3$63, [
109150
+ ? (vue$1.openBlock(), vue$1.createElementBlock("section", _hoisted_3$64, [
109330
109151
  ($data.loading)
109331
109152
  ? (vue$1.openBlock(), vue$1.createBlock(_component_NcLoadingIcon, { key: 0 }))
109332
109153
  : ($data.boards.length === 0)
@@ -109335,7 +109156,7 @@ function render$7c(_ctx, _cache, $props, $setup, $data, $options) {
109335
109156
  name: $options.t('nextcloud-vue', 'No boards available'),
109336
109157
  description: $options.t('nextcloud-vue', 'NC Deck has no boards visible to you yet.')
109337
109158
  }, null, 8 /* PROPS */, ["name", "description"]))
109338
- : (vue$1.openBlock(), vue$1.createElementBlock("ul", _hoisted_4$5u, [
109159
+ : (vue$1.openBlock(), vue$1.createElementBlock("ul", _hoisted_4$5v, [
109339
109160
  (vue$1.openBlock(true), vue$1.createElementBlock(vue$1.Fragment, null, vue$1.renderList($data.boards, (board) => {
109340
109161
  return (vue$1.openBlock(), vue$1.createElementBlock("li", {
109341
109162
  key: board.id,
@@ -109347,14 +109168,14 @@ function render$7c(_ctx, _cache, $props, $setup, $data, $options) {
109347
109168
  onClick: $event => ($options.pickBoard(board))
109348
109169
  }, [
109349
109170
  vue$1.createVNode(_component_ViewColumnOutline, { size: 20 }),
109350
- vue$1.createElementVNode("span", _hoisted_6$4s, vue$1.toDisplayString(board.title), 1 /* TEXT */)
109351
- ], 8 /* PROPS */, _hoisted_5$4Q)
109171
+ vue$1.createElementVNode("span", _hoisted_6$4t, vue$1.toDisplayString(board.title), 1 /* TEXT */)
109172
+ ], 8 /* PROPS */, _hoisted_5$4R)
109352
109173
  ], 2 /* CLASS */))
109353
109174
  }), 128 /* KEYED_FRAGMENT */))
109354
109175
  ]))
109355
109176
  ]))
109356
109177
  : ($data.step === 2)
109357
- ? (vue$1.openBlock(), vue$1.createElementBlock("section", _hoisted_7$41, [
109178
+ ? (vue$1.openBlock(), vue$1.createElementBlock("section", _hoisted_7$42, [
109358
109179
  ($data.loading)
109359
109180
  ? (vue$1.openBlock(), vue$1.createBlock(_component_NcLoadingIcon, { key: 0 }))
109360
109181
  : ($data.stacks.length === 0)
@@ -109363,7 +109184,7 @@ function render$7c(_ctx, _cache, $props, $setup, $data, $options) {
109363
109184
  name: $options.t('nextcloud-vue', 'No stacks on this board'),
109364
109185
  description: $options.t('nextcloud-vue', 'Pick a different board or add a stack in NC Deck.')
109365
109186
  }, null, 8 /* PROPS */, ["name", "description"]))
109366
- : (vue$1.openBlock(), vue$1.createElementBlock("ul", _hoisted_8$3D, [
109187
+ : (vue$1.openBlock(), vue$1.createElementBlock("ul", _hoisted_8$3E, [
109367
109188
  (vue$1.openBlock(true), vue$1.createElementBlock(vue$1.Fragment, null, vue$1.renderList($data.stacks, (stack) => {
109368
109189
  return (vue$1.openBlock(), vue$1.createElementBlock("li", {
109369
109190
  key: stack.id,
@@ -109374,14 +109195,14 @@ function render$7c(_ctx, _cache, $props, $setup, $data, $options) {
109374
109195
  class: "cn-deck-card-picker__row-button",
109375
109196
  onClick: $event => ($options.pickStack(stack))
109376
109197
  }, [
109377
- vue$1.createElementVNode("span", _hoisted_10$2X, vue$1.toDisplayString(stack.title), 1 /* TEXT */)
109378
- ], 8 /* PROPS */, _hoisted_9$3j)
109198
+ vue$1.createElementVNode("span", _hoisted_10$2Y, vue$1.toDisplayString(stack.title), 1 /* TEXT */)
109199
+ ], 8 /* PROPS */, _hoisted_9$3k)
109379
109200
  ], 2 /* CLASS */))
109380
109201
  }), 128 /* KEYED_FRAGMENT */))
109381
109202
  ]))
109382
109203
  ]))
109383
109204
  : ($data.step === 3)
109384
- ? (vue$1.openBlock(), vue$1.createElementBlock("section", _hoisted_11$2C, [
109205
+ ? (vue$1.openBlock(), vue$1.createElementBlock("section", _hoisted_11$2D, [
109385
109206
  ($data.loading)
109386
109207
  ? (vue$1.openBlock(), vue$1.createBlock(_component_NcLoadingIcon, { key: 0 }))
109387
109208
  : ($data.cards.length === 0)
@@ -109390,7 +109211,7 @@ function render$7c(_ctx, _cache, $props, $setup, $data, $options) {
109390
109211
  name: $options.t('nextcloud-vue', 'No cards on this stack'),
109391
109212
  description: $options.t('nextcloud-vue', 'Pick a different stack or create a card in NC Deck.')
109392
109213
  }, null, 8 /* PROPS */, ["name", "description"]))
109393
- : (vue$1.openBlock(), vue$1.createElementBlock("ul", _hoisted_12$2l, [
109214
+ : (vue$1.openBlock(), vue$1.createElementBlock("ul", _hoisted_12$2m, [
109394
109215
  (vue$1.openBlock(true), vue$1.createElementBlock(vue$1.Fragment, null, vue$1.renderList($data.cards, (card) => {
109395
109216
  return (vue$1.openBlock(), vue$1.createElementBlock("li", {
109396
109217
  key: card.id,
@@ -109401,8 +109222,8 @@ function render$7c(_ctx, _cache, $props, $setup, $data, $options) {
109401
109222
  class: "cn-deck-card-picker__row-button",
109402
109223
  onClick: $event => ($options.pickCard(card))
109403
109224
  }, [
109404
- vue$1.createElementVNode("span", _hoisted_14$1_, vue$1.toDisplayString(card.title), 1 /* TEXT */)
109405
- ], 8 /* PROPS */, _hoisted_13$25)
109225
+ vue$1.createElementVNode("span", _hoisted_14$1$, vue$1.toDisplayString(card.title), 1 /* TEXT */)
109226
+ ], 8 /* PROPS */, _hoisted_13$26)
109406
109227
  ], 2 /* CLASS */))
109407
109228
  }), 128 /* KEYED_FRAGMENT */))
109408
109229
  ]))
@@ -109414,8 +109235,563 @@ function render$7c(_ctx, _cache, $props, $setup, $data, $options) {
109414
109235
  }, 8 /* PROPS */, ["name", "onClosing"]))
109415
109236
  }
109416
109237
 
109238
+ script$7e.render = render$7d;
109239
+ script$7e.__scopeId = "data-v-7861e746";
109240
+ const __sfc_main$78 = script$7e;
109241
+
109242
+ const VALID_SURFACES$e = ['user-dashboard', 'app-dashboard', 'detail-page', 'single-entity'];
109243
+
109244
+ /**
109245
+ * CnDeckCard — bespoke surface-aware widget for the `deck` integration.
109246
+ *
109247
+ * Renders Deck-aware metadata across all four surfaces. See the
109248
+ * file-level docblock for surface-by-surface behaviour.
109249
+ */
109250
+ var script$7d = {
109251
+ name: 'CnDeckCard',
109252
+
109253
+ components: { CnDeckCardCreate: __sfc_main$79, CnDeckCardPicker: __sfc_main$78, CnDetailCard: __sfc_main$7F, LinkVariant, NcButton: vue.NcButton, NcLoadingIcon: vue.NcLoadingIcon, Plus, ViewColumnOutline },
109254
+
109255
+ props: {
109256
+ /** Stable integration id (forwarded from the registry — always `'deck'`). */
109257
+ integrationId: { type: String, default: 'deck' },
109258
+ /** OpenRegister register id (slug or uuid). */
109259
+ register: { type: String, required: true },
109260
+ /** OpenRegister schema id (slug or uuid). */
109261
+ schema: { type: String, required: true },
109262
+ /** Parent object id. */
109263
+ objectId: { type: String, required: true },
109264
+ /** Rendering surface (AD-19). */
109265
+ surface: {
109266
+ type: String,
109267
+ default: 'detail-page',
109268
+ validator: (s) => VALID_SURFACES$e.includes(s),
109269
+ },
109270
+
109271
+ /** Optional single-entity reference (card id). */
109272
+ value: { type: [String, Number], default: '' },
109273
+ /** Pre-translated card title. */
109274
+ title: { type: String, default: () => l10n.translate('nextcloud-vue', 'Cards') },
109275
+ /** Optional Material Design Icon component. */
109276
+ icon: { type: Object, default: () => ViewColumnOutline },
109277
+ /** Base API URL. */
109278
+ apiBase: { type: String, default: '/apps/openregister/api' },
109279
+ /** Whether the card body is collapsible. */
109280
+ collapsible: { type: Boolean, default: true },
109281
+ /** Pre-translated empty-state label. */
109282
+ emptyLabel: { type: String, default: () => l10n.translate('nextcloud-vue', 'No cards linked yet') },
109283
+ /** Pre-translated unavailable label. */
109284
+ unavailableLabel: { type: String, default: () => l10n.translate('nextcloud-vue', 'NC Deck is currently unavailable.') },
109285
+ /** URL of the NC Deck app entry. */
109286
+ deckAppUrl: { type: String, default: '/index.php/apps/deck' },
109287
+ /**
109288
+ * Buttons in the card's title row on a detail page: `link` links an
109289
+ * existing Deck card, `create` makes a new one linked to the object.
109290
+ * In the order given; none by default.
109291
+ */
109292
+ headerActions: { type: Array, default: () => [] },
109293
+ /** Label of the `link` button. */
109294
+ linkLabel: { type: String, default: () => l10n.translate('nextcloud-vue', 'Link an existing card') },
109295
+ /** Label of the `create` button. */
109296
+ createLabel: { type: String, default: () => l10n.translate('nextcloud-vue', 'New card') },
109297
+ },
109298
+
109299
+ data() {
109300
+ return {
109301
+ cards: [],
109302
+ entity: null,
109303
+ loading: false,
109304
+ degraded: '',
109305
+ pickerOpen: false,
109306
+ createOpen: false,
109307
+ actionError: '',
109308
+ }
109309
+ },
109310
+
109311
+ computed: {
109312
+ /**
109313
+ * The title-row buttons to draw: only on a detail page with an
109314
+ * object, only the known ones, in the order given.
109315
+ *
109316
+ * @return {Array<string>}
109317
+ */
109318
+ shownHeaderActions() {
109319
+ if (this.surface !== 'detail-page' || !this.objectId || !Array.isArray(this.headerActions)) {
109320
+ return []
109321
+ }
109322
+ return this.headerActions.filter((action, index, all) => ['create', 'link'].includes(action) && all.indexOf(action) === index)
109323
+ },
109324
+
109325
+ cardHeaderTitle() {
109326
+ return this.title || this.integrationId
109327
+ },
109328
+
109329
+ cardIcon() {
109330
+ return this.icon
109331
+ },
109332
+
109333
+ /**
109334
+ * Cards grouped by stack for both the mini-kanban (detail-page)
109335
+ * and the stack-distribution list (dashboard surfaces).
109336
+ *
109337
+ * @return {Array<{key: string, label: string, cards: Array}>}
109338
+ */
109339
+ columns() {
109340
+ const groups = new Map();
109341
+ for (const card of this.cards) {
109342
+ const stackId = card.stackId ?? card.stack?.id ?? 'unstacked';
109343
+ const stackLabel = card.stackTitle
109344
+ ?? card.stack?.title
109345
+ ?? (stackId === 'unstacked'
109346
+ ? l10n.translate('nextcloud-vue', 'No stack')
109347
+ : l10n.translate('nextcloud-vue', 'Stack {n}', { n: stackId }));
109348
+ const key = String(stackId);
109349
+ if (!groups.has(key)) {
109350
+ groups.set(key, { key, label: stackLabel, cards: [] });
109351
+ }
109352
+ groups.get(key).cards.push(card);
109353
+ }
109354
+ return Array.from(groups.values())
109355
+ },
109356
+
109357
+ /**
109358
+ * Up to three columns for the mini-kanban view on `detail-page`.
109359
+ *
109360
+ * Per AD-2 (design.md): when the linked card has its own stack
109361
+ * we always include that stack; otherwise the first three stacks
109362
+ * by first-seen order are surfaced.
109363
+ *
109364
+ * @return {Array<{key: string, label: string, cards: Array}>}
109365
+ */
109366
+ miniColumns() {
109367
+ return this.columns.slice(0, 3)
109368
+ },
109369
+
109370
+ stackDistribution() {
109371
+ return this.columns.map((col) => ({
109372
+ key: col.key,
109373
+ label: col.label,
109374
+ count: col.cards.length,
109375
+ }))
109376
+ },
109377
+
109378
+ countHeadline() {
109379
+ const total = this.cards.length;
109380
+ const stackCount = this.columns.length;
109381
+ if (stackCount <= 1) {
109382
+ return l10n.translatePlural('nextcloud-vue', '{count} card', '{count} cards', total, { count: total })
109383
+ }
109384
+ const cardFragment = l10n.translatePlural('nextcloud-vue', '{count} card', '{count} cards', total, { count: total });
109385
+ const stacksFragment = l10n.translatePlural('nextcloud-vue', 'across {count} stack', 'across {count} stacks', stackCount, { count: stackCount });
109386
+ return `${cardFragment} ${stacksFragment}`
109387
+ },
109388
+
109389
+ mostRecent() {
109390
+ if (this.cards.length === 0) {
109391
+ return null
109392
+ }
109393
+ const sorted = [...this.cards].sort((a, b) => {
109394
+ const ta = Date.parse(a.linkedAt ?? a.lastActivity ?? '') || 0;
109395
+ const tb = Date.parse(b.linkedAt ?? b.lastActivity ?? '') || 0;
109396
+ return tb - ta
109397
+ });
109398
+ return sorted[0]
109399
+ },
109400
+ },
109401
+
109402
+ watch: {
109403
+ objectId: { immediate: true, handler() {
109404
+ this.fetch();
109405
+ } },
109406
+
109407
+ surface() {
109408
+ this.fetch();
109409
+ },
109410
+
109411
+ value() {
109412
+ if (this.surface === 'single-entity') {
109413
+ this.fetchSingle();
109414
+ }
109415
+ },
109416
+ },
109417
+
109418
+ methods: {
109419
+ /** @return {string} The object's Deck endpoint the link and create flows post to. */
109420
+ deckEndpoint() {
109421
+ return `${this.apiBase}/objects/${this.register}/${this.schema}/${this.objectId}/deck`
109422
+ },
109423
+
109424
+ /**
109425
+ * Link the picked card, then read the list again.
109426
+ *
109427
+ * @param {object} payload `{ cardId }` from the picker.
109428
+ */
109429
+ async onLink(payload) {
109430
+ this.pickerOpen = false;
109431
+ await this.post(this.deckEndpoint(), payload, l10n.translate('nextcloud-vue', 'Could not link card.'));
109432
+ },
109433
+
109434
+ /**
109435
+ * Create the card linked to the object, then read the list again.
109436
+ *
109437
+ * @param {object} payload `{ boardId, stackId, title, ... }` from the form.
109438
+ */
109439
+ async onCreate(payload) {
109440
+ this.createOpen = false;
109441
+ await this.post(`${this.deckEndpoint()}/new`, payload, l10n.translate('nextcloud-vue', 'Could not create card.'));
109442
+ },
109443
+
109444
+ /**
109445
+ * POST one flow's payload and reload on success.
109446
+ *
109447
+ * @param {string} url The endpoint.
109448
+ * @param {object} payload The body.
109449
+ * @param {string} failure The sentence shown when it fails.
109450
+ */
109451
+ async post(url, payload, failure) {
109452
+ this.actionError = '';
109453
+ try {
109454
+ const response = await fetch(prefixUrl(url), {
109455
+ method: 'POST',
109456
+ headers: { ...buildHeaders(), 'Content-Type': 'application/json' },
109457
+ body: JSON.stringify(payload),
109458
+ });
109459
+ if (response.ok) {
109460
+ await this.fetchList();
109461
+ } else if (response.status === 409) {
109462
+ this.actionError = l10n.translate('nextcloud-vue', 'This card is already linked.');
109463
+ } else {
109464
+ this.actionError = failure;
109465
+ }
109466
+ } catch {
109467
+ this.actionError = failure;
109468
+ }
109469
+ },
109470
+
109471
+ baseUrl() {
109472
+ return `${this.apiBase}/objects/${this.register}/${this.schema}/${this.objectId}/integrations/${this.integrationId}`
109473
+ },
109474
+
109475
+ cardKey(card) {
109476
+ return card.cardId ?? card.id ?? ''
109477
+ },
109478
+
109479
+ cardTitle(card) {
109480
+ return card.cardTitle ?? card.title ?? this.cardKey(card)
109481
+ },
109482
+
109483
+ cardUrl(card) {
109484
+ if (card.url && safeHref(card.url) !== '#') {
109485
+ return card.url
109486
+ }
109487
+ const boardId = card.boardId ?? card.board?.id ?? '';
109488
+ const cardId = card.cardId ?? card.id ?? '';
109489
+ if (boardId && cardId) {
109490
+ return `/index.php/apps/deck/board/${boardId}/card/${cardId}`
109491
+ }
109492
+ return this.deckAppUrl
109493
+ },
109494
+
109495
+ stackTitle(card) {
109496
+ return card.stackTitle ?? card.stack?.title ?? ''
109497
+ },
109498
+
109499
+ isLinked(card) {
109500
+ if (!this.value) {
109501
+ return false
109502
+ }
109503
+ return String(this.cardKey(card)) === String(this.value)
109504
+ },
109505
+
109506
+ chipSubtitle(card) {
109507
+ return this.stackTitle(card) || this.cardTitle(card)
109508
+ },
109509
+
109510
+ fetch() {
109511
+ if (this.surface === 'single-entity') {
109512
+ this.fetchSingle();
109513
+ return
109514
+ }
109515
+ this.fetchList();
109516
+ },
109517
+
109518
+ async fetchList() {
109519
+ if (!this.register || !this.schema || !this.objectId) {
109520
+ return
109521
+ }
109522
+ this.loading = true;
109523
+ this.degraded = '';
109524
+ try {
109525
+ const response = await fetch(prefixUrl(this.baseUrl()), { headers: buildHeaders() });
109526
+ if (response.ok) {
109527
+ const data = await response.json();
109528
+ this.cards = data.results || data.items || (Array.isArray(data) ? data : []) || [];
109529
+ } else if (response.status === 503) {
109530
+ this.cards = [];
109531
+ this.degraded = this.unavailableLabel;
109532
+ } else {
109533
+ this.cards = [];
109534
+ }
109535
+ } catch (err) {
109536
+ // eslint-disable-next-line no-console
109537
+ console.error('[CnDeckCard] failed to fetch cards', err);
109538
+ this.cards = [];
109539
+ } finally {
109540
+ this.loading = false;
109541
+ }
109542
+ },
109543
+
109544
+ async fetchSingle() {
109545
+ if (!this.value || !this.register || !this.schema || !this.objectId) {
109546
+ this.entity = null;
109547
+ return
109548
+ }
109549
+ this.loading = true;
109550
+ this.degraded = '';
109551
+ try {
109552
+ const response = await fetch(prefixUrl(`${this.baseUrl()}/${encodeURIComponent(this.value)}`), { headers: buildHeaders() });
109553
+ if (response.ok) {
109554
+ this.entity = await response.json();
109555
+ } else if (response.status === 503) {
109556
+ this.entity = null;
109557
+ this.degraded = this.unavailableLabel;
109558
+ } else {
109559
+ this.entity = null;
109560
+ }
109561
+ } catch (err) {
109562
+ // eslint-disable-next-line no-console
109563
+ console.error('[CnDeckCard] failed to fetch single card', err);
109564
+ this.entity = null;
109565
+ } finally {
109566
+ this.loading = false;
109567
+ }
109568
+ },
109569
+ },
109570
+ };
109571
+
109572
+ const _hoisted_1$6W = ["title"];
109573
+ const _hoisted_2$6I = ["href"];
109574
+ const _hoisted_3$63 = {
109575
+ key: 0,
109576
+ class: "cn-deck-card__chip-stack"
109577
+ };
109578
+ const _hoisted_4$5u = {
109579
+ key: 1,
109580
+ class: "cn-deck-card__empty"
109581
+ };
109582
+ const _hoisted_5$4Q = {
109583
+ key: 0,
109584
+ class: "cn-deck-card__empty"
109585
+ };
109586
+ const _hoisted_6$4s = {
109587
+ key: 1,
109588
+ class: "cn-deck-card__empty"
109589
+ };
109590
+ const _hoisted_7$41 = {
109591
+ key: 2,
109592
+ class: "cn-deck-card__headline"
109593
+ };
109594
+ const _hoisted_8$3D = { class: "cn-deck-card__headline-line" };
109595
+ const _hoisted_9$3j = {
109596
+ key: 0,
109597
+ class: "cn-deck-card__distribution"
109598
+ };
109599
+ const _hoisted_10$2X = { class: "cn-deck-card__distribution-label" };
109600
+ const _hoisted_11$2C = { class: "cn-deck-card__distribution-count" };
109601
+ const _hoisted_12$2l = {
109602
+ key: 1,
109603
+ class: "cn-deck-card__headline-recent"
109604
+ };
109605
+ const _hoisted_13$25 = ["href"];
109606
+ const _hoisted_14$1_ = {
109607
+ key: 0,
109608
+ class: "cn-deck-card__empty"
109609
+ };
109610
+ const _hoisted_15$1R = {
109611
+ key: 1,
109612
+ class: "cn-deck-card__empty"
109613
+ };
109614
+ const _hoisted_16$1F = {
109615
+ key: 2,
109616
+ class: "cn-deck-card__kanban"
109617
+ };
109618
+ const _hoisted_17$1s = { class: "cn-deck-card__column-header" };
109619
+ const _hoisted_18$1f = { class: "cn-deck-card__column-title" };
109620
+ const _hoisted_19$19 = { class: "cn-deck-card__column-count" };
109621
+ const _hoisted_20$11 = { class: "cn-deck-card__column-list" };
109622
+ const _hoisted_21$$ = ["href"];
109623
+ const _hoisted_22$_ = {
109624
+ key: 4,
109625
+ class: "cn-deck-card__action-error",
109626
+ role: "alert"
109627
+ };
109628
+
109629
+ function render$7c(_ctx, _cache, $props, $setup, $data, $options) {
109630
+ const _component_Plus = vue$1.resolveComponent("Plus");
109631
+ const _component_LinkVariant = vue$1.resolveComponent("LinkVariant");
109632
+ const _component_NcButton = vue$1.resolveComponent("NcButton");
109633
+ const _component_NcLoadingIcon = vue$1.resolveComponent("NcLoadingIcon");
109634
+ const _component_ViewColumnOutline = vue$1.resolveComponent("ViewColumnOutline");
109635
+ const _component_CnDeckCardPicker = vue$1.resolveComponent("CnDeckCardPicker");
109636
+ const _component_CnDeckCardCreate = vue$1.resolveComponent("CnDeckCardCreate");
109637
+ const _component_CnDetailCard = vue$1.resolveComponent("CnDetailCard");
109638
+
109639
+ return (vue$1.openBlock(), vue$1.createBlock(_component_CnDetailCard, {
109640
+ title: $options.cardHeaderTitle,
109641
+ icon: $options.cardIcon,
109642
+ collapsible: $props.collapsible
109643
+ }, vue$1.createSlots({
109644
+ default: vue$1.withCtx(() => [
109645
+ ($data.loading)
109646
+ ? (vue$1.openBlock(), vue$1.createBlock(_component_NcLoadingIcon, { key: 0 }))
109647
+ : ($props.surface === 'single-entity')
109648
+ ? (vue$1.openBlock(), vue$1.createElementBlock(vue$1.Fragment, { key: 1 }, [
109649
+ ($data.entity)
109650
+ ? (vue$1.openBlock(), vue$1.createElementBlock("span", {
109651
+ key: 0,
109652
+ class: "cn-deck-card__chip",
109653
+ title: $options.chipSubtitle($data.entity)
109654
+ }, [
109655
+ vue$1.createVNode(_component_ViewColumnOutline, { size: 14 }),
109656
+ vue$1.createElementVNode("a", {
109657
+ href: $options.cardUrl($data.entity),
109658
+ target: "_blank",
109659
+ rel: "noopener"
109660
+ }, vue$1.toDisplayString($options.cardTitle($data.entity)), 9 /* TEXT, PROPS */, _hoisted_2$6I),
109661
+ ($options.stackTitle($data.entity))
109662
+ ? (vue$1.openBlock(), vue$1.createElementBlock("span", _hoisted_3$63, " · " + vue$1.toDisplayString($options.stackTitle($data.entity)), 1 /* TEXT */))
109663
+ : vue$1.createCommentVNode("v-if", true)
109664
+ ], 8 /* PROPS */, _hoisted_1$6W))
109665
+ : (vue$1.openBlock(), vue$1.createElementBlock("span", _hoisted_4$5u, vue$1.toDisplayString($props.emptyLabel), 1 /* TEXT */))
109666
+ ], 64 /* STABLE_FRAGMENT */))
109667
+ : ($props.surface === 'user-dashboard' || $props.surface === 'app-dashboard')
109668
+ ? (vue$1.openBlock(), vue$1.createElementBlock(vue$1.Fragment, { key: 2 }, [
109669
+ ($data.degraded)
109670
+ ? (vue$1.openBlock(), vue$1.createElementBlock("div", _hoisted_5$4Q, vue$1.toDisplayString($data.degraded), 1 /* TEXT */))
109671
+ : ($data.cards.length === 0)
109672
+ ? (vue$1.openBlock(), vue$1.createElementBlock("div", _hoisted_6$4s, vue$1.toDisplayString($props.emptyLabel), 1 /* TEXT */))
109673
+ : (vue$1.openBlock(), vue$1.createElementBlock("div", _hoisted_7$41, [
109674
+ vue$1.createElementVNode("div", _hoisted_8$3D, [
109675
+ vue$1.createElementVNode("strong", null, vue$1.toDisplayString($options.countHeadline), 1 /* TEXT */)
109676
+ ]),
109677
+ ($options.stackDistribution.length > 0)
109678
+ ? (vue$1.openBlock(), vue$1.createElementBlock("ul", _hoisted_9$3j, [
109679
+ (vue$1.openBlock(true), vue$1.createElementBlock(vue$1.Fragment, null, vue$1.renderList($options.stackDistribution, (bucket) => {
109680
+ return (vue$1.openBlock(), vue$1.createElementBlock("li", {
109681
+ key: bucket.key,
109682
+ class: "cn-deck-card__distribution-row"
109683
+ }, [
109684
+ vue$1.createElementVNode("span", _hoisted_10$2X, vue$1.toDisplayString(bucket.label), 1 /* TEXT */),
109685
+ vue$1.createElementVNode("span", _hoisted_11$2C, vue$1.toDisplayString(bucket.count), 1 /* TEXT */)
109686
+ ]))
109687
+ }), 128 /* KEYED_FRAGMENT */))
109688
+ ]))
109689
+ : vue$1.createCommentVNode("v-if", true),
109690
+ ($options.mostRecent)
109691
+ ? (vue$1.openBlock(), vue$1.createElementBlock("div", _hoisted_12$2l, [
109692
+ vue$1.createVNode(_component_ViewColumnOutline, { size: 14 }),
109693
+ vue$1.createElementVNode("a", {
109694
+ href: $options.cardUrl($options.mostRecent),
109695
+ target: "_blank",
109696
+ rel: "noopener"
109697
+ }, vue$1.toDisplayString($options.cardTitle($options.mostRecent)), 9 /* TEXT, PROPS */, _hoisted_13$25)
109698
+ ]))
109699
+ : vue$1.createCommentVNode("v-if", true)
109700
+ ]))
109701
+ ], 64 /* STABLE_FRAGMENT */))
109702
+ : (vue$1.openBlock(), vue$1.createElementBlock(vue$1.Fragment, { key: 3 }, [
109703
+ ($data.degraded)
109704
+ ? (vue$1.openBlock(), vue$1.createElementBlock("div", _hoisted_14$1_, vue$1.toDisplayString($data.degraded), 1 /* TEXT */))
109705
+ : ($data.cards.length === 0)
109706
+ ? (vue$1.openBlock(), vue$1.createElementBlock("div", _hoisted_15$1R, vue$1.toDisplayString($props.emptyLabel), 1 /* TEXT */))
109707
+ : (vue$1.openBlock(), vue$1.createElementBlock("div", _hoisted_16$1F, [
109708
+ (vue$1.openBlock(true), vue$1.createElementBlock(vue$1.Fragment, null, vue$1.renderList($options.miniColumns, (stack) => {
109709
+ return (vue$1.openBlock(), vue$1.createElementBlock("section", {
109710
+ key: stack.key,
109711
+ class: "cn-deck-card__column"
109712
+ }, [
109713
+ vue$1.createElementVNode("header", _hoisted_17$1s, [
109714
+ vue$1.createElementVNode("span", _hoisted_18$1f, vue$1.toDisplayString(stack.label), 1 /* TEXT */),
109715
+ vue$1.createElementVNode("span", _hoisted_19$19, vue$1.toDisplayString(stack.cards.length), 1 /* TEXT */)
109716
+ ]),
109717
+ vue$1.createElementVNode("ul", _hoisted_20$11, [
109718
+ (vue$1.openBlock(true), vue$1.createElementBlock(vue$1.Fragment, null, vue$1.renderList(stack.cards, (card) => {
109719
+ return (vue$1.openBlock(), vue$1.createElementBlock("li", {
109720
+ key: $options.cardKey(card),
109721
+ class: vue$1.normalizeClass(["cn-deck-card__row", { 'cn-deck-card__row--highlight': $options.isLinked(card) }])
109722
+ }, [
109723
+ vue$1.createElementVNode("a", {
109724
+ href: $options.cardUrl(card),
109725
+ target: "_blank",
109726
+ rel: "noopener",
109727
+ class: "cn-deck-card__title"
109728
+ }, vue$1.toDisplayString($options.cardTitle(card)), 9 /* TEXT, PROPS */, _hoisted_21$$)
109729
+ ], 2 /* CLASS */))
109730
+ }), 128 /* KEYED_FRAGMENT */))
109731
+ ])
109732
+ ]))
109733
+ }), 128 /* KEYED_FRAGMENT */))
109734
+ ]))
109735
+ ], 64 /* STABLE_FRAGMENT */)),
109736
+ ($data.actionError)
109737
+ ? (vue$1.openBlock(), vue$1.createElementBlock("p", _hoisted_22$_, vue$1.toDisplayString($data.actionError), 1 /* TEXT */))
109738
+ : vue$1.createCommentVNode("v-if", true),
109739
+ ($data.pickerOpen)
109740
+ ? (vue$1.openBlock(), vue$1.createBlock(_component_CnDeckCardPicker, {
109741
+ key: 5,
109742
+ apiBase: $props.apiBase,
109743
+ onClose: _cache[0] || (_cache[0] = $event => ($data.pickerOpen = false)),
109744
+ onLink: $options.onLink
109745
+ }, null, 8 /* PROPS */, ["apiBase", "onLink"]))
109746
+ : vue$1.createCommentVNode("v-if", true),
109747
+ ($data.createOpen)
109748
+ ? (vue$1.openBlock(), vue$1.createBlock(_component_CnDeckCardCreate, {
109749
+ key: 6,
109750
+ apiBase: $props.apiBase,
109751
+ onClose: _cache[1] || (_cache[1] = $event => ($data.createOpen = false)),
109752
+ onCreate: $options.onCreate
109753
+ }, null, 8 /* PROPS */, ["apiBase", "onCreate"]))
109754
+ : vue$1.createCommentVNode("v-if", true)
109755
+ ]),
109756
+ _: 2 /* DYNAMIC */
109757
+ }, [
109758
+ ($options.shownHeaderActions.length > 0)
109759
+ ? {
109760
+ name: "actions",
109761
+ fn: vue$1.withCtx(() => [
109762
+ (vue$1.openBlock(true), vue$1.createElementBlock(vue$1.Fragment, null, vue$1.renderList($options.shownHeaderActions, (action) => {
109763
+ return (vue$1.openBlock(), vue$1.createBlock(_component_NcButton, {
109764
+ key: action,
109765
+ variant: "secondary",
109766
+ "data-testid": `cn-deck-card-${action}`,
109767
+ onClick: vue$1.withModifiers($event => (action === 'create' ? ($data.createOpen = true) : ($data.pickerOpen = true)), ["stop"])
109768
+ }, {
109769
+ icon: vue$1.withCtx(() => [
109770
+ (action === 'create')
109771
+ ? (vue$1.openBlock(), vue$1.createBlock(_component_Plus, {
109772
+ key: 0,
109773
+ size: 20
109774
+ }))
109775
+ : (vue$1.openBlock(), vue$1.createBlock(_component_LinkVariant, {
109776
+ key: 1,
109777
+ size: 20
109778
+ }))
109779
+ ]),
109780
+ default: vue$1.withCtx(() => [
109781
+ vue$1.createTextVNode(" " + vue$1.toDisplayString(action === 'create' ? $props.createLabel : $props.linkLabel), 1 /* TEXT */)
109782
+ ]),
109783
+ _: 2 /* DYNAMIC */
109784
+ }, 1032 /* PROPS, DYNAMIC_SLOTS */, ["data-testid", "onClick"]))
109785
+ }), 128 /* KEYED_FRAGMENT */))
109786
+ ]),
109787
+ key: "0"
109788
+ }
109789
+ : undefined
109790
+ ]), 1032 /* PROPS, DYNAMIC_SLOTS */, ["title", "icon", "collapsible"]))
109791
+ }
109792
+
109417
109793
  script$7d.render = render$7c;
109418
- script$7d.__scopeId = "data-v-7861e746";
109794
+ script$7d.__scopeId = "data-v-d8cff1c2";
109419
109795
  const __sfc_main$77 = script$7d;
109420
109796
 
109421
109797
  /** Maximum assignee avatars shown before collapsing the rest into a +N overflow badge. */
@@ -109440,8 +109816,8 @@ var script$7c = {
109440
109816
  LinkVariant,
109441
109817
  Plus,
109442
109818
  ViewColumnOutline,
109443
- CnDeckCardPicker: __sfc_main$77,
109444
- CnDeckCardCreate: __sfc_main$78,
109819
+ CnDeckCardPicker: __sfc_main$78,
109820
+ CnDeckCardCreate: __sfc_main$79,
109445
109821
  CnStatusBadge: __sfc_main$8g,
109446
109822
  },
109447
109823
 
@@ -110083,7 +110459,7 @@ const deckIntegration = {
110083
110459
  group: 'workflow',
110084
110460
  referenceType: 'deck',
110085
110461
  tab: __sfc_main$76,
110086
- widget: __sfc_main$79,
110462
+ widget: __sfc_main$77,
110087
110463
  defaultSize: { w: 4, h: 3 },
110088
110464
  // CnIntegrationWidget contract — exemplar accent (NC Deck brand blue).
110089
110465
  // `appName` / `docsUrl` default from id+label in the registry.
@@ -116059,15 +116435,19 @@ function indexRowData(data, { path = '', key = 'fileId' } = {}) {
116059
116435
  *
116060
116436
  * `visibleIf.extension` lists file extensions (no case, a leading dot is
116061
116437
  * allowed); `visibleIf.mime` lists mime types, where one ending in `/` or
116062
- * `/*` names the whole family. Every condition named must hold. An action
116063
- * without `visibleIf` is offered on every file, as before. An action with
116064
- * `when` is offered only while `when` is `true`.
116438
+ * `/*` names the whole family; `visibleIf.row` maps fields of the host's row
116439
+ * for the file to the value each must have (compared strictly, so `true` is
116440
+ * not `"true"`). Every condition named must hold. An action without
116441
+ * `visibleIf` is offered on every file, as before. An action with `when` is
116442
+ * offered only while `when` is `true`.
116065
116443
  *
116066
116444
  * @param {object} action The declared action.
116067
116445
  * @param {object} node The file (`basename`, `mime`).
116446
+ * @param {((key: string) => unknown)|null} rowValue Reads a field of the host's row for the file; without it a `row` condition fails.
116068
116447
  * @return {boolean} True when the action belongs on this file.
116448
+ * @spec openspec/changes/files-browser-action-visible-if-row/specs/files-browser/spec.md#requirement-a-host-action-can-be-offered-by-a-field-of-the-files-row
116069
116449
  */
116070
- function hostActionApplies(action, node) {
116450
+ function hostActionApplies(action, node, rowValue = null) {
116071
116451
  // `when`: the action applies only while it is true (a case type flag).
116072
116452
  // @spec openspec/changes/files-review-row-when/specs/files-review-row-when/spec.md#requirement-a-files-browser-entry-can-apply-only-when-a-condition-holds
116073
116453
  if (action && typeof action === 'object' && 'when' in action && action.when !== true) {
@@ -116099,6 +116479,15 @@ function hostActionApplies(action, node) {
116099
116479
  return false
116100
116480
  }
116101
116481
  }
116482
+ if (condition.row && typeof condition.row === 'object') {
116483
+ if (typeof rowValue !== 'function') {
116484
+ return false
116485
+ }
116486
+ const holds = Object.entries(condition.row).every(([key, wanted]) => rowValue(key) === wanted);
116487
+ if (!holds) {
116488
+ return false
116489
+ }
116490
+ }
116102
116491
  return true
116103
116492
  }
116104
116493
 
@@ -116107,6 +116496,7 @@ function hostActionApplies(action, node) {
116107
116496
  * SPDX-License-Identifier: AGPL-3.0-or-later
116108
116497
  */
116109
116498
 
116499
+
116110
116500
  /**
116111
116501
  * The built-in columns a host may name by string, and what each one reads.
116112
116502
  *
@@ -116157,12 +116547,26 @@ function isBuiltInFileColumn(name) {
116157
116547
  return typeof name === 'string' && Object.hasOwn(BUILT_IN_FILE_COLUMNS, name)
116158
116548
  }
116159
116549
 
116550
+ /**
116551
+ * Whether the app a column leans on is enabled: one app id, or a list of which
116552
+ * any one will do. A column without `requiredApp` always applies.
116553
+ *
116554
+ * @param {(string|string[]|undefined)} requiredApp The app id(s).
116555
+ * @return {boolean} True when the column applies.
116556
+ * @spec openspec/changes/files-column-required-app/specs/files-column-required-app/spec.md#requirement-a-file-column-can-require-another-app
116557
+ */
116558
+ function requiredAppPresent(requiredApp) {
116559
+ const ids = (Array.isArray(requiredApp) ? requiredApp : [requiredApp]).filter((id) => typeof id === 'string' && id !== '');
116560
+ return ids.length === 0 || ids.some((id) => isAppInstalled(id))
116561
+ }
116562
+
116160
116563
  /**
116161
116564
  * Resolve a host's `columns` declaration into column objects.
116162
116565
  *
116163
116566
  * A string names a built-in. An object declares its own: `key`, `label`,
116164
116567
  * `source` (`node`, `attribute` or `row`), `attribute`, `formatter` and
116165
- * `sortable`. An entry naming an unknown built-in is dropped here and refused
116568
+ * `sortable`, and `requiredApp` (an app id, or a list of which any one will
116569
+ * do; without it the column is left out). An entry naming an unknown built-in is dropped here and refused
116166
116570
  * by the manifest validator, so an author hears about it at authoring time
116167
116571
  * rather than finding a column missing at runtime.
116168
116572
  *
@@ -116187,6 +116591,9 @@ function normaliseFileColumns(columns) {
116187
116591
  if ('when' in entry && entry.when !== true) {
116188
116592
  return
116189
116593
  }
116594
+ if (!requiredAppPresent(entry.requiredApp)) {
116595
+ return
116596
+ }
116190
116597
  if (isBuiltInFileColumn(entry.key) && entry.source === undefined) {
116191
116598
  out.push({ ...BUILT_IN_FILE_COLUMNS[entry.key], ...entry, builtIn: true });
116192
116599
  return
@@ -116836,10 +117243,22 @@ var script$71 = {
116836
117243
  * @spec openspec/changes/files-drop-panel/specs/files-browser/spec.md#requirement-the-drop-state-fills-the-panel-and-says-where-the-files-go
116837
117244
  */
116838
117245
  dropDetail: {
116839
- type: String,
117246
+ type: [String, Array],
116840
117247
  default: '',
116841
117248
  },
116842
117249
 
117250
+ /**
117251
+ * Named values filled into `dropDetail` as `{name}`, such as the case
117252
+ * number (`{ "case": "@object.identifier" }` in a detail page's props).
117253
+ * While a value is unknown the line is left out.
117254
+ *
117255
+ * @spec openspec/changes/files-drop-detail-values/specs/files-drop-detail-values/spec.md#requirement-the-drop-detail-line-can-name-the-record
117256
+ */
117257
+ dropDetailValues: {
117258
+ type: Object,
117259
+ default: null,
117260
+ },
117261
+
116843
117262
  /** Show a line under the list saying files can be dropped on it. */
116844
117263
  dropHint: {
116845
117264
  type: Boolean,
@@ -117132,6 +117551,22 @@ var script$71 = {
117132
117551
  },
117133
117552
 
117134
117553
  computed: {
117554
+ /**
117555
+ * The `dropDetail` text: the string, or the text of the first variant
117556
+ * `{ when, text }` whose `when` is `true` or that has none.
117557
+ *
117558
+ * @return {string}
117559
+ * @spec openspec/changes/files-drop-detail-values/specs/files-drop-detail-values/spec.md#requirement-the-drop-detail-line-can-name-the-record
117560
+ */
117561
+ dropDetailTemplate() {
117562
+ if (typeof this.dropDetail === 'string') {
117563
+ return this.dropDetail
117564
+ }
117565
+ const variants = Array.isArray(this.dropDetail) ? this.dropDetail : [];
117566
+ const chosen = variants.find((item) => item && typeof item.text === 'string' && (!('when' in item) || item.when === true));
117567
+ return chosen ? chosen.text : ''
117568
+ },
117569
+
117135
117570
  /**
117136
117571
  * `dropDetail` through the host translate with `{count}` filled, '' when
117137
117572
  * there is none or the count it needs is unknown.
@@ -117140,10 +117575,22 @@ var script$71 = {
117140
117575
  * @return {string}
117141
117576
  */
117142
117577
  dropDetailText() {
117143
- if (!this.dropDetail) {
117578
+ const template = this.dropDetailTemplate;
117579
+ if (!template) {
117144
117580
  return ''
117145
117581
  }
117146
- const text = this.cnTranslate(this.dropDetail);
117582
+ let text = this.cnTranslate(template);
117583
+ // `dropDetailValues`: named values such as the case number; a value
117584
+ // still unknown (an unresolved `@` token, or empty) leaves the line out.
117585
+ // @spec openspec/changes/files-drop-detail-values/specs/files-drop-detail-values/spec.md#requirement-the-drop-detail-line-can-name-the-record
117586
+ const values = this.dropDetailValues && typeof this.dropDetailValues === 'object' ? this.dropDetailValues : {};
117587
+ for (const [name, value] of Object.entries(values)) {
117588
+ const shown = value === null || value === undefined ? '' : String(value);
117589
+ if (shown === '' || shown.startsWith('@')) {
117590
+ return ''
117591
+ }
117592
+ text = text.split(`{${name}}`).join(shown);
117593
+ }
117147
117594
  if (!text.includes('{count}')) {
117148
117595
  return text
117149
117596
  }
@@ -117173,6 +117620,19 @@ var script$71 = {
117173
117620
  return crumbsFor(this.rootPath, this.currentPath, this.rootLabel)
117174
117621
  },
117175
117622
 
117623
+ /**
117624
+ * Whether the open folder is the browser's root: the trail then ends on
117625
+ * the root itself (the board look draws no trail there).
117626
+ *
117627
+ * @return {boolean}
117628
+ * @spec openspec/changes/board-files-root-crumb/specs/board-files-root-crumb/spec.md#requirement-the-board-files-bar-draws-no-trail-at-the-root
117629
+ */
117630
+ atRoot() {
117631
+ const root = String(this.rootPath || '/').replace(/\/+$/, '') || '/';
117632
+ const last = this.crumbs[this.crumbs.length - 1];
117633
+ return Boolean(last) && last.path === root
117634
+ },
117635
+
117176
117636
  /**
117177
117637
  * The children in the chosen order, folders first the way the Files app
117178
117638
  * lists them.
@@ -118470,7 +118930,8 @@ var script$71 = {
118470
118930
  }
118471
118931
  })
118472
118932
  .filter((field) => field.value !== null && field.value !== undefined && field.value !== ''),
118473
- actions: (Array.isArray(card.actions) ? card.actions : []).filter((action) => action && action.id),
118933
+ actions: (Array.isArray(card.actions) ? card.actions : [])
118934
+ .filter((action) => action && action.id && hostActionApplies(action, node, this.rowValueOf(node))),
118474
118935
  }))
118475
118936
  },
118476
118937
 
@@ -118766,7 +119227,18 @@ var script$71 = {
118766
119227
  * @spec openspec/changes/files-browser-hosts-a-documents-list/specs/files-browser/spec.md
118767
119228
  */
118768
119229
  hostActionsFor(node) {
118769
- return this.rowActions.filter((action) => hostActionApplies(action, node))
119230
+ return this.rowActions.filter((action) => hostActionApplies(action, node, this.rowValueOf(node)))
119231
+ },
119232
+
119233
+ /**
119234
+ * A reader of the host's row fields for one file, for `visibleIf.row`.
119235
+ *
119236
+ * @param {object} node The file.
119237
+ * @return {(key: string) => unknown} `(key) => value` over the row the host gave for the file.
119238
+ * @spec openspec/changes/files-browser-action-visible-if-row/specs/files-browser/spec.md#requirement-a-host-action-can-be-offered-by-a-field-of-the-files-row
119239
+ */
119240
+ rowValueOf(node) {
119241
+ return (key) => fileColumnValue({ key, source: 'row' }, node, this.resolvedRowData)
118770
119242
  },
118771
119243
 
118772
119244
  /**
@@ -118946,7 +119418,7 @@ const _hoisted_30$n = {
118946
119418
  scope: "col"
118947
119419
  };
118948
119420
  const _hoisted_31$l = { class: "hidden-visually" };
118949
- const _hoisted_32$k = {
119421
+ const _hoisted_32$l = {
118950
119422
  key: 0,
118951
119423
  class: "cn-files-browser__group",
118952
119424
  "data-testid": "cn-files-browser-group"
@@ -119043,7 +119515,7 @@ function render$70(_ctx, _cache, $props, $setup, $data, $options) {
119043
119515
  const _component_NcDialog = vue$1.resolveComponent("NcDialog");
119044
119516
 
119045
119517
  return (vue$1.openBlock(), vue$1.createElementBlock("div", {
119046
- class: vue$1.normalizeClass(["cn-files-browser", { 'cn-files-browser--dragging': $data.dragging, 'cn-files-browser--drop-panel': $props.dropOverlay && $props.dropDetail !== '' }]),
119518
+ class: vue$1.normalizeClass(["cn-files-browser", { 'cn-files-browser--dragging': $data.dragging, 'cn-files-browser--drop-panel': $props.dropOverlay && $options.dropDetailTemplate !== '' }]),
119047
119519
  "data-testid": "cn-files-browser",
119048
119520
  onDragenter: _cache[21] || (_cache[21] = vue$1.withModifiers((...args) => ($options.onDragEnter && $options.onDragEnter(...args)), ["prevent"])),
119049
119521
  onDragover: _cache[22] || (_cache[22] = vue$1.withModifiers((...args) => ($options.onDragOver && $options.onDragOver(...args)), ["prevent"])),
@@ -119065,7 +119537,9 @@ function render$70(_ctx, _cache, $props, $setup, $data, $options) {
119065
119537
  ? (vue$1.openBlock(), vue$1.createElementBlock("p", _hoisted_5$4H, vue$1.toDisplayString($data.dropStatus), 1 /* TEXT */))
119066
119538
  : vue$1.createCommentVNode("v-if", true),
119067
119539
  vue$1.createElementVNode("div", _hoisted_6$4j, [
119068
- vue$1.createVNode(_component_NcBreadcrumbs, { class: "cn-files-browser__crumbs" }, {
119540
+ vue$1.createVNode(_component_NcBreadcrumbs, {
119541
+ class: vue$1.normalizeClass(["cn-files-browser__crumbs", { 'cn-files-browser__crumbs--at-root': $options.atRoot }])
119542
+ }, {
119069
119543
  default: vue$1.withCtx(() => [
119070
119544
  (vue$1.openBlock(true), vue$1.createElementBlock(vue$1.Fragment, null, vue$1.renderList($options.crumbs, (crumb, index) => {
119071
119545
  return (vue$1.openBlock(), vue$1.createBlock(_component_NcBreadcrumb, {
@@ -119082,7 +119556,7 @@ function render$70(_ctx, _cache, $props, $setup, $data, $options) {
119082
119556
  }), 128 /* KEYED_FRAGMENT */))
119083
119557
  ]),
119084
119558
  _: 1 /* STABLE */
119085
- }),
119559
+ }, 8 /* PROPS */, ["class"]),
119086
119560
  ($options.columnsChooserEnabled)
119087
119561
  ? (vue$1.openBlock(), vue$1.createBlock(_component_NcActions, {
119088
119562
  key: 0,
@@ -119497,7 +119971,7 @@ function render$70(_ctx, _cache, $props, $setup, $data, $options) {
119497
119971
  (vue$1.openBlock(true), vue$1.createElementBlock(vue$1.Fragment, null, vue$1.renderList($options.displayRows, ({ key, group, node }) => {
119498
119972
  return (vue$1.openBlock(), vue$1.createElementBlock(vue$1.Fragment, { key: key }, [
119499
119973
  group
119500
- ? (vue$1.openBlock(), vue$1.createElementBlock("tr", _hoisted_32$k, [
119974
+ ? (vue$1.openBlock(), vue$1.createElementBlock("tr", _hoisted_32$l, [
119501
119975
  vue$1.createElementVNode("th", {
119502
119976
  colspan: $options.columnCount,
119503
119977
  scope: "rowgroup",
@@ -120079,7 +120553,7 @@ function render$70(_ctx, _cache, $props, $setup, $data, $options) {
120079
120553
  }
120080
120554
 
120081
120555
  script$71.render = render$70;
120082
- script$71.__scopeId = "data-v-3a771a01";
120556
+ script$71.__scopeId = "data-v-23ff0221";
120083
120557
  const __sfc_main$6X = script$71;
120084
120558
 
120085
120559
  /**
@@ -120423,7 +120897,9 @@ var script$70 = {
120423
120897
  /** Forwarded to CnFilesBrowser: the drop state's line ("Laat los om toe te voegen"); the library's own without it. */
120424
120898
  dropLabel: { type: String, default: undefined },
120425
120899
  /** Forwarded to CnFilesBrowser: the drop state's second line, `{count}` the files dragged; it also makes the overlay fill the panel. */
120426
- dropDetail: { type: String, default: '' },
120900
+ dropDetail: { type: [String, Array], default: '' },
120901
+ /** Forwarded to CnFilesBrowser: named values filled into `dropDetail`. */
120902
+ dropDetailValues: { type: Object, default: null },
120427
120903
  /** Forwarded to CnFilesBrowser: "Or drag files onto this list." under the list. */
120428
120904
  dropHint: { type: Boolean, default: false },
120429
120905
  /**
@@ -121212,6 +121688,7 @@ function render$6$(_ctx, _cache, $props, $setup, $data, $options) {
121212
121688
  dropOverlay: $props.dropOverlay,
121213
121689
  dropLabel: $props.dropLabel,
121214
121690
  dropDetail: $props.dropDetail,
121691
+ dropDetailValues: $props.dropDetailValues,
121215
121692
  dropHint: $props.dropHint,
121216
121693
  rowActions: $props.rowActions,
121217
121694
  newActions: $props.newActions,
@@ -121235,7 +121712,7 @@ function render$6$(_ctx, _cache, $props, $setup, $data, $options) {
121235
121712
  groupBy: $props.groupBy,
121236
121713
  facets: $props.facets,
121237
121714
  onChanged: $options.onBrowserChanged
121238
- }, null, 8 /* PROPS */, ["rootPath", "rootLabel", "source", "deleteLabel", "uploadButton", "newMenu", "folderButton", "dropOverlay", "dropLabel", "dropDetail", "dropHint", "rowActions", "newActions", "headerActions", "rowButton", "reviewSummary", "footnote", "nameSecondary", "secondLine", "linkedItems", "columns", "rowData", "preferenceApp", "preferenceKey", "bulkActions", "selectionLabel", "selectionLabelOne", "showClearSelection", "sideCards", "sideCardsPlacement", "groupBy", "facets", "onChanged"]))
121715
+ }, null, 8 /* PROPS */, ["rootPath", "rootLabel", "source", "deleteLabel", "uploadButton", "newMenu", "folderButton", "dropOverlay", "dropLabel", "dropDetail", "dropDetailValues", "dropHint", "rowActions", "newActions", "headerActions", "rowButton", "reviewSummary", "footnote", "nameSecondary", "secondLine", "linkedItems", "columns", "rowData", "preferenceApp", "preferenceKey", "bulkActions", "selectionLabel", "selectionLabelOne", "showClearSelection", "sideCards", "sideCardsPlacement", "groupBy", "facets", "onChanged"]))
121239
121716
  : (vue$1.openBlock(), vue$1.createElementBlock(vue$1.Fragment, { key: 1 }, [
121240
121717
  ($data.uploadError)
121241
121718
  ? (vue$1.openBlock(), vue$1.createElementBlock("div", _hoisted_2$6w, vue$1.toDisplayString($data.uploadError), 1 /* TEXT */))
@@ -121486,7 +121963,7 @@ function render$6$(_ctx, _cache, $props, $setup, $data, $options) {
121486
121963
  }
121487
121964
 
121488
121965
  script$70.render = render$6$;
121489
- script$70.__scopeId = "data-v-89d80864";
121966
+ script$70.__scopeId = "data-v-569603d2";
121490
121967
  const __sfc_main$6W = script$70;
121491
121968
 
121492
121969
  /**
@@ -154518,7 +154995,7 @@ const _hoisted_31$k = {
154518
154995
  key: 12,
154519
154996
  class: "cn-form-dialog__switch-wrapper"
154520
154997
  };
154521
- const _hoisted_32$j = {
154998
+ const _hoisted_32$k = {
154522
154999
  key: 13,
154523
155000
  class: "cn-form-dialog__select-wrapper"
154524
155001
  };
@@ -155393,7 +155870,7 @@ function render$6c(_ctx, _cache, $props, $setup, $data, $options) {
155393
155870
  }, null, 8 /* PROPS */, ["id", "text", "more", "help", "label", "error"])
155394
155871
  ]))
155395
155872
  : (field.widget === 'date' || field.widget === 'datetime')
155396
- ? (vue$1.openBlock(), vue$1.createElementBlock("div", _hoisted_32$j, [
155873
+ ? (vue$1.openBlock(), vue$1.createElementBlock("div", _hoisted_32$k, [
155397
155874
  (!$options.showsOuterLabel(field))
155398
155875
  ? (vue$1.openBlock(), vue$1.createElementBlock("label", {
155399
155876
  key: 0,
@@ -165413,7 +165890,7 @@ const _hoisted_31$j = {
165413
165890
  key: 1,
165414
165891
  class: "cn-related-objects-widget__detail"
165415
165892
  };
165416
- const _hoisted_32$i = {
165893
+ const _hoisted_32$j = {
165417
165894
  key: 3,
165418
165895
  class: "cn-related-objects-widget__children",
165419
165896
  "data-testid": "cn-related-children"
@@ -165696,7 +166173,7 @@ function render$64(_ctx, _cache, $props, $setup, $data, $options) {
165696
166173
  : vue$1.createCommentVNode("v-if", true)
165697
166174
  ], 42 /* CLASS, PROPS, NEED_HYDRATION */, _hoisted_28$o)),
165698
166175
  (item.children && item.children.length)
165699
- ? (vue$1.openBlock(), vue$1.createElementBlock("ul", _hoisted_32$i, [
166176
+ ? (vue$1.openBlock(), vue$1.createElementBlock("ul", _hoisted_32$j, [
165700
166177
  (vue$1.openBlock(true), vue$1.createElementBlock(vue$1.Fragment, null, vue$1.renderList(item.children, (child) => {
165701
166178
  return (vue$1.openBlock(), vue$1.createElementBlock("li", {
165702
166179
  key: child.key
@@ -184745,18 +185222,19 @@ function render$5E(_ctx, _cache, $props, $setup, $data, $options) {
184745
185222
  scope: $options.resolvedScope,
184746
185223
  title: $options.resolvedTitle,
184747
185224
  maxDisplay: $options.resolvedMaxDisplay,
185225
+ layout: $props.content && typeof $props.content.layout === 'string' ? $props.content.layout : '',
184748
185226
  excludeActions: $options.resolvedExcludeActions,
184749
185227
  actionLabels: $options.actionLabels,
184750
185228
  valueLabels: $options.valueLabels,
184751
185229
  relatedSources: $options.relatedSources,
184752
185230
  footnote: $options.footnote
184753
- }, $options.emptyText ? { noEntriesLabel: $options.emptyText } : {}), null, 16 /* FULL_PROPS */, ["source", "endpoint", "register", "schema", "objectId", "scope", "title", "maxDisplay", "excludeActions", "actionLabels", "valueLabels", "relatedSources", "footnote"])
185231
+ }, $options.emptyText ? { noEntriesLabel: $options.emptyText } : {}), null, 16 /* FULL_PROPS */, ["source", "endpoint", "register", "schema", "objectId", "scope", "title", "maxDisplay", "layout", "excludeActions", "actionLabels", "valueLabels", "relatedSources", "footnote"])
184754
185232
  ]))
184755
185233
  : vue$1.createCommentVNode("v-if", true)
184756
185234
  }
184757
185235
 
184758
185236
  script$5F.render = render$5E;
184759
- script$5F.__scopeId = "data-v-3f7bbf0c";
185237
+ script$5F.__scopeId = "data-v-6387051e";
184760
185238
  const __sfc_main$5z = script$5F;
184761
185239
 
184762
185240
  /** Variants understood by NcNoteCard. */
@@ -189956,7 +190434,7 @@ function render$5t(_ctx, _cache, $props, $setup, $data, $options) {
189956
190434
  }
189957
190435
 
189958
190436
  script$5u.render = render$5t;
189959
- script$5u.__scopeId = "data-v-05cd7cb8";
190437
+ script$5u.__scopeId = "data-v-5f54dc93";
189960
190438
  const __sfc_main$5o = script$5u;
189961
190439
 
189962
190440
  /**
@@ -190925,6 +191403,10 @@ var script$5s = {
190925
191403
  return `cn-timeline-draft-${this.uid}`
190926
191404
  },
190927
191405
 
191406
+ blockId() {
191407
+ return `cn-timeline-block-${this.uid}`
191408
+ },
191409
+
190928
191410
  /**
190929
191411
  * The kind options, the plain note first. A note is an entry with NO
190930
191412
  * kind, so "Note" filters on its absence.
@@ -191438,8 +191920,9 @@ const _hoisted_26$w = { class: "cn-timeline-manage__subtitle" };
191438
191920
  const _hoisted_27$o = { class: "cn-timeline-manage__composer-title" };
191439
191921
  const _hoisted_28$n = { class: "cn-timeline-manage__composer-hint" };
191440
191922
  const _hoisted_29$l = ["for"];
191441
- const _hoisted_30$k = ["id", "placeholder"];
191442
- const _hoisted_31$i = { class: "cn-timeline-manage__composer-foot" };
191923
+ const _hoisted_30$k = ["for"];
191924
+ const _hoisted_31$i = ["id", "placeholder"];
191925
+ const _hoisted_32$i = { class: "cn-timeline-manage__composer-foot" };
191443
191926
 
191444
191927
  function render$5r(_ctx, _cache, $props, $setup, $data, $options) {
191445
191928
  const _component_Plus = vue$1.resolveComponent("Plus");
@@ -191696,8 +192179,15 @@ function render$5r(_ctx, _cache, $props, $setup, $data, $options) {
191696
192179
  ], 64 /* STABLE_FRAGMENT */))
191697
192180
  : vue$1.createCommentVNode("v-if", true),
191698
192181
  ($data.textBlocks.length)
191699
- ? (vue$1.openBlock(), vue$1.createBlock(_component_NcSelect, {
192182
+ ? (vue$1.openBlock(), vue$1.createElementBlock("label", {
191700
192183
  key: 1,
192184
+ class: "cn-timeline-manage__draft-label",
192185
+ for: $options.blockId
192186
+ }, vue$1.toDisplayString($options.t('nextcloud-vue', 'Template')), 9 /* TEXT, PROPS */, _hoisted_29$l))
192187
+ : vue$1.createCommentVNode("v-if", true),
192188
+ ($data.textBlocks.length)
192189
+ ? (vue$1.openBlock(), vue$1.createBlock(_component_NcSelect, {
192190
+ key: 2,
191701
192191
  modelValue: $data.chosenBlock,
191702
192192
  "onUpdate:modelValue": [
191703
192193
  _cache[2] || (_cache[2] = $event => (($data.chosenBlock) = $event)),
@@ -191707,25 +192197,27 @@ function render$5r(_ctx, _cache, $props, $setup, $data, $options) {
191707
192197
  options: $options.blockOptions,
191708
192198
  clearable: true,
191709
192199
  label: "label",
191710
- inputLabel: $options.t('nextcloud-vue', 'Template'),
192200
+ inputId: $options.blockId,
192201
+ labelOutside: true,
192202
+ ariaLabelCombobox: $options.t('nextcloud-vue', 'Template'),
191711
192203
  placeholder: $options.t('nextcloud-vue', 'Write your own'),
191712
192204
  "data-testid": "cn-timeline-block"
191713
- }, null, 8 /* PROPS */, ["modelValue", "options", "inputLabel", "placeholder", "onUpdate:modelValue"]))
192205
+ }, null, 8 /* PROPS */, ["modelValue", "options", "inputId", "ariaLabelCombobox", "placeholder", "onUpdate:modelValue"]))
191714
192206
  : vue$1.createCommentVNode("v-if", true),
191715
192207
  vue$1.createElementVNode("label", {
191716
192208
  class: "cn-timeline-manage__draft-label",
191717
192209
  for: $options.draftId
191718
- }, vue$1.toDisplayString($options.t('nextcloud-vue', 'Note')), 9 /* TEXT, PROPS */, _hoisted_29$l),
192210
+ }, vue$1.toDisplayString($options.t('nextcloud-vue', 'Note')), 9 /* TEXT, PROPS */, _hoisted_30$k),
191719
192211
  vue$1.withDirectives(vue$1.createElementVNode("textarea", {
191720
192212
  id: $options.draftId,
191721
192213
  "onUpdate:modelValue": _cache[3] || (_cache[3] = $event => (($data.draft) = $event)),
191722
192214
  class: "cn-timeline-manage__draft",
191723
192215
  placeholder: $options.t('nextcloud-vue', 'Write a note on this record'),
191724
192216
  "data-testid": "cn-timeline-draft"
191725
- }, null, 8 /* PROPS */, _hoisted_30$k), [
192217
+ }, null, 8 /* PROPS */, _hoisted_31$i), [
191726
192218
  [vue$1.vModelText, $data.draft]
191727
192219
  ]),
191728
- vue$1.createElementVNode("div", _hoisted_31$i, [
192220
+ vue$1.createElementVNode("div", _hoisted_32$i, [
191729
192221
  vue$1.createVNode(_component_NcCheckboxRadioSwitch, {
191730
192222
  modelValue: $data.draftIsPublic,
191731
192223
  "onUpdate:modelValue": _cache[4] || (_cache[4] = $event => (($data.draftIsPublic) = $event)),
@@ -191757,7 +192249,7 @@ function render$5r(_ctx, _cache, $props, $setup, $data, $options) {
191757
192249
  }
191758
192250
 
191759
192251
  script$5s.render = render$5r;
191760
- script$5s.__scopeId = "data-v-a4c73a6a";
192252
+ script$5s.__scopeId = "data-v-31e6673c";
191761
192253
  const __sfc_main$5m = script$5s;
191762
192254
 
191763
192255
  /**
@@ -194982,7 +195474,8 @@ var script$5k = {
194982
195474
 
194983
195475
  /**
194984
195476
  * The crumbs for CnBreadcrumbs: each declared crumb as a link, then the
194985
- * current page. Empty without a declared crumb.
195477
+ * current page, once (a last crumb that names the page is dropped).
195478
+ * Empty without a declared crumb.
194986
195479
  *
194987
195480
  * @spec openspec/changes/page-header-breadcrumb/specs/page-header/spec.md#requirement-a-list-dashboard-or-settings-page-can-show-a-breadcrumb-and-a-meta-note
194988
195481
  * @return {Array<object>}
@@ -195004,6 +195497,10 @@ var script$5k = {
195004
195497
  return entry
195005
195498
  });
195006
195499
  if (this.current) {
195500
+ // A last crumb naming the page itself is the current one, drawn once.
195501
+ if (out.length > 0 && out[out.length - 1].label === this.current) {
195502
+ out.pop();
195503
+ }
195007
195504
  out.push({ label: this.current });
195008
195505
  }
195009
195506
  return out
@@ -201124,6 +201621,7 @@ function render$5d(_ctx, _cache, $props, $setup, $data, $options) {
201124
201621
  ? (vue$1.openBlock(), vue$1.createBlock(_component_CnObjectDataWidget, {
201125
201622
  key: 1,
201126
201623
  title: $options.resolvedTitle,
201624
+ subtitle: $options.widgetSubtitle,
201127
201625
  chromeless: $options.isBare,
201128
201626
  showActions: !$options.isBare && $options.actionsShown,
201129
201627
  icon: $props.widget.icon || null,
@@ -201139,7 +201637,7 @@ function render$5d(_ctx, _cache, $props, $setup, $data, $options) {
201139
201637
  collapsedFields: $options.content.collapsedFields ?? null,
201140
201638
  footnote: $options.content.footnote || '',
201141
201639
  editable: $options.content.editable !== false
201142
- }, null, 8 /* PROPS */, ["title", "chromeless", "showActions", "icon", "schema", "objectData", "objectType", "store", "overrides", "include", "exclude", "hideEmpty", "columns", "collapsedFields", "footnote", "editable"]))
201640
+ }, null, 8 /* PROPS */, ["title", "subtitle", "chromeless", "showActions", "icon", "schema", "objectData", "objectType", "store", "overrides", "include", "exclude", "hideEmpty", "columns", "collapsedFields", "footnote", "editable"]))
201143
201641
  : ($options.isRelated)
201144
201642
  ? (vue$1.openBlock(), vue$1.createBlock(_component_CnRelatedObjectsWidget, {
201145
201643
  key: 2,
@@ -201675,7 +202173,7 @@ function render$5d(_ctx, _cache, $props, $setup, $data, $options) {
201675
202173
  }
201676
202174
 
201677
202175
  script$5e.render = render$5d;
201678
- script$5e.__scopeId = "data-v-10c797a6";
202176
+ script$5e.__scopeId = "data-v-38f1ce74";
201679
202177
  const __sfc_main$58 = script$5e;
201680
202178
 
201681
202179
  /**
@@ -236927,6 +237425,8 @@ var script$48 = {
236927
237425
  cnDispatchAction: { default: null },
236928
237426
  /** The page's object sidebar channel; a `link.sidebarTab` opens one of its tabs. */
236929
237427
  objectSidebarState: { default: null },
237428
+ /** The records the detail page reads beside the record (`@context.<name>`), for a `labelPath`. */
237429
+ cnDetailVisibilityRows: { default: null },
236930
237430
  },
236931
237431
 
236932
237432
  props: {
@@ -236943,13 +237443,14 @@ var script$48 = {
236943
237443
  * `route` (`{ name, params?, query? }`, `@source.<path>` in a param) on a `title` or a `row` links its value to that route; a param that does not fill leaves it plain.
236944
237444
  * `format: 'user'` shows a Nextcloud user id as the user's display name, read once per id; the entry stays empty until the name is known.
236945
237445
  * `template` ("{available} {unit}") fills its `{path}` placeholders from the record instead of reading `path`; it is empty when every placeholder is. `suffix` (" kg") is added to a value that is not empty.
237446
+ * `labelPath` ("@context.caseType.handlerLabel") names a value on the record or the page's `@context` records that labels the row when it holds text; `label` is the fallback.
236946
237447
  * `emptyValue` ("No") is shown, translated, when the entry has no value, so the entry stays drawn whatever `hideEmpty` says (an override that was never set reads "No").
236947
237448
  * - `action` — an action drawn as a button under the facts; `headerAction` — one drawn in the card header (reported through the `header` event).
236948
237449
  * - `actions` — action buttons under the facts in the `headerActions` shape (`api-call`, `open-form`, `navigate`, `open-modal`, ...; `confirm`, `variant`). `@source.<field>` names a field of the record shown, and an action whose token names an empty field is not drawn. `visibleWhen` reads the record shown; `adminOnly: true` draws the action for an instance admin only (visibility, never authorisation). An api-call or a saved form refreshes the page, and the facts read their source again.
236949
237450
  * - `rowsPath` — a path to a list of `{ label, value }` the record holds, drawn as rows after `fields` (a preview the server builds).
236950
237451
  * - `headerPill` — a status pill in the card header (reported through the `header` event): `{ path?, text?, map?, variant?, variantMap?, colorMap? }`, read from the record like a `pill` entry (DqBezwaar "Advies ontvangen"); nothing shows while the value is empty.
236951
237452
  * - `notice` — `{ text, variant? }`, a note band inside the card under the facts (`info` by default; `success`, `warning` or `error`); the text is translated.
236952
- * `format` is `text` (default), `date` (board short date), `date-long` (always with the year), `list` (an array joined by ", ", each item read at `itemPath`), `bytes` (a size, "1.5 MB"), `number` (in the reader's language, `decimals` fraction digits when set) or `currency` (a money amount in the reader's language, "€ 1.234,50": the code in `currency`, else the record's `currencyField`, else the app's reporting currency, else EUR; `decimals` defaults to 2).
237453
+ * `format` is `text` (default), `date` (board short date), `date-long` (always with the year), `longdate` (the month written out, the year only outside this year: "3 oktober"), `list` (an array joined by ", ", each item read at `itemPath`), `bytes` (a size, "1.5 MB"), `number` (in the reader's language, `decimals` fraction digits when set) or `currency` (a money amount in the reader's language, "€ 1.234,50": the code in `currency`, else the record's `currencyField`, else the app's reporting currency, else EUR; `decimals` defaults to 2).
236953
237454
  * `map` turns a raw value into a label (translated). `parts` (on a `line`) lists paths, or `{ path, label?, format? }`, joined by `separator` (default " · "); empty parts are dropped.
236954
237455
  * - `source` — `{ register, schema, id }` or `{ url }`; omitted = the current object. `{ register, schema, filter, sort? }` without `id` reads the first object that matches `filter` in `sort` order (`{ field, dir }`): the latest count of a shift. An entry with `from: "object"` reads the current object even then (a client card that also shows the ticket's channel).
236955
237456
  * - `endpointSource` — `{ url, method?, params?, responsePath? }`, the block a stat or chart takes: the facts read an app endpoint, shared and cached like those.
@@ -237233,7 +237734,7 @@ var script$48 = {
237233
237734
  }
237234
237735
  if (kind === 'row') {
237235
237736
  const last = out[out.length - 1];
237236
- const row = { key, label: this.tr(field.label || ''), value, ...this.rowExtras(record, field, value) };
237737
+ const row = { key, label: this.labelOf(record, field), value, ...this.rowExtras(record, field, value) };
237237
237738
  if (field.route && !row.href) {
237238
237739
  row.to = this.resolveRoute(field.route, record);
237239
237740
  }
@@ -237917,6 +238418,30 @@ var script$48 = {
237917
238418
  }
237918
238419
  },
237919
238420
 
238421
+ /**
238422
+ * A row's label: the value at `labelPath` (the record, or the page's
238423
+ * `@context.<name>` records) when it holds text, else `label`, both
238424
+ * through the host translate. A case type can name its handler
238425
+ * ("Regisseur") while another keeps "Behandelaar".
238426
+ *
238427
+ * @param {object} record The record shown.
238428
+ * @param {object} field The entry.
238429
+ * @return {string}
238430
+ * @spec openspec/changes/facts-label-from-path/specs/facts-widget/spec.md#requirement-a-facts-row-can-take-its-label-from-the-record-or-its-context
238431
+ */
238432
+ labelOf(record, field) {
238433
+ if (typeof field.labelPath === 'string' && field.labelPath !== '') {
238434
+ const rows = this.cnDetailVisibilityRows && typeof this.cnDetailVisibilityRows === 'object' && 'value' in this.cnDetailVisibilityRows
238435
+ ? this.cnDetailVisibilityRows.value
238436
+ : this.cnDetailVisibilityRows;
238437
+ const named = readPath$8({ ...(record || {}), '@context': rows || {} }, field.labelPath);
238438
+ if (typeof named === 'string' && named.trim() !== '') {
238439
+ return this.tr(named.trim())
238440
+ }
238441
+ }
238442
+ return this.tr(field.label || '')
238443
+ },
238444
+
237920
238445
  /**
237921
238446
  * Copy a row's value to the clipboard.
237922
238447
  *
@@ -238286,6 +238811,10 @@ var script$48 = {
238286
238811
  .filter((item) => item !== '');
238287
238812
  return items.join(', ')
238288
238813
  }
238814
+ // The month written out, the year only outside this year: "3 oktober".
238815
+ if (format === 'longdate') {
238816
+ return formatLongDate(raw)
238817
+ }
238289
238818
  if (format === 'date' || format === 'date-long') {
238290
238819
  const date = parseDateValue(raw);
238291
238820
  if (date === null) {
@@ -238792,7 +239321,7 @@ function render$47(_ctx, _cache, $props, $setup, $data, $options) {
238792
239321
  }
238793
239322
 
238794
239323
  script$48.render = render$47;
238795
- script$48.__scopeId = "data-v-1b8f8e6f";
239324
+ script$48.__scopeId = "data-v-b1b0c69e";
238796
239325
  const __sfc_main$48 = script$48;
238797
239326
 
238798
239327
  /**
@@ -242159,7 +242688,7 @@ function render$42(_ctx, _cache, $props, $setup, $data, $options) {
242159
242688
  }
242160
242689
 
242161
242690
  script$43.render = render$42;
242162
- script$43.__scopeId = "data-v-3d97a9f0";
242691
+ script$43.__scopeId = "data-v-dd87442e";
242163
242692
  const __sfc_main$43 = script$43;
242164
242693
 
242165
242694
  /**
@@ -251182,7 +251711,7 @@ function unwrap$1(value) {
251182
251711
  * `rowRoute`, `pageControls`), or `endpointSource` (an app endpoint whose
251183
251712
  * payload, after `responsePath`, is the array of rows, as on the object table), or `objectRows`
251184
251713
  * (`{ path, where?, valuePath? }`: rows the page record holds, such as one answer of a case); `avatar` puts a circle with the initials of a name
251185
- * template before the title; what differs is the drawing: `presentation` is `rows`, `feed`
251714
+ * template before the title (`{ text, size: 32 }` draws the 32px circle 12px from the title, as DqZaakBesluiten); what differs is the drawing: `presentation` is `rows`, `feed`
251186
251715
  * or `inline`, and each line is a template (`"{identifier} · {caseTypeName}"`,
251187
251716
  * `"Termijn {deadline|date}"`). `cards` draws a framed card per row in a
251188
251717
  * grid, with `trailing` as the large figure (board ShBank's accounts).
@@ -251378,6 +251907,17 @@ var script$3Q = {
251378
251907
  },
251379
251908
 
251380
251909
  computed: {
251910
+ /**
251911
+ * Whether the avatar is the 32px circle (`avatar.size: 32`).
251912
+ *
251913
+ * @return {boolean}
251914
+ * @spec openspec/changes/record-list-avatar-size/specs/record-list-avatar/spec.md#requirement-a-record-list-avatar-can-be-the-small-circle
251915
+ */
251916
+ avatarSmall() {
251917
+ const avatar = this.content?.avatar;
251918
+ return Boolean(avatar && typeof avatar === 'object' && Number(avatar.size) === 32)
251919
+ },
251920
+
251381
251921
  /** @return {boolean} Whether a row's pill comes before its title (`pillAt: "start"`). */
251382
251922
  pillFirst() {
251383
251923
  return this.content?.pillAt === 'start'
@@ -253877,7 +254417,7 @@ function render$3P(_ctx, _cache, $props, $setup, $data, $options) {
253877
254417
  (group.items.length > 0)
253878
254418
  ? (vue$1.openBlock(), vue$1.createElementBlock("ul", {
253879
254419
  key: 2,
253880
- class: "cn-record-list__list",
254420
+ class: vue$1.normalizeClass(["cn-record-list__list", { 'cn-record-list__list--avatar-small': $options.avatarSmall }]),
253881
254421
  "aria-labelledby": group.label ? group.headingId : null,
253882
254422
  "data-testid": $options.isGrouped ? 'cn-record-list-group' : null
253883
254423
  }, [
@@ -254252,7 +254792,7 @@ function render$3P(_ctx, _cache, $props, $setup, $data, $options) {
254252
254792
  : vue$1.createCommentVNode("v-if", true)
254253
254793
  ]))
254254
254794
  }), 128 /* KEYED_FRAGMENT */))
254255
- ], 8 /* PROPS */, _hoisted_23$u))
254795
+ ], 10 /* CLASS, PROPS */, _hoisted_23$u))
254256
254796
  : vue$1.createCommentVNode("v-if", true)
254257
254797
  ], 64 /* STABLE_FRAGMENT */))
254258
254798
  }), 128 /* KEYED_FRAGMENT */)),
@@ -254385,7 +254925,7 @@ function render$3P(_ctx, _cache, $props, $setup, $data, $options) {
254385
254925
  }
254386
254926
 
254387
254927
  script$3Q.render = render$3P;
254388
- script$3Q.__scopeId = "data-v-2c65cbc2";
254928
+ script$3Q.__scopeId = "data-v-544b79cd";
254389
254929
  const __sfc_main$3Q = script$3Q;
254390
254930
 
254391
254931
  /**
@@ -318104,7 +318644,7 @@ function render$2C(_ctx, _cache, $props, $setup, $data, $options) {
318104
318644
  }
318105
318645
 
318106
318646
  script$2D.render = render$2C;
318107
- script$2D.__scopeId = "data-v-cfc2a11a";
318647
+ script$2D.__scopeId = "data-v-51150930";
318108
318648
  const __sfc_main$2D = script$2D;
318109
318649
 
318110
318650
  /**
@@ -321790,6 +322330,16 @@ var script$2A = {
321790
322330
  type: Number,
321791
322331
  default: 0,
321792
322332
  },
322333
+
322334
+ /**
322335
+ * The board look's gap in px between a card's title and its
322336
+ * description, when the app's board draws it other than 4px; the
322337
+ * content follows 10px further (DqBeheerinstellingen 6, so 16).
322338
+ */
322339
+ descGap: {
322340
+ type: Number,
322341
+ default: 0,
322342
+ },
321793
322343
  },
321794
322344
 
321795
322345
  emits: ['update', 'reimported', 'reimport-error', 'tab-change'],
@@ -321828,6 +322378,23 @@ var script$2A = {
321828
322378
  },
321829
322379
 
321830
322380
  computed: {
322381
+ /**
322382
+ * The board look sizes an app's board sets on the shell
322383
+ * (`versionTitleSize`, `descGap`), as CSS custom properties.
322384
+ *
322385
+ * @return {object|null} The style, or null when none is set.
322386
+ */
322387
+ shellStyle() {
322388
+ const style = {};
322389
+ if (this.versionTitleSize) {
322390
+ style['--cn-board-version-title-size'] = `${this.versionTitleSize}px`;
322391
+ }
322392
+ if (this.descGap) {
322393
+ style['--cn-board-settings-desc-gap'] = `${this.descGap}px`;
322394
+ }
322395
+ return Object.keys(style).length > 0 ? style : null
322396
+ },
322397
+
321831
322398
  /**
321832
322399
  * The tabs that have an id and a label.
321833
322400
  *
@@ -322167,7 +322734,7 @@ function render$2z(_ctx, _cache, $props, $setup, $data, $options) {
322167
322734
 
322168
322735
  return (vue$1.openBlock(), vue$1.createElementBlock("div", {
322169
322736
  class: vue$1.normalizeClass(["cn-admin-settings-shell", [$setup.ownLookClass, $props.sectionColumns ? `cn-admin-settings-shell--columns-${$props.sectionColumns}` : '']]),
322170
- style: vue$1.normalizeStyle($props.versionTitleSize ? { '--cn-board-version-title-size': `${$props.versionTitleSize}px` } : null)
322737
+ style: vue$1.normalizeStyle($options.shellStyle)
322171
322738
  }, [
322172
322739
  ($setup.environmentName)
322173
322740
  ? (vue$1.openBlock(), vue$1.createBlock(_component_CnEnvironmentBanner, {
@@ -322453,7 +323020,7 @@ function render$2z(_ctx, _cache, $props, $setup, $data, $options) {
322453
323020
  }
322454
323021
 
322455
323022
  script$2A.render = render$2z;
322456
- script$2A.__scopeId = "data-v-447d33ea";
323023
+ script$2A.__scopeId = "data-v-69055093";
322457
323024
  const __sfc_main$2A = script$2A;
322458
323025
 
322459
323026
  /**
@@ -343271,15 +343838,15 @@ function buildViewTree({ views = [], labelFilter = '', maxDepth = 3 } = {}) {
343271
343838
  }
343272
343839
  }
343273
343840
 
343274
- // Seeded roots first, then the reader's own, each alphabetically. A
343275
- // dropdown whose order changes between two openings is a dropdown nobody
343276
- // can build a habit with.
343841
+ // Seeded roots first, in the order the app declares them, then the
343842
+ // reader's own in the order they were saved (DqFilterBeheren). Both are
343843
+ // stable between two openings, so a person can build a habit with them.
343277
343844
  const seededRoots = roots.filter(({ view }) => view?.seeded === true);
343278
343845
  const ownRoots = roots.filter(({ view }) => view?.seeded !== true);
343279
- for (const { view, orphaned } of sortRootsByName(seededRoots)) {
343846
+ for (const { view, orphaned } of seededRoots) {
343280
343847
  emit(view, 0, orphaned);
343281
343848
  }
343282
- for (const { view, orphaned } of sortRootsByName(ownRoots)) {
343849
+ for (const { view, orphaned } of sortRootsBySaved(ownRoots)) {
343283
343850
  emit(view, 0, orphaned);
343284
343851
  }
343285
343852
 
@@ -343335,13 +343902,28 @@ function sortByName(views) {
343335
343902
  }
343336
343903
 
343337
343904
  /**
343338
- * Root entries by the name of the view they carry.
343905
+ * Root entries in the order their views were saved (`created`, oldest
343906
+ * first); views without a saved time follow, by name.
343339
343907
  *
343340
343908
  * @param {Array<object>} roots - The root entries.
343341
343909
  * @return {Array<object>} The same entries, sorted.
343342
343910
  */
343343
- function sortRootsByName(roots) {
343344
- return [...roots].sort((left, right) => String(left.view?.name ?? '').localeCompare(String(right.view?.name ?? '')))
343911
+ function sortRootsBySaved(roots) {
343912
+ const savedAt = (entry) => (typeof entry.view?.created === 'string' ? entry.view.created : '');
343913
+ return [...roots].sort((left, right) => {
343914
+ const a = savedAt(left);
343915
+ const b = savedAt(right);
343916
+ if (a !== b) {
343917
+ if (a === '') {
343918
+ return 1
343919
+ }
343920
+ if (b === '') {
343921
+ return -1
343922
+ }
343923
+ return a < b ? -1 : 1
343924
+ }
343925
+ return String(left.view?.name ?? '').localeCompare(String(right.view?.name ?? ''))
343926
+ })
343345
343927
  }
343346
343928
 
343347
343929
  /**
@@ -351913,6 +352495,18 @@ function useSelfFetchList(props, instance, inject, extras = {}) {
351913
352495
  // a reactive getter so a runtime flip attaches/detaches accordingly.
351914
352496
  // Stores without live-updates support (no `subscribe` action) are a
351915
352497
  // silent no-op inside the composable, keeping this fully inert.
352498
+ // An address carrying `@myTeam` (a shared link) waits for the team, as a
352499
+ // saved view on it does: once read, the token becomes the team, or goes
352500
+ // for a reader in none.
352501
+ const carriesMyTeam = Object.values(initialActiveFilters || {})
352502
+ .some((value) => value === MY_TEAM_TOKEN || (Array.isArray(value) && value.includes(MY_TEAM_TOKEN)));
352503
+ if (carriesMyTeam) {
352504
+ loadMyTeam().then(() => {
352505
+ list.activeFilters.value = dropOptionalUnresolved(resolveFilterTokens(list.activeFilters.value, tokenCtx()));
352506
+ list.refresh(1);
352507
+ });
352508
+ }
352509
+
351916
352510
  useObjectSubscription(objectStore, () => objectType.value, null, {
351917
352511
  enabled: () => props.subscribe !== false,
351918
352512
  });
@@ -353579,6 +354173,17 @@ var script$20 = {
353579
354173
  default: null,
353580
354174
  },
353581
354175
 
354176
+ /**
354177
+ * The leading icon's tile tone in the board look (`primary`, `teal`,
354178
+ * `neutral`), from `pages[].config.rowIconTone`. Forwarded to CnDataTable.
354179
+ *
354180
+ * @type {string}
354181
+ */
354182
+ rowIconTone: {
354183
+ type: String,
354184
+ default: 'primary',
354185
+ },
354186
+
353582
354187
  /** Columns to exclude in schema mode */
353583
354188
  excludeColumns: {
353584
354189
  type: Array,
@@ -356816,6 +357421,7 @@ var script$20 = {
356816
357421
  r: this.register,
356817
357422
  s: this.exportSchemaSlug,
356818
357423
  f: this.filter || null,
357424
+ a: this.effectiveActiveFilters || null,
356819
357425
  e: this.countEntries,
356820
357426
  // The store's total, not the error override in effectivePagination,
356821
357427
  // so a failed fetch and its recovery do not refetch the counts.
@@ -358898,7 +359504,9 @@ var script$20 = {
358898
359504
  return [
358899
359505
  ...this.searchTermChips,
358900
359506
  ...this.quickFilterActiveChips,
358901
- ...this.filterChipsOf(this.effectiveActiveFilters, (key, value) => this.isFixedFilter(key, value) || ownToView(key, value)),
359507
+ // The folder pane's own filter is not a chip: the selected folder
359508
+ // shows in the pane and as the heading above the list (DqAfdelingen).
359509
+ ...this.filterChipsOf(this.effectiveActiveFilters, (key, value) => this.isFixedFilter(key, value) || ownToView(key, value) || this.isFolderFilter(key)),
358902
359510
  ]
358903
359511
  },
358904
359512
 
@@ -360084,6 +360692,18 @@ var script$20 = {
360084
360692
  * @return {boolean}
360085
360693
  * @spec openspec/changes/index-scope-presentation/specs/index-page/spec.md#requirement-the-query-that-chose-a-preset-is-not-a-removable-filter
360086
360694
  */
360695
+ /**
360696
+ * Whether a filter key is the folder pane's (`folderSidebar.filterField`).
360697
+ *
360698
+ * @param {string} key The filter key.
360699
+ * @return {boolean}
360700
+ * @spec openspec/changes/board-folder-scope-outside-card/specs/index-page/spec.md#requirement-the-selected-folder-heads-the-list-from-outside-its-card
360701
+ */
360702
+ isFolderFilter(key) {
360703
+ const field = this.folderSidebar && this.folderSidebar.filterField;
360704
+ return typeof field === 'string' && field !== '' && key === field
360705
+ },
360706
+
360087
360707
  isFixedFilter(key, value) {
360088
360708
  const fixed = this.fixedFilters;
360089
360709
  if (!fixed || !Object.hasOwn(fixed, key)) {
@@ -360406,7 +361026,15 @@ var script$20 = {
360406
361026
  const counts = await fetchFilterCounts({
360407
361027
  register: this.register,
360408
361028
  schema,
360409
- entries: this.countEntries.map((entry) => ({ key: entry.key, filter: resolveFilterMap(entry.filter, params, ctx) })),
361029
+ // A quick filter counts within the list as filtered (the
361030
+ // active filters, its own field its own); a saved view counts
361031
+ // its own query.
361032
+ entries: this.countEntries.map((entry) => ({
361033
+ key: entry.key,
361034
+ filter: entry.key.startsWith('tab:')
361035
+ ? { ...(this.effectiveActiveFilters || {}), ...resolveFilterMap(entry.filter, params, ctx) }
361036
+ : resolveFilterMap(entry.filter, params, ctx),
361037
+ })),
360410
361038
  baseFilter: resolveFilterMap(this.filter, params, ctx),
360411
361039
  ctx,
360412
361040
  });
@@ -365902,6 +366530,7 @@ function render$1$(_ctx, _cache, $props, $setup, $data, $options) {
365902
366530
  columns: $options.renderedColumns,
365903
366531
  pinnedCount: $options.pinnedColumnCount,
365904
366532
  rowIcon: $props.rowIcon,
366533
+ rowIconTone: $props.rowIconTone,
365905
366534
  rowIndicators: $props.rowIndicators,
365906
366535
  rowIndicatorCap: $props.rowIndicatorCap,
365907
366536
  rows: $options.displayObjects,
@@ -366049,7 +366678,7 @@ function render$1$(_ctx, _cache, $props, $setup, $data, $options) {
366049
366678
  key: "2"
366050
366679
  }
366051
366680
  : undefined
366052
- ]), 1032 /* PROPS, DYNAMIC_SLOTS */, ["schema", "filterChips", "columns", "pinnedCount", "rowIcon", "rowIndicators", "rowIndicatorCap", "rows", "sortKey", "sortOrder", "sortKeys", "selectable", "hideHeader", "rowClickToView", "rowClickRoute", "selectedIds", "rowKey", "emptyText", "excludeColumns", "includeColumns", "columnOverrides", "rowClass", "rowTitle", "showUnread", "filterable", "filterSchema", "activeFilters", "filterRegister", "onColumnFilter", "onSort", "onSelect", "onRowClick", "onRowAuxClick", "onRowContextMenu"]))
366681
+ ]), 1032 /* PROPS, DYNAMIC_SLOTS */, ["schema", "filterChips", "columns", "pinnedCount", "rowIcon", "rowIconTone", "rowIndicators", "rowIndicatorCap", "rows", "sortKey", "sortOrder", "sortKeys", "selectable", "hideHeader", "rowClickToView", "rowClickRoute", "selectedIds", "rowKey", "emptyText", "excludeColumns", "includeColumns", "columnOverrides", "rowClass", "rowTitle", "showUnread", "filterable", "filterSchema", "activeFilters", "filterRegister", "onColumnFilter", "onSort", "onSelect", "onRowClick", "onRowAuxClick", "onRowContextMenu"]))
366053
366682
  : ($data.currentViewMode === 'map' && $options.mapListEnabled)
366054
366683
  ? (vue$1.openBlock(), vue$1.createElementBlock("div", _hoisted_42$3, [
366055
366684
  vue$1.createVNode(_component_CnMapWidget, {
@@ -477735,8 +478364,8 @@ exports.CnDataTable = __sfc_main$7Y;
477735
478364
  exports.CnDateAxisView = __sfc_main$2x;
477736
478365
  exports.CnDateRangePicker = __sfc_main$2e;
477737
478366
  exports.CnDecisionListWidget = __sfc_main$5x;
477738
- exports.CnDeckCardCreate = __sfc_main$78;
477739
- exports.CnDeckCardPicker = __sfc_main$77;
478367
+ exports.CnDeckCardCreate = __sfc_main$79;
478368
+ exports.CnDeckCardPicker = __sfc_main$78;
477740
478369
  exports.CnDeleteDialog = __sfc_main$2g;
477741
478370
  exports.CnDeltaWidget = __sfc_main$4q;
477742
478371
  exports.CnDeltaWidgetForm = __sfc_main$4r;