@geode/opengeodeweb-front 10.14.1 → 10.14.2-rc.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.
@@ -1,20 +1,68 @@
1
1
  <script setup>
2
+ import { useHybridViewerStore } from "@ogw_front/stores/hybrid_viewer";
3
+
2
4
  const SCROLL_SYNC_DELAY = 50;
3
5
  const SCROLL_THRESHOLD = 1;
4
6
  const { title, closable, icon, mdiIcon, scrollTop } = defineProps({
5
7
  title: { type: String, required: true },
6
- closable: { type: Boolean, default: false },
7
- icon: { type: String, default: "" },
8
- mdiIcon: { type: String, default: "" },
9
- scrollTop: { type: Number, default: 0 },
8
+ closable: { type: Boolean, required: false, default: false },
9
+ icon: { type: String, required: false, default: "" },
10
+ mdiIcon: { type: String, required: false, default: "" },
11
+ scrollTop: { type: Number, required: false, default: 0 },
10
12
  });
11
-
12
13
  const emit = defineEmits(["close", "dragstart", "update:scrollTop"]);
13
14
 
14
- const scrollContainer = ref(undefined);
15
+ const scrollContainer = useTemplateRef("scroll-container");
16
+ const treeviewBox = useTemplateRef("treeview-box");
17
+ const hybridViewerStore = useHybridViewerStore();
18
+
19
+ const LUMINANCE_THRESHOLD = 0.65;
20
+ const ADAPTIVE_EXPONENT = 0.3;
21
+
22
+ const MIN_BLUR = 8;
23
+ const MAX_BLUR = 25;
24
+
25
+ const MIN_OPACITY = 0;
26
+ const MAX_OPACITY = 0.5;
27
+
28
+ const MIN_BOOST = 1;
29
+ const MAX_BOOST = 1.2;
30
+ const ADAPTIVE_REFRESH_RATE = 150;
31
+
32
+ const { x, y, width, height } = useElementBounding(treeviewBox);
33
+ const brightness = ref(LUMINANCE_THRESHOLD);
34
+
35
+ const updateBrightness = useThrottleFn(() => {
36
+ brightness.value = hybridViewerStore.getAverageBrightness({
37
+ x: x.value,
38
+ y: y.value,
39
+ width: width.value,
40
+ height: height.value,
41
+ });
42
+ }, ADAPTIVE_REFRESH_RATE);
43
+
15
44
  let isApplyingScroll = false;
16
45
  let resizeObserver = undefined;
17
46
 
47
+ watch([x, y, width, height, () => hybridViewerStore.latestImage], updateBrightness, {
48
+ immediate: true,
49
+ });
50
+
51
+ const adaptiveStyles = computed(() => {
52
+ const normalized = Math.min(1, brightness.value / LUMINANCE_THRESHOLD);
53
+ const darkFactor = (1 - normalized) ** ADAPTIVE_EXPONENT;
54
+
55
+ const blur = MIN_BLUR + darkFactor * (MAX_BLUR - MIN_BLUR);
56
+ const opacity = MIN_OPACITY + darkFactor * (MAX_OPACITY - MIN_OPACITY);
57
+ const brightnessBoost = MIN_BOOST + darkFactor * (MAX_BOOST - MIN_BOOST);
58
+
59
+ return {
60
+ "--adaptive-blur": `${blur}px`,
61
+ "--adaptive-opacity": opacity,
62
+ "--adaptive-brightness": brightnessBoost,
63
+ };
64
+ });
65
+
18
66
  function handleScroll(event) {
19
67
  if (isApplyingScroll) {
20
68
  return;
@@ -69,7 +117,12 @@ watch(
69
117
  </script>
70
118
 
71
119
  <template>
72
- <v-card variant="outlined" class="tree-box d-flex flex-column">
120
+ <v-card
121
+ ref="treeview-box"
122
+ variant="outlined"
123
+ class="tree-box d-flex flex-column"
124
+ :style="adaptiveStyles"
125
+ >
73
126
  <v-card-title
74
127
  class="tree-box-header d-flex align-center"
75
128
  :class="{ 'cursor-grab': closable }"
@@ -89,7 +142,15 @@ watch(
89
142
  <v-icon v-else-if="closable" size="24" class="mr-2">mdi-drag-variant</v-icon>
90
143
  <span
91
144
  class="text-subtitle-2 font-weight-bold d-inline-flex align-center"
92
- style="height: 24px; line-height: 1"
145
+ style="
146
+ height: 24px;
147
+ line-height: 1;
148
+ overflow: hidden;
149
+ text-overflow: ellipsis;
150
+ white-space: nowrap;
151
+ flex-shrink: 1;
152
+ min-width: 0;
153
+ "
93
154
  >
94
155
  {{ title }}
95
156
  </span>
@@ -103,10 +164,11 @@ watch(
103
164
  />
104
165
  </v-card-title>
105
166
  <v-divider />
106
- <v-card-text class="pa-0 flex-grow-1 overflow-hidden d-flex flex-column">
167
+ <v-card-text class="pa-0 flex-grow-1 overflow-hidden d-flex flex-column" style="min-height: 0">
107
168
  <div
108
- ref="scrollContainer"
109
- class="flex-grow-1 overflow-y-auto overflow-x-hidden"
169
+ ref="scroll-container"
170
+ class="flex-grow-1 overflow-y-hidden overflow-x-hidden d-flex flex-column"
171
+ style="min-height: 0"
110
172
  @scroll="handleScroll"
111
173
  >
112
174
  <slot />
@@ -118,15 +180,44 @@ watch(
118
180
  <style scoped>
119
181
  .tree-box {
120
182
  height: 100%;
183
+ min-height: 0;
121
184
  border-radius: 16px;
122
185
  background-color: transparent !important;
123
- backdrop-filter: blur(2px);
124
- border: 1px solid rgba(0, 0, 0, 0.2);
186
+ border: 1px solid rgba(255, 255, 255, 0.2) !important;
187
+ box-shadow: 0 4px 15px rgba(0, 0, 0, 0.05);
188
+ position: relative;
189
+ overflow: hidden;
190
+ transition:
191
+ background-color 0.3s ease,
192
+ backdrop-filter 0.3s ease;
193
+ }
194
+
195
+ .tree-box::before {
196
+ content: "";
197
+ position: absolute;
198
+ inset: 0;
199
+ background: rgba(255, 255, 255, var(--adaptive-opacity));
200
+ backdrop-filter: blur(var(--adaptive-blur)) brightness(var(--adaptive-brightness));
201
+ -webkit-backdrop-filter: blur(var(--adaptive-blur)) brightness(var(--adaptive-brightness));
202
+ mix-blend-mode: lighten;
203
+ z-index: 0;
204
+ pointer-events: none;
205
+ border-radius: inherit;
206
+ transition:
207
+ background-color 0.3s ease,
208
+ backdrop-filter 0.3s ease;
209
+ }
210
+
211
+ .tree-box > * {
212
+ position: relative;
213
+ z-index: 1;
125
214
  }
126
215
 
127
216
  .tree-box-header {
128
217
  height: 40px !important;
129
- padding: 0 8px !important;
130
- background-color: rgba(255, 255, 255, 0.1);
218
+ padding: 0 12px !important;
219
+ background-color: rgba(255, 255, 255, 0.05);
220
+ border-bottom: 1px solid rgba(0, 0, 0, 0.05);
221
+ flex-shrink: 0;
131
222
  }
132
223
  </style>
@@ -48,7 +48,7 @@ watch(
48
48
  { immediate: true },
49
49
  );
50
50
 
51
- watch(maxWidth, (newMax) => {
51
+ watch([maxWidth, () => additionalViews.value.length], ([newMax]) => {
52
52
  const hasAdditional = additionalViews.value.length > 0;
53
53
  const gap = hasAdditional ? GAP_WIDTH : 0;
54
54
  const total =
@@ -143,20 +143,20 @@ function onVerticalResizeStart(event, index) {
143
143
  const deltaPercent = (deltaY / containerHeight) * PERCENT_100;
144
144
  const minHeightPercent = (HEIGHT_MIN / containerHeight) * PERCENT_100;
145
145
 
146
- let newH1 = startHeight1 + deltaPercent;
147
- let newH2 = startHeight2 - deltaPercent;
146
+ let newHeight1 = startHeight1 + deltaPercent;
147
+ let newHeight2 = startHeight2 - deltaPercent;
148
148
 
149
- if (newH1 < minHeightPercent) {
150
- newH1 = minHeightPercent;
151
- newH2 = startHeight1 + startHeight2 - minHeightPercent;
152
- } else if (newH2 < minHeightPercent) {
153
- newH2 = minHeightPercent;
154
- newH1 = startHeight1 + startHeight2 - minHeightPercent;
149
+ if (newHeight1 < minHeightPercent) {
150
+ newHeight1 = minHeightPercent;
151
+ newHeight2 = startHeight1 + startHeight2 - minHeightPercent;
152
+ } else if (newHeight2 < minHeightPercent) {
153
+ newHeight2 = minHeightPercent;
154
+ newHeight1 = startHeight1 + startHeight2 - minHeightPercent;
155
155
  }
156
156
 
157
157
  const newHeights = [...rowHeights.value];
158
- newHeights[index] = newH1;
159
- newHeights[index + 1] = newH2;
158
+ newHeights[index] = newHeight1;
159
+ newHeights[index + 1] = newHeight2;
160
160
  treeviewStore.setRowHeights(newHeights);
161
161
 
162
162
  document.body.style.userSelect = "none";
@@ -272,7 +272,7 @@ function onVerticalResizeStart(event, index) {
272
272
  display: flex;
273
273
  flex-direction: column;
274
274
  height: 100%;
275
- overflow-y: auto;
275
+ overflow-y: hidden;
276
276
  overflow-x: hidden;
277
277
  flex-shrink: 0;
278
278
  }
@@ -286,6 +286,8 @@ function onVerticalResizeStart(event, index) {
286
286
  }
287
287
 
288
288
  .view-wrapper {
289
+ display: flex;
290
+ flex-direction: column;
289
291
  overflow: hidden;
290
292
  padding: 2px;
291
293
  transition: transform 0.2s;
@@ -1,12 +1,13 @@
1
1
  <script setup>
2
+ import CommonTreeView from "@ogw_front/components/Viewer/ObjectTree/Base/CommonTreeView.vue";
2
3
  import ObjectTreeControls from "@ogw_front/components/Viewer/ObjectTree/Base/Controls.vue";
3
4
  import ObjectTreeItemLabel from "@ogw_front/components/Viewer/ObjectTree/Base/ItemLabel.vue";
4
5
  import { compareSelections } from "@ogw_front/utils/treeview";
5
6
  import { useDataStore } from "@ogw_front/stores/data";
6
7
  import { useDataStyleStore } from "@ogw_front/stores/data_style";
7
- import { useHoverhighlight } from "@ogw_front/composables/use_hover_highlight";
8
+ import { useHoverhighlight } from "@ogw_front/composables/hover_highlight";
8
9
  import { useHybridViewerStore } from "@ogw_front/stores/hybrid_viewer";
9
- import { useTreeFilter } from "@ogw_front/composables/use_tree_filter";
10
+ import { useTreeFilter } from "@ogw_front/composables/tree_filter";
10
11
  import { useTreeviewStore } from "@ogw_front/stores/treeview";
11
12
 
12
13
  const treeviewStore = useTreeviewStore();
@@ -32,7 +33,7 @@ const {
32
33
  toggleSort,
33
34
  customFilter,
34
35
  applySearchFilter,
35
- } = useTreeFilter(toRef(() => treeviewStore.items));
36
+ } = useTreeFilter(() => treeviewStore.items, { recursiveSort: true });
36
37
 
37
38
  function onUpdateSelection(val) {
38
39
  treeviewStore.selection = applySearchFilter(val, treeviewStore.selection);
@@ -74,18 +75,28 @@ function isModel(item) {
74
75
  );
75
76
  }
76
77
 
77
- async function handleHoverEnter(item) {
78
+ function handleHoverEnter({ item, immediate = false }) {
78
79
  const actualItem = item.raw || item;
79
- const is_model = isModel(item);
80
- let block_ids = [];
81
- if (is_model) {
82
- block_ids = await dataStore.getAllModelComponentsViewerIds(actualItem.id);
80
+
81
+ if (!actualItem.viewer_type) {
82
+ return;
83
83
  }
84
- onHoverEnter(actualItem.id, block_ids, is_model ? "model" : "mesh");
84
+
85
+ const is_model = isModel(item);
86
+
87
+ onHoverEnter(
88
+ actualItem.id,
89
+ async () => (is_model ? await dataStore.getAllModelComponentsViewerIds(actualItem.id) : []),
90
+ is_model ? "model" : "mesh",
91
+ immediate,
92
+ );
85
93
  }
86
94
 
87
- function handleHoverLeave(item) {
95
+ function handleHoverLeave({ item }) {
88
96
  const actualItem = item.raw || item;
97
+ if (!actualItem.viewer_type) {
98
+ return;
99
+ }
89
100
  onHoverLeave(actualItem.id);
90
101
  }
91
102
  </script>
@@ -98,26 +109,29 @@ function handleHoverLeave(item) {
98
109
  :filter-options="filterOptions"
99
110
  :available-filter-options="availableFilterOptions"
100
111
  @toggle-sort="toggleSort"
112
+ @collapse-all="opened = []"
101
113
  />
102
114
 
103
- <v-treeview
115
+ <CommonTreeView
104
116
  :selected="visibleSelection"
105
117
  v-model:opened="opened"
106
118
  :items="processedItems"
107
- :search="search"
108
- :custom-filter="customFilter"
109
- class="transparent-treeview"
110
- item-value="id"
111
- select-strategy="classic"
112
- selectable
113
- items-registration="props"
119
+ :options="{
120
+ selection: { selectable: true },
121
+ search,
122
+ customFilter,
123
+ }"
124
+ :scroll-top="mainView?.scrollTop || 0"
125
+ class="transparent-treeview virtual-tree-height"
114
126
  @update:selected="onUpdateSelection"
127
+ @update:scroll-top="treeviewStore.setScrollTop(mainView.id, $event)"
128
+ @hover:enter="handleHoverEnter"
129
+ @hover:leave="handleHoverLeave"
115
130
  >
116
- <template #title="{ item }">
131
+ <template #title="{ item, isLeaf }">
117
132
  <ObjectTreeItemLabel
118
133
  :item="item"
119
- @mouseenter="handleHoverEnter(item)"
120
- @mouseleave="handleHoverLeave(item)"
134
+ :is-leaf="isLeaf"
121
135
  @contextmenu="emit('show-menu', { event: $event, itemId: item.id })"
122
136
  />
123
137
  </template>
@@ -135,25 +149,26 @@ function handleHoverLeave(item) {
135
149
  "
136
150
  />
137
151
  </template>
138
- </v-treeview>
152
+ </CommonTreeView>
139
153
  </div>
140
154
  </template>
141
155
 
142
156
  <style scoped>
143
- .transparent-treeview {
144
- background-color: transparent;
145
- margin: 4px 0;
146
- }
147
-
148
- :deep(.v-list-item) {
149
- transition: background-color 0.2s ease;
157
+ .tree-view-container {
158
+ height: 100%;
159
+ display: flex;
160
+ flex-direction: column;
161
+ overflow: hidden;
162
+ min-height: 0;
150
163
  }
151
164
 
152
- :deep(.v-list-item--active > .v-list-item__overlay) {
153
- opacity: 0 !important;
165
+ .virtual-tree-height {
166
+ flex-grow: 1;
167
+ min-height: 0;
154
168
  }
155
169
 
156
- :deep(.v-list-item:hover > .v-list-item__overlay) {
157
- opacity: 0.1 !important;
170
+ .transparent-treeview {
171
+ background-color: transparent;
172
+ margin: 4px 0;
158
173
  }
159
174
  </style>
@@ -1,85 +1,113 @@
1
1
  <script setup>
2
+ import { sortAndFormatItems, useTreeFilter } from "@ogw_front/composables/tree_filter";
3
+ import CommonTreeView from "@ogw_front/components/Viewer/ObjectTree/Base/CommonTreeView.vue";
2
4
  import FetchingData from "@ogw_front/components/FetchingData.vue";
3
5
  import ObjectTreeControls from "@ogw_front/components/Viewer/ObjectTree/Base/Controls.vue";
4
6
  import ObjectTreeItemLabel from "@ogw_front/components/Viewer/ObjectTree/Base/ItemLabel.vue";
5
- import { compareSelections } from "@ogw_front/utils/treeview";
6
- import { useDataStore } from "@ogw_front/stores/data";
7
- import { useDataStyleStore } from "@ogw_front/stores/data_style";
8
- import { useHoverhighlight } from "@ogw_front/composables/use_hover_highlight";
9
- import { useHybridViewerStore } from "@ogw_front/stores/hybrid_viewer";
10
- import { useTreeFilter } from "@ogw_front/composables/use_tree_filter";
7
+ import { useHoverhighlight } from "@ogw_front/composables/hover_highlight";
8
+ import { useModelComponents } from "@ogw_front/composables/model_components";
11
9
  import { useTreeviewStore } from "@ogw_front/stores/treeview";
12
10
 
13
- const { id: viewId } = defineProps({ id: { type: String, required: true } });
11
+ const { id } = defineProps({ id: { type: String, required: true } });
14
12
  const { onHoverEnter, onHoverLeave } = useHoverhighlight();
15
13
  const emit = defineEmits(["show-menu"]);
16
14
 
17
- const dataStore = useDataStore();
18
- const dataStyleStore = useDataStyleStore();
19
- const hybridViewerStore = useHybridViewerStore();
20
15
  const treeviewStore = useTreeviewStore();
16
+ const {
17
+ items: rawItems,
18
+ componentsCache,
19
+ localCategories,
20
+ selection: visibleComponents,
21
+ updateVisibility,
22
+ } = useModelComponents(id);
23
+
24
+ const currentView = computed(() => treeviewStore.opened_views.find((view) => view.id === id));
21
25
 
22
- const currentView = computed(() => treeviewStore.opened_views.find((view) => view.id === viewId));
23
26
  const opened = computed({
24
27
  get: () => currentView.value?.opened || [],
25
- set: (val) => treeviewStore.setOpened(viewId, val),
28
+ set: (val) => treeviewStore.setOpened(id, val),
26
29
  });
27
30
 
28
- const items = dataStore.refFormatedMeshComponents(viewId);
29
- const mesh_components_selection = dataStyleStore.visibleMeshComponents(viewId);
30
-
31
31
  const {
32
32
  search,
33
33
  sortType,
34
34
  filterOptions,
35
- processedItems,
35
+ processedItems: filteredCategories,
36
36
  availableFilterOptions,
37
37
  toggleSort,
38
38
  customFilter,
39
39
  applySearchFilter,
40
- } = useTreeFilter(items);
40
+ } = useTreeFilter(localCategories);
41
41
 
42
- async function onSelectionChange(newSelection) {
43
- const current = applySearchFilter(newSelection, mesh_components_selection.value);
44
- const previous = mesh_components_selection.value;
45
- const { added, removed } = compareSelections(current, previous);
42
+ function onUpdateSelection(newSelection) {
43
+ const finalSelection = applySearchFilter(newSelection, visibleComponents.value);
44
+ updateVisibility(finalSelection);
45
+ }
46
46
 
47
- if (added.length === 0 && removed.length === 0) {
48
- return;
47
+ const visibleSelection = computed(() => applySearchFilter(visibleComponents.value, []));
48
+
49
+ const itemsForTreeView = computed(() => {
50
+ if (search.value && componentsCache.value) {
51
+ const query = search.value.toLowerCase();
52
+ const result = [];
53
+ for (const type of Object.keys(componentsCache.value)) {
54
+ const matches = componentsCache.value[type].filter(
55
+ (component) =>
56
+ component.title.toLowerCase().includes(query) ||
57
+ component.id.toLowerCase().includes(query),
58
+ );
59
+ if (matches.length > 0) {
60
+ result.push({
61
+ id: type,
62
+ title: `${type}s (${matches.length})`,
63
+ children: sortAndFormatItems(matches, sortType.value),
64
+ });
65
+ }
66
+ }
67
+ return result;
49
68
  }
50
69
 
51
- if (added.length > 0) {
52
- await dataStyleStore.setModelComponentsVisibility(viewId, added, true);
70
+ const result = [];
71
+ for (const category of filteredCategories.value) {
72
+ result.push({
73
+ ...category,
74
+ children: sortAndFormatItems(componentsCache.value?.[category.id], sortType.value),
75
+ });
53
76
  }
54
- if (removed.length > 0) {
55
- await dataStyleStore.setModelComponentsVisibility(viewId, removed, false);
56
- }
57
- hybridViewerStore.remoteRender();
58
- }
59
-
60
- const visibleSelection = computed(() => applySearchFilter(mesh_components_selection.value, []));
77
+ return result;
78
+ });
61
79
 
62
80
  function showContextMenu(event, item) {
63
81
  const actualItem = item.raw || item;
64
82
  emit("show-menu", {
65
83
  event,
66
- itemId: actualItem.category ? actualItem.id : viewId,
84
+ itemId: actualItem.category ? actualItem.id : id,
67
85
  context_type: actualItem.category ? "model_component" : "model_component_type",
68
- modelId: viewId,
86
+ modelId: id,
69
87
  modelComponentType: actualItem.category ? undefined : actualItem.id,
70
88
  });
71
89
  }
72
90
 
73
- function handleHoverEnter(item) {
91
+ function handleHoverEnter({ item, immediate = false }) {
74
92
  const actualItem = item.raw || item;
75
- const block_ids = actualItem.category
76
- ? [actualItem.viewer_id]
77
- : actualItem.children?.map((child) => child.viewer_id) || [];
78
- onHoverEnter(viewId, block_ids);
93
+
94
+ if (!actualItem.category && (!actualItem.children || actualItem.children.length === 0)) {
95
+ return;
96
+ }
97
+
98
+ onHoverEnter(
99
+ id,
100
+ () =>
101
+ actualItem.category
102
+ ? [actualItem.viewer_id]
103
+ : actualItem.children?.map((child) => child.viewer_id) || [],
104
+ "model",
105
+ immediate,
106
+ );
79
107
  }
80
108
 
81
109
  function handleHoverLeave() {
82
- onHoverLeave(viewId);
110
+ onHoverLeave(id);
83
111
  }
84
112
  </script>
85
113
 
@@ -91,52 +119,60 @@ function handleHoverLeave() {
91
119
  :filter-options="filterOptions"
92
120
  :available-filter-options="availableFilterOptions"
93
121
  @toggle-sort="toggleSort"
122
+ @collapse-all="opened = []"
94
123
  />
95
124
 
96
- <FetchingData v-if="items === undefined" :size="48" :width="4" text="" />
125
+ <FetchingData v-if="rawItems === undefined" :size="48" :width="4" text="" />
97
126
 
98
- <v-treeview
99
- v-else
127
+ <CommonTreeView
100
128
  :selected="visibleSelection"
101
129
  v-model:opened="opened"
102
- :items="processedItems"
103
- :search="search"
104
- :custom-filter="customFilter"
105
- class="transparent-treeview"
106
- item-value="id"
107
- select-strategy="classic"
108
- selectable
109
- items-registration="props"
110
- @update:selected="onSelectionChange"
130
+ :items="itemsForTreeView"
131
+ :options="{
132
+ selection: { selectable: true, strategy: 'classic' },
133
+ search,
134
+ customFilter,
135
+ }"
136
+ :scroll-top="currentView?.scrollTop || 0"
137
+ class="transparent-treeview virtual-tree-height"
138
+ @update:selected="onUpdateSelection"
139
+ @click:item="onUpdateSelection([$event.id, ...visibleComponents])"
140
+ @update:scroll-top="treeviewStore.setScrollTop(id, $event)"
141
+ @hover:enter="handleHoverEnter"
142
+ @hover:leave="handleHoverLeave"
111
143
  >
112
- <template #title="{ item }">
144
+ <template #title="{ item, isLeaf }">
113
145
  <ObjectTreeItemLabel
114
146
  :item="item"
147
+ :is-leaf="isLeaf"
115
148
  show-tooltip
116
- @mouseenter="handleHoverEnter(item)"
117
- @mouseleave="handleHoverLeave(item)"
118
- @contextmenu="showContextMenu($event, item)"
149
+ class="text-body-1"
150
+ @contextmenu.prevent.stop="showContextMenu($event, item)"
119
151
  />
120
152
  </template>
121
- </v-treeview>
153
+ </CommonTreeView>
122
154
  </div>
123
155
  </template>
124
156
 
125
157
  <style scoped>
126
- .transparent-treeview {
127
- background-color: transparent;
128
- margin: 4px 0;
158
+ .tree-view-container {
159
+ height: 100%;
160
+ display: flex;
161
+ flex-direction: column;
162
+ overflow: hidden;
163
+ min-height: 0;
129
164
  }
130
165
 
131
- :deep(.v-list-item) {
132
- transition: background-color 0.2s ease;
166
+ .virtual-tree-height {
167
+ flex-grow: 1;
168
+ min-height: 0;
133
169
  }
134
170
 
135
- :deep(.v-list-item--active > .v-list-item__overlay) {
136
- opacity: 0 !important;
171
+ .transparent-treeview {
172
+ background-color: transparent;
137
173
  }
138
174
 
139
- :deep(.v-list-item:hover > .v-list-item__overlay) {
140
- opacity: 0.1 !important;
175
+ :deep(.v-list-item__overlay) {
176
+ display: none !important;
141
177
  }
142
178
  </style>