@datagouv/components-next 0.0.19 → 0.0.20

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-CUy8gy19.js";
1
+ import { g as Ke } from "./main-CgjLq1oz.js";
2
2
  import We from "vue";
3
3
  function Fe(I, 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": "0.0.19",
3
+ "version": "0.0.20",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "main": "./src/main.ts",
@@ -18,7 +18,7 @@
18
18
  "lint": "eslint . --fix",
19
19
  "format": "prettier --write src/",
20
20
  "css": "tailwindcss -i ./assets/main.css -o ./dist/components.css --minify --optimize",
21
- "preversion": "npm run build-only && npm run css",
21
+ "preversion": "npm run build && npm run css",
22
22
  "publish-stable": "npm publish --access public"
23
23
  },
24
24
  "dependencies": {
@@ -28,7 +28,7 @@
28
28
  "chart.js": "^4.4.8",
29
29
  "dompurify": "^3.2.5",
30
30
  "geopf-extensions-openlayers": "^1.0.0-beta.5",
31
- "maplibre-gl": "^5.5.0",
31
+ "maplibre-gl": "^5.6.2",
32
32
  "ofetch": "^1.4.1",
33
33
  "ol": "^10.6.1",
34
34
  "pdf-vue3": "^1.0.12",
@@ -8,7 +8,7 @@
8
8
  </component>
9
9
  <a
10
10
  v-else-if="isExternal"
11
- :href="to"
11
+ :href="(to as string)"
12
12
  >
13
13
  <slot />
14
14
  </a>
@@ -15,7 +15,7 @@
15
15
  </template>
16
16
 
17
17
  <script setup lang = "ts">
18
- import { onMounted, ref } from 'vue'
18
+ import { onMounted, ref, useTemplateRef } from 'vue'
19
19
  import { useI18n } from 'vue-i18n'
20
20
  import { RiErrorWarningLine } from '@remixicon/vue'
21
21
 
@@ -32,6 +32,7 @@ import {
32
32
  GeoportalZoom,
33
33
  LayerImport,
34
34
  LayerSwitcher,
35
+ // @ts-expect-error no types provided
35
36
  } from 'geopf-extensions-openlayers'
36
37
 
37
38
  import SimpleBanner from '../SimpleBanner.vue'
@@ -42,7 +43,7 @@ const props = defineProps<{ resource: Resource }>()
42
43
  const { t } = useI18n()
43
44
 
44
45
  let map = null
45
- const mapRef = ref(0)
46
+ const mapRef = useTemplateRef('mapRef')
46
47
  const hasError = ref(false)
47
48
 
48
49
  async function displayMap() {
@@ -53,6 +54,7 @@ async function displayMap() {
53
54
 
54
55
  CRS.load()
55
56
  map = new Map({
57
+ // @ts-expect-error null is not happening during onMount
56
58
  target: mapRef.value,
57
59
  layers: [
58
60
  new TileLayer({
@@ -117,6 +119,7 @@ async function displayMap() {
117
119
  hasError.value = true
118
120
  }
119
121
  else {
122
+ // @ts-expect-error no typing from library
120
123
  const layerInfo = layerImport._getCapResponseWMSLayers.filter(layer => layer.Name == props.resource.title)[0]
121
124
  layerImport._addGetCapWMSLayer(layerInfo)
122
125
  }
@@ -52,7 +52,7 @@
52
52
  </template>
53
53
 
54
54
  <script setup lang="ts">
55
- import { computed, onMounted, ref } from 'vue'
55
+ import { computed, onMounted, ref, useTemplateRef } from 'vue'
56
56
  import { useI18n } from 'vue-i18n'
57
57
  import { RiErrorWarningLine, RiExternalLinkFill } from '@remixicon/vue'
58
58
  import { Protocol, PMTiles } from 'pmtiles'
@@ -60,6 +60,7 @@ import maplibregl from 'maplibre-gl'
60
60
  import DOMPurify from 'dompurify'
61
61
  import { useComponentsConfig } from '../../config'
62
62
  import { useFormatDate } from '../../functions/dates'
63
+ import { throwOnNever } from '../../functions/never'
63
64
  import type { Resource } from '../../types/resources'
64
65
  import BrandedButton from '../BrandedButton.vue'
65
66
  import styleVector from '../../../assets/json/vector.json'
@@ -74,12 +75,12 @@ const { formatDate } = useFormatDate()
74
75
  const config = useComponentsConfig()
75
76
 
76
77
  const hasError = ref(false)
77
- const pmtilesUrl = computed(() => props.resource.extras['analysis:parsing:pmtiles_url'])
78
+ const pmtilesUrl = computed(() => props.resource.extras['analysis:parsing:pmtiles_url'] as string)
78
79
  const pmtilesViewerUrl = computed(() => {
79
80
  return config.pmtilesViewerBaseUrl ? `${config.pmtilesViewerBaseUrl}${encodeURIComponent(pmtilesUrl.value)}` : null
80
81
  })
81
82
 
82
- const lastUpdate = computed(() => formatDate(props.resource.extras['analysis:parsing:finished_at']))
83
+ const lastUpdate = computed(() => formatDate(props.resource.extras['analysis:parsing:finished_at'] as string | undefined))
83
84
 
84
85
  const container = useTemplateRef('containerRef')
85
86
 
@@ -94,7 +95,9 @@ async function displayMap() {
94
95
 
95
96
  p.getHeader().then((h) => {
96
97
  const map = new maplibregl.Map({
98
+ // @ts-expect-error only null before mount
97
99
  container: container.value, // container id
100
+ // @ts-expect-error TODO: type JSON
98
101
  style: styleVector,
99
102
  zoom: h.maxZoom - 2,
100
103
  center: [h.centerLon, h.centerLat],
@@ -106,6 +109,7 @@ async function displayMap() {
106
109
  closeOnClick: false,
107
110
  })
108
111
 
112
+ // @ts-expect-error TODO: add type from library
109
113
  function showMapPopup(e) {
110
114
  if (!e.features || !e.features[0])
111
115
  popup.remove()
@@ -125,7 +129,7 @@ async function displayMap() {
125
129
  url: `pmtiles://${pmtilesUrl.value}`,
126
130
  attribution: '© <a href="https://openstreetmap.org">OpenStreetMap</a>',
127
131
  })
128
-
132
+ // @ts-expect-error not typed from library
129
133
  metadata.tilestats.layers.forEach((layer) => {
130
134
  const typeLayer = computed(() => {
131
135
  switch (layer.geometry) {
@@ -136,6 +140,7 @@ async function displayMap() {
136
140
  case 'LineString':
137
141
  return `line`
138
142
  default:
143
+ // @ts-expect-error no other geometries ?
139
144
  throwOnNever(layer.geometry, 'Unsupported geometry')
140
145
  return ''
141
146
  }
@@ -144,6 +149,7 @@ async function displayMap() {
144
149
  'id': layer.layer,
145
150
  'source': 'pmtiles_source',
146
151
  'source-layer': layer.layer,
152
+ // @ts-expect-error `''` (empty string) shouldn't happen (see `throwOnNever`)
147
153
  'type': typeLayer.value,
148
154
  'paint': {
149
155
  [`${typeLayer.value}-color`]: 'steelblue',
@@ -151,6 +157,7 @@ async function displayMap() {
151
157
  },
152
158
  })
153
159
  map.on('mousemove', layer.layer, showMapPopup)
160
+ // @ts-expect-error doesn't exist ?
154
161
  map.on('touchmove', layer.layer, showMapPopup)
155
162
  map.on('click', layer.layer, showMapPopup)
156
163
  map.on('mouseleave', layer.layer, showMapPopup)
@@ -199,7 +199,7 @@ function sortByField(col: string) {
199
199
  getTableInfos(currentPage.value, sortConfig.value)
200
200
  };
201
201
 
202
- const lastUpdate = computed(() => formatDate(props.resource.extras['analysis:parsing:finished_at']))
202
+ const lastUpdate = computed(() => formatDate(props.resource.extras['analysis:parsing:finished_at'] as string | undefined))
203
203
 
204
204
  onMounted(() => {
205
205
  getTableInfos(currentPage.value)
@@ -492,7 +492,7 @@ const communityResource = computed<CommunityResource | null>(() => {
492
492
  const owner = computed(() => communityResource.value ? getOwnerName(communityResource.value) : null)
493
493
 
494
494
  const lastUpdate = props.resource.last_modified
495
- const conversionsLastUpdate = computed(() => formatRelativeIfRecentDate(props.resource.extras['analysis:parsing:finished_at']))
495
+ const conversionsLastUpdate = computed(() => formatRelativeIfRecentDate(props.resource.extras['analysis:parsing:finished_at'] as string | undefined))
496
496
  const availabilityChecked = props.resource.extras && 'check:available' in props.resource.extras
497
497
 
498
498
  const unavailable = availabilityChecked && props.resource.extras['check:available'] === false
@@ -121,7 +121,7 @@ const title = computed(() => {
121
121
  return props.resource.schema.name || props.resource.schema.url
122
122
  })
123
123
 
124
- const validataErrors = computed<Array<ValidataError>>(() => props.resource.extras['validation-report:errors'] || [])
124
+ const validataErrors = computed<Array<ValidataError>>(() => props.resource.extras['validation-report:errors'] as Array<ValidataError> || [])
125
125
  const validataWarnings = computed(() => validataErrors.value.filter(error => [''].includes(error.code)))
126
126
  const validataBodyErrors = computed(() => validataErrors.value.filter(error => ['#body', '#cell', '#content', '#row', '#table'].some(tag => error.tags.includes(tag))))
127
127
  const validataStructureErrors = computed(() => validataErrors.value.filter(error => ['#head', '#structure', '#header'].some(tag => error.tags.includes(tag))))
@@ -4,6 +4,7 @@
4
4
 
5
5
  <script setup lang="ts">
6
6
  import { onMounted } from 'vue'
7
+ // @ts-expect-error no types for `swagger-ui-dist`
7
8
  import * as SwaggerUiDist from 'swagger-ui-dist'
8
9
  import 'swagger-ui-dist/swagger-ui.css'
9
10
  import '../../../assets/swagger-themes/newspaper.css'
@@ -21,7 +21,8 @@
21
21
  </template>
22
22
 
23
23
  <script setup lang="ts">
24
- import { Chart, type ChartOptions } from 'chart.js/auto'
24
+ import type { ChartOptions, ScriptableLineSegmentContext } from 'chart.js'
25
+ import Chart from 'chart.js/auto'
25
26
  import { computed, onMounted, ref, useTemplateRef, watchEffect } from 'vue'
26
27
 
27
28
  const LIGHT_COLOR = '#B6CFFB'
@@ -43,7 +44,7 @@ const props = withDefaults(defineProps<{
43
44
  width: 120,
44
45
  })
45
46
 
46
- const last = (ctx, value) => {
47
+ const last = (ctx: ScriptableLineSegmentContext, value: unknown) => {
47
48
  return ctx.p1DataIndex === months.value.length - 1 ? value : null
48
49
  }
49
50
 
@@ -63,27 +64,45 @@ const data = computed(() => {
63
64
  const months = computed(() => Object.keys(data.value))
64
65
  const values = computed(() => Object.values(data.value))
65
66
 
66
- const additionalDatasetConfig = computed(() => {
67
- if (props.type === 'bar') {
68
- return {
69
- barPercentage: 1,
70
- categoryPercentage: 0.9,
71
- // Change the color of the last bar only
72
- backgroundColor: months.value.map((_value, index) => index === months.value.length - 1 ? (props.lastWithLowEmphasis ? LIGHT_COLOR_WITH_OPACITY : COLOR) : LIGHT_COLOR),
73
- }
67
+ const additionalDatasetConfig = computed<{
68
+ type: 'bar'
69
+ barPercentage: number
70
+ categoryPercentage: number
71
+ backgroundColor: Array<string>
72
+ } | {
73
+ type: 'line'
74
+ segment?: {
75
+ borderColor: (ctx: ScriptableLineSegmentContext) => string
76
+ borderDash: (ctx: ScriptableLineSegmentContext) => Array<number>
74
77
  }
75
-
76
- if (props.type === 'line' && props.lastWithLowEmphasis) {
77
- return {
78
- segment: {
79
- borderColor: ctx => last(ctx, COLOR_WITH_OPACITY) || COLOR,
80
- borderDash: ctx => last(ctx, [3, 3]) || [6, 0],
81
- },
82
- }
83
- }
84
-
85
- return {}
86
- })
78
+ } | object>(() => {
79
+ if (props.type === 'bar') {
80
+ return {
81
+ type: 'bar',
82
+ barPercentage: 1,
83
+ categoryPercentage: 0.9,
84
+ // Change the color of the last bar only
85
+ backgroundColor: months.value.map((_value, index) => index === months.value.length - 1 ? (props.lastWithLowEmphasis ? LIGHT_COLOR_WITH_OPACITY : COLOR) : LIGHT_COLOR),
86
+ }
87
+ }
88
+
89
+ if (props.type === 'line') {
90
+ if (props.lastWithLowEmphasis) {
91
+ return {
92
+ type: 'line',
93
+ segment: {
94
+ borderColor: (ctx: ScriptableLineSegmentContext) => last(ctx, COLOR_WITH_OPACITY) || COLOR,
95
+ borderDash: (ctx: ScriptableLineSegmentContext) => last(ctx, [3, 3]) || [6, 0],
96
+ },
97
+ }
98
+ }
99
+ return {
100
+ type: 'line',
101
+ }
102
+ }
103
+
104
+ return {}
105
+ })
87
106
 
88
107
  const getMonthYear = (dateAsString: string): string => {
89
108
  const date = new Date(dateAsString)
@@ -95,6 +114,7 @@ const startDate = computed(() => months.value.length ? getMonthYear(months.value
95
114
  const endDate = computed(() => months.value.length ? getMonthYear(months.value[months.value.length - 1]) : null)
96
115
 
97
116
  const OPTIONS = {
117
+ // @ts-expect-error animation can be `true` but the typing is not expecting it
98
118
  animation: true,
99
119
  devicePixelRatio: 1,
100
120
  responsive: false,
@@ -155,8 +175,9 @@ watchEffect(() => {
155
175
  chart.value = new Chart(context.value, {
156
176
  data: {
157
177
  labels: months.value,
158
- datasets: [{ data: values.value, type: props.type, ...additionalDatasetConfig.value }],
178
+ datasets: [{ data: values.value, ...additionalDatasetConfig.value }],
159
179
  },
180
+ // @ts-expect-error animation type should allow `true`
160
181
  options: OPTIONS,
161
182
  })
162
183
  })
@@ -3,15 +3,15 @@ import type { ComputedRef, Ref, WatchSource } from 'vue'
3
3
  export type UseFetchOptions<DataT> = {
4
4
  key?: string
5
5
  method?: string
6
- query?: SearchParams
7
- params?: SearchParams
8
- body?: RequestInit['body'] | Record<string, any>
6
+ query?: Record<string, unknown>
7
+ params?: Record<string, unknown>
8
+ body?: RequestInit['body'] | Record<string, unknown>
9
9
  headers?: Record<string, string> | [key: string, value: string][] | Headers
10
10
  baseURL?: string
11
11
  server?: boolean
12
12
  lazy?: boolean
13
13
  immediate?: boolean
14
- getCachedData?: (key: string, nuxtApp: any) => DataT
14
+ getCachedData?: (key: string, nuxtApp: unknown) => DataT
15
15
  deep?: boolean
16
16
  dedupe?: 'cancel' | 'defer'
17
17
  default?: () => DataT
@@ -5,7 +5,7 @@ const SECONDS_IN_A_DAY = 3600 * 24
5
5
  export function useFormatDate() {
6
6
  const { t, locale } = useI18n()
7
7
 
8
- const formatDate = (date: Date | string | null, options: Intl.DateTimeFormatOptions = {}) => {
8
+ const formatDate = (date: Date | string | null | undefined, options: Intl.DateTimeFormatOptions = {}) => {
9
9
  if (!date) {
10
10
  return ''
11
11
  }
@@ -20,7 +20,7 @@ export function useFormatDate() {
20
20
  * Format date as relative from now.
21
21
  * It displays "today" or Intl.RelativeTimeFormat content, based on date.
22
22
  */
23
- const formatFromNow = (date: Date | string | null) => {
23
+ const formatFromNow = (date: Date | string | null | undefined) => {
24
24
  if (!date) {
25
25
  return ''
26
26
  }
@@ -65,7 +65,7 @@ export function useFormatDate() {
65
65
  * Format date relative form now if date is less than a month ago.
66
66
  * Otherwise, show a formatted date.
67
67
  */
68
- const formatRelativeIfRecentDate = (date: Date | string | null, options: Intl.DateTimeFormatOptions = {}) => {
68
+ const formatRelativeIfRecentDate = (date: Date | string | null | undefined, options: Intl.DateTimeFormatOptions = {}) => {
69
69
  if (!date) {
70
70
  return ''
71
71
  }
@@ -1,3 +1,4 @@
1
1
  export function trackEvent(values: Array<unknown>): void {
2
+ // @ts-expect-error Matomo is not typed
2
3
  globalThis._paq?.push(['trackEvent', ...values])
3
4
  }
@@ -0,0 +1,3 @@
1
+ export function throwOnNever(_: never, message: string): never {
2
+ throw new Error(message)
3
+ }
package/src/main.ts CHANGED
@@ -56,6 +56,7 @@ export * from './functions/datasets'
56
56
  export * from './functions/owned'
57
57
  export * from './functions/helpers'
58
58
  export * from './functions/matomo'
59
+ export * from './functions/never'
59
60
  export * from './functions/schemas'
60
61
  export * from './functions/markdown'
61
62