@open-pioneer/spatial-bookmarks 1.4.0-dev.20260727093741 → 1.5.0-dev.20260910103330
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 +44 -29
- package/SpatialBookmarks.js +3 -1
- package/SpatialBookmarks.js.map +1 -1
- package/SpatialBookmarksViewModel.js.map +1 -1
- package/package.json +16 -12
package/CHANGELOG.md
CHANGED
|
@@ -1,14 +1,27 @@
|
|
|
1
1
|
# @open-pioneer/spatial-bookmarks
|
|
2
2
|
|
|
3
|
-
## 1.
|
|
3
|
+
## 1.5.0-dev.20260910103330
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- f790fda: Update to Chakra 3.37.0
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- 3203815: Update code to match new react linting rules from oxlint.
|
|
12
|
+
- 09ec7c7: Updated dependencies
|
|
13
|
+
|
|
14
|
+
## 1.4.0
|
|
4
15
|
|
|
5
16
|
### Minor Changes
|
|
6
17
|
|
|
7
18
|
- c30396d: Update Chakra to 3.36.1
|
|
19
|
+
- d862003: Update to trails core-packages 4.7.0
|
|
8
20
|
|
|
9
21
|
### Patch Changes
|
|
10
22
|
|
|
11
23
|
- 078bef5: Use private JavaScript properties (#) instead of TypeScript keyword.
|
|
24
|
+
- c16a401: Migrated from eslint to oxlint and from prettier to oxfmt.
|
|
12
25
|
|
|
13
26
|
## 1.3.0
|
|
14
27
|
|
|
@@ -67,27 +80,29 @@
|
|
|
67
80
|
|
|
68
81
|
- 9376a74: Ensure that icons and other decorative elements are hidden from the screen reader using the `aria-hidden="true"` attribute.
|
|
69
82
|
|
|
70
|
-
|
|
83
|
+
The easiest way to do that is to wrap icons into chakra's `<Icon />` component, for example:
|
|
71
84
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
85
|
+
```tsx
|
|
86
|
+
import { Icon } from "@chakra-ui/react";
|
|
87
|
+
import { FiX } from "react-icons/fi";
|
|
75
88
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
89
|
+
<Icon>
|
|
90
|
+
<FiX />
|
|
91
|
+
</Icon>;
|
|
92
|
+
```
|
|
80
93
|
|
|
81
94
|
- 0137b05: Fix a11y issues.
|
|
82
95
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
96
|
+
**Improvements:**
|
|
97
|
+
|
|
98
|
+
- add descriptive `aria-label` to each list item to make it clearer for screen reader users that list item is an interactive element
|
|
99
|
+
- use title in `aria-label` of deleteOne button to provide more context for screen reader users
|
|
100
|
+
|
|
101
|
+
**Known issues:**
|
|
86
102
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
- ideally interactive elements should not be nested (deleteOne Button is currently a child of list item)
|
|
103
|
+
- screen readers read both tooltip content and aria label of deleteOne Button
|
|
104
|
+
- descriptive `aria-label` for list items is a workaround
|
|
105
|
+
- ideally interactive elements should not be nested (deleteOne Button is currently a child of list item)
|
|
91
106
|
|
|
92
107
|
## 0.10.0
|
|
93
108
|
|
|
@@ -96,17 +111,17 @@
|
|
|
96
111
|
- 193068a: Deprecate the `mapId` property on React components.
|
|
97
112
|
Use the `MapModel` directly instead to pass a reference to the map.
|
|
98
113
|
|
|
99
|
-
|
|
114
|
+
Example:
|
|
100
115
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
116
|
+
```tsx
|
|
117
|
+
// Default map for entire component tree
|
|
118
|
+
<DefaultMapProvider map={mapModel}>
|
|
119
|
+
<Toc />
|
|
120
|
+
</DefaultMapProvider>
|
|
106
121
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
122
|
+
// Map for specific component
|
|
123
|
+
<Toc map={mapModel} />
|
|
124
|
+
```
|
|
110
125
|
|
|
111
126
|
### Patch Changes
|
|
112
127
|
|
|
@@ -125,9 +140,9 @@
|
|
|
125
140
|
### Minor Changes
|
|
126
141
|
|
|
127
142
|
- 2fa8020: Update trails core package dependencies.
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
143
|
+
- Also updates Chakra UI to the latest 2.x version and Chakra React Select to version 5.
|
|
144
|
+
- Removes any obsolete references to `@chakra-ui/system`.
|
|
145
|
+
This dependency seems to be no longer required and may lead to duplicate packages in your dependency tree.
|
|
131
146
|
|
|
132
147
|
### Patch Changes
|
|
133
148
|
|
|
@@ -146,7 +161,7 @@
|
|
|
146
161
|
- 583f1d6: The `mapId` or `map` properties are now optional on individual components.
|
|
147
162
|
You can use the `DefaultMapProvider` to configure an implicit default value.
|
|
148
163
|
|
|
149
|
-
|
|
164
|
+
Note that configuring _neither_ a default _nor_ an explicit `map` or `mapId` will trigger a runtime error.
|
|
150
165
|
|
|
151
166
|
- 583f1d6: All UI components in this project now accept the `mapId` (a `string`) _or_ the `map` (a `MapModel`) directly.
|
|
152
167
|
- a8b3449: Switch to a new versioning strategy.
|
package/SpatialBookmarks.js
CHANGED
|
@@ -130,7 +130,9 @@ function SpatialBookmarkUI(props) {
|
|
|
130
130
|
)
|
|
131
131
|
] });
|
|
132
132
|
const content = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
133
|
-
uiMode === "list" &&
|
|
133
|
+
uiMode === "list" && // Looks like a false positive..
|
|
134
|
+
// oxlint-disable-next-line react/refs
|
|
135
|
+
listContent(),
|
|
134
136
|
uiMode === "create" && createContent(),
|
|
135
137
|
uiMode === "delete" && deleteContent()
|
|
136
138
|
] });
|
package/SpatialBookmarks.js.map
CHANGED
|
@@ -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 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, useMapModelValue } 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 \"@open-pioneer/react-utils\";\nimport { useIntl, useService } from \"open-pioneer:react-hooks\";\nimport { FC, KeyboardEvent, ReactNode, useEffect, useRef, useState } from \"react\";\nimport { LuMap, LuTrash } from \"react-icons/lu\";\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 = useMapModelValue(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.RefObject<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 <LuMap />\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 <LuTrash />\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 <LuTrash />\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, localStorageService: LocalStorageService) {\n const [viewModel, setViewModel] = useState<SpatialBookmarkViewModel>();\n useEffect(() => {\n const viewModel = new SpatialBookmarkViewModel(map, localStorageService);\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\n\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, useMapModelValue } from \"@open-pioneer/map\";\nimport {\n CommonComponentProps,\n useCommonComponentProps,\n classNames\n} from \"@open-pioneer/react-utils\";\nimport { useReactiveSnapshot } from \"@open-pioneer/reactivity\";\nimport { PackageIntl } from \"@open-pioneer/runtime\";\nimport { useIntl, useService } from \"open-pioneer:react-hooks\";\nimport { FC, KeyboardEvent, ReactNode, useEffect, useRef, useState } from \"react\";\nimport { LuMap, LuTrash } from \"react-icons/lu\";\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 = useMapModelValue(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 // oxlint-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\" &&\n // Looks like a false positive..\n // oxlint-disable-next-line react/refs\n 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.RefObject<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 // TODO: needs a good fix\n // oxlint-disable-next-line jsx-a11y/role-has-required-aria-props\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 <LuMap />\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 <LuTrash />\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 <LuTrash />\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, localStorageService: LocalStorageService) {\n const [viewModel, setViewModel] = useState<SpatialBookmarkViewModel>();\n useEffect(() => {\n const viewModel = new SpatialBookmarkViewModel(map, localStorageService);\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-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport { CleanupHandle, reactiveArray, watch } from \"@conterra/reactivity-core\";\nimport { createLogger } from \"@open-pioneer/core\";\nimport { LocalStorageNamespace, LocalStorageService } from \"@open-pioneer/local-storage\";\nimport { MapModel } from \"@open-pioneer/map\";\nimport { Extent as OlExtent, getCenter } from \"ol/extent\";\nimport { transformExtent } from \"ol/proj\";\nimport { sourceId } from \"open-pioneer:source-info\";\nimport { v4 as uuid4v } from \"uuid\";\n\nconst LOG = createLogger(sourceId);\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 #map: MapModel;\n #packageNamespace: LocalStorageNamespace;\n #writableBookmarks = reactiveArray<Bookmark>([]);\n #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 [minX = 0, minY = 0, maxX = 0, maxY = 0] = olExtent;\n const extent: Extent = { minX, minY, maxX, maxY };\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 #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 #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 #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 #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\n\nimport { CleanupHandle, reactiveArray, watch } from \"@conterra/reactivity-core\";\nimport { createLogger } from \"@open-pioneer/core\";\nimport { LocalStorageNamespace, LocalStorageService } from \"@open-pioneer/local-storage\";\nimport { MapModel } from \"@open-pioneer/map\";\nimport { Extent as OlExtent, getCenter } from \"ol/extent\";\nimport { transformExtent } from \"ol/proj\";\nimport { sourceId } from \"open-pioneer:source-info\";\nimport { v4 as uuid4v } from \"uuid\";\n\nconst LOG = createLogger(sourceId);\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 #map: MapModel;\n #packageNamespace: LocalStorageNamespace;\n #writableBookmarks = reactiveArray<Bookmark>([]);\n #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 [minX = 0, minY = 0, maxX = 0, maxY = 0] = olExtent;\n const extent: Extent = { minX, minY, maxX, maxY };\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 #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 #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 #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 #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": "1.
|
|
4
|
+
"version": "1.5.0-dev.20260910103330",
|
|
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,19 +14,23 @@
|
|
|
14
14
|
"directory": "src/packages/spatial-bookmarks"
|
|
15
15
|
},
|
|
16
16
|
"dependencies": {
|
|
17
|
-
"@chakra-ui/react": "^3.
|
|
18
|
-
"@
|
|
19
|
-
"@open-pioneer/
|
|
20
|
-
"@open-pioneer/
|
|
21
|
-
"@open-pioneer/
|
|
22
|
-
"@open-pioneer/
|
|
23
|
-
"
|
|
17
|
+
"@chakra-ui/react": "^3.37.0",
|
|
18
|
+
"@conterra/reactivity-core": "^0.8.8",
|
|
19
|
+
"@open-pioneer/chakra-snippets": "4.8.0-dev.20260910101405",
|
|
20
|
+
"@open-pioneer/core": "4.8.0-dev.20260910101405",
|
|
21
|
+
"@open-pioneer/local-storage": "4.8.0-dev.20260910101405",
|
|
22
|
+
"@open-pioneer/map": "1.5.0-dev.20260910103330",
|
|
23
|
+
"@open-pioneer/react-utils": "4.8.0-dev.20260910101405",
|
|
24
|
+
"@open-pioneer/reactivity": "4.8.0-dev.20260910101405",
|
|
25
|
+
"@open-pioneer/runtime": "4.8.0-dev.20260910101405",
|
|
26
|
+
"ol": "^10.10.0",
|
|
24
27
|
"react": "^19.2.8",
|
|
25
28
|
"react-icons": "^5.7.0",
|
|
26
|
-
"
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
"
|
|
29
|
+
"uuid": "^14.0.2"
|
|
30
|
+
},
|
|
31
|
+
"publishConfig": {
|
|
32
|
+
"directory": "dist",
|
|
33
|
+
"linkDirectory": false
|
|
30
34
|
},
|
|
31
35
|
"exports": {
|
|
32
36
|
"./package.json": "./package.json",
|