@rural-environmental-registry/map_component 2.0.0 → 2.0.2
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.
- package/dist/index.css +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.mjs +8713 -8638
- package/dist/types/index.d.ts +5 -1
- package/dist/utils/layersConfigNormalizer.d.ts +2 -0
- package/package.json +1 -1
- package/src/components/menu/ChildMenu.vue +18 -11
- package/src/components/menu/LayerMenu.vue +20 -7
- package/src/components/menu/ParentMenu.vue +85 -9
- package/src/index.ts +2 -0
- package/src/types/index.ts +5 -1
- package/src/utils/layersConfigNormalizer.ts +22 -1
package/dist/types/index.d.ts
CHANGED
|
@@ -19,6 +19,7 @@ export type LayerActionDefaultItem = {
|
|
|
19
19
|
key?: string;
|
|
20
20
|
name: string;
|
|
21
21
|
icon?: FaIconName;
|
|
22
|
+
tooltip?: string;
|
|
22
23
|
style?: LayerActionStyle;
|
|
23
24
|
disabled?: boolean;
|
|
24
25
|
visible?: boolean;
|
|
@@ -37,6 +38,7 @@ export type LayerActionConfig = {
|
|
|
37
38
|
type?: 'edit' | 'import' | 'delete' | 'visibility' | 'custom' | 'cancel' | 'conclude';
|
|
38
39
|
disabled?: boolean;
|
|
39
40
|
visible?: boolean;
|
|
41
|
+
tooltip?: string;
|
|
40
42
|
style?: LayerActionStyle;
|
|
41
43
|
};
|
|
42
44
|
export type LayerMetricsConfig = {
|
|
@@ -73,7 +75,7 @@ export type LayerData = {
|
|
|
73
75
|
name: string;
|
|
74
76
|
active: boolean;
|
|
75
77
|
activeDefault: boolean;
|
|
76
|
-
role?: 'layer' | 'separator';
|
|
78
|
+
role?: 'layer' | 'separator' | 'subgroup';
|
|
77
79
|
tooltip?: string;
|
|
78
80
|
toggle?: {
|
|
79
81
|
active: string;
|
|
@@ -102,6 +104,8 @@ export type LayerData = {
|
|
|
102
104
|
infoIcons?: LayerInfoIconConfig[];
|
|
103
105
|
required?: boolean;
|
|
104
106
|
editActions?: LayerActionConfig[];
|
|
107
|
+
children?: LayerData[];
|
|
108
|
+
collapsed?: boolean;
|
|
105
109
|
meta?: Record<string, unknown>;
|
|
106
110
|
};
|
|
107
111
|
export type GroupLayerData = {
|
|
@@ -5,6 +5,8 @@ export declare const normalizeLayersConfig: (config?: LayersConfig | null) => Se
|
|
|
5
5
|
export declare const resolveLayerActions: (layer: LayerData, defaults?: LayerActionDefaults) => LayerActionConfig[];
|
|
6
6
|
export declare const resolveEditControlAction: (defaults: LayerActionDefaults | undefined, kind: "cancel" | "conclude") => LayerActionConfig;
|
|
7
7
|
export declare const isMenuSeparator: (layer: LayerData | null | undefined) => boolean;
|
|
8
|
+
export declare const isMenuSubgroup: (layer: LayerData | null | undefined) => boolean;
|
|
9
|
+
export declare const walkMenuLayers: (layers: LayerData[] | undefined, visitor: (layer: LayerData) => void) => void;
|
|
8
10
|
export declare const shouldApplyMapOverlay: (layer: LayerData) => boolean;
|
|
9
11
|
export declare const collectLayerMetricsMap: (config?: LayersConfig | null) => LayerMetricsMap;
|
|
10
12
|
export declare const resolveLayerMetrics: (layer: LayerData | null | undefined) => LayerMetricsConfig[];
|
package/package.json
CHANGED
|
@@ -84,19 +84,26 @@
|
|
|
84
84
|
v-if="!hideControls && visibleActions.length"
|
|
85
85
|
class="child-menu-actions"
|
|
86
86
|
>
|
|
87
|
-
<
|
|
87
|
+
<ElTooltip
|
|
88
88
|
v-for="action in visibleActions"
|
|
89
89
|
:key="action.key"
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
@click.stop="onActionClick(action)"
|
|
90
|
+
:content="action.tooltip || action.name"
|
|
91
|
+
:disabled="!(action.tooltip || action.name)"
|
|
92
|
+
placement="top"
|
|
94
93
|
>
|
|
95
|
-
<
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
94
|
+
<button
|
|
95
|
+
type="button"
|
|
96
|
+
class="child-action-button"
|
|
97
|
+
:disabled="action.disabled"
|
|
98
|
+
:aria-label="action.tooltip || action.name"
|
|
99
|
+
@click.stop="onActionClick(action)"
|
|
100
|
+
>
|
|
101
|
+
<FontAwesomeIcon
|
|
102
|
+
v-if="action.icon"
|
|
103
|
+
:iconName="action.icon"
|
|
104
|
+
/>
|
|
105
|
+
</button>
|
|
106
|
+
</ElTooltip>
|
|
100
107
|
</div>
|
|
101
108
|
<template v-else-if="!hideControls && visibilityMode !== 'eye'">
|
|
102
109
|
<ElSwitch
|
|
@@ -367,7 +374,7 @@
|
|
|
367
374
|
align-items: center;
|
|
368
375
|
justify-content: center;
|
|
369
376
|
border: none !important;
|
|
370
|
-
background: transparent !important
|
|
377
|
+
background: transparent !important;
|
|
371
378
|
color: var(--mapa-base-green);
|
|
372
379
|
cursor: pointer;
|
|
373
380
|
padding: var(--mapa-size-base-2);
|
|
@@ -49,8 +49,10 @@
|
|
|
49
49
|
SectionSelectPayload
|
|
50
50
|
} from '../../types'
|
|
51
51
|
import {
|
|
52
|
+
isMenuSubgroup,
|
|
52
53
|
normalizeLayersConfig,
|
|
53
|
-
shouldApplyMapOverlay
|
|
54
|
+
shouldApplyMapOverlay,
|
|
55
|
+
walkMenuLayers
|
|
54
56
|
} from '../../utils/layersConfigNormalizer'
|
|
55
57
|
import {
|
|
56
58
|
resolveGroupCollapsedState,
|
|
@@ -152,6 +154,15 @@
|
|
|
152
154
|
? group.collapsed
|
|
153
155
|
: resolveGroupCollapsedState(group.key, undefined, persist)
|
|
154
156
|
if (!collapsed) openeds.push(group.key)
|
|
157
|
+
|
|
158
|
+
;(group.layers || []).forEach((layer) => {
|
|
159
|
+
if (!isMenuSubgroup(layer)) return
|
|
160
|
+
const subCollapsed =
|
|
161
|
+
layer.collapsed !== undefined
|
|
162
|
+
? layer.collapsed
|
|
163
|
+
: resolveGroupCollapsedState(layer.key, true, persist)
|
|
164
|
+
if (!subCollapsed) openeds.push(layer.key)
|
|
165
|
+
})
|
|
155
166
|
})
|
|
156
167
|
})
|
|
157
168
|
|
|
@@ -279,7 +290,7 @@
|
|
|
279
290
|
|
|
280
291
|
normalizedSections.value.forEach((section) => {
|
|
281
292
|
section.groups.forEach((group) => {
|
|
282
|
-
group.layers
|
|
293
|
+
walkMenuLayers(group.layers, (layer) => {
|
|
283
294
|
if (initializedLayerKeys.has(layer.key)) return
|
|
284
295
|
if (!shouldApplyMapOverlay(layer)) return
|
|
285
296
|
if (!shouldInitLayerOnMap(layer, persist)) return
|
|
@@ -313,7 +324,7 @@
|
|
|
313
324
|
}
|
|
314
325
|
|
|
315
326
|
const onGroupLayerToggle = (parent: GroupLayerData): void => {
|
|
316
|
-
parent.layers
|
|
327
|
+
walkMenuLayers(parent.layers, (childLayer) => {
|
|
317
328
|
applyLayerOverlay(childLayer)
|
|
318
329
|
})
|
|
319
330
|
|
|
@@ -363,7 +374,8 @@
|
|
|
363
374
|
|
|
364
375
|
const handleWmsLayer = (layer: LayerData): void => {
|
|
365
376
|
if (convertedLayers.value[layer.key]) {
|
|
366
|
-
if (!layer.active)
|
|
377
|
+
if (!layer.active) removeWmsLayer(layer)
|
|
378
|
+
return
|
|
367
379
|
}
|
|
368
380
|
|
|
369
381
|
if (!layer.active) return
|
|
@@ -415,7 +427,9 @@
|
|
|
415
427
|
|
|
416
428
|
const handleGeoJsonLayer = (layer: LayerData): void => {
|
|
417
429
|
if (convertedGeoJsonLayers.value[layer.key]) {
|
|
418
|
-
|
|
430
|
+
// Já no mapa: só remove se desativada — evita GeoJSON órfão ao reaplicar active=true.
|
|
431
|
+
if (!layer.active) removeGeoJsonLayer(layer)
|
|
432
|
+
return
|
|
419
433
|
}
|
|
420
434
|
|
|
421
435
|
if (!layer.active) return
|
|
@@ -469,8 +483,7 @@
|
|
|
469
483
|
.layer-menu > .map-custom-menu {
|
|
470
484
|
box-shadow: var(--mapa-base-box-shadow);
|
|
471
485
|
padding: var(--mapa-size-base-10);
|
|
472
|
-
overflow-y:
|
|
473
|
-
scrollbar-width: none;
|
|
486
|
+
overflow-y: auto;
|
|
474
487
|
height: 100%;
|
|
475
488
|
}
|
|
476
489
|
|
|
@@ -51,8 +51,29 @@
|
|
|
51
51
|
v-for="(child, idx) in childrenLayers"
|
|
52
52
|
:key="child.key"
|
|
53
53
|
>
|
|
54
|
+
<ElSubMenu
|
|
55
|
+
v-if="isMenuSubgroup(child)"
|
|
56
|
+
:index="child.key"
|
|
57
|
+
class="parent-menu-subgroup-accordion"
|
|
58
|
+
>
|
|
59
|
+
<template #title>
|
|
60
|
+
<div class="parent-menu-subgroup-title">{{ child.name }}</div>
|
|
61
|
+
</template>
|
|
62
|
+
<ChildMenu
|
|
63
|
+
v-for="(nested, nestedIdx) in child.children || []"
|
|
64
|
+
:key="nested.key"
|
|
65
|
+
:actionDefaults="actionDefaults"
|
|
66
|
+
:data="nested"
|
|
67
|
+
:groupKey="groupData.key"
|
|
68
|
+
:persist="props.persist"
|
|
69
|
+
:sectionKey="sectionKey"
|
|
70
|
+
:visibilityMode="visibilityMode"
|
|
71
|
+
@onChildLayerToggle="onNestedChildChange($event, idx, nestedIdx)"
|
|
72
|
+
@onLayerAction="emit('onLayerAction', $event)"
|
|
73
|
+
/>
|
|
74
|
+
</ElSubMenu>
|
|
54
75
|
<ElMenuItem
|
|
55
|
-
v-if="isMenuSeparator(child)"
|
|
76
|
+
v-else-if="isMenuSeparator(child)"
|
|
56
77
|
:index="child.key"
|
|
57
78
|
class="parent-menu-subgroup-header"
|
|
58
79
|
disabled
|
|
@@ -114,6 +135,7 @@
|
|
|
114
135
|
} from '../../types'
|
|
115
136
|
import {
|
|
116
137
|
isMenuSeparator,
|
|
138
|
+
isMenuSubgroup,
|
|
117
139
|
resolveActiveGroupActions
|
|
118
140
|
} from '../../utils/layersConfigNormalizer'
|
|
119
141
|
import { resolveLayerActiveState, setHistory } from '../../utils/menuHistory.ts'
|
|
@@ -154,16 +176,26 @@
|
|
|
154
176
|
onLayerAction: [LayerActionPayload]
|
|
155
177
|
}>()
|
|
156
178
|
|
|
179
|
+
const resolveMenuEntry = (layer: LayerData): LayerData => {
|
|
180
|
+
if (isMenuSubgroup(layer)) {
|
|
181
|
+
return {
|
|
182
|
+
...layer,
|
|
183
|
+
children: (layer.children || []).map((child) =>
|
|
184
|
+
resolveLayerActiveState(child, props.persist)
|
|
185
|
+
)
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
return resolveLayerActiveState(layer, props.persist)
|
|
189
|
+
}
|
|
190
|
+
|
|
157
191
|
const childrenLayers = ref<LayerData[]>(
|
|
158
|
-
(props.groupData.layers ?? []).map((layer) =>
|
|
192
|
+
(props.groupData.layers ?? []).map((layer) => resolveMenuEntry(layer))
|
|
159
193
|
)
|
|
160
194
|
|
|
161
195
|
watch(
|
|
162
196
|
() => props.groupData.layers,
|
|
163
197
|
(layers) => {
|
|
164
|
-
childrenLayers.value = (layers ?? []).map((layer) =>
|
|
165
|
-
resolveLayerActiveState(layer, props.persist)
|
|
166
|
-
)
|
|
198
|
+
childrenLayers.value = (layers ?? []).map((layer) => resolveMenuEntry(layer))
|
|
167
199
|
},
|
|
168
200
|
{ deep: true }
|
|
169
201
|
)
|
|
@@ -190,9 +222,20 @@
|
|
|
190
222
|
'Ocultar'
|
|
191
223
|
)
|
|
192
224
|
|
|
193
|
-
const
|
|
194
|
-
|
|
195
|
-
|
|
225
|
+
const collectToggleableLeaves = (layers: LayerData[]): LayerData[] => {
|
|
226
|
+
const leaves: LayerData[] = []
|
|
227
|
+
for (const layer of layers) {
|
|
228
|
+
if (isMenuSeparator(layer)) continue
|
|
229
|
+
if (isMenuSubgroup(layer)) {
|
|
230
|
+
leaves.push(...collectToggleableLeaves(layer.children || []))
|
|
231
|
+
continue
|
|
232
|
+
}
|
|
233
|
+
leaves.push(layer)
|
|
234
|
+
}
|
|
235
|
+
return leaves
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
const toggleableLayers = computed(() => collectToggleableLeaves(childrenLayers.value))
|
|
196
239
|
|
|
197
240
|
const toggleVisibleAllLayers = (): void => {
|
|
198
241
|
if (props.persist) {
|
|
@@ -210,6 +253,12 @@
|
|
|
210
253
|
set: (active: boolean) => {
|
|
211
254
|
childrenLayers.value = (props.groupData.layers ?? []).map((layer: LayerData) => {
|
|
212
255
|
if (isMenuSeparator(layer)) return resolveLayerActiveState(layer, props.persist)
|
|
256
|
+
if (isMenuSubgroup(layer)) {
|
|
257
|
+
return {
|
|
258
|
+
...layer,
|
|
259
|
+
children: (layer.children || []).map((child) => ({ ...child, active }))
|
|
260
|
+
}
|
|
261
|
+
}
|
|
213
262
|
return { ...layer, active }
|
|
214
263
|
})
|
|
215
264
|
|
|
@@ -222,6 +271,19 @@
|
|
|
222
271
|
emit('onChildLayerToggle', layer)
|
|
223
272
|
}
|
|
224
273
|
|
|
274
|
+
const onNestedChildChange = (
|
|
275
|
+
layer: LayerData,
|
|
276
|
+
subgroupIdx: number,
|
|
277
|
+
nestedIdx: number
|
|
278
|
+
): void => {
|
|
279
|
+
const subgroup = childrenLayers.value[subgroupIdx]
|
|
280
|
+
if (!subgroup) return
|
|
281
|
+
const children = [...(subgroup.children || [])]
|
|
282
|
+
children[nestedIdx] = layer
|
|
283
|
+
childrenLayers.value[subgroupIdx] = { ...subgroup, children }
|
|
284
|
+
emit('onChildLayerToggle', layer)
|
|
285
|
+
}
|
|
286
|
+
|
|
225
287
|
const onGroupActionClick = (action: GroupActionConfig): void => {
|
|
226
288
|
if (action.disabled) return
|
|
227
289
|
|
|
@@ -337,7 +399,6 @@
|
|
|
337
399
|
margin: 0 !important;
|
|
338
400
|
}
|
|
339
401
|
|
|
340
|
-
/* Título de subgrupo: separador visual, sem accordion */
|
|
341
402
|
.parent-menu .parent-menu-subgroup-header {
|
|
342
403
|
height: auto !important;
|
|
343
404
|
line-height: normal !important;
|
|
@@ -355,6 +416,21 @@
|
|
|
355
416
|
opacity: 1 !important;
|
|
356
417
|
}
|
|
357
418
|
|
|
419
|
+
.parent-menu .parent-menu-subgroup-accordion {
|
|
420
|
+
padding-left: 0 !important;
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
.parent-menu .parent-menu-subgroup-accordion > .el-sub-menu__title {
|
|
424
|
+
height: auto !important;
|
|
425
|
+
line-height: normal !important;
|
|
426
|
+
white-space: normal !important;
|
|
427
|
+
padding: var(--mapa-size-base-10) var(--mapa-size-base-20) var(--mapa-size-base-5) !important;
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
.parent-menu .parent-menu-subgroup-accordion > .el-sub-menu__title:hover {
|
|
431
|
+
background-color: transparent !important;
|
|
432
|
+
}
|
|
433
|
+
|
|
358
434
|
.parent-menu .parent-menu-subgroup-title {
|
|
359
435
|
font-size: var(--mapa-fs-12);
|
|
360
436
|
font-weight: 700;
|
package/src/index.ts
CHANGED
package/src/types/index.ts
CHANGED
|
@@ -47,6 +47,7 @@ export type LayerActionDefaultItem = {
|
|
|
47
47
|
key?: string
|
|
48
48
|
name: string
|
|
49
49
|
icon?: FaIconName
|
|
50
|
+
tooltip?: string
|
|
50
51
|
style?: LayerActionStyle
|
|
51
52
|
disabled?: boolean
|
|
52
53
|
visible?: boolean
|
|
@@ -67,6 +68,7 @@ export type LayerActionConfig = {
|
|
|
67
68
|
type?: 'edit' | 'import' | 'delete' | 'visibility' | 'custom' | 'cancel' | 'conclude'
|
|
68
69
|
disabled?: boolean
|
|
69
70
|
visible?: boolean
|
|
71
|
+
tooltip?: string
|
|
70
72
|
style?: LayerActionStyle
|
|
71
73
|
}
|
|
72
74
|
|
|
@@ -115,7 +117,7 @@ export type LayerData = {
|
|
|
115
117
|
name: string
|
|
116
118
|
active: boolean
|
|
117
119
|
activeDefault: boolean
|
|
118
|
-
role?: 'layer' | 'separator'
|
|
120
|
+
role?: 'layer' | 'separator' | 'subgroup'
|
|
119
121
|
tooltip?: string
|
|
120
122
|
toggle?: {
|
|
121
123
|
active: string
|
|
@@ -145,6 +147,8 @@ export type LayerData = {
|
|
|
145
147
|
infoIcons?: LayerInfoIconConfig[]
|
|
146
148
|
required?: boolean
|
|
147
149
|
editActions?: LayerActionConfig[]
|
|
150
|
+
children?: LayerData[]
|
|
151
|
+
collapsed?: boolean
|
|
148
152
|
meta?: Record<string, unknown>
|
|
149
153
|
}
|
|
150
154
|
|
|
@@ -110,6 +110,7 @@ export const resolveLayerActions = (
|
|
|
110
110
|
name: defaults.edit.name,
|
|
111
111
|
icon: defaults.edit.icon ?? 'pencil',
|
|
112
112
|
type: 'edit',
|
|
113
|
+
tooltip: defaults.edit.tooltip,
|
|
113
114
|
style: defaults.edit.style,
|
|
114
115
|
disabled: defaults.edit.disabled
|
|
115
116
|
})
|
|
@@ -121,6 +122,7 @@ export const resolveLayerActions = (
|
|
|
121
122
|
name: defaults.import.name,
|
|
122
123
|
icon: defaults.import.icon ?? 'upload',
|
|
123
124
|
type: 'import',
|
|
125
|
+
tooltip: defaults.import.tooltip,
|
|
124
126
|
style: defaults.import.style,
|
|
125
127
|
disabled: defaults.import.disabled
|
|
126
128
|
})
|
|
@@ -132,6 +134,7 @@ export const resolveLayerActions = (
|
|
|
132
134
|
name: defaults.delete.name,
|
|
133
135
|
icon: defaults.delete.icon ?? 'trash',
|
|
134
136
|
type: 'delete',
|
|
137
|
+
tooltip: defaults.delete.tooltip,
|
|
135
138
|
style: defaults.delete.style,
|
|
136
139
|
disabled: defaults.delete.disabled
|
|
137
140
|
})
|
|
@@ -163,8 +166,26 @@ export const isMenuSeparator = (layer: LayerData | null | undefined): boolean =>
|
|
|
163
166
|
return layer?.role === 'separator' || !!layer?.meta?.isSeparator
|
|
164
167
|
}
|
|
165
168
|
|
|
169
|
+
export const isMenuSubgroup = (layer: LayerData | null | undefined): boolean => {
|
|
170
|
+
return layer?.role === 'subgroup' || !!layer?.meta?.isSubgroup
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
export const walkMenuLayers = (
|
|
174
|
+
layers: LayerData[] | undefined,
|
|
175
|
+
visitor: (layer: LayerData) => void
|
|
176
|
+
): void => {
|
|
177
|
+
for (const layer of layers || []) {
|
|
178
|
+
if (isMenuSubgroup(layer) && layer.children?.length) {
|
|
179
|
+
walkMenuLayers(layer.children, visitor)
|
|
180
|
+
continue
|
|
181
|
+
}
|
|
182
|
+
if (isMenuSeparator(layer)) continue
|
|
183
|
+
visitor(layer)
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
166
187
|
export const shouldApplyMapOverlay = (layer: LayerData): boolean => {
|
|
167
|
-
if (isMenuSeparator(layer)) return false
|
|
188
|
+
if (isMenuSeparator(layer) || isMenuSubgroup(layer)) return false
|
|
168
189
|
if (layer.mapSource === 'none' || layer.mapSource === 'consumer') return false
|
|
169
190
|
if (layer.mapSource === 'wms' || layer.mapSource === 'geojson') return true
|
|
170
191
|
if (layer.geojson) return true
|