@open-pioneer/spatial-bookmarks 0.9.0-dev.20250220091855 → 0.9.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 CHANGED
@@ -1,212 +1,221 @@
1
1
  # @open-pioneer/spatial-bookmarks
2
2
 
3
- ## 0.9.0-dev.20250220091855
3
+ ## 0.9.0
4
+
5
+ ### Minor Changes
6
+
7
+ - cb94c75: update dependencies
4
8
 
5
9
  ### Patch Changes
6
10
 
7
- - Updated dependencies [f327eec]
8
- - Updated dependencies [f327eec]
9
- - Updated dependencies [209eb8e]
10
- - @open-pioneer/map@0.9.0-dev.20250220091855
11
+ - Updated dependencies [e7fdc5d]
12
+ - Updated dependencies [cb94c75]
13
+ - Updated dependencies [37cd707]
14
+ - Updated dependencies [32ed2cd]
15
+ - Updated dependencies [f327eec]
16
+ - Updated dependencies [f327eec]
17
+ - Updated dependencies [209eb8e]
18
+ - Updated dependencies [d72e42c]
19
+ - @open-pioneer/map@0.9.0
11
20
 
12
21
  ## 0.8.0
13
22
 
14
23
  ### Minor Changes
15
24
 
16
- - 2fa8020: Update trails core package dependencies.
25
+ - 2fa8020: Update trails core package dependencies.
17
26
 
18
- - Also updates Chakra UI to the latest 2.x version and Chakra React Select to version 5.
19
- - Removes any obsolete references to `@chakra-ui/system`.
20
- This dependency seems to be no longer required and may lead to duplicate packages in your dependency tree.
27
+ - Also updates Chakra UI to the latest 2.x version and Chakra React Select to version 5.
28
+ - Removes any obsolete references to `@chakra-ui/system`.
29
+ This dependency seems to be no longer required and may lead to duplicate packages in your dependency tree.
21
30
 
22
31
  ### Patch Changes
23
32
 
24
- - 49f0207: Update trails core packages to version 2.4.0
25
- - d8337a6: Refactor implementation to use the new reactive properties of the map model.
26
- - Updated dependencies [b717121]
27
- - Updated dependencies [e7978a8]
28
- - Updated dependencies [7a5f1e1]
29
- - Updated dependencies [7ae9f90]
30
- - Updated dependencies [d8337a6]
31
- - Updated dependencies [49f0207]
32
- - Updated dependencies [b2127df]
33
- - Updated dependencies [2fa8020]
34
- - Updated dependencies [7ae9f90]
35
- - Updated dependencies [d8337a6]
36
- - @open-pioneer/map@0.8.0
33
+ - 49f0207: Update trails core packages to version 2.4.0
34
+ - d8337a6: Refactor implementation to use the new reactive properties of the map model.
35
+ - Updated dependencies [b717121]
36
+ - Updated dependencies [e7978a8]
37
+ - Updated dependencies [7a5f1e1]
38
+ - Updated dependencies [7ae9f90]
39
+ - Updated dependencies [d8337a6]
40
+ - Updated dependencies [49f0207]
41
+ - Updated dependencies [b2127df]
42
+ - Updated dependencies [2fa8020]
43
+ - Updated dependencies [7ae9f90]
44
+ - Updated dependencies [d8337a6]
45
+ - @open-pioneer/map@0.8.0
37
46
 
38
47
  ## 0.7.0
39
48
 
40
49
  ### Minor Changes
41
50
 
42
- - 310800c: Switch from `peerDependencies` to normal `dependencies`. Peer dependencies have some usability problems when used at scale.
51
+ - 310800c: Switch from `peerDependencies` to normal `dependencies`. Peer dependencies have some usability problems when used at scale.
43
52
 
44
53
  ### Patch Changes
45
54
 
46
- - 310800c: Update core packages version.
47
- - 583f1d6: The `mapId` or `map` properties are now optional on individual components.
48
- You can use the `DefaultMapProvider` to configure an implicit default value.
55
+ - 310800c: Update core packages version.
56
+ - 583f1d6: The `mapId` or `map` properties are now optional on individual components.
57
+ You can use the `DefaultMapProvider` to configure an implicit default value.
49
58
 
50
59
  Note that configuring _neither_ a default _nor_ an explicit `map` or `mapId` will trigger a runtime error.
51
60
 
52
- - 583f1d6: All UI components in this project now accept the `mapId` (a `string`) _or_ the `map` (a `MapModel`) directly.
53
- - a8b3449: Switch to a new versioning strategy.
54
- From now on, packages released by this repository share a common version number.
55
- - 900eb11: Update dependencies.
56
- - Updated dependencies [310800c]
57
- - Updated dependencies [2502050]
58
- - Updated dependencies [583f1d6]
59
- - Updated dependencies [583f1d6]
60
- - Updated dependencies [397d617]
61
- - Updated dependencies [a8b3449]
62
- - Updated dependencies [310800c]
63
- - Updated dependencies [900eb11]
64
- - Updated dependencies [583f1d6]
65
- - Updated dependencies [397d617]
66
- - @open-pioneer/map@0.7.0
61
+ - 583f1d6: All UI components in this project now accept the `mapId` (a `string`) _or_ the `map` (a `MapModel`) directly.
62
+ - a8b3449: Switch to a new versioning strategy.
63
+ From now on, packages released by this repository share a common version number.
64
+ - 900eb11: Update dependencies.
65
+ - Updated dependencies [310800c]
66
+ - Updated dependencies [2502050]
67
+ - Updated dependencies [583f1d6]
68
+ - Updated dependencies [583f1d6]
69
+ - Updated dependencies [397d617]
70
+ - Updated dependencies [a8b3449]
71
+ - Updated dependencies [310800c]
72
+ - Updated dependencies [900eb11]
73
+ - Updated dependencies [583f1d6]
74
+ - Updated dependencies [397d617]
75
+ - @open-pioneer/map@0.7.0
67
76
 
68
77
  ## 0.4.4
69
78
 
70
79
  ### Patch Changes
71
80
 
72
- - 3e7d978: Use reactivity API to manage internal state.
73
- - b152428: Update trails dependencies
74
- - Updated dependencies [b152428]
75
- - Updated dependencies [291ccb6]
76
- - @open-pioneer/map@0.6.1
81
+ - 3e7d978: Use reactivity API to manage internal state.
82
+ - b152428: Update trails dependencies
83
+ - Updated dependencies [b152428]
84
+ - Updated dependencies [291ccb6]
85
+ - @open-pioneer/map@0.6.1
77
86
 
78
87
  ## 0.4.3
79
88
 
80
89
  ### Patch Changes
81
90
 
82
- - 28e092a: Update dependencies
83
- - Updated dependencies [28e092a]
84
- - Updated dependencies [0d51d2f]
85
- - Updated dependencies [76f8863]
86
- - @open-pioneer/map@0.6.0
91
+ - 28e092a: Update dependencies
92
+ - Updated dependencies [28e092a]
93
+ - Updated dependencies [0d51d2f]
94
+ - Updated dependencies [76f8863]
95
+ - @open-pioneer/map@0.6.0
87
96
 
88
97
  ## 0.4.2
89
98
 
90
99
  ### Patch Changes
91
100
 
92
- - 4140646: Update trails dependencies
93
- - 4140646: Update to react 18.3.1
94
- - 81bc7da: Update trails dependencies
95
- - 2c092dc: Update dependencies
96
- - Updated dependencies [4140646]
97
- - Updated dependencies [4140646]
98
- - Updated dependencies [b5bb7a1]
99
- - Updated dependencies [81bc7da]
100
- - Updated dependencies [2c092dc]
101
- - Updated dependencies [4140646]
102
- - @open-pioneer/react-utils@0.2.3
103
- - @open-pioneer/map@0.5.1
101
+ - 4140646: Update trails dependencies
102
+ - 4140646: Update to react 18.3.1
103
+ - 81bc7da: Update trails dependencies
104
+ - 2c092dc: Update dependencies
105
+ - Updated dependencies [4140646]
106
+ - Updated dependencies [4140646]
107
+ - Updated dependencies [b5bb7a1]
108
+ - Updated dependencies [81bc7da]
109
+ - Updated dependencies [2c092dc]
110
+ - Updated dependencies [4140646]
111
+ - @open-pioneer/react-utils@0.2.3
112
+ - @open-pioneer/map@0.5.1
104
113
 
105
114
  ## 0.4.1
106
115
 
107
116
  ### Patch Changes
108
117
 
109
- - Updated dependencies [520a97b]
110
- - @open-pioneer/map@0.5.0
118
+ - Updated dependencies [520a97b]
119
+ - @open-pioneer/map@0.5.0
111
120
 
112
121
  ## 0.4.0
113
122
 
114
123
  ### Minor Changes
115
124
 
116
- - 9334e81: Update to OpenLayers 9
125
+ - 9334e81: Update to OpenLayers 9
117
126
 
118
127
  ### Patch Changes
119
128
 
120
- - 1a8ad89: Update package.json metadata
121
- - 6162979: Update versions of core packages
122
- - Updated dependencies [1a8ad89]
123
- - Updated dependencies [a11bf72]
124
- - Updated dependencies [fc6bf82]
125
- - Updated dependencies [a0d8882]
126
- - Updated dependencies [6162979]
127
- - Updated dependencies [9334e81]
128
- - Updated dependencies [ac7fdd1]
129
- - Updated dependencies [13ea342]
130
- - @open-pioneer/react-utils@0.2.2
131
- - @open-pioneer/map@0.4.0
129
+ - 1a8ad89: Update package.json metadata
130
+ - 6162979: Update versions of core packages
131
+ - Updated dependencies [1a8ad89]
132
+ - Updated dependencies [a11bf72]
133
+ - Updated dependencies [fc6bf82]
134
+ - Updated dependencies [a0d8882]
135
+ - Updated dependencies [6162979]
136
+ - Updated dependencies [9334e81]
137
+ - Updated dependencies [ac7fdd1]
138
+ - Updated dependencies [13ea342]
139
+ - @open-pioneer/react-utils@0.2.2
140
+ - @open-pioneer/map@0.4.0
132
141
 
133
142
  ## 0.3.1
134
143
 
135
144
  ### Patch Changes
136
145
 
137
- - Updated dependencies [611ddb9]
138
- - @open-pioneer/map@0.3.1
146
+ - Updated dependencies [611ddb9]
147
+ - @open-pioneer/map@0.3.1
139
148
 
140
149
  ## 0.3.0
141
150
 
142
151
  ### Minor Changes
143
152
 
144
- - ee7c2d4: Update runtime version.
153
+ - ee7c2d4: Update runtime version.
145
154
 
146
155
  ### Patch Changes
147
156
 
148
- - Updated dependencies [ee7c2d4]
149
- - Updated dependencies [a582e5e]
150
- - Updated dependencies [0456500]
151
- - Updated dependencies [762e7b9]
152
- - @open-pioneer/local-storage@0.3.0
153
- - @open-pioneer/map@0.3.0
154
- - @open-pioneer/react-utils@0.2.1
157
+ - Updated dependencies [ee7c2d4]
158
+ - Updated dependencies [a582e5e]
159
+ - Updated dependencies [0456500]
160
+ - Updated dependencies [762e7b9]
161
+ - @open-pioneer/local-storage@0.3.0
162
+ - @open-pioneer/map@0.3.0
163
+ - @open-pioneer/react-utils@0.2.1
155
164
 
156
165
  ## 0.2.0
157
166
 
158
167
  ### Minor Changes
159
168
 
160
- - 70349a8: Update to new core packages major versions
169
+ - 70349a8: Update to new core packages major versions
161
170
 
162
171
  ### Patch Changes
163
172
 
164
- - Updated dependencies [70349a8]
165
- - @open-pioneer/local-storage@0.2.0
166
- - @open-pioneer/map@0.2.0
167
- - @open-pioneer/react-utils@0.2.0
173
+ - Updated dependencies [70349a8]
174
+ - @open-pioneer/local-storage@0.2.0
175
+ - @open-pioneer/map@0.2.0
176
+ - @open-pioneer/react-utils@0.2.0
168
177
 
169
178
  ## 0.1.0
170
179
 
171
180
  ### Minor Changes
172
181
 
173
- - 3ca8a25: Initial release
182
+ - 3ca8a25: Initial release
174
183
 
175
184
  ### Patch Changes
176
185
 
177
- - Updated dependencies [08bffbc]
178
- - Updated dependencies [a58546b]
179
- - Updated dependencies [3ca8a25]
180
- - Updated dependencies [a58546b]
181
- - Updated dependencies [0c4ce04]
182
- - @open-pioneer/map@0.1.1
183
- - @open-pioneer/local-storage@0.1.0
186
+ - Updated dependencies [08bffbc]
187
+ - Updated dependencies [a58546b]
188
+ - Updated dependencies [3ca8a25]
189
+ - Updated dependencies [a58546b]
190
+ - Updated dependencies [0c4ce04]
191
+ - @open-pioneer/map@0.1.1
192
+ - @open-pioneer/local-storage@0.1.0
184
193
 
185
194
  ## 0.2.0
186
195
 
187
196
  ### Minor Changes
188
197
 
189
- - 70349a8: Update to new core packages major versions
198
+ - 70349a8: Update to new core packages major versions
190
199
 
191
200
  ### Patch Changes
192
201
 
193
- - Updated dependencies [70349a8]
194
- - @open-pioneer/local-storage@0.2.0
195
- - @open-pioneer/map@0.2.0
196
- - @open-pioneer/react-utils@0.2.0
202
+ - Updated dependencies [70349a8]
203
+ - @open-pioneer/local-storage@0.2.0
204
+ - @open-pioneer/map@0.2.0
205
+ - @open-pioneer/react-utils@0.2.0
197
206
 
198
207
  ## 0.1.0
199
208
 
200
209
  ### Minor Changes
201
210
 
202
- - 3ca8a25: Initial release
211
+ - 3ca8a25: Initial release
203
212
 
204
213
  ### Patch Changes
205
214
 
206
- - Updated dependencies [08bffbc]
207
- - Updated dependencies [a58546b]
208
- - Updated dependencies [3ca8a25]
209
- - Updated dependencies [a58546b]
210
- - Updated dependencies [0c4ce04]
211
- - @open-pioneer/map@0.1.1
212
- - @open-pioneer/local-storage@0.1.0
215
+ - Updated dependencies [08bffbc]
216
+ - Updated dependencies [a58546b]
217
+ - Updated dependencies [3ca8a25]
218
+ - Updated dependencies [a58546b]
219
+ - Updated dependencies [0c4ce04]
220
+ - @open-pioneer/map@0.1.1
221
+ - @open-pioneer/local-storage@0.1.0
@@ -1,11 +1,11 @@
1
1
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
2
- import { Flex, VStack, Alert, AlertIcon, Input, List, Box, Center, Text, Spacer, Tooltip, Button } from '@open-pioneer/chakra-integration';
2
+ import { Flex, Alert, AlertIcon, VStack, Input, List, Box, Center, Text, Spacer, Tooltip, Button } from '@open-pioneer/chakra-integration';
3
3
  import { useMapModel } from '@open-pioneer/map';
4
4
  import { useCommonComponentProps } from '@open-pioneer/react-utils';
5
5
  import classNames from 'classnames';
6
6
  import { useService, useIntl } from './_virtual/_virtual-pioneer-module_react-hooks.js';
7
- import { useRef, useState, useEffect } from 'react';
8
- import { PiMapTrifold, PiTrashSimpleLight } from 'react-icons/pi';
7
+ import { useState, useEffect, useRef } from 'react';
8
+ import { PiTrashSimpleLight, PiMapTrifold } from 'react-icons/pi';
9
9
  import { SpatialBookmarkViewModel } from './SpatialBookmarksViewModel.js';
10
10
  import { useReactiveSnapshot } from '@open-pioneer/reactivity';
11
11
 
@@ -1 +1 @@
1
- {"version":3,"file":"SpatialBookmarks.js","sources":["SpatialBookmarks.tsx"],"sourcesContent":["// SPDX-FileCopyrightText: 2023 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport {\n Alert,\n AlertIcon,\n Box,\n Button,\n ButtonProps,\n Flex,\n Input,\n List,\n Spacer,\n Text,\n Tooltip,\n VStack,\n Center\n} from \"@open-pioneer/chakra-integration\";\nimport { LocalStorageService } from \"@open-pioneer/local-storage\";\nimport { MapModel, MapModelProps, useMapModel } from \"@open-pioneer/map\";\nimport { CommonComponentProps, useCommonComponentProps } from \"@open-pioneer/react-utils\";\nimport { PackageIntl } from \"@open-pioneer/runtime\";\nimport classNames from \"classnames\";\nimport { useIntl, useService } from \"open-pioneer:react-hooks\";\nimport { FC, KeyboardEvent, ReactNode, useEffect, useRef, useState } from \"react\";\nimport { PiMapTrifold, PiTrashSimpleLight } from \"react-icons/pi\";\nimport { Bookmark, SpatialBookmarkViewModel } from \"./SpatialBookmarksViewModel\";\nimport { useReactiveSnapshot } from \"@open-pioneer/reactivity\";\n\ntype UIMode = \"list\" | \"create\" | \"delete\";\n\nexport interface SpatialBookmarksProps extends CommonComponentProps, MapModelProps {}\n\n/**\n * A component that allows the user to manage a set of spatial bookmarks.\n */\nexport const SpatialBookmarks: FC<SpatialBookmarksProps> = (props) => {\n const { map } = useMapModel(props);\n const localStorageService = useService<LocalStorageService>(\n \"local-storage.LocalStorageService\"\n );\n const viewModel = useViewModel(map, localStorageService);\n return viewModel && <SpatialBookmarkUI {...props} viewModel={viewModel} />;\n};\n\nfunction SpatialBookmarkUI(props: SpatialBookmarksProps & { viewModel: SpatialBookmarkViewModel }) {\n const { viewModel } = props;\n const intl = useIntl();\n const listItemNodes = useRef<HTMLElement[]>([]);\n const [scrollToLastItem, setScrollToLastItem] = useState(false);\n const bookmarks = useReactiveSnapshot(() => viewModel.bookmarks, [viewModel]);\n const [bookmarkName, setBookmarkName] = useState<string>(\"\");\n const isValidBookmarkName = bookmarkName.trim().length > 0; // use trim to avoid bookmarks with space character only\n const { containerProps } = useCommonComponentProps(\"spatial-bookmarks\", props);\n const [uiMode, setUiMode] = useState<UIMode>(\"list\");\n\n const clearBookmarks = () => {\n viewModel.deleteAllBookmarks();\n setUiMode(\"list\");\n };\n\n const addBookmark = () => {\n if (isValidBookmarkName) {\n viewModel.createBookmark(bookmarkName);\n setUiMode(\"list\");\n setBookmarkName(\"\");\n setScrollToLastItem(true);\n }\n };\n\n // Scroll to newly created bookmark after render\n useEffect(() => {\n if (scrollToLastItem) {\n const listItems = listItemNodes.current;\n if (listItems) {\n const lastItem = listItems[bookmarks.length - 1];\n lastItem?.scrollIntoView?.();\n }\n setScrollToLastItem(false);\n }\n }, [bookmarks, scrollToLastItem]);\n\n const deleteContent = () => (\n <VStack>\n <Alert rounded=\"md\" status=\"warning\">\n <AlertIcon />\n {intl.formatMessage({ id: \"bookmark.alert.delete\" })}\n </Alert>\n <RemoveControls\n intl={intl}\n onClear={clearBookmarks}\n onCancel={() => setUiMode(\"list\")}\n />\n </VStack>\n );\n\n const createContent = () => (\n <VStack>\n <Alert rounded=\"md\" status=\"info\">\n <AlertIcon />\n {intl.formatMessage({ id: \"bookmark.alert.create\" })}\n </Alert>\n <Input\n aria-label={intl.formatMessage({ id: \"bookmark.input.label\" })}\n placeholder={intl.formatMessage({ id: \"bookmark.input.placeholder\" })}\n value={bookmarkName}\n onChange={(event) => {\n setBookmarkName(event.target.value);\n }}\n onKeyDown={(e) => {\n // add bookmark only, if valid bookmark name exists\n if (e.key === \"Enter\") {\n addBookmark();\n }\n }}\n isRequired\n isInvalid={!isValidBookmarkName}\n autoFocus // eslint-disable-line jsx-a11y/no-autofocus\n />\n <CreateControls\n intl={intl}\n isInvalid={!isValidBookmarkName}\n onCancel={() => {\n setBookmarkName(\"\");\n setUiMode(\"list\");\n }}\n onSave={addBookmark}\n />\n </VStack>\n );\n\n const listContent = () => (\n <>\n {bookmarks.length ? (\n createList(bookmarks, viewModel, intl, listItemNodes)\n ) : (\n <Alert rounded=\"md\" status=\"info\">\n <AlertIcon />\n {intl.formatMessage({ id: \"bookmark.alert.noSaved\" })}\n </Alert>\n )}\n <ListControls\n intl={intl}\n bookmarks={bookmarks}\n showCreate={() => setUiMode(\"create\")}\n showDelete={() => setUiMode(\"delete\")}\n />\n </>\n );\n\n const content = (\n <>\n {uiMode === \"list\" && listContent()}\n {uiMode === \"create\" && createContent()}\n {uiMode === \"delete\" && deleteContent()}\n </>\n );\n\n return (\n <Flex flexDirection=\"column\" {...containerProps}>\n {content}\n </Flex>\n );\n}\n\nfunction createList(\n bookmarks: Bookmark[],\n viewModel: SpatialBookmarkViewModel,\n intl: PackageIntl,\n listRef: React.MutableRefObject<HTMLElement[]>\n) {\n const deleteBtnLabel = intl.formatMessage({\n id: \"bookmark.button.deleteOne\"\n });\n\n const bookmarkItems = bookmarks.map((bookmark, idx) => (\n <BookmarkItem\n key={bookmark.id}\n index={idx}\n listItemNodes={listRef}\n bookmark={bookmark}\n onActivate={() => viewModel.activateBookmark(bookmark)}\n onDelete={() => viewModel.deleteBookmark(bookmark.id)}\n deleteBtnLabel={deleteBtnLabel}\n />\n ));\n\n return (\n <List\n as=\"ul\"\n className=\"spatial-bookmark-list\"\n role=\"listbox\"\n aria-label={intl.formatMessage({\n id: \"bookmark.list.label\"\n })}\n flexShrink={1}\n flexGrow={1}\n p={1} // Some padding for children's box shadow\n spacing={1}\n overflowY=\"auto\"\n listStyleType=\"none\"\n >\n {bookmarkItems}\n </List>\n );\n}\n\n// key name -> index\nconst ARROW_INDEX_MAP: Record<string, number> = {\n ArrowDown: 1,\n ArrowUp: -1\n};\n\nfunction BookmarkItem(props: {\n index: number;\n listItemNodes: React.MutableRefObject<HTMLElement[]>;\n bookmark: Bookmark;\n onActivate: () => void;\n onDelete: () => void;\n deleteBtnLabel: string;\n}): JSX.Element {\n const { index, listItemNodes, bookmark, onDelete, onActivate, deleteBtnLabel } = props;\n const title = bookmark.title;\n const onKeyDown = (evt: KeyboardEvent) => {\n const key = evt.key;\n if (key === \"Enter\") {\n // Ignore enter from child components (buttons)\n if (evt.target === evt.currentTarget) {\n onActivate();\n }\n return;\n }\n\n if (ARROW_INDEX_MAP[key] != null) {\n const len = listItemNodes.current?.length;\n if (!len) {\n return;\n }\n\n let nextIndex = (index + ARROW_INDEX_MAP[key]!) % len;\n if (nextIndex < 0) {\n nextIndex = len - 1;\n }\n listItemNodes.current[nextIndex]?.focus();\n }\n };\n return (\n <Box\n as=\"li\"\n p={1}\n ref={(el: HTMLDivElement | null) => {\n if (!el) {\n listItemNodes.current.splice(index, 1);\n return;\n }\n listItemNodes.current[index] = el;\n }}\n className={classNames(\"spatial-bookmarks-item\")}\n tabIndex={0}\n rounded=\"md\"\n role=\"option\"\n cursor=\"pointer\"\n outline={0}\n _hover={{ background: \"trails.50\" }}\n _focusVisible={{ boxShadow: \"outline\" }}\n onKeyDown={onKeyDown}\n onClick={onActivate}\n >\n <Flex width=\"100%\" flexDirection=\"row\" align=\"center\" gap={1}>\n <Center>\n <PiMapTrifold />\n </Center>\n <Text ps={2} noOfLines={1}>\n {title}\n </Text>\n <Spacer />\n <Tooltip key={index} hasArrow label={deleteBtnLabel} placement=\"right\">\n <Button\n className=\"spatial-bookmarks-item-delete\"\n aria-label={deleteBtnLabel}\n borderRadius=\"full\"\n iconSpacing={0}\n padding={0}\n colorScheme=\"red\"\n variant=\"ghost\"\n leftIcon={<PiTrashSimpleLight />}\n onClick={(event) => {\n onDelete();\n event.stopPropagation();\n }}\n />\n </Tooltip>\n </Flex>\n </Box>\n );\n}\n\nfunction ListControls(props: {\n intl: PackageIntl;\n bookmarks: Bookmark[];\n showCreate: () => void;\n showDelete: () => void;\n}): JSX.Element {\n const { intl, bookmarks, showCreate, showDelete } = props;\n\n return (\n <ButtonContainer>\n <DialogButton\n isDisabled={bookmarks.length === 0}\n colorScheme=\"red\"\n width={undefined}\n iconSpacing={0}\n leftIcon={<PiTrashSimpleLight />}\n onClick={showDelete}\n aria-label={intl.formatMessage({ id: \"bookmark.button.deleteAll\" })}\n variant=\"outline\"\n />\n <DialogButton onClick={showCreate} width=\"100%\">\n {intl.formatMessage({ id: \"bookmark.button.create\" })}\n </DialogButton>\n </ButtonContainer>\n );\n}\n\nfunction RemoveControls(props: { intl: PackageIntl; onClear: () => void; onCancel: () => void }) {\n const { intl, onCancel, onClear } = props;\n return (\n <ButtonContainer>\n <DialogButton variant=\"outline\" onClick={onCancel}>\n {intl.formatMessage({ id: \"bookmark.button.cancelDelete\" })}\n </DialogButton>\n <DialogButton onClick={onClear}>\n {intl.formatMessage({ id: \"bookmark.button.confirmDelete\" })}\n </DialogButton>\n </ButtonContainer>\n );\n}\n\nfunction CreateControls(props: {\n intl: PackageIntl;\n isInvalid: boolean;\n onCancel: () => void;\n onSave: () => void;\n}) {\n const { intl, onCancel, onSave, isInvalid } = props;\n return (\n <ButtonContainer>\n <DialogButton variant=\"outline\" onClick={() => onCancel()}>\n {intl.formatMessage({ id: \"bookmark.button.cancel\" })}\n </DialogButton>\n <DialogButton isDisabled={isInvalid} onClick={() => onSave()}>\n {intl.formatMessage({ id: \"bookmark.button.save\" })}\n </DialogButton>\n </ButtonContainer>\n );\n}\n\nfunction ButtonContainer(props: { children: ReactNode }) {\n return (\n <Flex width=\"100%\" flexDirection=\"row\" mt={2} gap={1} flexGrow={0} flexShrink={0}>\n {props.children}\n </Flex>\n );\n}\n\nfunction DialogButton(props?: ButtonProps): JSX.Element {\n return <Button width=\"100%\" {...props} />;\n}\n\nfunction useViewModel(map: MapModel | undefined, localStorageService: LocalStorageService) {\n const [viewModel, setViewModel] = useState<SpatialBookmarkViewModel>();\n useEffect(() => {\n let viewModel: SpatialBookmarkViewModel | undefined;\n if (!map) {\n viewModel = undefined;\n } else {\n viewModel = new SpatialBookmarkViewModel(map, localStorageService);\n }\n\n setViewModel(viewModel);\n return () => viewModel?.destroy();\n }, [map, localStorageService]);\n\n return viewModel;\n}\n"],"names":["viewModel"],"mappings":"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"}
1
+ {"version":3,"file":"SpatialBookmarks.js","sources":["SpatialBookmarks.tsx"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport {\n Alert,\n AlertIcon,\n Box,\n Button,\n ButtonProps,\n Flex,\n Input,\n List,\n Spacer,\n Text,\n Tooltip,\n VStack,\n Center\n} from \"@open-pioneer/chakra-integration\";\nimport { LocalStorageService } from \"@open-pioneer/local-storage\";\nimport { MapModel, MapModelProps, useMapModel } from \"@open-pioneer/map\";\nimport { CommonComponentProps, useCommonComponentProps } from \"@open-pioneer/react-utils\";\nimport { PackageIntl } from \"@open-pioneer/runtime\";\nimport classNames from \"classnames\";\nimport { useIntl, useService } from \"open-pioneer:react-hooks\";\nimport { FC, KeyboardEvent, ReactNode, useEffect, useRef, useState } from \"react\";\nimport { PiMapTrifold, PiTrashSimpleLight } from \"react-icons/pi\";\nimport { Bookmark, SpatialBookmarkViewModel } from \"./SpatialBookmarksViewModel\";\nimport { useReactiveSnapshot } from \"@open-pioneer/reactivity\";\n\ntype UIMode = \"list\" | \"create\" | \"delete\";\n\nexport interface SpatialBookmarksProps extends CommonComponentProps, MapModelProps {}\n\n/**\n * A component that allows the user to manage a set of spatial bookmarks.\n */\nexport const SpatialBookmarks: FC<SpatialBookmarksProps> = (props) => {\n const { map } = useMapModel(props);\n const localStorageService = useService<LocalStorageService>(\n \"local-storage.LocalStorageService\"\n );\n const viewModel = useViewModel(map, localStorageService);\n return viewModel && <SpatialBookmarkUI {...props} viewModel={viewModel} />;\n};\n\nfunction SpatialBookmarkUI(props: SpatialBookmarksProps & { viewModel: SpatialBookmarkViewModel }) {\n const { viewModel } = props;\n const intl = useIntl();\n const listItemNodes = useRef<HTMLElement[]>([]);\n const [scrollToLastItem, setScrollToLastItem] = useState(false);\n const bookmarks = useReactiveSnapshot(() => viewModel.bookmarks, [viewModel]);\n const [bookmarkName, setBookmarkName] = useState<string>(\"\");\n const isValidBookmarkName = bookmarkName.trim().length > 0; // use trim to avoid bookmarks with space character only\n const { containerProps } = useCommonComponentProps(\"spatial-bookmarks\", props);\n const [uiMode, setUiMode] = useState<UIMode>(\"list\");\n\n const clearBookmarks = () => {\n viewModel.deleteAllBookmarks();\n setUiMode(\"list\");\n };\n\n const addBookmark = () => {\n if (isValidBookmarkName) {\n viewModel.createBookmark(bookmarkName);\n setUiMode(\"list\");\n setBookmarkName(\"\");\n setScrollToLastItem(true);\n }\n };\n\n // Scroll to newly created bookmark after render\n useEffect(() => {\n if (scrollToLastItem) {\n const listItems = listItemNodes.current;\n if (listItems) {\n const lastItem = listItems[bookmarks.length - 1];\n lastItem?.scrollIntoView?.();\n }\n setScrollToLastItem(false);\n }\n }, [bookmarks, scrollToLastItem]);\n\n const deleteContent = () => (\n <VStack>\n <Alert rounded=\"md\" status=\"warning\">\n <AlertIcon />\n {intl.formatMessage({ id: \"bookmark.alert.delete\" })}\n </Alert>\n <RemoveControls\n intl={intl}\n onClear={clearBookmarks}\n onCancel={() => setUiMode(\"list\")}\n />\n </VStack>\n );\n\n const createContent = () => (\n <VStack>\n <Alert rounded=\"md\" status=\"info\">\n <AlertIcon />\n {intl.formatMessage({ id: \"bookmark.alert.create\" })}\n </Alert>\n <Input\n aria-label={intl.formatMessage({ id: \"bookmark.input.label\" })}\n placeholder={intl.formatMessage({ id: \"bookmark.input.placeholder\" })}\n value={bookmarkName}\n onChange={(event) => {\n setBookmarkName(event.target.value);\n }}\n onKeyDown={(e) => {\n // add bookmark only, if valid bookmark name exists\n if (e.key === \"Enter\") {\n addBookmark();\n }\n }}\n isRequired\n isInvalid={!isValidBookmarkName}\n autoFocus // eslint-disable-line jsx-a11y/no-autofocus\n />\n <CreateControls\n intl={intl}\n isInvalid={!isValidBookmarkName}\n onCancel={() => {\n setBookmarkName(\"\");\n setUiMode(\"list\");\n }}\n onSave={addBookmark}\n />\n </VStack>\n );\n\n const listContent = () => (\n <>\n {bookmarks.length ? (\n createList(bookmarks, viewModel, intl, listItemNodes)\n ) : (\n <Alert rounded=\"md\" status=\"info\">\n <AlertIcon />\n {intl.formatMessage({ id: \"bookmark.alert.noSaved\" })}\n </Alert>\n )}\n <ListControls\n intl={intl}\n bookmarks={bookmarks}\n showCreate={() => setUiMode(\"create\")}\n showDelete={() => setUiMode(\"delete\")}\n />\n </>\n );\n\n const content = (\n <>\n {uiMode === \"list\" && listContent()}\n {uiMode === \"create\" && createContent()}\n {uiMode === \"delete\" && deleteContent()}\n </>\n );\n\n return (\n <Flex flexDirection=\"column\" {...containerProps}>\n {content}\n </Flex>\n );\n}\n\nfunction createList(\n bookmarks: Bookmark[],\n viewModel: SpatialBookmarkViewModel,\n intl: PackageIntl,\n listRef: React.MutableRefObject<HTMLElement[]>\n) {\n const deleteBtnLabel = intl.formatMessage({\n id: \"bookmark.button.deleteOne\"\n });\n\n const bookmarkItems = bookmarks.map((bookmark, idx) => (\n <BookmarkItem\n key={bookmark.id}\n index={idx}\n listItemNodes={listRef}\n bookmark={bookmark}\n onActivate={() => viewModel.activateBookmark(bookmark)}\n onDelete={() => viewModel.deleteBookmark(bookmark.id)}\n deleteBtnLabel={deleteBtnLabel}\n />\n ));\n\n return (\n <List\n as=\"ul\"\n className=\"spatial-bookmark-list\"\n role=\"listbox\"\n aria-label={intl.formatMessage({\n id: \"bookmark.list.label\"\n })}\n flexShrink={1}\n flexGrow={1}\n p={1} // Some padding for children's box shadow\n spacing={1}\n overflowY=\"auto\"\n listStyleType=\"none\"\n >\n {bookmarkItems}\n </List>\n );\n}\n\n// key name -> index\nconst ARROW_INDEX_MAP: Record<string, number> = {\n ArrowDown: 1,\n ArrowUp: -1\n};\n\nfunction BookmarkItem(props: {\n index: number;\n listItemNodes: React.MutableRefObject<HTMLElement[]>;\n bookmark: Bookmark;\n onActivate: () => void;\n onDelete: () => void;\n deleteBtnLabel: string;\n}): ReactNode {\n const { index, listItemNodes, bookmark, onDelete, onActivate, deleteBtnLabel } = props;\n const title = bookmark.title;\n const onKeyDown = (evt: KeyboardEvent) => {\n const key = evt.key;\n if (key === \"Enter\") {\n // Ignore enter from child components (buttons)\n if (evt.target === evt.currentTarget) {\n onActivate();\n }\n return;\n }\n\n if (ARROW_INDEX_MAP[key] != null) {\n const len = listItemNodes.current?.length;\n if (!len) {\n return;\n }\n\n let nextIndex = (index + ARROW_INDEX_MAP[key]!) % len;\n if (nextIndex < 0) {\n nextIndex = len - 1;\n }\n listItemNodes.current[nextIndex]?.focus();\n }\n };\n return (\n <Box\n as=\"li\"\n p={1}\n ref={(el: HTMLDivElement | null) => {\n if (!el) {\n listItemNodes.current.splice(index, 1);\n return;\n }\n listItemNodes.current[index] = el;\n }}\n className={classNames(\"spatial-bookmarks-item\")}\n tabIndex={0}\n rounded=\"md\"\n role=\"option\"\n cursor=\"pointer\"\n outline={0}\n _hover={{ background: \"trails.50\" }}\n _focusVisible={{ boxShadow: \"outline\" }}\n onKeyDown={onKeyDown}\n onClick={onActivate}\n >\n <Flex width=\"100%\" flexDirection=\"row\" align=\"center\" gap={1}>\n <Center>\n <PiMapTrifold />\n </Center>\n <Text ps={2} noOfLines={1}>\n {title}\n </Text>\n <Spacer />\n <Tooltip key={index} hasArrow label={deleteBtnLabel} placement=\"right\">\n <Button\n className=\"spatial-bookmarks-item-delete\"\n aria-label={deleteBtnLabel}\n borderRadius=\"full\"\n iconSpacing={0}\n padding={0}\n colorScheme=\"red\"\n variant=\"ghost\"\n leftIcon={<PiTrashSimpleLight />}\n onClick={(event) => {\n onDelete();\n event.stopPropagation();\n }}\n />\n </Tooltip>\n </Flex>\n </Box>\n );\n}\n\nfunction ListControls(props: {\n intl: PackageIntl;\n bookmarks: Bookmark[];\n showCreate: () => void;\n showDelete: () => void;\n}): ReactNode {\n const { intl, bookmarks, showCreate, showDelete } = props;\n\n return (\n <ButtonContainer>\n <DialogButton\n isDisabled={bookmarks.length === 0}\n colorScheme=\"red\"\n width={undefined}\n iconSpacing={0}\n leftIcon={<PiTrashSimpleLight />}\n onClick={showDelete}\n aria-label={intl.formatMessage({ id: \"bookmark.button.deleteAll\" })}\n variant=\"outline\"\n />\n <DialogButton onClick={showCreate} width=\"100%\">\n {intl.formatMessage({ id: \"bookmark.button.create\" })}\n </DialogButton>\n </ButtonContainer>\n );\n}\n\nfunction RemoveControls(props: { intl: PackageIntl; onClear: () => void; onCancel: () => void }) {\n const { intl, onCancel, onClear } = props;\n return (\n <ButtonContainer>\n <DialogButton variant=\"outline\" onClick={onCancel}>\n {intl.formatMessage({ id: \"bookmark.button.cancelDelete\" })}\n </DialogButton>\n <DialogButton onClick={onClear}>\n {intl.formatMessage({ id: \"bookmark.button.confirmDelete\" })}\n </DialogButton>\n </ButtonContainer>\n );\n}\n\nfunction CreateControls(props: {\n intl: PackageIntl;\n isInvalid: boolean;\n onCancel: () => void;\n onSave: () => void;\n}) {\n const { intl, onCancel, onSave, isInvalid } = props;\n return (\n <ButtonContainer>\n <DialogButton variant=\"outline\" onClick={() => onCancel()}>\n {intl.formatMessage({ id: \"bookmark.button.cancel\" })}\n </DialogButton>\n <DialogButton isDisabled={isInvalid} onClick={() => onSave()}>\n {intl.formatMessage({ id: \"bookmark.button.save\" })}\n </DialogButton>\n </ButtonContainer>\n );\n}\n\nfunction ButtonContainer(props: { children: ReactNode }) {\n return (\n <Flex width=\"100%\" flexDirection=\"row\" mt={2} gap={1} flexGrow={0} flexShrink={0}>\n {props.children}\n </Flex>\n );\n}\n\nfunction DialogButton(props?: ButtonProps): ReactNode {\n return <Button width=\"100%\" {...props} />;\n}\n\nfunction useViewModel(map: MapModel | undefined, localStorageService: LocalStorageService) {\n const [viewModel, setViewModel] = useState<SpatialBookmarkViewModel>();\n useEffect(() => {\n let viewModel: SpatialBookmarkViewModel | undefined;\n if (!map) {\n viewModel = undefined;\n } else {\n viewModel = new SpatialBookmarkViewModel(map, localStorageService);\n }\n\n setViewModel(viewModel);\n return () => viewModel?.destroy();\n }, [map, localStorageService]);\n\n return viewModel;\n}\n"],"names":["viewModel"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"SpatialBookmarksViewModel.js","sources":["SpatialBookmarksViewModel.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport { MapModel } from \"@open-pioneer/map\";\nimport { LocalStorageNamespace, LocalStorageService } from \"@open-pioneer/local-storage\";\nimport { v4 as uuid4v } from \"uuid\";\nimport { Extent as OlExtent, getCenter } from \"ol/extent\";\nimport { transformExtent } from \"ol/proj\";\nimport { createLogger } from \"@open-pioneer/core\";\nimport { CleanupHandle, reactiveArray, watch } from \"@conterra/reactivity-core\";\n\nconst LOG = createLogger(\"spatial-bookmark:SpatialBookmarkViewModel\");\n\ninterface Extent {\n minX: number;\n minY: number;\n maxX: number;\n maxY: number;\n}\n\nexport interface Bookmark {\n id: string;\n title: string;\n extent: Extent;\n projection: string;\n}\n\nexport class SpatialBookmarkViewModel {\n private map: MapModel;\n private packageNamespace: LocalStorageNamespace;\n private writableBookmarks = reactiveArray<Bookmark>([]);\n private watchBookmarksHandle: CleanupHandle;\n\n /**\n * Provides read-only access to the bookmarks array.\n * The UI simply renders the contents of the store and\n * uses the methods below to modify the state.\n */\n get bookmarks(): Bookmark[] {\n return this.writableBookmarks.getItems();\n }\n\n constructor(map: MapModel, localStorageService: LocalStorageService) {\n this.map = map;\n this.packageNamespace = localStorageService.getNamespace(\"spatial-bookmarks\");\n\n // Load from local storage on start; save changes whenever bookmarks change.\n this.loadState();\n this.watchBookmarksHandle = watch(\n () => [this.writableBookmarks.getItems()],\n ([bookmarks]) => this.saveState(bookmarks),\n { immediate: false }\n );\n }\n\n destroy() {\n this.watchBookmarksHandle.destroy();\n }\n\n /**\n * Creates a new bookmark with the `title` provided by the UI.\n * The current map extent is used for the new bookmark's extent.\n */\n createBookmark(title: string) {\n // minx, miny, maxx, maxy\n const olExtent = this.map.olView.calculateExtent();\n const projection = this.map.projection.getCode();\n const extent: Extent = {\n minX: olExtent[0]!,\n minY: olExtent[1]!,\n maxX: olExtent[2]!,\n maxY: olExtent[3]!\n };\n const bookmark: Bookmark = {\n id: uuid4v(),\n title,\n extent,\n projection\n };\n LOG.debug(\"Created a new bookmark\", bookmark);\n\n const bookmarks = this.writableBookmarks;\n bookmarks.push(bookmark);\n }\n\n /**\n * Activates the bookmark with the given id by zooming\n * to the bookmark's extent.\n */\n activateBookmark(bookmark: Bookmark) {\n LOG.debug(\"Activating bookmark\", bookmark);\n const extent = this.getBookmarkExtent(bookmark);\n\n LOG.debug(\"Attempting to apply extent\", extent);\n this.applyExtent(extent);\n }\n\n /**\n * Deletes the bookmark with the given id.\n */\n deleteBookmark(id: string) {\n LOG.debug(\"Deleting bookmark\", id);\n const index = this.writableBookmarks.findIndex((bookmark) => bookmark.id === id);\n if (index > -1) {\n this.writableBookmarks.splice(index, 1);\n }\n }\n\n /**\n * Deletes all bookmarks.\n */\n deleteAllBookmarks() {\n LOG.debug(\"Deleting all bookmarks\");\n this.writableBookmarks.splice(0);\n }\n\n /**\n * Loads the bookmarks from local storage.\n * If the bookmarks are not valid, the initial state (empty array) is restored.\n */\n private loadState() {\n LOG.debug(\"Restoring bookmarks from local storage\");\n\n const rawBookmarks = this.packageNamespace.get(\"bookmarks\") ?? [];\n try {\n validateBookmarks(rawBookmarks);\n this.writableBookmarks.push(...rawBookmarks);\n } catch (e) {\n LOG.error(\"Bookmarks data in local storage is invalid, resetting to default value.\", e);\n this.writableBookmarks.splice(0);\n this.saveState([]);\n }\n }\n\n /**\n * Saves the bookmarks to local storage.\n */\n private saveState(bookmarks: Bookmark[]) {\n LOG.debug(\"Saving bookmarks to local storage\");\n this.packageNamespace.set(\"bookmarks\", bookmarks);\n }\n\n /** Computes an OpenLayers extent for the given bookmark. */\n private getBookmarkExtent(bookmark: Bookmark) {\n const olView = this.map.olView;\n const extent = bookmark.extent;\n const olExtent = [extent.minX, extent.minY, extent.maxX, extent.maxY];\n const viewProjection = olView.getProjection();\n const extentProjection = bookmark.projection;\n return transformExtent(olExtent, extentProjection, viewProjection);\n }\n\n /** Moves the map to the given extent. */\n private applyExtent(olExtent: OlExtent) {\n const olView = this.map.olView;\n const center = getCenter(olExtent);\n const resolution = olView.getResolutionForExtent(olExtent);\n olView.setCenter(center);\n olView.setResolution(resolution);\n }\n}\n\nfunction validateBookmarks(rawBookmarks: unknown): asserts rawBookmarks is Bookmark[] {\n if (!Array.isArray(rawBookmarks)) {\n throw new Error(`Expected bookmarks from local storage to be an array.`);\n }\n for (const rawBookmark of rawBookmarks) {\n validateBookmark(rawBookmark);\n }\n}\n\nfunction validateBookmark(rawBookmark: unknown): asserts rawBookmark is Bookmark {\n if (!rawBookmark || typeof rawBookmark !== \"object\") {\n throw new Error(`Expected bookmark from local storage to be an object.`);\n }\n\n const bookmark = rawBookmark as Record<keyof Bookmark, unknown>;\n if (typeof bookmark.id !== \"string\") {\n throw new Error(\"Bookmark does not have a valid id.\");\n }\n if (typeof bookmark.title !== \"string\") {\n throw new Error(\"Bookmark does not have a valid title.\");\n }\n validateExtent(bookmark.extent);\n if (typeof bookmark.projection !== \"string\") {\n throw new Error(\"Bookmark does not have a valid projection value.\");\n }\n}\n\nfunction validateExtent(rawExtent: unknown): asserts rawExtent is Extent {\n if (!rawExtent || typeof rawExtent !== \"object\") {\n throw new Error(`Expected bookmark extent from local storage to be an object.`);\n }\n\n const extent = rawExtent as Record<keyof Extent, unknown>;\n if (\n typeof extent.minX !== \"number\" ||\n typeof extent.minY !== \"number\" ||\n typeof extent.maxX !== \"number\" ||\n typeof extent.maxY !== \"number\"\n ) {\n throw new Error(\"Expected bookmark extent from local storage to have valid coordinates.\");\n }\n}\n"],"names":["uuid4v"],"mappings":"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"}
1
+ {"version":3,"file":"SpatialBookmarksViewModel.js","sources":["SpatialBookmarksViewModel.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport { MapModel } from \"@open-pioneer/map\";\nimport { LocalStorageNamespace, LocalStorageService } from \"@open-pioneer/local-storage\";\nimport { v4 as uuid4v } from \"uuid\";\nimport { Extent as OlExtent, getCenter } from \"ol/extent\";\nimport { transformExtent } from \"ol/proj\";\nimport { createLogger } from \"@open-pioneer/core\";\nimport { CleanupHandle, reactiveArray, watch } from \"@conterra/reactivity-core\";\n\nconst LOG = createLogger(\"spatial-bookmark:SpatialBookmarkViewModel\");\n\ninterface Extent {\n minX: number;\n minY: number;\n maxX: number;\n maxY: number;\n}\n\nexport interface Bookmark {\n id: string;\n title: string;\n extent: Extent;\n projection: string;\n}\n\nexport class SpatialBookmarkViewModel {\n private map: MapModel;\n private packageNamespace: LocalStorageNamespace;\n private writableBookmarks = reactiveArray<Bookmark>([]);\n private watchBookmarksHandle: CleanupHandle;\n\n /**\n * Provides read-only access to the bookmarks array.\n * The UI simply renders the contents of the store and\n * uses the methods below to modify the state.\n */\n get bookmarks(): Bookmark[] {\n return this.writableBookmarks.getItems();\n }\n\n constructor(map: MapModel, localStorageService: LocalStorageService) {\n this.map = map;\n this.packageNamespace = localStorageService.getNamespace(\"spatial-bookmarks\");\n\n // Load from local storage on start; save changes whenever bookmarks change.\n this.loadState();\n this.watchBookmarksHandle = watch(\n () => [this.writableBookmarks.getItems()],\n ([bookmarks]) => this.saveState(bookmarks),\n { immediate: false }\n );\n }\n\n destroy() {\n this.watchBookmarksHandle.destroy();\n }\n\n /**\n * Creates a new bookmark with the `title` provided by the UI.\n * The current map extent is used for the new bookmark's extent.\n */\n createBookmark(title: string) {\n // minx, miny, maxx, maxy\n const olExtent = this.map.olView.calculateExtent();\n const projection = this.map.projection.getCode();\n const extent: Extent = {\n minX: olExtent[0]!,\n minY: olExtent[1]!,\n maxX: olExtent[2]!,\n maxY: olExtent[3]!\n };\n const bookmark: Bookmark = {\n id: uuid4v(),\n title,\n extent,\n projection\n };\n LOG.debug(\"Created a new bookmark\", bookmark);\n\n const bookmarks = this.writableBookmarks;\n bookmarks.push(bookmark);\n }\n\n /**\n * Activates the bookmark with the given id by zooming\n * to the bookmark's extent.\n */\n activateBookmark(bookmark: Bookmark) {\n LOG.debug(\"Activating bookmark\", bookmark);\n const extent = this.getBookmarkExtent(bookmark);\n\n LOG.debug(\"Attempting to apply extent\", extent);\n this.applyExtent(extent);\n }\n\n /**\n * Deletes the bookmark with the given id.\n */\n deleteBookmark(id: string) {\n LOG.debug(\"Deleting bookmark\", id);\n const index = this.writableBookmarks.findIndex((bookmark) => bookmark.id === id);\n if (index > -1) {\n this.writableBookmarks.splice(index, 1);\n }\n }\n\n /**\n * Deletes all bookmarks.\n */\n deleteAllBookmarks() {\n LOG.debug(\"Deleting all bookmarks\");\n this.writableBookmarks.splice(0);\n }\n\n /**\n * Loads the bookmarks from local storage.\n * If the bookmarks are not valid, the initial state (empty array) is restored.\n */\n private loadState() {\n LOG.debug(\"Restoring bookmarks from local storage\");\n\n const rawBookmarks = this.packageNamespace.get(\"bookmarks\") ?? [];\n try {\n validateBookmarks(rawBookmarks);\n this.writableBookmarks.push(...rawBookmarks);\n } catch (e) {\n LOG.error(\"Bookmarks data in local storage is invalid, resetting to default value.\", e);\n this.writableBookmarks.splice(0);\n this.saveState([]);\n }\n }\n\n /**\n * Saves the bookmarks to local storage.\n */\n private saveState(bookmarks: Bookmark[]) {\n LOG.debug(\"Saving bookmarks to local storage\");\n this.packageNamespace.set(\"bookmarks\", bookmarks);\n }\n\n /** Computes an OpenLayers extent for the given bookmark. */\n private getBookmarkExtent(bookmark: Bookmark) {\n const olView = this.map.olView;\n const extent = bookmark.extent;\n const olExtent = [extent.minX, extent.minY, extent.maxX, extent.maxY];\n const viewProjection = olView.getProjection();\n const extentProjection = bookmark.projection;\n return transformExtent(olExtent, extentProjection, viewProjection);\n }\n\n /** Moves the map to the given extent. */\n private applyExtent(olExtent: OlExtent) {\n const olView = this.map.olView;\n const center = getCenter(olExtent);\n const resolution = olView.getResolutionForExtent(olExtent);\n olView.setCenter(center);\n olView.setResolution(resolution);\n }\n}\n\nfunction validateBookmarks(rawBookmarks: unknown): asserts rawBookmarks is Bookmark[] {\n if (!Array.isArray(rawBookmarks)) {\n throw new Error(`Expected bookmarks from local storage to be an array.`);\n }\n for (const rawBookmark of rawBookmarks) {\n validateBookmark(rawBookmark);\n }\n}\n\nfunction validateBookmark(rawBookmark: unknown): asserts rawBookmark is Bookmark {\n if (!rawBookmark || typeof rawBookmark !== \"object\") {\n throw new Error(`Expected bookmark from local storage to be an object.`);\n }\n\n const bookmark = rawBookmark as Record<keyof Bookmark, unknown>;\n if (typeof bookmark.id !== \"string\") {\n throw new Error(\"Bookmark does not have a valid id.\");\n }\n if (typeof bookmark.title !== \"string\") {\n throw new Error(\"Bookmark does not have a valid title.\");\n }\n validateExtent(bookmark.extent);\n if (typeof bookmark.projection !== \"string\") {\n throw new Error(\"Bookmark does not have a valid projection value.\");\n }\n}\n\nfunction validateExtent(rawExtent: unknown): asserts rawExtent is Extent {\n if (!rawExtent || typeof rawExtent !== \"object\") {\n throw new Error(`Expected bookmark extent from local storage to be an object.`);\n }\n\n const extent = rawExtent as Record<keyof Extent, unknown>;\n if (\n typeof extent.minX !== \"number\" ||\n typeof extent.minY !== \"number\" ||\n typeof extent.maxX !== \"number\" ||\n typeof extent.maxY !== \"number\"\n ) {\n throw new Error(\"Expected bookmark extent from local storage to have valid coordinates.\");\n }\n}\n"],"names":["uuid4v"],"mappings":"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"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@open-pioneer/spatial-bookmarks",
4
- "version": "0.9.0-dev.20250220091855",
4
+ "version": "0.9.0",
5
5
  "description": "This package provides a UI component that allows the user to store, manage, and easily navigate between different map extents by creating bookmarks.",
6
6
  "keywords": [
7
7
  "open-pioneer-trails"
@@ -15,19 +15,19 @@
15
15
  },
16
16
  "dependencies": {
17
17
  "@chakra-ui/icons": "^2.2.4",
18
- "@open-pioneer/chakra-integration": "^2.4.0",
19
- "@open-pioneer/core": "^2.4.0",
20
- "@open-pioneer/local-storage": "^2.4.0",
21
- "@open-pioneer/react-utils": "^2.4.0",
22
- "@open-pioneer/runtime": "^2.4.0",
18
+ "@open-pioneer/chakra-integration": "^3.0.0",
19
+ "@open-pioneer/core": "^3.0.0",
20
+ "@open-pioneer/local-storage": "^3.0.0",
21
+ "@open-pioneer/react-utils": "^3.0.0",
22
+ "@open-pioneer/runtime": "^3.0.0",
23
23
  "classnames": "^2.3.2",
24
- "ol": "^10.3.0",
25
- "react": "^18.3.1",
24
+ "ol": "^10.4.0",
25
+ "react": "^19.0.0",
26
26
  "react-icons": "^5.3.0",
27
27
  "@conterra/reactivity-core": "^0.4.3",
28
- "@open-pioneer/reactivity": "^2.4.0",
29
- "uuid": "^10.0.0",
30
- "@open-pioneer/map": "^0.9.0-dev.20250220091855"
28
+ "@open-pioneer/reactivity": "^3.0.0",
29
+ "uuid": "^11.1.0",
30
+ "@open-pioneer/map": "^0.9.0"
31
31
  },
32
32
  "exports": {
33
33
  "./package.json": "./package.json",