@datagouv/components-next 1.2.0 → 1.3.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 (47) hide show
  1. package/README.md +7 -6
  2. package/dist/{Control-ZFh5ta_U.js → Control-b-43UT2B.js} +10 -10
  3. package/dist/{Datafair.client-rf4T1IkA.js → Datafair.client-BrjISlaZ.js} +4 -4
  4. package/dist/{Event-DSQcW7OF.js → Event-py_AAwJY.js} +18 -18
  5. package/dist/{Image-BijNEG0p.js → Image-BHQYZWzH.js} +23 -23
  6. package/dist/{JsonPreview.client-dzar6iuh.js → JsonPreview.client-DivFAnbN.js} +5 -5
  7. package/dist/{Map-BUtPf5GN.js → Map-CtP7leHl.js} +1313 -1173
  8. package/dist/{MapContainer.client-D-MoRNhG.js → MapContainer.client-Cq8tNLZZ.js} +17 -17
  9. package/dist/{OSM-D4MTdBtk.js → OSM-gdDSIsDA.js} +15 -23
  10. package/dist/{PdfPreview.client-DoDYLmJD.js → PdfPreview.client-BNBgLsK2.js} +6 -10
  11. package/dist/Pmtiles.client-CQi5Rw8W.js +26123 -0
  12. package/dist/{PreviewWrapper.vue_vue_type_script_setup_true_lang-BRNYswg3.js → PreviewWrapper.vue_vue_type_script_setup_true_lang-C3dDzrIr.js} +2 -2
  13. package/dist/{ScaleLine-hJQIqcZm.js → ScaleLine-hG-FhNqy.js} +2 -2
  14. package/dist/{Tile-Dcl7oIVu.js → Tile-D6rFonpT.js} +163 -166
  15. package/dist/{TileImage-BJeHipMX.js → TileImage-cfrEgz5y.js} +131 -119
  16. package/dist/{View-xp_P_OHw.js → View-vp7vDb9q.js} +169 -119
  17. package/dist/{XmlPreview.client-cOhwff6P.js → XmlPreview.client-XCsNvnsZ.js} +5 -5
  18. package/dist/{common-BjQlan3k.js → common-C8efyyuc.js} +49 -49
  19. package/dist/components-next.css +1 -52
  20. package/dist/components-next.js +157 -153
  21. package/dist/components.css +2 -2
  22. package/dist/{index-NofRBuyf.js → index-CXUamc8Z.js} +6382 -6057
  23. package/dist/{leaflet-src-7m1mB8LI.js → leaflet-src-BRKv9Ksv.js} +162 -164
  24. package/dist/{main-Iz1ZCL6k.js → main-DKu5SOAl.js} +20671 -21654
  25. package/dist/{proj-CsNo9yH1.js → proj-CsjVeojN.js} +322 -306
  26. package/dist/{text-clamp.esm-B5kW_XMt.js → text-clamp.esm-DVseBqZZ.js} +4 -4
  27. package/dist/{tilecoord-A0fLnBZr.js → tilecoord-CPcQJnrF.js} +270 -261
  28. package/dist/{vue3-json-viewer-BXwup7nO.js → vue3-json-viewer-CJLQFzXZ.js} +10 -16
  29. package/dist/{vue3-xml-viewer.common-tVI9uXUz.js → vue3-xml-viewer.common-BIaEIFYG.js} +1 -1
  30. package/package.json +34 -34
  31. package/src/components/ResourceAccordion/Pmtiles.client.vue +3 -1
  32. package/src/components/ResourceAccordion/ResourceAccordion.vue +2 -2
  33. package/src/components/ResourceExplorer/ResourceExplorer.vue +8 -9
  34. package/src/components/ResourceExplorer/ResourceExplorerViewer.vue +4 -1
  35. package/src/components/Search/GlobalSearch.vue +16 -2
  36. package/src/components/TabularExplorer/TabularCellPopover.vue +2 -2
  37. package/src/components/TabularExplorer/TabularExplorer.vue +212 -74
  38. package/src/components/TabularExplorer/TabularFilterContent.vue +15 -13
  39. package/src/components/TabularExplorer/TabularFilterPopover.vue +21 -26
  40. package/src/components/TabularExplorer/types.ts +9 -9
  41. package/src/composables/useResourceCapabilities.ts +1 -1
  42. package/src/composables/useSearchFilter.ts +7 -5
  43. package/src/functions/api.ts +13 -7
  44. package/src/functions/resources.ts +5 -0
  45. package/src/functions/tabular.ts +103 -1
  46. package/src/types/resources.ts +0 -1
  47. package/dist/Pmtiles.client-Dzm01Zfm.js +0 -25185
@@ -1,4 +1,4 @@
1
- import { defineComponent as T, ref as k, onMounted as J, h as g, watch as F, computed as O, inject as $, provide as q, createElementBlock as _, openBlock as N, normalizeClass as S, toDisplayString as A, resolveComponent as ie, createCommentVNode as Y, createElementVNode as z, renderSlot as ce, createTextVNode as pe, createVNode as fe, nextTick as de } from "vue";
1
+ import { defineComponent as T, ref as k, onMounted as J, h as g, watch as F, computed as O, inject as $, provide as q, openBlock as _, createElementBlock as N, toDisplayString as A, normalizeClass as S, resolveComponent as ie, createElementVNode as z, renderSlot as ce, createTextVNode as pe, createCommentVNode as Y, createVNode as fe, nextTick as de } from "vue";
2
2
  const ve = /^([hH][tT]{2}[pP]:\/\/|[hH][tT]{2}[pP][sS]:\/\/)(([A-Za-z0-9-~]+)\.)+([A-Za-z0-9-~\/])+$/, X = T({
3
3
  name: "JsonString",
4
4
  props: {
@@ -66,7 +66,7 @@ const ve = /^([hH][tT]{2}[pP]:\/\/|[hH][tT]{2}[pP][sS]:\/\/)(([A-Za-z0-9-~]+)\.)
66
66
  },
67
67
  setup(e) {
68
68
  const y = e, c = O(() => y.jsonValue === null ? "null" : "undefined");
69
- return (p, d) => (N(), _("span", ye, A(c.value), 1));
69
+ return (p, d) => (_(), N("span", ye, A(c.value), 1));
70
70
  }
71
71
  }), he = /* @__PURE__ */ T({
72
72
  __name: "json-number",
@@ -79,7 +79,7 @@ const ve = /^([hH][tT]{2}[pP]:\/\/|[hH][tT]{2}[pP][sS]:\/\/)(([A-Za-z0-9-~]+)\.)
79
79
  },
80
80
  setup(e) {
81
81
  const y = e, c = O(() => Number.isInteger(y.jsonValue));
82
- return (p, d) => (N(), _("span", {
82
+ return (p, d) => (_(), N("span", {
83
83
  class: S(["jv-item", "jv-number", c.value ? "jv-number-integer" : "jv-number-float"])
84
84
  }, A(e.jsonValue.toString()), 3));
85
85
  }
@@ -95,7 +95,7 @@ const ve = /^([hH][tT]{2}[pP]:\/\/|[hH][tT]{2}[pP][sS]:\/\/)(([A-Za-z0-9-~]+)\.)
95
95
  }
96
96
  },
97
97
  setup(e) {
98
- return (y, c) => (N(), _("span", ge, A(e.jsonValue.toString()), 1));
98
+ return (y, c) => (_(), N("span", ge, A(e.jsonValue.toString()), 1));
99
99
  }
100
100
  }), je = T({
101
101
  name: "JsonObject",
@@ -277,7 +277,7 @@ const ve = /^([hH][tT]{2}[pP]:\/\/|[hH][tT]{2}[pP][sS]:\/\/)(([A-Za-z0-9-~]+)\.)
277
277
  }
278
278
  },
279
279
  setup(e) {
280
- return (y, c) => (N(), _("span", {
280
+ return (y, c) => (_(), N("span", {
281
281
  class: S(["jv-item", "jv-function"]),
282
282
  title: e.jsonValue.toString()
283
283
  }, " <function> ", 8, Ee));
@@ -295,7 +295,7 @@ const ve = /^([hH][tT]{2}[pP]:\/\/|[hH][tT]{2}[pP][sS]:\/\/)(([A-Za-z0-9-~]+)\.)
295
295
  },
296
296
  setup(e) {
297
297
  const y = e, c = $("timeformat", (d) => d.toLocaleString()), p = O(() => c(y.jsonValue));
298
- return (d, i) => (N(), _("span", ke, ' "' + A(p.value) + '" ', 1));
298
+ return (d, i) => (_(), N("span", ke, ' "' + A(p.value) + '" ', 1));
299
299
  }
300
300
  }), Te = {
301
301
  class: /* @__PURE__ */ S(["jv-item", "jv-regexp"])
@@ -309,7 +309,7 @@ const ve = /^([hH][tT]{2}[pP]:\/\/|[hH][tT]{2}[pP][sS]:\/\/)(([A-Za-z0-9-~]+)\.)
309
309
  }
310
310
  },
311
311
  setup(e) {
312
- return (y, c) => (N(), _("span", Te, A(e.jsonValue.toString()), 1));
312
+ return (y, c) => (_(), N("span", Te, A(e.jsonValue.toString()), 1));
313
313
  }
314
314
  }), I = T({
315
315
  name: "JsonBox",
@@ -421,12 +421,6 @@ function _e(e) {
421
421
  return e && e.__esModule && Object.prototype.hasOwnProperty.call(e, "default") ? e.default : e;
422
422
  }
423
423
  var H = { exports: {} };
424
- /*!
425
- * clipboard.js v2.0.11
426
- * https://clipboardjs.com/
427
- *
428
- * Licensed MIT © Zeno Rocha
429
- */
430
424
  var Ne = H.exports, Z;
431
425
  function Oe() {
432
426
  return Z || (Z = 1, (function(e, y) {
@@ -1041,10 +1035,10 @@ const Me = /* @__PURE__ */ _e(Ae), Ve = function(e, y) {
1041
1035
  };
1042
1036
  function Re(e, y, c, p, d, i) {
1043
1037
  const n = ie("json-box");
1044
- return N(), _("div", {
1038
+ return _(), N("div", {
1045
1039
  class: S(e.jvClass)
1046
1040
  }, [
1047
- e.copyable ? (N(), _("div", {
1041
+ e.copyable ? (_(), N("div", {
1048
1042
  key: 0,
1049
1043
  class: S(`jv-tooltip ${e.copyText.align || "right"}`)
1050
1044
  }, [
@@ -1067,7 +1061,7 @@ function Re(e, y, c, p, d, i) {
1067
1061
  "preview-mode": e.previewMode
1068
1062
  }, null, 8, ["value", "sort", "preview-mode"])
1069
1063
  ], 2),
1070
- e.expandableCode && e.boxed ? (N(), _("div", {
1064
+ e.expandableCode && e.boxed ? (_(), N("div", {
1071
1065
  key: 1,
1072
1066
  class: "jv-more",
1073
1067
  onClick: y[0] || (y[0] = (...t) => e.toggleExpandCode && e.toggleExpandCode(...t))
@@ -1,4 +1,4 @@
1
- import { c as Ke } from "./main-Iz1ZCL6k.js";
1
+ import { b7 as Ke } from "./main-DKu5SOAl.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": "1.2.0",
3
+ "version": "1.3.0",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "engines": {
@@ -25,21 +25,22 @@
25
25
  "dependencies": {
26
26
  "@floating-ui/vue": "^1.1.11",
27
27
  "@headlessui/vue": "^1.7.23",
28
- "@remixicon/vue": "^4.5.0",
28
+ "@remixicon/vue": "^4.9.0",
29
29
  "@types/hast": "^3.0.4",
30
- "@types/leaflet": "^1.9.17",
31
- "@vueuse/core": "^14.2.1",
32
- "@vueuse/router": "^14.2.1",
33
- "chart.js": "^4.4.8",
34
- "dompurify": "^3.2.5",
35
- "geopf-extensions-openlayers": "^1.0.0-beta.10",
30
+ "@types/leaflet": "^1.9.21",
31
+ "@vueuse/core": "^14.3.0",
32
+ "@vueuse/router": "^14.3.0",
33
+ "chart.js": "^4.5.1",
34
+ "dompurify": "^3.4.7",
35
+ "echarts": "^6.1.0",
36
+ "geopf-extensions-openlayers": "1.0.0-beta.11",
36
37
  "leaflet": "^1.9.4",
37
- "maplibre-gl": "^5.6.2",
38
- "ofetch": "^1.4.1",
39
- "ol": "^10.6.1",
38
+ "maplibre-gl": "^5.24.0",
39
+ "ofetch": "^1.5.1",
40
+ "ol": "^10.9.0",
40
41
  "pdfjs-dist": "^4.10.38",
41
- "pmtiles": "^4.3.0",
42
- "popmotion": "^11.0",
42
+ "pmtiles": "^4.4.1",
43
+ "popmotion": "^11.0.5",
43
44
  "rehype-highlight": "^7.0.2",
44
45
  "rehype-raw": "^7.0.0",
45
46
  "rehype-sanitize": "^6.0.0",
@@ -53,39 +54,38 @@
53
54
  "strip-markdown": "^6.0.0",
54
55
  "stylefire": "^7.0.3",
55
56
  "unified": "^11.0.5",
56
- "unist-util-visit": "^5.0.0",
57
+ "unist-util-visit": "^5.1.0",
57
58
  "vue-content-loader": "^2.0.1",
58
59
  "vue-sonner": "^2.0.9",
59
60
  "vue3-json-viewer": "^2.4.1",
60
61
  "vue3-text-clamp": "^0.1.2",
61
62
  "vue3-xml-viewer": "^0.0.14",
62
- "yaml": "^2.8.2"
63
+ "yaml": "^2.9.0"
63
64
  },
64
65
  "devDependencies": {
65
66
  "@intlify/cli": "^0.13.1",
66
- "@tailwindcss/cli": "^4.0.8",
67
- "@tailwindcss/typography": "^0.5.16",
68
- "@tsconfig/node22": "^22.0.0",
67
+ "@tailwindcss/cli": "^4.3.0",
68
+ "@tailwindcss/typography": "^0.5.19",
69
+ "@tsconfig/node22": "^22.0.5",
69
70
  "@types/geojson": "^7946.0.16",
70
- "@types/node": "^22.13.1",
71
- "@vitejs/plugin-vue": "^6.0",
71
+ "@types/node": "^22.19.19",
72
+ "@vitejs/plugin-vue": "^6.0.7",
72
73
  "@vue/eslint-config-prettier": "^10.2.0",
73
- "@vue/eslint-config-typescript": "^14.3.0",
74
- "@vue/tsconfig": "^0.8.0",
75
- "echarts": "^6.0.0",
76
- "eslint": "^9.18.0",
77
- "eslint-plugin-vue": "^10.0",
78
- "jiti": "^2.4.2",
79
- "npm-run-all2": "^8.0",
74
+ "@vue/eslint-config-typescript": "^14.7.0",
75
+ "@vue/tsconfig": "^0.8.1",
76
+ "eslint": "^9.39.4",
77
+ "eslint-plugin-vue": "^10.9.1",
78
+ "jiti": "^2.7.0",
79
+ "npm-run-all2": "^8.0.4",
80
80
  "openapi-types": "^12.1.3",
81
- "prettier": "^3.0.0",
82
- "tailwindcss": "^4.0.8",
81
+ "prettier": "^3.8.3",
82
+ "tailwindcss": "^4.3.0",
83
83
  "typescript": "^5.9.3",
84
- "vite": "^7.0",
85
- "vite-plugin-vue-devtools": "^8.0",
86
- "vue": "^3.5.33",
87
- "vue-router": "^5.0.4",
88
- "vue-tsc": "^3.0"
84
+ "vite": "^7.3.3",
85
+ "vite-plugin-vue-devtools": "^8.1.2",
86
+ "vue": "^3.5.35",
87
+ "vue-router": "^5.0.7",
88
+ "vue-tsc": "^3.3.2"
89
89
  },
90
90
  "peerDependencies": {
91
91
  "vue": "^3.5.13",
@@ -107,7 +107,9 @@ async function displayMap() {
107
107
  p.getHeader().then((h: { maxZoom: number, centerLon: number, centerLat: number }) => {
108
108
  const map = new maplibregl.Map({
109
109
  container: container.value!,
110
- style: styleVector as maplibregl.StyleSpecification,
110
+ // JSON import is inferred too loosely (e.g. center as number[]) to match
111
+ // maplibre's strict StyleSpecification, so cast through unknown.
112
+ style: styleVector as unknown as maplibregl.StyleSpecification,
111
113
  zoom: h.maxZoom - 2,
112
114
  center: [h.centerLon, h.centerLat],
113
115
  })
@@ -271,7 +271,7 @@
271
271
  />
272
272
  </div>
273
273
  <div
274
- v-if="tab.key === 'swagger'"
274
+ v-if="tab.key === 'api'"
275
275
  >
276
276
  <div class="fr-mb-4w">
277
277
  <p>{{ t("Cette API est générée automatiquement par {platform} à partir du fichier.", { platform: config.name }) }}</p>
@@ -417,7 +417,7 @@ const tabsOptions = computed(() => {
417
417
  options.push({ key: 'downloads', label: t('Téléchargements') })
418
418
 
419
419
  if (hasTabularData.value) {
420
- options.push({ key: 'swagger', label: t('Swagger') })
420
+ options.push({ key: 'api', label: t('API') })
421
421
  }
422
422
 
423
423
  return options
@@ -71,7 +71,7 @@ import { useComponentsConfig } from '../../config'
71
71
  import { useTranslation } from '../../composables/useTranslation'
72
72
  import { useDebouncedRef } from '../../composables/useDebouncedRef'
73
73
  import { useFetch } from '../../functions/api'
74
- import { RESOURCE_TYPE } from '../../functions/resources'
74
+ import { RESOURCE_EXPLORER_PAGE_SIZE, RESOURCE_TYPE } from '../../functions/resources'
75
75
  import type { PaginatedArray } from '../../types/api'
76
76
  import type { DatasetV2 } from '../../types/datasets'
77
77
  import type { Resource, ResourceGroup, ResourceType } from '../../types/resources'
@@ -94,7 +94,6 @@ const sidebarCollapsed = ref(false)
94
94
  const search = ref('')
95
95
  const { debounced: searchDebounced, flush } = useDebouncedRef(search, config.searchDebounce ?? 300)
96
96
 
97
- const PAGE_SIZE = 10
98
97
  const url = computed(() => `/api/2/datasets/${props.dataset.id}/resources/`)
99
98
 
100
99
  // Resource ID from URL query
@@ -103,32 +102,32 @@ const resourceIdQuery = useRouteQuery<string | undefined>('resource_id')
103
102
  // Fetch resources for each type
104
103
  const mainParams = computed(() => ({
105
104
  type: 'main' as const,
106
- page_size: PAGE_SIZE,
105
+ page_size: RESOURCE_EXPLORER_PAGE_SIZE,
107
106
  q: searchDebounced.value || undefined,
108
107
  }))
109
108
  const documentationParams = computed(() => ({
110
109
  type: 'documentation' as const,
111
- page_size: PAGE_SIZE,
110
+ page_size: RESOURCE_EXPLORER_PAGE_SIZE,
112
111
  q: searchDebounced.value || undefined,
113
112
  }))
114
113
  const updateParams = computed(() => ({
115
114
  type: 'update' as const,
116
- page_size: PAGE_SIZE,
115
+ page_size: RESOURCE_EXPLORER_PAGE_SIZE,
117
116
  q: searchDebounced.value || undefined,
118
117
  }))
119
118
  const apiParams = computed(() => ({
120
119
  type: 'api' as const,
121
- page_size: PAGE_SIZE,
120
+ page_size: RESOURCE_EXPLORER_PAGE_SIZE,
122
121
  q: searchDebounced.value || undefined,
123
122
  }))
124
123
  const codeParams = computed(() => ({
125
124
  type: 'code' as const,
126
- page_size: PAGE_SIZE,
125
+ page_size: RESOURCE_EXPLORER_PAGE_SIZE,
127
126
  q: searchDebounced.value || undefined,
128
127
  }))
129
128
  const otherParams = computed(() => ({
130
129
  type: 'other' as const,
131
- page_size: PAGE_SIZE,
130
+ page_size: RESOURCE_EXPLORER_PAGE_SIZE,
132
131
  q: searchDebounced.value || undefined,
133
132
  }))
134
133
 
@@ -169,7 +168,7 @@ const loadMoreType = ref<ResourceType>('main')
169
168
  const loadMorePage = ref(1)
170
169
  const loadMoreParams = computed(() => ({
171
170
  type: loadMoreType.value,
172
- page_size: PAGE_SIZE,
171
+ page_size: RESOURCE_EXPLORER_PAGE_SIZE,
173
172
  page: loadMorePage.value,
174
173
  q: searchDebounced.value || undefined,
175
174
  }))
@@ -185,12 +185,15 @@
185
185
  :dataset="dataset"
186
186
  />
187
187
  </div>
188
- <div v-if="tab.key === 'swagger'">
188
+ <div v-if="tab.key === 'api'">
189
189
  <div class="fr-mb-4w">
190
190
  <p>{{ t("Cette API est générée automatiquement par {platform} à partir du fichier.", { platform: config.name }) }}</p>
191
191
  <p>{{ t("- Si le fichier est modifié, l'API sera mise à jour et sa structure pourra changer.") }}</p>
192
192
  <p>{{ t("- Si le fichier est supprimé, l'API sera également supprimée.") }}</p>
193
193
  <p>{{ t("Pour des usages pérennes, prévoyez que cette API dépend directement du fichier source.") }}</p>
194
+ <p v-if="config.tabularApiUrl">
195
+ {{ t("L'URL de base de l'API est {url}", { url: config.tabularApiUrl }) }}
196
+ </p>
194
197
  </div>
195
198
  <OpenApiViewer
196
199
  v-if="hasTabularData"
@@ -549,20 +549,34 @@ const allFilters: Record<string, Ref<unknown>> = {
549
549
  type: reuseType,
550
550
  }
551
551
 
552
- // Reset sort and filters when changing type if they're not valid for the new type
552
+ // Reset page, sort and filters when changing type. Every reset below goes
553
+ // through useRouteQuery, so VueUse coalesces them into a single router.replace
554
+ // (its shared _queriesQueue flushes once on nextTick). Custom filters are cleared
555
+ // here too, rather than in useSearchFilter's onunmount, so their URL change joins
556
+ // that same batch instead of racing it with a separate router.replace.
553
557
  watch(currentType, () => {
558
+ // page=1 is the default and is dropped from the URL, so only reset when needed.
559
+ if (page.value !== 1) page.value = 1
560
+
554
561
  // Reset sort if not valid
555
562
  const validSortValues = activeSortOptions.value.map(o => o.value as string)
556
563
  if (sort.value && !validSortValues.includes(sort.value)) {
557
564
  sort.value = undefined
558
565
  }
559
566
 
560
- // Reset filters that are not enabled for the new type
567
+ // Reset built-in filters that are not enabled for the new type
561
568
  for (const [filterName, filterRef] of Object.entries(allFilters)) {
562
569
  if (filterRef.value !== undefined && !activeFilters.value.includes(filterName)) {
563
570
  filterRef.value = undefined
564
571
  }
565
572
  }
573
+
574
+ // Reset type-scoped custom filters that don't apply to the new type
575
+ for (const entry of customFilterRegistry.values()) {
576
+ if (entry.typeKeys && !entry.typeKeys.includes(currentType.value) && isCustomFilterActive(entry)) {
577
+ entry.ref.value = entry.defaultValue
578
+ }
579
+ }
566
580
  })
567
581
 
568
582
  // Create stable params for each type
@@ -38,7 +38,7 @@
38
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
39
  @click="filterByValue"
40
40
  >
41
- <RiFilter2Line
41
+ <RiFilterLine
42
42
  class="size-4"
43
43
  aria-hidden="true"
44
44
  />
@@ -71,7 +71,7 @@ import { computed, ref, useTemplateRef, watch } from 'vue'
71
71
  import { flip, shift, autoUpdate, useFloating } from '@floating-ui/vue'
72
72
  import { onClickOutside } from '@vueuse/core'
73
73
  import {
74
- RiFilter2Line,
74
+ RiFilterLine,
75
75
  RiFileCopyLine,
76
76
  RiCheckLine,
77
77
  } from '@remixicon/vue'