@conduction/nextcloud-vue 2.62.0 → 2.63.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 (154) hide show
  1. package/dist/esm/components/CnAdminActionCard/CnAdminActionCard.vue.js +10 -0
  2. package/dist/esm/components/CnAdminActionCard/CnAdminActionCard.vue.js.map +1 -0
  3. package/dist/esm/components/CnAdminActionCard/CnAdminActionCard.vue2.js +189 -0
  4. package/dist/esm/components/CnAdminActionCard/CnAdminActionCard.vue2.js.map +1 -0
  5. package/dist/esm/components/CnAdminActionCard/CnAdminActionCard.vue3.js +72 -0
  6. package/dist/esm/components/CnAdminActionCard/CnAdminActionCard.vue3.js.map +1 -0
  7. package/dist/esm/components/CnAppNav/CnAppNav.vue2.js +271 -32
  8. package/dist/esm/components/CnAppNav/CnAppNav.vue2.js.map +1 -1
  9. package/dist/esm/components/CnAppNav/CnAppNav.vue3.js.map +1 -1
  10. package/dist/esm/components/CnAppRoot/CnAppRoot.vue2.js +99 -9
  11. package/dist/esm/components/CnAppRoot/CnAppRoot.vue2.js.map +1 -1
  12. package/dist/esm/components/CnAppRoot/CnAppRoot.vue3.js +39 -18
  13. package/dist/esm/components/CnAppRoot/CnAppRoot.vue3.js.map +1 -1
  14. package/dist/esm/components/CnChoiceCards/CnChoiceCards.vue2.js.map +1 -1
  15. package/dist/esm/components/CnChoiceCards/CnChoiceCards.vue3.js +53 -37
  16. package/dist/esm/components/CnChoiceCards/CnChoiceCards.vue3.js.map +1 -1
  17. package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue2.js.map +1 -1
  18. package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue3.js +2 -2
  19. package/dist/esm/components/CnDashboardPage/CnDashboardPage.vue3.js.map +1 -1
  20. package/dist/esm/components/CnDataTable/CnColumnFilterPopover.vue.js +10 -0
  21. package/dist/esm/components/CnDataTable/CnColumnFilterPopover.vue.js.map +1 -0
  22. package/dist/esm/components/CnDataTable/CnColumnFilterPopover.vue2.js +293 -0
  23. package/dist/esm/components/CnDataTable/CnColumnFilterPopover.vue2.js.map +1 -0
  24. package/dist/esm/components/CnDataTable/CnColumnFilterPopover.vue3.js +189 -0
  25. package/dist/esm/components/CnDataTable/CnColumnFilterPopover.vue3.js.map +1 -0
  26. package/dist/esm/components/CnDataTable/CnDataTable.vue2.js +216 -8
  27. package/dist/esm/components/CnDataTable/CnDataTable.vue2.js.map +1 -1
  28. package/dist/esm/components/CnDataTable/CnDataTable.vue3.js +118 -50
  29. package/dist/esm/components/CnDataTable/CnDataTable.vue3.js.map +1 -1
  30. package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue2.js.map +1 -1
  31. package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue3.js +2 -1
  32. package/dist/esm/components/CnDetailWidgetHost/CnDetailWidgetHost.vue3.js.map +1 -1
  33. package/dist/esm/components/CnFieldHelper/CnFieldHelper.vue2.js +3 -1
  34. package/dist/esm/components/CnFieldHelper/CnFieldHelper.vue2.js.map +1 -1
  35. package/dist/esm/components/CnFieldHelper/CnFieldHelper.vue3.js +1 -1
  36. package/dist/esm/components/CnFieldHelper/CnFieldHelper.vue3.js.map +1 -1
  37. package/dist/esm/components/CnFormDialog/CnFormDialog.vue2.js +234 -9
  38. package/dist/esm/components/CnFormDialog/CnFormDialog.vue2.js.map +1 -1
  39. package/dist/esm/components/CnFormDialog/CnFormDialog.vue3.js +96 -57
  40. package/dist/esm/components/CnFormDialog/CnFormDialog.vue3.js.map +1 -1
  41. package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js +51 -2
  42. package/dist/esm/components/CnIndexPage/CnIndexPage.vue2.js.map +1 -1
  43. package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js +5 -1
  44. package/dist/esm/components/CnIndexPage/CnIndexPage.vue3.js.map +1 -1
  45. package/dist/esm/components/CnIndexPage/selfModeActions.js +3 -3
  46. package/dist/esm/components/CnIndexPage/selfModeActions.js.map +1 -1
  47. package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue2.js +36 -1
  48. package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue2.js.map +1 -1
  49. package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue3.js +4 -1
  50. package/dist/esm/components/CnObjectListWidget/CnObjectListWidget.vue3.js.map +1 -1
  51. package/dist/esm/components/CnResourceSelect/CnResourceSelect.vue2.js +121 -12
  52. package/dist/esm/components/CnResourceSelect/CnResourceSelect.vue2.js.map +1 -1
  53. package/dist/esm/components/CnResourceSelect/CnResourceSelect.vue3.js +3 -1
  54. package/dist/esm/components/CnResourceSelect/CnResourceSelect.vue3.js.map +1 -1
  55. package/dist/esm/components/CnSetupWizard/CnSetupWizard.vue2.js +326 -1
  56. package/dist/esm/components/CnSetupWizard/CnSetupWizard.vue2.js.map +1 -1
  57. package/dist/esm/components/CnSetupWizard/CnSetupWizard.vue3.js +112 -26
  58. package/dist/esm/components/CnSetupWizard/CnSetupWizard.vue3.js.map +1 -1
  59. package/dist/esm/components/CnTimelineWidget/CnTimelineWidget.vue.js +10 -0
  60. package/dist/esm/components/CnTimelineWidget/CnTimelineWidget.vue.js.map +1 -0
  61. package/dist/esm/components/CnTimelineWidget/CnTimelineWidget.vue2.js +337 -0
  62. package/dist/esm/components/CnTimelineWidget/CnTimelineWidget.vue2.js.map +1 -0
  63. package/dist/esm/components/CnTimelineWidget/CnTimelineWidget.vue3.js +102 -0
  64. package/dist/esm/components/CnTimelineWidget/CnTimelineWidget.vue3.js.map +1 -0
  65. package/dist/esm/components/CnTimelineWidget/dashboardRegistration.js +34 -0
  66. package/dist/esm/components/CnTimelineWidget/dashboardRegistration.js.map +1 -0
  67. package/dist/esm/components/CnWalkthrough/CnWalkthrough.vue2.js +131 -8
  68. package/dist/esm/components/CnWalkthrough/CnWalkthrough.vue2.js.map +1 -1
  69. package/dist/esm/components/CnWalkthrough/CnWalkthrough.vue3.js +40 -38
  70. package/dist/esm/components/CnWalkthrough/CnWalkthrough.vue3.js.map +1 -1
  71. package/dist/esm/components/CnWidgetGrid/builtInWidgets.js +8 -6
  72. package/dist/esm/components/CnWidgetGrid/builtInWidgets.js.map +1 -1
  73. package/dist/esm/components/CnWidgetGrid/registerDashboardWidgets.js +1 -0
  74. package/dist/esm/components/CnWidgetGrid/registerDashboardWidgets.js.map +1 -1
  75. package/dist/esm/components/CnWizardDialog/CnWizardDialog.vue2.js +19 -0
  76. package/dist/esm/components/CnWizardDialog/CnWizardDialog.vue2.js.map +1 -1
  77. package/dist/esm/components/CnWizardDialog/CnWizardDialog.vue3.js +1 -1
  78. package/dist/esm/components/CnWizardDialog/CnWizardDialog.vue3.js.map +1 -1
  79. package/dist/esm/composables/useDependencyCheck.js +65 -0
  80. package/dist/esm/composables/useDependencyCheck.js.map +1 -0
  81. package/dist/esm/composables/useWalkthrough.js +218 -6
  82. package/dist/esm/composables/useWalkthrough.js.map +1 -1
  83. package/dist/esm/index.js +2 -0
  84. package/dist/esm/index.js.map +1 -1
  85. package/dist/esm/l10n/en.json.js +43 -0
  86. package/dist/esm/l10n/en.json.js.map +1 -1
  87. package/dist/esm/l10n/nl.json.js +43 -0
  88. package/dist/esm/l10n/nl.json.js.map +1 -1
  89. package/dist/esm/nextcloud-vue.css +449 -0
  90. package/dist/esm/store/useObjectStore.js +8 -0
  91. package/dist/esm/store/useObjectStore.js.map +1 -1
  92. package/dist/esm/utils/columnFilters.js +311 -0
  93. package/dist/esm/utils/columnFilters.js.map +1 -0
  94. package/dist/esm/utils/groupAutocomplete.js +123 -0
  95. package/dist/esm/utils/groupAutocomplete.js.map +1 -0
  96. package/dist/esm/utils/libraryWidgetKeys.js +2 -0
  97. package/dist/esm/utils/libraryWidgetKeys.js.map +1 -1
  98. package/dist/esm/utils/pickerOptions.js +198 -0
  99. package/dist/esm/utils/pickerOptions.js.map +1 -0
  100. package/dist/esm/utils/schema.js +83 -7
  101. package/dist/esm/utils/schema.js.map +1 -1
  102. package/dist/esm/utils/timelineEvents.js +174 -0
  103. package/dist/esm/utils/timelineEvents.js.map +1 -0
  104. package/dist/esm/utils/validateManifestV2.compiled.js +2 -2
  105. package/dist/esm/utils/validateManifestV2.compiled.js.map +1 -1
  106. package/dist/esm/utils/walkthroughSignals.js +88 -0
  107. package/dist/esm/utils/walkthroughSignals.js.map +1 -0
  108. package/dist/nextcloud-vue.cjs.js +9369 -5193
  109. package/dist/nextcloud-vue.cjs.js.map +2 -2
  110. package/dist/nextcloud-vue.css +449 -0
  111. package/l10n/en.json +43 -0
  112. package/l10n/nl.json +43 -0
  113. package/package.json +1 -1
  114. package/src/components/CnAdminActionCard/CnAdminActionCard.vue +234 -0
  115. package/src/components/CnAdminActionCard/index.js +4 -0
  116. package/src/components/CnAppNav/CnAppNav.vue +271 -32
  117. package/src/components/CnAppRoot/CnAppRoot.vue +129 -15
  118. package/src/components/CnChoiceCards/CnChoiceCards.vue +56 -31
  119. package/src/components/CnDashboardPage/CnDashboardPage.vue +2 -2
  120. package/src/components/CnDataTable/CnColumnFilterPopover.vue +524 -0
  121. package/src/components/CnDataTable/CnDataTable.md +3 -0
  122. package/src/components/CnDataTable/CnDataTable.vue +260 -4
  123. package/src/components/CnDetailWidgetHost/CnDetailWidgetHost.vue +2 -2
  124. package/src/components/CnFieldHelper/CnFieldHelper.vue +4 -2
  125. package/src/components/CnFormDialog/CnFormDialog.vue +290 -31
  126. package/src/components/CnIndexPage/CnIndexPage.vue +55 -2
  127. package/src/components/CnIndexPage/selfModeActions.js +3 -3
  128. package/src/components/CnObjectListWidget/CnObjectListWidget.vue +39 -1
  129. package/src/components/CnResourceSelect/CnResourceSelect.vue +123 -12
  130. package/src/components/CnSetupWizard/CnSetupWizard.vue +392 -3
  131. package/src/components/CnTimelineWidget/CnTimelineWidget.vue +477 -0
  132. package/src/components/CnTimelineWidget/dashboardRegistration.js +32 -0
  133. package/src/components/CnTimelineWidget/index.js +4 -0
  134. package/src/components/CnWalkthrough/CnWalkthrough.vue +143 -10
  135. package/src/components/CnWidgetGrid/builtInWidgets.js +2 -0
  136. package/src/components/CnWidgetGrid/registerDashboardWidgets.js +1 -0
  137. package/src/components/CnWizardDialog/CnWizardDialog.vue +20 -1
  138. package/src/components/index.js +2 -0
  139. package/src/composables/useDependencyCheck.js +61 -0
  140. package/src/composables/useWalkthrough.js +217 -5
  141. package/src/css/dashboard.css +49 -0
  142. package/src/css/detail-page.css +19 -0
  143. package/src/css/table.css +81 -0
  144. package/src/index.js +2 -0
  145. package/src/schemas/app-manifest-v2.schema.json +23 -1
  146. package/src/store/useObjectStore.js +8 -0
  147. package/src/utils/columnFilters.js +324 -0
  148. package/src/utils/groupAutocomplete.js +119 -0
  149. package/src/utils/libraryWidgetKeys.js +2 -0
  150. package/src/utils/pickerOptions.js +194 -0
  151. package/src/utils/schema.js +83 -7
  152. package/src/utils/timelineEvents.js +171 -0
  153. package/src/utils/validateManifestV2.compiled.js +2 -2
  154. package/src/utils/walkthroughSignals.js +94 -0
@@ -1,16 +1,20 @@
1
1
  import axios__default from '@nextcloud/axios';
2
- import { translate } from '@nextcloud/l10n';
2
+ import { translate, translatePlural } from '@nextcloud/l10n';
3
3
  import { generateUrl } from '@nextcloud/router';
4
4
  import { NcLoadingIcon, NcCheckboxRadioSwitch } from '@nextcloud/vue';
5
+ import FilterIcon from 'vue-material-design-icons/Filter.vue';
6
+ import FilterOutline from 'vue-material-design-icons/FilterOutline.vue';
7
+ import __sfc_main$1 from './CnColumnFilterPopover.vue.js';
5
8
  import { useClickDragGuard } from '../../composables/useClickDragGuard.js';
9
+ import { columnFilterDef, columnFilterState, isColumnFilterActive, columnFilterParams, clearedColumnFilterParams, isColumnSortable } from '../../utils/columnFilters.js';
6
10
  import { resolveHref, openRowTarget, followLinkClick } from '../../utils/linkNavigation.js';
7
11
  import { nextSortState } from '../../utils/multiColumnSort.js';
8
12
  import { preventMiddleClickAutoscroll, isRowMiddleClick, isNewTabHandled, markNewTabHandled, isNewTabClick } from '../../utils/rowAuxClick.js';
9
13
  import { DEFAULT_ROW_INDICATOR_CAP, resolveRowIndicators } from '../../utils/rowIndicators.js';
10
14
  import { columnsFromSchema } from '../../utils/schema.js';
11
15
  import __sfc_main from '../CnCellRenderer/CnCellRenderer.vue.js';
12
- import __sfc_main$1 from '../CnIcon/CnIcon.vue.js';
13
- import __sfc_main$2 from '../CnLockIndicator/CnLockIndicator.vue.js';
16
+ import __sfc_main$2 from '../CnIcon/CnIcon.vue.js';
17
+ import __sfc_main$3 from '../CnLockIndicator/CnLockIndicator.vue.js';
14
18
 
15
19
  /**
16
20
  * CnDataTable — Generic sortable data table for list views.
@@ -68,8 +72,11 @@ var script = {
68
72
  NcLoadingIcon,
69
73
  NcCheckboxRadioSwitch,
70
74
  CnCellRenderer: __sfc_main,
71
- CnIcon: __sfc_main$1,
72
- CnLockIndicator: __sfc_main$2,
75
+ CnColumnFilterPopover: __sfc_main$1,
76
+ CnIcon: __sfc_main$2,
77
+ CnLockIndicator: __sfc_main$3,
78
+ FilterIcon,
79
+ FilterOutline,
73
80
  },
74
81
 
75
82
  inject: {
@@ -438,9 +445,39 @@ var script = {
438
445
  type: Boolean,
439
446
  default: false,
440
447
  },
448
+
449
+ /**
450
+ * Show a filter button in every header whose column can filter (see
451
+ * `columnFilterDef`): enum, boolean, text, number, date and reference
452
+ * columns backed by a schema property. A column opts out with
453
+ * `filterable: false`. Applying a filter emits `column-filter`; the
454
+ * host owns the filter state and passes it back as `activeFilters`.
455
+ *
456
+ * @spec openspec/changes/table-header-sort-and-filter/specs/cn-data-table/spec.md#requirement-every-backed-column-filters-from-its-header
457
+ */
458
+ filterable: {
459
+ type: Boolean,
460
+ default: false,
461
+ },
462
+
463
+ /**
464
+ * The active filter map, `{ paramKey: values[] }`: the same map the
465
+ * facet sidebar writes, so a header filter and a sidebar filter on one
466
+ * field show the same state.
467
+ */
468
+ activeFilters: {
469
+ type: Object,
470
+ default: () => ({}),
471
+ },
472
+
473
+ /** Register slug a reference column's filter searches in when the column names none. */
474
+ filterRegister: {
475
+ type: String,
476
+ default: '',
477
+ },
441
478
  },
442
479
 
443
- emits: ['row-click', 'row-aux-click', 'row-context-menu', 'select', 'select-all', 'sort', 'view-all'],
480
+ emits: ['row-click', 'row-aux-click', 'row-context-menu', 'select', 'select-all', 'sort', 'view-all', 'column-filter'],
444
481
 
445
482
  setup() {
446
483
  // Tell a deliberate row click apart from a text-selection drag.
@@ -449,6 +486,10 @@ var script = {
449
486
 
450
487
  data() {
451
488
  return {
489
+ /** Key of the column whose filter panel is open, or ''. */
490
+ openFilterKey: '',
491
+ /** The open filter button's bounding rect, to place the panel. */
492
+ filterAnchorRect: null,
452
493
  /**
453
494
  * Resolved aggregate-column values, keyed by `String(row[rowKey])`
454
495
  * then by column key. Populated by `loadAggregates()` for columns
@@ -566,8 +607,12 @@ var script = {
566
607
  overrides: this.columnOverrides,
567
608
  })
568
609
  : this.columns;
610
+ // Every column backed by a schema property sorts unless it says
611
+ // `sortable: false`; object columns from a manifest used to need an
612
+ // explicit flag and so could not sort at all.
613
+ const withSort = (c) => (c && typeof c === 'object' ? { ...c, sortable: isColumnSortable(c, this.schema) } : c);
569
614
  if (!(cols || []).some((c) => typeof c === 'string')) {
570
- return cols || []
615
+ return (cols || []).map(withSort)
571
616
  }
572
617
  const schemaCols = this.schema
573
618
  ? columnsFromSchema(this.schema, { overrides: this.columnOverrides })
@@ -575,7 +620,7 @@ var script = {
575
620
  const byKey = new Map(schemaCols.map((c) => [c.key, c]));
576
621
  return (cols || []).map((c) => {
577
622
  if (typeof c !== 'string') {
578
- return c
623
+ return withSort(c)
579
624
  }
580
625
  return byKey.get(c) || { key: c, label: c, sortable: true }
581
626
  })
@@ -616,6 +661,40 @@ var script = {
616
661
  return links
617
662
  },
618
663
 
664
+ /**
665
+ * The column whose filter panel is open, or null.
666
+ *
667
+ * @return {object|null}
668
+ */
669
+ openFilterColumn() {
670
+ if (!this.openFilterKey) {
671
+ return null
672
+ }
673
+ return this.effectiveColumns.find((c) => c && c.key === this.openFilterKey && this.filterDefFor(c)) || null
674
+ },
675
+
676
+ /**
677
+ * One chip per column with an active header filter.
678
+ *
679
+ * @return {Array<{key: string, col: object, text: string, removeLabel: string}>}
680
+ */
681
+ activeColumnFilterChips() {
682
+ if (!this.filterable) {
683
+ return []
684
+ }
685
+ return this.effectiveColumns
686
+ .filter((c) => c && this.isColumnFiltered(c))
687
+ .map((col) => {
688
+ const label = this.translateLabel(col.label);
689
+ const text = translate('nextcloud-vue', '{column}: {value}', { column: label, value: this.columnFilterSummary(col) });
690
+ return { key: col.key, col, text, removeLabel: translate('nextcloud-vue', 'Remove filter {column}', { column: label }) }
691
+ })
692
+ },
693
+
694
+ activeFiltersLabel() {
695
+ return translate('nextcloud-vue', 'Active filters')
696
+ },
697
+
619
698
  effectiveSortKeys() {
620
699
  if (this.sortKeys && this.sortKeys.length > 0) {
621
700
  return this.sortKeys
@@ -1287,6 +1366,135 @@ var script = {
1287
1366
  * @param {string} key Column key.
1288
1367
  * @param {MouseEvent} [event] The originating click event.
1289
1368
  */
1369
+ /**
1370
+ * The filter definition for a column, or null when it does not filter
1371
+ * (header filters off, `filterable: false`, or nothing to filter on).
1372
+ *
1373
+ * @param {object} col The column.
1374
+ * @return {object|null}
1375
+ */
1376
+ filterDefFor(col) {
1377
+ if (!this.filterable || !col) {
1378
+ return null
1379
+ }
1380
+ return columnFilterDef(col, this.schema)
1381
+ },
1382
+
1383
+ columnFilterStateFor(col) {
1384
+ return columnFilterState(this.filterDefFor(col), this.activeFilters)
1385
+ },
1386
+
1387
+ isColumnFiltered(col) {
1388
+ const def = this.filterDefFor(col);
1389
+ return !!def && isColumnFilterActive(def, this.activeFilters)
1390
+ },
1391
+
1392
+ filterButtonLabel(col) {
1393
+ const column = this.translateLabel(col.label);
1394
+ return this.isColumnFiltered(col)
1395
+ ? translate('nextcloud-vue', 'Filter {column}, active', { column })
1396
+ : translate('nextcloud-vue', 'Filter {column}', { column })
1397
+ },
1398
+
1399
+ /**
1400
+ * Short text for an active filter: the picked labels, or the range.
1401
+ *
1402
+ * @param {object} col The column.
1403
+ * @return {string}
1404
+ */
1405
+ columnFilterSummary(col) {
1406
+ const def = this.filterDefFor(col);
1407
+ const state = this.columnFilterStateFor(col);
1408
+ if (!def) {
1409
+ return ''
1410
+ }
1411
+ if (def.kind === 'enum') {
1412
+ const labels = Object.fromEntries((def.options || []).map((o) => [o.value, o.label]));
1413
+ return state.values.map((v) => this.translateLabel(labels[v] || v)).join(', ')
1414
+ }
1415
+ if (def.kind === 'reference') {
1416
+ return translatePlural('nextcloud-vue', '{count} selected', '{count} selected', state.values.length, { count: state.values.length })
1417
+ }
1418
+ if (def.kind === 'number' || def.kind === 'date') {
1419
+ if (state.from && state.to) {
1420
+ return translate('nextcloud-vue', '{from} to {to}', { from: state.from, to: state.to })
1421
+ }
1422
+ return state.from
1423
+ ? translate('nextcloud-vue', 'from {value}', { value: state.from })
1424
+ : translate('nextcloud-vue', 'up to {value}', { value: state.to })
1425
+ }
1426
+ if (def.kind === 'boolean') {
1427
+ return state.value === 'true' ? translate('nextcloud-vue', 'Yes') : translate('nextcloud-vue', 'No')
1428
+ }
1429
+ return state.value
1430
+ },
1431
+
1432
+ /**
1433
+ * Open or close a column's filter panel under its button.
1434
+ *
1435
+ * @param {object} col The column.
1436
+ * @param {Event} event The click.
1437
+ * @return {void}
1438
+ */
1439
+ toggleColumnFilter(col, event) {
1440
+ if (this.openFilterKey === col.key) {
1441
+ this.closeColumnFilter();
1442
+ return
1443
+ }
1444
+ const target = event && event.currentTarget;
1445
+ this.filterAnchorRect = target && typeof target.getBoundingClientRect === 'function'
1446
+ ? target.getBoundingClientRect()
1447
+ : null;
1448
+ this.openFilterKey = col.key;
1449
+ },
1450
+
1451
+ /**
1452
+ * Close the open panel and give focus back to its button.
1453
+ *
1454
+ * @return {void}
1455
+ */
1456
+ closeColumnFilter() {
1457
+ const key = this.openFilterKey;
1458
+ this.openFilterKey = '';
1459
+ if (!key) {
1460
+ return
1461
+ }
1462
+ this.$nextTick(() => {
1463
+ const ref = this.$refs['filterButton-' + key];
1464
+ const button = Array.isArray(ref) ? ref[0] : ref;
1465
+ if (button && typeof button.focus === 'function') {
1466
+ button.focus();
1467
+ }
1468
+ });
1469
+ },
1470
+
1471
+ /**
1472
+ * Apply a panel's state: emit the query parameters it stands for.
1473
+ *
1474
+ * @param {object} col The column.
1475
+ * @param {object} state The panel state.
1476
+ * @return {void}
1477
+ * @spec openspec/changes/table-header-sort-and-filter/specs/cn-data-table/spec.md#requirement-a-header-filter-speaks-the-sidebars-query-language
1478
+ */
1479
+ applyColumnFilter(col, state) {
1480
+ const def = this.filterDefFor(col);
1481
+ if (def) {
1482
+ /**
1483
+ * @event column-filter A header filter was applied or cleared.
1484
+ * @type {{ key: string, params: object }} `params` maps each query parameter the column owns to its values; an empty list clears it.
1485
+ */
1486
+ this.$emit('column-filter', { key: col.key, params: columnFilterParams(def, state) });
1487
+ }
1488
+ this.closeColumnFilter();
1489
+ },
1490
+
1491
+ clearColumnFilter(col) {
1492
+ const def = this.filterDefFor(col);
1493
+ if (def) {
1494
+ this.$emit('column-filter', { key: col.key, params: clearedColumnFilterParams(def) });
1495
+ }
1496
+ },
1497
+
1290
1498
  onHeaderClick(key, event) {
1291
1499
  this.applySort(key, !!(event && event.shiftKey));
1292
1500
  },