@conduction/nextcloud-vue 2.110.0 → 2.112.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 (142) hide show
  1. package/dist/esm/components/CnActionDialog/CnActionDialog.vue.js +1 -1
  2. package/dist/esm/components/CnActionDialog/CnActionDialog.vue2.js +3 -2
  3. package/dist/esm/components/CnActionDialog/CnActionDialog.vue2.js.map +1 -1
  4. package/dist/esm/components/CnActionDialog/CnActionDialog.vue3.js +4 -2
  5. package/dist/esm/components/CnActionDialog/CnActionDialog.vue3.js.map +1 -1
  6. package/dist/esm/components/CnAppRoot/CnAppRoot.vue2.js +2 -1
  7. package/dist/esm/components/CnAppRoot/CnAppRoot.vue2.js.map +1 -1
  8. package/dist/esm/components/CnAppRoot/CnAppRoot.vue3.js.map +1 -1
  9. package/dist/esm/components/CnAssignDialog/CnAssignDialog.vue.js +1 -1
  10. package/dist/esm/components/CnAssignDialog/CnAssignDialog.vue2.js +3 -2
  11. package/dist/esm/components/CnAssignDialog/CnAssignDialog.vue2.js.map +1 -1
  12. package/dist/esm/components/CnAssignDialog/CnAssignDialog.vue3.js +2 -1
  13. package/dist/esm/components/CnAssignDialog/CnAssignDialog.vue3.js.map +1 -1
  14. package/dist/esm/components/CnBoardView/CnBoardView.vue.js +1 -1
  15. package/dist/esm/components/CnBoardView/CnBoardView.vue2.js +54 -5
  16. package/dist/esm/components/CnBoardView/CnBoardView.vue2.js.map +1 -1
  17. package/dist/esm/components/CnBoardView/CnBoardView.vue3.js +16 -2
  18. package/dist/esm/components/CnBoardView/CnBoardView.vue3.js.map +1 -1
  19. package/dist/esm/components/CnCardGrid/CnCardGrid.vue.js +1 -1
  20. package/dist/esm/components/CnCardGrid/CnCardGrid.vue2.js +10 -0
  21. package/dist/esm/components/CnCardGrid/CnCardGrid.vue2.js.map +1 -1
  22. package/dist/esm/components/CnCardGrid/CnCardGrid.vue3.js +2 -1
  23. package/dist/esm/components/CnCardGrid/CnCardGrid.vue3.js.map +1 -1
  24. package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue.js +1 -1
  25. package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue2.js +22 -2
  26. package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue2.js.map +1 -1
  27. package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue3.js +17 -3
  28. package/dist/esm/components/CnCellRenderer/CnCellRenderer.vue3.js.map +1 -1
  29. package/dist/esm/components/CnChartWidget/CnChartWidget.vue.js +1 -1
  30. package/dist/esm/components/CnChartWidget/CnChartWidget.vue2.js.map +1 -1
  31. package/dist/esm/components/CnChartWidget/CnChartWidget.vue3.js.map +1 -1
  32. package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js +52 -8
  33. package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js.map +1 -1
  34. package/dist/esm/components/CnDetailPage/CnDetailPage.vue3.js +98 -63
  35. package/dist/esm/components/CnDetailPage/CnDetailPage.vue3.js.map +1 -1
  36. package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue.js +1 -1
  37. package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue2.js +48 -11
  38. package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue2.js.map +1 -1
  39. package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue3.js +160 -97
  40. package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue3.js.map +1 -1
  41. package/dist/esm/components/CnFormDialog/CnFormDialog.vue.js +1 -1
  42. package/dist/esm/components/CnFormDialog/CnFormDialog.vue2.js.map +1 -1
  43. package/dist/esm/components/CnFormDialog/CnFormDialog.vue3.js +2 -2
  44. package/dist/esm/components/CnFormDialog/CnFormDialog.vue3.js.map +1 -1
  45. package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js +203 -14
  46. package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js.map +1 -1
  47. package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js +19 -4
  48. package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js.map +1 -1
  49. package/dist/esm/components/CnIndexSidebar/CnIndexSidebar.vue2.js.map +1 -1
  50. package/dist/esm/components/CnIndexSidebar/CnIndexSidebar.vue3.js +1 -1
  51. package/dist/esm/components/CnIndexSidebar/CnIndexSidebar.vue3.js.map +1 -1
  52. package/dist/esm/components/CnNcDashboardList/CnNcDashboardList.vue.js +1 -1
  53. package/dist/esm/components/CnNcDashboardList/CnNcDashboardList.vue2.js +21 -1
  54. package/dist/esm/components/CnNcDashboardList/CnNcDashboardList.vue2.js.map +1 -1
  55. package/dist/esm/components/CnNcDashboardList/CnNcDashboardList.vue3.js.map +1 -1
  56. package/dist/esm/components/CnObjectCard/CnObjectCard.vue.js +1 -1
  57. package/dist/esm/components/CnObjectCard/CnObjectCard.vue2.js +36 -2
  58. package/dist/esm/components/CnObjectCard/CnObjectCard.vue2.js.map +1 -1
  59. package/dist/esm/components/CnObjectCard/CnObjectCard.vue3.js +44 -5
  60. package/dist/esm/components/CnObjectCard/CnObjectCard.vue3.js.map +1 -1
  61. package/dist/esm/components/CnPartyPicker/CnPartyPicker.vue.js +1 -0
  62. package/dist/esm/components/CnPartyPicker/CnPartyPicker.vue.js.map +1 -1
  63. package/dist/esm/components/CnPartyPicker/CnPartyPicker.vue2.js +22 -2
  64. package/dist/esm/components/CnPartyPicker/CnPartyPicker.vue2.js.map +1 -1
  65. package/dist/esm/components/CnPartyPicker/CnPartyPicker.vue3.js +36 -16
  66. package/dist/esm/components/CnPartyPicker/CnPartyPicker.vue3.js.map +1 -1
  67. package/dist/esm/components/CnSearchSelect/CnSearchSelect.vue.js +1 -1
  68. package/dist/esm/components/CnSearchSelect/CnSearchSelect.vue2.js.map +1 -1
  69. package/dist/esm/components/CnSearchSelect/CnSearchSelect.vue3.js.map +1 -1
  70. package/dist/esm/composables/useRefLabels.js +26 -6
  71. package/dist/esm/composables/useRefLabels.js.map +1 -1
  72. package/dist/esm/integrations/registry.js +4 -0
  73. package/dist/esm/integrations/registry.js.map +1 -1
  74. package/dist/esm/l10n/en.json.js +3 -1
  75. package/dist/esm/l10n/en.json.js.map +1 -1
  76. package/dist/esm/l10n/nl.json.js +3 -1
  77. package/dist/esm/l10n/nl.json.js.map +1 -1
  78. package/dist/esm/library-style.js +1 -1
  79. package/dist/esm/nextcloud-vue.css +630 -303
  80. package/dist/esm/store/plugins/liveUpdates.js +3 -1
  81. package/dist/esm/store/plugins/liveUpdates.js.map +1 -1
  82. package/dist/esm/store/plugins/logs.js +2 -1
  83. package/dist/esm/store/plugins/logs.js.map +1 -1
  84. package/dist/esm/utils/detailActionModel.js +28 -1
  85. package/dist/esm/utils/detailActionModel.js.map +1 -1
  86. package/dist/esm/utils/fillTemplate.js +13 -5
  87. package/dist/esm/utils/fillTemplate.js.map +1 -1
  88. package/dist/esm/utils/headerFieldChips.js +21 -2
  89. package/dist/esm/utils/headerFieldChips.js.map +1 -1
  90. package/dist/esm/utils/mapList.js +26 -11
  91. package/dist/esm/utils/mapList.js.map +1 -1
  92. package/dist/esm/utils/savedViewHelpers.js +40 -3
  93. package/dist/esm/utils/savedViewHelpers.js.map +1 -1
  94. package/dist/esm/utils/savedViewMenu.js +12 -5
  95. package/dist/esm/utils/savedViewMenu.js.map +1 -1
  96. package/dist/esm/utils/validateManifestV2.compiled.js +3 -3
  97. package/dist/esm/utils/validateManifestV2.compiled.js.map +1 -1
  98. package/dist/nextcloud-vue.cjs.js +2760 -1995
  99. package/dist/nextcloud-vue.cjs.js.map +2 -2
  100. package/dist/nextcloud-vue.css +630 -303
  101. package/l10n/en.json +3 -1
  102. package/l10n/nl.json +3 -1
  103. package/package.json +1 -1
  104. package/src/components/CnActionDialog/CnActionDialog.vue +32 -9
  105. package/src/components/CnAppRoot/CnAppRoot.vue +2 -1
  106. package/src/components/CnAssignDialog/CnAssignDialog.vue +4 -2
  107. package/src/components/CnBoardView/CnBoardView.vue +58 -5
  108. package/src/components/CnCardGrid/CnCardGrid.md +1 -0
  109. package/src/components/CnCardGrid/CnCardGrid.vue +11 -0
  110. package/src/components/CnCellRenderer/CnCellRenderer.vue +27 -3
  111. package/src/components/CnChartWidget/CnChartWidget.vue +6 -0
  112. package/src/components/CnDetailPage/CnDetailPage.vue +77 -20
  113. package/src/components/CnDetailWidgetHost/CnDetailWidgetHost.vue +100 -5
  114. package/src/components/CnFormDialog/CnFormDialog.vue +1 -1
  115. package/src/components/CnIndexPage/CnIndexPage.md +1 -1
  116. package/src/components/CnIndexPage/CnIndexPage.vue +211 -16
  117. package/src/components/CnIndexSidebar/CnIndexSidebar.md +1 -1
  118. package/src/components/CnIndexSidebar/CnIndexSidebar.vue +2 -2
  119. package/src/components/CnNcDashboardList/CnNcDashboardList.vue +21 -1
  120. package/src/components/CnObjectCard/CnObjectCard.md +1 -0
  121. package/src/components/CnObjectCard/CnObjectCard.vue +51 -5
  122. package/src/components/CnPartyPicker/CnPartyPicker.vue +62 -16
  123. package/src/components/CnSearchSelect/CnSearchSelect.vue +8 -0
  124. package/src/composables/useRefLabels.js +25 -5
  125. package/src/css/board.css +5 -2
  126. package/src/css/dialog.css +53 -3
  127. package/src/css/index-page.css +26 -1
  128. package/src/css/look-board-detail.css +55 -22
  129. package/src/css/look-board-index.css +82 -12
  130. package/src/css/look-board-reports.css +1 -1
  131. package/src/css/look-board.css +84 -11
  132. package/src/integrations/registry.js +4 -0
  133. package/src/schemas/app-manifest-v2.schema.json +11 -5
  134. package/src/store/plugins/liveUpdates.js +3 -1
  135. package/src/store/plugins/logs.js +2 -1
  136. package/src/utils/detailActionModel.js +27 -0
  137. package/src/utils/fillTemplate.js +13 -5
  138. package/src/utils/headerFieldChips.js +21 -2
  139. package/src/utils/mapList.js +26 -11
  140. package/src/utils/savedViewHelpers.js +39 -2
  141. package/src/utils/savedViewMenu.js +12 -5
  142. package/src/utils/validateManifestV2.compiled.js +3 -3
@@ -20,6 +20,12 @@
20
20
  /* Card h2 and side heading. */
21
21
  --cn-board-heading-size: 17px;
22
22
  --cn-board-side-heading-size: 15px;
23
+ /* The boards set text at the font's normal line height (1.2 for Fira
24
+ Sans), Nextcloud at 1.5: a card body's first line carries this much
25
+ half-leading above its glyphs that a board does not draw. A gap the
26
+ boards measure from a title to the text under it is the board's value
27
+ minus this. Resolved in the element that uses it. */
28
+ --cn-board-first-line-leading: 0.15em;
23
29
  }
24
30
 
25
31
  /* ---- The header: two rows on the ground ------------------------------- */
@@ -75,7 +81,7 @@
75
81
  height: var(--cn-board-control-height) !important;
76
82
  min-height: var(--cn-board-control-height) !important;
77
83
  padding: 0 14px !important;
78
- border: 1px solid var(--color-border-dark) !important;
84
+ border: 1px solid var(--cn-board-control-border) !important;
79
85
  border-radius: var(--cn-board-control-radius) !important;
80
86
  background: var(--color-main-background) !important;
81
87
  color: var(--color-main-text) !important;
@@ -88,13 +94,13 @@
88
94
  background: var(--color-background-hover) !important;
89
95
  }
90
96
 
91
- /* Each header icon is 16px with 8px to its label; NcButton draws 20px in a 30px slot. */
97
+ /* Each header icon is 16px; NcButton draws 20px in a 30px slot. The 8px to
98
+ the label is the board's icon-and-label gap (look-board.css). */
92
99
  .cn-look-board .cn-detail-page .cn-detail-page__header-actions > .button-vue--secondary .button-vue__icon {
93
100
  width: 16px;
94
101
  min-width: 16px;
95
102
  height: 16px;
96
103
  min-height: 16px;
97
- margin-inline-end: 8px;
98
104
  }
99
105
 
100
106
  .cn-look-board .cn-detail-page .cn-detail-page__header-actions > .button-vue--secondary .button-vue__icon svg {
@@ -102,6 +108,17 @@
102
108
  height: 16px;
103
109
  }
104
110
 
111
+ /* Row 3: the Follow control under the breadcrumb, on the full width.
112
+ @spec openspec/changes/board-follow-row/specs/board-follow-row/spec.md#requirement-the-board-follow-control-sits-under-the-breadcrumb */
113
+ .cn-look-board .cn-detail-page__header-row3 {
114
+ align-items: center;
115
+ display: flex;
116
+ flex: 1 0 100%;
117
+ flex-wrap: wrap;
118
+ gap: 8px;
119
+ min-width: 0;
120
+ }
121
+
105
122
  /* Row 2: pills, breadcrumb, dot, meta, chips. */
106
123
  .cn-look-board .cn-detail-page__header-row2 {
107
124
  align-items: center;
@@ -201,24 +218,27 @@
201
218
  widget's 4px pad is room for the 32px circles, which the bars variant does
202
219
  not draw), the label 8px under its bar and the date 8px under the label at
203
220
  the normal line height, open steps muted and the done and current ones in
204
- the main text. Each hands its ink to --nldesign-color-on-surface, which a
205
- theme that forces the body ink onto every span (thematiq) reads instead. */
221
+ the main text. Each sets its ink as `color`, and also hands it to
222
+ --nldesign-color-on-surface for a theme that still forces the body ink. */
206
223
  .cn-look-board .cn-stages-widget:has(> .cn-stages-widget__bars):not(.cn-look-nextcloud *) {
207
224
  padding: 0;
208
225
  }
209
226
 
210
227
  .cn-look-board .cn-stages-widget__bars .cn-stages-widget__bar-label:not(.cn-look-nextcloud *) {
211
228
  --nldesign-color-on-surface: var(--color-text-maxcontrast);
229
+ color: var(--color-text-maxcontrast);
212
230
  line-height: normal;
213
231
  }
214
232
 
215
233
  .cn-look-board .cn-stages-widget__bars .cn-stages-widget__bar-step--done .cn-stages-widget__bar-label:not(.cn-look-nextcloud *),
216
234
  .cn-look-board .cn-stages-widget__bars .cn-stages-widget__bar-step--current .cn-stages-widget__bar-label:not(.cn-look-nextcloud *) {
217
235
  --nldesign-color-on-surface: var(--color-main-text);
236
+ color: var(--color-main-text);
218
237
  }
219
238
 
220
239
  .cn-look-board .cn-stages-widget__bars .cn-stages-widget__bar-date:not(.cn-look-nextcloud *) {
221
240
  --nldesign-color-on-surface: var(--color-text-maxcontrast);
241
+ color: var(--color-text-maxcontrast);
222
242
  line-height: normal;
223
243
  }
224
244
 
@@ -259,14 +279,14 @@
259
279
  --nldesign-component-button-border-radius: 14px;
260
280
  --nldesign-component-button-secondary-action-color: var(--color-main-text);
261
281
  --nldesign-component-button-secondary-action-background-color: var(--color-main-background);
262
- --nldesign-component-button-secondary-action-border-color: var(--color-border-dark);
282
+ --nldesign-component-button-secondary-action-border-color: var(--cn-board-control-border);
263
283
  --nldesign-component-button-secondary-action-hover-background-color: var(--color-background-hover);
264
284
  box-sizing: border-box;
265
285
  height: 28px;
266
286
  min-height: 28px;
267
287
  min-width: 0;
268
288
  padding: 0 10px;
269
- border: 1px solid var(--color-border-dark);
289
+ border: 1px solid var(--cn-board-control-border);
270
290
  border-radius: 14px;
271
291
  background: var(--color-main-background);
272
292
  color: var(--color-main-text);
@@ -356,13 +376,15 @@
356
376
  The nldesign theme sets every button's weight and radius with `!important`
357
377
  through its button tokens, which drew every tab bold with four rounded
358
378
  corners; the tab hands the board's values to those tokens. A tab is 37px
359
- with or without a count (DqZaak), not 34px without one.
379
+ with or without a count (DqZaak), not 34px without one. Its outline is
380
+ the widget card's border, so tab and card meet in one line.
381
+ @spec openspec/changes/board-tabs-widget-border/specs/board-tabs-widget-border/spec.md#requirement-board-folder-tabs-draw-the-widget-card-border
360
382
  @spec openspec/changes/board-tabs-theme/specs/board-tabs-theme/spec.md#requirement-board-folder-tabs-keep-the-boards-weight-shape-and-height-under-a-theme */
361
383
  .cn-look-board .cn-tabs--board .cn-tabs__nav-item {
362
384
  --nldesign-component-button-font-weight: 400;
363
385
  --nldesign-component-button-border-radius: 8px 8px 0 0;
364
386
  background-color: var(--color-background-dark);
365
- border: 1px solid var(--color-border-dark);
387
+ border: 1px solid var(--color-border);
366
388
  border-bottom: none;
367
389
  border-radius: 8px 8px 0 0;
368
390
  font-size: 14px;
@@ -377,7 +399,7 @@
377
399
  --nldesign-component-button-font-weight: 700;
378
400
  background-color: var(--color-main-background);
379
401
  border-bottom: 1px solid var(--color-main-background);
380
- border-top: 1px solid var(--color-border-dark);
402
+ border-top: 1px solid var(--color-border);
381
403
  font-weight: 700;
382
404
  min-height: 38px;
383
405
  padding-bottom: 9px;
@@ -404,13 +426,14 @@
404
426
 
405
427
  /* The Actions button at the end of the strip: at the top, 8px in from the
406
428
  end and 8px clear of the card, so the tabs, aligned to the bottom, sit 6px
407
- lower than the button (DqZaak "Acties"). */
429
+ lower than the button, 12px in at both sides (DqZaak "Acties"). */
408
430
  .cn-look-board .cn-tabs--board .cn-tabs__nav-end {
409
431
  align-self: flex-start;
410
432
  margin: 0 8px 8px 0;
411
433
  }
412
434
 
413
435
  .cn-look-board .cn-tabs--board .cn-tabs__nav-end .button-vue {
436
+ --button-padding: 12px;
414
437
  min-height: 34px;
415
438
  block-size: 34px;
416
439
  }
@@ -487,15 +510,17 @@
487
510
  .cn-look-board .cn-detail-card .cn-detail-card__title {
488
511
  font-size: var(--cn-board-heading-size);
489
512
  font-weight: 700;
490
- line-height: 1.3;
513
+ line-height: normal;
491
514
  }
492
515
 
516
+ /* 12px from the title's glyphs to the first line's glyphs, as drawn.
517
+ @spec openspec/changes/board-card-title-gap/specs/board-card-title-gap/spec.md#requirement-a-board-cards-body-starts-the-boards-gap-below-its-title */
493
518
  .cn-look-board .cn-detail-page .cn-widget-wrapper__content {
494
- padding: 12px 22px 20px;
519
+ padding: calc(12px - var(--cn-board-first-line-leading)) 22px 20px;
495
520
  }
496
521
 
497
522
  .cn-look-board .cn-detail-card .cn-detail-card__content {
498
- padding: 12px 22px 20px;
523
+ padding: calc(12px - var(--cn-board-first-line-leading)) 22px 20px;
499
524
  }
500
525
 
501
526
  /* A header-less card keeps the full 20px 22px. */
@@ -503,13 +528,18 @@
503
528
  padding: var(--cn-board-card-padding);
504
529
  }
505
530
 
506
- /* The data card: 200px columns, a 12px 24px gap, label over value, hairline. */
507
- .cn-look-board .cn-object-data-widget__grid {
531
+ /* The data card: 200px columns, a 12px 24px gap, label over value, hairline.
532
+ Each selector holds one class more than the component's scoped rule
533
+ (`.cn-object-data-widget__cell[data-v-...]`), which loads after this sheet:
534
+ at equal specificity the cell kept its 8px top padding and the grid its 8px
535
+ gap, so the first label sat 8px further below the card's title.
536
+ @spec openspec/changes/board-card-title-gap/specs/board-card-title-gap/spec.md#requirement-the-data-cards-grid-keeps-the-boards-gap-and-cell-padding */
537
+ .cn-look-board .cn-object-data-widget__grid-wrap .cn-object-data-widget__grid {
508
538
  font-size: 15px;
509
539
  gap: 12px 24px;
510
540
  }
511
541
 
512
- .cn-look-board .cn-object-data-widget__cell {
542
+ .cn-look-board .cn-object-data-widget__grid .cn-object-data-widget__cell {
513
543
  border-bottom: 1px solid var(--cn-board-hairline);
514
544
  gap: 2px;
515
545
  padding: 0 0 10px;
@@ -557,7 +587,7 @@
557
587
  }
558
588
 
559
589
  .cn-look-board .cn-detail-page__side .cn-widget-wrapper__content {
560
- padding: 10px 22px 20px;
590
+ padding: calc(10px - var(--cn-board-first-line-leading)) 22px 20px;
561
591
  }
562
592
 
563
593
  /* A stat tile in a side card (DqZaak "Termijn") sits on the card's inset as
@@ -674,21 +704,24 @@
674
704
  font-size: 13px;
675
705
  }
676
706
 
677
- /* Done and open steps are muted, the current one in the main text. Each hands
678
- its ink to --nldesign-color-on-surface, which a theme that forces the body
679
- ink onto every li and span (thematiq) reads instead. */
707
+ /* Done and open steps are muted, the current one in the main text. Each sets
708
+ its ink as `color`, and also hands it to --nldesign-color-on-surface for a
709
+ theme that still forces the body ink. */
680
710
  .cn-look-board .cn-next-step-card--board .cn-next-step-card__item,
681
711
  .cn-look-board .cn-next-step-card--board .cn-next-step-card__hint,
682
712
  .cn-look-board .cn-next-step-card--board .cn-next-step-card__after {
683
713
  --nldesign-color-on-surface: var(--color-text-maxcontrast);
714
+ color: var(--color-text-maxcontrast);
684
715
  }
685
716
 
686
717
  .cn-look-board .cn-next-step-card--board .cn-next-step-card__item--current {
687
718
  --nldesign-color-on-surface: var(--color-main-text);
719
+ color: var(--color-main-text);
688
720
  }
689
721
 
690
722
  .cn-look-board .cn-next-step-card--board .cn-next-step-card__item--current .cn-next-step-card__hint {
691
723
  --nldesign-color-on-surface: var(--color-text-maxcontrast);
724
+ color: var(--color-text-maxcontrast);
692
725
  }
693
726
 
694
727
  /* ---- History: the activity tab ------------------------------------------ */
@@ -734,7 +767,7 @@
734
767
  .cn-look-board .cn-activity-tab--board .cn-activity-tab__kind {
735
768
  align-items: center;
736
769
  background: var(--color-main-background);
737
- border: 1px solid var(--color-border-dark);
770
+ border: 1px solid var(--cn-board-control-border);
738
771
  border-radius: 18px;
739
772
  color: var(--color-main-text);
740
773
  cursor: pointer;
@@ -60,7 +60,7 @@
60
60
  height: var(--cn-board-control-height) !important;
61
61
  min-height: var(--cn-board-control-height) !important;
62
62
  padding: 0 14px !important;
63
- border: 1px solid var(--color-border-dark) !important;
63
+ border: 1px solid var(--cn-board-control-border) !important;
64
64
  border-radius: var(--cn-board-control-radius) !important;
65
65
  background: var(--color-main-background) !important;
66
66
  color: var(--color-main-text) !important;
@@ -184,7 +184,7 @@
184
184
  min-height: 38px;
185
185
  margin: 0;
186
186
  padding: 0 14px;
187
- border: 1px solid var(--color-border-dark);
187
+ border: 1px solid var(--cn-board-control-border);
188
188
  border-radius: 19px;
189
189
  background: var(--color-main-background);
190
190
  color: var(--color-main-text);
@@ -219,9 +219,12 @@
219
219
  color: var(--color-main-background);
220
220
  }
221
221
 
222
- /* The count badge: grey on an idle chip, soft text colour on the selected one. */
222
+ /* The count badge: grey on an idle chip, soft text colour on the selected one.
223
+ Its ink also goes to --nldesign-color-on-surface, which a theme that forces
224
+ the body ink onto every span (thematiq) reads. */
223
225
  .cn-look-board .cn-saved-views__chip .cn-saved-views__chip-count,
224
226
  .cn-look-board .cn-quick-filter-bar .cn-quick-filter-bar__count {
227
+ --nldesign-color-on-surface: var(--cn-board-text-soft);
225
228
  min-width: 0;
226
229
  padding: 1px 7px;
227
230
  border: 0;
@@ -230,22 +233,25 @@
230
233
  color: var(--cn-board-text-soft);
231
234
  font-size: 12px;
232
235
  font-weight: 600;
233
- line-height: 1.4;
236
+ /* 16px tall on its 1px pad, as the boards draw it (DqTaken, DqWerkbord).
237
+ @spec openspec/changes/board-pill-tones/specs/board-pill-tones/spec.md#requirement-a-board-count-is-16px-tall */
238
+ line-height: 14px;
234
239
  }
235
240
 
236
241
  .cn-look-board .cn-saved-views__chip--selected .cn-saved-views__chip-count,
237
- /* On the selected chip the count is a lighter bubble on the dark chip
238
- (DqZaken: #3d4047 on #1b1c1d); --cn-board-text-soft resolves to the main
239
- text, the chip's own colour, which hid the bubble. */
242
+ /* On the selected chip the count is the soft ink as a lighter bubble on the
243
+ dark chip (DqZaken: #3d4047 on #1b1c1d). */
240
244
  .cn-look-board .cn-quick-filter-bar .cn-quick-filter-bar__tab--active .cn-quick-filter-bar__count {
241
245
  --nldesign-color-on-surface: var(--color-primary-element-text);
242
- background: color-mix(in srgb, var(--color-main-background) 15%, var(--color-main-text));
246
+ background: var(--cn-board-text-soft);
243
247
  color: var(--color-primary-element-text);
244
248
  }
245
249
 
246
250
  /* Save view: a ghost button, 34px, radius 17, no border, on the light primary
247
- tint, a 14px icon 6px before the label, on one line. */
251
+ tint, a 14px icon 6px before the label, on one line. The label is a span,
252
+ so its ink also goes to --nldesign-color-on-surface. */
248
253
  .cn-look-board .cn-saved-views__save .button-vue {
254
+ --nldesign-color-on-surface: var(--color-primary-element-light-text);
249
255
  min-height: 34px;
250
256
  height: 34px;
251
257
  padding: 0 12px;
@@ -286,9 +292,10 @@
286
292
  @spec openspec/changes/board-toolbar-buttons-theme/specs/board-toolbar-buttons-theme/spec.md#requirement-board-toolbar-buttons-are-neutral-under-a-theme */
287
293
  .cn-look-board .cn-actions-bar:not(.cn-look-nextcloud *) {
288
294
  --nldesign-component-button-font-weight: 600;
295
+ --nldesign-component-button-color: var(--color-main-text);
289
296
  --nldesign-component-button-secondary-action-color: var(--color-main-text);
290
297
  --nldesign-component-button-secondary-action-background-color: var(--color-main-background);
291
- --nldesign-component-button-secondary-action-border-color: var(--color-border-dark);
298
+ --nldesign-component-button-secondary-action-border-color: var(--cn-board-control-border);
292
299
  --nldesign-component-button-secondary-action-hover-background-color: var(--color-background-hover);
293
300
  }
294
301
 
@@ -315,6 +322,8 @@
315
322
  margin-inline-start: 6px;
316
323
  padding: 0 6px;
317
324
  border-radius: 10px;
325
+ /* A theme that forces the body ink onto every span reads it from here. */
326
+ --nldesign-color-on-surface: var(--color-primary-element-text);
318
327
  background: var(--color-primary-element);
319
328
  color: var(--color-primary-element-text);
320
329
  font-size: 12px;
@@ -423,7 +432,7 @@
423
432
  height: 40px;
424
433
  padding-block: 0;
425
434
  padding-inline: 38px 12px !important;
426
- border: 1px solid var(--color-border-dark);
435
+ border: 1px solid var(--cn-board-control-border);
427
436
  border-radius: 8px;
428
437
  font-size: 14px;
429
438
  }
@@ -433,7 +442,10 @@
433
442
  font-size: 14px;
434
443
  }
435
444
 
445
+ /* An active filter: the light primary tint, its label (a span) in the tint's
446
+ ink through --nldesign-color-on-surface too. */
436
447
  .cn-look-board .cn-actions-bar--board .cn-actions-bar__filter-chip {
448
+ --nldesign-color-on-surface: var(--color-primary-element-light-text);
437
449
  display: inline-flex;
438
450
  align-items: center;
439
451
  gap: 6px;
@@ -577,9 +589,13 @@
577
589
  line-height: normal;
578
590
  }
579
591
 
592
+ /* The sort button is the bare label, square (the boards draw no box round
593
+ it); the funnel after it is a 22px button with a 4px radius. Both outrank
594
+ the 8px element radius the table and Nextcloud's `button` rule give them. */
580
595
  .cn-look-board .cn-table-container--board .cn-data-table th .cn-table-header__sort {
581
596
  min-height: 0;
582
597
  height: auto;
598
+ border-radius: 0;
583
599
  line-height: inherit;
584
600
  }
585
601
 
@@ -635,6 +651,7 @@
635
651
  min-width: 22px;
636
652
  height: 22px;
637
653
  min-height: 22px;
654
+ border-radius: 4px;
638
655
  margin-inline-start: 4px;
639
656
  }
640
657
 
@@ -800,7 +817,7 @@
800
817
  height: 34px !important;
801
818
  min-height: 34px !important;
802
819
  padding: 0 !important;
803
- border: 1px solid var(--color-border-dark) !important;
820
+ border: 1px solid var(--cn-board-control-border) !important;
804
821
  border-radius: 8px !important;
805
822
  color: var(--cn-board-text-soft) !important;
806
823
  }
@@ -843,6 +860,8 @@
843
860
  margin-inline-start: auto;
844
861
  }
845
862
 
863
+ /* A page link is a <button>: Nextcloud's `button` rule sets it bold, the
864
+ boards set the links at the regular weight and only the current page at 600. */
846
865
  .cn-look-board .cn-pagination--board .cn-pagination__board-link {
847
866
  box-sizing: border-box;
848
867
  min-width: 34px;
@@ -855,6 +874,7 @@
855
874
  background: var(--color-main-background);
856
875
  color: var(--color-main-text);
857
876
  font-size: 14px;
877
+ font-weight: 400;
858
878
  cursor: pointer;
859
879
  }
860
880
 
@@ -1275,3 +1295,53 @@
1275
1295
  font-size: 20px;
1276
1296
  font-weight: 700;
1277
1297
  }
1298
+
1299
+ /* ---- Side panel cards --------------------------------------------------- */
1300
+ /* A card beside the list is the board's side card (DqTeamwachtrij "Team
1301
+ vandaag", "Werkvoorraad per zaaktype"): no rule under the header, the
1302
+ title a 15px muted label on the card's 20px 22px inset, 12px above the
1303
+ body, 20px between cards. The wrapper drew the Nextcloud panel: a 14px
1304
+ dark title on a 12px 16px header over a rule, 16px between cards. The
1305
+ tone carries `!important` against a theme that colours every h3.
1306
+ @spec openspec/changes/board-index-side-panel-cards/specs/board-index-side-panel-cards/spec.md#requirement-a-board-index-side-panel-card-is-the-boards-side-card */
1307
+ .cn-look-board .cn-index-page-widgets--side-panel:not(.cn-look-nextcloud *) {
1308
+ gap: var(--cn-board-section-gap, 20px);
1309
+ }
1310
+
1311
+ .cn-look-board .cn-index-page-widgets--side-panel:not(.cn-look-nextcloud *) .cn-widget-wrapper__header {
1312
+ border-bottom: none;
1313
+ padding: 20px 22px 0;
1314
+ }
1315
+
1316
+ .cn-look-board .cn-index-page-widgets--side-panel:not(.cn-look-nextcloud *) .cn-widget-wrapper__title {
1317
+ color: var(--color-text-maxcontrast) !important;
1318
+ font-size: var(--cn-board-side-heading-size, 15px);
1319
+ font-weight: 600;
1320
+ line-height: normal;
1321
+ }
1322
+
1323
+ .cn-look-board .cn-index-page-widgets--side-panel:not(.cn-look-nextcloud *) .cn-widget-wrapper__content {
1324
+ padding: calc(12px - var(--cn-board-first-line-leading, 0.15em)) 22px 20px;
1325
+ }
1326
+
1327
+ .cn-look-board .cn-index-page-widgets--side-panel:not(.cn-look-nextcloud *) .cn-index-page-widgets__note {
1328
+ font-size: 13px;
1329
+ }
1330
+
1331
+ /* A record list drawn as a table (DqTeamwachtrij "Werkvoorraad per
1332
+ zaaktype") is the board's compact grid: a 13px muted header at regular
1333
+ weight, rows 8px apart, no rules between them. Line heights differ from
1334
+ the board's normal ones, so the cell padding sets the board's row pitch.
1335
+ One class more than the component's scoped rules, which load later.
1336
+ @spec openspec/changes/board-index-side-panel-cards/specs/board-index-side-panel-cards/spec.md#requirement-a-board-record-list-table-is-the-boards-compact-grid */
1337
+ .cn-look-board .cn-record-list--table .cn-record-list__table th {
1338
+ border-bottom: none;
1339
+ font-size: 13px;
1340
+ font-weight: 400;
1341
+ padding-block: 0 2px;
1342
+ }
1343
+
1344
+ .cn-look-board .cn-record-list--table .cn-record-list__table td {
1345
+ border-bottom: none;
1346
+ padding-block: 2px;
1347
+ }
@@ -150,7 +150,7 @@
150
150
  height: var(--cn-board-control-height) !important;
151
151
  min-height: var(--cn-board-control-height) !important;
152
152
  padding: 0 14px !important;
153
- border: 1px solid var(--color-border-dark) !important;
153
+ border: 1px solid var(--cn-board-control-border) !important;
154
154
  border-radius: var(--cn-board-control-radius) !important;
155
155
  background: var(--color-main-background) !important;
156
156
  color: var(--color-main-text) !important;
@@ -24,14 +24,19 @@
24
24
  /* Buttons and inputs. */
25
25
  --cn-board-control-height: 40px;
26
26
  --cn-board-control-radius: 8px;
27
+ /* A control's edge: 3:1 against every ground a control sits on (WCAG
28
+ 1.4.11). Nextcloud's border-dark is a hairline (#dbdbdb, 1.4:1); its
29
+ max-contrast border is the control step, and a theme sets both. */
30
+ --cn-board-control-border: var(--color-border-maxcontrast);
27
31
  /* Cards. */
28
32
  --cn-board-card-radius: 12px;
29
33
  --cn-board-card-padding: 20px 22px;
30
34
  /* The side inset of a dashboard card: its title and its rows. */
31
35
  --cn-board-dashboard-card-inset: 24px;
32
- /* Hairline inside a card, and the soft secondary text. */
36
+ /* Hairline inside a card, and the soft secondary text: the boards' #3d4047,
37
+ between the main text and the muted text, so it follows a theme's pair. */
33
38
  --cn-board-hairline: var(--color-border);
34
- --cn-board-text-soft: var(--color-main-text);
39
+ --cn-board-text-soft: color-mix(in srgb, var(--color-main-text) 45%, var(--color-text-maxcontrast));
35
40
  }
36
41
 
37
42
  /*
@@ -183,6 +188,47 @@
183
188
  --font-weight-element: 600;
184
189
  }
185
190
 
191
+ /* ---- A button with an icon and a label --------------------------------- */
192
+ /* The boards draw it 14px in at both sides with 14px text and a 16px icon
193
+ 8px from its label (DqZaakEmail "Notitie toevoegen", DqVthInstellingen
194
+ "Regel toevoegen"). NcButton pads its start 4px and its end 12px, and puts
195
+ a 20px icon in a 30px slot. The rules hold the condition in `:where()`, so
196
+ they weigh (0,3,0): enough to outrank NcButton's own (0,2,0), and less than
197
+ any surface rule (header, toolbar, follow pill, Meer chevron, tab strip),
198
+ which keeps its own value. The padding goes through NcButton's
199
+ `--button-padding`, so a surface that sets `padding` is never contested.
200
+ @spec openspec/changes/board-icon-label-button/specs/board-icon-label-button/spec.md#requirement-a-board-button-with-an-icon-and-a-label-is-padded-as-the-boards-draw-it */
201
+ .cn-look-board .button-vue.button-vue:where(:has(> .button-vue__wrapper > .button-vue__icon:not(:empty)):has(> .button-vue__wrapper > .button-vue__text:not(:empty)):not(.cn-look-nextcloud *):not(.vue-crumb *)) {
202
+ --button-padding: 14px;
203
+ font-size: 14px;
204
+ }
205
+
206
+ .cn-look-board :where(.button-vue:has(> .button-vue__wrapper > .button-vue__icon:not(:empty)):has(> .button-vue__wrapper > .button-vue__text:not(:empty)):not(.cn-look-nextcloud *):not(.vue-crumb *)) .button-vue__wrapper.button-vue__wrapper {
207
+ gap: 8px;
208
+ }
209
+
210
+ .cn-look-board :where(.button-vue:has(> .button-vue__wrapper > .button-vue__icon:not(:empty)):has(> .button-vue__wrapper > .button-vue__text:not(:empty)):not(.cn-look-nextcloud *):not(.vue-crumb *)) .button-vue__icon.button-vue__icon {
211
+ width: 16px;
212
+ min-width: 16px;
213
+ height: 16px;
214
+ min-height: 16px;
215
+ }
216
+
217
+ .cn-look-board :where(.button-vue:has(> .button-vue__wrapper > .button-vue__icon:not(:empty)):has(> .button-vue__wrapper > .button-vue__text:not(:empty)):not(.cn-look-nextcloud *):not(.vue-crumb *)) .button-vue__icon svg {
218
+ width: 16px;
219
+ height: 16px;
220
+ }
221
+
222
+ /* ---- A single select -------------------------------------------------- */
223
+ /* NcSelect draws a single select as its search field with the clear and
224
+ open buttons laid over its end. A legacy vue-select rule that Nextcloud
225
+ still loads caps the field at the width less one clickable area, which
226
+ left those buttons outside the field's border (DqNieuweZaak "Zaaktype",
227
+ "Intakekanaal"). */
228
+ .cn-look-board .nc-select.v-select.select.vs--single .vs__selected-options {
229
+ max-width: none;
230
+ }
231
+
186
232
  /* ---- The header button ------------------------------------------------- */
187
233
  .cn-look-board .cn-index-page__header-buttons:not(.cn-look-nextcloud *),
188
234
  .cn-look-board .cn-detail-page__header-actions:not(.cn-look-nextcloud *),
@@ -212,7 +258,7 @@
212
258
  --nldesign-component-button-primary-action-font-weight: 600;
213
259
  --nldesign-component-button-secondary-action-color: var(--color-main-text);
214
260
  --nldesign-component-button-secondary-action-background-color: var(--color-main-background);
215
- --nldesign-component-button-secondary-action-border-color: var(--color-border-dark);
261
+ --nldesign-component-button-secondary-action-border-color: var(--cn-board-control-border);
216
262
  --nldesign-component-button-secondary-action-hover-background-color: var(--color-background-hover);
217
263
  }
218
264
 
@@ -226,7 +272,7 @@
226
272
  min-height: var(--cn-board-control-height);
227
273
  padding: 0 14px;
228
274
  gap: 8px;
229
- border: 1px solid var(--color-border-dark);
275
+ border: 1px solid var(--cn-board-control-border);
230
276
  border-radius: var(--cn-board-control-radius);
231
277
  background: var(--color-main-background);
232
278
  color: var(--color-main-text);
@@ -258,7 +304,7 @@
258
304
  height: var(--cn-board-control-height);
259
305
  min-height: var(--cn-board-control-height);
260
306
  padding: 0 14px;
261
- border: 1px solid var(--color-border-dark);
307
+ border: 1px solid var(--cn-board-control-border);
262
308
  border-radius: var(--cn-board-control-radius);
263
309
  background: var(--color-main-background);
264
310
  color: var(--color-main-text);
@@ -266,8 +312,9 @@
266
312
  font-weight: 600;
267
313
  }
268
314
 
269
- /* Buttons 10px apart, each icon 16px with 8px to its label (DqZaak's header,
270
- DqZaken's "Downloaden"); NcButton draws a 20px icon in a 30px slot. */
315
+ /* Buttons 10px apart, each icon 16px (DqZaak's header, DqZaken's
316
+ "Downloaden"); NcButton draws a 20px icon in a 30px slot. The 8px to the
317
+ label is the board's icon-and-label gap above. */
271
318
  .cn-look-board .cn-action-buttons:not(.cn-look-nextcloud *) {
272
319
  gap: 10px;
273
320
  }
@@ -277,7 +324,6 @@
277
324
  min-width: 16px;
278
325
  height: 16px;
279
326
  min-height: 16px;
280
- margin-inline-end: 8px;
281
327
  }
282
328
 
283
329
  .cn-look-board .cn-action-buttons .button-vue .button-vue__icon:not(.cn-look-nextcloud *) svg {
@@ -312,7 +358,7 @@
312
358
  body ink onto every span (thematiq). */
313
359
  .cn-look-board .action-item.action-item--secondary .action-item__menutoggle.button-vue--secondary:not(.cn-look-nextcloud *) {
314
360
  --nldesign-color-on-surface: var(--color-main-text);
315
- border: 1px solid var(--color-border-dark);
361
+ border: 1px solid var(--cn-board-control-border);
316
362
  border-radius: var(--cn-board-control-radius);
317
363
  background: var(--color-main-background);
318
364
  color: var(--color-main-text);
@@ -1109,6 +1155,15 @@
1109
1155
  line-height: normal;
1110
1156
  }
1111
1157
 
1158
+ /* A neutral board tag ("Normaal", "Uit") is the soft text on the chip ground,
1159
+ not the main text on the darker background a Nextcloud tag takes.
1160
+ @spec openspec/changes/board-pill-tones/specs/board-pill-tones/spec.md#requirement-a-neutral-board-tag-is-soft-text-on-the-chip-ground */
1161
+ .cn-look-board .cn-status-badge--default:not(.cn-status-badge--solid):not(.cn-look-nextcloud *) {
1162
+ --cn-status-badge-ink: var(--cn-board-text-soft);
1163
+ background-color: var(--color-background-hover);
1164
+ color: var(--cn-status-badge-ink);
1165
+ }
1166
+
1112
1167
  /* A pill paints its own pairing of ink and fill. A theme that forces the body
1113
1168
  ink onto every span (thematiq's text rule, `!important` at id level) reads
1114
1169
  that ink from --nldesign-color-on-surface when the surface sets it, so the
@@ -1233,7 +1288,7 @@
1233
1288
  .cn-look-board .cn-dashboard-page:not(.cn-look-nextcloud *) .cn-widget-wrapper:not(.cn-widget-wrapper--nc-dashboard) .cn-widget-wrapper__title {
1234
1289
  font-size: var(--cn-board-heading-size, 17px);
1235
1290
  font-weight: 700;
1236
- line-height: 1.3;
1291
+ line-height: normal;
1237
1292
  }
1238
1293
 
1239
1294
  /* The board draws no rule under a dashboard card's title (DqMijnWerk,
@@ -1247,7 +1302,7 @@
1247
1302
  }
1248
1303
 
1249
1304
  .cn-look-board .cn-dashboard-page:not(.cn-look-nextcloud *) .cn-widget-wrapper:not(.cn-widget-wrapper--nc-dashboard):not(.cn-widget-wrapper--borderless) .cn-widget-wrapper__header {
1250
- padding: 20px var(--cn-board-dashboard-card-inset) 12px;
1305
+ padding: 20px var(--cn-board-dashboard-card-inset) calc(12px - var(--cn-board-first-line-leading, 0.15em));
1251
1306
  }
1252
1307
 
1253
1308
  /* ---- Record list on a dashboard card (PtDashboard) ---------------------- */
@@ -1442,3 +1497,21 @@
1442
1497
  .cn-look-board .cn-dashboard-page:not(.cn-look-nextcloud *) .cn-stats-block-widget--tiles-box {
1443
1498
  padding: 14px 22px 20px;
1444
1499
  }
1500
+
1501
+ /* ---- Matrix chart (DqProcesanalyse "Dagen per fase") -------------------- */
1502
+ /* The board sets the matrix at 14px and the font's normal line height: the
1503
+ column heads and the cell figures at 600, a cell 37px with its 10px
1504
+ padding. Nextcloud's 15px at 1.5 made each row 42.5px.
1505
+ @spec openspec/changes/board-matrix-cells/specs/board-matrix-cells/spec.md#requirement-a-board-matrix-takes-the-boards-type */
1506
+ .cn-look-board .cn-chart-widget__matrix:not(.cn-look-nextcloud *) {
1507
+ font-size: 14px;
1508
+ line-height: normal;
1509
+ }
1510
+
1511
+ .cn-look-board .cn-chart-widget__matrix:not(.cn-look-nextcloud *) .cn-chart-widget__matrix-head {
1512
+ font-weight: 600;
1513
+ }
1514
+
1515
+ .cn-look-board .cn-chart-widget__matrix:not(.cn-look-nextcloud *) .cn-chart-widget__matrix-cell:not(.cn-chart-widget__matrix-cell--current) {
1516
+ font-weight: 600;
1517
+ }
@@ -89,6 +89,7 @@ export function createIntegrationRegistry() {
89
89
  * @param {?object} [entry.offlineConfig] Opaque per-integration config bag forwarded verbatim to the integration's components (e.g. the field-inspection leaf's offline schema/filter config). A consuming app overrides it by pre-registering the same id.
90
90
  * @param {'component'|'mount'} [entry.renderMode] Render strategy (openregister#2127 / ADR-066). `'component'` (default) interprets the SFC `tab`/`widget` under the host's own Vue runtime. `'mount'` hands the leaf a bare host-owned DOM element via `mount`/`unmount`, so a leaf built against a different Vue major than the host renders its own framework instance inside that element.
91
91
  * @param {(el: Element, props: object) => void} [entry.mount] Mount hand-off. Required together with `unmount` when `renderMode` is `'mount'`; the host calls it against a bare element with the same context an SFC widget/tab receives (`{ register, schema, objectId, surface, integrationContext, … }`). May also be supplied alongside an SFC pair as a same-major fast path.
92
+ * @param {'card'} [entry.chrome] `'card'` when a mount-mode leaf draws no card of its own: a detail page then hosts it in the library card and hands it `onHeader(header)` to report its count, actions and empty state.
92
93
  * @param {(el: Element) => void} [entry.unmount] Teardown hand-off, called by the host before it removes the element and on surface hide / bound-object change. Travels as a pair with `mount`.
93
94
  *
94
95
  * @return {?object} Normalised entry, or null on collision / malformed mount pair in prod.
@@ -209,6 +210,9 @@ export function createIntegrationRegistry() {
209
210
  // registration, with the tabbed panel silently keeping the sidebar
210
211
  // component.
211
212
  bareWidget: entry.bareWidget === true,
213
+ // `card`: a mount-mode leaf that draws no card of its own, so a
214
+ // detail page hosts it in the library card (CnDetailWidgetHost).
215
+ chrome: entry.chrome === 'card' ? 'card' : null,
212
216
  // Marker set by `registerBuiltinIntegrations` /
213
217
  // `registerLeafIntegrations` so `useIntegrationRegistry` can
214
218
  // distinguish lib-owned registrations (whose components must