sanity-plugin-media 2.0.5 → 2.0.6

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sanity-plugin-media",
3
- "version": "2.0.5",
3
+ "version": "2.0.6",
4
4
  "description": "This version of `sanity-plugin-media` is for Sanity Studio V3.",
5
5
  "keywords": [
6
6
  "sanity",
@@ -54,10 +54,10 @@
54
54
  "watch": "pkg-utils watch"
55
55
  },
56
56
  "dependencies": {
57
- "@hookform/resolvers": "2.0.0-beta.3",
57
+ "@hookform/resolvers": "2.9.11",
58
58
  "@reduxjs/toolkit": "^1.9.0",
59
59
  "@sanity/incompatible-plugin": "^1.0.4",
60
- "@sanity/ui": "^1.0.0",
60
+ "@sanity/ui": "^1.7.0",
61
61
  "@tanem/react-nprogress": "^5.0.0",
62
62
  "copy-to-clipboard": "^3.3.1",
63
63
  "date-fns": "^2.27.0",
@@ -71,7 +71,7 @@
71
71
  "react-hook-form": "^6.15.1",
72
72
  "react-redux": "^7.2.2",
73
73
  "react-select": "^5.3.2",
74
- "react-virtuoso": "^2.11.0",
74
+ "react-virtuoso": "^4.3.11",
75
75
  "redux": "^4.2.0",
76
76
  "redux-observable": "^2.0.0",
77
77
  "rxjs": "^7.0.0",
@@ -83,7 +83,7 @@
83
83
  "@sanity/client": "^4.0.1",
84
84
  "@sanity/color": "^2.1.20",
85
85
  "@sanity/icons": "^2.0.0",
86
- "@sanity/pkg-utils": "^1.17.2",
86
+ "@sanity/pkg-utils": "^2.0.0",
87
87
  "@sanity/plugin-kit": "^2.1.16",
88
88
  "@sanity/semantic-release-preset": "^2.0.2",
89
89
  "@types/is-hotkey": "^0.1.7",
@@ -116,8 +116,6 @@
116
116
  "typescript": "^4.8.4"
117
117
  },
118
118
  "peerDependencies": {
119
- "@sanity/color": "^2.1.20",
120
- "@sanity/icons": "^2.0.0",
121
119
  "react": "^18",
122
120
  "react-dom": "^18",
123
121
  "sanity": "^3.0.0",
@@ -36,6 +36,7 @@ const ItemContainer = styled.div`
36
36
  const ListContainer = styled.div`
37
37
  display: grid;
38
38
  grid-template-columns: repeat(auto-fill, ${CARD_WIDTH}px);
39
+ grid-template-rows: repeat(auto-fill, ${CARD_HEIGHT}px);
39
40
  justify-content: center;
40
41
  margin: 0 auto;
41
42
  `
@@ -71,7 +72,7 @@ const AssetGridVirtualized = (props: Props) => {
71
72
  return <VirtualCell item={item} selected={selected} />
72
73
  }}
73
74
  overscan={48}
74
- style={{overflowX: 'hidden'}}
75
+ style={{overflowX: 'hidden', overflowY: 'scroll'}}
75
76
  totalCount={totalCount}
76
77
  />
77
78
  )
@@ -1,8 +1,8 @@
1
1
  import type {MutationEvent} from '@sanity/client'
2
- import {Card, Flex, studioTheme, ThemeProvider, ToastProvider} from '@sanity/ui'
2
+ import {Card, Flex, PortalProvider, studioTheme, ThemeProvider, ToastProvider} from '@sanity/ui'
3
3
  import {Asset, Tag} from '@types'
4
4
  import groq from 'groq'
5
- import React, {useEffect} from 'react'
5
+ import React, {useEffect, useState} from 'react'
6
6
  import {useDispatch} from 'react-redux'
7
7
  import type {AssetSourceComponentProps, SanityDocument} from 'sanity'
8
8
  import {TAG_DOCUMENT_NAME} from '../../constants'
@@ -33,6 +33,8 @@ type Props = {
33
33
  const BrowserContent = ({onClose}: {onClose?: AssetSourceComponentProps['onClose']}) => {
34
34
  const client = useVersionedClient()
35
35
 
36
+ const [portalElement, setPortalElement] = useState<HTMLDivElement | null>(null)
37
+
36
38
  // Redux
37
39
  const dispatch = useDispatch()
38
40
 
@@ -98,31 +100,33 @@ const BrowserContent = ({onClose}: {onClose?: AssetSourceComponentProps['onClose
98
100
  }, [])
99
101
 
100
102
  return (
101
- <UploadDropzone>
102
- <Dialogs />
103
- <Notifications />
104
-
105
- <Card display="flex" height="fill">
106
- <Flex direction="column" flex={1}>
107
- {/* Header */}
108
- <Header onClose={onClose} />
109
-
110
- {/* Browser Controls */}
111
- <Controls />
112
-
113
- <Flex flex={1}>
114
- <Flex align="flex-end" direction="column" flex={1} style={{position: 'relative'}}>
115
- <PickedBar />
116
- <Items />
103
+ <PortalProvider element={portalElement}>
104
+ <UploadDropzone>
105
+ <Dialogs />
106
+ <Notifications />
107
+
108
+ <Card display="flex" height="fill" ref={setPortalElement}>
109
+ <Flex direction="column" flex={1}>
110
+ {/* Header */}
111
+ <Header onClose={onClose} />
112
+
113
+ {/* Browser Controls */}
114
+ <Controls />
115
+
116
+ <Flex flex={1}>
117
+ <Flex align="flex-end" direction="column" flex={1} style={{position: 'relative'}}>
118
+ <PickedBar />
119
+ <Items />
120
+ </Flex>
121
+ <TagsPanel />
117
122
  </Flex>
118
- <TagsPanel />
119
- </Flex>
120
123
 
121
- {/* Debug */}
122
- <DebugControls />
123
- </Flex>
124
- </Card>
125
- </UploadDropzone>
124
+ {/* Debug */}
125
+ <DebugControls />
126
+ </Flex>
127
+ </Card>
128
+ </UploadDropzone>
129
+ </PortalProvider>
126
130
  )
127
131
  }
128
132
 
@@ -2,22 +2,18 @@ import {ClipboardIcon} from '@sanity/icons'
2
2
  import {Button, Popover, Text} from '@sanity/ui'
3
3
  import copy from 'copy-to-clipboard'
4
4
  import React, {useEffect, useRef, useState} from 'react'
5
+ import {usePortalPopoverProps} from '../../hooks/usePortalPopoverProps'
5
6
 
6
7
  type Props = {
7
8
  disabled?: boolean
8
9
  url: string
9
10
  }
10
11
 
11
- const ButtonAssetCopy = (props: Props) => {
12
- const {disabled, url} = props
13
-
14
- // Refs
12
+ const ButtonAssetCopy = ({disabled, url}: Props) => {
13
+ const popoverProps = usePortalPopoverProps()
15
14
  const refPopoverTimeout = useRef<ReturnType<typeof window.setTimeout>>()
16
-
17
- // State
18
15
  const [popoverVisible, setPopoverVisible] = useState(false)
19
16
 
20
- // Callbacks
21
17
  const handleClick = () => {
22
18
  if (refPopoverTimeout.current) {
23
19
  clearTimeout(refPopoverTimeout.current)
@@ -51,6 +47,7 @@ const ButtonAssetCopy = (props: Props) => {
51
47
  padding={2}
52
48
  placement="top"
53
49
  radius={1}
50
+ {...popoverProps}
54
51
  >
55
52
  <Button
56
53
  disabled={disabled}
@@ -1,6 +1,6 @@
1
1
  import {hues} from '@sanity/color'
2
2
  import {CloseIcon} from '@sanity/icons'
3
- import {Box, Button, Flex, Text, Tooltip} from '@sanity/ui'
3
+ import {Box, Button, Flex, Text} from '@sanity/ui'
4
4
  import filesize from 'filesize'
5
5
  import React from 'react'
6
6
  import {useDispatch} from 'react-redux'
@@ -102,10 +102,10 @@ const CardUpload = (props: Props) => {
102
102
  </div>
103
103
  )}
104
104
 
105
- {/*
105
+ {/*
106
106
  Cancel upload button.
107
107
  Assets will only have a `complete` status _after_ it has been created on your dataset.
108
- As such, we also hide the cancel button when `percentLoaded === 100`, as cancelling when the asset
108
+ As such, we also hide the cancel button when `percentLoaded === 100`, as cancelling when the asset
109
109
  has been fully uploaded (even with a status of `progress`) won't stop the asset from being created.
110
110
  */}
111
111
  {!isComplete && percentLoaded !== 100 && (
@@ -121,27 +121,15 @@ const CardUpload = (props: Props) => {
121
121
  width: '100%'
122
122
  }}
123
123
  >
124
- <Tooltip
125
- content={
126
- <Box padding={2}>
127
- <Text muted size={1}>
128
- Cancel
129
- </Text>
130
- </Box>
131
- }
132
- disabled={'ontouchstart' in window}
133
- placement="top"
134
- >
135
- <Button
136
- fontSize={4}
137
- icon={CloseIcon}
138
- mode="bleed"
139
- onClick={handleCancelUpload}
140
- padding={2}
141
- style={{background: 'none', boxShadow: 'none'}}
142
- tone="critical"
143
- />
144
- </Tooltip>
124
+ <Button
125
+ fontSize={4}
126
+ icon={CloseIcon}
127
+ mode="bleed"
128
+ onClick={handleCancelUpload}
129
+ padding={2}
130
+ style={{background: 'none', boxShadow: 'none'}}
131
+ tone="critical"
132
+ />
145
133
  </Flex>
146
134
  )}
147
135
  </Box>
@@ -60,6 +60,7 @@ const DebugControls = () => {
60
60
  }
61
61
  fallbackPlacements={['right', 'left']}
62
62
  placement="bottom"
63
+ portal
63
64
  >
64
65
  <Switch
65
66
  checked={badConnection}
@@ -62,7 +62,7 @@ const useRootPortalElement = () => {
62
62
  return () => {
63
63
  document.body.removeChild(container)
64
64
  }
65
- }, [])
65
+ }, [container])
66
66
 
67
67
  return container
68
68
  }
@@ -40,6 +40,7 @@ const FormSubmitButton = (props: Props) => {
40
40
  }
41
41
  disabled={'ontouchstart' in window}
42
42
  placement="top"
43
+ portal
43
44
  >
44
45
  <Box>
45
46
  <Button
@@ -4,6 +4,7 @@ import React from 'react'
4
4
  import {useDispatch} from 'react-redux'
5
5
  import {getOrderTitle} from '../../config/orders'
6
6
  import {ORDER_OPTIONS} from '../../constants'
7
+ import {usePortalPopoverProps} from '../../hooks/usePortalPopoverProps'
7
8
  import useTypedSelector from '../../hooks/useTypedSelector'
8
9
  import {assetsActions} from '../../modules/assets'
9
10
 
@@ -12,6 +13,8 @@ const OrderSelect = () => {
12
13
  const dispatch = useDispatch()
13
14
  const order = useTypedSelector(state => state.assets.order)
14
15
 
16
+ const popoverProps = usePortalPopoverProps()
17
+
15
18
  return (
16
19
  <MenuButton
17
20
  button={
@@ -51,6 +54,7 @@ const OrderSelect = () => {
51
54
  })}
52
55
  </Menu>
53
56
  }
57
+ popover={popoverProps}
54
58
  />
55
59
  )
56
60
  }
@@ -8,6 +8,7 @@ import {
8
8
  import React from 'react'
9
9
  import {useDispatch} from 'react-redux'
10
10
  import {operators} from '../../config/searchFacets'
11
+ import {usePortalPopoverProps} from '../../hooks/usePortalPopoverProps'
11
12
  import {searchActions} from '../../modules/search'
12
13
  import SearchFacet from '../SearchFacet'
13
14
  import TextInputNumber from '../TextInputNumber'
@@ -16,12 +17,12 @@ type Props = {
16
17
  facet: SearchFacetInputNumberProps
17
18
  }
18
19
 
19
- const SearchFacetNumber = (props: Props) => {
20
- const {facet} = props
21
-
20
+ const SearchFacetNumber = ({facet}: Props) => {
22
21
  // Redux
23
22
  const dispatch = useDispatch()
24
23
 
24
+ const popoverProps = usePortalPopoverProps()
25
+
25
26
  const modifiers = facet?.modifiers
26
27
  const selectedModifier = facet?.modifier
27
28
  ? modifiers?.find(modifier => modifier.name === facet?.modifier)
@@ -75,6 +76,7 @@ const SearchFacetNumber = (props: Props) => {
75
76
  })}
76
77
  </Menu>
77
78
  }
79
+ popover={popoverProps}
78
80
  />
79
81
  )}
80
82
 
@@ -116,6 +118,7 @@ const SearchFacetNumber = (props: Props) => {
116
118
  ))}
117
119
  </Menu>
118
120
  }
121
+ popover={popoverProps}
119
122
  />
120
123
  )}
121
124
  </SearchFacet>
@@ -11,17 +11,18 @@ import {useDispatch} from 'react-redux'
11
11
  import {operators} from '../../config/searchFacets'
12
12
  import {searchActions} from '../../modules/search'
13
13
  import SearchFacet from '../SearchFacet'
14
+ import {usePortalPopoverProps} from '../../hooks/usePortalPopoverProps'
14
15
 
15
16
  type Props = {
16
17
  facet: SearchFacetInputSelectProps
17
18
  }
18
19
 
19
- const SearchFacetSelect = (props: Props) => {
20
- const {facet} = props
21
-
20
+ const SearchFacetSelect = ({facet}: Props) => {
22
21
  // Redux
23
22
  const dispatch = useDispatch()
24
23
 
24
+ const popoverProps = usePortalPopoverProps()
25
+
25
26
  const options = facet?.options
26
27
 
27
28
  const selectedItem = options?.find(v => v.name === facet?.value)
@@ -73,6 +74,7 @@ const SearchFacetSelect = (props: Props) => {
73
74
  })}
74
75
  </Menu>
75
76
  }
77
+ popover={popoverProps}
76
78
  />
77
79
  )}
78
80
 
@@ -101,6 +103,7 @@ const SearchFacetSelect = (props: Props) => {
101
103
  ))}
102
104
  </Menu>
103
105
  }
106
+ popover={popoverProps}
104
107
  />
105
108
  </SearchFacet>
106
109
  )
@@ -5,6 +5,7 @@ import React, {ChangeEvent} from 'react'
5
5
  import {useDispatch} from 'react-redux'
6
6
 
7
7
  import {operators} from '../../config/searchFacets'
8
+ import {usePortalPopoverProps} from '../../hooks/usePortalPopoverProps'
8
9
  import {searchActions} from '../../modules/search'
9
10
  import SearchFacet from '../SearchFacet'
10
11
 
@@ -12,12 +13,12 @@ type Props = {
12
13
  facet: SearchFacetInputStringProps
13
14
  }
14
15
 
15
- const SearchFacetString = (props: Props) => {
16
- const {facet} = props
17
-
16
+ const SearchFacetString = ({facet}: Props) => {
18
17
  // Redux
19
18
  const dispatch = useDispatch()
20
19
 
20
+ const popoverProps = usePortalPopoverProps()
21
+
21
22
  const handleOperatorItemClick = (operatorType: SearchFacetOperatorType) => {
22
23
  dispatch(searchActions.facetsUpdate({name: facet.name, operatorType}))
23
24
  }
@@ -62,6 +63,7 @@ const SearchFacetString = (props: Props) => {
62
63
  })}
63
64
  </Menu>
64
65
  }
66
+ popover={popoverProps}
65
67
  />
66
68
  )}
67
69
 
@@ -5,6 +5,7 @@ import React from 'react'
5
5
  import {useDispatch} from 'react-redux'
6
6
  import Select from 'react-select'
7
7
  import {operators} from '../../config/searchFacets'
8
+ import {usePortalPopoverProps} from '../../hooks/usePortalPopoverProps'
8
9
  import useTypedSelector from '../../hooks/useTypedSelector'
9
10
  import {searchActions} from '../../modules/search'
10
11
  import {selectTags} from '../../modules/tags'
@@ -16,15 +17,15 @@ type Props = {
16
17
  facet: SearchFacetInputSearchableProps
17
18
  }
18
19
 
19
- const SearchFacetTags = (props: Props) => {
20
- const {facet} = props
21
-
20
+ const SearchFacetTags = ({facet}: Props) => {
22
21
  // Redux
23
22
  const dispatch = useDispatch()
24
23
  const tags = useTypedSelector(state => selectTags(state))
25
24
  const tagsFetching = useTypedSelector(state => state.tags.fetching)
26
25
  const allTagOptions = getTagSelectOptions(tags)
27
26
 
27
+ const popoverProps = usePortalPopoverProps()
28
+
28
29
  const handleChange = (option: ReactSelectOption) => {
29
30
  dispatch(
30
31
  searchActions.facetsUpdate({
@@ -79,6 +80,7 @@ const SearchFacetTags = (props: Props) => {
79
80
  })}
80
81
  </Menu>
81
82
  }
83
+ popover={popoverProps}
82
84
  />
83
85
  )}
84
86
 
@@ -4,6 +4,7 @@ import {SearchFacetDivider, SearchFacetGroup, SearchFacetInputProps} from '@type
4
4
  import React from 'react'
5
5
  import {useDispatch} from 'react-redux'
6
6
  import {FACETS} from '../../constants'
7
+ import {usePortalPopoverProps} from '../../hooks/usePortalPopoverProps'
7
8
  import useTypedSelector from '../../hooks/useTypedSelector'
8
9
  import {searchActions} from '../../modules/search'
9
10
 
@@ -14,6 +15,8 @@ const SearchFacetsControl = () => {
14
15
  const searchFacets = useTypedSelector(state => state.search.facets)
15
16
  const selectedDocument = useTypedSelector(state => state.selected.document)
16
17
 
18
+ const popoverProps = usePortalPopoverProps()
19
+
17
20
  const isTool = !selectedDocument
18
21
 
19
22
  const filteredFacets = FACETS
@@ -108,8 +111,10 @@ const SearchFacetsControl = () => {
108
111
  }
109
112
  id="facets"
110
113
  menu={<Menu>{renderMenuFacets(filteredFacets)}</Menu>}
111
- placement="right-start"
112
- portal
114
+ popover={{
115
+ ...popoverProps,
116
+ placement: 'right-start'
117
+ }}
113
118
  />
114
119
 
115
120
  {/* Clear facets button */}
@@ -1,6 +1,6 @@
1
1
  import {hues} from '@sanity/color'
2
2
  import {CloseIcon} from '@sanity/icons'
3
- import {Box, Button, Flex, Grid, Stack, Text, Tooltip, useMediaIndex} from '@sanity/ui'
3
+ import {Box, Button, Flex, Grid, Stack, Text, useMediaIndex} from '@sanity/ui'
4
4
  import filesize from 'filesize'
5
5
  import React from 'react'
6
6
  import {useDispatch} from 'react-redux'
@@ -100,10 +100,10 @@ const TableRowUpload = (props: Props) => {
100
100
  </div>
101
101
  )}
102
102
 
103
- {/*
103
+ {/*
104
104
  Cancel upload button.
105
105
  Assets will only have a `complete` status _after_ it has been created on your dataset.
106
- As such, we also hide the cancel button when `percentLoaded === 100`, as cancelling when the asset
106
+ As such, we also hide the cancel button when `percentLoaded === 100`, as cancelling when the asset
107
107
  has been fully uploaded (even with a status of `progress`) won't stop the asset from being created.
108
108
  */}
109
109
  {!isComplete && percentLoaded !== 100 && (
@@ -118,27 +118,15 @@ const TableRowUpload = (props: Props) => {
118
118
  width: '100%'
119
119
  }}
120
120
  >
121
- <Tooltip
122
- content={
123
- <Box padding={2}>
124
- <Text muted size={1}>
125
- Cancel
126
- </Text>
127
- </Box>
128
- }
129
- disabled={'ontouchstart' in window}
130
- placement="top"
131
- >
132
- <Button
133
- fontSize={3}
134
- icon={CloseIcon}
135
- mode="bleed"
136
- onClick={handleCancelUpload}
137
- padding={2}
138
- style={{background: 'none', boxShadow: 'none'}}
139
- tone="critical"
140
- />
141
- </Tooltip>
121
+ <Button
122
+ fontSize={3}
123
+ icon={CloseIcon}
124
+ mode="bleed"
125
+ onClick={handleCancelUpload}
126
+ padding={2}
127
+ style={{background: 'none', boxShadow: 'none'}}
128
+ tone="critical"
129
+ />
142
130
  </Flex>
143
131
  )}
144
132
  </Box>
@@ -44,6 +44,7 @@ type TagButtonProps = {
44
44
 
45
45
  const TagButton = (props: TagButtonProps) => {
46
46
  const {disabled, icon, onClick, tone, tooltip} = props
47
+
47
48
  return (
48
49
  <Tooltip
49
50
  content={
@@ -55,6 +56,7 @@ const TagButton = (props: TagButtonProps) => {
55
56
  }
56
57
  disabled={'ontouchstart' in window}
57
58
  placement="top"
59
+ portal
58
60
  >
59
61
  <Button
60
62
  disabled={disabled}
@@ -13,15 +13,11 @@ type Props = {
13
13
  title: string
14
14
  }
15
15
 
16
- const TagViewHeader = (props: Props) => {
17
- const {allowCreate, light, title} = props
18
-
19
- // Redux
16
+ const TagViewHeader = ({allowCreate, light, title}: Props) => {
20
17
  const dispatch = useDispatch()
21
18
  const tagsCreating = useTypedSelector(state => state.tags.creating)
22
19
  const tagsFetching = useTypedSelector(state => state.tags.fetching)
23
20
 
24
- // Callbacks
25
21
  const handleTagCreate = () => {
26
22
  dispatch(DIALOG_ACTIONS.showTagCreate())
27
23
  }
@@ -35,6 +31,7 @@ const TagViewHeader = (props: Props) => {
35
31
  style={{
36
32
  background: light ? hues.gray?.[900].hex : black.hex,
37
33
  borderBottom: `1px solid ${hues.gray?.[900].hex}`,
34
+ flexShrink: 0,
38
35
  height: `${PANEL_HEIGHT}px`
39
36
  }}
40
37
  >
@@ -1,24 +1,26 @@
1
1
  import isHotkey from 'is-hotkey'
2
- import {RefObject, useEffect, useRef} from 'react'
2
+ import {RefObject, useCallback, useEffect, useRef} from 'react'
3
3
 
4
4
  const useKeyPress = (hotkey: string, onPress?: () => void): RefObject<boolean> => {
5
5
  const keyPressed = useRef(false)
6
6
 
7
7
  // If pressed key is our target key then set to true
8
- function downHandler(e: KeyboardEvent) {
9
- if (isHotkey(hotkey, e)) {
10
- keyPressed.current = true
11
-
12
- if (onPress) {
13
- onPress()
8
+ const downHandler = useCallback(
9
+ (e: KeyboardEvent) => {
10
+ if (isHotkey(hotkey, e)) {
11
+ keyPressed.current = true
12
+ if (onPress) {
13
+ onPress()
14
+ }
14
15
  }
15
- }
16
- }
16
+ },
17
+ [hotkey, onPress]
18
+ )
17
19
 
18
20
  // If released key is our target key then set to false
19
- const upHandler = () => {
21
+ const upHandler = useCallback(() => {
20
22
  keyPressed.current = false
21
- }
23
+ }, [])
22
24
 
23
25
  // Add event listeners
24
26
  useEffect(() => {
@@ -29,7 +31,7 @@ const useKeyPress = (hotkey: string, onPress?: () => void): RefObject<boolean> =
29
31
  window.removeEventListener('keydown', downHandler)
30
32
  window.removeEventListener('keyup', upHandler)
31
33
  }
32
- }, []) // Empty array ensures that effect is only run on mount and unmount
34
+ }, [downHandler, upHandler])
33
35
 
34
36
  return keyPressed
35
37
  }
@@ -0,0 +1,12 @@
1
+ import {PopoverProps, usePortal} from '@sanity/ui'
2
+
3
+ export function usePortalPopoverProps(): PopoverProps {
4
+ const portal = usePortal()
5
+
6
+ return {
7
+ constrainSize: true,
8
+ floatingBoundary: portal.element,
9
+ portal: true,
10
+ referenceBoundary: portal.element
11
+ }
12
+ }
@@ -1,4 +1,9 @@
1
- import {combineReducers} from '@reduxjs/toolkit'
1
+ import {
2
+ ActionFromReducersMapObject,
3
+ Reducer,
4
+ StateFromReducersMapObject,
5
+ combineReducers
6
+ } from '@reduxjs/toolkit'
2
7
  import {combineEpics} from 'redux-observable'
3
8
 
4
9
  import assetsReducer, {
@@ -97,7 +102,7 @@ export const rootEpic = combineEpics(
97
102
  uploadsCompleteQueueEpic
98
103
  )
99
104
 
100
- const reducers = combineReducers({
105
+ const reducers = {
101
106
  assets: assetsReducer,
102
107
  debug: debugReducer,
103
108
  dialog: dialogReducer,
@@ -106,5 +111,14 @@ const reducers = combineReducers({
106
111
  selected: selectedReducer,
107
112
  tags: tagsReducer,
108
113
  uploads: uploadsReducer
109
- })
110
- export const rootReducer = reducers
114
+ }
115
+
116
+ type ReducersMapObject = typeof reducers
117
+
118
+ // Workaround to avoid `$CombinedState` ts errors
119
+ // source: https://github.com/reduxjs/redux-toolkit/issues/2068#issuecomment-1130796500
120
+ // TODO: remove once we use `redux-toolkit` v2
121
+ export const rootReducer: Reducer<
122
+ StateFromReducersMapObject<ReducersMapObject>,
123
+ ActionFromReducersMapObject<ReducersMapObject>
124
+ > = combineReducers(reducers)