sanity-plugin-media 2.0.5 → 2.1.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sanity-plugin-media",
3
- "version": "2.0.5",
3
+ "version": "2.1.0",
4
4
  "description": "This version of `sanity-plugin-media` is for Sanity Studio V3.",
5
5
  "keywords": [
6
6
  "sanity",
@@ -54,10 +54,11 @@
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
+ "@sanity/uuid": "^3.0.1",
61
62
  "@tanem/react-nprogress": "^5.0.0",
62
63
  "copy-to-clipboard": "^3.3.1",
63
64
  "date-fns": "^2.27.0",
@@ -71,7 +72,7 @@
71
72
  "react-hook-form": "^6.15.1",
72
73
  "react-redux": "^7.2.2",
73
74
  "react-select": "^5.3.2",
74
- "react-virtuoso": "^2.11.0",
75
+ "react-virtuoso": "^4.3.11",
75
76
  "redux": "^4.2.0",
76
77
  "redux-observable": "^2.0.0",
77
78
  "rxjs": "^7.0.0",
@@ -83,7 +84,7 @@
83
84
  "@sanity/client": "^4.0.1",
84
85
  "@sanity/color": "^2.1.20",
85
86
  "@sanity/icons": "^2.0.0",
86
- "@sanity/pkg-utils": "^1.17.2",
87
+ "@sanity/pkg-utils": "^2.0.0",
87
88
  "@sanity/plugin-kit": "^2.1.16",
88
89
  "@sanity/semantic-release-preset": "^2.0.2",
89
90
  "@types/is-hotkey": "^0.1.7",
@@ -116,8 +117,6 @@
116
117
  "typescript": "^4.8.4"
117
118
  },
118
119
  "peerDependencies": {
119
- "@sanity/color": "^2.1.20",
120
- "@sanity/icons": "^2.0.0",
121
120
  "react": "^18",
122
121
  "react-dom": "^18",
123
122
  "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
  }
@@ -1,6 +1,6 @@
1
1
  import {CloseIcon} from '@sanity/icons'
2
2
  import {Box, Flex, Label, Text} from '@sanity/ui'
3
- import {SearchFacetInputProps} from '@types'
3
+ import {SearchFacetInputProps, WithId} from '@types'
4
4
  import React, {ReactNode} from 'react'
5
5
  import {useDispatch} from 'react-redux'
6
6
  import styled from 'styled-components'
@@ -8,7 +8,7 @@ import {searchActions} from '../../modules/search'
8
8
 
9
9
  type Props = {
10
10
  children: ReactNode
11
- facet: SearchFacetInputProps
11
+ facet: WithId<SearchFacetInputProps>
12
12
  }
13
13
 
14
14
  const Container = styled(Box)`
@@ -23,7 +23,7 @@ const SearchFacet = (props: Props) => {
23
23
  const dispatch = useDispatch()
24
24
 
25
25
  const handleClose = () => {
26
- dispatch(searchActions.facetsRemove({facetName: facet.name}))
26
+ dispatch(searchActions.facetsRemoveById({facetId: facet.id}))
27
27
  }
28
28
 
29
29
  return (
@@ -3,40 +3,42 @@ import {Box, Button, Menu, MenuButton, MenuDivider, MenuItem} from '@sanity/ui'
3
3
  import {
4
4
  SearchFacetInputNumberModifier,
5
5
  SearchFacetInputNumberProps,
6
- SearchFacetOperatorType
6
+ SearchFacetOperatorType,
7
+ WithId
7
8
  } from '@types'
8
9
  import React from 'react'
9
10
  import {useDispatch} from 'react-redux'
10
11
  import {operators} from '../../config/searchFacets'
12
+ import {usePortalPopoverProps} from '../../hooks/usePortalPopoverProps'
11
13
  import {searchActions} from '../../modules/search'
12
14
  import SearchFacet from '../SearchFacet'
13
15
  import TextInputNumber from '../TextInputNumber'
14
16
 
15
17
  type Props = {
16
- facet: SearchFacetInputNumberProps
18
+ facet: WithId<SearchFacetInputNumberProps>
17
19
  }
18
20
 
19
- const SearchFacetNumber = (props: Props) => {
20
- const {facet} = props
21
-
21
+ const SearchFacetNumber = ({facet}: Props) => {
22
22
  // Redux
23
23
  const dispatch = useDispatch()
24
24
 
25
+ const popoverProps = usePortalPopoverProps()
26
+
25
27
  const modifiers = facet?.modifiers
26
28
  const selectedModifier = facet?.modifier
27
29
  ? modifiers?.find(modifier => modifier.name === facet?.modifier)
28
30
  : modifiers?.[0]
29
31
 
30
32
  const handleOperatorItemClick = (operatorType: SearchFacetOperatorType) => {
31
- dispatch(searchActions.facetsUpdate({name: facet.name, operatorType}))
33
+ dispatch(searchActions.facetsUpdateById({id: facet.id, operatorType}))
32
34
  }
33
35
 
34
36
  const handleModifierClick = (modifier: SearchFacetInputNumberModifier) => {
35
- dispatch(searchActions.facetsUpdate({name: facet.name, modifier: modifier.name}))
37
+ dispatch(searchActions.facetsUpdateById({id: facet.id, modifier: modifier.name}))
36
38
  }
37
39
 
38
40
  const handleValueChange = (value: number) => {
39
- dispatch(searchActions.facetsUpdate({name: facet.name, value}))
41
+ dispatch(searchActions.facetsUpdateById({id: facet.id, value}))
40
42
  }
41
43
 
42
44
  const selectedOperatorType: SearchFacetOperatorType = facet.operatorType ?? 'greaterThan'
@@ -75,6 +77,7 @@ const SearchFacetNumber = (props: Props) => {
75
77
  })}
76
78
  </Menu>
77
79
  }
80
+ popover={popoverProps}
78
81
  />
79
82
  )}
80
83
 
@@ -116,6 +119,7 @@ const SearchFacetNumber = (props: Props) => {
116
119
  ))}
117
120
  </Menu>
118
121
  }
122
+ popover={popoverProps}
119
123
  />
120
124
  )}
121
125
  </SearchFacet>
@@ -3,7 +3,8 @@ import {Button, Menu, MenuButton, MenuDivider, MenuItem} from '@sanity/ui'
3
3
  import {
4
4
  SearchFacetInputSelectListItemProps,
5
5
  SearchFacetInputSelectProps,
6
- SearchFacetOperatorType
6
+ SearchFacetOperatorType,
7
+ WithId
7
8
  } from '@types'
8
9
  import React from 'react'
9
10
  import {useDispatch} from 'react-redux'
@@ -11,17 +12,18 @@ import {useDispatch} from 'react-redux'
11
12
  import {operators} from '../../config/searchFacets'
12
13
  import {searchActions} from '../../modules/search'
13
14
  import SearchFacet from '../SearchFacet'
15
+ import {usePortalPopoverProps} from '../../hooks/usePortalPopoverProps'
14
16
 
15
17
  type Props = {
16
- facet: SearchFacetInputSelectProps
18
+ facet: WithId<SearchFacetInputSelectProps>
17
19
  }
18
20
 
19
- const SearchFacetSelect = (props: Props) => {
20
- const {facet} = props
21
-
21
+ const SearchFacetSelect = ({facet}: Props) => {
22
22
  // Redux
23
23
  const dispatch = useDispatch()
24
24
 
25
+ const popoverProps = usePortalPopoverProps()
26
+
25
27
  const options = facet?.options
26
28
 
27
29
  const selectedItem = options?.find(v => v.name === facet?.value)
@@ -73,6 +75,7 @@ const SearchFacetSelect = (props: Props) => {
73
75
  })}
74
76
  </Menu>
75
77
  }
78
+ popover={popoverProps}
76
79
  />
77
80
  )}
78
81
 
@@ -101,6 +104,7 @@ const SearchFacetSelect = (props: Props) => {
101
104
  ))}
102
105
  </Menu>
103
106
  }
107
+ popover={popoverProps}
104
108
  />
105
109
  </SearchFacet>
106
110
  )
@@ -1,29 +1,30 @@
1
1
  import {SelectIcon} from '@sanity/icons'
2
2
  import {Box, Button, Menu, MenuButton, MenuDivider, MenuItem, TextInput} from '@sanity/ui'
3
- import {SearchFacetInputStringProps, SearchFacetOperatorType} from '@types'
3
+ import {SearchFacetInputStringProps, SearchFacetOperatorType, WithId} from '@types'
4
4
  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
 
11
12
  type Props = {
12
- facet: SearchFacetInputStringProps
13
+ facet: WithId<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
- dispatch(searchActions.facetsUpdate({name: facet.name, operatorType}))
23
+ dispatch(searchActions.facetsUpdateById({id: facet.id, operatorType}))
23
24
  }
24
25
 
25
26
  const handleChange = (e: ChangeEvent<HTMLInputElement>) => {
26
- dispatch(searchActions.facetsUpdate({name: facet.name, value: e.target.value}))
27
+ dispatch(searchActions.facetsUpdateById({id: facet.id, value: e.target.value}))
27
28
  }
28
29
 
29
30
  const selectedOperatorType: SearchFacetOperatorType = facet.operatorType
@@ -62,6 +63,7 @@ const SearchFacetString = (props: Props) => {
62
63
  })}
63
64
  </Menu>
64
65
  }
66
+ popover={popoverProps}
65
67
  />
66
68
  )}
67
69
 
@@ -1,10 +1,16 @@
1
1
  import {SelectIcon} from '@sanity/icons'
2
2
  import {Box, Button, Menu, MenuButton, MenuDivider, MenuItem} from '@sanity/ui'
3
- import {ReactSelectOption, SearchFacetInputSearchableProps, SearchFacetOperatorType} from '@types'
3
+ import {
4
+ ReactSelectOption,
5
+ SearchFacetInputSearchableProps,
6
+ SearchFacetOperatorType,
7
+ WithId
8
+ } from '@types'
4
9
  import React from 'react'
5
10
  import {useDispatch} from 'react-redux'
6
11
  import Select from 'react-select'
7
12
  import {operators} from '../../config/searchFacets'
13
+ import {usePortalPopoverProps} from '../../hooks/usePortalPopoverProps'
8
14
  import useTypedSelector from '../../hooks/useTypedSelector'
9
15
  import {searchActions} from '../../modules/search'
10
16
  import {selectTags} from '../../modules/tags'
@@ -13,22 +19,22 @@ import getTagSelectOptions from '../../utils/getTagSelectOptions'
13
19
  import SearchFacet from '../SearchFacet'
14
20
 
15
21
  type Props = {
16
- facet: SearchFacetInputSearchableProps
22
+ facet: WithId<SearchFacetInputSearchableProps>
17
23
  }
18
24
 
19
- const SearchFacetTags = (props: Props) => {
20
- const {facet} = props
21
-
25
+ const SearchFacetTags = ({facet}: Props) => {
22
26
  // Redux
23
27
  const dispatch = useDispatch()
24
28
  const tags = useTypedSelector(state => selectTags(state))
25
29
  const tagsFetching = useTypedSelector(state => state.tags.fetching)
26
30
  const allTagOptions = getTagSelectOptions(tags)
27
31
 
32
+ const popoverProps = usePortalPopoverProps()
33
+
28
34
  const handleChange = (option: ReactSelectOption) => {
29
35
  dispatch(
30
- searchActions.facetsUpdate({
31
- name: facet.name,
36
+ searchActions.facetsUpdateById({
37
+ id: facet.id,
32
38
  value: option
33
39
  })
34
40
  )
@@ -36,8 +42,8 @@ const SearchFacetTags = (props: Props) => {
36
42
 
37
43
  const handleOperatorItemClick = (operatorType: SearchFacetOperatorType) => {
38
44
  dispatch(
39
- searchActions.facetsUpdate({
40
- name: facet.name,
45
+ searchActions.facetsUpdateById({
46
+ id: facet.id,
41
47
  operatorType
42
48
  })
43
49
  )
@@ -79,6 +85,7 @@ const SearchFacetTags = (props: Props) => {
79
85
  })}
80
86
  </Menu>
81
87
  }
88
+ popover={popoverProps}
82
89
  />
83
90
  )}
84
91
 
@@ -25,20 +25,21 @@ const SearchFacets = (props: Props) => {
25
25
  const searchFacets = useTypedSelector(state => state.search.facets)
26
26
 
27
27
  const Items = searchFacets.map(facet => {
28
+ const key = facet.id
28
29
  if (facet.type === 'number') {
29
- return <SearchFacetNumber facet={facet} key={facet.name} />
30
+ return <SearchFacetNumber facet={facet} key={key} />
30
31
  }
31
32
 
32
33
  if (facet.type === 'searchable') {
33
- return <SearchFacetTags facet={facet} key={facet.name} />
34
+ return <SearchFacetTags facet={facet} key={key} />
34
35
  }
35
36
 
36
37
  if (facet.type === 'select') {
37
- return <SearchFacetSelect facet={facet} key={facet.name} />
38
+ return <SearchFacetSelect facet={facet} key={key} />
38
39
  }
39
40
 
40
41
  if (facet.type === 'string') {
41
- return <SearchFacetString facet={facet} key={facet.name} />
42
+ return <SearchFacetString facet={facet} key={key} />
42
43
  }
43
44
 
44
45
  return null
@@ -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
@@ -46,10 +49,7 @@ const SearchFacetsControl = () => {
46
49
  return true
47
50
  })
48
51
 
49
- // Determine if there are any remaining un-selected facets
50
- // (This operates under the assumption that only one of each facet can be active at any given time)
51
- const hasRemainingSearchFacets =
52
- filteredFacets.filter(facet => facet).length - searchFacets.length > 0
52
+ const hasSearchFacets = filteredFacets.length > 0
53
53
 
54
54
  const renderMenuFacets = (
55
55
  facets: (SearchFacetDivider | SearchFacetGroup | SearchFacetInputProps)[],
@@ -72,11 +72,11 @@ const SearchFacetsControl = () => {
72
72
  }
73
73
 
74
74
  if (facet) {
75
- const isPresent = !!searchFacets.find(v => v.name === facet.name)
75
+ const disabled = !facet.operatorTypes && !!searchFacets.find(v => v.name === facet.name)
76
76
 
77
77
  return (
78
78
  <MenuItem
79
- disabled={isPresent}
79
+ disabled={disabled}
80
80
  fontSize={1}
81
81
  key={facet.name}
82
82
  onClick={() => dispatch(searchActions.facetsAdd({facet}))}
@@ -98,7 +98,7 @@ const SearchFacetsControl = () => {
98
98
  <MenuButton
99
99
  button={
100
100
  <Button
101
- disabled={!hasRemainingSearchFacets}
101
+ disabled={!hasSearchFacets}
102
102
  fontSize={1}
103
103
  icon={AddCircleIcon}
104
104
  mode="bleed"
@@ -108,8 +108,10 @@ const SearchFacetsControl = () => {
108
108
  }
109
109
  id="facets"
110
110
  menu={<Menu>{renderMenuFacets(filteredFacets)}</Menu>}
111
- placement="right-start"
112
- portal
111
+ popover={{
112
+ ...popoverProps,
113
+ placement: 'right-start'
114
+ }}
113
115
  />
114
116
 
115
117
  {/* Clear facets button */}