@open-pioneer/spatial-bookmarks 0.11.0-dev.20250515143825 → 0.11.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,16 +1,46 @@
1
1
  # @open-pioneer/spatial-bookmarks
2
2
 
3
- ## 0.11.0-dev.20250515143825
3
+ ## 0.11.0
4
4
 
5
5
  ### Minor Changes
6
6
 
7
+ - 66179bc: Update to core-packages v4.0.0
7
8
  - 738390e: Update to Chakra v3
8
9
 
9
10
  ### Patch Changes
10
11
 
12
+ - 9376a74: Ensure that icons and other decorative elements are hidden from the screen reader using the `aria-hidden="true"` attribute.
13
+
14
+ The easiest way to do that is to wrap icons into chakra's `<Icon />` component, for example:
15
+
16
+ ```tsx
17
+ import { Icon } from "@chakra-ui/react";
18
+ import { FiX } from "react-icons/fi";
19
+
20
+ <Icon>
21
+ <FiX />
22
+ </Icon>;
23
+ ```
24
+
25
+ - 0137b05: Fix a11y issues.
26
+
27
+ **Improvements:**
28
+
29
+ - add descriptive `aria-label` to each list item to make it clearer for screen reader users that list item is an interactive element
30
+ - use title in `aria-label` of deleteOne button to provide more context for screen reader users
31
+
32
+ **Known issues:**
33
+
34
+ - screen readers read both tooltip content and aria label of deleteOne Button
35
+ - descriptive `aria-label` for list items is a workaround
36
+ - ideally interactive elements should not be nested (deleteOne Button is currently a child of list item)
37
+
11
38
  - Updated dependencies [738390e]
39
+ - Updated dependencies [66179bc]
40
+ - Updated dependencies [0a8ff71]
41
+ - Updated dependencies [acd5115]
12
42
  - Updated dependencies [738390e]
13
- - @open-pioneer/map@0.11.0-dev.20250515143825
43
+ - @open-pioneer/map@0.11.0
14
44
 
15
45
  ## 0.10.0
16
46
 
@@ -1,5 +1,5 @@
1
1
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
2
- import { Flex, VStack, Field, Input, List, Center, Text, Spacer, IconButton, Button } from '@chakra-ui/react';
2
+ import { Flex, VStack, Field, Input, List, Icon, Center, Text, Spacer, IconButton, Button } from '@chakra-ui/react';
3
3
  import { Alert } from '@open-pioneer/chakra-snippets/alert';
4
4
  import { Tooltip } from '@open-pioneer/chakra-snippets/tooltip';
5
5
  import { useMapModel } from '@open-pioneer/map';
@@ -138,9 +138,6 @@ function SpatialBookmarkUI(props) {
138
138
  return /* @__PURE__ */ jsx(Flex, { flexDirection: "column", ...containerProps, children: content });
139
139
  }
140
140
  function createList(bookmarks, viewModel, intl, listRef) {
141
- const deleteBtnLabel = intl.formatMessage({
142
- id: "bookmark.button.deleteOne"
143
- });
144
141
  const bookmarkItems = bookmarks.map((bookmark, idx) => /* @__PURE__ */ jsx(
145
142
  BookmarkItem,
146
143
  {
@@ -149,7 +146,7 @@ function createList(bookmarks, viewModel, intl, listRef) {
149
146
  bookmark,
150
147
  onActivate: () => viewModel.activateBookmark(bookmark),
151
148
  onDelete: () => viewModel.deleteBookmark(bookmark.id),
152
- deleteBtnLabel
149
+ intl
153
150
  },
154
151
  bookmark.id
155
152
  ));
@@ -177,7 +174,7 @@ const ARROW_INDEX_MAP = {
177
174
  ArrowUp: -1
178
175
  };
179
176
  function BookmarkItem(props) {
180
- const { index, listItemNodes, bookmark, onDelete, onActivate, deleteBtnLabel } = props;
177
+ const { index, listItemNodes, bookmark, onDelete, onActivate, intl } = props;
181
178
  const title = bookmark.title;
182
179
  const onKeyDown = (evt) => {
183
180
  const key = evt.key;
@@ -221,15 +218,18 @@ function BookmarkItem(props) {
221
218
  focusVisibleRing: "outside",
222
219
  onKeyDown,
223
220
  onClick: onActivate,
221
+ "aria-label": intl.formatMessage({ id: "bookmark.ariaLabel" }, { title }),
224
222
  children: /* @__PURE__ */ jsxs(Flex, { width: "100%", flexDirection: "row", align: "center", gap: 1, children: [
225
- /* @__PURE__ */ jsx(Center, { children: /* @__PURE__ */ jsx(PiMapTrifold, {}) }),
223
+ /* @__PURE__ */ jsx(Center, { children: /* @__PURE__ */ jsx(Icon, { children: /* @__PURE__ */ jsx(PiMapTrifold, {}) }) }),
226
224
  /* @__PURE__ */ jsx(Text, { ps: 2, maxLines: 1, children: title }),
227
225
  /* @__PURE__ */ jsx(Spacer, {}),
228
226
  /* @__PURE__ */ jsx(
229
227
  Tooltip,
230
228
  {
231
229
  showArrow: true,
232
- content: deleteBtnLabel,
230
+ content: intl.formatMessage({
231
+ id: "bookmark.button.deleteOne.tooltip"
232
+ }),
233
233
  positioning: {
234
234
  placement: "right"
235
235
  },
@@ -237,7 +237,6 @@ function BookmarkItem(props) {
237
237
  IconButton,
238
238
  {
239
239
  className: "spatial-bookmarks-item-delete",
240
- "aria-label": deleteBtnLabel,
241
240
  borderRadius: "full",
242
241
  padding: 0,
243
242
  colorPalette: "red",
@@ -246,7 +245,11 @@ function BookmarkItem(props) {
246
245
  onDelete();
247
246
  event.stopPropagation();
248
247
  },
249
- children: /* @__PURE__ */ jsx(PiTrashSimpleLight, {})
248
+ "aria-label": intl.formatMessage(
249
+ { id: "bookmark.button.deleteOne.ariaLabel" },
250
+ { title }
251
+ ),
252
+ children: /* @__PURE__ */ jsx(Icon, { children: /* @__PURE__ */ jsx(PiTrashSimpleLight, {}) })
250
253
  }
251
254
  )
252
255
  },
@@ -267,7 +270,7 @@ function ListControls(props) {
267
270
  colorPalette: "red",
268
271
  onClick: showDelete,
269
272
  variant: "outline",
270
- children: /* @__PURE__ */ jsx(PiTrashSimpleLight, {})
273
+ children: /* @__PURE__ */ jsx(Icon, { children: /* @__PURE__ */ jsx(PiTrashSimpleLight, {}) })
271
274
  }
272
275
  ),
273
276
  /* @__PURE__ */ jsx(DialogButton, { onClick: showCreate, children: intl.formatMessage({ id: "bookmark.button.create" }) })
@@ -1 +1 @@
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 Button,\n ButtonProps,\n Center,\n Field,\n Flex,\n IconButton,\n IconButtonProps,\n Input,\n List,\n Spacer,\n Text,\n VStack\n} from \"@chakra-ui/react\";\nimport { Alert } from \"@open-pioneer/chakra-snippets/alert\";\nimport { Tooltip } from \"@open-pioneer/chakra-snippets/tooltip\";\nimport { LocalStorageService } from \"@open-pioneer/local-storage\";\nimport { MapModel, MapModelProps, useMapModel } from \"@open-pioneer/map\";\nimport { CommonComponentProps, useCommonComponentProps } from \"@open-pioneer/react-utils\";\nimport { useReactiveSnapshot } from \"@open-pioneer/reactivity\";\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\";\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\n rounded=\"md\"\n status=\"warning\"\n title={intl.formatMessage({ id: \"bookmark.alert.delete\" })}\n role=\"alert\"\n />\n <RemoveControls\n intl={intl}\n onClear={clearBookmarks}\n onCancel={() => setUiMode(\"list\")}\n />\n </VStack>\n );\n\n const createContent = () => (\n <VStack>\n <Alert\n rounded=\"md\"\n status=\"info\"\n title={intl.formatMessage({ id: \"bookmark.alert.create\" })}\n role=\"alert\"\n />\n <Field.Root invalid={!isValidBookmarkName} required>\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 autoFocus // eslint-disable-line jsx-a11y/no-autofocus\n />\n </Field.Root>\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\n rounded=\"md\"\n status=\"info\"\n title={intl.formatMessage({ id: \"bookmark.alert.noSaved\" })}\n role=\"alert\"\n />\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.Root\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 gap={1}\n overflowY=\"auto\"\n listStyleType=\"none\"\n >\n {bookmarkItems}\n </List.Root>\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.RefObject<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 <List.Item\n as=\"li\"\n p={1}\n ref={(el: HTMLElement | 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 focusVisibleRing=\"outside\"\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} maxLines={1}>\n {title}\n </Text>\n <Spacer />\n <Tooltip\n key={index}\n showArrow\n content={deleteBtnLabel}\n positioning={{\n placement: \"right\"\n }}\n >\n <IconButton\n className=\"spatial-bookmarks-item-delete\"\n aria-label={deleteBtnLabel}\n borderRadius=\"full\"\n padding={0}\n colorPalette=\"red\"\n variant=\"plain\"\n onClick={(event) => {\n onDelete();\n event.stopPropagation();\n }}\n >\n {<PiTrashSimpleLight />}\n </IconButton>\n </Tooltip>\n </Flex>\n </List.Item>\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 <DialogIconButton\n aria-label={intl.formatMessage({ id: \"bookmark.button.deleteAll\" })}\n disabled={bookmarks.length === 0}\n colorPalette=\"red\"\n onClick={showDelete}\n variant=\"outline\"\n >\n <PiTrashSimpleLight />\n </DialogIconButton>\n <DialogButton onClick={showCreate}>\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 disabled={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={2} flexGrow={0} flexShrink={0}>\n {props.children}\n </Flex>\n );\n}\n\nfunction DialogButton(props?: ButtonProps): ReactNode {\n return <Button flex=\"1 1 auto\" {...props} />;\n}\n\nfunction DialogIconButton(props: IconButtonProps): ReactNode {\n return <IconButton flex=\"0 0 auto\" px={4} {...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 Button,\n ButtonProps,\n Center,\n Field,\n Flex,\n Icon,\n IconButton,\n IconButtonProps,\n Input,\n List,\n Spacer,\n Text,\n VStack\n} from \"@chakra-ui/react\";\nimport { Alert } from \"@open-pioneer/chakra-snippets/alert\";\nimport { Tooltip } from \"@open-pioneer/chakra-snippets/tooltip\";\nimport { LocalStorageService } from \"@open-pioneer/local-storage\";\nimport { MapModel, MapModelProps, useMapModel } from \"@open-pioneer/map\";\nimport { CommonComponentProps, useCommonComponentProps } from \"@open-pioneer/react-utils\";\nimport { useReactiveSnapshot } from \"@open-pioneer/reactivity\";\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\";\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\n rounded=\"md\"\n status=\"warning\"\n title={intl.formatMessage({ id: \"bookmark.alert.delete\" })}\n role=\"alert\"\n />\n <RemoveControls\n intl={intl}\n onClear={clearBookmarks}\n onCancel={() => setUiMode(\"list\")}\n />\n </VStack>\n );\n\n const createContent = () => (\n <VStack>\n <Alert\n rounded=\"md\"\n status=\"info\"\n title={intl.formatMessage({ id: \"bookmark.alert.create\" })}\n role=\"alert\"\n />\n <Field.Root invalid={!isValidBookmarkName} required>\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 autoFocus // eslint-disable-line jsx-a11y/no-autofocus\n />\n </Field.Root>\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\n rounded=\"md\"\n status=\"info\"\n title={intl.formatMessage({ id: \"bookmark.alert.noSaved\" })}\n role=\"alert\"\n />\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 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 intl={intl}\n />\n ));\n\n return (\n <List.Root\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 gap={1}\n overflowY=\"auto\"\n listStyleType=\"none\"\n >\n {bookmarkItems}\n </List.Root>\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.RefObject<HTMLElement[]>;\n bookmark: Bookmark;\n onActivate: () => void;\n onDelete: () => void;\n intl: PackageIntl;\n}): ReactNode {\n const { index, listItemNodes, bookmark, onDelete, onActivate, intl } = 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\n return (\n <List.Item\n as=\"li\"\n p={1}\n ref={(el: HTMLElement | 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 focusVisibleRing=\"outside\"\n onKeyDown={onKeyDown}\n onClick={onActivate}\n aria-label={intl.formatMessage({ id: \"bookmark.ariaLabel\" }, { title: title })}\n >\n <Flex width=\"100%\" flexDirection=\"row\" align=\"center\" gap={1}>\n <Center>\n <Icon>\n <PiMapTrifold />\n </Icon>\n </Center>\n <Text ps={2} maxLines={1}>\n {title}\n </Text>\n <Spacer />\n <Tooltip\n key={index}\n showArrow\n content={intl.formatMessage({\n id: \"bookmark.button.deleteOne.tooltip\"\n })}\n positioning={{\n placement: \"right\"\n }}\n >\n <IconButton\n className=\"spatial-bookmarks-item-delete\"\n borderRadius=\"full\"\n padding={0}\n colorPalette=\"red\"\n variant=\"plain\"\n onClick={(event) => {\n onDelete();\n event.stopPropagation();\n }}\n aria-label={intl.formatMessage(\n { id: \"bookmark.button.deleteOne.ariaLabel\" },\n { title: title }\n )}\n >\n <Icon>\n <PiTrashSimpleLight />\n </Icon>\n </IconButton>\n </Tooltip>\n </Flex>\n </List.Item>\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 <DialogIconButton\n aria-label={intl.formatMessage({ id: \"bookmark.button.deleteAll\" })}\n disabled={bookmarks.length === 0}\n colorPalette=\"red\"\n onClick={showDelete}\n variant=\"outline\"\n >\n <Icon>\n <PiTrashSimpleLight />\n </Icon>\n </DialogIconButton>\n <DialogButton onClick={showCreate}>\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 disabled={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={2} flexGrow={0} flexShrink={0}>\n {props.children}\n </Flex>\n );\n}\n\nfunction DialogButton(props?: ButtonProps): ReactNode {\n return <Button flex=\"1 1 auto\" {...props} />;\n}\n\nfunction DialogIconButton(props: IconButtonProps): ReactNode {\n return <IconButton flex=\"0 0 auto\" px={4} {...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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"}
package/i18n/de.yaml CHANGED
@@ -1,9 +1,12 @@
1
1
  messages:
2
2
  bookmark:
3
+ ariaLabel: "Eingabetaste drücken, um die Kartenansicht auf das räumliche Lesezeichen {title} zu zentrieren."
3
4
  button:
4
5
  create: "Neues Lesezeichen hinzufügen"
5
6
  deleteAll: "Alle Lesezeichen löschen"
6
- deleteOne: "Lesezeichen löschen"
7
+ deleteOne:
8
+ tooltip: "Lesezeichen löschen"
9
+ ariaLabel: "Lesezeichen {title} löschen"
7
10
  save: "Speichern"
8
11
  cancel: "Abbrechen"
9
12
  cancelDelete: "Nein"
package/i18n/en.yaml CHANGED
@@ -1,9 +1,12 @@
1
1
  messages:
2
2
  bookmark:
3
+ ariaLabel: "Press enter to focus map on spatial bookmark {title}."
3
4
  button:
4
5
  create: "Add new bookmark"
5
6
  deleteAll: "Delete all bookmarks"
6
- deleteOne: "Delete bookmark"
7
+ deleteOne:
8
+ tooltip: "Delete bookmark"
9
+ ariaLabel: "Delete bookmark {title}"
7
10
  save: "Save"
8
11
  cancel: "Cancel"
9
12
  cancelDelete: "No"
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@open-pioneer/spatial-bookmarks",
4
- "version": "0.11.0-dev.20250515143825",
4
+ "version": "0.11.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"
@@ -14,20 +14,20 @@
14
14
  "directory": "src/packages/spatial-bookmarks"
15
15
  },
16
16
  "dependencies": {
17
- "@chakra-ui/react": "^3.17.0",
18
- "@open-pioneer/chakra-snippets": "4.0.0-dev.20250512105016",
19
- "@open-pioneer/core": "4.0.0-dev.20250512105016",
20
- "@open-pioneer/local-storage": "4.0.0-dev.20250512105016",
21
- "@open-pioneer/react-utils": "4.0.0-dev.20250512105016",
22
- "@open-pioneer/runtime": "4.0.0-dev.20250512105016",
23
- "classnames": "^2.3.2",
17
+ "@chakra-ui/react": "^3.19.2",
18
+ "@open-pioneer/chakra-snippets": "^4.0.0",
19
+ "@open-pioneer/core": "^4.0.0",
20
+ "@open-pioneer/local-storage": "^4.0.0",
21
+ "@open-pioneer/react-utils": "^4.0.0",
22
+ "@open-pioneer/runtime": "^4.0.0",
23
+ "classnames": "^2.5.1",
24
24
  "ol": "^10.5.0",
25
25
  "react": "^19.1.0",
26
- "react-icons": "^5.3.0",
27
- "@conterra/reactivity-core": "^0.6.0",
28
- "@open-pioneer/reactivity": "4.0.0-dev.20250512105016",
26
+ "react-icons": "^5.5.0",
27
+ "@conterra/reactivity-core": "^0.7.0",
28
+ "@open-pioneer/reactivity": "^4.0.0",
29
29
  "uuid": "^11.1.0",
30
- "@open-pioneer/map": "0.11.0-dev.20250515143825"
30
+ "@open-pioneer/map": "^0.11.0"
31
31
  },
32
32
  "exports": {
33
33
  "./package.json": "./package.json",