@rural-environmental-registry/map_component 1.2.0 → 2.0.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.
- package/README.md +1 -0
- package/dist/handlers/measureToolsHandler.d.ts +1 -0
- package/dist/index.css +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.mjs +15596 -14769
- package/dist/types/index.d.ts +117 -15
- package/dist/utils/layersConfigNormalizer.d.ts +16 -0
- package/dist/utils/menuHistory.d.ts +3 -3
- package/package.json +1 -1
- package/src/components/MapDPG.vue +90 -2
- package/src/components/fa-icon/FontAwesomeIcon.vue +35 -5
- package/src/components/map/LeafletMap.vue +3 -1
- package/src/components/menu/ChildMenu.vue +307 -27
- package/src/components/menu/LayerMenu.vue +232 -37
- package/src/components/menu/ParentMenu.vue +261 -27
- package/src/components/menu/SectionMenu.vue +512 -0
- package/src/handlers/mapToolsHandler.ts +3 -1
- package/src/handlers/measureToolsHandler.ts +36 -27
- package/src/handlers/toolsConstants.ts +1 -0
- package/src/index.ts +47 -0
- package/src/types/index.ts +148 -14
- package/src/utils/layersConfigNormalizer.ts +273 -0
- package/src/utils/menuHistory.ts +35 -19
package/src/types/index.ts
CHANGED
|
@@ -15,6 +15,19 @@ export type FaIconName =
|
|
|
15
15
|
| 'pencil'
|
|
16
16
|
| 'trash'
|
|
17
17
|
| 'chevron-down'
|
|
18
|
+
| 'eye'
|
|
19
|
+
| 'eye-slash'
|
|
20
|
+
| 'circle-info'
|
|
21
|
+
| 'circle-exclamation'
|
|
22
|
+
| 'triangle-exclamation'
|
|
23
|
+
| 'circle-check'
|
|
24
|
+
| 'circle-xmark'
|
|
25
|
+
| 'ban'
|
|
26
|
+
| 'lock'
|
|
27
|
+
| 'unlock'
|
|
28
|
+
| 'thumbtack'
|
|
29
|
+
| 'thumb-tack'
|
|
30
|
+
| 'map-pin'
|
|
18
31
|
|
|
19
32
|
export type DrawnArea = {
|
|
20
33
|
m2: number
|
|
@@ -24,39 +37,156 @@ export type DrawnArea = {
|
|
|
24
37
|
|
|
25
38
|
export type IncrementedLayer = Layer & { drawnArea: DrawnArea }
|
|
26
39
|
|
|
27
|
-
export type
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
40
|
+
export type LayerActionStyle = {
|
|
41
|
+
backgroundColor: string
|
|
42
|
+
color: string
|
|
43
|
+
borderColor?: string
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export type LayerActionDefaultItem = {
|
|
47
|
+
key?: string
|
|
33
48
|
name: string
|
|
34
|
-
|
|
35
|
-
|
|
49
|
+
icon?: FaIconName
|
|
50
|
+
style?: LayerActionStyle
|
|
51
|
+
disabled?: boolean
|
|
52
|
+
visible?: boolean
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export type LayerActionDefaults = {
|
|
56
|
+
edit?: LayerActionDefaultItem
|
|
57
|
+
import?: LayerActionDefaultItem
|
|
58
|
+
delete?: LayerActionDefaultItem
|
|
59
|
+
cancel?: LayerActionDefaultItem
|
|
60
|
+
conclude?: LayerActionDefaultItem
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export type LayerActionConfig = {
|
|
64
|
+
key: string
|
|
65
|
+
name: string
|
|
66
|
+
icon?: FaIconName
|
|
67
|
+
type?: 'edit' | 'import' | 'delete' | 'visibility' | 'custom' | 'cancel' | 'conclude'
|
|
68
|
+
disabled?: boolean
|
|
69
|
+
visible?: boolean
|
|
70
|
+
style?: LayerActionStyle
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export type LayerMetricsConfig = {
|
|
74
|
+
title: string
|
|
75
|
+
type: string
|
|
76
|
+
value: string | number
|
|
77
|
+
style?: LayerActionStyle
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/** @deprecated Use LayerMetricsConfig */
|
|
81
|
+
export type LayerMetrics = LayerMetricsConfig
|
|
82
|
+
|
|
83
|
+
export type LayerMetricsMap = Record<string, LayerMetricsConfig[]>
|
|
84
|
+
|
|
85
|
+
export type LayerInfoIconConfig = {
|
|
86
|
+
|
|
87
|
+
key?: string
|
|
88
|
+
icon: FaIconName
|
|
89
|
+
active: boolean
|
|
90
|
+
tooltip?: string
|
|
91
|
+
style?: Partial<Pick<LayerActionStyle, 'color' | 'backgroundColor'>>
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export type LayerInfoIconsMap = Record<string, LayerInfoIconConfig[]>
|
|
95
|
+
|
|
96
|
+
export type GroupActionConfig = LayerActionConfig & {
|
|
36
97
|
active: boolean
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
export type GroupActionsMap = Record<string, GroupActionConfig[]>
|
|
102
|
+
|
|
103
|
+
export type SectionConfig = {
|
|
104
|
+
name?: string
|
|
105
|
+
key: string
|
|
106
|
+
groups: GroupLayerData[]
|
|
107
|
+
actionDefaults?: LayerActionDefaults
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/** @deprecated Use SectionConfig */
|
|
111
|
+
export type SectionData = SectionConfig
|
|
112
|
+
|
|
113
|
+
export type LayerData = {
|
|
37
114
|
key: string
|
|
38
|
-
|
|
115
|
+
name: string
|
|
116
|
+
active: boolean
|
|
117
|
+
activeDefault: boolean
|
|
118
|
+
role?: 'layer' | 'separator'
|
|
119
|
+
tooltip?: string
|
|
120
|
+
toggle?: {
|
|
39
121
|
active: string
|
|
40
122
|
inactive: string
|
|
41
123
|
}
|
|
42
|
-
|
|
124
|
+
visibility?: {
|
|
125
|
+
labelShow?: string
|
|
126
|
+
labelHide?: string
|
|
127
|
+
show?: boolean
|
|
128
|
+
}
|
|
129
|
+
style?: {
|
|
43
130
|
color: string
|
|
44
131
|
fillColor: string
|
|
132
|
+
icon?: string
|
|
45
133
|
}
|
|
46
|
-
|
|
134
|
+
baseUrl?: string
|
|
135
|
+
layers?: string
|
|
136
|
+
format?: string
|
|
137
|
+
transparent?: boolean
|
|
138
|
+
geojson?: GeoJsonObject | GeoJsonObject[]
|
|
139
|
+
cqlFilter?: string
|
|
140
|
+
options?: Record<string, unknown>
|
|
141
|
+
|
|
142
|
+
mapSource?: 'wms' | 'geojson' | 'none' | 'consumer'
|
|
143
|
+
actions?: LayerActionConfig[]
|
|
144
|
+
metrics?: LayerMetricsConfig[]
|
|
145
|
+
infoIcons?: LayerInfoIconConfig[]
|
|
146
|
+
required?: boolean
|
|
147
|
+
editActions?: LayerActionConfig[]
|
|
148
|
+
meta?: Record<string, unknown>
|
|
47
149
|
}
|
|
48
150
|
|
|
49
151
|
export type GroupLayerData = {
|
|
50
152
|
name: string
|
|
51
153
|
key: string
|
|
52
|
-
toggle
|
|
154
|
+
toggle?: {
|
|
53
155
|
active: string
|
|
54
156
|
inactive: string
|
|
55
157
|
}
|
|
158
|
+
visibility?: {
|
|
159
|
+
show?: boolean
|
|
160
|
+
labelShow?: string
|
|
161
|
+
labelHide?: string
|
|
162
|
+
}
|
|
163
|
+
collapsed?: boolean
|
|
164
|
+
actions?: GroupActionConfig[]
|
|
56
165
|
layers: LayerData[]
|
|
166
|
+
meta?: Record<string, unknown>
|
|
57
167
|
}
|
|
58
168
|
|
|
59
|
-
export type LayersConfig = GroupLayerData[]
|
|
169
|
+
export type LayersConfig = GroupLayerData[] | SectionConfig[]
|
|
170
|
+
|
|
171
|
+
export type LayerActionPayload = {
|
|
172
|
+
actionKey: string
|
|
173
|
+
actionType?: LayerActionConfig['type']
|
|
174
|
+
sectionKey?: string
|
|
175
|
+
groupKey?: string
|
|
176
|
+
layerKey?: string
|
|
177
|
+
layer?: LayerData
|
|
178
|
+
source: 'child-menu' | 'edit-panel' | 'group-menu'
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
export type SectionEditStatePayload = {
|
|
182
|
+
sectionKey: string | null
|
|
183
|
+
layerKey: string | null
|
|
184
|
+
layer: LayerData | null
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
export type SectionSelectPayload = {
|
|
188
|
+
sectionKey: string
|
|
189
|
+
}
|
|
60
190
|
|
|
61
191
|
export type DrawingEvent = {
|
|
62
192
|
type: 'created' | 'edited' | 'deleted'
|
|
@@ -87,7 +217,6 @@ export type MapConfigConfig = MapOptions & {
|
|
|
87
217
|
id: string
|
|
88
218
|
removeControlLayers?: boolean
|
|
89
219
|
zoomControlPosition?: ControlPosition
|
|
90
|
-
/** Reposiciona marcadores após zoom (evita drift de divIcon). Padrão: true. */
|
|
91
220
|
stabilizeMarkersOnZoom?: boolean
|
|
92
221
|
}
|
|
93
222
|
|
|
@@ -99,6 +228,10 @@ export type LayersMenuConfig = {
|
|
|
99
228
|
size: 'small' | 'medium' | 'large'
|
|
100
229
|
removeMenu?: boolean
|
|
101
230
|
persist: boolean
|
|
231
|
+
editingLayerKey?: string | null
|
|
232
|
+
selectedSectionKey?: string | null
|
|
233
|
+
visibilityMode?: 'switch' | 'eye'
|
|
234
|
+
defaultOpen?: boolean
|
|
102
235
|
}
|
|
103
236
|
|
|
104
237
|
export type MemorialConfig = {
|
|
@@ -131,6 +264,7 @@ export type MapToolsConfig = {
|
|
|
131
264
|
show?: boolean
|
|
132
265
|
title?: string
|
|
133
266
|
}
|
|
267
|
+
showInteractionPanel?: boolean
|
|
134
268
|
texts?: {
|
|
135
269
|
measureResult?: string
|
|
136
270
|
measureLength?: string
|
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
import {
|
|
2
|
+
GroupActionConfig,
|
|
3
|
+
GroupActionsMap,
|
|
4
|
+
GroupLayerData,
|
|
5
|
+
LayerActionConfig,
|
|
6
|
+
LayerActionDefaults,
|
|
7
|
+
LayerData,
|
|
8
|
+
LayerInfoIconConfig,
|
|
9
|
+
LayerInfoIconsMap,
|
|
10
|
+
LayerMetricsConfig,
|
|
11
|
+
LayerMetricsMap,
|
|
12
|
+
LayersConfig,
|
|
13
|
+
SectionConfig
|
|
14
|
+
} from '../types'
|
|
15
|
+
|
|
16
|
+
type GroupLike = GroupLayerData & {
|
|
17
|
+
customLayers?: LayerData[]
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export const isSectionConfig = (item: unknown): item is SectionConfig => {
|
|
21
|
+
return (
|
|
22
|
+
typeof item === 'object' &&
|
|
23
|
+
item !== null &&
|
|
24
|
+
Array.isArray((item as SectionConfig).groups)
|
|
25
|
+
)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export const isGroupConfig = (item: unknown): item is GroupLayerData => {
|
|
29
|
+
if (typeof item !== 'object' || item === null) return false
|
|
30
|
+
if (Array.isArray((item as SectionConfig).groups)) return false
|
|
31
|
+
|
|
32
|
+
const group = item as GroupLike
|
|
33
|
+
return Array.isArray(group.layers) || Array.isArray(group.customLayers)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const normalizeGroup = (group: GroupLike): GroupLayerData => {
|
|
37
|
+
const layers = group.layers ?? group.customLayers ?? []
|
|
38
|
+
const { customLayers: _alias, ...rest } = group
|
|
39
|
+
return {
|
|
40
|
+
...rest,
|
|
41
|
+
layers
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export const normalizeLayersConfig = (config?: LayersConfig | null): SectionConfig[] => {
|
|
46
|
+
if (!config?.length) return []
|
|
47
|
+
|
|
48
|
+
const allSections = config.every(isSectionConfig)
|
|
49
|
+
const allGroups = config.every(isGroupConfig)
|
|
50
|
+
|
|
51
|
+
if (allSections) {
|
|
52
|
+
return (config as SectionConfig[]).map((section) => ({
|
|
53
|
+
...section,
|
|
54
|
+
groups: section.groups.map((group) => normalizeGroup(group as GroupLike))
|
|
55
|
+
}))
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (allGroups) {
|
|
59
|
+
return [
|
|
60
|
+
{
|
|
61
|
+
key: 'default',
|
|
62
|
+
groups: (config as GroupLike[]).map(normalizeGroup)
|
|
63
|
+
}
|
|
64
|
+
]
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
console.warn(
|
|
68
|
+
'[map_component] LayersConfig misto (sections e groups). Usando apenas itens reconhecidos como section ou group.'
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
const sections: SectionConfig[] = []
|
|
72
|
+
const orphanGroups: GroupLayerData[] = []
|
|
73
|
+
const mixedItems = config as Array<SectionConfig | GroupLayerData>
|
|
74
|
+
|
|
75
|
+
for (const item of mixedItems) {
|
|
76
|
+
if (isSectionConfig(item)) {
|
|
77
|
+
sections.push({
|
|
78
|
+
...item,
|
|
79
|
+
groups: item.groups.map((group) => normalizeGroup(group as GroupLike))
|
|
80
|
+
})
|
|
81
|
+
} else if (isGroupConfig(item)) {
|
|
82
|
+
orphanGroups.push(normalizeGroup(item as GroupLike))
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if (orphanGroups.length) {
|
|
87
|
+
sections.push({ key: 'default', groups: orphanGroups })
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return sections
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export const resolveLayerActions = (
|
|
94
|
+
layer: LayerData,
|
|
95
|
+
defaults?: LayerActionDefaults
|
|
96
|
+
): LayerActionConfig[] => {
|
|
97
|
+
|
|
98
|
+
if (Array.isArray(layer.actions)) {
|
|
99
|
+
if (layer.actions.length === 0) return []
|
|
100
|
+
return layer.actions.filter((action) => action.visible !== false)
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
if (!defaults) return []
|
|
104
|
+
|
|
105
|
+
const actions: LayerActionConfig[] = []
|
|
106
|
+
|
|
107
|
+
if (defaults.edit) {
|
|
108
|
+
actions.push({
|
|
109
|
+
key: defaults.edit.key ?? 'edit',
|
|
110
|
+
name: defaults.edit.name,
|
|
111
|
+
icon: defaults.edit.icon ?? 'pencil',
|
|
112
|
+
type: 'edit',
|
|
113
|
+
style: defaults.edit.style,
|
|
114
|
+
disabled: defaults.edit.disabled
|
|
115
|
+
})
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
if (defaults.import) {
|
|
119
|
+
actions.push({
|
|
120
|
+
key: defaults.import.key ?? 'import',
|
|
121
|
+
name: defaults.import.name,
|
|
122
|
+
icon: defaults.import.icon ?? 'upload',
|
|
123
|
+
type: 'import',
|
|
124
|
+
style: defaults.import.style,
|
|
125
|
+
disabled: defaults.import.disabled
|
|
126
|
+
})
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
if (defaults.delete) {
|
|
130
|
+
actions.push({
|
|
131
|
+
key: defaults.delete.key ?? 'delete',
|
|
132
|
+
name: defaults.delete.name,
|
|
133
|
+
icon: defaults.delete.icon ?? 'trash',
|
|
134
|
+
type: 'delete',
|
|
135
|
+
style: defaults.delete.style,
|
|
136
|
+
disabled: defaults.delete.disabled
|
|
137
|
+
})
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
return actions.filter((action) => action.visible !== false)
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
export const resolveEditControlAction = (
|
|
145
|
+
defaults: LayerActionDefaults | undefined,
|
|
146
|
+
kind: 'cancel' | 'conclude'
|
|
147
|
+
): LayerActionConfig => {
|
|
148
|
+
const configured = defaults?.[kind]
|
|
149
|
+
const fallbackName = kind === 'cancel' ? 'Cancelar' : 'Concluir'
|
|
150
|
+
|
|
151
|
+
return {
|
|
152
|
+
key: configured?.key ?? kind,
|
|
153
|
+
name: configured?.name ?? fallbackName,
|
|
154
|
+
icon: configured?.icon,
|
|
155
|
+
type: kind,
|
|
156
|
+
style: configured?.style,
|
|
157
|
+
disabled: configured?.disabled,
|
|
158
|
+
visible: configured?.visible
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
export const isMenuSeparator = (layer: LayerData | null | undefined): boolean => {
|
|
163
|
+
return layer?.role === 'separator' || !!layer?.meta?.isSeparator
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
export const shouldApplyMapOverlay = (layer: LayerData): boolean => {
|
|
167
|
+
if (isMenuSeparator(layer)) return false
|
|
168
|
+
if (layer.mapSource === 'none' || layer.mapSource === 'consumer') return false
|
|
169
|
+
if (layer.mapSource === 'wms' || layer.mapSource === 'geojson') return true
|
|
170
|
+
if (layer.geojson) return true
|
|
171
|
+
if (layer.baseUrl) return true
|
|
172
|
+
return false
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
export const collectLayerMetricsMap = (config?: LayersConfig | null): LayerMetricsMap => {
|
|
176
|
+
const result: LayerMetricsMap = {}
|
|
177
|
+
|
|
178
|
+
normalizeLayersConfig(config).forEach((section) => {
|
|
179
|
+
section.groups.forEach((group) => {
|
|
180
|
+
group.layers?.forEach((layer: LayerData) => {
|
|
181
|
+
if (layer.metrics?.length) {
|
|
182
|
+
result[layer.key] = layer.metrics
|
|
183
|
+
}
|
|
184
|
+
})
|
|
185
|
+
})
|
|
186
|
+
})
|
|
187
|
+
|
|
188
|
+
return result
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
export const resolveLayerMetrics = (layer: LayerData | null | undefined): LayerMetricsConfig[] => {
|
|
192
|
+
return layer?.metrics?.length ? layer.metrics : []
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
export const collectLayerInfoIconsMap = (config?: LayersConfig | null): LayerInfoIconsMap => {
|
|
196
|
+
const result: LayerInfoIconsMap = {}
|
|
197
|
+
|
|
198
|
+
normalizeLayersConfig(config).forEach((section) => {
|
|
199
|
+
section.groups.forEach((group) => {
|
|
200
|
+
group.layers?.forEach((layer: LayerData) => {
|
|
201
|
+
if (layer.infoIcons?.length) {
|
|
202
|
+
result[layer.key] = layer.infoIcons
|
|
203
|
+
}
|
|
204
|
+
})
|
|
205
|
+
})
|
|
206
|
+
})
|
|
207
|
+
|
|
208
|
+
return result
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
export const resolveActiveLayerInfoIcons = (
|
|
212
|
+
layer: LayerData | null | undefined
|
|
213
|
+
): LayerInfoIconConfig[] => {
|
|
214
|
+
return (layer?.infoIcons ?? []).filter((item) => item.active)
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
export const collectGroupActionsMap = (config?: LayersConfig | null): GroupActionsMap => {
|
|
218
|
+
const result: GroupActionsMap = {}
|
|
219
|
+
|
|
220
|
+
normalizeLayersConfig(config).forEach((section) => {
|
|
221
|
+
section.groups.forEach((group) => {
|
|
222
|
+
if (group.actions?.length) {
|
|
223
|
+
result[group.key] = group.actions
|
|
224
|
+
}
|
|
225
|
+
})
|
|
226
|
+
})
|
|
227
|
+
|
|
228
|
+
return result
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
export const resolveActiveGroupActions = (
|
|
232
|
+
group: GroupLayerData | null | undefined
|
|
233
|
+
): GroupActionConfig[] => {
|
|
234
|
+
return (group?.actions ?? []).filter(
|
|
235
|
+
(action) => action.active && action.visible !== false
|
|
236
|
+
)
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
export const withLayerInfoIconActive = (
|
|
240
|
+
infoIcons: LayerInfoIconConfig[] | undefined,
|
|
241
|
+
iconRef: string,
|
|
242
|
+
active: boolean
|
|
243
|
+
): LayerInfoIconConfig[] | null => {
|
|
244
|
+
if (!infoIcons?.length) return null
|
|
245
|
+
|
|
246
|
+
let targetIndex = infoIcons.findIndex((item) => item.key === iconRef)
|
|
247
|
+
if (targetIndex < 0) {
|
|
248
|
+
const parsed = Number.parseInt(iconRef, 10)
|
|
249
|
+
if (!Number.isInteger(parsed) || parsed < 0 || parsed >= infoIcons.length) {
|
|
250
|
+
return null
|
|
251
|
+
}
|
|
252
|
+
targetIndex = parsed
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
return infoIcons.map((item, idx) =>
|
|
256
|
+
idx === targetIndex ? { ...item, active } : item
|
|
257
|
+
)
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
export const withGroupActionActive = (
|
|
261
|
+
actions: GroupActionConfig[] | undefined,
|
|
262
|
+
actionKey: string,
|
|
263
|
+
active: boolean
|
|
264
|
+
): GroupActionConfig[] | null => {
|
|
265
|
+
if (!actions?.length) return null
|
|
266
|
+
|
|
267
|
+
const exists = actions.some((action) => action.key === actionKey)
|
|
268
|
+
if (!exists) return null
|
|
269
|
+
|
|
270
|
+
return actions.map((action) =>
|
|
271
|
+
action.key === actionKey ? { ...action, active } : action
|
|
272
|
+
)
|
|
273
|
+
}
|
package/src/utils/menuHistory.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { LayerData } from '../types'
|
|
2
2
|
|
|
3
3
|
const MENU_HISTORY_KEY = 'menuHistory'
|
|
4
|
+
const MENU_COLLAPSE_KEY = 'menuCollapseHistory'
|
|
4
5
|
|
|
5
|
-
const
|
|
6
|
+
const readJsonObject = (storageKey: string): Record<string, boolean> => {
|
|
6
7
|
try {
|
|
7
|
-
const raw = window.sessionStorage.getItem(
|
|
8
|
+
const raw = window.sessionStorage.getItem(storageKey)
|
|
8
9
|
if (!raw) return {}
|
|
9
10
|
|
|
10
11
|
const parsed: unknown = JSON.parse(raw)
|
|
@@ -18,31 +19,35 @@ const readHistory = (): Record<string, boolean> => {
|
|
|
18
19
|
}
|
|
19
20
|
}
|
|
20
21
|
|
|
21
|
-
|
|
22
|
+
const writeJsonObject = (storageKey: string, value: Record<string, boolean>): void => {
|
|
22
23
|
try {
|
|
23
|
-
|
|
24
|
-
window.sessionStorage.setItem(
|
|
25
|
-
MENU_HISTORY_KEY,
|
|
26
|
-
JSON.stringify({ ...history, [layer.key]: layer.active })
|
|
27
|
-
)
|
|
24
|
+
window.sessionStorage.setItem(storageKey, JSON.stringify(value))
|
|
28
25
|
} catch {
|
|
29
|
-
// sessionStorage indisponível ou JSON inválido — ignora persistência
|
|
30
26
|
}
|
|
31
27
|
}
|
|
32
28
|
|
|
33
|
-
|
|
29
|
+
export const setHistory = (layer: LayerData): void => {
|
|
30
|
+
const history = readJsonObject(MENU_HISTORY_KEY)
|
|
31
|
+
writeJsonObject(MENU_HISTORY_KEY, { ...history, [layer.key]: layer.active })
|
|
32
|
+
}
|
|
33
|
+
|
|
34
34
|
export const getHistory = (layerKey: string): boolean | undefined => {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
35
|
+
const history = readJsonObject(MENU_HISTORY_KEY)
|
|
36
|
+
const isActive = history[layerKey]
|
|
37
|
+
return isActive !== undefined ? isActive : undefined
|
|
38
|
+
}
|
|
38
39
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
40
|
+
export const setGroupCollapsedHistory = (groupKey: string, collapsed: boolean): void => {
|
|
41
|
+
const history = readJsonObject(MENU_COLLAPSE_KEY)
|
|
42
|
+
writeJsonObject(MENU_COLLAPSE_KEY, { ...history, [groupKey]: collapsed })
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export const getGroupCollapsedHistory = (groupKey: string): boolean | undefined => {
|
|
46
|
+
const history = readJsonObject(MENU_COLLAPSE_KEY)
|
|
47
|
+
const collapsed = history[groupKey]
|
|
48
|
+
return collapsed !== undefined ? collapsed : undefined
|
|
43
49
|
}
|
|
44
50
|
|
|
45
|
-
/** Resolve `active`/`activeDefault` sem mutar o objeto original (mesma regra do fluxo legado). */
|
|
46
51
|
export const resolveLayerActiveState = (layer: LayerData, persist: boolean): LayerData => {
|
|
47
52
|
const savedActive = persist ? getHistory(layer.key) : undefined
|
|
48
53
|
|
|
@@ -61,7 +66,18 @@ export const resolveLayerActiveState = (layer: LayerData, persist: boolean): Lay
|
|
|
61
66
|
return { ...layer, active, activeDefault }
|
|
62
67
|
}
|
|
63
68
|
|
|
64
|
-
|
|
69
|
+
export const resolveGroupCollapsedState = (
|
|
70
|
+
groupKey: string,
|
|
71
|
+
collapsedFromConfig: boolean | undefined,
|
|
72
|
+
persist: boolean
|
|
73
|
+
): boolean => {
|
|
74
|
+
if (persist) {
|
|
75
|
+
const saved = getGroupCollapsedHistory(groupKey)
|
|
76
|
+
if (saved !== undefined) return saved
|
|
77
|
+
}
|
|
78
|
+
return collapsedFromConfig ?? false
|
|
79
|
+
}
|
|
80
|
+
|
|
65
81
|
export const shouldInitLayerOnMap = (layer: LayerData, persist: boolean): boolean => {
|
|
66
82
|
const resolved = resolveLayerActiveState(layer, persist)
|
|
67
83
|
|