sanity-plugin-media 4.3.0 → 4.3.2
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/LICENSE +4 -4
- package/README.md +12 -12
- package/dist/index.d.mts +263 -195
- package/dist/index.d.ts +263 -195
- package/dist/index.js +83 -203
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +84 -203
- package/dist/index.mjs.map +1 -1
- package/package.json +42 -64
- package/src/__tests__/fixtures/createEpicTestStore.ts +5 -4
- package/src/__tests__/fixtures/mockSanityClient.ts +8 -8
- package/src/__tests__/fixtures/renderWithProviders.tsx +8 -7
- package/src/__tests__/fixtures/rootState.ts +4 -4
- package/src/components/AssetGridVirtualized/index.tsx +8 -7
- package/src/components/AssetMetadata/index.tsx +6 -5
- package/src/components/AssetTableVirtualized/index.tsx +7 -6
- package/src/components/AutoTagInputWrapper/index.tsx +9 -4
- package/src/components/Browser/Browser.test.tsx +9 -8
- package/src/components/Browser/index.tsx +2 -1
- package/src/components/Browser/useBrowserInit.ts +9 -9
- package/src/components/ButtonAssetCopy/index.tsx +1 -0
- package/src/components/ButtonViewGroup/index.tsx +4 -3
- package/src/components/CardAsset/CardAsset.test.tsx +53 -52
- package/src/components/CardAsset/index.tsx +52 -49
- package/src/components/CardUpload/index.tsx +7 -6
- package/src/components/Controls/index.tsx +7 -6
- package/src/components/DebugControls/index.tsx +5 -4
- package/src/components/DialogAssetEdit/Details.tsx +3 -2
- package/src/components/DialogAssetEdit/DialogAssetEdit.test.tsx +28 -27
- package/src/components/DialogAssetEdit/index.tsx +37 -37
- package/src/components/DialogConfirm/index.tsx +2 -1
- package/src/components/DialogSearchFacets/index.tsx +3 -2
- package/src/components/DialogTagCreate/DialogTagCreate.test.tsx +16 -15
- package/src/components/DialogTagCreate/index.tsx +11 -10
- package/src/components/DialogTagEdit/DialogTagEdit.test.tsx +28 -27
- package/src/components/DialogTagEdit/index.tsx +17 -16
- package/src/components/DialogTags/index.tsx +4 -3
- package/src/components/Dialogs/index.tsx +2 -3
- package/src/components/DocumentList/index.tsx +2 -3
- package/src/components/FileAssetPreview/index.tsx +2 -2
- package/src/components/FormBuilderTool/FormBuilderTool.test.tsx +12 -11
- package/src/components/FormBuilderTool/index.tsx +2 -1
- package/src/components/FormFieldInputLabel/index.tsx +1 -2
- package/src/components/FormFieldInputTags/index.tsx +4 -3
- package/src/components/FormSubmitButton/index.tsx +1 -1
- package/src/components/Header/index.tsx +3 -3
- package/src/components/Image/index.tsx +10 -4
- package/src/components/Items/index.tsx +5 -4
- package/src/components/Notifications/index.tsx +3 -2
- package/src/components/OrderSelect/index.tsx +4 -3
- package/src/components/PickedBar/index.tsx +2 -1
- package/src/components/Progress/index.tsx +3 -3
- package/src/components/ReduxProvider/index.tsx +15 -12
- package/src/components/SearchFacet/index.tsx +3 -2
- package/src/components/SearchFacetNumber/index.tsx +8 -8
- package/src/components/SearchFacetSelect/index.tsx +7 -8
- package/src/components/SearchFacetString/index.tsx +1 -1
- package/src/components/SearchFacetTags/index.tsx +13 -12
- package/src/components/SearchFacets/index.tsx +2 -3
- package/src/components/SearchFacetsControl/index.tsx +13 -12
- package/src/components/TableHeader/index.tsx +18 -17
- package/src/components/TableHeaderItem/index.tsx +4 -4
- package/src/components/TableRowAsset/index.tsx +37 -36
- package/src/components/TableRowUpload/index.tsx +7 -6
- package/src/components/Tag/index.tsx +8 -7
- package/src/components/TagView/index.tsx +2 -2
- package/src/components/TagViewHeader/index.tsx +5 -4
- package/src/components/TagsPanel/index.tsx +3 -3
- package/src/components/TagsVirtualized/index.tsx +25 -24
- package/src/components/TextInputSearch/index.tsx +3 -2
- package/src/components/UploadDropzone/UploadDropzone.test.tsx +8 -7
- package/src/components/UploadDropzone/index.tsx +14 -13
- package/src/config/orders.ts +6 -6
- package/src/config/searchFacets.ts +56 -55
- package/src/constants.ts +15 -14
- package/src/contexts/AssetSourceDispatchContext.tsx +1 -1
- package/src/contexts/ToolOptionsContext.tsx +6 -5
- package/src/formSchema/index.test.ts +6 -5
- package/src/formSchema/index.ts +5 -5
- package/src/hooks/useBreakpointIndex.ts +6 -6
- package/src/hooks/useKeyPress.ts +2 -2
- package/src/hooks/usePortalPopoverProps.ts +1 -1
- package/src/modules/assets/actions.ts +8 -7
- package/src/modules/assets/deleteAndUpdateEpics.test.ts +18 -17
- package/src/modules/assets/fetchEpic.test.ts +12 -11
- package/src/modules/assets/index.ts +134 -133
- package/src/modules/assets/reducer.test.ts +9 -8
- package/src/modules/assets/tagsAndListenerEpics.test.ts +36 -35
- package/src/modules/debug/index.ts +3 -3
- package/src/modules/dialog/actions.ts +2 -2
- package/src/modules/dialog/epics.test.ts +29 -28
- package/src/modules/dialog/index.ts +36 -35
- package/src/modules/dialog/reducer.test.ts +31 -30
- package/src/modules/index.ts +9 -9
- package/src/modules/notifications/epics.test.ts +71 -70
- package/src/modules/notifications/index.ts +50 -49
- package/src/modules/notifications/reducer.test.ts +8 -7
- package/src/modules/search/index.test.ts +2 -1
- package/src/modules/search/index.ts +22 -22
- package/src/modules/selected/index.ts +2 -2
- package/src/modules/selectors.test.ts +4 -3
- package/src/modules/selectors.ts +5 -5
- package/src/modules/tags/epics.test.ts +16 -15
- package/src/modules/tags/index.test.ts +2 -1
- package/src/modules/tags/index.ts +82 -81
- package/src/modules/uploads/actions.ts +3 -3
- package/src/modules/uploads/epics.test.ts +13 -12
- package/src/modules/uploads/index.test.ts +8 -7
- package/src/modules/uploads/index.ts +48 -47
- package/src/operators/checkTagName.test.ts +7 -6
- package/src/operators/checkTagName.ts +6 -5
- package/src/operators/debugThrottle.ts +4 -4
- package/src/plugin.tsx +18 -18
- package/src/schemas/tag.ts +7 -7
- package/src/styled/react-select/creatable.tsx +40 -39
- package/src/styled/react-select/single.tsx +39 -38
- package/src/types/index.ts +4 -3
- package/src/utils/applyMediaTags.ts +11 -10
- package/src/utils/blocksToText.test.ts +5 -4
- package/src/utils/blocksToText.ts +2 -2
- package/src/utils/constructFilter.test.ts +15 -14
- package/src/utils/constructFilter.ts +7 -7
- package/src/utils/generatePreviewBlobUrl.test.ts +6 -5
- package/src/utils/generatePreviewBlobUrl.ts +2 -2
- package/src/utils/getAssetResolution.test.ts +3 -2
- package/src/utils/getDocumentAssetIds.test.ts +7 -6
- package/src/utils/getDocumentAssetIds.ts +2 -2
- package/src/utils/getSchemeColor.test.ts +1 -0
- package/src/utils/getSchemeColor.ts +9 -9
- package/src/utils/getTagSelectOptions.test.ts +6 -5
- package/src/utils/getTagSelectOptions.ts +1 -1
- package/src/utils/getUniqueDocuments.test.ts +4 -3
- package/src/utils/getUniqueDocuments.ts +2 -2
- package/src/utils/imageDprUrl.test.ts +4 -3
- package/src/utils/imageDprUrl.ts +1 -1
- package/src/utils/isSupportedAssetType.test.ts +1 -0
- package/src/utils/mediaField.ts +4 -3
- package/src/utils/sanitizeFormData.test.ts +14 -13
- package/src/utils/typeGuards.test.ts +2 -1
- package/src/utils/uploadSanityAsset.test.ts +5 -4
- package/src/utils/uploadSanityAsset.ts +17 -16
- package/src/utils/withMaxConcurrency.test.ts +5 -4
- package/src/utils/withMaxConcurrency.ts +4 -4
- package/src/utils/zodFormResolver.ts +17 -0
- package/v2-incompatible.js +2 -2
|
@@ -9,9 +9,9 @@ import {
|
|
|
9
9
|
Text,
|
|
10
10
|
type ThemeColorSchemeKey,
|
|
11
11
|
Tooltip,
|
|
12
|
-
useMediaIndex
|
|
12
|
+
useMediaIndex,
|
|
13
13
|
} from '@sanity/ui'
|
|
14
|
-
import {
|
|
14
|
+
import {formatRelative} from 'date-fns'
|
|
15
15
|
import filesize from 'filesize'
|
|
16
16
|
import {
|
|
17
17
|
memo,
|
|
@@ -20,11 +20,12 @@ import {
|
|
|
20
20
|
useCallback,
|
|
21
21
|
useEffect,
|
|
22
22
|
useRef,
|
|
23
|
-
useState
|
|
23
|
+
useState,
|
|
24
24
|
} from 'react'
|
|
25
25
|
import {useDispatch} from 'react-redux'
|
|
26
26
|
import {WithReferringDocuments, useColorSchemeValue} from 'sanity'
|
|
27
27
|
import {styled, css} from 'styled-components'
|
|
28
|
+
|
|
28
29
|
import {GRID_TEMPLATE_COLUMNS} from '../../constants'
|
|
29
30
|
import {useAssetSourceActions} from '../../contexts/AssetSourceDispatchContext'
|
|
30
31
|
import useKeyPress from '../../hooks/useKeyPress'
|
|
@@ -32,12 +33,12 @@ import useTypedSelector from '../../hooks/useTypedSelector'
|
|
|
32
33
|
import {assetsActions, selectAssetById} from '../../modules/assets'
|
|
33
34
|
import {dialogActions} from '../../modules/dialog'
|
|
34
35
|
import getAssetResolution from '../../utils/getAssetResolution'
|
|
36
|
+
import {getSchemeColor} from '../../utils/getSchemeColor'
|
|
37
|
+
import {getUniqueDocuments} from '../../utils/getUniqueDocuments'
|
|
35
38
|
import imageDprUrl from '../../utils/imageDprUrl'
|
|
36
39
|
import {isFileAsset, isImageAsset} from '../../utils/typeGuards'
|
|
37
40
|
import FileIcon from '../FileIcon'
|
|
38
41
|
import Image from '../Image'
|
|
39
|
-
import {getUniqueDocuments} from '../../utils/getUniqueDocuments'
|
|
40
|
-
import {getSchemeColor} from '../../utils/getSchemeColor'
|
|
41
42
|
|
|
42
43
|
// Duration (ms) to wait before reference counts (and associated listeners) are rendered
|
|
43
44
|
const REFERENCE_COUNT_VISIBILITY_DELAY = 750
|
|
@@ -70,22 +71,22 @@ const ContainerGrid = styled<
|
|
|
70
71
|
`
|
|
71
72
|
})
|
|
72
73
|
|
|
73
|
-
const ContextActionContainer = styled<typeof Flex, {$scheme: ThemeColorSchemeKey}>(Flex)(
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
}
|
|
74
|
+
const ContextActionContainer = styled<typeof Flex, {$scheme: ThemeColorSchemeKey}>(Flex)(({
|
|
75
|
+
$scheme,
|
|
76
|
+
}) => {
|
|
77
|
+
return css`
|
|
78
|
+
cursor: pointer;
|
|
79
|
+
@media (hover: hover) and (pointer: fine) {
|
|
80
|
+
&:hover {
|
|
81
|
+
background: ${getSchemeColor($scheme, 'bg2')};
|
|
81
82
|
}
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
)
|
|
83
|
+
}
|
|
84
|
+
`
|
|
85
|
+
})
|
|
85
86
|
|
|
86
87
|
const StyledWarningIcon = styled(WarningFilledIcon)(({theme}) => {
|
|
87
88
|
return {
|
|
88
|
-
color: theme.sanity.color.spot.red
|
|
89
|
+
color: theme.sanity.color.spot.red,
|
|
89
90
|
}
|
|
90
91
|
})
|
|
91
92
|
|
|
@@ -101,8 +102,8 @@ const TableRowAsset = (props: Props) => {
|
|
|
101
102
|
const refCountVisibleTimeout = useRef<ReturnType<typeof window.setTimeout>>(null)
|
|
102
103
|
|
|
103
104
|
const dispatch = useDispatch()
|
|
104
|
-
const lastPicked = useTypedSelector(state => state.assets.lastPicked)
|
|
105
|
-
const item = useTypedSelector(state => selectAssetById(state, id))
|
|
105
|
+
const lastPicked = useTypedSelector((state) => state.assets.lastPicked)
|
|
106
|
+
const item = useTypedSelector((state) => selectAssetById(state, id))
|
|
106
107
|
|
|
107
108
|
const mediaIndex = useMediaIndex()
|
|
108
109
|
|
|
@@ -127,7 +128,7 @@ const TableRowAsset = (props: Props) => {
|
|
|
127
128
|
dispatch(assetsActions.pick({assetId: asset._id, picked: !picked}))
|
|
128
129
|
}
|
|
129
130
|
},
|
|
130
|
-
[asset, dispatch, lastPicked, onSelect, picked, shiftPressed]
|
|
131
|
+
[asset, dispatch, lastPicked, onSelect, picked, shiftPressed],
|
|
131
132
|
)
|
|
132
133
|
|
|
133
134
|
const handleClick = useCallback(
|
|
@@ -147,7 +148,7 @@ const TableRowAsset = (props: Props) => {
|
|
|
147
148
|
dispatch(dialogActions.showAssetEdit({assetId: asset._id}))
|
|
148
149
|
}
|
|
149
150
|
},
|
|
150
|
-
[asset, dispatch, lastPicked, onSelect, picked, shiftPressed]
|
|
151
|
+
[asset, dispatch, lastPicked, onSelect, picked, shiftPressed],
|
|
151
152
|
)
|
|
152
153
|
|
|
153
154
|
const opacityCell = updating ? 0.5 : 1
|
|
@@ -157,7 +158,7 @@ const TableRowAsset = (props: Props) => {
|
|
|
157
158
|
useEffect(() => {
|
|
158
159
|
refCountVisibleTimeout.current = setTimeout(
|
|
159
160
|
() => setReferenceCountVisible(true),
|
|
160
|
-
REFERENCE_COUNT_VISIBILITY_DELAY
|
|
161
|
+
REFERENCE_COUNT_VISIBILITY_DELAY,
|
|
161
162
|
)
|
|
162
163
|
return () => {
|
|
163
164
|
if (refCountVisibleTimeout.current) {
|
|
@@ -181,7 +182,7 @@ const TableRowAsset = (props: Props) => {
|
|
|
181
182
|
gridRowGap: 0,
|
|
182
183
|
gridTemplateColumns:
|
|
183
184
|
mediaIndex < 3 ? GRID_TEMPLATE_COLUMNS.SMALL : GRID_TEMPLATE_COLUMNS.LARGE,
|
|
184
|
-
gridTemplateRows: mediaIndex < 3 ? 'auto' : '1fr'
|
|
185
|
+
gridTemplateRows: mediaIndex < 3 ? 'auto' : '1fr',
|
|
185
186
|
}}
|
|
186
187
|
$updating={item.updating}
|
|
187
188
|
>
|
|
@@ -197,14 +198,14 @@ const TableRowAsset = (props: Props) => {
|
|
|
197
198
|
height: '100%',
|
|
198
199
|
justifyContent: 'center',
|
|
199
200
|
opacity: opacityCell,
|
|
200
|
-
position: 'relative'
|
|
201
|
+
position: 'relative',
|
|
201
202
|
}}
|
|
202
203
|
>
|
|
203
204
|
{onSelect ? (
|
|
204
205
|
<EditIcon
|
|
205
206
|
style={{
|
|
206
207
|
flexShrink: 0,
|
|
207
|
-
opacity: 0.5
|
|
208
|
+
opacity: 0.5,
|
|
208
209
|
}}
|
|
209
210
|
/>
|
|
210
211
|
) : (
|
|
@@ -213,7 +214,7 @@ const TableRowAsset = (props: Props) => {
|
|
|
213
214
|
readOnly
|
|
214
215
|
style={{
|
|
215
216
|
pointerEvents: 'none', // TODO: consider alternative for usability
|
|
216
|
-
transform: 'scale(0.8)'
|
|
217
|
+
transform: 'scale(0.8)',
|
|
217
218
|
}}
|
|
218
219
|
/>
|
|
219
220
|
)}
|
|
@@ -226,7 +227,7 @@ const TableRowAsset = (props: Props) => {
|
|
|
226
227
|
gridRowStart: 1,
|
|
227
228
|
gridRowEnd: 'span 5',
|
|
228
229
|
height: '90px',
|
|
229
|
-
width: '100px'
|
|
230
|
+
width: '100px',
|
|
230
231
|
}}
|
|
231
232
|
>
|
|
232
233
|
<Flex align="center" justify="center" style={{height: '100%', position: 'relative'}}>
|
|
@@ -255,7 +256,7 @@ const TableRowAsset = (props: Props) => {
|
|
|
255
256
|
left: 0,
|
|
256
257
|
position: 'absolute',
|
|
257
258
|
top: 0,
|
|
258
|
-
width: '100%'
|
|
259
|
+
width: '100%',
|
|
259
260
|
}}
|
|
260
261
|
>
|
|
261
262
|
<Spinner />
|
|
@@ -272,7 +273,7 @@ const TableRowAsset = (props: Props) => {
|
|
|
272
273
|
left: 0,
|
|
273
274
|
position: 'absolute',
|
|
274
275
|
top: 0,
|
|
275
|
-
width: '100%'
|
|
276
|
+
width: '100%',
|
|
276
277
|
}}
|
|
277
278
|
>
|
|
278
279
|
<Text size={2}>
|
|
@@ -289,7 +290,7 @@ const TableRowAsset = (props: Props) => {
|
|
|
289
290
|
style={{
|
|
290
291
|
gridColumn: 3,
|
|
291
292
|
gridRow: mediaIndex < 3 ? 2 : 'auto',
|
|
292
|
-
opacity: opacityCell
|
|
293
|
+
opacity: opacityCell,
|
|
293
294
|
}}
|
|
294
295
|
>
|
|
295
296
|
<Text muted size={1} style={{lineHeight: '2em'}} textOverflow="ellipsis">
|
|
@@ -303,7 +304,7 @@ const TableRowAsset = (props: Props) => {
|
|
|
303
304
|
style={{
|
|
304
305
|
gridColumn: mediaIndex < 3 ? 3 : 4,
|
|
305
306
|
gridRow: mediaIndex < 3 ? 3 : 'auto',
|
|
306
|
-
opacity: opacityCell
|
|
307
|
+
opacity: opacityCell,
|
|
307
308
|
}}
|
|
308
309
|
>
|
|
309
310
|
<Text muted size={1} style={{lineHeight: '2em'}} textOverflow="ellipsis">
|
|
@@ -317,7 +318,7 @@ const TableRowAsset = (props: Props) => {
|
|
|
317
318
|
display: mediaIndex < 3 ? 'none' : 'block',
|
|
318
319
|
gridColumn: 5,
|
|
319
320
|
gridRow: 'auto',
|
|
320
|
-
opacity: opacityCell
|
|
321
|
+
opacity: opacityCell,
|
|
321
322
|
}}
|
|
322
323
|
>
|
|
323
324
|
<Text muted size={1} style={{lineHeight: '2em'}} textOverflow="ellipsis">
|
|
@@ -331,7 +332,7 @@ const TableRowAsset = (props: Props) => {
|
|
|
331
332
|
display: mediaIndex < 3 ? 'none' : 'block',
|
|
332
333
|
gridColumn: 6,
|
|
333
334
|
gridRow: 'auto',
|
|
334
|
-
opacity: opacityCell
|
|
335
|
+
opacity: opacityCell,
|
|
335
336
|
}}
|
|
336
337
|
>
|
|
337
338
|
<Text muted size={1} style={{lineHeight: '2em'}} textOverflow="ellipsis">
|
|
@@ -345,7 +346,7 @@ const TableRowAsset = (props: Props) => {
|
|
|
345
346
|
style={{
|
|
346
347
|
gridColumn: mediaIndex < 3 ? 3 : 7,
|
|
347
348
|
gridRow: mediaIndex < 3 ? 4 : 'auto',
|
|
348
|
-
opacity: opacityCell
|
|
349
|
+
opacity: opacityCell,
|
|
349
350
|
}}
|
|
350
351
|
>
|
|
351
352
|
<Text muted size={1} style={{lineHeight: '2em'}} textOverflow="ellipsis">
|
|
@@ -359,7 +360,7 @@ const TableRowAsset = (props: Props) => {
|
|
|
359
360
|
display: mediaIndex < 3 ? 'none' : 'block',
|
|
360
361
|
gridColumn: 8,
|
|
361
362
|
gridRow: 'auto',
|
|
362
|
-
opacity: opacityCell
|
|
363
|
+
opacity: opacityCell,
|
|
363
364
|
}}
|
|
364
365
|
>
|
|
365
366
|
<Text muted size={1} style={{lineHeight: '2em'}} textOverflow="ellipsis">
|
|
@@ -388,7 +389,7 @@ const TableRowAsset = (props: Props) => {
|
|
|
388
389
|
gridColumn: mediaIndex < 3 ? 4 : 9,
|
|
389
390
|
gridRowStart: '1',
|
|
390
391
|
gridRowEnd: mediaIndex < 3 ? 'span 5' : 'auto',
|
|
391
|
-
opacity: opacityCell
|
|
392
|
+
opacity: opacityCell,
|
|
392
393
|
}}
|
|
393
394
|
>
|
|
394
395
|
{/* TODO: DRY */}
|
|
@@ -3,6 +3,7 @@ import {Box, Button, Flex, Grid, Stack, Text, useMediaIndex} from '@sanity/ui'
|
|
|
3
3
|
import filesize from 'filesize'
|
|
4
4
|
import {useDispatch} from 'react-redux'
|
|
5
5
|
import {useColorSchemeValue} from 'sanity'
|
|
6
|
+
|
|
6
7
|
import {GRID_TEMPLATE_COLUMNS} from '../../constants'
|
|
7
8
|
import useTypedSelector from '../../hooks/useTypedSelector'
|
|
8
9
|
import {selectUploadById, uploadsActions} from '../../modules/uploads'
|
|
@@ -21,7 +22,7 @@ const TableRowUpload = (props: Props) => {
|
|
|
21
22
|
|
|
22
23
|
// Redux
|
|
23
24
|
const dispatch = useDispatch()
|
|
24
|
-
const item = useTypedSelector(state => selectUploadById(state, id))
|
|
25
|
+
const item = useTypedSelector((state) => selectUploadById(state, id))
|
|
25
26
|
|
|
26
27
|
const mediaIndex = useMediaIndex()
|
|
27
28
|
|
|
@@ -63,7 +64,7 @@ const TableRowUpload = (props: Props) => {
|
|
|
63
64
|
mediaIndex < 3 ? GRID_TEMPLATE_COLUMNS.SMALL : GRID_TEMPLATE_COLUMNS.LARGE,
|
|
64
65
|
gridTemplateRows: mediaIndex < 3 ? 'auto' : '1fr',
|
|
65
66
|
height: '100%',
|
|
66
|
-
position: 'relative'
|
|
67
|
+
position: 'relative',
|
|
67
68
|
}}
|
|
68
69
|
>
|
|
69
70
|
{/* Progress bar */}
|
|
@@ -77,7 +78,7 @@ const TableRowUpload = (props: Props) => {
|
|
|
77
78
|
width: '100%',
|
|
78
79
|
transform: `scaleX(${percentLoaded * 0.01})`,
|
|
79
80
|
transformOrigin: 'bottom left',
|
|
80
|
-
transition: 'all 1000ms ease-out'
|
|
81
|
+
transition: 'all 1000ms ease-out',
|
|
81
82
|
}}
|
|
82
83
|
/>
|
|
83
84
|
|
|
@@ -88,7 +89,7 @@ const TableRowUpload = (props: Props) => {
|
|
|
88
89
|
gridRowStart: mediaIndex < 3 ? 1 : 'auto',
|
|
89
90
|
gridRowEnd: mediaIndex < 3 ? 'span 4' : 'auto',
|
|
90
91
|
height: '90px',
|
|
91
|
-
width: '100px'
|
|
92
|
+
width: '100px',
|
|
92
93
|
}}
|
|
93
94
|
>
|
|
94
95
|
<Box style={{height: '100%', position: 'relative'}}>
|
|
@@ -122,7 +123,7 @@ const TableRowUpload = (props: Props) => {
|
|
|
122
123
|
height: '100%',
|
|
123
124
|
left: 0,
|
|
124
125
|
top: 0,
|
|
125
|
-
width: '100%'
|
|
126
|
+
width: '100%',
|
|
126
127
|
}}
|
|
127
128
|
>
|
|
128
129
|
<Button
|
|
@@ -144,7 +145,7 @@ const TableRowUpload = (props: Props) => {
|
|
|
144
145
|
style={{
|
|
145
146
|
gridColumn: mediaIndex < 3 ? 3 : '3/8',
|
|
146
147
|
gridRow: mediaIndex < 3 ? '2/4' : 'auto',
|
|
147
|
-
marginLeft: mediaIndex < 3 ? 3 : 0
|
|
148
|
+
marginLeft: mediaIndex < 3 ? 3 : 0,
|
|
148
149
|
}}
|
|
149
150
|
>
|
|
150
151
|
<Stack space={3}>
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {ArrowDownIcon, ArrowUpIcon, CloseIcon, EditIcon, SearchIcon, TrashIcon} from '@sanity/icons'
|
|
2
2
|
import {Box, Button, Container, Flex, Text, Tooltip} from '@sanity/ui'
|
|
3
|
-
import type {SearchFacetInputSearchableProps, TagActions, TagItem} from '../../types'
|
|
4
3
|
import {type ReactNode} from 'react'
|
|
5
4
|
import {useDispatch} from 'react-redux'
|
|
6
5
|
import {styled} from 'styled-components'
|
|
6
|
+
|
|
7
7
|
import {inputs} from '../../config/searchFacets'
|
|
8
8
|
import {PANEL_HEIGHT} from '../../constants'
|
|
9
9
|
import useTypedSelector from '../../hooks/useTypedSelector'
|
|
@@ -11,6 +11,7 @@ import {selectAssetsPicked} from '../../modules/assets'
|
|
|
11
11
|
import {dialogActions} from '../../modules/dialog'
|
|
12
12
|
import {DIALOG_ACTIONS} from '../../modules/dialog/actions'
|
|
13
13
|
import {searchActions, selectIsSearchFacetTag} from '../../modules/search'
|
|
14
|
+
import type {SearchFacetInputSearchableProps, TagActions, TagItem} from '../../types'
|
|
14
15
|
|
|
15
16
|
type Props = {
|
|
16
17
|
actions?: TagActions[]
|
|
@@ -77,7 +78,7 @@ const Tag = (props: Props) => {
|
|
|
77
78
|
// Redux
|
|
78
79
|
const dispatch = useDispatch()
|
|
79
80
|
const assetsPicked = useTypedSelector(selectAssetsPicked)
|
|
80
|
-
const isSearchFacetTag = useTypedSelector(state => selectIsSearchFacetTag(state, tag?.tag?._id))
|
|
81
|
+
const isSearchFacetTag = useTypedSelector((state) => selectIsSearchFacetTag(state, tag?.tag?._id))
|
|
81
82
|
|
|
82
83
|
// Callbacks
|
|
83
84
|
const handleSearchFacetTagRemove = () => {
|
|
@@ -105,8 +106,8 @@ const Tag = (props: Props) => {
|
|
|
105
106
|
...inputs.tag,
|
|
106
107
|
value: {
|
|
107
108
|
label: tag?.tag?.name?.current,
|
|
108
|
-
value: tag?.tag?._id
|
|
109
|
-
}
|
|
109
|
+
value: tag?.tag?._id,
|
|
110
|
+
},
|
|
110
111
|
} as SearchFacetInputSearchableProps
|
|
111
112
|
|
|
112
113
|
if (isSearchFacetTag) {
|
|
@@ -114,8 +115,8 @@ const Tag = (props: Props) => {
|
|
|
114
115
|
searchActions.facetsUpdate({
|
|
115
116
|
name: 'tag',
|
|
116
117
|
operatorType: 'references',
|
|
117
|
-
value: searchFacet.value
|
|
118
|
-
})
|
|
118
|
+
value: searchFacet.value,
|
|
119
|
+
}),
|
|
119
120
|
)
|
|
120
121
|
} else {
|
|
121
122
|
dispatch(searchActions.facetsAdd({facet: searchFacet}))
|
|
@@ -130,7 +131,7 @@ const Tag = (props: Props) => {
|
|
|
130
131
|
size={1}
|
|
131
132
|
style={{
|
|
132
133
|
opacity: tag?.updating ? 0.5 : 1.0,
|
|
133
|
-
userSelect: 'none'
|
|
134
|
+
userSelect: 'none',
|
|
134
135
|
}}
|
|
135
136
|
textOverflow="ellipsis"
|
|
136
137
|
>
|
|
@@ -9,8 +9,8 @@ import TagViewHeader from '../TagViewHeader'
|
|
|
9
9
|
const TagView = () => {
|
|
10
10
|
const numPickedAssets = useTypedSelector(selectAssetsPickedLength)
|
|
11
11
|
const tags = useTypedSelector(selectTags)
|
|
12
|
-
const fetching = useTypedSelector(state => state.tags.fetching)
|
|
13
|
-
const fetchCount = useTypedSelector(state => state.tags.fetchCount)
|
|
12
|
+
const fetching = useTypedSelector((state) => state.tags.fetching)
|
|
13
|
+
const fetchCount = useTypedSelector((state) => state.tags.fetchCount)
|
|
14
14
|
const fetchComplete = fetchCount !== -1
|
|
15
15
|
const hasTags = !fetching && tags?.length > 0
|
|
16
16
|
const hasPicked = !!(numPickedAssets > 0)
|
|
@@ -2,6 +2,7 @@ import {ComposeIcon} from '@sanity/icons'
|
|
|
2
2
|
import {Box, Button, Flex, Inline, Label} from '@sanity/ui'
|
|
3
3
|
import {useDispatch} from 'react-redux'
|
|
4
4
|
import {useColorSchemeValue} from 'sanity'
|
|
5
|
+
|
|
5
6
|
import {PANEL_HEIGHT} from '../../constants'
|
|
6
7
|
import useTypedSelector from '../../hooks/useTypedSelector'
|
|
7
8
|
import {DIALOG_ACTIONS} from '../../modules/dialog/actions'
|
|
@@ -17,8 +18,8 @@ const TagViewHeader = ({allowCreate, light, title}: Props) => {
|
|
|
17
18
|
const scheme = useColorSchemeValue()
|
|
18
19
|
|
|
19
20
|
const dispatch = useDispatch()
|
|
20
|
-
const tagsCreating = useTypedSelector(state => state.tags.creating)
|
|
21
|
-
const tagsFetching = useTypedSelector(state => state.tags.fetching)
|
|
21
|
+
const tagsCreating = useTypedSelector((state) => state.tags.creating)
|
|
22
|
+
const tagsFetching = useTypedSelector((state) => state.tags.fetching)
|
|
22
23
|
|
|
23
24
|
const handleTagCreate = () => {
|
|
24
25
|
dispatch(DIALOG_ACTIONS.showTagCreate())
|
|
@@ -34,7 +35,7 @@ const TagViewHeader = ({allowCreate, light, title}: Props) => {
|
|
|
34
35
|
background: light ? getSchemeColor(scheme, 'bg') : 'inherit',
|
|
35
36
|
borderBottom: '1px solid var(--card-border-color)',
|
|
36
37
|
flexShrink: 0,
|
|
37
|
-
height: `${PANEL_HEIGHT}px
|
|
38
|
+
height: `${PANEL_HEIGHT}px`,
|
|
38
39
|
}}
|
|
39
40
|
>
|
|
40
41
|
<Inline space={2}>
|
|
@@ -56,7 +57,7 @@ const TagViewHeader = ({allowCreate, light, title}: Props) => {
|
|
|
56
57
|
onClick={handleTagCreate}
|
|
57
58
|
style={{
|
|
58
59
|
background: 'transparent',
|
|
59
|
-
boxShadow: 'none'
|
|
60
|
+
boxShadow: 'none',
|
|
60
61
|
}}
|
|
61
62
|
/>
|
|
62
63
|
</Box>
|
|
@@ -5,7 +5,7 @@ import useTypedSelector from '../../hooks/useTypedSelector'
|
|
|
5
5
|
import TagView from '../TagView'
|
|
6
6
|
|
|
7
7
|
const TagsPanel = () => {
|
|
8
|
-
const tagsPanelVisible = useTypedSelector(state => state.tags.panelVisible)
|
|
8
|
+
const tagsPanelVisible = useTypedSelector((state) => state.tags.panelVisible)
|
|
9
9
|
|
|
10
10
|
if (!tagsPanelVisible) {
|
|
11
11
|
return null
|
|
@@ -15,7 +15,7 @@ const TagsPanel = () => {
|
|
|
15
15
|
<Box
|
|
16
16
|
style={{
|
|
17
17
|
position: 'relative',
|
|
18
|
-
width: TAGS_PANEL_WIDTH
|
|
18
|
+
width: TAGS_PANEL_WIDTH,
|
|
19
19
|
}}
|
|
20
20
|
>
|
|
21
21
|
<Box
|
|
@@ -28,7 +28,7 @@ const TagsPanel = () => {
|
|
|
28
28
|
position: 'absolute',
|
|
29
29
|
right: 0,
|
|
30
30
|
top: 0,
|
|
31
|
-
width: '100%'
|
|
31
|
+
width: '100%',
|
|
32
32
|
}}
|
|
33
33
|
>
|
|
34
34
|
<TagView />
|
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
import {Flex, Label} from '@sanity/ui'
|
|
2
|
-
import type {TagActions, TagItem} from '../../types'
|
|
3
2
|
import {memo, useState} from 'react'
|
|
4
3
|
import {Virtuoso} from 'react-virtuoso'
|
|
4
|
+
|
|
5
5
|
import {PANEL_HEIGHT} from '../../constants'
|
|
6
6
|
import useTypedSelector from '../../hooks/useTypedSelector'
|
|
7
7
|
import {selectAssetsPicked} from '../../modules/assets'
|
|
8
8
|
import {selectTags} from '../../modules/tags'
|
|
9
|
+
import type {TagActions, TagItem} from '../../types'
|
|
9
10
|
import Tag from '../Tag'
|
|
10
11
|
|
|
11
12
|
const VirtualRow = memo(
|
|
12
13
|
({
|
|
13
14
|
isScrolling,
|
|
14
|
-
item
|
|
15
|
+
item,
|
|
15
16
|
}: {
|
|
16
17
|
isScrolling?: boolean
|
|
17
18
|
item:
|
|
@@ -37,7 +38,7 @@ const VirtualRow = memo(
|
|
|
37
38
|
|
|
38
39
|
// Render tag - only display actions if we're not in the process of scrolling
|
|
39
40
|
return <Tag actions={isScrolling ? undefined : item.actions} key={item.tag?._id} tag={item} />
|
|
40
|
-
}
|
|
41
|
+
},
|
|
41
42
|
)
|
|
42
43
|
|
|
43
44
|
const TagsVirtualized = () => {
|
|
@@ -51,7 +52,7 @@ const TagsVirtualized = () => {
|
|
|
51
52
|
|
|
52
53
|
// Filter out all tag IDS used (across all) and dedupe
|
|
53
54
|
const pickedTagIds = assetsPicked?.reduce((acc: string[], val) => {
|
|
54
|
-
const assetTagIds = val?.asset?.opt?.media?.tags?.map(tag => tag._ref) || []
|
|
55
|
+
const assetTagIds = val?.asset?.opt?.media?.tags?.map((tag) => tag._ref) || []
|
|
55
56
|
acc = acc.concat(assetTagIds)
|
|
56
57
|
return acc
|
|
57
58
|
}, [])
|
|
@@ -62,9 +63,9 @@ const TagsVirtualized = () => {
|
|
|
62
63
|
// 2. those which exist in some picked assets ('applied to some')
|
|
63
64
|
const tagIdsSegmented = pickedTagIdsUnique.reduce(
|
|
64
65
|
(acc: {appliedToAll: string[]; appliedToSome: string[]}, tagId) => {
|
|
65
|
-
const tagIsInEveryAsset = assetsPicked.every(assetItem => {
|
|
66
|
+
const tagIsInEveryAsset = assetsPicked.every((assetItem) => {
|
|
66
67
|
const tagIndex =
|
|
67
|
-
assetItem.asset.opt?.media?.tags?.findIndex(tag => tag._ref === tagId) ?? -1
|
|
68
|
+
assetItem.asset.opt?.media?.tags?.findIndex((tag) => tag._ref === tagId) ?? -1
|
|
68
69
|
return tagIndex >= 0
|
|
69
70
|
})
|
|
70
71
|
|
|
@@ -78,27 +79,27 @@ const TagsVirtualized = () => {
|
|
|
78
79
|
},
|
|
79
80
|
{
|
|
80
81
|
appliedToAll: [],
|
|
81
|
-
appliedToSome: []
|
|
82
|
-
}
|
|
82
|
+
appliedToSome: [],
|
|
83
|
+
},
|
|
83
84
|
)
|
|
84
85
|
|
|
85
86
|
const tagsAppliedToAll = tags
|
|
86
|
-
.filter(tag => tagIdsSegmented.appliedToAll.includes(tag.tag._id))
|
|
87
|
-
.map(tagItem => ({
|
|
87
|
+
.filter((tag) => tagIdsSegmented.appliedToAll.includes(tag.tag._id))
|
|
88
|
+
.map((tagItem) => ({
|
|
88
89
|
...tagItem,
|
|
89
|
-
actions: ['delete', 'edit', 'removeAll', 'search'] as TagActions[]
|
|
90
|
+
actions: ['delete', 'edit', 'removeAll', 'search'] as TagActions[],
|
|
90
91
|
}))
|
|
91
92
|
const tagsAppliedToSome = tags
|
|
92
|
-
.filter(tag => tagIdsSegmented.appliedToSome.includes(tag.tag._id))
|
|
93
|
-
.map(tagItem => ({
|
|
93
|
+
.filter((tag) => tagIdsSegmented.appliedToSome.includes(tag.tag._id))
|
|
94
|
+
.map((tagItem) => ({
|
|
94
95
|
...tagItem,
|
|
95
|
-
actions: ['applyAll', 'delete', 'edit', 'removeAll', 'search'] as TagActions[]
|
|
96
|
+
actions: ['applyAll', 'delete', 'edit', 'removeAll', 'search'] as TagActions[],
|
|
96
97
|
}))
|
|
97
98
|
const tagsUnused = tags
|
|
98
|
-
.filter(tag => !pickedTagIdsUnique.includes(tag.tag._id))
|
|
99
|
-
.map(tagItem => ({
|
|
99
|
+
.filter((tag) => !pickedTagIdsUnique.includes(tag.tag._id))
|
|
100
|
+
.map((tagItem) => ({
|
|
100
101
|
...tagItem,
|
|
101
|
-
actions: ['applyAll', 'delete', 'edit', 'search'] as TagActions[]
|
|
102
|
+
actions: ['applyAll', 'delete', 'edit', 'search'] as TagActions[],
|
|
102
103
|
}))
|
|
103
104
|
|
|
104
105
|
let items: (
|
|
@@ -108,30 +109,30 @@ const TagsVirtualized = () => {
|
|
|
108
109
|
})
|
|
109
110
|
)[] = []
|
|
110
111
|
if (assetsPicked.length === 0) {
|
|
111
|
-
items = tags.map(tagItem => ({
|
|
112
|
+
items = tags.map((tagItem) => ({
|
|
112
113
|
...tagItem,
|
|
113
|
-
actions: ['delete', 'edit', 'search'] as TagActions[]
|
|
114
|
+
actions: ['delete', 'edit', 'search'] as TagActions[],
|
|
114
115
|
}))
|
|
115
116
|
} else {
|
|
116
117
|
if (tagsAppliedToAll?.length > 0) {
|
|
117
118
|
items = [
|
|
118
119
|
...items, //
|
|
119
120
|
assetsPicked.length === 1 ? 'Used' : 'Used by all',
|
|
120
|
-
...tagsAppliedToAll
|
|
121
|
+
...tagsAppliedToAll,
|
|
121
122
|
]
|
|
122
123
|
}
|
|
123
124
|
if (tagsAppliedToSome?.length > 0) {
|
|
124
125
|
items = [
|
|
125
126
|
...items, //
|
|
126
127
|
'Used by some',
|
|
127
|
-
...tagsAppliedToSome
|
|
128
|
+
...tagsAppliedToSome,
|
|
128
129
|
]
|
|
129
130
|
}
|
|
130
131
|
if (tagsUnused?.length > 0) {
|
|
131
132
|
items = [
|
|
132
133
|
...items, //
|
|
133
134
|
'Unused',
|
|
134
|
-
...tagsUnused
|
|
135
|
+
...tagsUnused,
|
|
135
136
|
]
|
|
136
137
|
}
|
|
137
138
|
}
|
|
@@ -139,7 +140,7 @@ const TagsVirtualized = () => {
|
|
|
139
140
|
return (
|
|
140
141
|
<Virtuoso
|
|
141
142
|
className="media__custom-scrollbar"
|
|
142
|
-
computeItemKey={index => {
|
|
143
|
+
computeItemKey={(index) => {
|
|
143
144
|
const item = items[index]
|
|
144
145
|
if (typeof item === 'string') {
|
|
145
146
|
return item
|
|
@@ -147,7 +148,7 @@ const TagsVirtualized = () => {
|
|
|
147
148
|
return item.tag._id
|
|
148
149
|
}}
|
|
149
150
|
isScrolling={setIsScrolling}
|
|
150
|
-
itemContent={index => {
|
|
151
|
+
itemContent={(index) => {
|
|
151
152
|
return <VirtualRow isScrolling={isScrolling} item={items[index]} />
|
|
152
153
|
}}
|
|
153
154
|
style={{flex: 1, overflowX: 'hidden'}}
|
|
@@ -2,12 +2,13 @@ import {CloseIcon, SearchIcon} from '@sanity/icons'
|
|
|
2
2
|
import {Box, Flex, TextInput} from '@sanity/ui'
|
|
3
3
|
import {type ChangeEvent} from 'react'
|
|
4
4
|
import {useDispatch} from 'react-redux'
|
|
5
|
+
|
|
5
6
|
import useTypedSelector from '../../hooks/useTypedSelector'
|
|
6
7
|
import {searchActions} from '../../modules/search'
|
|
7
8
|
|
|
8
9
|
const TextInputSearch = () => {
|
|
9
10
|
// Redux
|
|
10
|
-
const searchQuery = useTypedSelector(state => state.search.query)
|
|
11
|
+
const searchQuery = useTypedSelector((state) => state.search.query)
|
|
11
12
|
|
|
12
13
|
// Redux
|
|
13
14
|
const dispatch = useDispatch()
|
|
@@ -46,7 +47,7 @@ const TextInputSearch = () => {
|
|
|
46
47
|
right: 0,
|
|
47
48
|
top: 0,
|
|
48
49
|
width: '2em',
|
|
49
|
-
zIndex: 1 // force stacking context
|
|
50
|
+
zIndex: 1, // force stacking context
|
|
50
51
|
}}
|
|
51
52
|
>
|
|
52
53
|
<CloseIcon />
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import {describe, expect, it} from 'vitest'
|
|
2
|
-
|
|
2
|
+
|
|
3
3
|
import {renderWithProviders} from '../../__tests__/fixtures/renderWithProviders'
|
|
4
4
|
import {initialState as assetsInitialState} from '../../modules/assets'
|
|
5
|
+
import UploadDropzone from './index'
|
|
5
6
|
|
|
6
7
|
describe('UploadDropzone', () => {
|
|
7
8
|
it('still renders file input when directUploads is false (dropzone in disabled mode)', () => {
|
|
@@ -12,9 +13,9 @@ describe('UploadDropzone', () => {
|
|
|
12
13
|
{
|
|
13
14
|
toolOptions: {creditLine: {enabled: false}, directUploads: false},
|
|
14
15
|
preloaded: {
|
|
15
|
-
assets: {...assetsInitialState, assetTypes: ['image', 'file']}
|
|
16
|
-
}
|
|
17
|
-
}
|
|
16
|
+
assets: {...assetsInitialState, assetTypes: ['image', 'file']},
|
|
17
|
+
},
|
|
18
|
+
},
|
|
18
19
|
)
|
|
19
20
|
|
|
20
21
|
expect(container.querySelector('input[type="file"]')).toBeTruthy()
|
|
@@ -28,9 +29,9 @@ describe('UploadDropzone', () => {
|
|
|
28
29
|
{
|
|
29
30
|
toolOptions: {creditLine: {enabled: false}, directUploads: true},
|
|
30
31
|
preloaded: {
|
|
31
|
-
assets: {...assetsInitialState, assetTypes: ['image', 'file']}
|
|
32
|
-
}
|
|
33
|
-
}
|
|
32
|
+
assets: {...assetsInitialState, assetTypes: ['image', 'file']},
|
|
33
|
+
},
|
|
34
|
+
},
|
|
34
35
|
)
|
|
35
36
|
|
|
36
37
|
const input = container.querySelector('input[type="file"]')
|