@eodash/eodash 5.4.0 → 5.5.1

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 (114) hide show
  1. package/core/client/App.vue +1 -1
  2. package/core/client/asWebComponent.js +1 -1
  3. package/core/client/composables/DefineWidgets.js +12 -2
  4. package/core/client/eodashSTAC/EodashCollection.js +12 -13
  5. package/core/client/eodashSTAC/createLayers.js +45 -18
  6. package/core/client/eodashSTAC/helpers.js +13 -5
  7. package/core/client/eodashSTAC/parquet.js +2 -1
  8. package/core/client/eodashSTAC/triggers.js +1 -2
  9. package/core/client/store/actions.js +17 -17
  10. package/core/client/store/states.js +26 -4
  11. package/core/client/types.ts +9 -0
  12. package/core/client/utils/index.js +18 -1
  13. package/dist/client/{DashboardLayout-CQOGHPW_.js → DashboardLayout-D_590Zle.js} +2 -2
  14. package/dist/client/{DynamicWebComponent-CoLO8FEf.js → DynamicWebComponent-67cfzL4o.js} +1 -1
  15. package/dist/client/EodashChart-BsW18Em1.js +144 -0
  16. package/dist/client/{EodashDatePicker-BZeQ6bcu.js → EodashDatePicker-BwyFIBlK.js} +10 -7
  17. package/dist/client/{EodashItemFilter-CmZkk7GK.js → EodashItemFilter-CgdrG-pX.js} +2 -2
  18. package/dist/client/{EodashLayerControl-D54fY-bX.js → EodashLayerControl-V98fahVJ.js} +2 -2
  19. package/dist/client/{EodashLayoutSwitcher-BCP3FvDb.js → EodashLayoutSwitcher-B4oI5PAx.js} +3 -3
  20. package/dist/client/EodashMapBtns-Ce2tFjJK.js +433 -0
  21. package/dist/client/{EodashStacInfo-BZbmT8vT.js → EodashStacInfo-Cb28jVEr.js} +11 -15
  22. package/dist/client/{EodashTimeSlider-DIcAJr6D.js → EodashTimeSlider-B5boxpCK.js} +2 -2
  23. package/dist/client/{EodashTools-Cz6X6hsF.js → EodashTools-RwiXxELa.js} +4 -4
  24. package/dist/client/{ExportState-DFVFAgKz.js → ExportState-Cp4ftu4f.js} +46 -21
  25. package/dist/client/{Footer-DLzQcjkI.js → Footer-xGfh2LUv.js} +1 -1
  26. package/dist/client/{Header-_D9Z-zFJ.js → Header-BggV8BVC.js} +127 -17
  27. package/dist/client/MobileLayout-BwXCBKFL.js +118 -0
  28. package/dist/client/{PopUp-DwI8V2gW.js → PopUp-C6x6Rpv0.js} +8 -59
  29. package/dist/client/{ProcessList-C9eAg2Sb.js → ProcessList-DDwo71cD.js} +9 -13
  30. package/dist/client/{VImg-COXTnCWE.js → VImg-DN23k6uX.js} +2 -2
  31. package/dist/client/{VMain-C74l1bv-.js → VMain-BT2ZxPLy.js} +1 -1
  32. package/dist/client/{VTooltip-BLS-cQ9N.js → VTooltip-CAkym6KY.js} +3 -4
  33. package/dist/client/{WidgetsContainer-D-VfMRxE.js → WidgetsContainer-CLYZgRgc.js} +1 -1
  34. package/dist/client/asWebComponent-C5YMrXyg.js +9206 -0
  35. package/dist/client/{async-D4G-FOIc.js → async-DHmiD7O-.js} +6 -8
  36. package/dist/client/eo-dash.js +1 -1
  37. package/dist/client/{forwardRefs-CRMFoNYN.js → forwardRefs-YqjFe8WZ.js} +196 -37
  38. package/dist/client/{handling-DTAhQuPh.js → handling-DRaAJMSG.js} +93 -53
  39. package/dist/client/{helpers-CsjKHAcK.js → helpers-Bi-qmnbZ.js} +188 -87
  40. package/dist/client/{index-BoCcZ0l4.js → index-BtY2y1sL.js} +15 -16
  41. package/dist/client/{index-DEmHaCL3.js → index-D4GBjamF.js} +5 -3
  42. package/dist/client/{index-BIcmbjr0.js → index-DYLTaaU8.js} +27 -14
  43. package/dist/client/{index-BHilH1qx.js → index-bSHJLUNu.js} +30 -73
  44. package/dist/client/templates.js +64 -5
  45. package/dist/client/{transition-6MJLK-_H.js → transition-C4YbXuIb.js} +1 -1
  46. package/dist/node/cli.js +1 -1
  47. package/dist/types/core/client/App.vue.d.ts +16 -6
  48. package/dist/types/core/client/asWebComponent.d.ts +2 -2
  49. package/dist/types/core/client/components/DashboardLayout.vue.d.ts +2 -1
  50. package/dist/types/core/client/components/DynamicWebComponent.vue.d.ts +36 -16
  51. package/dist/types/core/client/components/EodashOverlay.vue.d.ts +2 -1
  52. package/dist/types/core/client/components/ErrorAlert.vue.d.ts +9 -1
  53. package/dist/types/core/client/components/Footer.vue.d.ts +2 -1
  54. package/dist/types/core/client/components/Header.vue.d.ts +2 -1
  55. package/dist/types/core/client/components/IframeWrapper.vue.d.ts +12 -6
  56. package/dist/types/core/client/components/Loading.vue.d.ts +2 -1
  57. package/dist/types/core/client/components/MobileLayout.vue.d.ts +2 -1
  58. package/dist/types/core/client/eodashSTAC/helpers.d.ts +2 -0
  59. package/dist/types/core/client/store/actions.d.ts +1 -2
  60. package/dist/types/core/client/store/states.d.ts +22 -4
  61. package/dist/types/core/client/types.d.ts +6 -1
  62. package/dist/types/core/client/utils/index.d.ts +1 -0
  63. package/dist/types/core/client/views/Dashboard.vue.d.ts +20 -8
  64. package/dist/types/templates/compare.d.ts +20 -0
  65. package/dist/types/templates/expert.d.ts +30 -1
  66. package/dist/types/widgets/EodashChart.vue.d.ts +28 -0
  67. package/dist/types/widgets/EodashDatePicker.vue.d.ts +38 -9
  68. package/dist/types/widgets/EodashItemCatalog/index.vue.d.ts +88 -13
  69. package/dist/types/widgets/EodashItemCatalog/methods/map.d.ts +1 -1
  70. package/dist/types/widgets/EodashItemFilter.vue.d.ts +169 -26
  71. package/dist/types/widgets/EodashLayerControl.vue.d.ts +38 -10
  72. package/dist/types/widgets/EodashLayoutSwitcher.vue.d.ts +22 -7
  73. package/dist/types/widgets/EodashMap/EodashMapBtns.vue.d.ts +94 -21
  74. package/dist/types/widgets/EodashMap/index.vue.d.ts +646 -93
  75. package/dist/types/widgets/EodashMap/methods/btns.d.ts +14 -0
  76. package/dist/types/widgets/EodashProcess/ProcessList.vue.d.ts +24 -7
  77. package/dist/types/widgets/EodashProcess/index.vue.d.ts +26 -7
  78. package/dist/types/widgets/EodashProcess/methods/composables.d.ts +1 -2
  79. package/dist/types/widgets/EodashProcess/methods/handling.d.ts +9 -14
  80. package/dist/types/widgets/EodashProcess/methods/outputs.d.ts +2 -2
  81. package/dist/types/widgets/EodashProcess/methods/utils.d.ts +2 -2
  82. package/dist/types/widgets/EodashStacInfo.vue.d.ts +67 -18
  83. package/dist/types/widgets/EodashTimeSlider.vue.d.ts +14 -6
  84. package/dist/types/widgets/EodashTools.vue.d.ts +437 -47
  85. package/dist/types/widgets/ExportState.vue.d.ts +26 -8
  86. package/dist/types/widgets/PopUp.vue.d.ts +61 -11
  87. package/dist/types/widgets/WidgetsContainer.vue.d.ts +22 -6
  88. package/package.json +33 -34
  89. package/templates/baseConfig.js +14 -0
  90. package/templates/compare.js +30 -3
  91. package/templates/expert.js +20 -2
  92. package/templates/lite.js +1 -1
  93. package/widgets/EodashChart.vue +139 -0
  94. package/widgets/EodashDatePicker.vue +5 -2
  95. package/widgets/EodashItemCatalog/index.vue +2 -2
  96. package/widgets/EodashItemCatalog/methods/map.js +9 -10
  97. package/widgets/EodashMap/EodashMapBtns.vue +58 -93
  98. package/widgets/EodashMap/index.vue +10 -2
  99. package/widgets/EodashMap/methods/btns.js +155 -0
  100. package/widgets/EodashMap/methods/create-layers-config.js +3 -3
  101. package/widgets/EodashMap/methods/index.js +2 -1
  102. package/widgets/EodashProcess/ProcessList.vue +2 -3
  103. package/widgets/EodashProcess/index.vue +24 -63
  104. package/widgets/EodashProcess/methods/async.js +1 -1
  105. package/widgets/EodashProcess/methods/composables.js +1 -6
  106. package/widgets/EodashProcess/methods/custom-endpoints/chart/veda-endpoint.js +10 -6
  107. package/widgets/EodashProcess/methods/handling.js +42 -40
  108. package/widgets/EodashProcess/methods/outputs.js +44 -4
  109. package/widgets/EodashProcess/methods/utils.js +3 -5
  110. package/widgets/EodashStacInfo.vue +10 -23
  111. package/widgets/ExportState.vue +9 -15
  112. package/dist/client/EodashMapBtns-D-HulIl1.js +0 -306
  113. package/dist/client/MobileLayout-3Ko9XSfO.js +0 -118
  114. package/dist/client/asWebComponent-Bw03Jutr.js +0 -9090
@@ -1,5 +1,5 @@
1
- import { s as getCompareLayers, q as getLayers, W as replaceLayer, b as extractLayerConfig, x as extractLayerLegend, m as mergeGeojsons, d as axios, X as axios$1, I as compareIndicator, G as indicator } from './helpers-CsjKHAcK.js';
2
- import { P as useEmitLayersUpdate } from './asWebComponent-Bw03Jutr.js';
1
+ import { x as getCompareLayers, w as getLayers, $ as replaceLayer, b as extractLayerConfig, v as extractLayerLegend, m as mergeGeojsons, d as axios, a0 as axios$1, I as compareIndicator, G as indicator } from './helpers-Bi-qmnbZ.js';
2
+ import { P as useEmitLayersUpdate } from './asWebComponent-C5YMrXyg.js';
3
3
  import { isMulti } from '@eox/jsonform/src/custom-inputs/spatial/utils';
4
4
  import log from 'loglevel';
5
5
 
@@ -537,7 +537,7 @@ const applyProcessLayersToMap = (mapElement, processLayers) => {
537
537
  (l) => l.properties?.id === layer.properties?.id,
538
538
  );
539
539
  if (!exists) {
540
- analysisGroup.layers.unshift(layer);
540
+ analysisGroup.layers.push(layer);
541
541
  } else {
542
542
  analysisGroup.layers = replaceLayer(
543
543
  analysisGroup.layers,
@@ -558,7 +558,7 @@ const applyProcessLayersToMap = (mapElement, processLayers) => {
558
558
  };
559
559
  /**
560
560
  * Updates the jsonform schema to target the compare map
561
- * @param {import("json-schema").JSONSchema7 | null | undefined} jsonformSchema
561
+ * @param {Record<string,any> | null | undefined} jsonformSchema
562
562
  */
563
563
  function updateJsonformSchemaTarget(jsonformSchema) {
564
564
  if (!jsonformSchema) {
@@ -568,9 +568,7 @@ function updateJsonformSchemaTarget(jsonformSchema) {
568
568
  "eox-map#main",
569
569
  "eox-map#compare",
570
570
  );
571
- return /** @type {import("json-schema").JSONSchema7} */ (
572
- JSON.parse(stringified)
573
- );
571
+ return JSON.parse(stringified);
574
572
  }
575
573
 
576
574
  /**
@@ -679,7 +677,7 @@ async function updateJobsStatus(jobs, indicator) {
679
677
  new Date(a.job_start_datetime).getTime()
680
678
  );
681
679
  });
682
- jobs.value = jobResults;
680
+ jobs.value.splice(0, jobs.value.length, ...jobResults);
683
681
  }
684
682
 
685
683
  /**
@@ -1,2 +1,2 @@
1
- export { aI as EodashConstructor, aH as register, aJ as store } from './asWebComponent-Bw03Jutr.js';
1
+ export { aJ as EodashConstructor, aI as register, aK as store } from './asWebComponent-C5YMrXyg.js';
2
2
  import 'vue';
@@ -1,17 +1,18 @@
1
- import { computed, watch, onScopeDispose, nextTick, ref, watchEffect, effectScope, inject, mergeProps, shallowRef, onMounted, toRef, reactive, provide, toValue, toRaw, readonly, warn, onBeforeUnmount, createElementVNode, Fragment, createVNode, Teleport, withDirectives, vShow, Transition } from 'vue';
2
- import { ar as isOn, as as eventName, p as propsFactory, at as destructComputed, au as parseAnchor, av as flipSide, aw as flipAlign, ax as flipCorner, ay as CircularBuffer, az as deepEqual, X as consoleError, aA as getAxis, o as convertToUnit, v as clamp, ao as IN_BROWSER, y as useToggleScope, aB as defer, ak as getCurrentInstance, aC as templateRef, aD as matchesSelector, D as useDisplay, q as makeThemeProps, d as makeDimensionProps, e as makeComponentProps, g as genericComponent, x as useProxiedModel, k as provideTheme, l as useRtl, f as useBackgroundColor, b as useDimension, aE as useRouter, aF as useBackButton, an as standardEasing, c as useRender } from './asWebComponent-Bw03Jutr.js';
3
- import { m as makeTransitionProps, M as MaybeTransition } from './transition-6MJLK-_H.js';
1
+ import { computed, watch, onScopeDispose, nextTick, ref, watchEffect, effectScope, inject, mergeProps, toRef, toValue, shallowRef, onMounted, reactive, provide, toRaw, readonly, warn, onBeforeUnmount, createElementVNode, Fragment, createVNode, Teleport, withDirectives, vShow, Transition } from 'vue';
2
+ import { aq as isOn, ar as eventName, p as propsFactory, as as destructComputed, at as parseAnchor, au as flipSide, av as flipAlign, aw as flipCorner, ax as CircularBuffer, ay as deepEqual, Y as consoleError, az as getAxis, o as convertToUnit, v as clamp, aA as IN_BROWSER, y as useToggleScope, aB as defer, al as getCurrentInstance, aC as templateRef, aD as matchesSelector, aE as focusableChildren, D as useDisplay, q as makeThemeProps, d as makeDimensionProps, e as makeComponentProps, g as genericComponent, $ as omit, x as useProxiedModel, k as provideTheme, l as useRtl, f as useBackgroundColor, b as useDimension, aF as useRouter, aG as useBackButton, ao as standardEasing, c as useRender } from './asWebComponent-C5YMrXyg.js';
3
+ import { m as makeTransitionProps, M as MaybeTransition } from './transition-C4YbXuIb.js';
4
4
 
5
5
  class Box {
6
6
  constructor(args) {
7
7
  const pageScale = document.body.currentCSSZoom ?? 1;
8
- const factor = args instanceof DOMRect ? 1 + (1 - pageScale) / pageScale : 1;
8
+ const isElement = args instanceof Element;
9
+ const factor = isElement ? 1 + (1 - pageScale) / pageScale : 1;
9
10
  const {
10
11
  x,
11
12
  y,
12
13
  width,
13
14
  height
14
- } = args;
15
+ } = isElement ? args.getBoundingClientRect() : args;
15
16
  this.x = x * factor;
16
17
  this.y = y * factor;
17
18
  this.width = width * factor;
@@ -53,7 +54,7 @@ function getTargetBox(target) {
53
54
  height: 0 * factor
54
55
  });
55
56
  } else {
56
- return new Box(target.getBoundingClientRect());
57
+ return new Box(target);
57
58
  }
58
59
  }
59
60
  function getElementBox(el) {
@@ -75,20 +76,14 @@ function getElementBox(el) {
75
76
  });
76
77
  }
77
78
  } else {
78
- const rect = el.getBoundingClientRect();
79
- return new Box({
80
- x: rect.x,
81
- y: rect.y,
82
- width: el.clientWidth,
83
- height: el.clientHeight
84
- });
79
+ return new Box(el);
85
80
  }
86
81
  }
87
82
 
88
83
  // Utilities
89
84
  /** @see https://stackoverflow.com/a/57876601/2074736 */
90
85
  function nullifyTransforms(el) {
91
- const rect = new Box(el.getBoundingClientRect());
86
+ const rect = new Box(el);
92
87
  const style = getComputedStyle(el);
93
88
  const tx = style.transform;
94
89
  if (tx) {
@@ -418,7 +413,11 @@ const makeLocationStrategyProps = propsFactory({
418
413
  default: 'auto'
419
414
  },
420
415
  offset: [Number, String, Array],
421
- stickToTarget: Boolean
416
+ stickToTarget: Boolean,
417
+ viewportMargin: {
418
+ type: [Number, String],
419
+ default: 12
420
+ }
422
421
  }, 'VOverlay-location-strategies');
423
422
  function useLocationStrategies(props, data) {
424
423
  const contentStyles = ref({});
@@ -605,7 +604,7 @@ function connectedLocationStrategy(data, props, contentStyles) {
605
604
 
606
605
  const contentBox = getIntrinsicSize(data.contentEl.value, data.isRtl.value);
607
606
  const scrollParents = getScrollParents(data.contentEl.value);
608
- const viewportMargin = 12;
607
+ const viewportMargin = Number(props.viewportMargin);
609
608
  if (!scrollParents.length) {
610
609
  scrollParents.push(document.documentElement);
611
610
  if (!(data.contentEl.value.style.top && data.contentEl.value.style.left)) {
@@ -625,10 +624,17 @@ function connectedLocationStrategy(data, props, contentStyles) {
625
624
  }
626
625
  return scrollBox;
627
626
  }, undefined);
628
- viewport.x += viewportMargin;
629
- viewport.y += viewportMargin;
630
- viewport.width -= viewportMargin * 2;
631
- viewport.height -= viewportMargin * 2;
627
+ if (props.stickToTarget) {
628
+ viewport.x += Math.min(viewportMargin, targetBox.x);
629
+ viewport.y += Math.min(viewportMargin, targetBox.y);
630
+ viewport.width = Math.max(viewport.width - viewportMargin * 2, targetBox.x + targetBox.width - viewportMargin);
631
+ viewport.height = Math.max(viewport.height - viewportMargin * 2, targetBox.y + targetBox.height - viewportMargin);
632
+ } else {
633
+ viewport.x += viewportMargin;
634
+ viewport.y += viewportMargin;
635
+ viewport.width -= viewportMargin * 2;
636
+ viewport.height -= viewportMargin * 2;
637
+ }
632
638
  let placement = {
633
639
  anchor: preferredAnchor.value,
634
640
  origin: preferredOrigin.value
@@ -739,19 +745,19 @@ function connectedLocationStrategy(data, props, contentStyles) {
739
745
 
740
746
  // shift
741
747
  if (overflows.x.before) {
742
- if (!props.stickToTarget) x += overflows.x.before;
748
+ x += overflows.x.before;
743
749
  contentBox.x += overflows.x.before;
744
750
  }
745
751
  if (overflows.x.after) {
746
- if (!props.stickToTarget) x -= overflows.x.after;
752
+ x -= overflows.x.after;
747
753
  contentBox.x -= overflows.x.after;
748
754
  }
749
755
  if (overflows.y.before) {
750
- if (!props.stickToTarget) y += overflows.y.before;
756
+ y += overflows.y.before;
751
757
  contentBox.y += overflows.y.before;
752
758
  }
753
759
  if (overflows.y.after) {
754
- if (!props.stickToTarget) y -= overflows.y.after;
760
+ y -= overflows.y.after;
755
761
  contentBox.y -= overflows.y.after;
756
762
  }
757
763
 
@@ -760,9 +766,9 @@ function connectedLocationStrategy(data, props, contentStyles) {
760
766
  const overflows = getOverflow(contentBox, viewport);
761
767
  available.x = viewport.width - overflows.x.before - overflows.x.after;
762
768
  available.y = viewport.height - overflows.y.before - overflows.y.after;
763
- if (!props.stickToTarget) x += overflows.x.before;
769
+ x += overflows.x.before;
764
770
  contentBox.x += overflows.x.before;
765
- if (!props.stickToTarget) y += overflows.y.before;
771
+ y += overflows.y.before;
766
772
  contentBox.y += overflows.y.before;
767
773
  }
768
774
  break;
@@ -985,11 +991,12 @@ const makeDelayProps = propsFactory({
985
991
  }, 'delay');
986
992
  function useDelay(props, cb) {
987
993
  let clearDelay = () => {};
988
- function runDelay(isOpening) {
994
+ function runDelay(isOpening, options) {
989
995
  clearDelay?.();
990
- const delay = Number(isOpening ? props.openDelay : props.closeDelay);
996
+ const delay = isOpening ? props.openDelay : props.closeDelay;
997
+ const normalizedDelay = Math.max(options?.minDelay ?? 0, Number(delay ?? 0));
991
998
  return new Promise(resolve => {
992
- clearDelay = defer(delay, () => {
999
+ clearDelay = defer(normalizedDelay, () => {
993
1000
  cb?.(isOpening);
994
1001
  resolve(isOpening);
995
1002
  });
@@ -998,8 +1005,8 @@ function useDelay(props, cb) {
998
1005
  function runOpenDelay() {
999
1006
  return runDelay(true);
1000
1007
  }
1001
- function runCloseDelay() {
1002
- return runDelay(false);
1008
+ function runCloseDelay(options) {
1009
+ return runDelay(false, options);
1003
1010
  }
1004
1011
  return {
1005
1012
  clearDelay,
@@ -1063,7 +1070,6 @@ function useActivator(props, _ref) {
1063
1070
  isActive.value = !isActive.value;
1064
1071
  },
1065
1072
  onMouseenter: e => {
1066
- if (e.sourceCapabilities?.firesTouchEvents) return;
1067
1073
  isHovered = true;
1068
1074
  activatorEl.value = e.currentTarget || e.target;
1069
1075
  runOpenDelay();
@@ -1082,7 +1088,9 @@ function useActivator(props, _ref) {
1082
1088
  onBlur: e => {
1083
1089
  isFocused = false;
1084
1090
  e.stopPropagation();
1085
- runCloseDelay();
1091
+ runCloseDelay({
1092
+ minDelay: 1
1093
+ });
1086
1094
  }
1087
1095
  };
1088
1096
  const activatorEvents = computed(() => {
@@ -1113,13 +1121,16 @@ function useActivator(props, _ref) {
1113
1121
  };
1114
1122
  }
1115
1123
  if (openOnFocus.value) {
1116
- events.onFocusin = () => {
1124
+ events.onFocusin = e => {
1125
+ if (!e.target.matches(':focus-visible')) return;
1117
1126
  isFocused = true;
1118
1127
  runOpenDelay();
1119
1128
  };
1120
1129
  events.onFocusout = () => {
1121
1130
  isFocused = false;
1122
- runCloseDelay();
1131
+ runCloseDelay({
1132
+ minDelay: 1
1133
+ });
1123
1134
  };
1124
1135
  }
1125
1136
  if (props.closeOnContentClick) {
@@ -1274,6 +1285,148 @@ function getTarget(selector, vm) {
1274
1285
  return target;
1275
1286
  }
1276
1287
 
1288
+ // Utilities
1289
+ // Types
1290
+ // Composables
1291
+ const makeFocusTrapProps = propsFactory({
1292
+ retainFocus: Boolean,
1293
+ captureFocus: Boolean,
1294
+ /** @deprecated */
1295
+ disableInitialFocus: Boolean
1296
+ }, 'focusTrap');
1297
+ const registry = new Map();
1298
+ let subscribers = 0;
1299
+ function onKeydown(e) {
1300
+ const activeElement = document.activeElement;
1301
+ if (e.key !== 'Tab' || !activeElement) return;
1302
+ const parentTraps = Array.from(registry.values()).filter(_ref => {
1303
+ let {
1304
+ isActive,
1305
+ contentEl
1306
+ } = _ref;
1307
+ return isActive.value && contentEl.value?.contains(activeElement);
1308
+ }).map(x => x.contentEl.value);
1309
+ let closestTrap;
1310
+ let currentParent = activeElement.parentElement;
1311
+ while (currentParent) {
1312
+ if (parentTraps.includes(currentParent)) {
1313
+ closestTrap = currentParent;
1314
+ break;
1315
+ }
1316
+ currentParent = currentParent.parentElement;
1317
+ }
1318
+ if (!closestTrap) return;
1319
+ const focusable = focusableChildren(closestTrap)
1320
+ // excluding VListItems with tabindex="-2"
1321
+ .filter(x => x.tabIndex >= 0);
1322
+ if (!focusable.length) return;
1323
+ const active = document.activeElement;
1324
+ if (focusable.length === 1 && focusable[0].classList.contains('v-list') && focusable[0].contains(active)) {
1325
+ e.preventDefault();
1326
+ return;
1327
+ }
1328
+ const firstElement = focusable[0];
1329
+ const lastElement = focusable[focusable.length - 1];
1330
+ if (e.shiftKey && (active === firstElement || firstElement.classList.contains('v-list') && firstElement.contains(active))) {
1331
+ e.preventDefault();
1332
+ lastElement.focus();
1333
+ }
1334
+ if (!e.shiftKey && (active === lastElement || lastElement.classList.contains('v-list') && lastElement.contains(active))) {
1335
+ e.preventDefault();
1336
+ firstElement.focus();
1337
+ }
1338
+ }
1339
+ function useFocusTrap(props, _ref2) {
1340
+ let {
1341
+ isActive,
1342
+ localTop,
1343
+ contentEl
1344
+ } = _ref2;
1345
+ const trapId = Symbol('trap');
1346
+ let focusTrapSuppressed = false;
1347
+ let focusTrapSuppressionTimeout = -1;
1348
+ async function onPointerdown() {
1349
+ focusTrapSuppressed = true;
1350
+ focusTrapSuppressionTimeout = window.setTimeout(() => {
1351
+ focusTrapSuppressed = false;
1352
+ }, 100);
1353
+ }
1354
+ async function captureOnFocus(e) {
1355
+ const before = e.relatedTarget;
1356
+ const after = e.target;
1357
+ document.removeEventListener('pointerdown', onPointerdown);
1358
+ document.removeEventListener('keydown', captureOnKeydown);
1359
+ await nextTick();
1360
+ if (isActive.value && !focusTrapSuppressed && before !== after && contentEl.value &&
1361
+ // We're the menu without open submenus or overlays
1362
+ toValue(localTop) &&
1363
+ // It isn't the document or the container body
1364
+ ![document, contentEl.value].includes(after) &&
1365
+ // It isn't inside the container body
1366
+ !contentEl.value.contains(after)) {
1367
+ const focusable = focusableChildren(contentEl.value);
1368
+ focusable[0]?.focus();
1369
+ }
1370
+ }
1371
+ function captureOnKeydown(e) {
1372
+ if (e.key !== 'Tab') return;
1373
+ document.removeEventListener('keydown', captureOnKeydown);
1374
+ if (isActive.value && contentEl.value && e.target && !contentEl.value.contains(e.target)) {
1375
+ const allFocusableElements = focusableChildren(document.documentElement);
1376
+ if (e.shiftKey && e.target === allFocusableElements.at(0) || !e.shiftKey && e.target === allFocusableElements.at(-1)) {
1377
+ const focusable = focusableChildren(contentEl.value);
1378
+ if (focusable.length > 0) {
1379
+ e.preventDefault();
1380
+ focusable[0].focus();
1381
+ }
1382
+ }
1383
+ }
1384
+ }
1385
+ const shouldCapture = toRef(() => isActive.value && props.captureFocus && !props.disableInitialFocus);
1386
+ if (IN_BROWSER) {
1387
+ watch(() => props.retainFocus, val => {
1388
+ if (val) {
1389
+ registry.set(trapId, {
1390
+ isActive,
1391
+ contentEl
1392
+ });
1393
+ } else {
1394
+ registry.delete(trapId);
1395
+ }
1396
+ }, {
1397
+ immediate: true
1398
+ });
1399
+ watch(shouldCapture, val => {
1400
+ if (val) {
1401
+ document.addEventListener('pointerdown', onPointerdown);
1402
+ document.addEventListener('focusin', captureOnFocus, {
1403
+ once: true
1404
+ });
1405
+ document.addEventListener('keydown', captureOnKeydown);
1406
+ } else {
1407
+ document.removeEventListener('pointerdown', onPointerdown);
1408
+ document.removeEventListener('focusin', captureOnFocus);
1409
+ document.removeEventListener('keydown', captureOnKeydown);
1410
+ }
1411
+ }, {
1412
+ immediate: true
1413
+ });
1414
+ if (subscribers++ < 1) {
1415
+ document.addEventListener('keydown', onKeydown);
1416
+ }
1417
+ }
1418
+ onScopeDispose(() => {
1419
+ registry.delete(trapId);
1420
+ clearTimeout(focusTrapSuppressionTimeout);
1421
+ document.removeEventListener('pointerdown', onPointerdown);
1422
+ document.removeEventListener('focusin', captureOnFocus);
1423
+ document.removeEventListener('keydown', captureOnKeydown);
1424
+ if (--subscribers < 1) {
1425
+ document.removeEventListener('keydown', onKeydown);
1426
+ }
1427
+ });
1428
+ }
1429
+
1277
1430
  // Composables
1278
1431
  function useHydration() {
1279
1432
  if (!IN_BROWSER) return shallowRef(false);
@@ -1432,6 +1585,7 @@ const makeVOverlayProps = propsFactory({
1432
1585
  ...makeLazyProps(),
1433
1586
  ...makeLocationStrategyProps(),
1434
1587
  ...makeScrollStrategyProps(),
1588
+ ...makeFocusTrapProps(),
1435
1589
  ...makeThemeProps(),
1436
1590
  ...makeTransitionProps()
1437
1591
  }, 'VOverlay');
@@ -1443,7 +1597,7 @@ const VOverlay = genericComponent()({
1443
1597
  inheritAttrs: false,
1444
1598
  props: {
1445
1599
  _disableGlobalStack: Boolean,
1446
- ...makeVOverlayProps()
1600
+ ...omit(makeVOverlayProps(), ['disableInitialFocus'])
1447
1601
  },
1448
1602
  emits: {
1449
1603
  'click:outside': e => true,
@@ -1543,10 +1697,14 @@ const VOverlay = genericComponent()({
1543
1697
  if (!props.persistent) isActive.value = false;else animateClick();
1544
1698
  }
1545
1699
  function closeConditional(e) {
1546
- return isActive.value && globalTop.value && (
1700
+ return isActive.value && localTop.value && (
1547
1701
  // If using scrim, only close if clicking on it rather than anything opened on top
1548
1702
  !props.scrim || e.target === scrimEl.value || e instanceof MouseEvent && e.shadowTarget === scrimEl.value);
1549
1703
  }
1704
+ useFocusTrap(props, {
1705
+ isActive,
1706
+ localTop,
1707
+ contentEl});
1550
1708
  IN_BROWSER && watch(isActive, val => {
1551
1709
  if (val) {
1552
1710
  window.addEventListener('keydown', onKeydown);
@@ -1672,6 +1830,7 @@ const VOverlay = genericComponent()({
1672
1830
  target,
1673
1831
  animateClick,
1674
1832
  contentEl,
1833
+ rootEl: root,
1675
1834
  globalTop,
1676
1835
  localTop,
1677
1836
  updateLocation