@datagouv/components-next 1.0.2-dev.13 → 1.0.2-dev.131

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 (111) hide show
  1. package/README.md +7 -6
  2. package/assets/main.css +4 -0
  3. package/dist/{Control-DuZJdKV_.js → Control-b-43UT2B.js} +10 -10
  4. package/dist/{Datafair.client-8haHXl47.js → Datafair.client-CFl7MKdB.js} +4 -4
  5. package/dist/{Event--kp8kMdJ.js → Event-py_AAwJY.js} +35 -35
  6. package/dist/{Image-34hvypZI.js → Image-BHQYZWzH.js} +23 -23
  7. package/dist/JsonPreview.client-CowJU7XP.js +40 -0
  8. package/dist/{Map-BjUnLyj8.js → Map-CtP7leHl.js} +1742 -1602
  9. package/dist/{MapContainer.client-l6HuXTHR.js → MapContainer.client-CgdBWq2S.js} +37 -38
  10. package/dist/{OSM-s40W6sQ2.js → OSM-gdDSIsDA.js} +15 -23
  11. package/dist/{PdfPreview.client-4OueK-2Z.js → PdfPreview.client-Dm4l4fyb.js} +823 -855
  12. package/dist/Pmtiles.client-DsjzH41p.js +26123 -0
  13. package/dist/PreviewWrapper.vue_vue_type_script_setup_true_lang-BgFVrfFi.js +61 -0
  14. package/dist/{ScaleLine-KW-nXqp3.js → ScaleLine-hG-FhNqy.js} +2 -2
  15. package/dist/{Tile-DbNFNPfU.js → Tile-D6rFonpT.js} +164 -167
  16. package/dist/{TileImage-BsXBxMtq.js → TileImage-cfrEgz5y.js} +131 -119
  17. package/dist/{View-BR92hTWP.js → View-vp7vDb9q.js} +482 -421
  18. package/dist/XmlPreview.client-DBceFnA1.js +34 -0
  19. package/dist/{common-PJfpC179.js → common-C8efyyuc.js} +57 -57
  20. package/dist/components-next.css +1 -52
  21. package/dist/components-next.js +172 -143
  22. package/dist/components.css +2 -2
  23. package/dist/{index-CVTIoZQ0.js → index-DWmJJEjk.js} +21855 -15827
  24. package/dist/{leaflet-src-7m1mB8LI.js → leaflet-src-CGmV0V-K.js} +162 -164
  25. package/dist/main-CQREzlRN.js +72634 -0
  26. package/dist/{proj-DsetBcW7.js → proj-CsjVeojN.js} +663 -627
  27. package/dist/{text-clamp.esm-B5kW_XMt.js → text-clamp.esm-DVseBqZZ.js} +4 -4
  28. package/dist/{tilecoord-Db24Px13.js → tilecoord-CPcQJnrF.js} +258 -249
  29. package/dist/{vue3-json-viewer-BXwup7nO.js → vue3-json-viewer-CJLQFzXZ.js} +10 -16
  30. package/dist/{vue3-xml-viewer.common-CWer_T5-.js → vue3-xml-viewer.common-d08lX8ER.js} +1 -1
  31. package/package.json +50 -36
  32. package/src/chart.ts +5 -0
  33. package/src/components/ActivityList/ActivityList.vue +3 -2
  34. package/src/components/Chart/ChartViewer.vue +227 -0
  35. package/src/components/Chart/ChartViewerWrapper.vue +174 -0
  36. package/src/components/DataserviceCard.vue +3 -0
  37. package/src/components/DatasetCard.vue +9 -4
  38. package/src/components/Form/Listbox.vue +101 -0
  39. package/src/components/Form/SearchableSelect.vue +2 -1
  40. package/src/components/InfiniteLoader.vue +53 -0
  41. package/src/components/ObjectCardHeader.vue +11 -4
  42. package/src/components/OpenApiViewer/ContentTypeSelect.vue +48 -0
  43. package/src/components/OpenApiViewer/EndpointRequest.vue +164 -0
  44. package/src/components/OpenApiViewer/EndpointResponses.vue +149 -0
  45. package/src/components/OpenApiViewer/OpenApiViewer.vue +308 -0
  46. package/src/components/OpenApiViewer/SchemaPanel.vue +53 -0
  47. package/src/components/OpenApiViewer/SchemaTree.vue +77 -0
  48. package/src/components/OpenApiViewer/openapi.ts +150 -0
  49. package/src/components/OrganizationNameWithCertificate.vue +3 -2
  50. package/src/components/Pagination.vue +8 -5
  51. package/src/components/RadioInput.vue +7 -2
  52. package/src/components/ReadMore.vue +1 -1
  53. package/src/components/ResourceAccordion/DataStructure.vue +11 -33
  54. package/src/components/ResourceAccordion/Downloads.vue +160 -0
  55. package/src/components/ResourceAccordion/JsonPreview.client.vue +23 -104
  56. package/src/components/ResourceAccordion/MapContainer.client.vue +1 -3
  57. package/src/components/ResourceAccordion/Metadata.vue +1 -2
  58. package/src/components/ResourceAccordion/PdfPreview.client.vue +24 -87
  59. package/src/components/ResourceAccordion/Pmtiles.client.vue +3 -1
  60. package/src/components/ResourceAccordion/Preview.vue +11 -11
  61. package/src/components/ResourceAccordion/PreviewWrapper.vue +82 -0
  62. package/src/components/ResourceAccordion/ResourceAccordion.vue +12 -111
  63. package/src/components/ResourceAccordion/XmlPreview.client.vue +16 -98
  64. package/src/components/ResourceExplorer/ResourceExplorer.vue +22 -19
  65. package/src/components/ResourceExplorer/ResourceExplorerSidebar.vue +2 -2
  66. package/src/components/ResourceExplorer/ResourceExplorerViewer.vue +50 -148
  67. package/src/components/ResourceExplorer/ResourceSelector.vue +113 -0
  68. package/src/components/ReuseCard.vue +12 -4
  69. package/src/components/Search/GlobalSearch.vue +217 -115
  70. package/src/components/Search/SearchInput.vue +5 -4
  71. package/src/components/TabularExplorer/TabularCell.vue +51 -0
  72. package/src/components/TabularExplorer/TabularCellPopover.vue +170 -0
  73. package/src/components/TabularExplorer/TabularExplorer.vue +1106 -0
  74. package/src/components/TabularExplorer/TabularFilterContent.vue +353 -0
  75. package/src/components/TabularExplorer/TabularFilterPopover.vue +106 -0
  76. package/src/components/TabularExplorer/types.ts +86 -0
  77. package/src/composables/useHasTabularData.ts +13 -0
  78. package/src/composables/useMetrics.ts +1 -1
  79. package/src/composables/useResourceCapabilities.ts +1 -1
  80. package/src/composables/useSearchFilter.ts +120 -0
  81. package/src/composables/useStableQueryParams.ts +38 -6
  82. package/src/composables/useTabularProfile.ts +70 -0
  83. package/src/config.ts +20 -3
  84. package/src/functions/activities.ts +3 -3
  85. package/src/functions/api.ts +20 -42
  86. package/src/functions/api.types.ts +1 -0
  87. package/src/functions/charts.ts +79 -0
  88. package/src/functions/datasets.ts +0 -17
  89. package/src/functions/metrics.ts +6 -4
  90. package/src/functions/resources.ts +61 -1
  91. package/src/functions/tabular.ts +171 -0
  92. package/src/functions/tabularApi.ts +96 -11
  93. package/src/main.ts +95 -9
  94. package/src/types/dataservices.ts +2 -0
  95. package/src/types/pages.ts +0 -5
  96. package/src/types/posts.ts +2 -2
  97. package/src/types/reports.ts +5 -1
  98. package/src/types/resources.ts +0 -1
  99. package/src/types/search.ts +63 -1
  100. package/src/types/site.ts +5 -3
  101. package/src/types/ui.ts +2 -0
  102. package/src/types/users.ts +2 -1
  103. package/src/types/visualizations.ts +93 -0
  104. package/assets/swagger-themes/newspaper.css +0 -1670
  105. package/dist/JsonPreview.client-D53pj9Cw.js +0 -72
  106. package/dist/Pmtiles.client-4j3VTYkz.js +0 -25185
  107. package/dist/Swagger.client-DPBmsH9q.js +0 -4
  108. package/dist/XmlPreview.client-XElkoA4F.js +0 -64
  109. package/dist/main-BbT-LUXy.js +0 -105854
  110. package/src/components/ResourceAccordion/Swagger.client.vue +0 -48
  111. package/src/functions/pagination.ts +0 -9
@@ -0,0 +1,170 @@
1
+ <template>
2
+ <ClientOnly>
3
+ <Teleport to="#tooltips">
4
+ <div
5
+ v-if="cell"
6
+ ref="panel"
7
+ class="bg-white border border-black/10 rounded-lg shadow-md w-80 absolute z-[800]"
8
+ :style="floatingStyles"
9
+ >
10
+ <!-- Value -->
11
+ <div class="px-3 pt-3 pb-2 border-b border-gray-default">
12
+ <p class="text-[10px] text-gray-plain mb-0">
13
+ {{ t('Valeur brute') }}
14
+ </p>
15
+ <p class="text-xs text-gray-title mb-0">
16
+ {{ displayValue }}
17
+ </p>
18
+ </div>
19
+
20
+ <!-- Type -->
21
+ <div class="flex items-center gap-2 px-3 py-2 border-b border-gray-default">
22
+ <span class="text-[10px] text-gray-plain">{{ t('Type') }}</span>
23
+ <span class="inline-flex items-center gap-1 bg-gray-some rounded px-1.5 py-0.5 text-xs text-gray-plain">
24
+ <component
25
+ :is="typeIcon"
26
+ class="size-3"
27
+ aria-hidden="true"
28
+ />
29
+ {{ typeLabel }}
30
+ </span>
31
+ <span class="text-[10px] text-gray-plain shrink-0">·</span>
32
+ <span class="text-[10px] text-gray-plain truncate min-w-0">{{ cell.column }}</span>
33
+ </div>
34
+
35
+ <!-- Actions -->
36
+ <div class="p-1">
37
+ <button
38
+ class="flex items-center gap-2.5 w-full px-3 py-2 rounded-md text-xs font-medium hover:bg-gray-50"
39
+ @click="filterByValue"
40
+ >
41
+ <RiFilterLine
42
+ class="size-4"
43
+ aria-hidden="true"
44
+ />
45
+ {{ t('Filtrer par cette valeur') }}
46
+ </button>
47
+ <button
48
+ class="flex items-center gap-2.5 w-full px-3 py-2 rounded-md text-xs font-medium hover:bg-gray-50"
49
+ @click="copyValue"
50
+ >
51
+ <RiCheckLine
52
+ v-if="copied"
53
+ class="size-4 text-green-500"
54
+ aria-hidden="true"
55
+ />
56
+ <RiFileCopyLine
57
+ v-else
58
+ class="size-4 text-gray-plain"
59
+ aria-hidden="true"
60
+ />
61
+ {{ copied ? t('Copié !') : t('Copier la valeur') }}
62
+ </button>
63
+ </div>
64
+ </div>
65
+ </Teleport>
66
+ </ClientOnly>
67
+ </template>
68
+
69
+ <script setup lang="ts">
70
+ import { computed, ref, useTemplateRef, watch } from 'vue'
71
+ import { flip, shift, autoUpdate, useFloating } from '@floating-ui/vue'
72
+ import { onClickOutside } from '@vueuse/core'
73
+ import {
74
+ RiFilterLine,
75
+ RiFileCopyLine,
76
+ RiCheckLine,
77
+ } from '@remixicon/vue'
78
+ import { toast } from 'vue-sonner'
79
+ import { useTranslation } from '../../composables/useTranslation'
80
+ import { buildTypeConfig } from '../../functions/tabular'
81
+ import ClientOnly from '../ClientOnly.vue'
82
+ import type { ColumnType, ColumnFilters } from './types'
83
+
84
+ export interface CellInfo {
85
+ column: string
86
+ columnType: ColumnType
87
+ value: unknown
88
+ element: HTMLElement
89
+ }
90
+
91
+ const cell = defineModel<CellInfo | null>('cell', { default: null })
92
+ const filters = defineModel<Record<string, ColumnFilters>>('filters', { default: () => ({}) })
93
+
94
+ const { t } = useTranslation()
95
+
96
+ const panelRef = useTemplateRef<HTMLElement>('panel')
97
+ const anchorRef = ref<HTMLElement | null>(null)
98
+
99
+ watch(cell, (c) => {
100
+ anchorRef.value = c?.element ?? null
101
+ })
102
+
103
+ const { floatingStyles } = useFloating(anchorRef, panelRef, {
104
+ placement: 'bottom-start',
105
+ middleware: [flip(), shift()],
106
+ whileElementsMounted: autoUpdate,
107
+ })
108
+
109
+ const displayValue = computed(() => {
110
+ if (!cell.value) return ''
111
+ const v = cell.value.value
112
+ if (v == null || v === '') return '–'
113
+ if (typeof v === 'object') return JSON.stringify(v)
114
+ return String(v)
115
+ })
116
+
117
+ const typeConfig = buildTypeConfig(t)
118
+
119
+ const typeIcon = computed(() => cell.value ? typeConfig[cell.value.columnType].icon : typeConfig.text.icon)
120
+ const typeLabel = computed(() => cell.value ? typeConfig[cell.value.columnType].label : '')
121
+
122
+ function close() {
123
+ cell.value = null
124
+ }
125
+
126
+ function filterByValue() {
127
+ if (!cell.value) return
128
+ const val = String(cell.value.value ?? '')
129
+ const col = cell.value.column
130
+ const existing = filters.value[col] ?? {}
131
+ if (cell.value.columnType === 'categorical' || cell.value.columnType === 'text' || cell.value.columnType === 'date') {
132
+ const current = existing.in ?? []
133
+ if (!current.includes(val)) {
134
+ filters.value = { ...filters.value, [col]: { ...existing, in: [...current, val] } }
135
+ }
136
+ }
137
+ else if (cell.value.columnType === 'number') {
138
+ const num = Number(cell.value.value)
139
+ if (Number.isFinite(num)) {
140
+ filters.value = { ...filters.value, [col]: { ...existing, min: num, max: num } }
141
+ }
142
+ }
143
+ else if (cell.value.columnType === 'boolean') {
144
+ filters.value = { ...filters.value, [col]: { ...existing, exact: val } }
145
+ }
146
+ close()
147
+ }
148
+
149
+ const copied = ref(false)
150
+
151
+ async function copyValue() {
152
+ try {
153
+ await navigator.clipboard.writeText(displayValue.value)
154
+ copied.value = true
155
+ setTimeout(() => {
156
+ copied.value = false
157
+ }, 1500)
158
+ }
159
+ catch {
160
+ toast.error(t('Impossible de copier dans le presse-papier'))
161
+ }
162
+ }
163
+
164
+ onClickOutside(panelRef, (e) => {
165
+ if (!cell.value) return
166
+ const clickedCell = (e.target as HTMLElement).closest('[data-cell]')
167
+ if (clickedCell && clickedCell === cell.value.element) return
168
+ close()
169
+ })
170
+ </script>