@open-pioneer/basemap-switcher 0.10.0 → 0.11.0-dev.20250515143825
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/BasemapSwitcher.d.ts +4 -0
- package/BasemapSwitcher.js +84 -126
- package/BasemapSwitcher.js.map +1 -1
- package/CHANGELOG.md +14 -0
- package/README.md +13 -11
- package/package.json +8 -8
package/BasemapSwitcher.d.ts
CHANGED
package/BasemapSwitcher.js
CHANGED
|
@@ -1,156 +1,114 @@
|
|
|
1
1
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
2
|
-
import {
|
|
2
|
+
import { createListCollection, Box, Select, Portal } from '@chakra-ui/react';
|
|
3
|
+
import { Tooltip } from '@open-pioneer/chakra-snippets/tooltip';
|
|
3
4
|
import { useMapModel } from '@open-pioneer/map';
|
|
4
|
-
import { useCommonComponentProps
|
|
5
|
+
import { useCommonComponentProps } from '@open-pioneer/react-utils';
|
|
5
6
|
import { useReactiveSnapshot } from '@open-pioneer/reactivity';
|
|
6
|
-
import { Select, chakraComponents } from 'chakra-react-select';
|
|
7
7
|
import { useIntl } from './_virtual/_virtual-pioneer-module_react-hooks.js';
|
|
8
|
-
import { useMemo, useState } from 'react';
|
|
9
8
|
import { FiAlertTriangle } from 'react-icons/fi';
|
|
10
9
|
|
|
11
10
|
const NO_BASEMAP_ID = "___NO_BASEMAP___";
|
|
12
11
|
const BasemapSwitcher = (props) => {
|
|
12
|
+
const { map } = useMapModel(props);
|
|
13
|
+
return map && /* @__PURE__ */ jsx(BasemapSwitcherImpl, { ...props, map });
|
|
14
|
+
};
|
|
15
|
+
function BasemapSwitcherImpl(props) {
|
|
13
16
|
const intl = useIntl();
|
|
14
17
|
const {
|
|
15
18
|
allowSelectingEmptyBasemap = false,
|
|
16
19
|
"aria-label": ariaLabel,
|
|
17
|
-
"aria-labelledby": ariaLabelledBy
|
|
20
|
+
"aria-labelledby": ariaLabelledBy,
|
|
21
|
+
map
|
|
18
22
|
} = props;
|
|
19
23
|
const { containerProps } = useCommonComponentProps("basemap-switcher", props);
|
|
20
24
|
const emptyBasemapLabel = intl.formatMessage({ id: "emptyBasemapLabel" });
|
|
21
|
-
const { map } = useMapModel(props);
|
|
22
|
-
const baseLayers = useBaseLayers(map);
|
|
23
|
-
const activeBaseLayer = useReactiveSnapshot(() => map?.layers.getActiveBaseLayer(), [map]);
|
|
24
25
|
const activateLayer = (layerId) => {
|
|
25
|
-
map
|
|
26
|
+
map.layers.activateBaseLayer(layerId[0] === NO_BASEMAP_ID ? void 0 : layerId[0]);
|
|
26
27
|
};
|
|
27
|
-
const {
|
|
28
|
-
const
|
|
29
|
-
|
|
28
|
+
const { optionsListCollection, selectedOption } = useReactiveSnapshot(() => {
|
|
29
|
+
const baseLayers = map.layers.getBaseLayers() ?? [];
|
|
30
|
+
const options = baseLayers.map((layer) => {
|
|
31
|
+
return {
|
|
32
|
+
value: layer.id,
|
|
33
|
+
layer,
|
|
34
|
+
label: layer.title,
|
|
35
|
+
disabled: layer.loadState == "error"
|
|
36
|
+
};
|
|
30
37
|
});
|
|
38
|
+
const activeBaseLayer = map.layers.getActiveBaseLayer();
|
|
31
39
|
if (allowSelectingEmptyBasemap || activeBaseLayer == null) {
|
|
32
|
-
const emptyOption = {
|
|
33
|
-
|
|
40
|
+
const emptyOption = {
|
|
41
|
+
value: NO_BASEMAP_ID,
|
|
42
|
+
layer: void 0,
|
|
43
|
+
label: emptyBasemapLabel
|
|
44
|
+
};
|
|
45
|
+
options.push(emptyOption);
|
|
34
46
|
}
|
|
35
|
-
const
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
return {
|
|
42
|
-
Option: BasemapSelectOption,
|
|
43
|
-
SingleValue: BasemapSelectValue
|
|
44
|
-
};
|
|
45
|
-
}, []);
|
|
46
|
-
const keyDown = useEvent((event) => {
|
|
47
|
-
if (!isOpenSelect && event.key === "Enter") {
|
|
48
|
-
setIsOpenSelect(true);
|
|
49
|
-
}
|
|
50
|
-
});
|
|
51
|
-
return /* @__PURE__ */ jsx(Box, { ...containerProps, children: map ? /* @__PURE__ */ jsx(
|
|
52
|
-
Select,
|
|
47
|
+
const optionsListCollection2 = createListCollection({ items: options });
|
|
48
|
+
const selectedOption2 = [activeBaseLayer?.id ?? NO_BASEMAP_ID];
|
|
49
|
+
return { optionsListCollection: optionsListCollection2, selectedOption: selectedOption2 };
|
|
50
|
+
}, [allowSelectingEmptyBasemap, emptyBasemapLabel, map]);
|
|
51
|
+
return /* @__PURE__ */ jsx(Box, { ...containerProps, children: /* @__PURE__ */ jsxs(
|
|
52
|
+
Select.Root,
|
|
53
53
|
{
|
|
54
|
-
|
|
55
|
-
|
|
54
|
+
collection: optionsListCollection,
|
|
55
|
+
value: selectedOption,
|
|
56
|
+
onValueChange: (option) => option && activateLayer(option.value),
|
|
56
57
|
className: "basemap-switcher-select",
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
onFilter: () => "",
|
|
75
|
-
onFocus: () => ""
|
|
76
|
-
},
|
|
77
|
-
chakraStyles,
|
|
78
|
-
onKeyDown: keyDown,
|
|
79
|
-
menuIsOpen: isOpenSelect,
|
|
80
|
-
onMenuOpen: () => setIsOpenSelect(true),
|
|
81
|
-
onMenuClose: () => setIsOpenSelect(false)
|
|
82
|
-
}
|
|
83
|
-
) : null });
|
|
84
|
-
};
|
|
85
|
-
function useBaseLayers(mapModel) {
|
|
86
|
-
return useReactiveSnapshot(() => mapModel?.layers.getBaseLayers() ?? [], [mapModel]);
|
|
87
|
-
}
|
|
88
|
-
function BasemapSelectOption(props) {
|
|
89
|
-
const { layer } = props.data;
|
|
90
|
-
const { isAvailable, content } = useBasemapItem(layer);
|
|
91
|
-
return /* @__PURE__ */ jsx(
|
|
92
|
-
chakraComponents.Option,
|
|
93
|
-
{
|
|
94
|
-
...props,
|
|
95
|
-
isDisabled: !isAvailable,
|
|
96
|
-
className: "basemap-switcher-option",
|
|
97
|
-
children: content
|
|
58
|
+
lazyMount: true,
|
|
59
|
+
unmountOnExit: true,
|
|
60
|
+
children: [
|
|
61
|
+
/* @__PURE__ */ jsxs(Select.Control, { children: [
|
|
62
|
+
/* @__PURE__ */ jsx(
|
|
63
|
+
Select.Trigger,
|
|
64
|
+
{
|
|
65
|
+
"aria-label": ariaLabel,
|
|
66
|
+
"aria-labelledby": ariaLabelledBy,
|
|
67
|
+
className: "basemap-switcher-select-trigger",
|
|
68
|
+
children: /* @__PURE__ */ jsx(Select.ValueText, {})
|
|
69
|
+
}
|
|
70
|
+
),
|
|
71
|
+
/* @__PURE__ */ jsx(Select.IndicatorGroup, { children: /* @__PURE__ */ jsx(Select.Indicator, {}) })
|
|
72
|
+
] }),
|
|
73
|
+
/* @__PURE__ */ jsx(Portal, { children: /* @__PURE__ */ jsx(Select.Positioner, { children: /* @__PURE__ */ jsx(Select.Content, { className: "basemap-switcher-select-content", children: optionsListCollection.items.map((item) => /* @__PURE__ */ jsx(BasemapItem, { item }, item.value)) }) }) })
|
|
74
|
+
]
|
|
98
75
|
}
|
|
99
|
-
);
|
|
76
|
+
) });
|
|
100
77
|
}
|
|
101
|
-
function
|
|
102
|
-
const { layer } = props.data;
|
|
103
|
-
const { isAvailable, content } = useBasemapItem(layer);
|
|
104
|
-
return /* @__PURE__ */ jsx(
|
|
105
|
-
chakraComponents.SingleValue,
|
|
106
|
-
{
|
|
107
|
-
...props,
|
|
108
|
-
isDisabled: !isAvailable,
|
|
109
|
-
className: "basemap-switcher-value",
|
|
110
|
-
children: content
|
|
111
|
-
}
|
|
112
|
-
);
|
|
113
|
-
}
|
|
114
|
-
function useBasemapItem(layer) {
|
|
78
|
+
function BasemapItem(props) {
|
|
115
79
|
const intl = useIntl();
|
|
116
80
|
const notAvailableLabel = intl.formatMessage({ id: "layerNotAvailable" });
|
|
117
|
-
const
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
81
|
+
const item = props.item;
|
|
82
|
+
return /* @__PURE__ */ jsxs(
|
|
83
|
+
Select.Item,
|
|
84
|
+
{
|
|
85
|
+
item,
|
|
86
|
+
justifyContent: "flex-start",
|
|
87
|
+
pointerEvents: "auto",
|
|
88
|
+
className: "basemap-switcher-option",
|
|
89
|
+
children: [
|
|
90
|
+
item.label,
|
|
91
|
+
item.layer?.loadState === "error" && /* @__PURE__ */ jsx(Box, { ml: 2, children: /* @__PURE__ */ jsx(
|
|
92
|
+
Tooltip,
|
|
93
|
+
{
|
|
94
|
+
content: notAvailableLabel,
|
|
95
|
+
"aria-label": notAvailableLabel,
|
|
96
|
+
positioning: { placement: "right" },
|
|
97
|
+
children: /* @__PURE__ */ jsx("span", { children: /* @__PURE__ */ jsx(
|
|
98
|
+
FiAlertTriangle,
|
|
99
|
+
{
|
|
100
|
+
color: "red",
|
|
101
|
+
"aria-label": intl.formatMessage({
|
|
102
|
+
id: "layerNotAvailable"
|
|
103
|
+
})
|
|
104
|
+
}
|
|
105
|
+
) })
|
|
106
|
+
}
|
|
107
|
+
) })
|
|
108
|
+
]
|
|
109
|
+
},
|
|
110
|
+
item.value
|
|
139
111
|
);
|
|
140
|
-
return useMemo(() => {
|
|
141
|
-
const chakraStyles = {
|
|
142
|
-
control: (styles) => ({ ...styles, cursor: "pointer" }),
|
|
143
|
-
indicatorSeparator: (styles) => ({
|
|
144
|
-
...styles,
|
|
145
|
-
borderColor
|
|
146
|
-
}),
|
|
147
|
-
dropdownIndicator: (provided) => ({
|
|
148
|
-
...provided,
|
|
149
|
-
backgroundColor: dropDownBackground
|
|
150
|
-
})
|
|
151
|
-
};
|
|
152
|
-
return chakraStyles;
|
|
153
|
-
}, [dropDownBackground, borderColor]);
|
|
154
112
|
}
|
|
155
113
|
|
|
156
114
|
export { BasemapSwitcher, NO_BASEMAP_ID };
|
package/BasemapSwitcher.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BasemapSwitcher.js","sources":["BasemapSwitcher.tsx"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport { Box, Flex, Tooltip, useToken } from \"@open-pioneer/chakra-integration\";\nimport { Layer, MapModel, useMapModel, MapModelProps } from \"@open-pioneer/map\";\nimport { CommonComponentProps, useCommonComponentProps, useEvent } from \"@open-pioneer/react-utils\";\nimport { useReactiveSnapshot } from \"@open-pioneer/reactivity\";\nimport {\n chakraComponents,\n ChakraStylesConfig,\n GroupBase,\n OptionProps,\n Select,\n SingleValueProps\n} from \"chakra-react-select\";\nimport { useIntl } from \"open-pioneer:react-hooks\";\nimport { FC, KeyboardEvent, useMemo, useState, ReactNode } from \"react\";\nimport { FiAlertTriangle } from \"react-icons/fi\";\n\n/*\n Exported for tests. Feels a bit hacky but should be fine for now.\n Originally was using the empty string, but that doesn't work well with happy-dom.\n*/\nexport const NO_BASEMAP_ID = \"___NO_BASEMAP___\";\n\n/**\n * Properties for single select options.\n */\nexport interface SelectOption {\n /**\n * The id of the basemap for the select option.\n */\n value: string;\n\n /**\n * The layer object for the select option.\n */\n layer: Layer | undefined;\n}\n\n/**\n * These are special properties for the BasemapSwitcher.\n */\nexport interface BasemapSwitcherProps extends CommonComponentProps, MapModelProps {\n /**\n * Additional css class name(s) that will be added to the BasemapSwitcher component.\n */\n className?: string;\n\n /**\n * Specifies whether an option to deactivate all basemap layers is available in the BasemapSwitcher.\n * Defaults to `false`.\n */\n allowSelectingEmptyBasemap?: boolean | undefined;\n\n /**\n * Optional aria-labelledby property.\n * Do not use together with aria-label.\n */\n \"aria-labelledby\"?: string;\n\n /**\n * Optional aria-label property.\n * Do not use together with aria-label.\n */\n \"aria-label\"?: string;\n}\n\n/**\n * The `BasemapSwitcher` component can be used in an app to switch between the different basemaps.\n */\nexport const BasemapSwitcher: FC<BasemapSwitcherProps> = (props) => {\n const intl = useIntl();\n const {\n allowSelectingEmptyBasemap = false,\n \"aria-label\": ariaLabel,\n \"aria-labelledby\": ariaLabelledBy\n } = props;\n const { containerProps } = useCommonComponentProps(\"basemap-switcher\", props);\n const emptyBasemapLabel = intl.formatMessage({ id: \"emptyBasemapLabel\" });\n\n const { map } = useMapModel(props);\n const baseLayers = useBaseLayers(map);\n const activeBaseLayer = useReactiveSnapshot(() => map?.layers.getActiveBaseLayer(), [map]);\n\n const activateLayer = (layerId: string) => {\n map?.layers.activateBaseLayer(layerId === NO_BASEMAP_ID ? undefined : layerId);\n };\n\n const { options, selectedLayer } = useMemo(() => {\n const options: SelectOption[] = baseLayers.map<SelectOption>((layer) => {\n return { value: layer.id, layer: layer };\n });\n\n if (allowSelectingEmptyBasemap || activeBaseLayer == null) {\n const emptyOption: SelectOption = { value: NO_BASEMAP_ID, layer: undefined };\n options.push(emptyOption);\n }\n\n const selectedLayer = options.find((l) => l.layer === activeBaseLayer);\n return { options, selectedLayer };\n }, [allowSelectingEmptyBasemap, baseLayers, activeBaseLayer]);\n\n const chakraStyles = useChakraStyles();\n const [isOpenSelect, setIsOpenSelect] = useState(false);\n const components = useMemo(() => {\n return {\n Option: BasemapSelectOption,\n SingleValue: BasemapSelectValue\n };\n }, []);\n const keyDown = useEvent((event: KeyboardEvent<HTMLDivElement>) => {\n //if the menu is already open, do noting\n if (!isOpenSelect && event.key === \"Enter\") {\n setIsOpenSelect(true);\n }\n });\n\n return (\n <Box {...containerProps}>\n {map ? (\n <Select<SelectOption>\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledBy}\n className=\"basemap-switcher-select\"\n classNamePrefix=\"react-select\"\n options={options}\n value={selectedLayer}\n onChange={(option) => option && activateLayer(option.value)}\n isClearable={false}\n isSearchable={false}\n menuPosition=\"fixed\"\n // optionLabel is used by screenreaders\n getOptionLabel={(option) =>\n option.layer !== undefined\n ? option.layer.title +\n (option.layer.loadState === \"error\"\n ? \" \" + intl.formatMessage({ id: \"layerNotAvailable\" })\n : \"\")\n : emptyBasemapLabel\n }\n isOptionDisabled={(option) => option?.layer?.loadState === \"error\"}\n components={components}\n ariaLiveMessages={{\n guidance: () => \"\",\n onChange: (props) => {\n if (\n props.action == \"select-option\" ||\n props.action == \"initial-input-focus\"\n )\n return props.label + \" \" + intl.formatMessage({ id: \"selected\" });\n else return \"\";\n },\n onFilter: () => \"\",\n onFocus: () => \"\"\n }}\n chakraStyles={chakraStyles}\n onKeyDown={keyDown}\n menuIsOpen={isOpenSelect}\n onMenuOpen={() => setIsOpenSelect(true)}\n onMenuClose={() => setIsOpenSelect(false)}\n />\n ) : null}\n </Box>\n );\n};\n\nfunction useBaseLayers(mapModel: MapModel | undefined): Layer[] {\n return useReactiveSnapshot(() => mapModel?.layers.getBaseLayers() ?? [], [mapModel]);\n}\n\nfunction BasemapSelectOption(props: OptionProps<SelectOption>): ReactNode {\n const { layer } = props.data;\n const { isAvailable, content } = useBasemapItem(layer);\n\n return (\n <chakraComponents.Option\n {...props}\n isDisabled={!isAvailable}\n className=\"basemap-switcher-option\"\n >\n {content}\n </chakraComponents.Option>\n );\n}\n\nfunction BasemapSelectValue(props: SingleValueProps<SelectOption>): ReactNode {\n const { layer } = props.data;\n const { isAvailable, content } = useBasemapItem(layer);\n\n return (\n <chakraComponents.SingleValue\n {...props}\n isDisabled={!isAvailable}\n className=\"basemap-switcher-value\"\n >\n {content}\n </chakraComponents.SingleValue>\n );\n}\n\nfunction useBasemapItem(layer: Layer | undefined) {\n const intl = useIntl();\n const notAvailableLabel = intl.formatMessage({ id: \"layerNotAvailable\" });\n const { label, isAvailable } = useReactiveSnapshot(() => {\n if (!layer) {\n // undefined layer -> empty basemap entry\n return { label: intl.formatMessage({ id: \"emptyBasemapLabel\" }), isAvailable: true };\n }\n\n return {\n label: layer.title,\n isAvailable: layer.loadState !== \"error\"\n };\n }, [layer, intl]);\n\n return {\n isAvailable,\n content: (\n <Flex direction=\"row\" alignItems=\"center\">\n {label}\n {!isAvailable && (\n <Box ml={2}>\n <Tooltip label={notAvailableLabel} placement=\"right\" openDelay={500}>\n <span>\n <FiAlertTriangle color={\"red\"} aria-label={notAvailableLabel} />\n </span>\n </Tooltip>\n </Box>\n )}\n </Flex>\n )\n };\n}\n\n/**\n * Customizes components styles within the select component.\n */\nfunction useChakraStyles() {\n const [dropDownBackground, borderColor] = useToken(\n \"colors\",\n [\"background_body\", \"border\"],\n [\"#ffffff\", \"#ffffff\"]\n );\n return useMemo(() => {\n const chakraStyles: ChakraStylesConfig<SelectOption, false, GroupBase<SelectOption>> = {\n control: (styles) => ({ ...styles, cursor: \"pointer\" }),\n indicatorSeparator: (styles) => ({\n ...styles,\n borderColor: borderColor\n }),\n dropdownIndicator: (provided) => ({\n ...provided,\n backgroundColor: dropDownBackground\n })\n };\n return chakraStyles;\n }, [dropDownBackground, borderColor]);\n}\n"],"names":["options","selectedLayer","props"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"BasemapSwitcher.js","sources":["BasemapSwitcher.tsx"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport { Box, createListCollection, Portal, Select } from \"@chakra-ui/react\";\nimport { Tooltip } from \"@open-pioneer/chakra-snippets/tooltip\";\nimport { Layer, useMapModel, MapModelProps, MapModel } from \"@open-pioneer/map\";\nimport { CommonComponentProps, useCommonComponentProps } from \"@open-pioneer/react-utils\";\nimport { useReactiveSnapshot } from \"@open-pioneer/reactivity\";\nimport { useIntl } from \"open-pioneer:react-hooks\";\nimport { FC } from \"react\";\nimport { FiAlertTriangle } from \"react-icons/fi\";\n\n/*\n Exported for tests. Feels a bit hacky but should be fine for now.\n Originally was using the empty string, but that doesn't work well with happy-dom.\n*/\nexport const NO_BASEMAP_ID = \"___NO_BASEMAP___\";\n\n/**\n * Properties for single select options.\n */\nexport interface SelectOption {\n /**\n * The id of the basemap for the select option.\n */\n value: string;\n\n /**\n * The label of the select option.\n */\n label: string;\n\n /**\n * The layer object for the select option.\n */\n layer: Layer | undefined;\n}\n\n/**\n * These are special properties for the BasemapSwitcher.\n */\nexport interface BasemapSwitcherProps extends CommonComponentProps, MapModelProps {\n /**\n * Additional css class name(s) that will be added to the BasemapSwitcher component.\n */\n className?: string;\n\n /**\n * Specifies whether an option to deactivate all basemap layers is available in the BasemapSwitcher.\n * Defaults to `false`.\n */\n allowSelectingEmptyBasemap?: boolean | undefined;\n\n /**\n * Optional aria-labelledby property.\n * Do not use together with aria-label.\n */\n \"aria-labelledby\"?: string;\n\n /**\n * Optional aria-label property.\n * Do not use together with aria-label.\n */\n \"aria-label\"?: string;\n}\n\n/**\n * The `BasemapSwitcher` component can be used in an app to switch between the different basemaps.\n */\nexport const BasemapSwitcher: FC<BasemapSwitcherProps> = (props) => {\n const { map } = useMapModel(props);\n return map && <BasemapSwitcherImpl {...props} map={map} />;\n};\n\n// Wait for the map resolve before rendering the component, this can be removed once we take the map model as a prop directly.\nfunction BasemapSwitcherImpl(props: BasemapSwitcherProps & { map: MapModel }) {\n const intl = useIntl();\n const {\n allowSelectingEmptyBasemap = false,\n \"aria-label\": ariaLabel,\n \"aria-labelledby\": ariaLabelledBy,\n map\n } = props;\n const { containerProps } = useCommonComponentProps(\"basemap-switcher\", props);\n const emptyBasemapLabel = intl.formatMessage({ id: \"emptyBasemapLabel\" });\n\n const activateLayer = (layerId: string[]) => {\n map.layers.activateBaseLayer(layerId[0] === NO_BASEMAP_ID ? undefined : layerId[0]);\n };\n\n const { optionsListCollection, selectedOption } = useReactiveSnapshot(() => {\n const baseLayers = map.layers.getBaseLayers() ?? [];\n const options: SelectOption[] = baseLayers.map<SelectOption>((layer) => {\n return {\n value: layer.id,\n layer: layer,\n label: layer.title,\n disabled: layer.loadState == \"error\"\n };\n });\n\n const activeBaseLayer = map.layers.getActiveBaseLayer();\n if (allowSelectingEmptyBasemap || activeBaseLayer == null) {\n const emptyOption: SelectOption = {\n value: NO_BASEMAP_ID,\n layer: undefined,\n label: emptyBasemapLabel\n };\n options.push(emptyOption);\n }\n const optionsListCollection = createListCollection({ items: options });\n\n const selectedOption = [activeBaseLayer?.id ?? NO_BASEMAP_ID];\n\n return { optionsListCollection, selectedOption };\n }, [allowSelectingEmptyBasemap, emptyBasemapLabel, map]);\n\n return (\n <Box {...containerProps}>\n <Select.Root\n collection={optionsListCollection}\n value={selectedOption}\n onValueChange={(option) => option && activateLayer(option.value)}\n className=\"basemap-switcher-select\"\n lazyMount={true}\n unmountOnExit={true}\n >\n <Select.Control>\n <Select.Trigger\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledBy}\n className=\"basemap-switcher-select-trigger\"\n >\n <Select.ValueText />\n </Select.Trigger>\n <Select.IndicatorGroup>\n <Select.Indicator />\n </Select.IndicatorGroup>\n </Select.Control>\n\n <Portal>\n <Select.Positioner>\n <Select.Content className=\"basemap-switcher-select-content\">\n {optionsListCollection.items.map((item) => (\n <BasemapItem item={item} key={item.value} />\n ))}\n </Select.Content>\n </Select.Positioner>\n </Portal>\n </Select.Root>\n </Box>\n );\n}\n\nfunction BasemapItem(props: { item: SelectOption }) {\n const intl = useIntl();\n const notAvailableLabel = intl.formatMessage({ id: \"layerNotAvailable\" });\n const item = props.item;\n return (\n <Select.Item\n item={item}\n key={item.value}\n justifyContent=\"flex-start\"\n // Override pointer-events: none rule for disabled items; we want to show the tooltip on hover\n pointerEvents=\"auto\"\n className=\"basemap-switcher-option\"\n >\n {item.label}\n {item.layer?.loadState === \"error\" && (\n <Box ml={2}>\n <Tooltip\n content={notAvailableLabel}\n aria-label={notAvailableLabel}\n positioning={{ placement: \"right\" }}\n >\n <span>\n <FiAlertTriangle\n color={\"red\"}\n aria-label={intl.formatMessage({\n id: \"layerNotAvailable\"\n })}\n />\n </span>\n </Tooltip>\n </Box>\n )}\n </Select.Item>\n );\n}\n"],"names":["optionsListCollection","selectedOption"],"mappings":"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"}
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# @open-pioneer/basemap-switcher
|
|
2
2
|
|
|
3
|
+
## 0.11.0-dev.20250515143825
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 738390e: It is no longer possible to use the BasemapSwitcher within a Chakra Form/Field to an automatic label id.
|
|
8
|
+
However, it is still possible to provide a label for accessibility via the props `aria-label` and `aria-labelledby` (for details see the packages README).
|
|
9
|
+
- 738390e: Update to Chakra v3
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- Updated dependencies [738390e]
|
|
14
|
+
- Updated dependencies [738390e]
|
|
15
|
+
- @open-pioneer/map@0.11.0-dev.20250515143825
|
|
16
|
+
|
|
3
17
|
## 0.10.0
|
|
4
18
|
|
|
5
19
|
### Minor Changes
|
package/README.md
CHANGED
|
@@ -22,23 +22,25 @@ To provide an option to deactivate all basemap layers, add the optional property
|
|
|
22
22
|
|
|
23
23
|
## Accessibility
|
|
24
24
|
|
|
25
|
-
The package provides only a
|
|
25
|
+
The package provides only a select component.
|
|
26
26
|
To be compliant with a11y guidelines (screen reader compatibility), a label must be added to the basemap switcher.
|
|
27
|
-
Therefore, use one of the following
|
|
27
|
+
Therefore, use one of the following approaches:
|
|
28
28
|
|
|
29
|
-
-
|
|
30
|
-
- Use the `aria-
|
|
31
|
-
- Use the `aria-label` property of the `BasemapSwitcher` to set an label for the screen reader that is not shown in the UI.
|
|
29
|
+
- Use the `aria-labelledby` property of the `BasemapSwitcher` to specify that another HTML element (e.g. a heading shown above the control) is used as the basemap switcher's label.
|
|
30
|
+
- Use the `aria-label` property of the `BasemapSwitcher` to set a label for the screen reader that is not shown in the UI.
|
|
32
31
|
|
|
33
32
|
Example:
|
|
34
33
|
|
|
35
34
|
```jsx
|
|
36
|
-
<
|
|
37
|
-
|
|
38
|
-
<
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
35
|
+
<TitledSection
|
|
36
|
+
title={
|
|
37
|
+
<SectionHeading id={basemapsHeadingId} mb={2}>
|
|
38
|
+
{intl.formatMessage({ id: "basemapLabel" })}
|
|
39
|
+
</SectionHeading>
|
|
40
|
+
}
|
|
41
|
+
>
|
|
42
|
+
<BasemapSwitcher map={map} aria-labelledby={basemapsHeadingId} />
|
|
43
|
+
</TitledSection>
|
|
42
44
|
```
|
|
43
45
|
|
|
44
46
|
## License
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "module",
|
|
3
3
|
"name": "@open-pioneer/basemap-switcher",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.11.0-dev.20250515143825",
|
|
5
5
|
"description": "This package provides a UI component that allows a user to switch between different base maps.",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"open-pioneer-trails"
|
|
@@ -14,16 +14,16 @@
|
|
|
14
14
|
"directory": "src/packages/basemap-switcher"
|
|
15
15
|
},
|
|
16
16
|
"dependencies": {
|
|
17
|
-
"@open-pioneer/
|
|
18
|
-
"@open-pioneer/
|
|
19
|
-
"@
|
|
20
|
-
"chakra-react-select": "^5.0.4",
|
|
17
|
+
"@open-pioneer/react-utils": "4.0.0-dev.20250512105016",
|
|
18
|
+
"@open-pioneer/runtime": "4.0.0-dev.20250512105016",
|
|
19
|
+
"@chakra-ui/react": "^3.17.0",
|
|
21
20
|
"ol": "^10.5.0",
|
|
22
21
|
"react": "^19.1.0",
|
|
23
22
|
"react-icons": "^5.3.0",
|
|
24
|
-
"@open-pioneer/reactivity": "
|
|
25
|
-
"@conterra/reactivity-core": "^0.
|
|
26
|
-
"@open-pioneer/
|
|
23
|
+
"@open-pioneer/reactivity": "4.0.0-dev.20250512105016",
|
|
24
|
+
"@conterra/reactivity-core": "^0.6.0",
|
|
25
|
+
"@open-pioneer/chakra-snippets": "4.0.0-dev.20250512105016",
|
|
26
|
+
"@open-pioneer/map": "0.11.0-dev.20250515143825"
|
|
27
27
|
},
|
|
28
28
|
"exports": {
|
|
29
29
|
"./package.json": "./package.json",
|