@open-pioneer/toc 0.7.0 → 0.8.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/CHANGELOG.md +39 -0
- package/Context.d.ts +11 -0
- package/Context.js +14 -0
- package/Context.js.map +1 -0
- package/LayerList.js +46 -121
- package/LayerList.js.map +1 -1
- package/README.md +11 -0
- package/Toc.d.ts +5 -0
- package/Toc.js +6 -3
- package/Toc.js.map +1 -1
- package/Tools.d.ts +1 -1
- package/Tools.js +10 -8
- package/Tools.js.map +1 -1
- package/package.json +9 -7
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,44 @@
|
|
|
1
1
|
# @open-pioneer/toc
|
|
2
2
|
|
|
3
|
+
## 0.8.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 2fa8020: Update trails core package dependencies.
|
|
8
|
+
|
|
9
|
+
- Also updates Chakra UI to the latest 2.x version and Chakra React Select to version 5.
|
|
10
|
+
- Removes any obsolete references to `@chakra-ui/system`.
|
|
11
|
+
This dependency seems to be no longer required and may lead to duplicate packages in your dependency tree.
|
|
12
|
+
|
|
13
|
+
- 7ae9f90: When showing a layer via the toc, all parent layers of that layer will also be made visible.
|
|
14
|
+
|
|
15
|
+
This can be disabled by configuring `autoShowParents={false}` on the `TOC` component.
|
|
16
|
+
|
|
17
|
+
```jsx
|
|
18
|
+
// Default: true
|
|
19
|
+
<Toc autoShowParents={false} />
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
### Patch Changes
|
|
23
|
+
|
|
24
|
+
- e7978a8: Use reactive map model APIs to access the current set of layers and their attributes.
|
|
25
|
+
- 49f0207: Update trails core packages to version 2.4.0
|
|
26
|
+
- 7ae9f90: Implement support for `GroupLayer`.
|
|
27
|
+
The hierarchy of (possibly nested) groups is visualized by rendering them as a tree.
|
|
28
|
+
- Updated dependencies [b717121]
|
|
29
|
+
- Updated dependencies [e7978a8]
|
|
30
|
+
- Updated dependencies [7a5f1e1]
|
|
31
|
+
- Updated dependencies [7ae9f90]
|
|
32
|
+
- Updated dependencies [e7978a8]
|
|
33
|
+
- Updated dependencies [d8337a6]
|
|
34
|
+
- Updated dependencies [49f0207]
|
|
35
|
+
- Updated dependencies [b2127df]
|
|
36
|
+
- Updated dependencies [2fa8020]
|
|
37
|
+
- Updated dependencies [7ae9f90]
|
|
38
|
+
- Updated dependencies [d8337a6]
|
|
39
|
+
- @open-pioneer/map@0.8.0
|
|
40
|
+
- @open-pioneer/basemap-switcher@0.8.0
|
|
41
|
+
|
|
3
42
|
## 0.7.0
|
|
4
43
|
|
|
5
44
|
### Minor Changes
|
package/Context.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Toc context to pass global widget options around (to avoid props drilling).
|
|
3
|
+
*
|
|
4
|
+
* @internal
|
|
5
|
+
*/
|
|
6
|
+
export interface TocWidgetOptions {
|
|
7
|
+
/** True: When showing a child, show all parents as well (`setVisible(true)`). */
|
|
8
|
+
autoShowParents: boolean;
|
|
9
|
+
}
|
|
10
|
+
export declare const TocWidgetOptionsProvider: React.Provider<TocWidgetOptions>;
|
|
11
|
+
export declare function useTocWidgetOptions(): TocWidgetOptions;
|
package/Context.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { createContext, useContext } from 'react';
|
|
2
|
+
|
|
3
|
+
const TocWidgetOptionsContext = createContext(void 0);
|
|
4
|
+
const TocWidgetOptionsProvider = TocWidgetOptionsContext.Provider;
|
|
5
|
+
function useTocWidgetOptions() {
|
|
6
|
+
const context = useContext(TocWidgetOptionsContext);
|
|
7
|
+
if (!context) {
|
|
8
|
+
throw new Error("useTocWidgetOptions must be used within a TocWidgetOptionsProvider");
|
|
9
|
+
}
|
|
10
|
+
return context;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export { TocWidgetOptionsProvider, useTocWidgetOptions };
|
|
14
|
+
//# sourceMappingURL=Context.js.map
|
package/Context.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Context.js","sources":["Context.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport { createContext, useContext } from \"react\";\n\n/**\n * Toc context to pass global widget options around (to avoid props drilling).\n *\n * @internal\n */\nexport interface TocWidgetOptions {\n /** True: When showing a child, show all parents as well (`setVisible(true)`). */\n autoShowParents: boolean;\n}\n\nconst TocWidgetOptionsContext = createContext<TocWidgetOptions | undefined>(undefined);\n\nexport const TocWidgetOptionsProvider =\n TocWidgetOptionsContext.Provider as React.Provider<TocWidgetOptions>;\n\nexport function useTocWidgetOptions(): TocWidgetOptions {\n const context = useContext(TocWidgetOptionsContext);\n if (!context) {\n throw new Error(\"useTocWidgetOptions must be used within a TocWidgetOptionsProvider\");\n }\n return context;\n}\n"],"names":[],"mappings":";;AAcA,MAAM,uBAAA,GAA0B,cAA4C,KAAS,CAAA,CAAA,CAAA;AAE9E,MAAM,2BACT,uBAAwB,CAAA,SAAA;AAErB,SAAS,mBAAwC,GAAA;AACpD,EAAM,MAAA,OAAA,GAAU,WAAW,uBAAuB,CAAA,CAAA;AAClD,EAAA,IAAI,CAAC,OAAS,EAAA;AACV,IAAM,MAAA,IAAI,MAAM,oEAAoE,CAAA,CAAA;AAAA,GACxF;AACA,EAAO,OAAA,OAAA,CAAA;AACX;;;;"}
|
package/LayerList.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
2
2
|
import { Text, List, Box, Flex, Checkbox, Tooltip, Spacer, Popover, PopoverTrigger, Button, Portal, PopoverContent, PopoverArrow, PopoverCloseButton, PopoverHeader, PopoverBody } from '@open-pioneer/chakra-integration';
|
|
3
3
|
import { isSublayer } from '@open-pioneer/map';
|
|
4
|
+
import { useReactiveSnapshot } from '@open-pioneer/reactivity';
|
|
4
5
|
import classNames from 'classnames';
|
|
5
6
|
import { useIntl } from './_virtual/_virtual-pioneer-module_react-hooks.js';
|
|
6
|
-
import { useCallback, useSyncExternalStore, useRef } from 'react';
|
|
7
7
|
import { FiAlertTriangle, FiMoreVertical } from 'react-icons/fi';
|
|
8
|
+
import { useTocWidgetOptions } from './Context.js';
|
|
8
9
|
|
|
9
10
|
function LayerList(props) {
|
|
10
11
|
const { map, "aria-label": ariaLabel } = props;
|
|
@@ -13,12 +14,12 @@ function LayerList(props) {
|
|
|
13
14
|
if (!layers.length) {
|
|
14
15
|
return /* @__PURE__ */ jsx(Text, { className: "toc-missing-layers", "aria-label": ariaLabel, children: intl.formatMessage({ id: "missingLayers" }) });
|
|
15
16
|
}
|
|
16
|
-
return createList(layers,
|
|
17
|
+
return createList(layers, {
|
|
17
18
|
"aria-label": ariaLabel
|
|
18
19
|
});
|
|
19
20
|
}
|
|
20
|
-
function createList(layers,
|
|
21
|
-
const items = layers.map((layer) => /* @__PURE__ */ jsx(LayerItem, { layer
|
|
21
|
+
function createList(layers, listProps) {
|
|
22
|
+
const items = layers.map((layer) => /* @__PURE__ */ jsx(LayerItem, { layer }, layer.id));
|
|
22
23
|
return /* @__PURE__ */ jsx(
|
|
23
24
|
List,
|
|
24
25
|
{
|
|
@@ -32,15 +33,22 @@ function createList(layers, intl, listProps) {
|
|
|
32
33
|
);
|
|
33
34
|
}
|
|
34
35
|
function LayerItem(props) {
|
|
35
|
-
const { layer
|
|
36
|
-
const
|
|
37
|
-
const
|
|
38
|
-
const
|
|
36
|
+
const { layer } = props;
|
|
37
|
+
const intl = useIntl();
|
|
38
|
+
const options = useTocWidgetOptions();
|
|
39
|
+
const { title, description, isVisible } = useReactiveSnapshot(() => {
|
|
40
|
+
return {
|
|
41
|
+
title: layer.title,
|
|
42
|
+
description: layer.description,
|
|
43
|
+
isVisible: layer.visible
|
|
44
|
+
};
|
|
45
|
+
}, [layer]);
|
|
46
|
+
const childLayers = useChildLayers(layer);
|
|
39
47
|
const isAvailable = useLoadState(layer) !== "error";
|
|
40
48
|
const notAvailableLabel = intl.formatMessage({ id: "layerNotAvailable" });
|
|
41
49
|
let nestedChildren;
|
|
42
|
-
if (
|
|
43
|
-
nestedChildren = createList(
|
|
50
|
+
if (childLayers?.length) {
|
|
51
|
+
nestedChildren = createList(childLayers, {
|
|
44
52
|
ml: 4,
|
|
45
53
|
"aria-label": intl.formatMessage({ id: "childgroupLabel" }, { title })
|
|
46
54
|
});
|
|
@@ -63,7 +71,7 @@ function LayerItem(props) {
|
|
|
63
71
|
"aria-label": title + (!isAvailable ? " " + notAvailableLabel : ""),
|
|
64
72
|
isChecked: isVisible,
|
|
65
73
|
isDisabled: !isAvailable,
|
|
66
|
-
onChange: (event) =>
|
|
74
|
+
onChange: (event) => updateLayerVisibility(layer, event.target.checked, options.autoShowParents),
|
|
67
75
|
children: title
|
|
68
76
|
}
|
|
69
77
|
),
|
|
@@ -85,17 +93,30 @@ function LayerItem(props) {
|
|
|
85
93
|
}
|
|
86
94
|
),
|
|
87
95
|
/* @__PURE__ */ jsx(Spacer, {}),
|
|
88
|
-
|
|
96
|
+
description && /* @__PURE__ */ jsx(
|
|
97
|
+
LayerItemDescriptor,
|
|
98
|
+
{
|
|
99
|
+
layer,
|
|
100
|
+
title,
|
|
101
|
+
description,
|
|
102
|
+
intl
|
|
103
|
+
}
|
|
104
|
+
)
|
|
89
105
|
]
|
|
90
106
|
}
|
|
91
107
|
),
|
|
92
108
|
nestedChildren
|
|
93
109
|
] });
|
|
94
110
|
}
|
|
111
|
+
function updateLayerVisibility(layer, visible, autoShowParents) {
|
|
112
|
+
layer.setVisible(visible);
|
|
113
|
+
if (visible && autoShowParents && layer.parent) {
|
|
114
|
+
updateLayerVisibility(layer.parent, true, true);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
95
117
|
function LayerItemDescriptor(props) {
|
|
96
|
-
const { layer, title, intl } = props;
|
|
118
|
+
const { layer, title, description, intl } = props;
|
|
97
119
|
const buttonLabel = intl.formatMessage({ id: "descriptionLabel" });
|
|
98
|
-
const description = useLayerDescription(layer);
|
|
99
120
|
const isAvailable = useLoadState(layer) !== "error";
|
|
100
121
|
return /* @__PURE__ */ jsxs(Popover, { placement: "bottom-start", children: [
|
|
101
122
|
/* @__PURE__ */ jsx(PopoverTrigger, { children: /* @__PURE__ */ jsx(
|
|
@@ -119,121 +140,25 @@ function LayerItemDescriptor(props) {
|
|
|
119
140
|
] }) })
|
|
120
141
|
] });
|
|
121
142
|
}
|
|
122
|
-
function useLayerDescription(layer) {
|
|
123
|
-
const getSnapshot = useCallback(() => layer.description, [layer]);
|
|
124
|
-
const subscribe = useCallback(
|
|
125
|
-
(cb) => {
|
|
126
|
-
const resource = layer.on("changed:description", cb);
|
|
127
|
-
return () => resource.destroy();
|
|
128
|
-
},
|
|
129
|
-
[layer]
|
|
130
|
-
);
|
|
131
|
-
return useSyncExternalStore(subscribe, getSnapshot);
|
|
132
|
-
}
|
|
133
|
-
function useTitle(layer) {
|
|
134
|
-
const getSnapshot = useCallback(() => layer.title, [layer]);
|
|
135
|
-
const subscribe = useCallback(
|
|
136
|
-
(cb) => {
|
|
137
|
-
const resource = layer.on("changed:title", cb);
|
|
138
|
-
return () => resource.destroy();
|
|
139
|
-
},
|
|
140
|
-
[layer]
|
|
141
|
-
);
|
|
142
|
-
return useSyncExternalStore(subscribe, getSnapshot);
|
|
143
|
-
}
|
|
144
|
-
function useVisibility(layer) {
|
|
145
|
-
const getSnapshot = useCallback(() => layer.visible, [layer]);
|
|
146
|
-
const subscribe = useCallback(
|
|
147
|
-
(cb) => {
|
|
148
|
-
const resource = layer.on("changed:visible", cb);
|
|
149
|
-
return () => resource.destroy();
|
|
150
|
-
},
|
|
151
|
-
[layer]
|
|
152
|
-
);
|
|
153
|
-
const isVisible = useSyncExternalStore(subscribe, getSnapshot);
|
|
154
|
-
const setVisible = useCallback(
|
|
155
|
-
(visible) => {
|
|
156
|
-
layer.setVisible(visible);
|
|
157
|
-
},
|
|
158
|
-
[layer]
|
|
159
|
-
);
|
|
160
|
-
return {
|
|
161
|
-
isVisible,
|
|
162
|
-
setVisible
|
|
163
|
-
};
|
|
164
|
-
}
|
|
165
143
|
function useLayers(map) {
|
|
166
|
-
|
|
167
|
-
(
|
|
168
|
-
|
|
169
|
-
return () => resource.destroy();
|
|
170
|
-
},
|
|
171
|
-
[map]
|
|
172
|
-
);
|
|
173
|
-
const getValue = useCallback(() => {
|
|
174
|
-
let layers = map.layers.getOperationalLayers({ sortByDisplayOrder: true }) ?? [];
|
|
175
|
-
layers = layers.reverse();
|
|
144
|
+
return useReactiveSnapshot(() => {
|
|
145
|
+
const layers = map.layers.getOperationalLayers({ sortByDisplayOrder: true }) ?? [];
|
|
146
|
+
layers.reverse();
|
|
176
147
|
return layers;
|
|
177
148
|
}, [map]);
|
|
178
|
-
return useCachedExternalStore(subscribe, getValue);
|
|
179
149
|
}
|
|
180
|
-
function
|
|
181
|
-
|
|
182
|
-
(
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
},
|
|
186
|
-
[layer]
|
|
187
|
-
);
|
|
188
|
-
const getValue = useCallback(() => {
|
|
189
|
-
const sublayers = layer.sublayers;
|
|
190
|
-
if (!sublayers) {
|
|
191
|
-
return void 0;
|
|
192
|
-
}
|
|
193
|
-
let layers = layer.sublayers?.getSublayers({ sortByDisplayOrder: true });
|
|
194
|
-
layers = layers.reverse();
|
|
195
|
-
return layers;
|
|
150
|
+
function useChildLayers(layer) {
|
|
151
|
+
return useReactiveSnapshot(() => {
|
|
152
|
+
const children = layer.children?.getItems({ sortByDisplayOrder: true });
|
|
153
|
+
children?.reverse();
|
|
154
|
+
return children;
|
|
196
155
|
}, [layer]);
|
|
197
|
-
return useCachedExternalStore(subscribe, getValue);
|
|
198
156
|
}
|
|
199
157
|
function useLoadState(layer) {
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
(cb) => {
|
|
203
|
-
const resource = target.on("changed:loadState", cb);
|
|
204
|
-
return () => resource.destroy();
|
|
205
|
-
},
|
|
206
|
-
[target]
|
|
207
|
-
);
|
|
208
|
-
const getSnapshot = useCallback(() => {
|
|
158
|
+
return useReactiveSnapshot(() => {
|
|
159
|
+
const target = isSublayer(layer) ? layer.parentLayer : layer;
|
|
209
160
|
return target.loadState;
|
|
210
|
-
}, [
|
|
211
|
-
return useSyncExternalStore(subscribe, getSnapshot);
|
|
212
|
-
}
|
|
213
|
-
function useCachedExternalStore(subscribe, getValue) {
|
|
214
|
-
const cachedValue = useRef();
|
|
215
|
-
const cachedSubscribe = useCallback(
|
|
216
|
-
(cb) => {
|
|
217
|
-
const cleanup = subscribe(() => {
|
|
218
|
-
cachedValue.current = void 0;
|
|
219
|
-
cb();
|
|
220
|
-
});
|
|
221
|
-
return () => {
|
|
222
|
-
cachedValue.current = void 0;
|
|
223
|
-
cleanup();
|
|
224
|
-
};
|
|
225
|
-
},
|
|
226
|
-
[subscribe]
|
|
227
|
-
);
|
|
228
|
-
const cachedGetSnapshot = useCallback(() => {
|
|
229
|
-
if (cachedValue.current) {
|
|
230
|
-
return cachedValue.current.value;
|
|
231
|
-
}
|
|
232
|
-
const value = getValue();
|
|
233
|
-
cachedValue.current = { value };
|
|
234
|
-
return value;
|
|
235
|
-
}, [getValue]);
|
|
236
|
-
return useSyncExternalStore(cachedSubscribe, cachedGetSnapshot);
|
|
161
|
+
}, [layer]);
|
|
237
162
|
}
|
|
238
163
|
function slug(id) {
|
|
239
164
|
return id.toLowerCase().replace(/[^a-z0-9 -]/g, "").replace(/\s+/g, "-").replace(/-+/g, "-");
|
package/LayerList.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LayerList.js","sources":["LayerList.tsx"],"sourcesContent":["// SPDX-FileCopyrightText: 2023 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport {\n Box,\n Button,\n Checkbox,\n Flex,\n List,\n ListProps,\n Popover,\n PopoverArrow,\n PopoverBody,\n PopoverCloseButton,\n PopoverContent,\n PopoverHeader,\n PopoverTrigger,\n Portal,\n Spacer,\n Text,\n Tooltip\n} from \"@open-pioneer/chakra-integration\";\nimport { Layer, AnyLayer, MapModel, Sublayer, isSublayer } from \"@open-pioneer/map\";\nimport { PackageIntl } from \"@open-pioneer/runtime\";\nimport classNames from \"classnames\";\nimport { useIntl } from \"open-pioneer:react-hooks\";\nimport { useCallback, useRef, useSyncExternalStore } from \"react\";\nimport { FiAlertTriangle, FiMoreVertical } from \"react-icons/fi\";\n\n/**\n * Lists the (top level) operational layers in the map.\n *\n * Layer Groups are skipped in the current implementation.\n */\nexport function LayerList(props: { map: MapModel; \"aria-label\"?: string }): JSX.Element {\n const { map, \"aria-label\": ariaLabel } = props;\n const intl = useIntl();\n const layers = useLayers(map);\n if (!layers.length) {\n return (\n <Text className=\"toc-missing-layers\" aria-label={ariaLabel}>\n {intl.formatMessage({ id: \"missingLayers\" })}\n </Text>\n );\n }\n\n return createList(layers, intl, {\n \"aria-label\": ariaLabel\n });\n}\n\nfunction createList(layers: AnyLayer[], intl: PackageIntl, listProps: ListProps) {\n const items = layers.map((layer) => <LayerItem key={layer.id} layer={layer} intl={intl} />);\n return (\n <List\n // Note: not using UnorderedList because it adds default margins\n as=\"ul\"\n className=\"toc-layer-list\"\n listStyleType=\"none\"\n role=\"group\"\n {...listProps}\n >\n {items}\n </List>\n );\n}\n\n/**\n * Renders a single layer as a list item.\n *\n * The item may have further nested list items if there are sublayers present.\n */\nfunction LayerItem(props: { layer: AnyLayer; intl: PackageIntl }): JSX.Element {\n const { layer, intl } = props;\n const title = useTitle(layer);\n const { isVisible, setVisible } = useVisibility(layer);\n const sublayers = useSublayers(layer);\n const isAvailable = useLoadState(layer) !== \"error\";\n const notAvailableLabel = intl.formatMessage({ id: \"layerNotAvailable\" });\n\n let nestedChildren;\n if (sublayers?.length) {\n nestedChildren = createList(sublayers, intl, {\n ml: 4,\n \"aria-label\": intl.formatMessage({ id: \"childgroupLabel\" }, { title: title })\n });\n }\n\n return (\n <Box as=\"li\" className={classNames(\"toc-layer-item\", `layer-${slug(layer.id)}`)}>\n <Flex\n className=\"toc-layer-item-content\"\n width=\"100%\"\n flexDirection=\"row\"\n align=\"center\"\n justifyContent=\"space-between\"\n /** Gap to prevent bleeding of the buttons hover style into the layer title */\n gap={2}\n /** Aligned to the size of the (potential) menu button in LayerItemDescriptor */\n minHeight={10}\n >\n <Checkbox\n // Keyboard navigation jumps only to Checkboxes and uses the texts inside this DOM node. The aria-labels of Tooltip and Icon is ignored by screenreader because they are no child element of the checkbox. To consider the notAvailableLabel, an aria-label at the checkbox is necessary.\n aria-label={title + (!isAvailable ? \" \" + notAvailableLabel : \"\")}\n isChecked={isVisible}\n isDisabled={!isAvailable}\n onChange={(event) => setVisible(event.target.checked)}\n >\n {title}\n </Checkbox>\n {!isAvailable && (\n <Tooltip\n className=\"toc-layer-item-content-tooltip\"\n label={notAvailableLabel}\n placement=\"right\"\n openDelay={500}\n >\n <span>\n <FiAlertTriangle\n className=\"toc-layer-item-content-icon\"\n color={\"red\"}\n aria-label={notAvailableLabel}\n />\n </span>\n </Tooltip>\n )}\n <Spacer></Spacer>\n {layer.description && (\n <LayerItemDescriptor layer={layer} title={title} intl={intl} />\n )}\n </Flex>\n {nestedChildren}\n </Box>\n );\n}\n\nfunction LayerItemDescriptor(props: {\n layer: AnyLayer;\n title: string;\n intl: PackageIntl;\n}): JSX.Element {\n const { layer, title, intl } = props;\n const buttonLabel = intl.formatMessage({ id: \"descriptionLabel\" });\n const description = useLayerDescription(layer);\n const isAvailable = useLoadState(layer) !== \"error\";\n\n return (\n <Popover placement=\"bottom-start\">\n <PopoverTrigger>\n <Button\n isDisabled={!isAvailable}\n className=\"toc-layer-item-details-button\"\n aria-label={buttonLabel}\n borderRadius=\"full\"\n iconSpacing={0}\n padding={0}\n variant=\"ghost\"\n leftIcon={<FiMoreVertical />}\n />\n </PopoverTrigger>\n <Portal>\n <PopoverContent className=\"toc-layer-item-details\" overflowY=\"auto\" maxHeight=\"400\">\n <PopoverArrow />\n <PopoverCloseButton mt={1} />\n <PopoverHeader>{title}</PopoverHeader>\n <PopoverBody>{description}</PopoverBody>\n </PopoverContent>\n </Portal>\n </Popover>\n );\n}\n\nfunction useLayerDescription(layer: AnyLayer): string {\n const getSnapshot = useCallback(() => layer.description, [layer]);\n const subscribe = useCallback(\n (cb: () => void) => {\n const resource = layer.on(\"changed:description\", cb);\n return () => resource.destroy();\n },\n [layer]\n );\n return useSyncExternalStore(subscribe, getSnapshot);\n}\n\n/** Returns the layers current title. */\nfunction useTitle(layer: AnyLayer): string {\n const getSnapshot = useCallback(() => layer.title, [layer]);\n const subscribe = useCallback(\n (cb: () => void) => {\n const resource = layer.on(\"changed:title\", cb);\n return () => resource.destroy();\n },\n [layer]\n );\n\n return useSyncExternalStore(subscribe, getSnapshot);\n}\n\n/** Returns the layer's current visibility and a function to change it. */\nfunction useVisibility(layer: AnyLayer): {\n isVisible: boolean;\n setVisible(visible: boolean): void;\n} {\n const getSnapshot = useCallback(() => layer.visible, [layer]);\n const subscribe = useCallback(\n (cb: () => void) => {\n const resource = layer.on(\"changed:visible\", cb);\n return () => resource.destroy();\n },\n [layer]\n );\n const isVisible = useSyncExternalStore(subscribe, getSnapshot);\n const setVisible = useCallback(\n (visible: boolean) => {\n layer.setVisible(visible);\n },\n [layer]\n );\n\n return {\n isVisible,\n setVisible\n };\n}\n\n/** Returns the top level operation layers (without LayerGroups). */\nfunction useLayers(map: MapModel): Layer[] {\n const subscribe = useCallback(\n (cb: () => void) => {\n const resource = map.layers.on(\"changed\", cb);\n return () => resource.destroy();\n },\n [map]\n );\n const getValue = useCallback(() => {\n let layers = map.layers.getOperationalLayers({ sortByDisplayOrder: true }) ?? [];\n layers = layers.reverse();\n return layers;\n }, [map]);\n return useCachedExternalStore(subscribe, getValue);\n}\n\n/** Returns the sublayers of the given layer (or undefined, if the sublayer cannot have any). */\nfunction useSublayers(layer: AnyLayer): Sublayer[] | undefined {\n const subscribe = useCallback(\n (cb: () => void) => {\n const resource = layer.sublayers?.on(\"changed\", cb);\n return () => resource?.destroy();\n },\n [layer]\n );\n const getValue = useCallback((): Sublayer[] | undefined => {\n const sublayers = layer.sublayers;\n if (!sublayers) {\n return undefined;\n }\n\n let layers = layer.sublayers?.getSublayers({ sortByDisplayOrder: true });\n layers = layers.reverse();\n return layers;\n }, [layer]);\n return useCachedExternalStore(subscribe, getValue);\n}\n\n/** Returns the layers current state. */\nfunction useLoadState(layer: AnyLayer): string {\n // for sublayers, use the state of the parent\n const target = isSublayer(layer) ? layer.parentLayer : layer;\n const subscribe = useCallback(\n (cb: () => void) => {\n const resource = target.on(\"changed:loadState\", cb);\n return () => resource.destroy();\n },\n [target]\n );\n\n const getSnapshot = useCallback(() => {\n return target.loadState;\n }, [target]);\n\n return useSyncExternalStore(subscribe, getSnapshot);\n}\n\n/**\n * This hooks wraps an external store that does not cache its own values, i.e.\n * it may return a different value each time from `getValue()`.\n *\n * The results returned from `getValue()` are cached locally; the cache\n * is only invalidated on re-subscription or if a change event has been observed.\n */\nfunction useCachedExternalStore<T>(\n subscribe: (onStoreChanged: () => void) => () => void,\n getValue: () => T\n): T {\n const cachedValue = useRef<{ value: T } | undefined>();\n\n const cachedSubscribe = useCallback(\n (cb: () => void) => {\n const cleanup = subscribe(() => {\n // Reset cache on change\n cachedValue.current = undefined;\n cb();\n });\n return () => {\n // Reset cache when (re-) subscribing\n cachedValue.current = undefined;\n cleanup();\n };\n },\n [subscribe]\n );\n const cachedGetSnapshot = useCallback(() => {\n // Return cached values if still up to date (see resets above).\n if (cachedValue.current) {\n return cachedValue.current.value;\n }\n\n // Compute values and cache the result.\n const value = getValue();\n cachedValue.current = { value };\n return value;\n }, [getValue]);\n return useSyncExternalStore(cachedSubscribe, cachedGetSnapshot);\n}\n\nfunction slug(id: string) {\n return id\n .toLowerCase()\n .replace(/[^a-z0-9 -]/g, \"\")\n .replace(/\\s+/g, \"-\")\n .replace(/-+/g, \"-\");\n}\n"],"names":[],"mappings":";;;;;;;;AAiCO,SAAS,UAAU,KAA8D,EAAA;AACpF,EAAA,MAAM,EAAE,GAAA,EAAK,YAAc,EAAA,SAAA,EAAc,GAAA,KAAA,CAAA;AACzC,EAAA,MAAM,OAAO,OAAQ,EAAA,CAAA;AACrB,EAAM,MAAA,MAAA,GAAS,UAAU,GAAG,CAAA,CAAA;AAC5B,EAAI,IAAA,CAAC,OAAO,MAAQ,EAAA;AAChB,IAAA,uBACK,GAAA,CAAA,IAAA,EAAA,EAAK,SAAU,EAAA,oBAAA,EAAqB,YAAY,EAAA,SAAA,EAC5C,QAAK,EAAA,IAAA,CAAA,aAAA,CAAc,EAAE,EAAA,EAAI,eAAgB,EAAC,CAC/C,EAAA,CAAA,CAAA;AAAA,GAER;AAEA,EAAO,OAAA,UAAA,CAAW,QAAQ,IAAM,EAAA;AAAA,IAC5B,YAAc,EAAA,SAAA;AAAA,GACjB,CAAA,CAAA;AACL,CAAA;AAEA,SAAS,UAAA,CAAW,MAAoB,EAAA,IAAA,EAAmB,SAAsB,EAAA;AAC7E,EAAM,MAAA,KAAA,GAAQ,MAAO,CAAA,GAAA,CAAI,CAAC,KAAA,qBAAW,GAAA,CAAA,SAAA,EAAA,EAAyB,KAAc,EAAA,IAAA,EAAA,EAAxB,KAAM,CAAA,EAA8B,CAAE,CAAA,CAAA;AAC1F,EACI,uBAAA,GAAA;AAAA,IAAC,IAAA;AAAA,IAAA;AAAA,MAEG,EAAG,EAAA,IAAA;AAAA,MACH,SAAU,EAAA,gBAAA;AAAA,MACV,aAAc,EAAA,MAAA;AAAA,MACd,IAAK,EAAA,OAAA;AAAA,MACJ,GAAG,SAAA;AAAA,MAEH,QAAA,EAAA,KAAA;AAAA,KAAA;AAAA,GACL,CAAA;AAER,CAAA;AAOA,SAAS,UAAU,KAA4D,EAAA;AAC3E,EAAM,MAAA,EAAE,KAAO,EAAA,IAAA,EAAS,GAAA,KAAA,CAAA;AACxB,EAAM,MAAA,KAAA,GAAQ,SAAS,KAAK,CAAA,CAAA;AAC5B,EAAA,MAAM,EAAE,SAAA,EAAW,UAAW,EAAA,GAAI,cAAc,KAAK,CAAA,CAAA;AACrD,EAAM,MAAA,SAAA,GAAY,aAAa,KAAK,CAAA,CAAA;AACpC,EAAM,MAAA,WAAA,GAAc,YAAa,CAAA,KAAK,CAAM,KAAA,OAAA,CAAA;AAC5C,EAAA,MAAM,oBAAoB,IAAK,CAAA,aAAA,CAAc,EAAE,EAAA,EAAI,qBAAqB,CAAA,CAAA;AAExE,EAAI,IAAA,cAAA,CAAA;AACJ,EAAA,IAAI,WAAW,MAAQ,EAAA;AACnB,IAAiB,cAAA,GAAA,UAAA,CAAW,WAAW,IAAM,EAAA;AAAA,MACzC,EAAI,EAAA,CAAA;AAAA,MACJ,YAAA,EAAc,KAAK,aAAc,CAAA,EAAE,IAAI,iBAAkB,EAAA,EAAG,EAAE,KAAA,EAAc,CAAA;AAAA,KAC/E,CAAA,CAAA;AAAA,GACL;AAEA,EAAA,uBACK,IAAA,CAAA,GAAA,EAAA,EAAI,EAAG,EAAA,IAAA,EAAK,SAAW,EAAA,UAAA,CAAW,gBAAkB,EAAA,CAAA,MAAA,EAAS,IAAK,CAAA,KAAA,CAAM,EAAE,CAAC,EAAE,CAC1E,EAAA,QAAA,EAAA;AAAA,oBAAA,IAAA;AAAA,MAAC,IAAA;AAAA,MAAA;AAAA,QACG,SAAU,EAAA,wBAAA;AAAA,QACV,KAAM,EAAA,MAAA;AAAA,QACN,aAAc,EAAA,KAAA;AAAA,QACd,KAAM,EAAA,QAAA;AAAA,QACN,cAAe,EAAA,eAAA;AAAA,QAEf,GAAK,EAAA,CAAA;AAAA,QAEL,SAAW,EAAA,EAAA;AAAA,QAEX,QAAA,EAAA;AAAA,0BAAA,GAAA;AAAA,YAAC,QAAA;AAAA,YAAA;AAAA,cAEG,YAAY,EAAA,KAAA,IAAS,CAAC,WAAA,GAAc,MAAM,iBAAoB,GAAA,EAAA,CAAA;AAAA,cAC9D,SAAW,EAAA,SAAA;AAAA,cACX,YAAY,CAAC,WAAA;AAAA,cACb,UAAU,CAAC,KAAA,KAAU,UAAW,CAAA,KAAA,CAAM,OAAO,OAAO,CAAA;AAAA,cAEnD,QAAA,EAAA,KAAA;AAAA,aAAA;AAAA,WACL;AAAA,UACC,CAAC,WACE,oBAAA,GAAA;AAAA,YAAC,OAAA;AAAA,YAAA;AAAA,cACG,SAAU,EAAA,gCAAA;AAAA,cACV,KAAO,EAAA,iBAAA;AAAA,cACP,SAAU,EAAA,OAAA;AAAA,cACV,SAAW,EAAA,GAAA;AAAA,cAEX,8BAAC,MACG,EAAA,EAAA,QAAA,kBAAA,GAAA;AAAA,gBAAC,eAAA;AAAA,gBAAA;AAAA,kBACG,SAAU,EAAA,6BAAA;AAAA,kBACV,KAAO,EAAA,KAAA;AAAA,kBACP,YAAY,EAAA,iBAAA;AAAA,iBAAA;AAAA,eAEpB,EAAA,CAAA;AAAA,aAAA;AAAA,WACJ;AAAA,8BAEH,MAAO,EAAA,EAAA,CAAA;AAAA,UACP,MAAM,WACH,oBAAA,GAAA,CAAC,mBAAoB,EAAA,EAAA,KAAA,EAAc,OAAc,IAAY,EAAA,CAAA;AAAA,SAAA;AAAA,OAAA;AAAA,KAErE;AAAA,IACC,cAAA;AAAA,GACL,EAAA,CAAA,CAAA;AAER,CAAA;AAEA,SAAS,oBAAoB,KAIb,EAAA;AACZ,EAAA,MAAM,EAAE,KAAA,EAAO,KAAO,EAAA,IAAA,EAAS,GAAA,KAAA,CAAA;AAC/B,EAAA,MAAM,cAAc,IAAK,CAAA,aAAA,CAAc,EAAE,EAAA,EAAI,oBAAoB,CAAA,CAAA;AACjE,EAAM,MAAA,WAAA,GAAc,oBAAoB,KAAK,CAAA,CAAA;AAC7C,EAAM,MAAA,WAAA,GAAc,YAAa,CAAA,KAAK,CAAM,KAAA,OAAA,CAAA;AAE5C,EACI,uBAAA,IAAA,CAAC,OAAQ,EAAA,EAAA,SAAA,EAAU,cACf,EAAA,QAAA,EAAA;AAAA,oBAAA,GAAA,CAAC,cACG,EAAA,EAAA,QAAA,kBAAA,GAAA;AAAA,MAAC,MAAA;AAAA,MAAA;AAAA,QACG,YAAY,CAAC,WAAA;AAAA,QACb,SAAU,EAAA,+BAAA;AAAA,QACV,YAAY,EAAA,WAAA;AAAA,QACZ,YAAa,EAAA,MAAA;AAAA,QACb,WAAa,EAAA,CAAA;AAAA,QACb,OAAS,EAAA,CAAA;AAAA,QACT,OAAQ,EAAA,OAAA;AAAA,QACR,QAAA,sBAAW,cAAe,EAAA,EAAA,CAAA;AAAA,OAAA;AAAA,KAElC,EAAA,CAAA;AAAA,oBACA,GAAA,CAAC,UACG,QAAC,kBAAA,IAAA,CAAA,cAAA,EAAA,EAAe,WAAU,wBAAyB,EAAA,SAAA,EAAU,MAAO,EAAA,SAAA,EAAU,KAC1E,EAAA,QAAA,EAAA;AAAA,sBAAA,GAAA,CAAC,YAAa,EAAA,EAAA,CAAA;AAAA,sBACd,GAAA,CAAC,kBAAmB,EAAA,EAAA,EAAA,EAAI,CAAG,EAAA,CAAA;AAAA,sBAC3B,GAAA,CAAC,iBAAe,QAAM,EAAA,KAAA,EAAA,CAAA;AAAA,sBACtB,GAAA,CAAC,eAAa,QAAY,EAAA,WAAA,EAAA,CAAA;AAAA,KAAA,EAC9B,CACJ,EAAA,CAAA;AAAA,GACJ,EAAA,CAAA,CAAA;AAER,CAAA;AAEA,SAAS,oBAAoB,KAAyB,EAAA;AAClD,EAAA,MAAM,cAAc,WAAY,CAAA,MAAM,MAAM,WAAa,EAAA,CAAC,KAAK,CAAC,CAAA,CAAA;AAChE,EAAA,MAAM,SAAY,GAAA,WAAA;AAAA,IACd,CAAC,EAAmB,KAAA;AAChB,MAAA,MAAM,QAAW,GAAA,KAAA,CAAM,EAAG,CAAA,qBAAA,EAAuB,EAAE,CAAA,CAAA;AACnD,MAAO,OAAA,MAAM,SAAS,OAAQ,EAAA,CAAA;AAAA,KAClC;AAAA,IACA,CAAC,KAAK,CAAA;AAAA,GACV,CAAA;AACA,EAAO,OAAA,oBAAA,CAAqB,WAAW,WAAW,CAAA,CAAA;AACtD,CAAA;AAGA,SAAS,SAAS,KAAyB,EAAA;AACvC,EAAA,MAAM,cAAc,WAAY,CAAA,MAAM,MAAM,KAAO,EAAA,CAAC,KAAK,CAAC,CAAA,CAAA;AAC1D,EAAA,MAAM,SAAY,GAAA,WAAA;AAAA,IACd,CAAC,EAAmB,KAAA;AAChB,MAAA,MAAM,QAAW,GAAA,KAAA,CAAM,EAAG,CAAA,eAAA,EAAiB,EAAE,CAAA,CAAA;AAC7C,MAAO,OAAA,MAAM,SAAS,OAAQ,EAAA,CAAA;AAAA,KAClC;AAAA,IACA,CAAC,KAAK,CAAA;AAAA,GACV,CAAA;AAEA,EAAO,OAAA,oBAAA,CAAqB,WAAW,WAAW,CAAA,CAAA;AACtD,CAAA;AAGA,SAAS,cAAc,KAGrB,EAAA;AACE,EAAA,MAAM,cAAc,WAAY,CAAA,MAAM,MAAM,OAAS,EAAA,CAAC,KAAK,CAAC,CAAA,CAAA;AAC5D,EAAA,MAAM,SAAY,GAAA,WAAA;AAAA,IACd,CAAC,EAAmB,KAAA;AAChB,MAAA,MAAM,QAAW,GAAA,KAAA,CAAM,EAAG,CAAA,iBAAA,EAAmB,EAAE,CAAA,CAAA;AAC/C,MAAO,OAAA,MAAM,SAAS,OAAQ,EAAA,CAAA;AAAA,KAClC;AAAA,IACA,CAAC,KAAK,CAAA;AAAA,GACV,CAAA;AACA,EAAM,MAAA,SAAA,GAAY,oBAAqB,CAAA,SAAA,EAAW,WAAW,CAAA,CAAA;AAC7D,EAAA,MAAM,UAAa,GAAA,WAAA;AAAA,IACf,CAAC,OAAqB,KAAA;AAClB,MAAA,KAAA,CAAM,WAAW,OAAO,CAAA,CAAA;AAAA,KAC5B;AAAA,IACA,CAAC,KAAK,CAAA;AAAA,GACV,CAAA;AAEA,EAAO,OAAA;AAAA,IACH,SAAA;AAAA,IACA,UAAA;AAAA,GACJ,CAAA;AACJ,CAAA;AAGA,SAAS,UAAU,GAAwB,EAAA;AACvC,EAAA,MAAM,SAAY,GAAA,WAAA;AAAA,IACd,CAAC,EAAmB,KAAA;AAChB,MAAA,MAAM,QAAW,GAAA,GAAA,CAAI,MAAO,CAAA,EAAA,CAAG,WAAW,EAAE,CAAA,CAAA;AAC5C,MAAO,OAAA,MAAM,SAAS,OAAQ,EAAA,CAAA;AAAA,KAClC;AAAA,IACA,CAAC,GAAG,CAAA;AAAA,GACR,CAAA;AACA,EAAM,MAAA,QAAA,GAAW,YAAY,MAAM;AAC/B,IAAI,IAAA,MAAA,GAAS,IAAI,MAAO,CAAA,oBAAA,CAAqB,EAAE,kBAAoB,EAAA,IAAA,EAAM,CAAA,IAAK,EAAC,CAAA;AAC/E,IAAA,MAAA,GAAS,OAAO,OAAQ,EAAA,CAAA;AACxB,IAAO,OAAA,MAAA,CAAA;AAAA,GACX,EAAG,CAAC,GAAG,CAAC,CAAA,CAAA;AACR,EAAO,OAAA,sBAAA,CAAuB,WAAW,QAAQ,CAAA,CAAA;AACrD,CAAA;AAGA,SAAS,aAAa,KAAyC,EAAA;AAC3D,EAAA,MAAM,SAAY,GAAA,WAAA;AAAA,IACd,CAAC,EAAmB,KAAA;AAChB,MAAA,MAAM,QAAW,GAAA,KAAA,CAAM,SAAW,EAAA,EAAA,CAAG,WAAW,EAAE,CAAA,CAAA;AAClD,MAAO,OAAA,MAAM,UAAU,OAAQ,EAAA,CAAA;AAAA,KACnC;AAAA,IACA,CAAC,KAAK,CAAA;AAAA,GACV,CAAA;AACA,EAAM,MAAA,QAAA,GAAW,YAAY,MAA8B;AACvD,IAAA,MAAM,YAAY,KAAM,CAAA,SAAA,CAAA;AACxB,IAAA,IAAI,CAAC,SAAW,EAAA;AACZ,MAAO,OAAA,KAAA,CAAA,CAAA;AAAA,KACX;AAEA,IAAA,IAAI,SAAS,KAAM,CAAA,SAAA,EAAW,aAAa,EAAE,kBAAA,EAAoB,MAAM,CAAA,CAAA;AACvE,IAAA,MAAA,GAAS,OAAO,OAAQ,EAAA,CAAA;AACxB,IAAO,OAAA,MAAA,CAAA;AAAA,GACX,EAAG,CAAC,KAAK,CAAC,CAAA,CAAA;AACV,EAAO,OAAA,sBAAA,CAAuB,WAAW,QAAQ,CAAA,CAAA;AACrD,CAAA;AAGA,SAAS,aAAa,KAAyB,EAAA;AAE3C,EAAA,MAAM,MAAS,GAAA,UAAA,CAAW,KAAK,CAAA,GAAI,MAAM,WAAc,GAAA,KAAA,CAAA;AACvD,EAAA,MAAM,SAAY,GAAA,WAAA;AAAA,IACd,CAAC,EAAmB,KAAA;AAChB,MAAA,MAAM,QAAW,GAAA,MAAA,CAAO,EAAG,CAAA,mBAAA,EAAqB,EAAE,CAAA,CAAA;AAClD,MAAO,OAAA,MAAM,SAAS,OAAQ,EAAA,CAAA;AAAA,KAClC;AAAA,IACA,CAAC,MAAM,CAAA;AAAA,GACX,CAAA;AAEA,EAAM,MAAA,WAAA,GAAc,YAAY,MAAM;AAClC,IAAA,OAAO,MAAO,CAAA,SAAA,CAAA;AAAA,GAClB,EAAG,CAAC,MAAM,CAAC,CAAA,CAAA;AAEX,EAAO,OAAA,oBAAA,CAAqB,WAAW,WAAW,CAAA,CAAA;AACtD,CAAA;AASA,SAAS,sBAAA,CACL,WACA,QACC,EAAA;AACD,EAAA,MAAM,cAAc,MAAiC,EAAA,CAAA;AAErD,EAAA,MAAM,eAAkB,GAAA,WAAA;AAAA,IACpB,CAAC,EAAmB,KAAA;AAChB,MAAM,MAAA,OAAA,GAAU,UAAU,MAAM;AAE5B,QAAA,WAAA,CAAY,OAAU,GAAA,KAAA,CAAA,CAAA;AACtB,QAAG,EAAA,EAAA,CAAA;AAAA,OACN,CAAA,CAAA;AACD,MAAA,OAAO,MAAM;AAET,QAAA,WAAA,CAAY,OAAU,GAAA,KAAA,CAAA,CAAA;AACtB,QAAQ,OAAA,EAAA,CAAA;AAAA,OACZ,CAAA;AAAA,KACJ;AAAA,IACA,CAAC,SAAS,CAAA;AAAA,GACd,CAAA;AACA,EAAM,MAAA,iBAAA,GAAoB,YAAY,MAAM;AAExC,IAAA,IAAI,YAAY,OAAS,EAAA;AACrB,MAAA,OAAO,YAAY,OAAQ,CAAA,KAAA,CAAA;AAAA,KAC/B;AAGA,IAAA,MAAM,QAAQ,QAAS,EAAA,CAAA;AACvB,IAAY,WAAA,CAAA,OAAA,GAAU,EAAE,KAAM,EAAA,CAAA;AAC9B,IAAO,OAAA,KAAA,CAAA;AAAA,GACX,EAAG,CAAC,QAAQ,CAAC,CAAA,CAAA;AACb,EAAO,OAAA,oBAAA,CAAqB,iBAAiB,iBAAiB,CAAA,CAAA;AAClE,CAAA;AAEA,SAAS,KAAK,EAAY,EAAA;AACtB,EAAA,OAAO,EACF,CAAA,WAAA,EACA,CAAA,OAAA,CAAQ,cAAgB,EAAA,EAAE,CAC1B,CAAA,OAAA,CAAQ,MAAQ,EAAA,GAAG,CACnB,CAAA,OAAA,CAAQ,OAAO,GAAG,CAAA,CAAA;AAC3B;;;;"}
|
|
1
|
+
{"version":3,"file":"LayerList.js","sources":["LayerList.tsx"],"sourcesContent":["// SPDX-FileCopyrightText: 2023 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport {\n Box,\n Button,\n Checkbox,\n Flex,\n List,\n ListProps,\n Popover,\n PopoverArrow,\n PopoverBody,\n PopoverCloseButton,\n PopoverContent,\n PopoverHeader,\n PopoverTrigger,\n Portal,\n Spacer,\n Text,\n Tooltip\n} from \"@open-pioneer/chakra-integration\";\nimport { AnyLayer, isSublayer, Layer, MapModel } from \"@open-pioneer/map\";\nimport { useReactiveSnapshot } from \"@open-pioneer/reactivity\";\nimport { PackageIntl } from \"@open-pioneer/runtime\";\nimport classNames from \"classnames\";\nimport { useIntl } from \"open-pioneer:react-hooks\";\nimport { FiAlertTriangle, FiMoreVertical } from \"react-icons/fi\";\nimport { useTocWidgetOptions } from \"./Context\";\n\n/**\n * Lists the (top level) operational layers in the map.\n *\n * Layer Groups are skipped in the current implementation.\n */\nexport function LayerList(props: { map: MapModel; \"aria-label\"?: string }): JSX.Element {\n const { map, \"aria-label\": ariaLabel } = props;\n const intl = useIntl();\n const layers = useLayers(map);\n if (!layers.length) {\n return (\n <Text className=\"toc-missing-layers\" aria-label={ariaLabel}>\n {intl.formatMessage({ id: \"missingLayers\" })}\n </Text>\n );\n }\n\n return createList(layers, {\n \"aria-label\": ariaLabel\n });\n}\n\nfunction createList(layers: AnyLayer[], listProps: ListProps) {\n const items = layers.map((layer) => <LayerItem key={layer.id} layer={layer} />);\n return (\n <List\n // Note: not using UnorderedList because it adds default margins\n as=\"ul\"\n className=\"toc-layer-list\"\n listStyleType=\"none\"\n role=\"group\"\n {...listProps}\n >\n {items}\n </List>\n );\n}\n\n/**\n * Renders a single layer as a list item.\n *\n * The item may have further nested list items if there are sublayers present.\n */\nfunction LayerItem(props: { layer: AnyLayer }): JSX.Element {\n const { layer } = props;\n const intl = useIntl();\n const options = useTocWidgetOptions();\n const { title, description, isVisible } = useReactiveSnapshot(() => {\n return {\n title: layer.title,\n description: layer.description,\n isVisible: layer.visible\n };\n }, [layer]);\n const childLayers = useChildLayers(layer);\n const isAvailable = useLoadState(layer) !== \"error\";\n const notAvailableLabel = intl.formatMessage({ id: \"layerNotAvailable\" });\n\n let nestedChildren;\n if (childLayers?.length) {\n nestedChildren = createList(childLayers, {\n ml: 4,\n \"aria-label\": intl.formatMessage({ id: \"childgroupLabel\" }, { title: title })\n });\n }\n return (\n <Box as=\"li\" className={classNames(\"toc-layer-item\", `layer-${slug(layer.id)}`)}>\n <Flex\n className=\"toc-layer-item-content\"\n width=\"100%\"\n flexDirection=\"row\"\n align=\"center\"\n justifyContent=\"space-between\"\n /** Gap to prevent bleeding of the buttons hover style into the layer title */\n gap={2}\n /** Aligned to the size of the (potential) menu button in LayerItemDescriptor */\n minHeight={10}\n >\n <Checkbox\n // Keyboard navigation jumps only to Checkboxes and uses the texts inside this DOM node. The aria-labels of Tooltip and Icon is ignored by screenreader because they are no child element of the checkbox. To consider the notAvailableLabel, an aria-label at the checkbox is necessary.\n aria-label={title + (!isAvailable ? \" \" + notAvailableLabel : \"\")}\n isChecked={isVisible}\n isDisabled={!isAvailable}\n onChange={(event) =>\n updateLayerVisibility(layer, event.target.checked, options.autoShowParents)\n }\n >\n {title}\n </Checkbox>\n {!isAvailable && (\n <Tooltip\n className=\"toc-layer-item-content-tooltip\"\n label={notAvailableLabel}\n placement=\"right\"\n openDelay={500}\n >\n <span>\n <FiAlertTriangle\n className=\"toc-layer-item-content-icon\"\n color={\"red\"}\n aria-label={notAvailableLabel}\n />\n </span>\n </Tooltip>\n )}\n <Spacer></Spacer>\n {description && (\n <LayerItemDescriptor\n layer={layer}\n title={title}\n description={description}\n intl={intl}\n />\n )}\n </Flex>\n {nestedChildren}\n </Box>\n );\n}\n\nfunction updateLayerVisibility(layer: AnyLayer, visible: boolean, autoShowParents: boolean) {\n layer.setVisible(visible);\n if (visible && autoShowParents && layer.parent) {\n updateLayerVisibility(layer.parent, true, true);\n }\n}\n\nfunction LayerItemDescriptor(props: {\n layer: AnyLayer;\n title: string;\n description: string;\n intl: PackageIntl;\n}): JSX.Element {\n const { layer, title, description, intl } = props;\n const buttonLabel = intl.formatMessage({ id: \"descriptionLabel\" });\n const isAvailable = useLoadState(layer) !== \"error\";\n\n return (\n <Popover placement=\"bottom-start\">\n <PopoverTrigger>\n <Button\n isDisabled={!isAvailable}\n className=\"toc-layer-item-details-button\"\n aria-label={buttonLabel}\n borderRadius=\"full\"\n iconSpacing={0}\n padding={0}\n variant=\"ghost\"\n leftIcon={<FiMoreVertical />}\n />\n </PopoverTrigger>\n <Portal>\n <PopoverContent className=\"toc-layer-item-details\" overflowY=\"auto\" maxHeight=\"400\">\n <PopoverArrow />\n <PopoverCloseButton mt={1} />\n <PopoverHeader>{title}</PopoverHeader>\n <PopoverBody>{description}</PopoverBody>\n </PopoverContent>\n </Portal>\n </Popover>\n );\n}\n\n/** Returns the top level operational layers in render order (topmost layer first). */\nfunction useLayers(map: MapModel): Layer[] {\n return useReactiveSnapshot(() => {\n const layers = map.layers.getOperationalLayers({ sortByDisplayOrder: true }) ?? [];\n layers.reverse(); // render topmost layer first\n return layers;\n }, [map]);\n}\n\n/**\n * Returns the child layers (sublayers or layers contained in a group layer) of a layer.\n * Layers are returned in render order (topmost sublayer first).\n */\nfunction useChildLayers(layer: AnyLayer): AnyLayer[] | undefined {\n return useReactiveSnapshot(() => {\n const children = layer.children?.getItems({ sortByDisplayOrder: true });\n children?.reverse(); // render topmost layer first\n return children;\n }, [layer]);\n}\n\n/** Returns the layers current state. */\nfunction useLoadState(layer: AnyLayer): string {\n return useReactiveSnapshot(() => {\n // for sublayers, use the state of the parent\n const target = isSublayer(layer) ? layer.parentLayer : layer;\n return target.loadState;\n }, [layer]);\n}\n\nfunction slug(id: string) {\n return id\n .toLowerCase()\n .replace(/[^a-z0-9 -]/g, \"\")\n .replace(/\\s+/g, \"-\")\n .replace(/-+/g, \"-\");\n}\n"],"names":[],"mappings":"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"}
|
package/README.md
CHANGED
|
@@ -59,6 +59,17 @@ For example, given a layer with the ID `test-geojson`, the TOC's list item for t
|
|
|
59
59
|
|
|
60
60
|
> NOTE: List items are not guaranteed to be rendered as `li`. Only the CSS class name is guaranteed.
|
|
61
61
|
|
|
62
|
+
### Automatic parent layer visibility
|
|
63
|
+
|
|
64
|
+
When showing a layer via the TOC component (e.g. by clicking the checkbox next to its name), all parent layers of that layer will also be made visible by default.
|
|
65
|
+
|
|
66
|
+
This can be disabled by configuring `autoShowParents={false}` on the `TOC` component.
|
|
67
|
+
|
|
68
|
+
```jsx
|
|
69
|
+
// Default: true
|
|
70
|
+
<Toc autoShowParents={false} />
|
|
71
|
+
```
|
|
72
|
+
|
|
62
73
|
## License
|
|
63
74
|
|
|
64
75
|
Apache-2.0 (see `LICENSE` file)
|
package/Toc.d.ts
CHANGED
|
@@ -25,6 +25,11 @@ export interface TocProps extends CommonComponentProps, MapModelProps {
|
|
|
25
25
|
* Property "mapId" is not applied.
|
|
26
26
|
*/
|
|
27
27
|
basemapSwitcherProps?: Omit<BasemapSwitcherProps, "mapId">;
|
|
28
|
+
/**
|
|
29
|
+
* Show the parent layers when a child layer is made visible.
|
|
30
|
+
* Defaults to `true`.
|
|
31
|
+
*/
|
|
32
|
+
autoShowParents?: boolean;
|
|
28
33
|
}
|
|
29
34
|
/**
|
|
30
35
|
* Props supported by the {@link Tools} component.
|
package/Toc.js
CHANGED
|
@@ -4,7 +4,8 @@ import { Box, Flex, Text, Spacer } from '@open-pioneer/chakra-integration';
|
|
|
4
4
|
import { useMapModel } from '@open-pioneer/map';
|
|
5
5
|
import { useCommonComponentProps, TitledSection, SectionHeading } from '@open-pioneer/react-utils';
|
|
6
6
|
import { useIntl } from './_virtual/_virtual-pioneer-module_react-hooks.js';
|
|
7
|
-
import { useId } from 'react';
|
|
7
|
+
import { useId, useMemo } from 'react';
|
|
8
|
+
import { TocWidgetOptionsProvider } from './Context.js';
|
|
8
9
|
import { LayerList } from './LayerList.js';
|
|
9
10
|
import { Tools } from './Tools.js';
|
|
10
11
|
|
|
@@ -15,10 +16,12 @@ const Toc = (props) => {
|
|
|
15
16
|
showTools = false,
|
|
16
17
|
toolsConfig,
|
|
17
18
|
showBasemapSwitcher = true,
|
|
18
|
-
basemapSwitcherProps
|
|
19
|
+
basemapSwitcherProps,
|
|
20
|
+
autoShowParents = true
|
|
19
21
|
} = props;
|
|
20
22
|
const { containerProps } = useCommonComponentProps("toc", props);
|
|
21
23
|
const basemapsHeadingId = useId();
|
|
24
|
+
const options = useMemo(() => ({ autoShowParents }), [autoShowParents]);
|
|
22
25
|
const state = useMapModel(props);
|
|
23
26
|
let content;
|
|
24
27
|
switch (state.kind) {
|
|
@@ -70,7 +73,7 @@ const Toc = (props) => {
|
|
|
70
73
|
break;
|
|
71
74
|
}
|
|
72
75
|
}
|
|
73
|
-
return /* @__PURE__ */ jsx(Flex, { ...containerProps, direction: "column", gap: PADDING, children: content });
|
|
76
|
+
return /* @__PURE__ */ jsx(Flex, { ...containerProps, direction: "column", gap: PADDING, children: /* @__PURE__ */ jsx(TocWidgetOptionsProvider, { value: options, children: content }) });
|
|
74
77
|
};
|
|
75
78
|
|
|
76
79
|
export { Toc };
|
package/Toc.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Toc.js","sources":["Toc.tsx"],"sourcesContent":["// SPDX-FileCopyrightText: 2023 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport { BasemapSwitcher, BasemapSwitcherProps } from \"@open-pioneer/basemap-switcher\";\nimport { Box, Flex, Spacer, Text } from \"@open-pioneer/chakra-integration\";\nimport { MapModelProps, useMapModel } from \"@open-pioneer/map\";\nimport {\n CommonComponentProps,\n SectionHeading,\n TitledSection,\n useCommonComponentProps\n} from \"@open-pioneer/react-utils\";\nimport { useIntl } from \"open-pioneer:react-hooks\";\nimport { FC, useId } from \"react\";\nimport { LayerList } from \"./LayerList\";\nimport { Tools } from \"./Tools\";\n\n/**\n * Props supported by the {@link Toc} component.\n */\nexport interface TocProps extends CommonComponentProps, MapModelProps {\n /**\n * Defines whether the tool component is shown in the toc.\n * Defaults to `false`.\n */\n showTools?: boolean;\n\n /**\n * Properties for the embedded tool component.\n */\n toolsConfig?: ToolsConfig;\n\n /**\n * Defines whether the basemap switcher is shown in the toc.\n * Defaults to `true`.\n */\n showBasemapSwitcher?: boolean;\n\n /**\n * Properties for the embedded basemap switcher.\n * Property \"mapId\" is not applied.\n */\n basemapSwitcherProps?: Omit<BasemapSwitcherProps, \"mapId\">;\n}\n\n/**\n * Props supported by the {@link Tools} component.\n */\nexport interface ToolsConfig {\n /**\n * Optional property to show the `hide all layers` entry.\n * Defaults to `true`.\n */\n showHideAllLayers?: boolean;\n}\n\nconst PADDING = 2;\n\n/**\n * Displays the layers of the configured map.\n */\nexport const Toc: FC<TocProps> = (props: TocProps) => {\n const intl = useIntl();\n const {\n showTools = false,\n toolsConfig,\n showBasemapSwitcher = true,\n basemapSwitcherProps\n } = props;\n const { containerProps } = useCommonComponentProps(\"toc\", props);\n const basemapsHeadingId = useId();\n const state = useMapModel(props);\n\n let content: JSX.Element | null;\n switch (state.kind) {\n case \"loading\":\n content = null;\n break;\n case \"rejected\":\n content = <Text className=\"toc-error\">{intl.formatMessage({ id: \"error\" })}</Text>;\n break;\n case \"resolved\": {\n const map = state.map;\n const basemapSwitcher = showBasemapSwitcher && (\n <Box className=\"toc-basemap-switcher\">\n <TitledSection\n title={\n <SectionHeading id={basemapsHeadingId} size={\"sm\"} mb={PADDING}>\n {intl.formatMessage({ id: \"basemapsLabel\" })}\n </SectionHeading>\n }\n >\n <BasemapSwitcher\n map={map}\n aria-labelledby={basemapsHeadingId}\n {...basemapSwitcherProps}\n />\n </TitledSection>\n </Box>\n );\n const layerList = (\n <Box className=\"toc-operational-layers\">\n <TitledSection\n title={\n <SectionHeading size={\"sm\"} mb={2}>\n <Flex>\n <Text my={3}>\n {intl.formatMessage({\n id: \"operationalLayerLabel\"\n })}\n </Text>\n <Spacer />\n {showTools && <Tools map={map} {...toolsConfig} />}\n </Flex>\n </SectionHeading>\n }\n >\n <LayerList\n map={map}\n aria-label={intl.formatMessage({ id: \"operationalLayerLabel\" })}\n />\n </TitledSection>\n </Box>\n );\n\n content = (\n <>\n {basemapSwitcher}\n {layerList}\n </>\n );\n break;\n }\n }\n\n return (\n <Flex {...containerProps} direction=\"column\" gap={PADDING}>\n {content}
|
|
1
|
+
{"version":3,"file":"Toc.js","sources":["Toc.tsx"],"sourcesContent":["// SPDX-FileCopyrightText: 2023 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport { BasemapSwitcher, BasemapSwitcherProps } from \"@open-pioneer/basemap-switcher\";\nimport { Box, Flex, Spacer, Text } from \"@open-pioneer/chakra-integration\";\nimport { MapModelProps, useMapModel } from \"@open-pioneer/map\";\nimport {\n CommonComponentProps,\n SectionHeading,\n TitledSection,\n useCommonComponentProps\n} from \"@open-pioneer/react-utils\";\nimport { useIntl } from \"open-pioneer:react-hooks\";\nimport { FC, useId, useMemo } from \"react\";\nimport { TocWidgetOptions, TocWidgetOptionsProvider } from \"./Context\";\nimport { LayerList } from \"./LayerList\";\nimport { Tools } from \"./Tools\";\n\n/**\n * Props supported by the {@link Toc} component.\n */\nexport interface TocProps extends CommonComponentProps, MapModelProps {\n /**\n * Defines whether the tool component is shown in the toc.\n * Defaults to `false`.\n */\n showTools?: boolean;\n\n /**\n * Properties for the embedded tool component.\n */\n toolsConfig?: ToolsConfig;\n\n /**\n * Defines whether the basemap switcher is shown in the toc.\n * Defaults to `true`.\n */\n showBasemapSwitcher?: boolean;\n\n /**\n * Properties for the embedded basemap switcher.\n * Property \"mapId\" is not applied.\n */\n basemapSwitcherProps?: Omit<BasemapSwitcherProps, \"mapId\">;\n\n /**\n * Show the parent layers when a child layer is made visible.\n * Defaults to `true`.\n */\n autoShowParents?: boolean;\n}\n\n/**\n * Props supported by the {@link Tools} component.\n */\nexport interface ToolsConfig {\n /**\n * Optional property to show the `hide all layers` entry.\n * Defaults to `true`.\n */\n showHideAllLayers?: boolean;\n}\n\nconst PADDING = 2;\n\n/**\n * Displays the layers of the configured map.\n */\nexport const Toc: FC<TocProps> = (props: TocProps) => {\n const intl = useIntl();\n const {\n showTools = false,\n toolsConfig,\n showBasemapSwitcher = true,\n basemapSwitcherProps,\n autoShowParents = true\n } = props;\n const { containerProps } = useCommonComponentProps(\"toc\", props);\n const basemapsHeadingId = useId();\n const options = useMemo((): TocWidgetOptions => ({ autoShowParents }), [autoShowParents]);\n const state = useMapModel(props);\n\n let content: JSX.Element | null;\n switch (state.kind) {\n case \"loading\":\n content = null;\n break;\n case \"rejected\":\n content = <Text className=\"toc-error\">{intl.formatMessage({ id: \"error\" })}</Text>;\n break;\n case \"resolved\": {\n const map = state.map;\n const basemapSwitcher = showBasemapSwitcher && (\n <Box className=\"toc-basemap-switcher\">\n <TitledSection\n title={\n <SectionHeading id={basemapsHeadingId} size={\"sm\"} mb={PADDING}>\n {intl.formatMessage({ id: \"basemapsLabel\" })}\n </SectionHeading>\n }\n >\n <BasemapSwitcher\n map={map}\n aria-labelledby={basemapsHeadingId}\n {...basemapSwitcherProps}\n />\n </TitledSection>\n </Box>\n );\n const layerList = (\n <Box className=\"toc-operational-layers\">\n <TitledSection\n title={\n <SectionHeading size={\"sm\"} mb={2}>\n <Flex>\n <Text my={3}>\n {intl.formatMessage({\n id: \"operationalLayerLabel\"\n })}\n </Text>\n <Spacer />\n {showTools && <Tools map={map} {...toolsConfig} />}\n </Flex>\n </SectionHeading>\n }\n >\n <LayerList\n map={map}\n aria-label={intl.formatMessage({ id: \"operationalLayerLabel\" })}\n />\n </TitledSection>\n </Box>\n );\n\n content = (\n <>\n {basemapSwitcher}\n {layerList}\n </>\n );\n break;\n }\n }\n\n return (\n <Flex {...containerProps} direction=\"column\" gap={PADDING}>\n <TocWidgetOptionsProvider value={options}>{content}</TocWidgetOptionsProvider>\n </Flex>\n );\n};\n"],"names":[],"mappings":"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"}
|
package/Tools.d.ts
CHANGED
package/Tools.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
2
2
|
import { Box, Menu, MenuButton, Button, Portal, MenuList, MenuItem } from '@open-pioneer/chakra-integration';
|
|
3
|
-
import { FiMoreVertical } from 'react-icons/fi';
|
|
4
3
|
import { useIntl } from './_virtual/_virtual-pioneer-module_react-hooks.js';
|
|
4
|
+
import { FiMoreVertical } from 'react-icons/fi';
|
|
5
5
|
|
|
6
6
|
const Tools = (props) => {
|
|
7
7
|
const intl = useIntl();
|
|
@@ -34,15 +34,17 @@ const Tools = (props) => {
|
|
|
34
34
|
] }) });
|
|
35
35
|
};
|
|
36
36
|
function hideAllLayers(map) {
|
|
37
|
-
const
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
37
|
+
const hide = (layer) => {
|
|
38
|
+
layer.setVisible(false);
|
|
39
|
+
const children = layer.children?.getItems();
|
|
40
|
+
if (children) {
|
|
41
|
+
for (const child of children) {
|
|
42
|
+
hide(child);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
42
45
|
};
|
|
43
46
|
map?.layers.getOperationalLayers().forEach((layer) => {
|
|
44
|
-
layer
|
|
45
|
-
hideSublayer(layer?.sublayers);
|
|
47
|
+
hide(layer);
|
|
46
48
|
});
|
|
47
49
|
}
|
|
48
50
|
|
package/Tools.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Tools.js","sources":["Tools.tsx"],"sourcesContent":["// SPDX-FileCopyrightText: 2023 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport {\n
|
|
1
|
+
{"version":3,"file":"Tools.js","sources":["Tools.tsx"],"sourcesContent":["// SPDX-FileCopyrightText: 2023 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport {\n Box,\n Button,\n Menu,\n MenuButton,\n MenuItem,\n MenuList,\n Portal\n} from \"@open-pioneer/chakra-integration\";\nimport { AnyLayer, MapModel } from \"@open-pioneer/map\";\nimport { useIntl } from \"open-pioneer:react-hooks\";\nimport { FC } from \"react\";\nimport { FiMoreVertical } from \"react-icons/fi\";\nimport { ToolsConfig } from \"./Toc\";\n\nexport const Tools: FC<{ map: MapModel } & ToolsConfig> = (props) => {\n const intl = useIntl();\n const { map, showHideAllLayers = true } = props;\n\n const noEntry = !showHideAllLayers;\n\n return (\n !noEntry && (\n <Box className=\"toc-tools\">\n <Menu placement=\"bottom-start\">\n <MenuButton\n as={Button}\n className=\"toc-tools-button\"\n aria-label={intl.formatMessage({ id: \"toolsLabel\" })}\n borderRadius=\"full\"\n iconSpacing={0}\n padding={3}\n variant=\"ghost\"\n leftIcon={<FiMoreVertical />}\n />\n <Portal>\n <MenuList className=\"tools-menu\">\n <MenuItem\n aria-label={intl.formatMessage({ id: \"tools.hideAllLayers\" })}\n onClick={() => {\n hideAllLayers(map);\n }}\n >\n {intl.formatMessage({ id: \"tools.hideAllLayers\" })}\n </MenuItem>\n </MenuList>\n </Portal>\n </Menu>\n </Box>\n )\n );\n};\n\nfunction hideAllLayers(map: MapModel | undefined) {\n const hide = (layer: AnyLayer) => {\n layer.setVisible(false);\n\n const children = layer.children?.getItems();\n if (children) {\n for (const child of children) {\n hide(child);\n }\n }\n };\n\n map?.layers.getOperationalLayers().forEach((layer) => {\n hide(layer);\n });\n}\n"],"names":[],"mappings":";;;;;AAiBa,MAAA,KAAA,GAA6C,CAAC,KAAU,KAAA;AACjE,EAAA,MAAM,OAAO,OAAQ,EAAA,CAAA;AACrB,EAAA,MAAM,EAAE,GAAA,EAAK,iBAAoB,GAAA,IAAA,EAAS,GAAA,KAAA,CAAA;AAE1C,EAAA,MAAM,UAAU,CAAC,iBAAA,CAAA;AAEjB,EACI,OAAA,CAAC,2BACI,GAAA,CAAA,GAAA,EAAA,EAAI,WAAU,WACX,EAAA,QAAA,kBAAA,IAAA,CAAC,IAAK,EAAA,EAAA,SAAA,EAAU,cACZ,EAAA,QAAA,EAAA;AAAA,oBAAA,GAAA;AAAA,MAAC,UAAA;AAAA,MAAA;AAAA,QACG,EAAI,EAAA,MAAA;AAAA,QACJ,SAAU,EAAA,kBAAA;AAAA,QACV,cAAY,IAAK,CAAA,aAAA,CAAc,EAAE,EAAA,EAAI,cAAc,CAAA;AAAA,QACnD,YAAa,EAAA,MAAA;AAAA,QACb,WAAa,EAAA,CAAA;AAAA,QACb,OAAS,EAAA,CAAA;AAAA,QACT,OAAQ,EAAA,OAAA;AAAA,QACR,QAAA,sBAAW,cAAe,EAAA,EAAA,CAAA;AAAA,OAAA;AAAA,KAC9B;AAAA,oBACC,GAAA,CAAA,MAAA,EAAA,EACG,QAAC,kBAAA,GAAA,CAAA,QAAA,EAAA,EAAS,WAAU,YAChB,EAAA,QAAA,kBAAA,GAAA;AAAA,MAAC,QAAA;AAAA,MAAA;AAAA,QACG,cAAY,IAAK,CAAA,aAAA,CAAc,EAAE,EAAA,EAAI,uBAAuB,CAAA;AAAA,QAC5D,SAAS,MAAM;AACX,UAAA,aAAA,CAAc,GAAG,CAAA,CAAA;AAAA,SACrB;AAAA,QAEC,QAAK,EAAA,IAAA,CAAA,aAAA,CAAc,EAAE,EAAA,EAAI,uBAAuB,CAAA;AAAA,OAAA;AAAA,OAEzD,CACJ,EAAA,CAAA;AAAA,GAAA,EACJ,CACJ,EAAA,CAAA,CAAA;AAGZ,EAAA;AAEA,SAAS,cAAc,GAA2B,EAAA;AAC9C,EAAM,MAAA,IAAA,GAAO,CAAC,KAAoB,KAAA;AAC9B,IAAA,KAAA,CAAM,WAAW,KAAK,CAAA,CAAA;AAEtB,IAAM,MAAA,QAAA,GAAW,KAAM,CAAA,QAAA,EAAU,QAAS,EAAA,CAAA;AAC1C,IAAA,IAAI,QAAU,EAAA;AACV,MAAA,KAAA,MAAW,SAAS,QAAU,EAAA;AAC1B,QAAA,IAAA,CAAK,KAAK,CAAA,CAAA;AAAA,OACd;AAAA,KACJ;AAAA,GACJ,CAAA;AAEA,EAAA,GAAA,EAAK,MAAO,CAAA,oBAAA,EAAuB,CAAA,OAAA,CAAQ,CAAC,KAAU,KAAA;AAClD,IAAA,IAAA,CAAK,KAAK,CAAA,CAAA;AAAA,GACb,CAAA,CAAA;AACL;;;;"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "module",
|
|
3
3
|
"name": "@open-pioneer/toc",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.8.0",
|
|
5
5
|
"description": "This package provides a UI component that displays the map content to the user and allows them to control it.",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"open-pioneer-trails"
|
|
@@ -14,15 +14,17 @@
|
|
|
14
14
|
"directory": "src/packages/toc"
|
|
15
15
|
},
|
|
16
16
|
"dependencies": {
|
|
17
|
-
"@open-pioneer/chakra-integration": "^2.
|
|
18
|
-
"@open-pioneer/react-utils": "^2.
|
|
19
|
-
"@open-pioneer/runtime": "^2.
|
|
17
|
+
"@open-pioneer/chakra-integration": "^2.4.0",
|
|
18
|
+
"@open-pioneer/react-utils": "^2.4.0",
|
|
19
|
+
"@open-pioneer/runtime": "^2.4.0",
|
|
20
20
|
"classnames": "^2.3.2",
|
|
21
|
-
"ol": "^
|
|
21
|
+
"ol": "^10.2.1",
|
|
22
22
|
"react": "^18.3.1",
|
|
23
23
|
"react-icons": "^5.3.0",
|
|
24
|
-
"@open-pioneer/
|
|
25
|
-
"@
|
|
24
|
+
"@open-pioneer/reactivity": "^2.4.0",
|
|
25
|
+
"@conterra/reactivity-core": "^0.4.3",
|
|
26
|
+
"@open-pioneer/basemap-switcher": "^0.8.0",
|
|
27
|
+
"@open-pioneer/map": "^0.8.0"
|
|
26
28
|
},
|
|
27
29
|
"exports": {
|
|
28
30
|
"./package.json": "./package.json",
|