sanity-plugin-media 4.3.1 → 4.3.3
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.mjs → index.cjs} +1115 -1242
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +462 -0
- package/dist/index.d.ts +263 -195
- package/dist/index.js +1125 -1237
- package/dist/index.js.map +1 -1
- package/package.json +45 -68
- 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
- package/dist/index.d.mts +0 -394
- package/dist/index.mjs.map +0 -1
|
@@ -4,12 +4,13 @@ import {type ReactNode} from 'react'
|
|
|
4
4
|
import {type DropEvent, type DropzoneOptions, useDropzone} from 'react-dropzone'
|
|
5
5
|
import {useDispatch} from 'react-redux'
|
|
6
6
|
import {styled} from 'styled-components'
|
|
7
|
+
|
|
7
8
|
import {useAssetSourceActions} from '../../contexts/AssetSourceDispatchContext'
|
|
8
9
|
import {DropzoneDispatchProvider} from '../../contexts/DropzoneDispatchContext'
|
|
10
|
+
import {useToolOptions} from '../../contexts/ToolOptionsContext'
|
|
9
11
|
import useTypedSelector from '../../hooks/useTypedSelector'
|
|
10
12
|
import {notificationsActions} from '../../modules/notifications'
|
|
11
13
|
import {uploadsActions} from '../../modules/uploads'
|
|
12
|
-
import {useToolOptions} from '../../contexts/ToolOptionsContext'
|
|
13
14
|
|
|
14
15
|
type Props = {
|
|
15
16
|
children: ReactNode
|
|
@@ -65,38 +66,38 @@ const UploadDropzone = (props: Props) => {
|
|
|
65
66
|
|
|
66
67
|
const {
|
|
67
68
|
dropzone: {maxSize},
|
|
68
|
-
directUploads
|
|
69
|
+
directUploads,
|
|
69
70
|
} = useToolOptions()
|
|
70
71
|
|
|
71
72
|
const {onSelect} = useAssetSourceActions()
|
|
72
73
|
|
|
73
74
|
// Redux
|
|
74
75
|
const dispatch = useDispatch()
|
|
75
|
-
const assetTypes = useTypedSelector(state => state.assets.assetTypes)
|
|
76
|
+
const assetTypes = useTypedSelector((state) => state.assets.assetTypes)
|
|
76
77
|
|
|
77
78
|
const isImageAssetType = assetTypes.length === 1 && assetTypes[0] === 'image'
|
|
78
79
|
|
|
79
80
|
// Callbacks
|
|
80
81
|
const handleDrop = async (acceptedFiles: File[]) => {
|
|
81
|
-
acceptedFiles.forEach(file =>
|
|
82
|
+
acceptedFiles.forEach((file) =>
|
|
82
83
|
dispatch(
|
|
83
84
|
uploadsActions.uploadRequest({
|
|
84
85
|
file,
|
|
85
|
-
forceAsAssetType: assetTypes.length === 1 ? assetTypes[0] : undefined
|
|
86
|
-
})
|
|
87
|
-
)
|
|
86
|
+
forceAsAssetType: assetTypes.length === 1 ? assetTypes[0] : undefined,
|
|
87
|
+
}),
|
|
88
|
+
),
|
|
88
89
|
)
|
|
89
90
|
}
|
|
90
91
|
|
|
91
|
-
const handleDropRejected: DropzoneOptions['onDropRejected'] = rejections => {
|
|
92
|
+
const handleDropRejected: DropzoneOptions['onDropRejected'] = (rejections) => {
|
|
92
93
|
const errorCodes = rejections.flatMap(({errors}) => errors.map(({code}) => code))
|
|
93
94
|
|
|
94
95
|
if (errorCodes.includes('file-too-large')) {
|
|
95
96
|
dispatch(
|
|
96
97
|
notificationsActions.add({
|
|
97
98
|
status: 'error',
|
|
98
|
-
title: 'One or more files exceed the maximum upload size.'
|
|
99
|
-
})
|
|
99
|
+
title: 'One or more files exceed the maximum upload size.',
|
|
100
|
+
}),
|
|
100
101
|
)
|
|
101
102
|
}
|
|
102
103
|
}
|
|
@@ -126,8 +127,8 @@ const UploadDropzone = (props: Props) => {
|
|
|
126
127
|
dispatch(
|
|
127
128
|
notificationsActions.add({
|
|
128
129
|
status: 'error',
|
|
129
|
-
title: `Unable to upload some items (folders and packages aren't supported)
|
|
130
|
-
})
|
|
130
|
+
title: `Unable to upload some items (folders and packages aren't supported)`,
|
|
131
|
+
}),
|
|
131
132
|
)
|
|
132
133
|
}
|
|
133
134
|
|
|
@@ -145,7 +146,7 @@ const UploadDropzone = (props: Props) => {
|
|
|
145
146
|
onDrop: handleDrop,
|
|
146
147
|
maxSize,
|
|
147
148
|
onDropRejected: handleDropRejected,
|
|
148
|
-
disabled: !directUploads
|
|
149
|
+
disabled: !directUploads,
|
|
149
150
|
})
|
|
150
151
|
|
|
151
152
|
return (
|
package/src/config/orders.ts
CHANGED
|
@@ -3,24 +3,24 @@ import type {OrderDirection} from '../types'
|
|
|
3
3
|
const ORDER_DICTIONARY: Record<string, {asc: string; desc: string}> = {
|
|
4
4
|
_createdAt: {
|
|
5
5
|
asc: 'Last created: Oldest first',
|
|
6
|
-
desc: 'Last created: Newest first'
|
|
6
|
+
desc: 'Last created: Newest first',
|
|
7
7
|
},
|
|
8
8
|
_updatedAt: {
|
|
9
9
|
asc: 'Last updated: Oldest first',
|
|
10
|
-
desc: 'Last updated: Newest first'
|
|
10
|
+
desc: 'Last updated: Newest first',
|
|
11
11
|
},
|
|
12
12
|
mimeType: {
|
|
13
13
|
asc: 'MIME type: A to Z',
|
|
14
|
-
desc: 'MIME type: Z to A'
|
|
14
|
+
desc: 'MIME type: Z to A',
|
|
15
15
|
},
|
|
16
16
|
originalFilename: {
|
|
17
17
|
asc: 'File name: A to Z',
|
|
18
|
-
desc: 'File name: Z to A'
|
|
18
|
+
desc: 'File name: Z to A',
|
|
19
19
|
},
|
|
20
20
|
size: {
|
|
21
21
|
asc: 'File size: Smallest first',
|
|
22
|
-
desc: 'File size: Largest first'
|
|
23
|
-
}
|
|
22
|
+
desc: 'File size: Largest first',
|
|
23
|
+
},
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
export const getOrderTitle = (field: string, direction: OrderDirection): string => {
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
+
import groq from 'groq'
|
|
2
|
+
|
|
1
3
|
import type {
|
|
2
4
|
SearchFacetDivider,
|
|
3
5
|
SearchFacetInputProps,
|
|
4
6
|
SearchFacetName,
|
|
5
|
-
SearchFacetOperators
|
|
7
|
+
SearchFacetOperators,
|
|
6
8
|
} from '../types'
|
|
7
|
-
import groq from 'groq'
|
|
8
9
|
|
|
9
10
|
export const divider: SearchFacetDivider = {type: 'divider'}
|
|
10
11
|
|
|
@@ -17,7 +18,7 @@ export const inputs: Record<SearchFacetName, SearchFacetInputProps> = {
|
|
|
17
18
|
operatorTypes: ['empty', 'notEmpty', null, 'includes', 'doesNotInclude'],
|
|
18
19
|
title: 'Alt text',
|
|
19
20
|
type: 'string',
|
|
20
|
-
value: ''
|
|
21
|
+
value: '',
|
|
21
22
|
},
|
|
22
23
|
creditLine: {
|
|
23
24
|
assetTypes: ['file', 'image'],
|
|
@@ -27,7 +28,7 @@ export const inputs: Record<SearchFacetName, SearchFacetInputProps> = {
|
|
|
27
28
|
operatorTypes: ['empty', 'notEmpty', null, 'includes', 'doesNotInclude'],
|
|
28
29
|
title: 'Credit',
|
|
29
30
|
type: 'string',
|
|
30
|
-
value: ''
|
|
31
|
+
value: '',
|
|
31
32
|
},
|
|
32
33
|
description: {
|
|
33
34
|
assetTypes: ['file', 'image'],
|
|
@@ -37,7 +38,7 @@ export const inputs: Record<SearchFacetName, SearchFacetInputProps> = {
|
|
|
37
38
|
operatorTypes: ['empty', 'notEmpty', null, 'includes', 'doesNotInclude'],
|
|
38
39
|
title: 'Description',
|
|
39
40
|
type: 'string',
|
|
40
|
-
value: ''
|
|
41
|
+
value: '',
|
|
41
42
|
},
|
|
42
43
|
fileName: {
|
|
43
44
|
assetTypes: ['file', 'image'],
|
|
@@ -47,7 +48,7 @@ export const inputs: Record<SearchFacetName, SearchFacetInputProps> = {
|
|
|
47
48
|
operatorTypes: ['includes', 'doesNotInclude'],
|
|
48
49
|
title: 'File name',
|
|
49
50
|
type: 'string',
|
|
50
|
-
value: ''
|
|
51
|
+
value: '',
|
|
51
52
|
},
|
|
52
53
|
height: {
|
|
53
54
|
assetTypes: ['image'],
|
|
@@ -60,11 +61,11 @@ export const inputs: Record<SearchFacetName, SearchFacetInputProps> = {
|
|
|
60
61
|
'lessThan',
|
|
61
62
|
'lessThanOrEqualTo',
|
|
62
63
|
null,
|
|
63
|
-
'equalTo'
|
|
64
|
+
'equalTo',
|
|
64
65
|
],
|
|
65
66
|
title: 'Height',
|
|
66
67
|
type: 'number',
|
|
67
|
-
value: 400
|
|
68
|
+
value: 400,
|
|
68
69
|
},
|
|
69
70
|
inCurrentDocument: {
|
|
70
71
|
assetTypes: ['file', 'image'],
|
|
@@ -74,18 +75,18 @@ export const inputs: Record<SearchFacetName, SearchFacetInputProps> = {
|
|
|
74
75
|
{
|
|
75
76
|
name: 'true',
|
|
76
77
|
title: 'True',
|
|
77
|
-
value: groq`_id in $documentAssetIds
|
|
78
|
+
value: groq`_id in $documentAssetIds`,
|
|
78
79
|
},
|
|
79
80
|
{
|
|
80
81
|
name: 'false',
|
|
81
82
|
title: 'False',
|
|
82
|
-
value: groq`!(_id in $documentAssetIds)
|
|
83
|
-
}
|
|
83
|
+
value: groq`!(_id in $documentAssetIds)`,
|
|
84
|
+
},
|
|
84
85
|
],
|
|
85
86
|
selectOnly: true,
|
|
86
87
|
title: 'In use in current document',
|
|
87
88
|
type: 'select',
|
|
88
|
-
value: 'true'
|
|
89
|
+
value: 'true',
|
|
89
90
|
},
|
|
90
91
|
inUse: {
|
|
91
92
|
assetTypes: ['file', 'image'],
|
|
@@ -95,17 +96,17 @@ export const inputs: Record<SearchFacetName, SearchFacetInputProps> = {
|
|
|
95
96
|
{
|
|
96
97
|
name: 'true',
|
|
97
98
|
title: 'True',
|
|
98
|
-
value: groq`count(*[references(^._id)]) > 0
|
|
99
|
+
value: groq`count(*[references(^._id)]) > 0`,
|
|
99
100
|
},
|
|
100
101
|
{
|
|
101
102
|
name: 'false',
|
|
102
103
|
title: 'False',
|
|
103
|
-
value: groq`count(*[references(^._id)]) == 0
|
|
104
|
-
}
|
|
104
|
+
value: groq`count(*[references(^._id)]) == 0`,
|
|
105
|
+
},
|
|
105
106
|
],
|
|
106
107
|
title: 'In use',
|
|
107
108
|
type: 'select',
|
|
108
|
-
value: 'true'
|
|
109
|
+
value: 'true',
|
|
109
110
|
},
|
|
110
111
|
isOpaque: {
|
|
111
112
|
assetTypes: ['image'],
|
|
@@ -116,17 +117,17 @@ export const inputs: Record<SearchFacetName, SearchFacetInputProps> = {
|
|
|
116
117
|
{
|
|
117
118
|
name: 'true',
|
|
118
119
|
title: 'True',
|
|
119
|
-
value: `false
|
|
120
|
+
value: `false`,
|
|
120
121
|
},
|
|
121
122
|
{
|
|
122
123
|
name: 'false',
|
|
123
124
|
title: 'False',
|
|
124
|
-
value: `true
|
|
125
|
-
}
|
|
125
|
+
value: `true`,
|
|
126
|
+
},
|
|
126
127
|
],
|
|
127
128
|
title: 'Has transparency',
|
|
128
129
|
type: 'select',
|
|
129
|
-
value: 'true'
|
|
130
|
+
value: 'true',
|
|
130
131
|
},
|
|
131
132
|
orientation: {
|
|
132
133
|
assetTypes: ['image'],
|
|
@@ -137,22 +138,22 @@ export const inputs: Record<SearchFacetName, SearchFacetInputProps> = {
|
|
|
137
138
|
{
|
|
138
139
|
name: 'portrait',
|
|
139
140
|
title: 'Portrait',
|
|
140
|
-
value: 'metadata.dimensions.aspectRatio < 1'
|
|
141
|
+
value: 'metadata.dimensions.aspectRatio < 1',
|
|
141
142
|
},
|
|
142
143
|
{
|
|
143
144
|
name: 'landscape',
|
|
144
145
|
title: 'Landscape',
|
|
145
|
-
value: 'metadata.dimensions.aspectRatio > 1'
|
|
146
|
+
value: 'metadata.dimensions.aspectRatio > 1',
|
|
146
147
|
},
|
|
147
148
|
{
|
|
148
149
|
name: 'square',
|
|
149
150
|
title: 'Square',
|
|
150
|
-
value: 'metadata.dimensions.aspectRatio == 1'
|
|
151
|
-
}
|
|
151
|
+
value: 'metadata.dimensions.aspectRatio == 1',
|
|
152
|
+
},
|
|
152
153
|
],
|
|
153
154
|
title: 'Orientation',
|
|
154
155
|
type: 'select',
|
|
155
|
-
value: 'portrait'
|
|
156
|
+
value: 'portrait',
|
|
156
157
|
},
|
|
157
158
|
size: {
|
|
158
159
|
assetTypes: ['file', 'image'],
|
|
@@ -162,13 +163,13 @@ export const inputs: Record<SearchFacetName, SearchFacetInputProps> = {
|
|
|
162
163
|
{
|
|
163
164
|
name: 'kb',
|
|
164
165
|
title: 'KB',
|
|
165
|
-
fieldModifier: fieldName => `round(${fieldName} / 1000)
|
|
166
|
+
fieldModifier: (fieldName) => `round(${fieldName} / 1000)`,
|
|
166
167
|
},
|
|
167
168
|
{
|
|
168
169
|
name: 'mb',
|
|
169
170
|
title: 'MB',
|
|
170
|
-
fieldModifier: fieldName => `round(${fieldName} / 1000000)
|
|
171
|
-
}
|
|
171
|
+
fieldModifier: (fieldName) => `round(${fieldName} / 1000000)`,
|
|
172
|
+
},
|
|
172
173
|
],
|
|
173
174
|
name: 'size',
|
|
174
175
|
operatorType: 'greaterThan',
|
|
@@ -178,11 +179,11 @@ export const inputs: Record<SearchFacetName, SearchFacetInputProps> = {
|
|
|
178
179
|
'lessThan',
|
|
179
180
|
'lessThanOrEqualTo',
|
|
180
181
|
null,
|
|
181
|
-
'equalTo'
|
|
182
|
+
'equalTo',
|
|
182
183
|
],
|
|
183
184
|
title: 'File size',
|
|
184
185
|
type: 'number',
|
|
185
|
-
value: 0
|
|
186
|
+
value: 0,
|
|
186
187
|
},
|
|
187
188
|
tag: {
|
|
188
189
|
assetTypes: ['file', 'image'],
|
|
@@ -191,7 +192,7 @@ export const inputs: Record<SearchFacetName, SearchFacetInputProps> = {
|
|
|
191
192
|
operatorType: 'references',
|
|
192
193
|
operatorTypes: ['references', 'doesNotReference', null, 'empty', 'notEmpty'],
|
|
193
194
|
title: 'Tags',
|
|
194
|
-
type: 'searchable'
|
|
195
|
+
type: 'searchable',
|
|
195
196
|
},
|
|
196
197
|
title: {
|
|
197
198
|
assetTypes: ['file', 'image'],
|
|
@@ -201,7 +202,7 @@ export const inputs: Record<SearchFacetName, SearchFacetInputProps> = {
|
|
|
201
202
|
operatorTypes: ['empty', 'notEmpty', null, 'includes', 'doesNotInclude'],
|
|
202
203
|
title: 'Title',
|
|
203
204
|
type: 'string',
|
|
204
|
-
value: ''
|
|
205
|
+
value: '',
|
|
205
206
|
},
|
|
206
207
|
type: {
|
|
207
208
|
assetTypes: ['file', 'image'],
|
|
@@ -212,27 +213,27 @@ export const inputs: Record<SearchFacetName, SearchFacetInputProps> = {
|
|
|
212
213
|
{
|
|
213
214
|
name: 'image',
|
|
214
215
|
title: 'Image',
|
|
215
|
-
value: 'mimeType match "image*"'
|
|
216
|
+
value: 'mimeType match "image*"',
|
|
216
217
|
},
|
|
217
218
|
{
|
|
218
219
|
name: 'video',
|
|
219
220
|
title: 'Video',
|
|
220
|
-
value: 'mimeType match "video*"'
|
|
221
|
+
value: 'mimeType match "video*"',
|
|
221
222
|
},
|
|
222
223
|
{
|
|
223
224
|
name: 'audio',
|
|
224
225
|
title: 'Audio',
|
|
225
|
-
value: 'mimeType match "audio*"'
|
|
226
|
+
value: 'mimeType match "audio*"',
|
|
226
227
|
},
|
|
227
228
|
{
|
|
228
229
|
name: 'pdf',
|
|
229
230
|
title: 'PDF',
|
|
230
|
-
value: 'mimeType == "application/pdf"'
|
|
231
|
-
}
|
|
231
|
+
value: 'mimeType == "application/pdf"',
|
|
232
|
+
},
|
|
232
233
|
],
|
|
233
234
|
title: 'File type',
|
|
234
235
|
type: 'select',
|
|
235
|
-
value: 'image'
|
|
236
|
+
value: 'image',
|
|
236
237
|
},
|
|
237
238
|
width: {
|
|
238
239
|
assetTypes: ['image'],
|
|
@@ -245,67 +246,67 @@ export const inputs: Record<SearchFacetName, SearchFacetInputProps> = {
|
|
|
245
246
|
'lessThan',
|
|
246
247
|
'lessThanOrEqualTo',
|
|
247
248
|
null,
|
|
248
|
-
'equalTo'
|
|
249
|
+
'equalTo',
|
|
249
250
|
],
|
|
250
251
|
title: 'Width',
|
|
251
252
|
type: 'number',
|
|
252
|
-
value: 400
|
|
253
|
-
}
|
|
253
|
+
value: 400,
|
|
254
|
+
},
|
|
254
255
|
}
|
|
255
256
|
|
|
256
257
|
export const operators: SearchFacetOperators = {
|
|
257
258
|
doesNotInclude: {
|
|
258
259
|
fn: (value, field) => (value ? `!(${field} match '*${value}*')` : undefined),
|
|
259
|
-
label: 'does not include'
|
|
260
|
+
label: 'does not include',
|
|
260
261
|
},
|
|
261
262
|
doesNotReference: {
|
|
262
263
|
fn: (value, _field) => (value ? `!references('${value}')` : undefined),
|
|
263
|
-
label: 'does not include'
|
|
264
|
+
label: 'does not include',
|
|
264
265
|
},
|
|
265
266
|
empty: {
|
|
266
267
|
fn: (_value, field) => `!defined(${field})`,
|
|
267
268
|
hideInput: true,
|
|
268
|
-
label: 'is empty'
|
|
269
|
+
label: 'is empty',
|
|
269
270
|
},
|
|
270
271
|
equalTo: {
|
|
271
272
|
fn: (value, field) => (value ? `${field} == ${value}` : undefined),
|
|
272
|
-
label: 'is equal to'
|
|
273
|
+
label: 'is equal to',
|
|
273
274
|
},
|
|
274
275
|
greaterThan: {
|
|
275
276
|
fn: (value, field) => (value ? `${field} > ${value}` : undefined),
|
|
276
|
-
label: 'is greater than'
|
|
277
|
+
label: 'is greater than',
|
|
277
278
|
},
|
|
278
279
|
greaterThanOrEqualTo: {
|
|
279
280
|
fn: (value, field) => (value ? `${field} >= ${value}` : undefined),
|
|
280
|
-
label: 'is greater than or equal to'
|
|
281
|
+
label: 'is greater than or equal to',
|
|
281
282
|
},
|
|
282
283
|
includes: {
|
|
283
284
|
fn: (value, field) => (value ? `${field} match '*${value}*'` : undefined),
|
|
284
|
-
label: 'includes'
|
|
285
|
+
label: 'includes',
|
|
285
286
|
},
|
|
286
287
|
is: {
|
|
287
288
|
fn: (value, _field) => `${value}`,
|
|
288
|
-
label: 'is'
|
|
289
|
+
label: 'is',
|
|
289
290
|
},
|
|
290
291
|
isNot: {
|
|
291
292
|
fn: (value, _field) => `!(${value})`,
|
|
292
|
-
label: 'is not'
|
|
293
|
+
label: 'is not',
|
|
293
294
|
},
|
|
294
295
|
lessThan: {
|
|
295
296
|
fn: (value, field) => (value ? `${field} < ${value}` : undefined),
|
|
296
|
-
label: 'is less than'
|
|
297
|
+
label: 'is less than',
|
|
297
298
|
},
|
|
298
299
|
lessThanOrEqualTo: {
|
|
299
300
|
fn: (value, field) => (value ? `${field} <= ${value}` : undefined),
|
|
300
|
-
label: 'is less than or equal to'
|
|
301
|
+
label: 'is less than or equal to',
|
|
301
302
|
},
|
|
302
303
|
notEmpty: {
|
|
303
304
|
fn: (_value, field) => `defined(${field})`,
|
|
304
305
|
hideInput: true,
|
|
305
|
-
label: 'is not empty'
|
|
306
|
+
label: 'is not empty',
|
|
306
307
|
},
|
|
307
308
|
references: {
|
|
308
309
|
fn: (value, _field) => (value ? `references('${value}')` : undefined),
|
|
309
|
-
label: 'includes'
|
|
310
|
-
}
|
|
310
|
+
label: 'includes',
|
|
311
|
+
},
|
|
311
312
|
}
|
package/src/constants.ts
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
import type {AssetSourceComponentProps} from 'sanity'
|
|
2
|
+
|
|
3
|
+
import {divider, inputs} from './config/searchFacets'
|
|
2
4
|
import type {
|
|
3
5
|
SearchFacetInputProps,
|
|
4
6
|
SearchFacetDivider,
|
|
5
7
|
SearchFacetGroup,
|
|
6
|
-
OrderDirection
|
|
8
|
+
OrderDirection,
|
|
7
9
|
} from './types'
|
|
8
|
-
import {divider, inputs} from './config/searchFacets'
|
|
9
10
|
|
|
10
11
|
export const SUPPORTED_ASSET_TYPES = [
|
|
11
12
|
'file',
|
|
12
|
-
'image'
|
|
13
|
+
'image',
|
|
13
14
|
] as const satisfies AssetSourceComponentProps['assetType'][]
|
|
14
15
|
|
|
15
16
|
// Sort order dropdown options
|
|
@@ -17,42 +18,42 @@ export const SUPPORTED_ASSET_TYPES = [
|
|
|
17
18
|
export const ORDER_OPTIONS: ({direction: OrderDirection; field: string} | null)[] = [
|
|
18
19
|
{
|
|
19
20
|
direction: 'desc',
|
|
20
|
-
field: '_createdAt'
|
|
21
|
+
field: '_createdAt',
|
|
21
22
|
},
|
|
22
23
|
{
|
|
23
24
|
direction: 'asc',
|
|
24
|
-
field: '_createdAt'
|
|
25
|
+
field: '_createdAt',
|
|
25
26
|
},
|
|
26
27
|
// Divider
|
|
27
28
|
null,
|
|
28
29
|
{
|
|
29
30
|
direction: 'desc',
|
|
30
|
-
field: '_updatedAt'
|
|
31
|
+
field: '_updatedAt',
|
|
31
32
|
},
|
|
32
33
|
{
|
|
33
34
|
direction: 'asc' as OrderDirection,
|
|
34
|
-
field: '_updatedAt'
|
|
35
|
+
field: '_updatedAt',
|
|
35
36
|
},
|
|
36
37
|
// Divider
|
|
37
38
|
null,
|
|
38
39
|
{
|
|
39
40
|
direction: 'asc',
|
|
40
|
-
field: 'originalFilename'
|
|
41
|
+
field: 'originalFilename',
|
|
41
42
|
},
|
|
42
43
|
{
|
|
43
44
|
direction: 'desc',
|
|
44
|
-
field: 'originalFilename'
|
|
45
|
+
field: 'originalFilename',
|
|
45
46
|
},
|
|
46
47
|
// Divider
|
|
47
48
|
null,
|
|
48
49
|
{
|
|
49
50
|
direction: 'desc',
|
|
50
|
-
field: 'size'
|
|
51
|
+
field: 'size',
|
|
51
52
|
},
|
|
52
53
|
{
|
|
53
54
|
direction: 'asc',
|
|
54
|
-
field: 'size'
|
|
55
|
-
}
|
|
55
|
+
field: 'size',
|
|
56
|
+
},
|
|
56
57
|
]
|
|
57
58
|
|
|
58
59
|
export const FACETS: (SearchFacetDivider | SearchFacetGroup | SearchFacetInputProps)[] = [
|
|
@@ -74,12 +75,12 @@ export const FACETS: (SearchFacetDivider | SearchFacetGroup | SearchFacetInputPr
|
|
|
74
75
|
divider,
|
|
75
76
|
inputs.orientation,
|
|
76
77
|
inputs.width,
|
|
77
|
-
inputs.height
|
|
78
|
+
inputs.height,
|
|
78
79
|
]
|
|
79
80
|
|
|
80
81
|
export const GRID_TEMPLATE_COLUMNS = {
|
|
81
82
|
SMALL: '3rem 100px auto 1.5rem',
|
|
82
|
-
LARGE: '3rem 100px auto 5.5rem 5.5rem 3.5rem 8.5rem 4.75rem 2rem'
|
|
83
|
+
LARGE: '3rem 100px auto 5.5rem 5.5rem 3.5rem 8.5rem 4.75rem 2rem',
|
|
83
84
|
}
|
|
84
85
|
export const PANEL_HEIGHT = 32 // px
|
|
85
86
|
export const TAG_DOCUMENT_NAME = 'media.tag'
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import type {MediaToolOptions, Locale} from '../types'
|
|
2
1
|
import {type PropsWithChildren, createContext, useContext, useMemo} from 'react'
|
|
3
2
|
import type {DropzoneOptions} from 'react-dropzone'
|
|
4
3
|
|
|
4
|
+
import type {MediaToolOptions, Locale} from '../types'
|
|
5
|
+
|
|
5
6
|
type ContextProps = {
|
|
6
7
|
dropzone: Pick<DropzoneOptions, 'maxSize'>
|
|
7
8
|
components: MediaToolOptions['components']
|
|
@@ -30,15 +31,15 @@ export const ToolOptionsProvider = ({options, children}: PropsWithChildren<Props
|
|
|
30
31
|
return {
|
|
31
32
|
dropzone: {maxSize: options?.maximumUploadSize},
|
|
32
33
|
components: {
|
|
33
|
-
details: options?.components?.details
|
|
34
|
+
details: options?.components?.details,
|
|
34
35
|
},
|
|
35
36
|
createTagsOnUpload: options?.createTagsOnUpload ?? true,
|
|
36
37
|
creditLine: {
|
|
37
38
|
enabled: options?.creditLine?.enabled || false,
|
|
38
|
-
excludeSources: creditLineExcludeSources
|
|
39
|
+
excludeSources: creditLineExcludeSources,
|
|
39
40
|
},
|
|
40
41
|
directUploads: options?.directUploads ?? true,
|
|
41
|
-
locales: options?.locales
|
|
42
|
+
locales: options?.locales,
|
|
42
43
|
}
|
|
43
44
|
}, [
|
|
44
45
|
options?.creditLine?.enabled,
|
|
@@ -47,7 +48,7 @@ export const ToolOptionsProvider = ({options, children}: PropsWithChildren<Props
|
|
|
47
48
|
options?.creditLine?.excludeSources,
|
|
48
49
|
options?.maximumUploadSize,
|
|
49
50
|
options?.directUploads,
|
|
50
|
-
options?.locales
|
|
51
|
+
options?.locales,
|
|
51
52
|
])
|
|
52
53
|
|
|
53
54
|
return <ToolOptionsContext.Provider value={value}>{children}</ToolOptionsContext.Provider>
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// @vitest-environment node
|
|
2
2
|
|
|
3
3
|
import {describe, expect, it} from 'vitest'
|
|
4
|
+
|
|
4
5
|
import {assetFormSchema, tagFormSchema, tagOptionSchema} from './index'
|
|
5
6
|
|
|
6
7
|
describe('tagOptionSchema', () => {
|
|
@@ -28,7 +29,7 @@ describe('assetFormSchema', () => {
|
|
|
28
29
|
description: '',
|
|
29
30
|
opt: {media: {tags: null}},
|
|
30
31
|
originalFilename: 'file.png',
|
|
31
|
-
title: ''
|
|
32
|
+
title: '',
|
|
32
33
|
}
|
|
33
34
|
|
|
34
35
|
it('accepts valid asset form payload', () => {
|
|
@@ -39,8 +40,8 @@ describe('assetFormSchema', () => {
|
|
|
39
40
|
expect(
|
|
40
41
|
assetFormSchema.safeParse({
|
|
41
42
|
...base,
|
|
42
|
-
originalFilename: ' '
|
|
43
|
-
}).success
|
|
43
|
+
originalFilename: ' ',
|
|
44
|
+
}).success,
|
|
44
45
|
).toBe(false)
|
|
45
46
|
})
|
|
46
47
|
|
|
@@ -48,8 +49,8 @@ describe('assetFormSchema', () => {
|
|
|
48
49
|
expect(
|
|
49
50
|
assetFormSchema.safeParse({
|
|
50
51
|
...base,
|
|
51
|
-
opt: {media: {tags: [{label: '', value: 'v'}]}}
|
|
52
|
-
}).success
|
|
52
|
+
opt: {media: {tags: [{label: '', value: 'v'}]}},
|
|
53
|
+
}).success,
|
|
53
54
|
).toBe(false)
|
|
54
55
|
})
|
|
55
56
|
})
|
package/src/formSchema/index.ts
CHANGED
|
@@ -14,7 +14,7 @@ export function localizedStringSchema(locales?: {id: string}[]) {
|
|
|
14
14
|
|
|
15
15
|
export const tagOptionSchema = z.object({
|
|
16
16
|
label: z.string().trim().min(1, {message: 'Label cannot be empty'}),
|
|
17
|
-
value: z.string().trim().min(1, {message: 'Value cannot be empty'})
|
|
17
|
+
value: z.string().trim().min(1, {message: 'Value cannot be empty'}),
|
|
18
18
|
})
|
|
19
19
|
|
|
20
20
|
export function getAssetFormSchema(locales?: {id: string}[]) {
|
|
@@ -24,16 +24,16 @@ export function getAssetFormSchema(locales?: {id: string}[]) {
|
|
|
24
24
|
description: localizedStringSchema(locales),
|
|
25
25
|
opt: z.object({
|
|
26
26
|
media: z.object({
|
|
27
|
-
tags: z.array(tagOptionSchema).nullable()
|
|
28
|
-
})
|
|
27
|
+
tags: z.array(tagOptionSchema).nullable(),
|
|
28
|
+
}),
|
|
29
29
|
}),
|
|
30
30
|
originalFilename: z.string().trim().min(1, {message: 'Filename cannot be empty'}),
|
|
31
|
-
title: localizedStringSchema(locales)
|
|
31
|
+
title: localizedStringSchema(locales),
|
|
32
32
|
})
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
export const assetFormSchema = getAssetFormSchema()
|
|
36
36
|
|
|
37
37
|
export const tagFormSchema = z.object({
|
|
38
|
-
name: z.string().min(1, {message: 'Name cannot be empty'})
|
|
38
|
+
name: z.string().min(1, {message: 'Name cannot be empty'}),
|
|
39
39
|
})
|
|
@@ -5,11 +5,11 @@ import {useEffect, useState} from 'react'
|
|
|
5
5
|
// - create MediaQueryLists from every breakpoint defined in our sanity studio theme
|
|
6
6
|
// - for each MQL, listen to change events and return the selected breakpoint index
|
|
7
7
|
const useBreakpointIndex = (): number => {
|
|
8
|
-
const mediaQueryLists = studioTheme?.container?.map(width =>
|
|
9
|
-
window.matchMedia(`(max-width: ${width}px)`)
|
|
8
|
+
const mediaQueryLists = studioTheme?.container?.map((width) =>
|
|
9
|
+
window.matchMedia(`(max-width: ${width}px)`),
|
|
10
10
|
)
|
|
11
11
|
|
|
12
|
-
const getBreakpointIndex = () => mediaQueryLists.findIndex(mql => mql.matches)
|
|
12
|
+
const getBreakpointIndex = () => mediaQueryLists.findIndex((mql) => mql.matches)
|
|
13
13
|
|
|
14
14
|
const [value, setValue] = useState(getBreakpointIndex())
|
|
15
15
|
|
|
@@ -19,7 +19,7 @@ const useBreakpointIndex = (): number => {
|
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
// NOTE: older versions of Safari use the older `addListener` and `removeListener` methods
|
|
22
|
-
mediaQueryLists.forEach(mql => {
|
|
22
|
+
mediaQueryLists.forEach((mql) => {
|
|
23
23
|
try {
|
|
24
24
|
mql.addEventListener('change', handleBreakpoint)
|
|
25
25
|
} catch (err) {
|
|
@@ -32,10 +32,10 @@ const useBreakpointIndex = (): number => {
|
|
|
32
32
|
})
|
|
33
33
|
return () => {
|
|
34
34
|
try {
|
|
35
|
-
mediaQueryLists.forEach(mql => mql.removeEventListener('change', handleBreakpoint))
|
|
35
|
+
mediaQueryLists.forEach((mql) => mql.removeEventListener('change', handleBreakpoint))
|
|
36
36
|
} catch (err) {
|
|
37
37
|
try {
|
|
38
|
-
mediaQueryLists.forEach(mql => mql.removeListener(handleBreakpoint))
|
|
38
|
+
mediaQueryLists.forEach((mql) => mql.removeListener(handleBreakpoint))
|
|
39
39
|
} catch (_err) {
|
|
40
40
|
// Do nothing
|
|
41
41
|
}
|