@datagouv/components-next 1.0.2-dev.150 → 1.0.2-dev.151

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.
@@ -1,4 +1,4 @@
1
- import { g as Ke } from "./main-CWzZZ7OE.js";
1
+ import { g as Ke } from "./main-BdrYl6mr.js";
2
2
  import We from "vue";
3
3
  function Fe($, K) {
4
4
  for (var V = 0; V < K.length; V++) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@datagouv/components-next",
3
- "version": "1.0.2-dev.150",
3
+ "version": "1.0.2-dev.151",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "engines": {
@@ -63,6 +63,7 @@
63
63
  ExploreResourceView), so they line up with the resource title /
64
64
  download button above. Only the table itself goes edge-to-edge
65
65
  (via -mx-4 below). -->
66
+ <slot name="toolbar-top" />
66
67
  <div>
67
68
  <div class="flex items-center py-3 gap-2">
68
69
  <!-- Mobile: filter & sort button -->
@@ -373,7 +374,8 @@
373
374
  <tr
374
375
  v-for="(row, i) in allRows"
375
376
  :key="row.__id ?? i"
376
- class="border-b border-gray-default even:bg-gray-lowest-2 hover:bg-gray-100"
377
+ class="border-b border-gray-default even:bg-gray-lowest-2 hover:bg-gray-100 cursor-pointer"
378
+ @click="emit('rowClick', row)"
377
379
  >
378
380
  <td
379
381
  v-for="col in displayedColumns"
@@ -402,6 +404,7 @@
402
404
 
403
405
  <!-- Cell popover -->
404
406
  <TabularCellPopover
407
+ v-if="!props.disablePopover"
405
408
  v-model:cell="activeCell"
406
409
  v-model:filters="filters"
407
410
  />
@@ -426,8 +429,9 @@
426
429
  <div
427
430
  v-for="(row, i) in allRows"
428
431
  :key="row.__id ?? i"
429
- class="border border-gray-default rounded-lg p-3 space-y-2"
432
+ class="border border-gray-default rounded-lg p-3 space-y-2 cursor-pointer"
430
433
  :class="i % 2 === 1 ? 'bg-gray-lowest-2' : 'bg-white'"
434
+ @click="emit('rowClick', row)"
431
435
  >
432
436
  <div
433
437
  v-for="col in mobileVisibleFields(i)"
@@ -633,6 +637,21 @@ const props = defineProps<{
633
637
  // the host's padding. Used on the standalone explore page where the table
634
638
  // should span the whole screen while the toolbar stays inside the container.
635
639
  fullBleed?: boolean
640
+ // When set, searches across multiple text columns using the Tabular API's
641
+ // or(...) parameter. Each text/varchar column gets a __contains filter.
642
+ // Note: combined via AND with any existing column-specific `contains` filters,
643
+ // so it acts as an additional narrowing constraint, not a replacement.
644
+ globalSearch?: string
645
+ // When true, clicking a cell does not open the popover. Use when row-click
646
+ // navigation is the primary interaction.
647
+ disablePopover?: boolean
648
+ // Initial filters applied on mount, e.g. { 'Administration': { contains: 'Ministère' } }.
649
+ // Used when navigating from the detail page badge with query params.
650
+ initialFilters?: Record<string, ColumnFilters>
651
+ }>()
652
+
653
+ const emit = defineEmits<{
654
+ rowClick: [row: TabularRow]
636
655
  }>()
637
656
 
638
657
  const { t } = useTranslation()
@@ -658,6 +677,10 @@ const dataUrl = computed(() =>
658
677
  const sort = ref<SortConfig | null>(null)
659
678
  const filters = ref<Record<string, ColumnFilters>>({})
660
679
 
680
+ if (props.initialFilters) {
681
+ filters.value = { ...props.initialFilters }
682
+ }
683
+
661
684
  const PAGE_SIZE = 50
662
685
 
663
686
  const dataQuery = computed(() => {
@@ -688,6 +711,10 @@ const dataQuery = computed(() => {
688
711
  q[`${col}__isnotnull`] = ''
689
712
  }
690
713
  }
714
+ if (props.globalSearch && profileData.value?.profile) {
715
+ const textCols = allColumns.value.filter(c => getColumnType(c) === 'text')
716
+ q.or = '(' + textCols.map(c => c + '__contains.' + encodeURIComponent(props.globalSearch!)).join(',') + ')'
717
+ }
691
718
  return q
692
719
  })
693
720
 
@@ -938,6 +965,7 @@ onUnmounted(() => {
938
965
  const activeCell = ref<CellInfo | null>(null)
939
966
 
940
967
  function onCellClick(col: string, value: unknown, event: MouseEvent) {
968
+ if (props.disablePopover) return
941
969
  const el = (event.target as HTMLElement).closest('[data-cell]') as HTMLElement | null
942
970
  if (!el) return
943
971
  if (activeCell.value && activeCell.value.element === el) {
@@ -961,7 +989,12 @@ const activeFilters = computed<ActiveFilter[]>(() => {
961
989
  parts.push(`= ${filter.in.join(', ')}`)
962
990
  }
963
991
  if (filter.exact != null) {
964
- parts.push(`= ${filter.exact === 'true' ? t('Vrai') : t('Faux')}`)
992
+ if (getColumnType(col) === 'boolean') {
993
+ parts.push(`= ${filter.exact === 'true' ? t('Vrai') : t('Faux')}`)
994
+ }
995
+ else {
996
+ parts.push(`= ${filter.exact}`)
997
+ }
965
998
  }
966
999
  if (filter.contains) {
967
1000
  parts.push(`${t('contient')} "${filter.contains}"`)
@@ -67,8 +67,8 @@ export type ColumnType = 'number' | 'categorical' | 'text' | 'date' | 'boolean'
67
67
  export type ColumnFilters = {
68
68
  in?: string[]
69
69
  exact?: string
70
- min?: number
71
- max?: number
70
+ min?: number | string
71
+ max?: number | string
72
72
  contains?: string
73
73
  null?: 'only' | 'exclude'
74
74
  }