@conduction/nextcloud-vue 2.68.0 → 2.70.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 (137) hide show
  1. package/dist/esm/components/CnActionsBar/CnActionsBar.vue2.js +25 -0
  2. package/dist/esm/components/CnActionsBar/CnActionsBar.vue2.js.map +1 -1
  3. package/dist/esm/components/CnActionsBar/CnActionsBar.vue3.js +155 -152
  4. package/dist/esm/components/CnActionsBar/CnActionsBar.vue3.js.map +1 -1
  5. package/dist/esm/components/CnAppNav/CnAppNav.vue2.js +77 -0
  6. package/dist/esm/components/CnAppNav/CnAppNav.vue2.js.map +1 -1
  7. package/dist/esm/components/CnAppNav/CnAppNav.vue3.js +8 -8
  8. package/dist/esm/components/CnAppNav/CnAppNav.vue3.js.map +1 -1
  9. package/dist/esm/components/CnBreadcrumbs/CnBreadcrumbs.vue.js +1 -0
  10. package/dist/esm/components/CnBreadcrumbs/CnBreadcrumbs.vue.js.map +1 -1
  11. package/dist/esm/components/CnBreadcrumbs/CnBreadcrumbs.vue2.js +28 -0
  12. package/dist/esm/components/CnBreadcrumbs/CnBreadcrumbs.vue2.js.map +1 -1
  13. package/dist/esm/components/CnBreadcrumbs/CnBreadcrumbs.vue3.js +4 -2
  14. package/dist/esm/components/CnBreadcrumbs/CnBreadcrumbs.vue3.js.map +1 -1
  15. package/dist/esm/components/CnCalendarWidget/CnCalendarWidget.vue2.js +25 -1
  16. package/dist/esm/components/CnCalendarWidget/CnCalendarWidget.vue2.js.map +1 -1
  17. package/dist/esm/components/CnCalendarWidget/CnCalendarWidget.vue3.js +32 -17
  18. package/dist/esm/components/CnCalendarWidget/CnCalendarWidget.vue3.js.map +1 -1
  19. package/dist/esm/components/CnCapabilityTable/CnCapabilityTable.vue2.js +14 -1
  20. package/dist/esm/components/CnCapabilityTable/CnCapabilityTable.vue2.js.map +1 -1
  21. package/dist/esm/components/CnCapabilityTable/CnCapabilityTable.vue3.js.map +1 -1
  22. package/dist/esm/components/CnDashboardGrid/CnDashboardGrid.vue2.js +43 -2
  23. package/dist/esm/components/CnDashboardGrid/CnDashboardGrid.vue2.js.map +1 -1
  24. package/dist/esm/components/CnDashboardGrid/CnDashboardGrid.vue3.js +3 -3
  25. package/dist/esm/components/CnDashboardGrid/CnDashboardGrid.vue3.js.map +1 -1
  26. package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue2.js +45 -35
  27. package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue2.js.map +1 -1
  28. package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue3.js +19 -1
  29. package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue3.js.map +1 -1
  30. package/dist/esm/components/CnDataTable/CnDataTable.vue2.js +35 -1
  31. package/dist/esm/components/CnDataTable/CnDataTable.vue2.js.map +1 -1
  32. package/dist/esm/components/CnDataTable/CnDataTable.vue3.js.map +1 -1
  33. package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js +94 -6
  34. package/dist/esm/components/CnDetailPage/CnDetailPage.vue2.js.map +1 -1
  35. package/dist/esm/components/CnDetailPage/CnDetailPage.vue3.js +64 -19
  36. package/dist/esm/components/CnDetailPage/CnDetailPage.vue3.js.map +1 -1
  37. package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue2.js +28 -0
  38. package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue2.js.map +1 -1
  39. package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue3.js +3 -2
  40. package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue3.js.map +1 -1
  41. package/dist/esm/components/CnFeaturesAndRoadmapPage/CnFeaturesAndRoadmapPage.vue2.js +12 -0
  42. package/dist/esm/components/CnFeaturesAndRoadmapPage/CnFeaturesAndRoadmapPage.vue2.js.map +1 -1
  43. package/dist/esm/components/CnFeaturesAndRoadmapView/CnFeaturesAndRoadmapView.vue2.js +9 -0
  44. package/dist/esm/components/CnFeaturesAndRoadmapView/CnFeaturesAndRoadmapView.vue2.js.map +1 -1
  45. package/dist/esm/components/CnFeaturesAndRoadmapView/CnFeaturesAndRoadmapView.vue3.js.map +1 -1
  46. package/dist/esm/components/CnHeaderWidget/CnHeaderWidget.vue2.js +54 -7
  47. package/dist/esm/components/CnHeaderWidget/CnHeaderWidget.vue2.js.map +1 -1
  48. package/dist/esm/components/CnHeaderWidget/CnHeaderWidget.vue3.js +26 -8
  49. package/dist/esm/components/CnHeaderWidget/CnHeaderWidget.vue3.js.map +1 -1
  50. package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js +143 -0
  51. package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js.map +1 -1
  52. package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js +68 -25
  53. package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js.map +1 -1
  54. package/dist/esm/components/CnNextStepCard/CnNextStepCard.vue2.js.map +1 -1
  55. package/dist/esm/components/CnNextStepCard/CnNextStepCard.vue3.js.map +1 -1
  56. package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue2.js +4 -1
  57. package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue2.js.map +1 -1
  58. package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue3.js.map +1 -1
  59. package/dist/esm/components/CnStackedBarWidget/CnStackedBarWidget.vue2.js +17 -3
  60. package/dist/esm/components/CnStackedBarWidget/CnStackedBarWidget.vue2.js.map +1 -1
  61. package/dist/esm/components/CnStackedBarWidget/CnStackedBarWidget.vue3.js +25 -24
  62. package/dist/esm/components/CnStackedBarWidget/CnStackedBarWidget.vue3.js.map +1 -1
  63. package/dist/esm/components/CnStagesWidget/CnStagesWidget.vue2.js.map +1 -1
  64. package/dist/esm/components/CnStagesWidget/CnStagesWidget.vue3.js.map +1 -1
  65. package/dist/esm/components/CnStatWidget/CnStatWidget.vue2.js +29 -2
  66. package/dist/esm/components/CnStatWidget/CnStatWidget.vue2.js.map +1 -1
  67. package/dist/esm/components/CnStatWidget/CnStatWidget.vue3.js +7 -0
  68. package/dist/esm/components/CnStatWidget/CnStatWidget.vue3.js.map +1 -1
  69. package/dist/esm/components/CnStatsBlock/CnStatsBlock.vue2.js +24 -1
  70. package/dist/esm/components/CnStatsBlock/CnStatsBlock.vue2.js.map +1 -1
  71. package/dist/esm/components/CnStatsBlock/CnStatsBlock.vue3.js +1 -1
  72. package/dist/esm/components/CnStatsBlock/CnStatsBlock.vue3.js.map +1 -1
  73. package/dist/esm/components/CnStatsBlockWidget/CnStatsBlockWidget.vue2.js +81 -1
  74. package/dist/esm/components/CnStatsBlockWidget/CnStatsBlockWidget.vue2.js.map +1 -1
  75. package/dist/esm/components/CnStatsBlockWidget/CnStatsBlockWidget.vue3.js +25 -3
  76. package/dist/esm/components/CnStatsBlockWidget/CnStatsBlockWidget.vue3.js.map +1 -1
  77. package/dist/esm/components/CnWeekStripWidget/CnWeekStripWidget.vue2.js +15 -2
  78. package/dist/esm/components/CnWeekStripWidget/CnWeekStripWidget.vue2.js.map +1 -1
  79. package/dist/esm/components/CnWeekStripWidget/CnWeekStripWidget.vue3.js +31 -32
  80. package/dist/esm/components/CnWeekStripWidget/CnWeekStripWidget.vue3.js.map +1 -1
  81. package/dist/esm/l10n/en.json.js +3 -0
  82. package/dist/esm/l10n/en.json.js.map +1 -1
  83. package/dist/esm/l10n/nl.json.js +3 -0
  84. package/dist/esm/l10n/nl.json.js.map +1 -1
  85. package/dist/esm/mixins/pageViews.js +278 -11
  86. package/dist/esm/mixins/pageViews.js.map +1 -1
  87. package/dist/esm/nextcloud-vue.css +145 -0
  88. package/dist/esm/store/plugins/dashboardLayouts.js +35 -1
  89. package/dist/esm/store/plugins/dashboardLayouts.js.map +1 -1
  90. package/dist/esm/utils/capabilityComparison.js +29 -1
  91. package/dist/esm/utils/capabilityComparison.js.map +1 -1
  92. package/dist/esm/utils/formatMetric.js +137 -16
  93. package/dist/esm/utils/formatMetric.js.map +1 -1
  94. package/dist/esm/utils/validateManifestV2.compiled.js +2 -2
  95. package/dist/esm/utils/validateManifestV2.compiled.js.map +1 -1
  96. package/dist/nextcloud-vue.cjs.js +2840 -1477
  97. package/dist/nextcloud-vue.cjs.js.map +2 -2
  98. package/dist/nextcloud-vue.css +145 -0
  99. package/l10n/en.json +3 -0
  100. package/l10n/nl.json +3 -0
  101. package/package.json +1 -1
  102. package/src/components/CnActionsBar/CnActionsBar.md +2 -0
  103. package/src/components/CnActionsBar/CnActionsBar.vue +28 -2
  104. package/src/components/CnAppNav/CnAppNav.vue +85 -8
  105. package/src/components/CnBreadcrumbs/CnBreadcrumbs.vue +45 -0
  106. package/src/components/CnCalendarWidget/CnCalendarWidget.vue +32 -4
  107. package/src/components/CnCapabilityTable/CnCapabilityTable.vue +14 -0
  108. package/src/components/CnDashboardGrid/CnDashboardGrid.md +2 -0
  109. package/src/components/CnDashboardGrid/CnDashboardGrid.vue +54 -2
  110. package/src/components/CnDashboardPage/CnDashboardPage.md +2 -0
  111. package/src/components/CnDashboardPage/CnDashboardPage.vue +59 -35
  112. package/src/components/CnDataTable/CnDataTable.vue +35 -1
  113. package/src/components/CnDetailPage/CnDetailPage.md +8 -0
  114. package/src/components/CnDetailPage/CnDetailPage.vue +124 -8
  115. package/src/components/CnDetailWidgetHost/CnDetailWidgetHost.vue +30 -1
  116. package/src/components/CnFeaturesAndRoadmapPage/CnFeaturesAndRoadmapPage.vue +12 -0
  117. package/src/components/CnFeaturesAndRoadmapView/CnFeaturesAndRoadmapView.vue +9 -0
  118. package/src/components/CnHeaderWidget/CnHeaderWidget.vue +95 -8
  119. package/src/components/CnIndexPage/CnIndexPage.vue +171 -6
  120. package/src/components/CnNextStepCard/CnNextStepCard.vue +11 -0
  121. package/src/components/CnObjectListWidget/CnObjectListWidget.vue +4 -1
  122. package/src/components/CnStackedBarWidget/CnStackedBarWidget.vue +34 -7
  123. package/src/components/CnStagesWidget/CnStagesWidget.vue +19 -0
  124. package/src/components/CnStatWidget/CnStatWidget.vue +38 -2
  125. package/src/components/CnStatsBlock/CnStatsBlock.md +2 -0
  126. package/src/components/CnStatsBlock/CnStatsBlock.vue +25 -2
  127. package/src/components/CnStatsBlockWidget/CnStatsBlockWidget.vue +95 -3
  128. package/src/components/CnWeekStripWidget/CnWeekStripWidget.vue +24 -3
  129. package/src/css/detail-page.css +10 -0
  130. package/src/css/index-page.css +12 -0
  131. package/src/css/kpi-card.css +15 -0
  132. package/src/mixins/pageViews.js +277 -10
  133. package/src/schemas/app-manifest-v2.schema.json +73 -6
  134. package/src/store/plugins/dashboardLayouts.js +34 -0
  135. package/src/utils/capabilityComparison.js +28 -0
  136. package/src/utils/formatMetric.js +143 -15
  137. package/src/utils/validateManifestV2.compiled.js +2 -2
@@ -1,4 +1,4 @@
1
1
  [diffend] Oversized file quarantined before diffing.
2
2
  name: package/dist/nextcloud-vue.cjs.js.map
3
- size: 35437389 bytes
4
- sha256: a49cebe981b616ba6555ce135455260b6b111ebcea9afc9c34da210cbc38f32b
3
+ size: 35617052 bytes
4
+ sha256: 8d17da3a5f3f43dba63932341520f63af085b4d61c1b614631488abb6ecd41d8
@@ -1330,6 +1330,21 @@ a.cn-kpi-card--stacked:focus-visible {
1330
1330
  text-decoration: none !important;
1331
1331
  }
1332
1332
 
1333
+ /* A stacked stats block (CnStatsBlock `layout: "stacked"`): its unit
1334
+ ("decisions") goes on a muted line of its own under the number, where the
1335
+ stat tile puts its caption (zuiddrecht-pixel-gaps-3). */
1336
+ .cn-kpi-card--stacked .cn-stats-block__count {
1337
+ flex-direction: column;
1338
+ align-items: flex-start;
1339
+ gap: var(--cn-kpi-stacked-gap, 6px);
1340
+ }
1341
+
1342
+ .cn-kpi-card--stacked .cn-stats-block__count-label {
1343
+ font-size: var(--cn-kpi-label-size, 13px);
1344
+ font-weight: 500;
1345
+ color: var(--color-text-maxcontrast);
1346
+ }
1347
+
1333
1348
  /* Filled: the card draws its own grey box, for a KPI that is NOT already
1334
1349
  inside a wrapper that draws one. Opt-in via `content.flat: false`. */
1335
1350
  .cn-kpi-card--filled {
@@ -2283,6 +2298,18 @@ a.cn-kpi-card--stacked:focus-visible {
2283
2298
  padding: calc(5 * var(--default-grid-baseline));
2284
2299
  }
2285
2300
 
2301
+ /* The board's header buttons (`headerButtons`) at the end of the title row,
2302
+ centred on the title and its count line. They wrap under the title on a
2303
+ narrow page. */
2304
+ .cn-index-page__header-buttons {
2305
+ display: flex;
2306
+ flex-wrap: wrap;
2307
+ align-items: center;
2308
+ align-self: center;
2309
+ gap: calc(2 * var(--default-grid-baseline));
2310
+ margin-inline-start: auto;
2311
+ }
2312
+
2286
2313
  .cn-index-page__below-header {
2287
2314
  margin-bottom: calc(4 * var(--default-grid-baseline));
2288
2315
  }
@@ -2862,6 +2889,16 @@ a.cn-kpi-card--stacked:focus-visible {
2862
2889
  row-gap: var(--cn-detail-header-row-gap, 22px);
2863
2890
  }
2864
2891
 
2892
+ /* That wrap must not take the actions off the title row. With `flex-basis:
2893
+ auto` a long title claimed its whole text width, so the actions wrapped
2894
+ under it. From a zero basis the title takes what the actions leave and
2895
+ wraps (two lines, then an ellipsis) inside it; only on a page too narrow
2896
+ for 16rem of title beside the actions do the actions drop a row. */
2897
+ .cn-detail-page__header--with-widget > :first-child {
2898
+ flex: 1 1 0;
2899
+ min-width: min(100%, 16rem);
2900
+ }
2901
+
2865
2902
  .cn-detail-page__header-widget {
2866
2903
  flex: 1 0 100%;
2867
2904
  min-width: 0;
@@ -6173,6 +6210,17 @@ svg.leaflet-image-layer.leaflet-interactive path {
6173
6210
  margin: 0;
6174
6211
  text-transform: uppercase;
6175
6212
  }
6213
+
6214
+ /* The title is a small kicker, not a section heading, but it is an <h3> (or
6215
+ whatever `titleTag` says) for the outline, and a theme that sizes every
6216
+ heading with !important (thematiq's nldesign sheet: `h3 { font-size:
6217
+ var(--nldesign-component-heading-3-font-size) !important }`) blew it up to
6218
+ an 18px uppercase heading. Only !important beats !important; the doubled
6219
+ class makes this the more specific rule. Without such a theme the size is
6220
+ the 0.85em above, unchanged. */
6221
+ .cn-next-step-card__title.cn-next-step-card__title[data-v-3a9ce962] {
6222
+ font-size: 0.85em !important;
6223
+ }
6176
6224
  .cn-next-step-card__list[data-v-3a9ce962] {
6177
6225
  display: grid;
6178
6226
  gap: calc(2 * var(--default-grid-baseline));
@@ -16465,6 +16513,14 @@ a.cn-xwiki-card__title[data-v-54e85fe3]:hover {
16465
16513
  gap: 16px;
16466
16514
  width: 100%;
16467
16515
  }
16516
+
16517
+ /* `content.inset: true`: the board's inset inside the card (zuiddrecht-pixel-
16518
+ gaps-3). A dashboard renders its widgets flush, so without it the strip ran
16519
+ from card edge to card edge. Theme hook: --cn-widget-board-inset. */
16520
+ .cn-stacked-bar--inset[data-v-c0bac1a2] {
16521
+ box-sizing: border-box;
16522
+ padding: var(--cn-widget-board-inset, 16px 24px 22px);
16523
+ }
16468
16524
  .cn-stacked-bar__state[data-v-c0bac1a2] {
16469
16525
  display: flex;
16470
16526
  align-items: center;
@@ -16980,6 +17036,25 @@ button.cn-stages-widget__bar-label[data-v-358fde0f] {
16980
17036
  line-height: inherit;
16981
17037
  cursor: pointer;
16982
17038
  }
17039
+
17040
+ /* The same label under a theme that restyles every button with !important
17041
+ (thematiq's nldesign sheet: `button:not(.action-button)` gets 8px 16px
17042
+ padding, `min-width: max-content` and `overflow: visible`), and under core's
17043
+ `margin: 3px 3px 3px 0`, which outranks the scoped base rule. Together they
17044
+ put each clickable label about 10px below the current step's <span> and let
17045
+ a long label run over its neighbours, so eight Woo steps overlapped instead
17046
+ of ending in an ellipsis. Only !important beats !important; this selector is
17047
+ the more specific of the two. Without such a theme nothing changes: these
17048
+ are the values the base rule already sets. */
17049
+ button.cn-stages-widget__bar-label.cn-stages-widget__bar-label[data-v-358fde0f] {
17050
+ min-width: 0 !important;
17051
+ margin: 0 !important;
17052
+ padding: 0 !important;
17053
+ border-width: 0 !important;
17054
+ overflow: hidden !important;
17055
+ text-overflow: ellipsis !important;
17056
+ white-space: nowrap !important;
17057
+ }
16983
17058
  button.cn-stages-widget__bar-label[aria-disabled="true"][data-v-358fde0f] {
16984
17059
  cursor: not-allowed;
16985
17060
  }
@@ -17459,6 +17534,21 @@ a.cn-kpi-card--stacked:focus-visible {
17459
17534
  text-decoration: none !important;
17460
17535
  }
17461
17536
 
17537
+ /* A stacked stats block (CnStatsBlock `layout: "stacked"`): its unit
17538
+ ("decisions") goes on a muted line of its own under the number, where the
17539
+ stat tile puts its caption (zuiddrecht-pixel-gaps-3). */
17540
+ .cn-kpi-card--stacked .cn-stats-block__count {
17541
+ flex-direction: column;
17542
+ align-items: flex-start;
17543
+ gap: var(--cn-kpi-stacked-gap, 6px);
17544
+ }
17545
+
17546
+ .cn-kpi-card--stacked .cn-stats-block__count-label {
17547
+ font-size: var(--cn-kpi-label-size, 13px);
17548
+ font-weight: 500;
17549
+ color: var(--color-text-maxcontrast);
17550
+ }
17551
+
17462
17552
  /* Filled: the card draws its own grey box, for a KPI that is NOT already
17463
17553
  inside a wrapper that draws one. Opt-in via `content.flat: false`. */
17464
17554
  .cn-kpi-card--filled {
@@ -18405,6 +18495,30 @@ to { background-position: -200% 0;
18405
18495
  flex: 1 1 320px;
18406
18496
  width: auto;
18407
18497
  }
18498
+
18499
+ /* The emblem beside the greeting (`content.emblem`): on one row with the
18500
+ date line and heading, centred on them, as LpStart draws it. */
18501
+ .cn-header-widget--with-emblem[data-v-1b97430f] {
18502
+ display: flex;
18503
+ column-gap: var(--cn-header-emblem-gap, 16px);
18504
+ }
18505
+ .cn-header-widget--with-emblem .cn-header-widget__content[data-v-1b97430f] {
18506
+ flex: 1 1 auto;
18507
+ width: auto;
18508
+ min-width: 0;
18509
+ }
18510
+ .cn-header-widget__emblem[data-v-1b97430f] {
18511
+ position: relative;
18512
+ z-index: 1;
18513
+ flex: none;
18514
+ align-self: center;
18515
+ height: var(--cn-header-emblem-size, 52px);
18516
+ width: auto;
18517
+ }
18518
+ .cn-header-widget__emblem--theme[data-v-1b97430f] {
18519
+ width: var(--cn-header-emblem-size, 52px);
18520
+ background: var(--nldesign-emblem-url) center / contain no-repeat;
18521
+ }
18408
18522
  .cn-header-widget__views[data-v-1b97430f] {
18409
18523
  position: relative;
18410
18524
  z-index: 1;
@@ -19507,6 +19621,14 @@ to { background-position: -200% 0;
19507
19621
  .cn-week-strip[data-v-153dd4cb] {
19508
19622
  width: 100%;
19509
19623
  }
19624
+
19625
+ /* `content.inset: true`: the board's inset inside the card (zuiddrecht-pixel-
19626
+ gaps-3). A dashboard renders its widgets flush, so without it the strip ran
19627
+ from card edge to card edge. Theme hook: --cn-widget-board-inset. */
19628
+ .cn-week-strip--inset[data-v-153dd4cb] {
19629
+ box-sizing: border-box;
19630
+ padding: var(--cn-widget-board-inset, 16px 24px 22px);
19631
+ }
19510
19632
  .cn-week-strip__state[data-v-153dd4cb] {
19511
19633
  display: flex;
19512
19634
  align-items: center;
@@ -30052,6 +30174,19 @@ to {
30052
30174
  }
30053
30175
 
30054
30176
 
30177
+ /* `separator`: a text separator in place of the chevron. The chevron's own
30178
+ element stays (it carries NcBreadcrumbs' spacing and its "no separator after
30179
+ the last crumb" rule); only its icon gives way to the text. */
30180
+ .cn-breadcrumbs--text-separator[data-v-296fde9b] .vue-crumb__separator svg {
30181
+ display: none;
30182
+ }
30183
+ .cn-breadcrumbs--text-separator[data-v-296fde9b] .vue-crumb__separator::before {
30184
+ content: var(--cn-breadcrumbs-separator);
30185
+ padding-inline: var(--cn-breadcrumbs-separator-gap, 0);
30186
+ color: var(--color-text-maxcontrast);
30187
+ }
30188
+
30189
+
30055
30190
  .cn-run-node-dialog__form[data-v-3eb7c55d] {
30056
30191
  display: flex;
30057
30192
  flex-direction: column;
@@ -30223,6 +30358,16 @@ to {
30223
30358
  outline-offset: 2px;
30224
30359
  border-radius: var(--border-radius-container-large, 16px);
30225
30360
  }
30361
+
30362
+ /* A size-to-content cell (`sizeToContent`) is measured by GridStack from the
30363
+ content's first child, and a widget wrapper there filled the cell
30364
+ (`height: 100%`), so the measure returned the cell's own height and the
30365
+ cell never shrank: "Waiting for me" stayed a tall card around one row. In
30366
+ such a cell the child takes its own height. A cell without the key keeps
30367
+ the filling child. */
30368
+ .cn-dashboard-grid__item--fit[data-v-9f6b1a22] > .grid-stack-item-content > * {
30369
+ height: auto;
30370
+ }
30226
30371
  [data-v-9f6b1a22] .grid-stack-item-content {
30227
30372
  background: var(--color-main-background);
30228
30373
  border: none;
package/l10n/en.json CHANGED
@@ -1092,6 +1092,9 @@
1092
1092
  "An attention card needs a title": "An attention card needs a title",
1093
1093
  "Good morning, {name}": "Good morning, {name}",
1094
1094
  "This view has no widgets yet.": "This view has no widgets yet.",
1095
+ "Arrange view": "Arrange view",
1096
+ "Reset view": "Reset view",
1097
+ "Reset layout": "Reset layout",
1095
1098
  "Good morning": "Good morning",
1096
1099
  "Good afternoon, {name}": "Good afternoon, {name}",
1097
1100
  "Good afternoon": "Good afternoon",
package/l10n/nl.json CHANGED
@@ -1136,6 +1136,9 @@
1136
1136
  "An attention card needs a title": "Een aandachtskaart heeft een titel nodig",
1137
1137
  "Good morning, {name}": "Goedemorgen, {name}",
1138
1138
  "This view has no widgets yet.": "Deze weergave heeft nog geen widgets.",
1139
+ "Arrange view": "Weergave indelen",
1140
+ "Reset view": "Weergave herstellen",
1141
+ "Reset layout": "Indeling herstellen",
1139
1142
  "Good morning": "Goedemorgen",
1140
1143
  "Good afternoon, {name}": "Goedemiddag, {name}",
1141
1144
  "Good afternoon": "Goedemiddag",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@conduction/nextcloud-vue",
3
- "version": "2.68.0",
3
+ "version": "2.70.0",
4
4
  "description": "Shared Vue component library for Conduction Nextcloud apps — complements @nextcloud/vue with higher-level components, OpenRegister integration, and NL Design System support",
5
5
  "homepage": "https://github.com/ConductionNL/nextcloud-vue#readme",
6
6
  "bugs": {
@@ -204,3 +204,5 @@ Controlling the inline action button count — `inlineActionCount` sets how many
204
204
  | `sortOptions` | Array | `[]` | Options `{ value, label }` for the sort dropdown. |
205
205
  | `sortValue` | String | `''` | Selected sort option value (controlled). |
206
206
  | `sortLabel` | String | *(i18n)* | Accessible label for the sort dropdown. |
207
+
208
+ `showCount` (Boolean, default `true`): `false` drops the "Showing 20 of 258" line. `showActionsMenu` (Boolean, default `true`): `false` drops the overflow Actions menu, for a page that offers its actions as buttons elsewhere (CnIndexPage `headerButtons`).
@@ -12,13 +12,13 @@
12
12
  :aria-label="searchPlaceholder || t('nextcloud-vue', 'Search')"
13
13
  @input="onSearchInput">
14
14
  </div>
15
- <span v-else-if="hasTotal" class="cn-actions-bar__count">
15
+ <span v-else-if="showCount && hasTotal" class="cn-actions-bar__count">
16
16
  {{ countText }}
17
17
  </span>
18
18
  <!-- @slot after-search Refinement controls rendered beside the search field on the LEFT side of the bar (e.g. a filter menu button). Convention: the left side groups the VISUAL controls — search, filters, view toggle — while the right cluster holds the ACT controls (add, overflow); the standalone sort select is a display control too but keeps its legacy right-side placement. -->
19
19
  <slot name="after-search" />
20
20
  <!-- Counter beside the search (`showCountWithSearch`): after the search and its #after-search controls. The live region stays mounted while there is no total, so results coming back after none are announced too. -->
21
- <span v-if="showSearch && showCountWithSearch"
21
+ <span v-if="showCount && showSearch && showCountWithSearch"
22
22
  class="cn-actions-bar__count cn-actions-bar__count--beside-search"
23
23
  :class="{ 'cn-actions-bar__count--empty': !hasTotal }"
24
24
  aria-live="polite">{{ hasTotal ? countText : '' }}</span>
@@ -140,6 +140,7 @@
140
140
 
141
141
  <!-- Actions menu (Refresh, Import, Export, mass actions) -->
142
142
  <NcActions
143
+ v-if="showActionsMenu"
143
144
  :forceName="true"
144
145
  :inline="inlineActionCount"
145
146
  :menuName="actionsMenuName"
@@ -683,6 +684,31 @@ export default {
683
684
  default: true,
684
685
  },
685
686
 
687
+ /**
688
+ * Whether the "Showing 20 of 258" line renders where the search field
689
+ * is not. `false` drops it, for a page whose title line already says
690
+ * how many there are. True by default.
691
+ *
692
+ * @spec openspec/changes/zuiddrecht-pixel-gaps-3/specs/zuiddrecht-pixel-gaps-3/spec.md#requirement-an-index-page-can-take-the-board-header
693
+ */
694
+ showCount: {
695
+ type: Boolean,
696
+ default: true,
697
+ },
698
+
699
+ /**
700
+ * Whether the overflow Actions menu (Refresh, Import, Export, mass
701
+ * actions, header actions) renders. `false` drops it, for a page that
702
+ * offers its actions as buttons elsewhere (CnIndexPage
703
+ * `headerButtons`). True by default.
704
+ *
705
+ * @spec openspec/changes/zuiddrecht-pixel-gaps-3/specs/zuiddrecht-pixel-gaps-3/spec.md#requirement-an-index-page-can-take-the-board-header
706
+ */
707
+ showActionsMenu: {
708
+ type: Boolean,
709
+ default: true,
710
+ },
711
+
686
712
  /**
687
713
  * Whether to show the Search/Columns sidebar toggle button. Lets the
688
714
  * index sidebar default to closed and be opened on demand.
@@ -188,8 +188,8 @@
188
188
  v-else
189
189
  :key="item.id"
190
190
  :name="resolveLabel(item)"
191
- :to="itemTo(item)"
192
- :href="itemHref(item)"
191
+ :to="linkTo(item)"
192
+ :href="linkHref(item)"
193
193
  :icon="cssIconClass(item)"
194
194
  :active="isActive(item)"
195
195
  :pinned="Boolean(item.pinned)"
@@ -224,8 +224,8 @@
224
224
  v-for="child in visibleChildren(item)"
225
225
  :key="child.id"
226
226
  :name="resolveLabel(child)"
227
- :to="itemTo(child)"
228
- :href="itemHref(child)"
227
+ :to="linkTo(child)"
228
+ :href="linkHref(child)"
229
229
  :icon="cssIconClass(child)"
230
230
  :active="isActive(child)"
231
231
  :pinned="Boolean(child.pinned)"
@@ -304,8 +304,8 @@
304
304
  v-for="item in footerItems"
305
305
  :key="item.id"
306
306
  :name="resolveLabel(item)"
307
- :to="itemTo(item)"
308
- :href="itemHref(item)"
307
+ :to="linkTo(item)"
308
+ :href="linkHref(item)"
309
309
  :icon="cssIconClass(item)"
310
310
  :active="isActive(item)"
311
311
  :data-testid="`cn-nav-entry-${item.id}`"
@@ -402,8 +402,8 @@
402
402
  v-else
403
403
  :key="item.id"
404
404
  :name="resolveLabel(item)"
405
- :to="itemTo(item)"
406
- :href="itemHref(item)"
405
+ :to="linkTo(item)"
406
+ :href="linkHref(item)"
407
407
  :icon="cssIconClass(item)"
408
408
  :active="isActive(item)"
409
409
  :data-cn-route="item.route"
@@ -2026,6 +2026,72 @@ export default {
2026
2026
  return to
2027
2027
  },
2028
2028
 
2029
+ /**
2030
+ * Whether another visible entry links to the same route, so the two
2031
+ * differ only in `query` or `params` ("All cases" and "Woo requests"
2032
+ * on one list).
2033
+ *
2034
+ * @param {object} item Menu entry.
2035
+ * @return {boolean} True when the route is shared.
2036
+ * @spec openspec/changes/zuiddrecht-pixel-gaps-3/specs/zuiddrecht-pixel-gaps-3/spec.md#requirement-only-the-best-matching-menu-entry-is-active
2037
+ */
2038
+ sharesRoute(item) {
2039
+ if (!item || item.href || item.action || !item.route) {
2040
+ return false
2041
+ }
2042
+ return this.flatEntries.some((entry) => entry !== item && !entry.href && !entry.action && entry.route === item.route)
2043
+ },
2044
+
2045
+ /**
2046
+ * The app's router, or null when the nav is mounted without one. Read
2047
+ * from the app's global properties: `this.$router` warns during render
2048
+ * on an instance that has none.
2049
+ *
2050
+ * @return {object|null} The router.
2051
+ * @spec openspec/changes/zuiddrecht-pixel-gaps-3/specs/zuiddrecht-pixel-gaps-3/spec.md#requirement-only-the-best-matching-menu-entry-is-active
2052
+ */
2053
+ appRouter() {
2054
+ return this.$?.appContext?.config?.globalProperties?.$router ?? null
2055
+ },
2056
+
2057
+ /**
2058
+ * The `:to` an entry renders with. An entry that shares its route
2059
+ * renders as a plain link instead (see `linkHref`): NcAppNavigationItem
2060
+ * marks a router link active whenever vue-router calls it active, and
2061
+ * vue-router ignores the query, so "Woo requests" lit up beside "All
2062
+ * cases" on the unfiltered list. As a plain link only `isActive`
2063
+ * decides, which marks the entry that matches best.
2064
+ *
2065
+ * @param {object} item Menu entry.
2066
+ * @return {object|null} The router target, or null.
2067
+ * @spec openspec/changes/zuiddrecht-pixel-gaps-3/specs/zuiddrecht-pixel-gaps-3/spec.md#requirement-only-the-best-matching-menu-entry-is-active
2068
+ */
2069
+ linkTo(item) {
2070
+ if (this.appRouter() && this.sharesRoute(item)) {
2071
+ return null
2072
+ }
2073
+ return this.itemTo(item)
2074
+ },
2075
+
2076
+ /**
2077
+ * The `:href` an entry renders with: `itemHref`, or for an entry that
2078
+ * shares its route the address vue-router resolves its target to (a
2079
+ * click on it is still routed in the app, see `onItemClick`).
2080
+ *
2081
+ * @param {object} item Menu entry.
2082
+ * @return {string|null} The address, or null.
2083
+ * @spec openspec/changes/zuiddrecht-pixel-gaps-3/specs/zuiddrecht-pixel-gaps-3/spec.md#requirement-only-the-best-matching-menu-entry-is-active
2084
+ */
2085
+ linkHref(item) {
2086
+ const own = this.itemHref(item)
2087
+ const router = this.appRouter()
2088
+ if (own || !router || !this.sharesRoute(item)) {
2089
+ return own
2090
+ }
2091
+ const to = this.itemTo(item)
2092
+ return to ? router.resolve(to).href : null
2093
+ },
2094
+
2029
2095
  /**
2030
2096
  * Build the `:href` value for an `NcAppNavigationItem`. Returns
2031
2097
  * the item's `href` so the entry renders as a real anchor whose
@@ -2175,6 +2241,17 @@ export default {
2175
2241
  this.cnReplayWalkthrough(item.tourId)
2176
2242
  return
2177
2243
  }
2244
+ // An entry that shares its route is a plain link (see linkTo); a
2245
+ // plain click still navigates inside the app. A modified click
2246
+ // (new tab, new window) is left to the browser.
2247
+ if (this.appRouter() && this.sharesRoute(item) && event && !event.defaultPrevented
2248
+ && !(event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) && event.button !== 1) {
2249
+ const to = this.itemTo(item)
2250
+ if (to) {
2251
+ event.preventDefault()
2252
+ this.appRouter().push(to).catch(() => {})
2253
+ }
2254
+ }
2178
2255
  // An entry left without a link (see itemTo) renders a `#` anchor;
2179
2256
  // following it would change the address, so the click goes nowhere.
2180
2257
  if (!item.href && this.unfilledRouteParam(item) && event && typeof event.preventDefault === 'function') {
@@ -19,6 +19,8 @@
19
19
  v-if="crumbs.length > 0"
20
20
  :aria-label="ariaLabel"
21
21
  :rootIcon="rootText ? '' : undefined"
22
+ :class="{ 'cn-breadcrumbs--text-separator': separator !== '' }"
23
+ :style="separatorStyle"
22
24
  data-testid="cn-breadcrumbs">
23
25
  <!-- `name` falls back to '' because NcBreadcrumb declares it a REQUIRED
24
26
  String and warns per render on the label-less icon-only crumb. The
@@ -111,6 +113,34 @@ export default {
111
113
  type: Boolean,
112
114
  default: false,
113
115
  },
116
+
117
+ /**
118
+ * Draw this text between the crumbs (for example `/`) instead of
119
+ * NcBreadcrumbs' chevron. Empty (the default) keeps the chevron. The
120
+ * separator is decoration: it is not read out.
121
+ *
122
+ * @spec openspec/changes/zuiddrecht-pixel-gaps-3/specs/zuiddrecht-pixel-gaps-3/spec.md#requirement-a-breadcrumb-can-name-the-record-by-a-field-and-use-a-text-separator
123
+ */
124
+ separator: {
125
+ type: String,
126
+ default: '',
127
+ },
128
+ },
129
+
130
+ computed: {
131
+ /**
132
+ * The separator handed to the stylesheet as a CSS string, or nothing
133
+ * without a `separator`.
134
+ *
135
+ * @spec openspec/changes/zuiddrecht-pixel-gaps-3/specs/zuiddrecht-pixel-gaps-3/spec.md#requirement-a-breadcrumb-can-name-the-record-by-a-field-and-use-a-text-separator
136
+ * @return {object|undefined}
137
+ */
138
+ separatorStyle() {
139
+ if (this.separator === '') {
140
+ return undefined
141
+ }
142
+ return { '--cn-breadcrumbs-separator': JSON.stringify(this.separator) }
143
+ },
114
144
  },
115
145
 
116
146
  methods: {
@@ -127,3 +157,18 @@ export default {
127
157
  },
128
158
  }
129
159
  </script>
160
+
161
+ <style scoped>
162
+ /* `separator`: a text separator in place of the chevron. The chevron's own
163
+ element stays (it carries NcBreadcrumbs' spacing and its "no separator after
164
+ the last crumb" rule); only its icon gives way to the text. */
165
+ .cn-breadcrumbs--text-separator :deep(.vue-crumb__separator svg) {
166
+ display: none;
167
+ }
168
+
169
+ .cn-breadcrumbs--text-separator :deep(.vue-crumb__separator)::before {
170
+ content: var(--cn-breadcrumbs-separator);
171
+ padding-inline: var(--cn-breadcrumbs-separator-gap, 0);
172
+ color: var(--color-text-maxcontrast);
173
+ }
174
+ </style>
@@ -5,9 +5,13 @@
5
5
 
6
6
  <template>
7
7
  <div class="cn-calendar-widget">
8
- <header class="cn-calendar-widget__header">
9
- <span class="cn-calendar-widget__title">{{ t('nextcloud-vue', 'Calendar') }}</span>
10
- <div class="cn-calendar-widget__modes">
8
+ <!-- `content.showTitle: false` and `content.showViewModes: false` drop
9
+ the sub-heading and the Month / Week / Agenda buttons, for an agenda
10
+ placement whose card already names it; without both the header
11
+ row goes. -->
12
+ <header v-if="showsTitle || showsViewModes" class="cn-calendar-widget__header">
13
+ <span v-if="showsTitle" class="cn-calendar-widget__title">{{ t('nextcloud-vue', 'Calendar') }}</span>
14
+ <div v-if="showsViewModes" class="cn-calendar-widget__modes">
11
15
  <button
12
16
  v-for="mode in viewModes"
13
17
  :key="mode"
@@ -160,7 +164,10 @@ export default {
160
164
 
161
165
  props: {
162
166
  /**
163
- * Persisted widget content `{viewMode, daysAhead, colorByCalendar}`.
167
+ * Persisted widget content `{viewMode, daysAhead, colorByCalendar,
168
+ * showTitle, showViewModes}`. `showTitle: false` drops the "Calendar"
169
+ * sub-heading and `showViewModes: false` the Month / Week / Agenda
170
+ * buttons (both shown by default).
164
171
  *
165
172
  * @type {object}
166
173
  */
@@ -197,6 +204,27 @@ export default {
197
204
  },
198
205
 
199
206
  computed: {
207
+ /**
208
+ * Whether the "Calendar" sub-heading renders (`content.showTitle`).
209
+ *
210
+ * @spec openspec/changes/zuiddrecht-pixel-gaps-3/specs/zuiddrecht-pixel-gaps-3/spec.md#requirement-an-agenda-placement-can-drop-the-calendar-chrome
211
+ * @return {boolean}
212
+ */
213
+ showsTitle() {
214
+ return !(this.content && this.content.showTitle === false)
215
+ },
216
+
217
+ /**
218
+ * Whether the Month / Week / Agenda buttons render
219
+ * (`content.showViewModes`).
220
+ *
221
+ * @spec openspec/changes/zuiddrecht-pixel-gaps-3/specs/zuiddrecht-pixel-gaps-3/spec.md#requirement-an-agenda-placement-can-drop-the-calendar-chrome
222
+ * @return {boolean}
223
+ */
224
+ showsViewModes() {
225
+ return !(this.content && this.content.showViewModes === false)
226
+ },
227
+
200
228
  /**
201
229
  * The available view modes.
202
230
  *
@@ -187,6 +187,7 @@ import {
187
187
  hasProviders,
188
188
  RATINGS,
189
189
  resolveProvider,
190
+ warnCapabilityComparisonDeprecated,
190
191
  } from '../../utils/capabilityComparison.js'
191
192
 
192
193
  /**
@@ -212,6 +213,13 @@ export default {
212
213
  * document without them renders the table this component's consumers
213
214
  * already had.
214
215
  *
216
+ * Deprecated, with the whole component: publish the comparison on the
217
+ * app's docs site and link to it (as dossiq #3312 and pipelinq #2195
218
+ * did). Still rendered; removal waits for a major version. A
219
+ * development build warns once when a comparison is given.
220
+ *
221
+ * @deprecated since 2.66.0, publish the comparison on the app's docs site and link to it.
222
+ * @spec openspec/changes/zuiddrecht-pixel-gaps-3/specs/zuiddrecht-pixel-gaps-3/spec.md#requirement-the-in-app-capability-comparison-is-deprecated
215
223
  * @type {object}
216
224
  */
217
225
  comparison: {
@@ -437,6 +445,12 @@ export default {
437
445
  }
438
446
  },
439
447
 
448
+ mounted() {
449
+ if (this.comparison) {
450
+ warnCapabilityComparisonDeprecated('CnCapabilityTable')
451
+ }
452
+ },
453
+
440
454
  methods: {
441
455
  /**
442
456
  * Debounce the reader's typing into `query`.
@@ -158,3 +158,5 @@ explicit event when you are writing new code:
158
158
  @item-activate="({ item, clientX, clientY }) => openMenu(item, clientX, clientY)"
159
159
  @layout-change="onLayoutChange" />
160
160
  ```
161
+
162
+ `float` (Boolean, default `true`): GridStack's `float`. `false` packs items upward, so a size-to-content cell that shrinks, or a widget that is not shown, closes its gap.