@conduction/nextcloud-vue 2.144.0 → 2.145.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 (85) hide show
  1. package/dist/esm/components/CnActionDialog/CnActionDialog.vue.js +1 -1
  2. package/dist/esm/components/CnActionDialog/CnActionDialog.vue2.js.map +1 -1
  3. package/dist/esm/components/CnActionDialog/CnActionDialog.vue3.js +1 -0
  4. package/dist/esm/components/CnActionDialog/CnActionDialog.vue3.js.map +1 -1
  5. package/dist/esm/components/CnAuditTrailCard/CnAuditTrailCard.vue.js +1 -1
  6. package/dist/esm/components/CnAuditTrailCard/CnAuditTrailCard.vue2.js +55 -2
  7. package/dist/esm/components/CnAuditTrailCard/CnAuditTrailCard.vue2.js.map +1 -1
  8. package/dist/esm/components/CnAuditTrailCard/CnAuditTrailCard.vue3.js.map +1 -1
  9. package/dist/esm/components/CnAuditTrailWidget/CnAuditTrailWidget.vue.js +1 -1
  10. package/dist/esm/components/CnAuditTrailWidget/CnAuditTrailWidget.vue2.js +16 -0
  11. package/dist/esm/components/CnAuditTrailWidget/CnAuditTrailWidget.vue2.js.map +1 -1
  12. package/dist/esm/components/CnAuditTrailWidget/CnAuditTrailWidget.vue3.js +3 -1
  13. package/dist/esm/components/CnAuditTrailWidget/CnAuditTrailWidget.vue3.js.map +1 -1
  14. package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHeaderItems.vue.js +1 -1
  15. package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHeaderItems.vue2.js +1 -1
  16. package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHeaderItems.vue2.js.map +1 -1
  17. package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHeaderItems.vue3.js +3 -3
  18. package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHeaderItems.vue3.js.map +1 -1
  19. package/dist/esm/components/CnFieldListWidget/CnFieldListWidget.vue.js +1 -1
  20. package/dist/esm/components/CnFieldListWidget/CnFieldListWidget.vue2.js +2 -2
  21. package/dist/esm/components/CnFieldListWidget/CnFieldListWidget.vue2.js.map +1 -1
  22. package/dist/esm/components/CnFieldListWidget/CnFieldListWidget.vue3.js.map +1 -1
  23. package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js +6 -3
  24. package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js.map +1 -1
  25. package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js.map +1 -1
  26. package/dist/esm/components/CnMailTab/CnMailTab.vue.js +1 -1
  27. package/dist/esm/components/CnMailTab/CnMailTab.vue2.js.map +1 -1
  28. package/dist/esm/components/CnMailTab/CnMailTab.vue3.js +2 -2
  29. package/dist/esm/components/CnMailTab/CnMailTab.vue3.js.map +1 -1
  30. package/dist/esm/components/CnNotificationMatrix/CnNotificationMatrix.vue.js +1 -1
  31. package/dist/esm/components/CnNotificationMatrix/CnNotificationMatrix.vue2.js.map +1 -1
  32. package/dist/esm/components/CnNotificationMatrix/CnNotificationMatrix.vue3.js.map +1 -1
  33. package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue.js +1 -1
  34. package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue2.js +73 -12
  35. package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue2.js.map +1 -1
  36. package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue3.js +165 -126
  37. package/dist/esm/components/CnRecordListWidget/CnRecordListWidget.vue3.js.map +1 -1
  38. package/dist/esm/components/CnSettingsField/CnSettingsField.vue.js +1 -1
  39. package/dist/esm/components/CnSettingsField/CnSettingsField.vue2.js +14 -0
  40. package/dist/esm/components/CnSettingsField/CnSettingsField.vue2.js.map +1 -1
  41. package/dist/esm/components/CnSettingsField/CnSettingsField.vue3.js +2 -1
  42. package/dist/esm/components/CnSettingsField/CnSettingsField.vue3.js.map +1 -1
  43. package/dist/esm/components/CnWidgetObjectTable/CnWidgetObjectTable.vue.js +1 -1
  44. package/dist/esm/components/CnWidgetObjectTable/CnWidgetObjectTable.vue2.js +13 -8
  45. package/dist/esm/components/CnWidgetObjectTable/CnWidgetObjectTable.vue2.js.map +1 -1
  46. package/dist/esm/components/CnWidgetObjectTable/CnWidgetObjectTable.vue3.js.map +1 -1
  47. package/dist/esm/components/CnWorkspaceFilterWidget/CnWorkspaceFilterWidget.vue.js +1 -1
  48. package/dist/esm/components/CnWorkspaceFilterWidget/CnWorkspaceFilterWidget.vue2.js +10 -2
  49. package/dist/esm/components/CnWorkspaceFilterWidget/CnWorkspaceFilterWidget.vue2.js.map +1 -1
  50. package/dist/esm/components/CnWorkspaceFilterWidget/CnWorkspaceFilterWidget.vue3.js.map +1 -1
  51. package/dist/esm/composables/indexSources.js +35 -9
  52. package/dist/esm/composables/indexSources.js.map +1 -1
  53. package/dist/esm/l10n/nl.json.js +2 -0
  54. package/dist/esm/l10n/nl.json.js.map +1 -1
  55. package/dist/esm/library-style.js +1 -1
  56. package/dist/esm/nextcloud-vue.css +742 -326
  57. package/dist/esm/utils/builtInFormatters.js +18 -1
  58. package/dist/esm/utils/builtInFormatters.js.map +1 -1
  59. package/dist/esm/utils/localHeaderRows.js +95 -0
  60. package/dist/esm/utils/localHeaderRows.js.map +1 -0
  61. package/dist/nextcloud-vue.cjs.js +514 -179
  62. package/dist/nextcloud-vue.cjs.js.map +2 -2
  63. package/dist/nextcloud-vue.css +742 -326
  64. package/l10n/nl.json +2 -0
  65. package/package.json +1 -1
  66. package/src/components/CnActionDialog/CnActionDialog.vue +8 -1
  67. package/src/components/CnAuditTrailCard/CnAuditTrailCard.vue +55 -2
  68. package/src/components/CnAuditTrailWidget/CnAuditTrailWidget.vue +18 -0
  69. package/src/components/CnDetailWidgetHost/CnDetailWidgetHeaderItems.vue +2 -1
  70. package/src/components/CnFieldListWidget/CnFieldListWidget.vue +2 -2
  71. package/src/components/CnIndexPage/CnIndexPage.vue +6 -3
  72. package/src/components/CnMailTab/CnMailTab.vue +6 -4
  73. package/src/components/CnNotificationMatrix/CnNotificationMatrix.vue +4 -1
  74. package/src/components/CnRecordListWidget/CnRecordListWidget.vue +131 -20
  75. package/src/components/CnSettingsField/CnSettingsField.vue +15 -0
  76. package/src/components/CnWidgetObjectTable/CnWidgetObjectTable.vue +13 -8
  77. package/src/components/CnWorkspaceFilterWidget/CnWorkspaceFilterWidget.vue +10 -2
  78. package/src/composables/indexSources.js +35 -9
  79. package/src/css/dialog.css +18 -9
  80. package/src/css/look-board-detail.css +219 -23
  81. package/src/css/look-board-index.css +38 -4
  82. package/src/css/look-board.css +138 -8
  83. package/src/css/table.css +8 -1
  84. package/src/utils/builtInFormatters.js +17 -0
  85. package/src/utils/localHeaderRows.js +91 -0
@@ -1109,7 +1109,9 @@ function fillRowTemplate(template, row) {
1109
1109
  * template, "{case.title}") or `linkedField` (a path) fills the "Linked"
1110
1110
  * column, drawn when a kind declares one; `sourceConfig.linkedLabel` names it.
1111
1111
  * `subtitleTemplate` ("Case {identifier}", translated) fills the line under a
1112
- * result, else `subtitleField`.
1112
+ * result, else `subtitleField`; `subtitleResolve` (`{ field, schema, labelField,
1113
+ * as }`) names a referenced object for it as `{as}`. `sourceConfig.titleWrap`
1114
+ * wraps a long result title instead of cutting it.
1113
1115
  * `linkedUser: true` reads that value as a user id and shows the user's
1114
1116
  * display name. `sourceConfig.columnWidths` sets a width per column key.
1115
1117
  * The page's title and count line can name the term as `{term}`, and the
@@ -1226,9 +1228,32 @@ function searchSource(config = {}, context = {}) {
1226
1228
  return ''
1227
1229
  }
1228
1230
 
1229
- const subtitleOf = (kind, object) => {
1231
+ // `subtitleResolve`: `{ field, schema, register?, labelField?, as }` names
1232
+ // the object a reference points at, for the subtitle template as `{as}`.
1233
+ const subtitleLabels = async (kind) => {
1234
+ const resolve = kind.subtitleResolve
1235
+ if (!resolve || !resolve.schema || !resolve.field) {
1236
+ return null
1237
+ }
1238
+ const objects = await fetchReferenceObjects({ register: resolve.register || kind.register, schema: resolve.schema }).catch(() => [])
1239
+ const labels = new Map()
1240
+ for (const object of objects) {
1241
+ const id = object.id || object.uuid || (object['@self'] && object['@self'].id)
1242
+ const label = readPath(object, resolve.labelField || 'title') ?? object.name
1243
+ if (id !== undefined && label !== undefined && label !== null) {
1244
+ labels.set(String(id), String(label))
1245
+ }
1246
+ }
1247
+ return labels
1248
+ }
1249
+
1250
+ const subtitleOf = (kind, object, labels = null) => {
1230
1251
  if (kind.subtitleTemplate) {
1231
- return fillTemplate(translate(kind.subtitleTemplate), object)
1252
+ const resolve = kind.subtitleResolve
1253
+ const data = labels && resolve
1254
+ ? { ...object, [resolve.as || resolve.field]: labels.get(String(readPath(object, resolve.field) ?? '')) ?? '' }
1255
+ : object
1256
+ return fillTemplate(translate(kind.subtitleTemplate), data)
1232
1257
  }
1233
1258
  return kind.subtitleField ? String(readPath(object, kind.subtitleField) ?? '') : ''
1234
1259
  }
@@ -1247,6 +1272,7 @@ function searchSource(config = {}, context = {}) {
1247
1272
  const results = Array.isArray(body.results) ? body.results : (Array.isArray(body) ? body : [])
1248
1273
  const labels = kind.statusResolve && kind.statusField ? await statusLabels(kind) : null
1249
1274
  const userNames = kind.linkedUser === true ? await linkedUserNames(kind, results) : null
1275
+ const subtitleNames = await subtitleLabels(kind)
1250
1276
  return {
1251
1277
  total: typeof body.total === 'number' ? body.total : results.length,
1252
1278
  rows: results.map((object) => {
@@ -1261,7 +1287,7 @@ function searchSource(config = {}, context = {}) {
1261
1287
  kindLabel: kind.label,
1262
1288
  kindText: kindTextOf(kind, object),
1263
1289
  title: String(readPath(object, kind.titleField || 'title') ?? object.name ?? id ?? ''),
1264
- subtitle: subtitleOf(kind, object),
1290
+ subtitle: subtitleOf(kind, object, subtitleNames),
1265
1291
  status,
1266
1292
  linked: userNames ? (userNames.get(linkedOf(kind, object)) || linkedOf(kind, object)) : linkedOf(kind, object),
1267
1293
  href: kind.href ? generateUrl(fillRowTemplate(kind.href, { ...object, id })) : '',
@@ -1372,7 +1398,7 @@ function searchSource(config = {}, context = {}) {
1372
1398
  loading: () => state.loading,
1373
1399
 
1374
1400
  columns: withColumnWidths([
1375
- { key: 'title', label: t('nextcloud-vue', 'Result'), secondary: 'subtitle', sortable: true },
1401
+ { key: 'title', label: t('nextcloud-vue', 'Result'), secondary: 'subtitle', sortable: true, ...(config && config.titleWrap === true ? { cellClass: 'cn-cell--wrap' } : {}) },
1376
1402
  // `kindAsText`: what one row is, as plain text ("Zaak", "Lantaarnpaal",
1377
1403
  // DqZoekresultaten), instead of the plural kind as a pill.
1378
1404
  config && config.kindAsText === true
@@ -1619,10 +1645,10 @@ function usersSource() {
1619
1645
  loading: () => state.loading,
1620
1646
 
1621
1647
  columns: [
1622
- { key: 'displayname', label: t('nextcloud-vue', 'Employee'), secondary: 'function' },
1623
- { key: 'roles', label: t('nextcloud-vue', 'Roles') },
1624
- { key: 'email', label: t('nextcloud-vue', 'E-mail') },
1625
- { key: 'today', label: t('nextcloud-vue', 'Today'), widget: 'badge', widgetProps: { colorMap: presenceColors, variant: 'warning' } },
1648
+ { key: 'displayname', label: t('nextcloud-vue', 'Employee'), secondary: 'function', sortable: true, cellClass: 'cn-cell--lead' },
1649
+ { key: 'roles', label: t('nextcloud-vue', 'Roles'), sortable: true },
1650
+ { key: 'email', label: t('nextcloud-vue', 'E-mail'), sortable: true },
1651
+ { key: 'today', label: t('nextcloud-vue', 'Today'), widget: 'badge', widgetProps: { colorMap: presenceColors, variant: 'warning' }, sortable: true },
1626
1652
  ],
1627
1653
 
1628
1654
  searchFields: {
@@ -177,11 +177,14 @@ body:has(.cn-look-board):not(:has(.cn-look-nextcloud)) .modal-mask {
177
177
  color: var(--color-text-maxcontrast);
178
178
  }
179
179
 
180
- /* The saved-view edit and share forms start 22px under the subtitle, as
181
- the Dq dialog boards draw a first field: the body's 16px gap and 6px. */
180
+ /* A body starts 22px under the subtitle, as the Dq dialog boards draw a
181
+ first field: the header's foot and the body gap alone, so the saved-view
182
+ edit and share forms and the confirm sentence pad nothing on top
183
+ (r29 on :8080: 28, 28 and 26px with their own padding). */
182
184
  .cn-dialog-board .dialog__content .cn-edit-view,
183
- .cn-dialog-board .dialog__content .cn-share-view {
184
- padding-top: 6px;
185
+ .cn-dialog-board .dialog__content .cn-share-view,
186
+ .cn-dialog-board .dialog__content .cn-confirm__confirm {
187
+ padding-top: 0;
185
188
  }
186
189
 
187
190
  /* The close button is a 36px circle. NcButton sizes an icon-only button by
@@ -218,7 +221,9 @@ body:has(.cn-look-board):not(:has(.cn-look-nextcloud)) .modal-mask {
218
221
  10px 14px padding, the checkbox row at the 24px minimum target instead of
219
222
  NcCheckboxRadioSwitch's 34px, the note at 1.2 line height; the card's
220
223
  corners 8px and the label on an 18px line, as the board draws them. */
221
- .cn-dialog-board .cn-assign-dialog__toggle {
224
+ /* `.dialog` outranks the component's scoped rule (class + attribute), which
225
+ loads after this sheet and kept 12px 14px and 12px corners on :8080 (r29). */
226
+ .cn-dialog-board .dialog .cn-assign-dialog__toggle {
222
227
  padding: 10px 14px;
223
228
  border-radius: 8px;
224
229
  }
@@ -347,10 +352,14 @@ body:has(.cn-look-board):not(:has(.cn-look-nextcloud)) .modal-mask {
347
352
  border and radius 8 (PlanItemDialog, DqWerkvoorraad). NcInputField draws
348
353
  its border as a 65%-transparent shadow, which on the white dialog read as
349
354
  an empty band, and floats its label inside the border. A field with
350
- `labelOutside` keeps the app's own label and takes the same control. */
355
+ `labelOutside` keeps the app's own label and takes the same control. The
356
+ label's box starts where the field starts and the control 23px under it,
357
+ as on every dialog board (72 fields on 11 boards): the label at the font's
358
+ normal line, 21px of room plus the control's 2px focus inset, the label
359
+ 4px above that room's end. */
351
360
  .cn-dialog-board .dialog__content .input-field:has(.input-field__label),
352
361
  .cn-dialog-board .dialog__content .textarea:has(.textarea__label) {
353
- margin-block-start: 26px;
362
+ margin-block-start: 21px;
354
363
  }
355
364
 
356
365
  /* NcSelect's search is an NcInputField inside the select, and the select's
@@ -359,7 +368,7 @@ body:has(.cn-look-board):not(:has(.cn-look-nextcloud)) .modal-mask {
359
368
  select makes the label's room instead.
360
369
  @spec openspec/changes/board-dialog-select-label-room/specs/board-dialog-select-label-room/spec.md#requirement-a-board-dialog-select-makes-room-for-its-raised-label */
361
370
  .cn-dialog-board .dialog__content .v-select:has(.input-field__label) {
362
- margin-block-start: 26px;
371
+ margin-block-start: 21px;
363
372
  }
364
373
 
365
374
  /* A select in a form dialog sits under its label and over its help line
@@ -420,7 +429,7 @@ body:has(.cn-look-board):not(:has(.cn-look-nextcloud)) .modal-mask {
420
429
  color: var(--color-main-text);
421
430
  font-size: var(--cn-field-label-size, 14px);
422
431
  font-weight: 600;
423
- line-height: 20px;
432
+ line-height: normal;
424
433
  pointer-events: auto;
425
434
  transition: none;
426
435
  }
@@ -627,6 +627,30 @@
627
627
  font-size: 14px;
628
628
  }
629
629
 
630
+ /* The reply box's buttons (Opslaan als concept, Versturen) are the board's
631
+ 40px control, as DqBerichtVersturen draws Versturen; NcButton draws 34
632
+ (DqZaakContact r29 controlHeight 34).
633
+ @spec openspec/changes/board-conversation-reply-buttons-40/specs/board-conversation-reply-buttons-40/spec.md#requirement-the-reply-boxs-buttons-are-the-boards-40px-control */
634
+ .cn-look-board .cn-conversation-thread__reply .button-vue:where(:not(.cn-look-nextcloud *)) {
635
+ --button-size: var(--cn-board-control-height);
636
+ }
637
+
638
+ /* A lead widget in a card (the review summary over the files) stands 16px
639
+ above the card's own body, the boards' gap between a card's parts
640
+ (DqZaakDocumenten r29: the files toolbar sat flush under the summary).
641
+ @spec openspec/changes/board-lead-widget-gap-16/specs/board-lead-widget-gap-16/spec.md#requirement-a-lead-widget-stands-16px-above-the-cards-body */
642
+ .cn-look-board .cn-detail-widget-host__lead:not(.cn-look-nextcloud *) {
643
+ margin-bottom: 16px;
644
+ }
645
+
646
+ /* The compact review summary runs on the normal line height, as the board
647
+ draws its heading and legend (DqZaakDocumenten r29: heading 22.5 vs 18,
648
+ the box 99.5 vs 91 high).
649
+ @spec openspec/changes/board-stacked-bar-compact-line-height/specs/board-stacked-bar-compact-line-height/spec.md#requirement-the-compact-summary-runs-on-the-normal-line-height */
650
+ .cn-look-board .cn-stacked-bar--compact:not(.cn-look-nextcloud *) {
651
+ line-height: normal;
652
+ }
653
+
630
654
  /* The case Status card as the board draws it: no grey box, the status's
631
655
  explanation as its bold line, the time in the status muted under it.
632
656
  @spec openspec/changes/status-explainer-board/specs/record-widgets/spec.md#requirement-the-status-card-says-where-the-record-stands-as-the-board-draws-it */
@@ -707,6 +731,14 @@
707
731
  padding: calc(12px - var(--cn-board-first-line-leading)) var(--cn-board-card-inline-padding) 20px;
708
732
  }
709
733
 
734
+ /* A history card with stacked rows (DqTaak "Historie") opens on the first
735
+ row's hairline 6px under the title, the row's own 12px padding above its
736
+ text, as drawn: 19px from the title to the first action.
737
+ @spec openspec/changes/board-history-card-ruled-start/specs/board-history-card-ruled-start/spec.md#requirement-a-board-history-card-with-stacked-rows-opens-on-its-first-rule */
738
+ .cn-look-board .cn-detail-card .cn-detail-card__content:has(> .cn-audit-card__list > .cn-audit-card__row--stacked:first-child):not(.cn-look-nextcloud *) {
739
+ padding-top: 6px;
740
+ }
741
+
710
742
  /* A data card (labels over values) starts 14px below its title (DqZaak
711
743
  "Zaakgegevens", DqContact "Contact"). A side card keeps its 10px.
712
744
  @spec openspec/changes/board-data-card-gap/specs/board-data-card-gap/spec.md#requirement-a-board-data-cards-body-starts-14px-below-its-title */
@@ -787,6 +819,47 @@
787
819
  font-weight: 500;
788
820
  }
789
821
 
822
+ /* A data card's label and value sit 3px apart on the normal line height, as
823
+ the boards draw their facts (194 of 212 dt/dd pairs: gap 3px, no line
824
+ height); live ran them at 1.5 with a 2px gap (DqZaakContact
825
+ Ontvangstbevestiging r29: the first label 33.8 under the title, board 29).
826
+ @spec openspec/changes/board-data-cell-rhythm/specs/board-data-cell-rhythm/spec.md#requirement-a-data-cards-label-and-value-sit-3px-apart-on-the-normal-line-height */
827
+ .cn-look-board .cn-object-data-widget__grid .cn-object-data-widget__cell.cn-object-data-widget__cell {
828
+ gap: 3px;
829
+ }
830
+
831
+ .cn-look-board .cn-object-data-widget__grid .cn-object-data-widget__label.cn-object-data-widget__label,
832
+ .cn-look-board .cn-object-data-widget__grid .cn-object-data-widget__value {
833
+ line-height: normal;
834
+ }
835
+
836
+ /* A note in a page card starts at the card's inset: no list-item padding
837
+ around it, its icon 12px before the text (DqZaakEmail Notities r29: icon
838
+ at 31 and text at 71 where the board draws 23 and 67).
839
+ @spec openspec/changes/board-notes-card-rows-flush/specs/board-notes-card-rows-flush/spec.md#requirement-a-note-in-a-page-card-starts-at-the-cards-inset */
840
+ .cn-look-board .cn-detail-widget-host .cn-notes-tab__thread .list-item__wrapper:not(.cn-look-nextcloud *),
841
+ .cn-look-board .cn-detail-widget-host .cn-notes-tab__thread .list-item:not(.cn-look-nextcloud *) {
842
+ padding: 0;
843
+ }
844
+
845
+ .cn-look-board .cn-detail-widget-host .cn-notes-tab__thread .list-item-content:not(.cn-look-nextcloud *) {
846
+ padding-inline-start: 12px;
847
+ }
848
+
849
+ /* The note's two lines on the normal line height and its icon at the top of
850
+ the row, as the board draws the author tile beside the name (probed on
851
+ :8080: the name 44.8 under the title as drawn, the icon 6.5px lower while
852
+ centred in the 45px item).
853
+ @spec openspec/changes/board-notes-card-rows-flush/specs/board-notes-card-rows-flush/spec.md#requirement-a-note-in-a-page-card-starts-at-the-cards-inset */
854
+ .cn-look-board .cn-detail-widget-host .cn-notes-tab__thread .list-item-content__name:not(.cn-look-nextcloud *),
855
+ .cn-look-board .cn-detail-widget-host .cn-notes-tab__thread .list-item-content__subname:not(.cn-look-nextcloud *) {
856
+ line-height: normal;
857
+ }
858
+
859
+ .cn-look-board .cn-detail-widget-host .cn-notes-tab__thread .list-item__anchor > :first-child:not(.list-item-content):not(.cn-look-nextcloud *) {
860
+ align-self: flex-start;
861
+ }
862
+
790
863
  /* Side cards: the heading is a 15px muted label, not a title. The tone
791
864
  carries `!important` against a theme that colours every h3 that way
792
865
  (thematiq's heading colour). */
@@ -806,6 +879,14 @@
806
879
  padding: calc(10px - var(--cn-board-first-line-leading)) 22px 20px;
807
880
  }
808
881
 
882
+ /* A side card that opens on a list draws its first row's hairline 10px below
883
+ the title box; the row has no leading for the glyph gap above to subtract
884
+ (DqZaaktypeRegels, DqZaaktypeStatussen "Versies").
885
+ @spec openspec/changes/board-side-list-gap/specs/board-side-list-gap/spec.md#requirement-a-board-side-cards-list-starts-10px-below-its-title */
886
+ .cn-look-board .cn-detail-page__side .cn-widget-wrapper__content:has(> .cn-record-list--rows) {
887
+ padding-top: 10px;
888
+ }
889
+
809
890
  /* A side card that opens on a lead (DqZaak "Aanvrager", DqOrganisatie "KvK en
810
891
  adres") draws the lead row 12px below the title, its two lines at their
811
892
  normal height so they centre on the 40px tile.
@@ -885,6 +966,13 @@
885
966
  line-height: 1;
886
967
  }
887
968
 
969
+ /* A list's Add in the title row is the card's 34px control, as the boards
970
+ draw a card's Add (DqZaaktype "Variant toevoegen"). */
971
+ .cn-look-board .cn-detail-page__catalog-action--add:not(.cn-detail-page__side *):not(.cn-look-nextcloud *) {
972
+ height: 34px;
973
+ min-height: 34px;
974
+ }
975
+
888
976
  .cn-look-board .cn-detail-page__catalog-action:not(.cn-detail-page__side *):not(.cn-look-nextcloud *):hover {
889
977
  background: var(--color-background-hover);
890
978
  }
@@ -1319,6 +1407,26 @@
1319
1407
  line-height: 1.2;
1320
1408
  }
1321
1409
 
1410
+ /* The task name takes the spare width, so it wraps only when long; the
1411
+ handler stays on one line. */
1412
+ .cn-look-board .cn-detail-page .cn-widget-wrapper__content > .cn-tasks-widget .cn-tasks-widget__table th:first-child,
1413
+ .cn-look-board .cn-detail-page .cn-widget-wrapper__content > .cn-tasks-widget .cn-tasks-widget__table .cn-tasks-widget__cell-task {
1414
+ width: 100%;
1415
+ }
1416
+
1417
+ .cn-look-board .cn-detail-page .cn-widget-wrapper__content > .cn-tasks-widget .cn-tasks-widget__table .cn-tasks-widget__cell-handler {
1418
+ white-space: nowrap;
1419
+ }
1420
+
1421
+ /* A head's filter is a 22px button, so a head is 42px high as drawn. */
1422
+ .cn-look-board .cn-detail-page .cn-widget-wrapper__content > .cn-tasks-widget .cn-tasks-widget__table .cn-tasks-widget__head-filter .button-vue {
1423
+ --button-size: 22px;
1424
+ min-width: 22px;
1425
+ min-height: 22px;
1426
+ width: 22px;
1427
+ height: 22px;
1428
+ }
1429
+
1322
1430
  /* A long task name wraps under itself, as the board draws it, rather than
1323
1431
  widening the table past the card. */
1324
1432
  .cn-look-board .cn-detail-page .cn-widget-wrapper__content > .cn-tasks-widget .cn-tasks-widget__table :is(.cn-tasks-widget__name, .cn-tasks-widget__meta) {
@@ -1352,6 +1460,13 @@
1352
1460
  padding-inline-end: var(--cn-board-card-inline-padding);
1353
1461
  }
1354
1462
 
1463
+ /* A row menu in the last column keeps its 34px button and 16px start
1464
+ padding beside the card's end padding, so it is not cut off. */
1465
+ .cn-look-board .cn-detail-page .cn-widget-wrapper__content > .cn-object-list-widget--bleed .cn-table-container .cn-data-table .cn-table-col--actions:last-child {
1466
+ width: calc(50px + var(--cn-board-card-inline-padding));
1467
+ min-width: calc(50px + var(--cn-board-card-inline-padding));
1468
+ }
1469
+
1355
1470
  /* ---- Grouped cards (CnGroupedCardsWidget, DqZaaktype "Fasen en taken") --- */
1356
1471
  /* Groups 14px apart, each padded 14px with a 10px radius and a bold title; a
1357
1472
  card in a group is padded 9px 12px with the 8px control radius, its title
@@ -1377,6 +1492,14 @@
1377
1492
 
1378
1493
  .cn-look-board .cn-grouped-cards__group-title.cn-grouped-cards__group-title {
1379
1494
  font-weight: 700;
1495
+ line-height: 1.2;
1496
+ }
1497
+
1498
+ /* The buttons above the groups are the card's 34px controls ("Bekijken als
1499
+ flow", "Taak toevoegen"), not the page's 40px ones. */
1500
+ .cn-look-board .cn-grouped-cards__actions:not(.cn-look-nextcloud *) .button-vue {
1501
+ min-height: 34px;
1502
+ height: 34px;
1380
1503
  }
1381
1504
 
1382
1505
  .cn-look-board .cn-grouped-cards__item.cn-grouped-cards__item {
@@ -1386,6 +1509,7 @@
1386
1509
 
1387
1510
  .cn-look-board .cn-grouped-cards__item-title.cn-grouped-cards__item-title {
1388
1511
  font-size: 15px;
1512
+ line-height: 1.2;
1389
1513
  }
1390
1514
 
1391
1515
  /* A card with actions holds them at its end, beside the title and meta (the
@@ -1564,6 +1688,15 @@
1564
1688
  font-size: 14px;
1565
1689
  }
1566
1690
 
1691
+ /* The mail card's description runs on the normal line height: thematiq's
1692
+ board paragraph token (1.5) gave
1693
+ it 21px lines (probed on :8080 after REFRESH-4b: 14px/21 vs the board's
1694
+ normal; DqZaakEmail r29 E-mail gapBelowTitle 44.4 vs 49).
1695
+ @spec openspec/changes/board-mail-subtitle-line-height/specs/board-mail-subtitle-line-height/spec.md#requirement-the-mail-cards-description-runs-on-the-normal-line-height */
1696
+ .cn-look-board .cn-detail-widget-host .cn-mail-tab__subtitle.cn-mail-tab__subtitle:not(.cn-look-nextcloud *) {
1697
+ line-height: normal;
1698
+ }
1699
+
1567
1700
  /* ---- The attention flag's buttons --------------------------------------- */
1568
1701
  /* The case boards draw "Markeer voor aandacht" and the flag's other labelled
1569
1702
  buttons at the 40px control height (DqZaak and the case tab boards);
@@ -1728,9 +1861,14 @@
1728
1861
  }
1729
1862
 
1730
1863
  .cn-look-board .cn-detail-page__leaf-card .cn-contacts-tab .cn-contacts-tab__header {
1864
+ display: inline-flex;
1731
1865
  justify-content: flex-start;
1732
1866
  }
1733
1867
 
1868
+ .cn-look-board .cn-detail-page__leaf-card .cn-contacts-tab .cn-contacts-tab__header .button-vue {
1869
+ --button-size: var(--cn-board-control-height);
1870
+ }
1871
+
1734
1872
  /* A body card's subtitle as the Dq boards draw it: 14px muted at line
1735
1873
  height 1.2, 3px under the title, and the content 12px under it.
1736
1874
  @spec openspec/changes/board-card-subtitle-gaps/specs/board-card/spec.md */
@@ -1836,23 +1974,25 @@
1836
1974
  /* Appointment and note rows (DqTaak Afspraken, Notities): a hairline above
1837
1975
  every row including the first, 12px 0 padding, a 32px round tile (the day
1838
1976
  an appointment starts, the author's initials) 12px before the text, the
1839
- title 15/600 and one 13px muted meta line joined with " · ".
1977
+ title 15/600 and one 13px muted meta line joined with " · ". Every
1978
+ selector carries :not(.cn-look-nextcloud *) to outrank the cards' scoped
1979
+ rules, which tie with a two-class selector and load later.
1840
1980
  @spec openspec/changes/board-task-cards-rows/specs/task-cards/spec.md#requirement-board-appointment-and-note-rows-carry-a-tile-and-a-meta-line */
1841
- .cn-look-board .cn-events-card__list {
1981
+ .cn-look-board .cn-events-card__list:not(.cn-look-nextcloud *) {
1842
1982
  gap: 0;
1843
1983
  }
1844
1984
 
1845
- .cn-look-board .cn-events-card__event,
1846
- .cn-look-board .cn-events-card__event:last-child,
1847
- .cn-look-board .cn-notes-card__note,
1848
- .cn-look-board .cn-notes-card__note:last-child {
1985
+ .cn-look-board .cn-events-card__event:not(.cn-look-nextcloud *),
1986
+ .cn-look-board .cn-events-card__event:not(.cn-look-nextcloud *):last-child,
1987
+ .cn-look-board .cn-notes-card__note:not(.cn-look-nextcloud *),
1988
+ .cn-look-board .cn-notes-card__note:not(.cn-look-nextcloud *):last-child {
1849
1989
  padding: 12px 0;
1850
1990
  border-top: 1px solid var(--cn-board-hairline);
1851
1991
  border-bottom: none;
1852
1992
  }
1853
1993
 
1854
- .cn-look-board .cn-events-card__day,
1855
- .cn-look-board .cn-notes-card__initials {
1994
+ .cn-look-board .cn-events-card__day:not(.cn-look-nextcloud *),
1995
+ .cn-look-board .cn-notes-card__initials:not(.cn-look-nextcloud *) {
1856
1996
  display: inline-flex;
1857
1997
  flex: 0 0 32px;
1858
1998
  align-items: center;
@@ -1866,60 +2006,60 @@
1866
2006
  font-weight: 700;
1867
2007
  }
1868
2008
 
1869
- .cn-look-board .cn-events-card__text {
2009
+ .cn-look-board .cn-events-card__text:not(.cn-look-nextcloud *) {
1870
2010
  flex-flow: row wrap;
1871
2011
  row-gap: 2px;
1872
2012
  }
1873
2013
 
1874
- .cn-look-board .cn-events-card__summary,
1875
- .cn-look-board .cn-notes-card__body {
2014
+ .cn-look-board .cn-events-card__summary:not(.cn-look-nextcloud *),
2015
+ .cn-look-board .cn-notes-card__body:not(.cn-look-nextcloud *) {
1876
2016
  font-size: 15px;
1877
2017
  font-weight: 600;
1878
2018
  line-height: 1.35;
1879
2019
  }
1880
2020
 
1881
- .cn-look-board .cn-events-card__summary {
2021
+ .cn-look-board .cn-events-card__summary:not(.cn-look-nextcloud *) {
1882
2022
  flex-basis: 100%;
1883
2023
  }
1884
2024
 
1885
- .cn-look-board .cn-events-card__when,
1886
- .cn-look-board .cn-events-card__where,
1887
- .cn-look-board .cn-notes-card__author,
1888
- .cn-look-board .cn-notes-card__time {
2025
+ .cn-look-board .cn-events-card__when:not(.cn-look-nextcloud *),
2026
+ .cn-look-board .cn-events-card__where:not(.cn-look-nextcloud *),
2027
+ .cn-look-board .cn-notes-card__author:not(.cn-look-nextcloud *),
2028
+ .cn-look-board .cn-notes-card__time:not(.cn-look-nextcloud *) {
1889
2029
  color: var(--color-text-maxcontrast);
1890
2030
  font-size: 13px;
1891
2031
  font-weight: 400;
1892
2032
  }
1893
2033
 
1894
- .cn-look-board .cn-events-card__where::before,
1895
- .cn-look-board .cn-notes-card__time::before {
2034
+ .cn-look-board .cn-events-card__where:not(.cn-look-nextcloud *)::before,
2035
+ .cn-look-board .cn-notes-card__time:not(.cn-look-nextcloud *)::before {
1896
2036
  content: ' · ';
1897
2037
  white-space: pre;
1898
2038
  }
1899
2039
 
1900
- .cn-look-board .cn-notes-card__note {
2040
+ .cn-look-board .cn-notes-card__note:not(.cn-look-nextcloud *) {
1901
2041
  display: flex;
1902
2042
  flex-direction: column;
1903
2043
  gap: 2px;
1904
2044
  padding-inline-start: 44px;
1905
2045
  }
1906
2046
 
1907
- .cn-look-board .cn-notes-card__initials {
2047
+ .cn-look-board .cn-notes-card__initials:not(.cn-look-nextcloud *) {
1908
2048
  position: absolute;
1909
2049
  top: 12px;
1910
2050
  inset-inline-start: 0;
1911
2051
  }
1912
2052
 
1913
- .cn-look-board .cn-notes-card__body {
2053
+ .cn-look-board .cn-notes-card__body:not(.cn-look-nextcloud *) {
1914
2054
  order: -1;
1915
2055
  }
1916
2056
 
1917
- .cn-look-board .cn-notes-card__note-header {
2057
+ .cn-look-board .cn-notes-card__note-header:not(.cn-look-nextcloud *) {
1918
2058
  justify-content: flex-start;
1919
2059
  margin-bottom: 0;
1920
2060
  }
1921
2061
 
1922
- .cn-look-board .cn-notes-card__time {
2062
+ .cn-look-board .cn-notes-card__time:not(.cn-look-nextcloud *) {
1923
2063
  margin-inline-start: 0;
1924
2064
  }
1925
2065
 
@@ -1928,6 +2068,10 @@
1928
2068
  that names the role, the pills at the end. The role headings stay for
1929
2069
  assistive tech only.
1930
2070
  @spec openspec/changes/board-parties-rows/specs/parties/spec.md */
2071
+ .cn-look-board .cn-object-parties--board {
2072
+ gap: 8px;
2073
+ }
2074
+
1931
2075
  .cn-look-board .cn-object-parties--board .cn-object-parties__role-label {
1932
2076
  position: absolute;
1933
2077
  width: 1px;
@@ -2039,3 +2183,55 @@
2039
2183
  font-weight: 600;
2040
2184
  text-decoration: underline;
2041
2185
  }
2186
+
2187
+ /* Two-column facts (`columns: 2`, DqContact "Contact", DqOrganisatie
2188
+ "Organisatie"): the boards draw the label 2px above a regular-weight
2189
+ value, with no hairline under the fact; the 14px row gap separates them.
2190
+ @spec openspec/changes/board-facts-columns-plain/specs/board-facts-columns-plain/spec.md#requirement-board-two-column-facts-are-plain-label-over-value-pairs */
2191
+ .cn-look-board .cn-facts-widget__rows--columns:not(.cn-look-nextcloud *) .cn-facts-widget__row {
2192
+ gap: 2px;
2193
+ padding-bottom: 0;
2194
+ border-bottom: none;
2195
+ }
2196
+
2197
+ .cn-look-board .cn-facts-widget__rows--columns:not(.cn-look-nextcloud *) .cn-facts-widget__value.cn-facts-widget__value {
2198
+ font-weight: 400;
2199
+ line-height: normal;
2200
+ }
2201
+
2202
+ .cn-look-board .cn-facts-widget__rows--columns:not(.cn-look-nextcloud *) .cn-facts-widget__label.cn-facts-widget__label {
2203
+ line-height: normal;
2204
+ }
2205
+
2206
+ /* A ruled list in a page card (`ruleAbove`, DqContact and DqOrganisatie
2207
+ "Zaken", "Tickets"): the rule sits 12px under the title and each row has
2208
+ 12px above and below its text, so the first row's text is 25px under the
2209
+ title.
2210
+ @spec openspec/changes/board-ruled-list-card-start/specs/board-ruled-list-card-start/spec.md#requirement-a-board-ruled-list-in-a-page-card-starts-12px-under-the-title */
2211
+ .cn-look-board .cn-detail-page .cn-widget-wrapper__content:has(> .cn-record-list--rows.cn-record-list--rule-above):not(.cn-detail-page__side *),
2212
+ .cn-look-board .cn-detail-card__content:has(> .cn-record-list--rows.cn-record-list--rule-above):not(.cn-detail-page__side *) {
2213
+ padding-top: 12px;
2214
+ }
2215
+
2216
+ .cn-look-board .cn-detail-page .cn-record-list--rows.cn-record-list--rule-above:not(.cn-detail-page__side *):not(.cn-look-nextcloud *) .cn-record-list__row {
2217
+ padding: 12px 0;
2218
+ }
2219
+
2220
+ /* A side list row with initials stays one line: a 28px circle 8px before
2221
+ the regular-weight text (DqSociaalDomein "Wie"). The library stacks side
2222
+ rows into a column, which put the initials above the name.
2223
+ @spec openspec/changes/board-side-person-rows/specs/board-side-person-rows/spec.md#requirement-a-board-side-row-with-initials-keeps-them-beside-the-text */
2224
+ .cn-look-board .cn-detail-page__side .cn-record-list__row:has(> .cn-record-list__avatar):not(.cn-look-nextcloud *) {
2225
+ flex-direction: row;
2226
+ align-items: center;
2227
+ gap: 8px;
2228
+ }
2229
+
2230
+ .cn-look-board .cn-detail-page__side .cn-record-list__row:not(.cn-look-nextcloud *) > .cn-record-list__avatar {
2231
+ width: 28px;
2232
+ height: 28px;
2233
+ }
2234
+
2235
+ .cn-look-board .cn-detail-page__side .cn-record-list__row:has(> .cn-record-list__avatar):not(.cn-look-nextcloud *) .cn-record-list__title {
2236
+ font-weight: 400;
2237
+ }
@@ -77,7 +77,7 @@
77
77
  grid-column: 1 / -1;
78
78
  grid-row: 2;
79
79
  justify-self: start;
80
- margin-block: 6px 3px;
80
+ margin-block: 6px 0;
81
81
  }
82
82
 
83
83
  .cn-look-board.cn-index-page--sidebar-open .cn-page-header .cn-header-trail,
@@ -90,6 +90,13 @@
90
90
  grid-row: 4;
91
91
  }
92
92
 
93
+ /* Without a breadcrumb trail the count line takes the trail's row, so no
94
+ empty row adds a second gap (DqZakenSorteren: 58px under the title). */
95
+ .cn-look-board.cn-index-page--sidebar-open .cn-page-header:not(:has(.cn-header-trail)) .cn-page-header__text > .cn-page-header__description,
96
+ .cn-look-board .cn-index-page--sidebar-open .cn-page-header:not(:has(.cn-header-trail)) .cn-page-header__text > .cn-page-header__description {
97
+ grid-row: 3;
98
+ }
99
+
93
100
  /* The header buttons keep the board's button under a theme that styles every
94
101
  secondary or primary button with `!important` (the nldesign theme: a
95
102
  primary border, 8px 16px padding): Download and the Actions menu are 40px,
@@ -190,6 +197,15 @@
190
197
  gap: 8px;
191
198
  }
192
199
 
200
+ /* With the side panel open the boards keep Filter on row 1 after Save view
201
+ and wrap the view switch alone to row 2 (DqFilterBeheren, DqZakenSorteren):
202
+ the unit dissolves into the bar's flex row.
203
+ @spec openspec/changes/board-filter-row-one-beside-side-panel/specs/board-filter-row-one-beside-side-panel/spec.md */
204
+ .cn-look-board.cn-index-page--sidebar-open .cn-actions-bar--board .cn-actions-bar__view-controls,
205
+ .cn-look-board .cn-index-page--sidebar-open .cn-actions-bar--board .cn-actions-bar__view-controls {
206
+ display: contents;
207
+ }
208
+
193
209
  /* `quickFilterPlacement: "toolbar"` (DqTeamwachtrij): the chips take the room
194
210
  the Filter button and the view switch leave on row 1, so the three stay on
195
211
  one row in the column beside a side panel; the chips that do not fit move
@@ -909,16 +925,21 @@
909
925
  `#content[class*="app-"]`, an id selector no class rule outranks, so a plain
910
926
  `content-box` here was ignored and the cell left 12px for the checkbox (the
911
927
  header's checkbox showed as a stray bracket). */
912
- /* The checkbox starts 20px in, as the boards draw a native checkbox (16px of
913
- cell padding and its 4px margin; DqZoekresultaten), in the same 60px. */
928
+ /* The cell pads 16px as the boards do and the checkbox starts 4px further in,
929
+ a native checkbox's margin (DqZoekresultaten, DqPostvak, DqContracten), in
930
+ the same 60px. */
914
931
  .cn-look-board .cn-table-container--board .cn-data-table .cn-table-col--checkbox {
915
932
  box-sizing: border-box !important;
916
933
  width: 60px;
917
934
  min-width: 60px;
918
- padding-inline: 20px 12px;
935
+ padding-inline: 16px;
919
936
  text-align: start;
920
937
  }
921
938
 
939
+ .cn-look-board .cn-table-container--board .cn-data-table .cn-table-col--checkbox .checkbox-radio-switch {
940
+ margin-inline-start: 4px;
941
+ }
942
+
922
943
  .cn-look-board .cn-table-container--board .cn-data-table .checkbox-radio-switch {
923
944
  --icon-size: 18px;
924
945
  }
@@ -1428,6 +1449,19 @@
1428
1449
  padding-top: 0;
1429
1450
  }
1430
1451
 
1452
+ /* The selection box sits flush where the boards draw it: NcCheckbox pads its
1453
+ content 7px on each side (DqAanMijToegewezen card head, DqTeamwachtrij rows,
1454
+ whose box starts 18px in).
1455
+ @spec openspec/changes/board-selection-box-flush/specs/board-selection-box-flush/spec.md#requirement-a-cards-and-a-rows-selection-box-sits-where-the-board-draws-it */
1456
+ .cn-look-board .cn-object-card__record-head > .cn-object-card__checkbox .checkbox-radio-switch__content,
1457
+ .cn-look-board .cn-object-row__checkbox .checkbox-radio-switch__content {
1458
+ padding-inline: 0;
1459
+ }
1460
+
1461
+ .cn-look-board .cn-object-row__checkbox {
1462
+ margin-inline-start: 6px;
1463
+ }
1464
+
1431
1465
  .cn-look-board .cn-object-card--board .cn-object-card__record-head > .cn-object-card__checkbox ~ .cn-object-card__record-pill {
1432
1466
  margin-inline-start: auto;
1433
1467
  }