@eodash/eodash 5.0.0 → 5.2.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 (162) hide show
  1. package/README.md +1 -0
  2. package/core/client/App.vue +8 -2
  3. package/core/client/asWebComponent.js +5 -5
  4. package/core/client/components/DashboardLayout.vue +43 -26
  5. package/core/client/components/EodashOverlay.vue +5 -6
  6. package/core/client/components/ErrorAlert.vue +2 -2
  7. package/core/client/components/Footer.vue +4 -4
  8. package/core/client/components/Header.vue +3 -3
  9. package/core/client/components/MobileLayout.vue +47 -27
  10. package/core/client/composables/DefineEodash.js +38 -43
  11. package/core/client/composables/DefineTemplate.js +4 -2
  12. package/core/client/composables/DefineWidgets.js +14 -8
  13. package/core/client/composables/index.js +273 -23
  14. package/core/client/eodashSTAC/EodashCollection.js +84 -62
  15. package/core/client/eodashSTAC/createLayers.js +30 -0
  16. package/core/client/eodashSTAC/helpers.js +159 -28
  17. package/core/client/eodashSTAC/parquet.js +145 -0
  18. package/core/client/eodashSTAC/triggers.js +6 -3
  19. package/core/client/plugins/index.js +4 -3
  20. package/core/client/plugins/vuetify.js +3 -0
  21. package/core/client/store/actions.js +21 -4
  22. package/core/client/store/stac.js +93 -56
  23. package/core/client/store/states.js +15 -5
  24. package/core/client/types.ts +59 -43
  25. package/core/client/utils/index.js +79 -0
  26. package/core/client/utils/keys.js +2 -2
  27. package/core/client/utils/states.js +30 -5
  28. package/core/client/views/Dashboard.vue +36 -32
  29. package/core/client/vite-env.d.ts +7 -0
  30. package/dist/client/{DashboardLayout-CkWvOMOW.js → DashboardLayout-Dq9Kfe6O.js} +24 -13
  31. package/dist/client/{DynamicWebComponent-DYBbpvUK.js → DynamicWebComponent-DCBMXskE.js} +1 -1
  32. package/dist/client/{EodashDatePicker-CALmW3SI.js → EodashDatePicker-DtngxU6s.js} +59 -32
  33. package/dist/client/{EodashItemFilter-DlQiE713.js → EodashItemFilter-ClQebJQt.js} +20 -10
  34. package/dist/client/{EodashLayerControl-DEzEbft7.js → EodashLayerControl-BLBds28C.js} +29 -16
  35. package/dist/client/EodashLayoutSwitcher-DQ8SfVDd.js +61 -0
  36. package/dist/client/EodashMapBtns-B89_YBDw.js +326 -0
  37. package/dist/client/{EodashStacInfo-DPPxDkF6.js → EodashStacInfo-Dt1nF06x.js} +3 -18
  38. package/dist/client/{EodashTools-CUaL9s4H.js → EodashTools-DV5ykmWc.js} +13 -13
  39. package/dist/client/{ExportState-DjyIZVhl.js → ExportState-B6zZQUmE.js} +57 -52
  40. package/dist/client/{Footer-DyL0JoWt.js → Footer-DNhXs8k6.js} +15 -13
  41. package/dist/client/{Header-B5Dgty9l.js → Header-BjhN5JY4.js} +32 -28
  42. package/dist/client/MobileLayout-JelB6w1G.js +118 -0
  43. package/dist/client/{PopUp-BfB8s_ki.js → PopUp-CgpvNr3o.js} +18 -10
  44. package/dist/client/ProcessList-vecpxThi.js +198 -0
  45. package/dist/client/{VImg-FD1WVphJ.js → VImg-CETuikH2.js} +221 -26
  46. package/dist/client/{VMain-DJKG4SvM.js → VMain-Ci9DyaGU.js} +7 -7
  47. package/dist/client/{VTooltip-CfeefrXI.js → VTooltip-J4ac48X7.js} +12 -10
  48. package/dist/client/{WidgetsContainer-C2TaTdb6.js → WidgetsContainer-CCML4TyV.js} +1 -1
  49. package/dist/client/asWebComponent-ZyEzWOOf.js +19092 -0
  50. package/dist/client/async-B7jIrM53.js +804 -0
  51. package/dist/client/eo-dash.js +1 -1
  52. package/dist/client/{VOverlay-BzOdRu9h.js → forwardRefs-BQclvjMq.js} +332 -28
  53. package/dist/client/handling-BS24aG1q.js +1227 -0
  54. package/dist/client/helpers-wXK7Ywio.js +4556 -0
  55. package/dist/client/index-4UCzZi8B.js +376 -0
  56. package/dist/client/{index-4CT7Tz83.js → index-9KR-G20t.js} +2 -2
  57. package/dist/client/{index-CIHH_3dW.js → index-B2XpdgR6.js} +227 -86
  58. package/dist/client/material-symbols-outlined.woff2 +0 -0
  59. package/dist/client/material-symbols-rounded.woff2 +0 -0
  60. package/dist/client/material-symbols-sharp.woff2 +0 -0
  61. package/dist/client/material-symbols-subset.woff2 +0 -0
  62. package/dist/client/{ssrBoot-BP7SYRyC.js → ssrBoot-Zgc_Ttvi.js} +2 -2
  63. package/dist/client/templates.js +840 -0
  64. package/dist/client/transition-yBii4fu6.js +40 -0
  65. package/dist/node/cli.js +16 -6
  66. package/dist/node/types.d.ts +1 -1
  67. package/dist/types/core/client/App.vue.d.ts +2 -2
  68. package/dist/types/core/client/asWebComponent.d.ts +1 -1
  69. package/dist/types/core/client/components/DynamicWebComponent.vue.d.ts +1 -3
  70. package/dist/types/core/client/components/Footer.vue.d.ts +1 -105
  71. package/dist/types/core/client/components/IframeWrapper.vue.d.ts +1 -1
  72. package/dist/types/core/client/components/MobileLayout.vue.d.ts +1 -324
  73. package/dist/types/core/client/composables/DefineEodash.d.ts +2 -2
  74. package/dist/types/core/client/composables/DefineTemplate.d.ts +1 -1
  75. package/dist/types/core/client/composables/DefineWidgets.d.ts +4 -4
  76. package/dist/types/core/client/composables/index.d.ts +24 -2
  77. package/dist/types/core/client/eodashSTAC/EodashCollection.d.ts +9 -6
  78. package/dist/types/core/client/eodashSTAC/helpers.d.ts +25 -5
  79. package/dist/types/core/client/eodashSTAC/parquet.d.ts +2 -0
  80. package/dist/types/core/client/plugins/vuetify.d.ts +7 -4
  81. package/dist/types/core/client/store/actions.d.ts +3 -2
  82. package/dist/types/core/client/store/stac.d.ts +16 -13
  83. package/dist/types/core/client/store/states.d.ts +14 -4
  84. package/dist/types/core/client/types.d.ts +46 -31
  85. package/dist/types/core/client/utils/index.d.ts +2 -0
  86. package/dist/types/core/client/utils/keys.d.ts +4 -4
  87. package/dist/types/core/client/utils/states.d.ts +59 -47
  88. package/dist/types/core/client/views/Dashboard.vue.d.ts +2 -2
  89. package/dist/types/templates/baseConfig.d.ts +4 -0
  90. package/dist/types/templates/compare.d.ts +185 -0
  91. package/dist/types/templates/expert.d.ts +147 -0
  92. package/dist/types/templates/index.d.ts +6 -0
  93. package/dist/types/templates/light.d.ts +154 -0
  94. package/dist/types/widgets/EodashDatePicker.vue.d.ts +1 -458
  95. package/dist/types/widgets/EodashItemFilter.vue.d.ts +3 -3
  96. package/dist/types/widgets/EodashLayerControl.vue.d.ts +14 -7
  97. package/dist/types/widgets/EodashLayoutSwitcher.vue.d.ts +1 -3
  98. package/dist/types/widgets/{EodashMapBtns.vue.d.ts → EodashMap/EodashMapBtns.vue.d.ts} +12 -8
  99. package/dist/types/widgets/EodashMap/index.vue.d.ts +9 -4
  100. package/dist/types/widgets/EodashProcess/ProcessList.vue.d.ts +8 -1
  101. package/dist/types/widgets/EodashProcess/index.vue.d.ts +8 -4
  102. package/dist/types/widgets/EodashProcess/methods/async.d.ts +19 -18
  103. package/dist/types/widgets/EodashProcess/methods/composables.d.ts +3 -2
  104. package/dist/types/widgets/EodashProcess/methods/custom-endpoints/chart/index.d.ts +1 -0
  105. package/dist/types/widgets/EodashProcess/methods/custom-endpoints/chart/sentinelhub-endpoint.d.ts +6 -0
  106. package/dist/types/widgets/EodashProcess/methods/custom-endpoints/chart/veda-endpoint.d.ts +4 -0
  107. package/dist/types/widgets/EodashProcess/methods/custom-endpoints/layers/eoxhub-workspaces-endpoint.d.ts +5 -0
  108. package/dist/types/widgets/EodashProcess/methods/custom-endpoints/layers/index.d.ts +1 -0
  109. package/dist/types/widgets/EodashProcess/methods/handling.d.ts +12 -5
  110. package/dist/types/widgets/EodashProcess/methods/outputs.d.ts +72 -41
  111. package/dist/types/widgets/EodashProcess/methods/utils.d.ts +41 -21
  112. package/dist/types/widgets/EodashProcess/states.d.ts +11 -0
  113. package/dist/types/widgets/EodashProcess/types.d.ts +41 -0
  114. package/dist/types/widgets/EodashStacInfo.vue.d.ts +14 -14
  115. package/dist/types/widgets/EodashTools.vue.d.ts +3 -3
  116. package/dist/types/widgets/ExportState.vue.d.ts +1 -1
  117. package/dist/types/widgets/PopUp.vue.d.ts +11 -16
  118. package/dist/types/widgets/WidgetsContainer.vue.d.ts +3 -6
  119. package/package.json +55 -45
  120. package/templates/baseConfig.js +68 -0
  121. package/templates/compare.js +142 -0
  122. package/templates/expert.js +124 -0
  123. package/templates/index.js +8 -0
  124. package/templates/light.js +139 -0
  125. package/widgets/EodashDatePicker.vue +80 -31
  126. package/widgets/EodashItemFilter.vue +26 -11
  127. package/widgets/EodashLayerControl.vue +20 -11
  128. package/widgets/EodashLayoutSwitcher.vue +6 -3
  129. package/widgets/EodashMap/EodashMapBtns.vue +269 -0
  130. package/widgets/EodashMap/index.vue +255 -45
  131. package/widgets/EodashMap/methods/create-layers-config.js +4 -3
  132. package/widgets/EodashMap/methods/index.js +33 -23
  133. package/widgets/EodashProcess/ProcessList.vue +47 -11
  134. package/widgets/EodashProcess/index.vue +55 -20
  135. package/widgets/EodashProcess/methods/async.js +99 -60
  136. package/widgets/EodashProcess/methods/composables.js +21 -14
  137. package/widgets/EodashProcess/methods/custom-endpoints/chart/index.js +35 -0
  138. package/widgets/EodashProcess/methods/custom-endpoints/chart/sentinelhub-endpoint.js +275 -0
  139. package/widgets/EodashProcess/methods/custom-endpoints/chart/veda-endpoint.js +132 -0
  140. package/widgets/EodashProcess/methods/custom-endpoints/layers/eoxhub-workspaces-endpoint.js +94 -0
  141. package/widgets/EodashProcess/methods/custom-endpoints/layers/index.js +33 -0
  142. package/widgets/EodashProcess/methods/handling.js +127 -80
  143. package/widgets/EodashProcess/methods/outputs.js +376 -125
  144. package/widgets/EodashProcess/methods/utils.js +442 -10
  145. package/widgets/EodashProcess/states.js +13 -0
  146. package/widgets/EodashProcess/types.ts +46 -0
  147. package/widgets/EodashStacInfo.vue +2 -17
  148. package/widgets/EodashTools.vue +13 -13
  149. package/widgets/WidgetsContainer.vue +1 -1
  150. package/core/client/eodash.js +0 -454
  151. package/dist/client/EodashLayoutSwitcher-CDeCV8F-.js +0 -52
  152. package/dist/client/EodashMapBtns-CktQCfa-.js +0 -131
  153. package/dist/client/MobileLayout-CRsg_5Q4.js +0 -1217
  154. package/dist/client/ProcessList-DTefwQZx.js +0 -484
  155. package/dist/client/asWebComponent-CLhcT715.js +0 -12479
  156. package/dist/client/eo-dash.css +0 -5
  157. package/dist/client/forwardRefs-Bon_Kku1.js +0 -245
  158. package/dist/client/index-Bm9cbtx5.js +0 -201
  159. package/dist/client/index-DiGDvTQU.js +0 -780
  160. package/dist/client/transition-C5I57hn6.js +0 -37
  161. package/dist/types/core/client/eodash.d.ts +0 -8
  162. package/widgets/EodashMapBtns.vue +0 -113
@@ -7,17 +7,54 @@ import {
7
7
  currentUrl,
8
8
  datetime,
9
9
  indicator,
10
+ mapEl,
10
11
  mapPosition,
12
+ poi,
11
13
  } from "@/store/states";
12
- import eodash from "@/eodash";
13
- import { useTheme } from "vuetify/lib/framework.mjs";
14
- import { inject, onMounted, onUnmounted, watch } from "vue";
14
+ import { useTheme } from "vuetify";
15
+ import { inject, nextTick, onMounted, onUnmounted, watch } from "vue";
15
16
  import { useSTAcStore } from "@/store/stac";
16
17
  import log from "loglevel";
17
18
  import { eodashKey, eoxLayersKey } from "@/utils/keys";
18
- import { useEventBus } from "@vueuse/core";
19
- import { posIsSetFromUrl } from "@/utils/states";
19
+ import { useEventBus, useMutationObserver } from "@vueuse/core";
20
+ import { isFirstLoad } from "@/utils/states";
20
21
  import { setCollectionsPalette } from "@/utils";
22
+ import mustache from "mustache";
23
+ import { toAbsolute } from "stac-js/src/http.js";
24
+ import axios from "@/plugins/axios";
25
+
26
+ /**
27
+ /** @type {import('@/types').Eodash | null}*/
28
+
29
+ let _eodash = null;
30
+
31
+ /**
32
+ * Call this once in a top-level component to inject and store the reactive eodash object.
33
+ * @throws {Error} If eodash is not found in the inject context
34
+ */
35
+ export function provideEodashInstance() {
36
+ const injected = inject(eodashKey);
37
+ if (!injected) {
38
+ throw new Error(
39
+ "Missing injected eodash – did you forget to call provideEodashInstance in a component?",
40
+ );
41
+ }
42
+ _eodash = injected;
43
+ }
44
+
45
+ /**
46
+ * Access the reactive eodash configuration anywhere after it has been provided.
47
+ * @returns {import('@/types').Eodash | null}
48
+ * @throws {Error} If eodash was not yet provided
49
+ */
50
+ export function useEodash() {
51
+ if (!_eodash) {
52
+ throw new Error(
53
+ "Eodash not yet available – call provideEodashInstance() first.",
54
+ );
55
+ }
56
+ return _eodash;
57
+ }
21
58
 
22
59
  /**
23
60
  * Creates an absolute URL from a relative link and assignes it to `currentUrl`
@@ -28,8 +65,11 @@ import { setCollectionsPalette } from "@/utils";
28
65
  * @returns {import("vue").Ref<string>} - Returns `currentUrl`
29
66
  * @see {@link '@/store/states.js'}
30
67
  */
31
- export const useAbsoluteUrl = (rel = "", base = eodash.stacEndpoint) => {
32
- if (!rel || rel.includes("http")) {
68
+ export const useAbsoluteUrl = (
69
+ rel = "",
70
+ base = inject(eodashKey)?.stacEndpoint,
71
+ ) => {
72
+ if (!rel || rel.includes("http") || !base) {
33
73
  currentUrl.value = rel;
34
74
  return currentUrl;
35
75
  }
@@ -57,9 +97,12 @@ export const useAbsoluteUrl = (rel = "", base = eodash.stacEndpoint) => {
57
97
  * @returns {import("vue").Ref<string>} - Returns `currentUrl`
58
98
  * @see {@link '@/store/states.js'}
59
99
  */
60
- export const useCompareAbsoluteUrl = (rel = "", base = eodash.stacEndpoint) => {
61
- if (!rel || rel.includes("http")) {
62
- currentCompareUrl.value = base;
100
+ export const useCompareAbsoluteUrl = (
101
+ rel = "",
102
+ base = inject(eodashKey)?.stacEndpoint,
103
+ ) => {
104
+ if (!rel || rel.includes("http") || !base) {
105
+ currentCompareUrl.value = rel;
63
106
  return currentCompareUrl;
64
107
  }
65
108
 
@@ -119,6 +162,7 @@ export const useURLSearchParametersSync = () => {
119
162
  // Analyze currently set url params when first loaded and set them in the store
120
163
  if (window.location.search) {
121
164
  const searchParams = new URLSearchParams(window.location.search);
165
+ const store = useSTAcStore();
122
166
 
123
167
  /** @type {number | undefined} */
124
168
  let x,
@@ -134,11 +178,54 @@ export const useURLSearchParametersSync = () => {
134
178
  }
135
179
  case "indicator": {
136
180
  log.debug("Found indicator key in url");
137
- const { loadSelectedSTAC, stac } = useSTAcStore();
138
- const match = stac?.find((link) => link.id == value);
181
+ const eodash = inject(eodashKey);
182
+ const match = store.stac?.find(
183
+ (link) => useGetSubCodeId(link) == value,
184
+ );
139
185
  if (match) {
140
186
  log.debug("Found match, loading stac item", match);
141
- await loadSelectedSTAC(match.href);
187
+ if (searchParams.has("poi")) {
188
+ const indicatorUrl = toAbsolute(
189
+ match.href,
190
+ eodash?.stacEndpoint ?? "",
191
+ );
192
+ // fetch indicator stac collection without rendering it
193
+ /** @type {import("stac-ts").StacCollection} */
194
+ const indicatorStac = await axios
195
+ .get(indicatorUrl)
196
+ .then((resp) => resp.data);
197
+ poi.value = searchParams.get("poi") ?? "";
198
+ // find the process link
199
+ const poiMatch = indicatorStac?.links.find(
200
+ (link) =>
201
+ link.rel === "service" &&
202
+ link.type === "application/json; profile=collection",
203
+ );
204
+ if (poiMatch) {
205
+ log.debug("Found poi match, setting poi", poiMatch);
206
+ // render poi value into the link href
207
+ /** @type {any} */
208
+ let viewForMustache = poi.value;
209
+ const tokens = mustache.parse(poiMatch.href);
210
+ const keyToken = tokens.find(
211
+ (token) => token[0] === "name" && token[1] !== ".",
212
+ );
213
+ // Construct the view object
214
+ if (keyToken) {
215
+ const keyName = keyToken[1];
216
+ viewForMustache = { [keyName]: poi.value };
217
+ }
218
+ /** @type {string} */
219
+ const poiUrl = mustache.render(
220
+ poiMatch.href,
221
+ viewForMustache,
222
+ );
223
+ const poiAbsoluteUrl = toAbsolute(poiUrl, indicatorUrl);
224
+ await store.loadSelectedSTAC(poiAbsoluteUrl, true);
225
+ }
226
+ } else {
227
+ await store.loadSelectedSTAC(match.href);
228
+ }
142
229
  }
143
230
  break;
144
231
  }
@@ -173,19 +260,25 @@ export const useURLSearchParametersSync = () => {
173
260
  if (x && y && z) {
174
261
  log.debug("Coordinates found, applying map poisition", x, y, z);
175
262
  mapPosition.value = [x, y, z];
176
- if (!posIsSetFromUrl.value) {
177
- posIsSetFromUrl.value = true;
263
+ if (mapEl.value) {
264
+ mapEl.value.center = [x, y];
265
+ mapEl.value.zoom = z;
178
266
  }
179
267
  }
268
+
269
+ if (!isFirstLoad.value) {
270
+ isFirstLoad.value = true;
271
+ }
180
272
  }
181
273
 
182
274
  watch(
183
- [indicator, mapPosition, datetime, activeTemplate],
275
+ [indicator, mapPosition, datetime, activeTemplate, poi],
184
276
  ([
185
277
  updatedIndicator,
186
278
  updatedMapPosition,
187
279
  updatedDatetime,
188
280
  updatedTemplate,
281
+ updatedPoi,
189
282
  ]) => {
190
283
  if ("URLSearchParams" in window) {
191
284
  const searchParams = new URLSearchParams(window.location.search);
@@ -205,6 +298,14 @@ export const useURLSearchParametersSync = () => {
205
298
  if (updatedTemplate) {
206
299
  searchParams.set("template", updatedTemplate);
207
300
  }
301
+ if (!updatedPoi) {
302
+ if (searchParams.has("poi")) {
303
+ searchParams.delete("poi");
304
+ }
305
+ } else {
306
+ searchParams.set("poi", updatedPoi);
307
+ }
308
+
208
309
  const newRelativePathQuery =
209
310
  window.location.pathname + "?" + searchParams.toString();
210
311
  history.pushState(null, "", newRelativePathQuery);
@@ -218,25 +319,28 @@ export const useURLSearchParametersSync = () => {
218
319
  * Converts eox-layout-item to transparent
219
320
  *
220
321
  * @param {import("vue").Ref<HTMLElement|null>} root - components root element ref*/
221
- export const makePanelTransparent = (root) => {
322
+ export const useTransparentPanel = (root) => {
222
323
  onMounted(() => {
223
- const eoxItem = root.value?.parentElement;
224
- if (eoxItem?.tagName === "EOX-LAYOUT-ITEM") {
225
- eoxItem.classList.remove("bg-surface");
324
+ const backgroundItem = root.value?.parentElement;
325
+ if (backgroundItem?.classList.contains("bg-surface")) {
326
+ backgroundItem.classList.remove("bg-surface");
226
327
  }
227
328
  });
228
329
  };
229
330
 
230
331
  export const useGetTemplates = () => {
231
- const eodash = /** @type {import("@/types").Eodash} */ (inject(eodashKey));
232
- return "template" in eodash ? [] : Object.keys(eodash.templates);
332
+ const eodash = inject(eodashKey);
333
+ if (!eodash) {
334
+ return [];
335
+ }
336
+ return "template" in eodash ? [] : Object.keys(eodash?.templates ?? {});
233
337
  };
234
338
 
235
339
  /**
236
340
  * Listens to the `layers:updated` and `time:updated` events and calls
237
341
  *
238
342
  * @param {import("@vueuse/core").EventBusListener<
239
- * "layers:updated"|"time:updated",
343
+ * import("@/types").LayersEventBusKeys,
240
344
  * {layers:Record<string,any>[]| undefined}
241
345
  * >} listener
242
346
  */
@@ -249,3 +353,149 @@ export const useOnLayersUpdate = (listener) => {
249
353
  unsubscribe();
250
354
  });
251
355
  };
356
+ /**
357
+ * @param {import("@/types").LayersEventBusKeys} event
358
+ * @param {import("@eox/map").EOxMap | null} mapEl
359
+ * @param {Record<string,any>[]} layers
360
+ */
361
+ export const useEmitLayersUpdate = async (event, mapEl, layers) => {
362
+ if (!mapEl) {
363
+ return;
364
+ }
365
+
366
+ const layersEvents = useEventBus(eoxLayersKey);
367
+
368
+ const emit = async () =>
369
+ mapEl?.updateComplete.then(async () => {
370
+ await nextTick(() => {
371
+ layersEvents.emit(event, layers);
372
+ });
373
+ });
374
+
375
+ const dl = /** @type {import("ol/layer").Group} */ (
376
+ mapEl.getLayerById("AnalysisGroup")
377
+ );
378
+ await new Promise((res, _rej) => {
379
+ if (!dl) {
380
+ mapEl.map.getLayers().once("add", async () => {
381
+ await emit();
382
+ res(true);
383
+ });
384
+ return;
385
+ }
386
+
387
+ mapEl.map.once("loadend", async () => {
388
+ await emit();
389
+ res(true);
390
+ });
391
+ });
392
+ };
393
+
394
+ /**
395
+ * @param {import("stac-ts").StacCollection | import("stac-ts").StacLink | import("stac-ts").StacItem | null} collection
396
+ * @returns {string} - Returns the collection id or subcode if `useSubCode` is enabled
397
+ */
398
+ export const useGetSubCodeId = (collection) => {
399
+ const eodash = useEodash();
400
+
401
+ if (!collection) {
402
+ return "";
403
+ }
404
+
405
+ if (eodash?.options?.useSubCode) {
406
+ return typeof collection.subcode === "string"
407
+ ? collection.subcode
408
+ : /** @type {string} */ (collection.id);
409
+ }
410
+ return /** @type {string} */ (collection.id);
411
+ };
412
+
413
+ /**
414
+ * Composable: Adopt Vuetify styles into eo-dash shadow root
415
+ * - Safe no-op outside Web Component context
416
+ * - Cleans up observers on unmount
417
+ */
418
+ /**
419
+ * @param {string[]} [keyWords=["vuetify"]] - list of case-insensitive substrings to match against <style> element IDs
420
+ */
421
+ export function useAdoptStyles(keyWords = ["vuetify"]) {
422
+ /** @type {Array<() => void>} */
423
+ let stops = [];
424
+
425
+ const eoDash =
426
+ /** @type {HTMLElement & { shadowRoot: ShadowRoot | null }} */ (
427
+ document.querySelector("eo-dash")
428
+ );
429
+ if (!eoDash || !eoDash.shadowRoot) return;
430
+ // Require Constructable Stylesheets support
431
+ if (typeof CSSStyleSheet === "undefined") return;
432
+
433
+ const head = document.head;
434
+ const shadow = eoDash.shadowRoot;
435
+ /** @type {Map<string, CSSStyleSheet>} */
436
+ const sheetsById = new Map();
437
+
438
+ /**
439
+ * @param {string} id
440
+ * @param {string} cssText
441
+ */
442
+ const updateSheet = (id, cssText) => {
443
+ let sheet = sheetsById.get(id);
444
+ if (!sheet) {
445
+ sheet = new CSSStyleSheet();
446
+ sheet.replaceSync(cssText);
447
+ sheetsById.set(id, sheet);
448
+ shadow.adoptedStyleSheets = [...shadow.adoptedStyleSheets, sheet];
449
+ } else {
450
+ sheet.replaceSync(cssText);
451
+ }
452
+ };
453
+
454
+ /**
455
+ * @param {HTMLStyleElement} el
456
+ */
457
+ const handleStyleEl = (el) => {
458
+ const id = el.id || "";
459
+ const idLc = id.toLowerCase();
460
+ if (!keyWords.some((s) => idLc.includes(String(s).toLowerCase()))) return;
461
+ const cssText = (el.textContent || "").replaceAll(":root", ":host");
462
+ if (!cssText) return;
463
+
464
+ updateSheet(id, cssText);
465
+
466
+ const observer = useMutationObserver(
467
+ el,
468
+ () => {
469
+ const nextCss = (el.textContent || "").replaceAll(":root", ":host");
470
+ if (nextCss) updateSheet(id, nextCss);
471
+ },
472
+ { childList: true, characterData: true, subtree: true },
473
+ );
474
+ if (observer?.stop) stops.push(() => observer.stop());
475
+ };
476
+
477
+ /**
478
+ * @param {Node} node
479
+ */
480
+ const handleNode = (node) => {
481
+ if (node instanceof HTMLStyleElement) handleStyleEl(node);
482
+ };
483
+
484
+ head.childNodes.forEach(handleNode);
485
+
486
+ const headObserver = useMutationObserver(
487
+ head,
488
+ (mutations) => {
489
+ mutations?.forEach((m) => {
490
+ m.addedNodes?.forEach(handleNode);
491
+ });
492
+ },
493
+ { childList: true },
494
+ );
495
+ if (headObserver?.stop) stops.push(() => headObserver.stop());
496
+
497
+ onUnmounted(() => {
498
+ stops.forEach((stop) => stop());
499
+ stops = [];
500
+ });
501
+ }