@conduction/nextcloud-vue 2.101.0 → 2.102.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.
- package/dist/esm/components/CnActionsBar/CnActionsBar.vue2.js +22 -0
- package/dist/esm/components/CnActionsBar/CnActionsBar.vue2.js.map +1 -1
- package/dist/esm/components/CnActionsBar/CnActionsBar.vue3.js +8 -6
- package/dist/esm/components/CnActionsBar/CnActionsBar.vue3.js.map +1 -1
- package/dist/esm/components/CnChartWidget/CnChartWidget.vue.js +1 -1
- package/dist/esm/components/CnChartWidget/CnChartWidget.vue2.js +29 -4
- package/dist/esm/components/CnChartWidget/CnChartWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnChartWidget/CnChartWidget.vue3.js +9 -1
- package/dist/esm/components/CnChartWidget/CnChartWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue.js +1 -1
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue2.js +20 -0
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue2.js.map +1 -1
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue3.js +1 -1
- package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue3.js.map +1 -1
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js +70 -4
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js.map +1 -1
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js +6 -4
- package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js.map +1 -1
- package/dist/esm/components/CnIndexPage/useNamedSource.js +26 -2
- package/dist/esm/components/CnIndexPage/useNamedSource.js.map +1 -1
- package/dist/esm/components/CnMenuWidget/CnMenuWidget.vue.js +1 -1
- package/dist/esm/components/CnMenuWidget/CnMenuWidget.vue2.js +25 -1
- package/dist/esm/components/CnMenuWidget/CnMenuWidget.vue2.js.map +1 -1
- package/dist/esm/components/CnMenuWidget/CnMenuWidget.vue3.js.map +1 -1
- package/dist/esm/components/CnQuickFilterBar/CnQuickFilterBar.vue.js +1 -1
- package/dist/esm/components/CnQuickFilterBar/CnQuickFilterBar.vue2.js +106 -4
- package/dist/esm/components/CnQuickFilterBar/CnQuickFilterBar.vue2.js.map +1 -1
- package/dist/esm/components/CnQuickFilterBar/CnQuickFilterBar.vue3.js +70 -25
- package/dist/esm/components/CnQuickFilterBar/CnQuickFilterBar.vue3.js.map +1 -1
- package/dist/esm/components/CnWidgetObjectTable/CnWidgetObjectTable.vue.js +1 -1
- package/dist/esm/components/CnWidgetObjectTable/CnWidgetObjectTable.vue2.js +2 -23
- package/dist/esm/components/CnWidgetObjectTable/CnWidgetObjectTable.vue2.js.map +1 -1
- package/dist/esm/components/CnWidgetObjectTable/CnWidgetObjectTable.vue3.js.map +1 -1
- package/dist/esm/composables/indexSources.js +9 -0
- package/dist/esm/composables/indexSources.js.map +1 -1
- package/dist/esm/l10n/en.json.js +5 -1
- package/dist/esm/l10n/en.json.js.map +1 -1
- package/dist/esm/l10n/nl.json.js +5 -1
- package/dist/esm/l10n/nl.json.js.map +1 -1
- package/dist/esm/library-style.js +1 -1
- package/dist/esm/nextcloud-vue.css +232 -187
- package/dist/esm/utils/builtInFormatters.js +24 -4
- package/dist/esm/utils/builtInFormatters.js.map +1 -1
- package/dist/esm/utils/rowClassRules.js +43 -0
- package/dist/esm/utils/rowClassRules.js.map +1 -0
- package/dist/esm/utils/validateManifestV2.compiled.js +3 -3
- package/dist/esm/utils/validateManifestV2.compiled.js.map +1 -1
- package/dist/esm/utils/visibleWhen.js +19 -2
- package/dist/esm/utils/visibleWhen.js.map +1 -1
- package/dist/nextcloud-vue.cjs.js +1464 -1053
- package/dist/nextcloud-vue.cjs.js.map +2 -2
- package/dist/nextcloud-vue.css +232 -187
- package/l10n/en.json +5 -1
- package/l10n/nl.json +5 -1
- package/package.json +1 -1
- package/src/components/CnActionsBar/CnActionsBar.md +1 -0
- package/src/components/CnActionsBar/CnActionsBar.vue +31 -4
- package/src/components/CnChartWidget/CnChartWidget.md +3 -2
- package/src/components/CnChartWidget/CnChartWidget.vue +42 -4
- package/src/components/CnDashboardPage/CnDashboardPage.vue +21 -1
- package/src/components/CnIndexPage/CnIndexPage.md +5 -1
- package/src/components/CnIndexPage/CnIndexPage.vue +74 -6
- package/src/components/CnIndexPage/useNamedSource.js +26 -2
- package/src/components/CnMenuWidget/CnMenuWidget.vue +25 -1
- package/src/components/CnQuickFilterBar/CnQuickFilterBar.md +1 -0
- package/src/components/CnQuickFilterBar/CnQuickFilterBar.vue +159 -5
- package/src/components/CnWidgetObjectTable/CnWidgetObjectTable.vue +2 -23
- package/src/composables/indexSources.js +9 -0
- package/src/css/look-board-index.css +10 -0
- package/src/schemas/app-manifest-v2.schema.json +55 -3
- package/src/utils/builtInFormatters.js +24 -4
- package/src/utils/rowClassRules.js +39 -0
- package/src/utils/validateManifestV2.compiled.js +3 -3
- package/src/utils/visibleWhen.js +19 -2
package/l10n/en.json
CHANGED
|
@@ -1720,7 +1720,11 @@
|
|
|
1720
1720
|
"Made {date}": "Made {date}",
|
|
1721
1721
|
"expires {date}": "expires {date}",
|
|
1722
1722
|
"Loading …": "Loading …",
|
|
1723
|
-
"Reorder {item}: drag, or press the up and down arrow keys": "Reorder {item}: drag, or press the up and down arrow keys"
|
|
1723
|
+
"Reorder {item}: drag, or press the up and down arrow keys": "Reorder {item}: drag, or press the up and down arrow keys",
|
|
1724
|
+
"No contacts linked": "No contacts linked",
|
|
1725
|
+
"No relations yet": "No relations yet",
|
|
1726
|
+
"Period": "Period",
|
|
1727
|
+
"On": "On"
|
|
1724
1728
|
},
|
|
1725
1729
|
"plurals": {
|
|
1726
1730
|
"{count} selected": [
|
package/l10n/nl.json
CHANGED
|
@@ -1933,7 +1933,11 @@
|
|
|
1933
1933
|
"Expires today": "Verloopt vandaag",
|
|
1934
1934
|
"Made {date}": "Gemaakt {date}",
|
|
1935
1935
|
"expires {date}": "verloopt {date}",
|
|
1936
|
-
"Reorder {item}: drag, or press the up and down arrow keys": "{item} verplaatsen: slepen, of de pijltoetsen omhoog en omlaag"
|
|
1936
|
+
"Reorder {item}: drag, or press the up and down arrow keys": "{item} verplaatsen: slepen, of de pijltoetsen omhoog en omlaag",
|
|
1937
|
+
"No contacts linked": "Geen contacten gekoppeld",
|
|
1938
|
+
"No relations yet": "Nog geen relaties",
|
|
1939
|
+
"Period": "Periode",
|
|
1940
|
+
"On": "Aan"
|
|
1937
1941
|
},
|
|
1938
1942
|
"plurals": {
|
|
1939
1943
|
"{count} selected": [
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@conduction/nextcloud-vue",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.102.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": {
|
|
@@ -217,6 +217,7 @@ Controlling the inline action button count — `inlineActionCount` sets how many
|
|
|
217
217
|
| `showBuildiqButton` | Boolean | `true` | Whether the buildiq square renders in the bar (the index page takes it into its header under the board look) |
|
|
218
218
|
| `bulkNoun` | String | `''` | The plural in the bulk band lead, "With the selected <noun>" (default "items") |
|
|
219
219
|
| `bulkHint` | String | `''` | The 13px hint after the bulk band's buttons |
|
|
220
|
+
| `bulkBandAlways` | Boolean | `false` | Board look: draw the bulk band before anything is selected too, its buttons disabled until there is a selection (DqZaken, DqWerkbord). Only when the band has an action to offer. |
|
|
220
221
|
|
|
221
222
|
|
|
222
223
|
`showBuildiqButton` is documented in the prop table of the component reference (board look, screens-chrome-parity).
|
|
@@ -507,12 +507,15 @@
|
|
|
507
507
|
|
|
508
508
|
<!--
|
|
509
509
|
Board look: the bulk band is its own row between the toolbar and the
|
|
510
|
-
table card, outside the toolbar element,
|
|
511
|
-
|
|
510
|
+
table card, outside the toolbar element, while rows are selected; with
|
|
511
|
+
`bulkBandAlways` also before, its buttons disabled until there is a
|
|
512
|
+
selection (DqZaken, DqWerkbord). The count stays announced by the live
|
|
513
|
+
region above.
|
|
512
514
|
-->
|
|
513
515
|
<div
|
|
514
|
-
v-if="isBoardLayout && selectable && selectedIds.length > 0"
|
|
516
|
+
v-if="isBoardLayout && selectable && (selectedIds.length > 0 || (bulkBandAlways && bulkBandHasActions))"
|
|
515
517
|
class="cn-actions-bar__band"
|
|
518
|
+
:class="{ 'cn-actions-bar__band--idle': selectedIds.length === 0 }"
|
|
516
519
|
role="region"
|
|
517
520
|
:aria-label="t('nextcloud-vue', 'Actions for the selection')"
|
|
518
521
|
data-testid="cn-bulk-band">
|
|
@@ -520,12 +523,14 @@
|
|
|
520
523
|
<NcButton
|
|
521
524
|
v-if="showMassCopy"
|
|
522
525
|
variant="secondary"
|
|
526
|
+
:disabled="selectedIds.length === 0"
|
|
523
527
|
@click="$emit('show-copy')">
|
|
524
528
|
{{ t('nextcloud-vue', 'Copy selected') }}
|
|
525
529
|
</NcButton>
|
|
526
530
|
<NcButton
|
|
527
531
|
v-if="showMassDelete"
|
|
528
532
|
variant="secondary"
|
|
533
|
+
:disabled="selectedIds.length === 0"
|
|
529
534
|
@click="$emit('show-delete')">
|
|
530
535
|
{{ t('nextcloud-vue', 'Delete selected') }}
|
|
531
536
|
</NcButton>
|
|
@@ -533,7 +538,7 @@
|
|
|
533
538
|
v-for="entry in bulkActions"
|
|
534
539
|
:key="entry.id"
|
|
535
540
|
variant="secondary"
|
|
536
|
-
:disabled="entry.disabled === true"
|
|
541
|
+
:disabled="entry.disabled === true || selectedIds.length === 0"
|
|
537
542
|
:data-testid="`cn-bulk-action-${entry.id}`"
|
|
538
543
|
:lang="bulkLang(entry)"
|
|
539
544
|
@click="$emit('bulk-action', { id: entry.id, action: entry.id, selectedIds, count: selectedIds.length })">
|
|
@@ -719,6 +724,16 @@ export default {
|
|
|
719
724
|
default: '',
|
|
720
725
|
},
|
|
721
726
|
|
|
727
|
+
/**
|
|
728
|
+
* Board look: draw the bulk band also before anything is selected, its
|
|
729
|
+
* buttons disabled until there is a selection, as DqZaken and DqWerkbord
|
|
730
|
+
* draw it. Only when the band has an action to offer.
|
|
731
|
+
*/
|
|
732
|
+
bulkBandAlways: {
|
|
733
|
+
type: Boolean,
|
|
734
|
+
default: false,
|
|
735
|
+
},
|
|
736
|
+
|
|
722
737
|
/** The 13px hint after the board bulk band's buttons (`config.bulkHint`). */
|
|
723
738
|
bulkHint: {
|
|
724
739
|
type: String,
|
|
@@ -1117,6 +1132,18 @@ export default {
|
|
|
1117
1132
|
return t('nextcloud-vue', '{count} active', { count: this.filterCount })
|
|
1118
1133
|
},
|
|
1119
1134
|
|
|
1135
|
+
/**
|
|
1136
|
+
* Whether the bulk band has an action to offer: copy, delete, a
|
|
1137
|
+
* declared bulk action or the host's own buttons.
|
|
1138
|
+
*
|
|
1139
|
+
* @return {boolean}
|
|
1140
|
+
*/
|
|
1141
|
+
bulkBandHasActions() {
|
|
1142
|
+
return this.showMassCopy || this.showMassDelete
|
|
1143
|
+
|| (Array.isArray(this.bulkActions) && this.bulkActions.length > 0)
|
|
1144
|
+
|| Boolean(this.$slots['selection-actions'])
|
|
1145
|
+
},
|
|
1146
|
+
|
|
1120
1147
|
/**
|
|
1121
1148
|
* The bold lead of the board bulk band.
|
|
1122
1149
|
*
|
|
@@ -18,7 +18,7 @@ When `CnDashboardPage` resolves a widget definition with `type: "chart"`, it mou
|
|
|
18
18
|
}
|
|
19
19
|
```
|
|
20
20
|
|
|
21
|
-
Supported `props` keys forwarded by the dispatcher: `chartKind` (→ `type`), `series`, `categories`, `labels`, `options`, `colors`, `toolbar`, `legend`, `height`, `width`, `unavailableLabel`, plus the display passthrough `horizontal`, `legendPosition`, `valueAxisBaseline`, `valueFormat`, `colorMap`, `emptyLabel`, `views`, `endpointSource`, `barMax`, `footnote`, `highlight`, `cellSource`. The `dataSource` field resolves declaratively: `aggregate: 'count'` / raw `graphql` via GraphQL, `bucket` / `groupBy` / the OBJECT-form `aggregate` (Wave 3: group-by + topN/Other + labelResolve) via OpenRegister's REST aggregation facets, with an optional sibling `drilldown: { route, filterParam }` that navigates on segment/bar click with the raw category key in the query.
|
|
21
|
+
Supported `props` keys forwarded by the dispatcher: `chartKind` (→ `type`), `series`, `categories`, `labels`, `options`, `colors`, `toolbar`, `legend`, `height`, `width`, `unavailableLabel`, plus the display passthrough `horizontal`, `legendPosition`, `valueAxisBaseline`, `valueFormat`, `colorMap`, `emptyLabel`, `views`, `endpointSource`, `barMax`, `footnote`, `highlight`, `cellSource`, `emptyCellLabel`. The `dataSource` field resolves declaratively: `aggregate: 'count'` / raw `graphql` via GraphQL, `bucket` / `groupBy` / the OBJECT-form `aggregate` (Wave 3: group-by + topN/Other + labelResolve) via OpenRegister's REST aggregation facets, with an optional sibling `drilldown: { route, filterParam }` that navigates on segment/bar click with the raw category key in the query.
|
|
22
22
|
|
|
23
23
|
Area chart — time series data:
|
|
24
24
|
|
|
@@ -107,7 +107,8 @@ Fallback slot — shown when ApexCharts is not available:
|
|
|
107
107
|
| `horizontal` | Boolean | `false` | Render `type: "bar"` charts horizontally (row bars); an explicit `options.plotOptions.bar.horizontal` still wins |
|
|
108
108
|
| `legendPosition` | String | `''` | Legend placement override (`top`/`bottom`/`left`/`right`); empty keeps the automatic placement |
|
|
109
109
|
| `barMax` | Number | `null` | `bar-list`: the value a full track stands for (100 for percentages); null takes the largest value |
|
|
110
|
-
| `footnote` | String | `''` |
|
|
110
|
+
| `footnote` | String | `''` | A line under the chart, through the host's translate: under the rows of a `bar-list` or `matrix`, under the plot of a `line`, `area` or `bar` chart |
|
|
111
|
+
| `emptyCellLabel` | String | `''` | `matrix`: the text of a cell without a value ("geen"), through the host's translate. Empty leaves the cell blank |
|
|
111
112
|
| `highlight` | Object | `null` | `matrix`: the cell to outline, `{ row, column, columnKeys? }`, tokens such as `@object.behaviour` resolved |
|
|
112
113
|
| `cellSource` | Object | `null` | `matrix`: read the cells from records that each hold one cell (`{ register, schema, filter?, rowField, columnField, valueField, … }`), or with `cellsPath` from the cells inside one record, see [Bar list and matrix](#bar-list-and-matrix) |
|
|
113
114
|
| `valueAxisBaseline` | String | `'auto'` | How the value axis picks its baseline, so a small difference cannot read as a dramatic one. `'auto'` anchors magnitude marks (bar/area) at zero and stops line charts zooming past a quarter of the data's magnitude; `'zero'` always anchors at zero; `'fit'` restores plain ApexCharts autoscaling — use it for series that live far from zero (a percentage hovering 95–99), where a zero baseline flattens the signal. Pie-family charts, negative series, empty data and stacked charts (`options.chart.stacked` — where the visible height is the per-category sum, not the largest datapoint) always autoscale; an explicit `options.yaxis.min`/`max` still wins. The ceiling rounds up to a nice number (7 → 8, 62 → 80). |
|
|
@@ -126,6 +126,12 @@
|
|
|
126
126
|
</p>
|
|
127
127
|
</slot>
|
|
128
128
|
</div>
|
|
129
|
+
<p
|
|
130
|
+
v-if="footnote && chartComponent && !showEmptyState && type !== 'bar-list' && type !== 'matrix'"
|
|
131
|
+
class="cn-chart-widget__footnote"
|
|
132
|
+
data-testid="cn-chart-widget-footnote">
|
|
133
|
+
{{ hostTranslate(footnote) }}
|
|
134
|
+
</p>
|
|
129
135
|
</div>
|
|
130
136
|
</template>
|
|
131
137
|
|
|
@@ -368,8 +374,9 @@ export default {
|
|
|
368
374
|
},
|
|
369
375
|
|
|
370
376
|
/**
|
|
371
|
-
* A line under
|
|
372
|
-
*
|
|
377
|
+
* A line under the chart ("Klik een balk om de zaken te zien"),
|
|
378
|
+
* through the host's translate: under the rows of a `bar-list` or
|
|
379
|
+
* `matrix`, and under the plot of an ApexCharts type.
|
|
373
380
|
*
|
|
374
381
|
* @spec openspec/changes/chart-bar-list-and-matrix/specs/chart-bar-list-and-matrix/spec.md#requirement-a-chart-can-draw-a-bar-list
|
|
375
382
|
*/
|
|
@@ -605,6 +612,17 @@ export default {
|
|
|
605
612
|
default: '',
|
|
606
613
|
},
|
|
607
614
|
|
|
615
|
+
/**
|
|
616
|
+
* `matrix`: the text of a cell without a value ("geen"), through the
|
|
617
|
+
* host's translate. Empty (the default) leaves the cell blank.
|
|
618
|
+
*
|
|
619
|
+
* @spec openspec/changes/chart-bar-list-and-matrix/specs/chart-bar-list-and-matrix/spec.md#requirement-a-chart-can-draw-a-matrix
|
|
620
|
+
*/
|
|
621
|
+
emptyCellLabel: {
|
|
622
|
+
type: String,
|
|
623
|
+
default: '',
|
|
624
|
+
},
|
|
625
|
+
|
|
608
626
|
/**
|
|
609
627
|
* Manifest dataSource block. When set, `series` /
|
|
610
628
|
* `categories` / `labels` are resolved from the GraphQL
|
|
@@ -1442,7 +1460,7 @@ export default {
|
|
|
1442
1460
|
const value = Number(raw)
|
|
1443
1461
|
return Number.isFinite(value) && raw !== null && raw !== undefined
|
|
1444
1462
|
? { text: this.formatPlain(value), level: levelOf(value), color: '', current: isCurrent }
|
|
1445
|
-
: { text: '', level: 0, color: '', current: isCurrent }
|
|
1463
|
+
: { text: this.emptyCellLabel ? this.hostTranslate(this.emptyCellLabel) : '', level: 0, color: '', current: isCurrent }
|
|
1446
1464
|
}),
|
|
1447
1465
|
})),
|
|
1448
1466
|
}
|
|
@@ -2388,6 +2406,8 @@ export default {
|
|
|
2388
2406
|
* Map an endpoint payload whose `rowsPath` names an array of rows:
|
|
2389
2407
|
* each row is a series (name at `rowLabelPath`, values at
|
|
2390
2408
|
* `rowValuesPath`), the categories are at `labelsPath`.
|
|
2409
|
+
* A missing value stays null; a `matrix` keeps a text value ("none")
|
|
2410
|
+
* as text, other types read it as 0.
|
|
2391
2411
|
*
|
|
2392
2412
|
* @param {unknown} payload The plucked payload.
|
|
2393
2413
|
* @param {object} es The `endpointSource` block.
|
|
@@ -2398,12 +2418,23 @@ export default {
|
|
|
2398
2418
|
const rows = getByPath(payload, es.rowsPath)
|
|
2399
2419
|
const rawLabels = es.labelsPath ? getByPath(payload, es.labelsPath) : undefined
|
|
2400
2420
|
const labels = Array.isArray(rawLabels) ? rawLabels.map((v) => ((v === null || v === undefined) ? '' : String(v))) : []
|
|
2421
|
+
const keepText = this.type === 'matrix'
|
|
2422
|
+
const cellOf = (v) => {
|
|
2423
|
+
if (v === null || v === undefined) {
|
|
2424
|
+
return null
|
|
2425
|
+
}
|
|
2426
|
+
const num = typeof v === 'string' && v.trim() === '' ? NaN : Number(v)
|
|
2427
|
+
if (Number.isFinite(num)) {
|
|
2428
|
+
return num
|
|
2429
|
+
}
|
|
2430
|
+
return keepText && typeof v === 'string' ? v : 0
|
|
2431
|
+
}
|
|
2401
2432
|
const series = (Array.isArray(rows) ? rows : []).map((row) => {
|
|
2402
2433
|
const name = getByPath(row, es.rowLabelPath || 'label')
|
|
2403
2434
|
const values = getByPath(row, es.rowValuesPath || 'values')
|
|
2404
2435
|
return {
|
|
2405
2436
|
name: (name === null || name === undefined) ? '' : String(name),
|
|
2406
|
-
data: Array.isArray(values) ? values.map(
|
|
2437
|
+
data: Array.isArray(values) ? values.map(cellOf) : [],
|
|
2407
2438
|
}
|
|
2408
2439
|
})
|
|
2409
2440
|
return { series, categories: labels, labels }
|
|
@@ -2690,6 +2721,13 @@ export default {
|
|
|
2690
2721
|
margin: 0;
|
|
2691
2722
|
}
|
|
2692
2723
|
|
|
2724
|
+
/* Under an ApexCharts plot the footnote is a sibling of the canvas, so it keeps
|
|
2725
|
+
its own line height while the canvas takes the rest of a fitted column. */
|
|
2726
|
+
.cn-chart-widget > .cn-chart-widget__footnote {
|
|
2727
|
+
flex: 0 0 auto;
|
|
2728
|
+
margin-top: 8px;
|
|
2729
|
+
}
|
|
2730
|
+
|
|
2693
2731
|
.cn-chart-widget__matrix {
|
|
2694
2732
|
display: grid;
|
|
2695
2733
|
gap: 4px;
|
|
@@ -111,7 +111,7 @@
|
|
|
111
111
|
<Pencil v-if="!isEditing" :size="20" />
|
|
112
112
|
<Check v-else :size="20" />
|
|
113
113
|
</template>
|
|
114
|
-
{{ isEditing ?
|
|
114
|
+
{{ isEditing ? shownDoneLabel : shownEditLabel }}
|
|
115
115
|
</NcButton>
|
|
116
116
|
<!-- With `userLayout`, edit mode offers a way back to the
|
|
117
117
|
manifest: the page's own grid and the chosen view return
|
|
@@ -1105,6 +1105,7 @@ const CHART_PROP_KEYS = [
|
|
|
1105
1105
|
'footnote',
|
|
1106
1106
|
'highlight',
|
|
1107
1107
|
'cellSource',
|
|
1108
|
+
'emptyCellLabel',
|
|
1108
1109
|
]
|
|
1109
1110
|
|
|
1110
1111
|
/**
|
|
@@ -2400,6 +2401,25 @@ export default {
|
|
|
2400
2401
|
return (this.pageFilters || []).filter((pf) => pf && pf.key && !inDescription.includes(pf))
|
|
2401
2402
|
},
|
|
2402
2403
|
|
|
2404
|
+
/**
|
|
2405
|
+
* The edit button's label through the app's translate: a manifest's
|
|
2406
|
+
* `editLabel` ("Edit layout", DqDashboard) reads in the user's language.
|
|
2407
|
+
*
|
|
2408
|
+
* @return {string}
|
|
2409
|
+
*/
|
|
2410
|
+
shownEditLabel() {
|
|
2411
|
+
return this.effectiveTranslate(this.editLabel)
|
|
2412
|
+
},
|
|
2413
|
+
|
|
2414
|
+
/**
|
|
2415
|
+
* The done button's label through the app's translate.
|
|
2416
|
+
*
|
|
2417
|
+
* @return {string}
|
|
2418
|
+
*/
|
|
2419
|
+
shownDoneLabel() {
|
|
2420
|
+
return this.effectiveTranslate(this.doneLabel)
|
|
2421
|
+
},
|
|
2422
|
+
|
|
2403
2423
|
/**
|
|
2404
2424
|
* The preset list passed to the picker. Falls back to the
|
|
2405
2425
|
* `DEFAULT_DATE_RANGE_PRESETS` constant when the consumer
|
|
@@ -362,7 +362,7 @@ export default {
|
|
|
362
362
|
| `lensReasonTexts` | Object \| null | `null` | App wording for an unavailable lens, keyed `<lens>.<reason>` or `<reason>`. |
|
|
363
363
|
| `loadingText` | String | `'Loading…'` | Accessible label for the loading spinner (NcLoadingIcon aria-label) |
|
|
364
364
|
| `rowIcon` | String \| Function | `null` | Optional leading icon for every table row — a static MDI name or `(row) => iconName`. Forwarded to CnDataTable; fed from the manifest as `pages[].config.rowIcon`. Unset = no icon column. |
|
|
365
|
-
| `rowClass` | Function | `null` | Callback returning CSS class(es) for a row |
|
|
365
|
+
| `rowClass` | Function \| Array | `null` | Callback returning CSS class(es) for a row, or (manifest `config.rowClass`) rules `[{ when: { field, op?, value }, class }]` compiled into one: each adds its class to a row whose field compares to the value (`visibleWhen` operators; two dates compare as moments, `@today` included). |
|
|
366
366
|
| `rowIcon` | String \| Function | `null` | Optional leading row icon forwarded to CnDataTable — a static MDI icon name or `(row) => iconName`. Fed from the manifest as `pages[].config.rowIcon`; unset = no icon column |
|
|
367
367
|
| `inlineActionCount` | Number | `2` | How many row actions to show inline (rest go in overflow menu) |
|
|
368
368
|
| `showMassImport` | Boolean | `true` | Whether to show the mass Import action |
|
|
@@ -414,6 +414,7 @@ export default {
|
|
|
414
414
|
| `quickFilterMode` | String | `'chips'` | How the quick filters render: `'chips'` (pill strip) or `'dropdown'` (a single `NcSelect`). Fed from `pages[].config.quickFilterMode`. |
|
|
415
415
|
| `quickFilterMultiple` | Boolean | `false` | Allow several quick filters active at once; selected tabs' filters are OR-ed into the fetch (same field → `field[]=` array). Fed from `pages[].config.quickFilterMultiple`. |
|
|
416
416
|
| `quickFilterMaxVisible` | Number | `0` | Chips mode only — how many quick-filter pills render inline before the rest move behind one more chip — a `⋯` pill that opens a panel of the hidden lenses. `0` renders every tab, which wraps the actions bar onto a second line once a page declares more than a handful. The visible set is the first *n* entries of `quickFilters`. Fed from `pages[].config.quickFilterMaxVisible`. |
|
|
417
|
+
| `quickFilterPlacement` | String | `''` | Where the quick-filter chips sit. `'toolbar'` keeps them on one row with the Filter button and the view switch, in whatever width that row has beside a side panel (DqTeamwachtrij): the chips take the room the buttons leave, and those that do not fit move behind the overflow chip. Fed from `pages[].config.quickFilterPlacement`. |
|
|
417
418
|
| `cardComponent` | String | `''` | Optional name of a consumer-provided card component (registered in the v2 `registry` — any kind carrying a `component` — or in the legacy `customComponents` map on `CnAppRoot`) to render in place of the default `CnObjectCard` when the page is in card-grid view mode. Resolution priority: `#card` scoped slot → `cardComponent` registry entry → default `CnObjectCard`. Unknown names log `console.warn` once and fall back to the default. |
|
|
418
419
|
| `customComponents` | Object | `null` | Optional explicit `customComponents` registry. Overrides the registry injected from `CnAppRoot` via `cnCustomComponents`. Mostly used by unit tests; production consumers register components on `CnAppRoot` instead. |
|
|
419
420
|
| `subscribe` | Boolean | `true` | Self-fetch mode only. When `register` + `schema` are set (and no `objects` prop), the page subscribes to the collection's `or-collection-{register}-{schema}` live-update scope on mount and refetches on an update event; released on unmount. Set `false` (manifest: `config.subscribe: false`) for static / read-once views. No-op in consumer-managed mode or on stores without live-updates support. |
|
|
@@ -1136,3 +1137,6 @@ columns are right.
|
|
|
1136
1137
|
## Board look
|
|
1137
1138
|
|
|
1138
1139
|
With `look: "board"` (the page's `look` prop, `config.look`, or the app's) the index page takes the DqZaken setup: a header with the count line from `countText` (`{shown}`, `{total}`), the buttons Download, Actions, the buildiq square and the primary one in that order, a two-row toolbar (saved-view chips, Filter with a count and the view switch; then search and active filter chips), a bulk band between toolbar and table (`bulkHint`), the table as a white card with one menu button per row, and a footer inside the card (`footerNote`). `cardFields` names the facts of each card in the cards view. Without the look nothing changes.
|
|
1140
|
+
|
|
1141
|
+
`bulkBandAlways` (`config.bulkBandAlways`) draws the board bulk band before a selection too, its buttons
|
|
1142
|
+
disabled until rows are selected (DqZaken, DqWerkbord).
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div class="cn-index-page"
|
|
3
|
-
:class="[lookClass, { 'cn-index-page--with-side-panel': hasSidePanel }]"
|
|
3
|
+
:class="[lookClass, { 'cn-index-page--with-side-panel': hasSidePanel, 'cn-index-page--quick-filters-toolbar': quickFilterPlacement === 'toolbar' }]"
|
|
4
4
|
data-testid="cn-index-page"
|
|
5
5
|
@keydown="onListKeydown">
|
|
6
6
|
<!-- Header — overridable via #header slot. CnPageHeader ALWAYS renders:
|
|
@@ -163,6 +163,7 @@
|
|
|
163
163
|
:showBuildiqButton="!buildiqInHeader"
|
|
164
164
|
:bulkNoun="boardBulkNoun"
|
|
165
165
|
:bulkHint="bulkHint ? cnTranslate(bulkHint) : bulkHint"
|
|
166
|
+
:bulkBandAlways="bulkBandAlways"
|
|
166
167
|
:pagination="effectivePagination"
|
|
167
168
|
:objectCount="effectiveObjects.length"
|
|
168
169
|
:selectable="selectable"
|
|
@@ -369,6 +370,7 @@
|
|
|
369
370
|
:tabs="tabStripEntries"
|
|
370
371
|
:mode="quickFilterMode"
|
|
371
372
|
:maxVisible="quickFilterMaxVisible"
|
|
373
|
+
:fit="quickFilterPlacement === 'toolbar'"
|
|
372
374
|
:multiple="quickFilterMultiple"
|
|
373
375
|
:activeIndex="activeQuickFilterIndex"
|
|
374
376
|
:selectedIndices="selectedQuickFilterIndices"
|
|
@@ -755,7 +757,7 @@
|
|
|
755
757
|
:excludeColumns="excludeColumns"
|
|
756
758
|
:includeColumns="includeColumns"
|
|
757
759
|
:columnOverrides="columnOverrides"
|
|
758
|
-
:rowClass="
|
|
760
|
+
:rowClass="compiledRowClass"
|
|
759
761
|
:rowTitle="rowTitle"
|
|
760
762
|
:showUnread="showUnreadRows"
|
|
761
763
|
:filterable="tableHeaderFilters"
|
|
@@ -1292,6 +1294,7 @@ import { resolveFilterMap } from '../../utils/routeFilters.js'
|
|
|
1292
1294
|
import { availableRowActions, DEFAULT_ROW_ACTION_FIELD, refusalReasonFor, undeclaredRowActions, withoutViewWhenRowOpensDetail } from '../../utils/rowActionAvailability.js'
|
|
1293
1295
|
import { isRowActionVisible, rowActionPayload } from '../../utils/rowActionItem.js'
|
|
1294
1296
|
import { isNewTabClick, isNewTabHandled, isRowMiddleClick, markNewTabHandled, preventMiddleClickAutoscroll } from '../../utils/rowAuxClick.js'
|
|
1297
|
+
import { compileRowClass } from '../../utils/rowClassRules.js'
|
|
1295
1298
|
import { DEFAULT_ROW_INDICATOR_CAP } from '../../utils/rowIndicators.js'
|
|
1296
1299
|
import { buildRouteQueryFromViewState, buildViewCreatePayload, extractViewState, extractViewStateFromRouteQuery, normalizeSharedWith, savedViewScope, viewMatchesScope } from '../../utils/savedViewHelpers.js'
|
|
1297
1300
|
import { columnsFromSchema, fieldsFromSchema } from '../../utils/schema.js'
|
|
@@ -1938,6 +1941,17 @@ export default {
|
|
|
1938
1941
|
default: '',
|
|
1939
1942
|
},
|
|
1940
1943
|
|
|
1944
|
+
/**
|
|
1945
|
+
* Board look: draw the bulk band before anything is selected too, its
|
|
1946
|
+
* buttons disabled until there is a selection (DqZaken, DqWerkbord).
|
|
1947
|
+
* Manifest key `config.bulkBandAlways`. Only when the band has an
|
|
1948
|
+
* action to offer.
|
|
1949
|
+
*/
|
|
1950
|
+
bulkBandAlways: {
|
|
1951
|
+
type: Boolean,
|
|
1952
|
+
default: false,
|
|
1953
|
+
},
|
|
1954
|
+
|
|
1941
1955
|
/**
|
|
1942
1956
|
* Board look: the 13px hint after the bulk band's buttons ("See what
|
|
1943
1957
|
* changes first, then run it"). Manifest key `config.bulkHint`.
|
|
@@ -2119,6 +2133,21 @@ export default {
|
|
|
2119
2133
|
default: null,
|
|
2120
2134
|
},
|
|
2121
2135
|
|
|
2136
|
+
/**
|
|
2137
|
+
* Where the quick-filter chips sit (manifest `config.quickFilterPlacement`).
|
|
2138
|
+
* `''` (the default) as before. `'toolbar'` keeps them on one row with
|
|
2139
|
+
* the Filter button and the view switch, in whatever width that row has
|
|
2140
|
+
* beside a side panel (DqTeamwachtrij): the chips take the room the
|
|
2141
|
+
* buttons leave, and those that do not fit move into the overflow chip.
|
|
2142
|
+
*
|
|
2143
|
+
* @type {''|'toolbar'}
|
|
2144
|
+
*/
|
|
2145
|
+
quickFilterPlacement: {
|
|
2146
|
+
type: String,
|
|
2147
|
+
default: '',
|
|
2148
|
+
validator: (v) => ['', 'toolbar'].includes(v),
|
|
2149
|
+
},
|
|
2150
|
+
|
|
2122
2151
|
/**
|
|
2123
2152
|
* How the quick filters render: `'chips'` (pill strip, default) or
|
|
2124
2153
|
* `'dropdown'` (a single `NcSelect`). Sourced from the manifest as
|
|
@@ -2695,9 +2724,18 @@ export default {
|
|
|
2695
2724
|
default: 'Loading…',
|
|
2696
2725
|
},
|
|
2697
2726
|
|
|
2698
|
-
/**
|
|
2727
|
+
/**
|
|
2728
|
+
* CSS class(es) for a row: a function `(row) => string`, or (manifest
|
|
2729
|
+
* `config.rowClass`) rules `[{ when: { field, op?, value }, class }]`,
|
|
2730
|
+
* each adding its class to a row whose field compares to the value
|
|
2731
|
+
* (the `visibleWhen` operators, `@today` included). DqTaken marks an
|
|
2732
|
+
* overdue task: `{ when: { field: "dueAt", op: "lt", value: "@today" },
|
|
2733
|
+
* class: "cn-row--overdue" }`.
|
|
2734
|
+
*
|
|
2735
|
+
* @type {((row: object) => string)|Array<{when: {field: string, op?: string, value: unknown}, class: string}>|null}
|
|
2736
|
+
*/
|
|
2699
2737
|
rowClass: {
|
|
2700
|
-
type: Function,
|
|
2738
|
+
type: [Function, Array],
|
|
2701
2739
|
default: null,
|
|
2702
2740
|
},
|
|
2703
2741
|
|
|
@@ -3779,6 +3817,10 @@ export default {
|
|
|
3779
3817
|
//
|
|
3780
3818
|
// Seeded from the route query so a shared link lands filtered, the
|
|
3781
3819
|
// same way `_order` and a deep-link filter already do for self-fetch.
|
|
3820
|
+
// The page a paging named source shows: page 1 at the source config's
|
|
3821
|
+
// `limit` (20 by default), moved by the pager.
|
|
3822
|
+
const namedPageSize = Number(props.sourceConfig && props.sourceConfig.limit) > 0 ? Number(props.sourceConfig.limit) : 20
|
|
3823
|
+
const namedPaging = ref({ page: 1, limit: namedPageSize })
|
|
3782
3824
|
const namedActiveFilters = ref(namedFiltersFromRoute(getCurrentInstance(), props))
|
|
3783
3825
|
|
|
3784
3826
|
const {
|
|
@@ -3787,7 +3829,7 @@ export default {
|
|
|
3787
3829
|
namedRows,
|
|
3788
3830
|
namedLoading,
|
|
3789
3831
|
namedQuickFilters,
|
|
3790
|
-
} = useNamedSource(props, { activeQuickFilterIndex, activeFilters: namedActiveFilters })
|
|
3832
|
+
} = useNamedSource(props, { activeQuickFilterIndex, activeFilters: namedActiveFilters, paging: namedPaging })
|
|
3791
3833
|
|
|
3792
3834
|
return {
|
|
3793
3835
|
isBoard: isBoardLook,
|
|
@@ -3799,6 +3841,7 @@ export default {
|
|
|
3799
3841
|
namedLoading,
|
|
3800
3842
|
namedQuickFilters,
|
|
3801
3843
|
namedActiveFilters,
|
|
3844
|
+
namedPaging,
|
|
3802
3845
|
contextMenuOpen,
|
|
3803
3846
|
contextMenuRow,
|
|
3804
3847
|
openContextMenu,
|
|
@@ -4761,6 +4804,9 @@ export default {
|
|
|
4761
4804
|
const loaded = this.effectivePagination || {}
|
|
4762
4805
|
return Number(loaded.page || 1) < Number(loaded.pages || 1)
|
|
4763
4806
|
}
|
|
4807
|
+
if (this.isNamedSource && this.namedSource && this.namedSource.pages === true) {
|
|
4808
|
+
return Number(this.effectivePagination?.pages || 1) > 1
|
|
4809
|
+
}
|
|
4764
4810
|
return Number(this.pagination?.pages || 1) > 1
|
|
4765
4811
|
},
|
|
4766
4812
|
|
|
@@ -5800,7 +5846,13 @@ export default {
|
|
|
5800
5846
|
// A named source that reports its own total (the search source)
|
|
5801
5847
|
// gives the count line its number.
|
|
5802
5848
|
if (this.isNamedSource && this.namedSource && typeof this.namedSource.total === 'function') {
|
|
5803
|
-
|
|
5849
|
+
const total = this.namedSource.total()
|
|
5850
|
+
// A source with `pages: true` gets the pager the self-fetched lists draw.
|
|
5851
|
+
if (this.namedSource.pages === true) {
|
|
5852
|
+
const { page, limit } = this.namedPaging
|
|
5853
|
+
return { page, limit, total, pages: Math.max(1, Math.ceil(total / limit)) }
|
|
5854
|
+
}
|
|
5855
|
+
return { ...(this.pagination || {}), total }
|
|
5804
5856
|
}
|
|
5805
5857
|
return this.isSelfFetchMode ? this.list.pagination.value : this.pagination
|
|
5806
5858
|
},
|
|
@@ -6053,6 +6105,16 @@ export default {
|
|
|
6053
6105
|
return (this.effectiveSchema && this.effectiveSchema.slug) || ''
|
|
6054
6106
|
},
|
|
6055
6107
|
|
|
6108
|
+
/**
|
|
6109
|
+
* The row-class function the table takes: a function as given, or the
|
|
6110
|
+
* manifest's rules compiled.
|
|
6111
|
+
*
|
|
6112
|
+
* @return {?(row: object) => string}
|
|
6113
|
+
*/
|
|
6114
|
+
compiledRowClass() {
|
|
6115
|
+
return compileRowClass(this.rowClass)
|
|
6116
|
+
},
|
|
6117
|
+
|
|
6056
6118
|
/** @return {number} How many leading columns the person pinned (0 while a saved view's columns are applied). */
|
|
6057
6119
|
pinnedColumnCount() {
|
|
6058
6120
|
if (!this.personalColumns || Array.isArray(this.appliedViewColumns) || !this.personalLayout) {
|
|
@@ -8777,6 +8839,9 @@ export default {
|
|
|
8777
8839
|
if (this.isSelfFetchMode && typeof this.list.onPageChange === 'function') {
|
|
8778
8840
|
this.list.onPageChange(page)
|
|
8779
8841
|
}
|
|
8842
|
+
if (this.isNamedSource && this.namedSource && this.namedSource.pages === true) {
|
|
8843
|
+
this.namedPaging = { ...this.namedPaging, page }
|
|
8844
|
+
}
|
|
8780
8845
|
this.$emit('page-changed', page)
|
|
8781
8846
|
},
|
|
8782
8847
|
|
|
@@ -8792,6 +8857,9 @@ export default {
|
|
|
8792
8857
|
if (this.isSelfFetchMode && typeof this.list.onPageSizeChange === 'function') {
|
|
8793
8858
|
this.list.onPageSizeChange(size)
|
|
8794
8859
|
}
|
|
8860
|
+
if (this.isNamedSource && this.namedSource && this.namedSource.pages === true) {
|
|
8861
|
+
this.namedPaging = { page: 1, limit: size }
|
|
8862
|
+
}
|
|
8795
8863
|
this.$emit('page-size-changed', size)
|
|
8796
8864
|
},
|
|
8797
8865
|
|
|
@@ -105,6 +105,9 @@ export function useNamedSource(props, options = {}) {
|
|
|
105
105
|
const tabs = manifestTabs || sourceTabs
|
|
106
106
|
const activeIndex = options.activeQuickFilterIndex || null
|
|
107
107
|
const activeFilters = options.activeFilters || null
|
|
108
|
+
// A source that pages (`pages: true`) gets the page as `limit` and
|
|
109
|
+
// `offset`, from the pager the page draws for it.
|
|
110
|
+
const paging = source.pages === true ? (options.paging || null) : null
|
|
108
111
|
|
|
109
112
|
// Seed the default tab before the watcher below registers: the mount load
|
|
110
113
|
// already carries this tab's filter, so the seed must not fire a second
|
|
@@ -165,6 +168,7 @@ export function useNamedSource(props, options = {}) {
|
|
|
165
168
|
activeFilters ? activeFilters.value : null,
|
|
166
169
|
props.entitySource,
|
|
167
170
|
),
|
|
171
|
+
...(paging ? { limit: paging.value.limit, offset: (paging.value.page - 1) * paging.value.limit } : {}),
|
|
168
172
|
},
|
|
169
173
|
tokenCtx(),
|
|
170
174
|
)
|
|
@@ -182,15 +186,35 @@ export function useNamedSource(props, options = {}) {
|
|
|
182
186
|
|
|
183
187
|
// Registered AFTER the seed above, so only a person switching tabs
|
|
184
188
|
// reloads. Without tabs there is nothing to watch.
|
|
189
|
+
/**
|
|
190
|
+
* Reload for a new query: on a paging source back to page 1, which
|
|
191
|
+
* reloads through the paging watcher below.
|
|
192
|
+
*
|
|
193
|
+
* @return {void}
|
|
194
|
+
*/
|
|
195
|
+
function reloadFromFirstPage() {
|
|
196
|
+
if (paging && paging.value.page !== 1) {
|
|
197
|
+
paging.value = { ...paging.value, page: 1 }
|
|
198
|
+
return
|
|
199
|
+
}
|
|
200
|
+
loadActive()
|
|
201
|
+
}
|
|
202
|
+
|
|
185
203
|
if (tabs && activeIndex) {
|
|
186
|
-
watch(activeIndex,
|
|
204
|
+
watch(activeIndex, reloadFromFirstPage)
|
|
187
205
|
}
|
|
188
206
|
|
|
189
207
|
// A sidebar choice is a new QUERY, not a new view of the page already
|
|
190
208
|
// fetched, so it reloads. `deep` because the map is rewritten key by key
|
|
191
209
|
// and a shallow watch misses a second value added to the same field.
|
|
192
210
|
if (activeFilters) {
|
|
193
|
-
watch(activeFilters,
|
|
211
|
+
watch(activeFilters, reloadFromFirstPage, { deep: true })
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
// A new page, or a new page size, is a new request. A new tab or filter
|
|
215
|
+
// first returns to page 1, which reloads through here.
|
|
216
|
+
if (paging) {
|
|
217
|
+
watch(paging, loadActive, { deep: true })
|
|
194
218
|
}
|
|
195
219
|
|
|
196
220
|
// No manual invalidation tick here on purpose. The adapters read from a
|
|
@@ -239,6 +239,11 @@ export default {
|
|
|
239
239
|
CnMenuItemIcon,
|
|
240
240
|
},
|
|
241
241
|
|
|
242
|
+
inject: {
|
|
243
|
+
/** Host translate function provided by CnAppRoot, for the item labels. */
|
|
244
|
+
cnTranslate: { default: () => (key) => key },
|
|
245
|
+
},
|
|
246
|
+
|
|
242
247
|
props: {
|
|
243
248
|
/**
|
|
244
249
|
* Persisted widget content `{items, style, orientation, showIcons,
|
|
@@ -288,7 +293,26 @@ export default {
|
|
|
288
293
|
*/
|
|
289
294
|
items() {
|
|
290
295
|
const arr = this.content?.items
|
|
291
|
-
|
|
296
|
+
if (!Array.isArray(arr)) {
|
|
297
|
+
return []
|
|
298
|
+
}
|
|
299
|
+
// Labels are manifest strings: they go through the app's translate,
|
|
300
|
+
// children included, so "Case types" reads "Zaaktypen" (DqCatalogus).
|
|
301
|
+
const translate = typeof this.cnTranslate === 'function' ? this.cnTranslate : (key) => key
|
|
302
|
+
const translated = (list) => list.map((item) => {
|
|
303
|
+
if (!item || typeof item !== 'object') {
|
|
304
|
+
return item
|
|
305
|
+
}
|
|
306
|
+
const out = { ...item }
|
|
307
|
+
if (typeof item.label === 'string' && item.label !== '') {
|
|
308
|
+
out.label = translate(item.label)
|
|
309
|
+
}
|
|
310
|
+
if (Array.isArray(item.children)) {
|
|
311
|
+
out.children = translated(item.children)
|
|
312
|
+
}
|
|
313
|
+
return out
|
|
314
|
+
})
|
|
315
|
+
return translated(arr)
|
|
292
316
|
},
|
|
293
317
|
|
|
294
318
|
/**
|
|
@@ -59,6 +59,7 @@ In `manifest.json` (the usual entry-point — CnIndexPage mounts the bar for you
|
|
|
59
59
|
- `selectLabel` (String, default `'Filter'`) — accessible label / placeholder for the dropdown control.
|
|
60
60
|
- `placeholder` (String) — placeholder text for the dropdown (falls back to `selectLabel`).
|
|
61
61
|
- `maxVisible` (Number, default `0`) — chips mode only: how many pills render inline before the rest move behind one more chip, a `⋯` pill that opens a small panel of the hidden lenses (also as chips). `0` renders every tab. The visible set is the first `maxVisible` entries of `tabs`, so their declared order decides what stays in the strip; an active hidden tab moves its label and fill onto that chip. Manifest: `config.quickFilterMaxVisible`.
|
|
62
|
+
- `fit` (Boolean, default `false`) — chips mode only: show as many chips as the bar's own width holds and move the rest behind the overflow chip, measured again when the width, the tabs or the counts change. The bar takes the room its parent gives it; CnIndexPage's `quickFilterPlacement: "toolbar"` gives it what the Filter button and the view switch leave on their row. With `maxVisible` too, the smaller of the two wins.
|
|
62
63
|
- `counts` (Object or Array, default `null`): how many records each tab matches, keyed by tab index. A tab with a number shows it after its label. CnIndexPage fills this for tabs that set `showCount`.
|
|
63
64
|
|
|
64
65
|
### Events
|