sanity-plugin-media 2.2.5 → 2.3.1
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/dist/index.d.ts +16 -3
- package/dist/index.esm.js +64 -7
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +63 -6
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/components/UploadDropzone/index.tsx +22 -2
- package/src/contexts/ToolOptionsContext.tsx +32 -0
- package/src/index.ts +2 -44
- package/src/plugin.tsx +53 -0
- package/src/types/index.ts +4 -0
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {white} from '@sanity/color'
|
|
2
2
|
import {Flex, Text} from '@sanity/ui'
|
|
3
3
|
import React, {ReactNode} from 'react'
|
|
4
|
-
import {DropEvent, useDropzone} from 'react-dropzone'
|
|
4
|
+
import {DropEvent, DropzoneOptions, useDropzone} from 'react-dropzone'
|
|
5
5
|
import {useDispatch} from 'react-redux'
|
|
6
6
|
import styled from 'styled-components'
|
|
7
7
|
import {useAssetSourceActions} from '../../contexts/AssetSourceDispatchContext'
|
|
@@ -9,6 +9,7 @@ import {DropzoneDispatchProvider} from '../../contexts/DropzoneDispatchContext'
|
|
|
9
9
|
import useTypedSelector from '../../hooks/useTypedSelector'
|
|
10
10
|
import {notificationsActions} from '../../modules/notifications'
|
|
11
11
|
import {uploadsActions} from '../../modules/uploads'
|
|
12
|
+
import {useToolOptions} from '../../contexts/ToolOptionsContext'
|
|
12
13
|
|
|
13
14
|
type Props = {
|
|
14
15
|
children: ReactNode
|
|
@@ -62,6 +63,10 @@ async function filterFiles(fileList: FileList) {
|
|
|
62
63
|
const UploadDropzone = (props: Props) => {
|
|
63
64
|
const {children} = props
|
|
64
65
|
|
|
66
|
+
const {
|
|
67
|
+
dropzone: {maxSize}
|
|
68
|
+
} = useToolOptions()
|
|
69
|
+
|
|
65
70
|
const {onSelect} = useAssetSourceActions()
|
|
66
71
|
|
|
67
72
|
// Redux
|
|
@@ -82,6 +87,19 @@ const UploadDropzone = (props: Props) => {
|
|
|
82
87
|
)
|
|
83
88
|
}
|
|
84
89
|
|
|
90
|
+
const handleDropRejected: DropzoneOptions['onDropRejected'] = rejections => {
|
|
91
|
+
const errorCodes = rejections.flatMap(({errors}) => errors.map(({code}) => code))
|
|
92
|
+
|
|
93
|
+
if (errorCodes.includes('file-too-large')) {
|
|
94
|
+
dispatch(
|
|
95
|
+
notificationsActions.add({
|
|
96
|
+
status: 'error',
|
|
97
|
+
title: 'One or more files exceed the maximum upload size.'
|
|
98
|
+
})
|
|
99
|
+
)
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
85
103
|
// Use custom file selector to obtain files on file drop + change events (excluding folders and packages)
|
|
86
104
|
const handleFileGetter = async (event: DropEvent) => {
|
|
87
105
|
let fileList: FileList | undefined
|
|
@@ -123,7 +141,9 @@ const UploadDropzone = (props: Props) => {
|
|
|
123
141
|
// HACK: Disable drag and drop functionality when in a selecting context
|
|
124
142
|
// (This is currently due to Sanity's native image input taking precedence with drag and drop)
|
|
125
143
|
noDrag: !!onSelect,
|
|
126
|
-
onDrop: handleDrop
|
|
144
|
+
onDrop: handleDrop,
|
|
145
|
+
maxSize,
|
|
146
|
+
onDropRejected: handleDropRejected
|
|
127
147
|
})
|
|
128
148
|
|
|
129
149
|
return (
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import {MediaToolOptions} from '@types'
|
|
2
|
+
import React, {PropsWithChildren, createContext, useContext, useMemo} from 'react'
|
|
3
|
+
import {DropzoneOptions} from 'react-dropzone'
|
|
4
|
+
|
|
5
|
+
type ContextProps = {
|
|
6
|
+
dropzone: Pick<DropzoneOptions, 'maxSize'>
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const ToolOptionsContext = createContext<ContextProps | null>(null)
|
|
10
|
+
|
|
11
|
+
type Props = {
|
|
12
|
+
options?: MediaToolOptions | void
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export const ToolOptionsProvider = ({options, children}: PropsWithChildren<Props>) => {
|
|
16
|
+
const value = useMemo<ContextProps>(
|
|
17
|
+
() => ({dropzone: {maxSize: options?.maximumUploadSize}}),
|
|
18
|
+
[options?.maximumUploadSize]
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
return <ToolOptionsContext.Provider value={value}>{children}</ToolOptionsContext.Provider>
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export const useToolOptions = () => {
|
|
25
|
+
const context = useContext(ToolOptionsContext)
|
|
26
|
+
|
|
27
|
+
if (!context) {
|
|
28
|
+
throw new Error('useToolOptions must be used within an ToolOptionsProvider')
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return context
|
|
32
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -1,44 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
import type {AssetSource} from 'sanity'
|
|
4
|
-
import FormBuilderTool from './components/FormBuilderTool'
|
|
5
|
-
import Tool from './components/Tool'
|
|
6
|
-
import mediaTag from './schemas/tag'
|
|
7
|
-
|
|
8
|
-
const plugin = {
|
|
9
|
-
icon: ImageIcon,
|
|
10
|
-
name: 'media',
|
|
11
|
-
title: 'Media'
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export const mediaAssetSource: AssetSource = {
|
|
15
|
-
...plugin,
|
|
16
|
-
component: FormBuilderTool
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
const tool = {
|
|
20
|
-
...plugin,
|
|
21
|
-
component: Tool
|
|
22
|
-
} as SanityTool
|
|
23
|
-
|
|
24
|
-
export const media = definePlugin({
|
|
25
|
-
name: 'media',
|
|
26
|
-
form: {
|
|
27
|
-
file: {
|
|
28
|
-
assetSources: prev => {
|
|
29
|
-
return [...prev, mediaAssetSource]
|
|
30
|
-
}
|
|
31
|
-
},
|
|
32
|
-
image: {
|
|
33
|
-
assetSources: prev => {
|
|
34
|
-
return [...prev, mediaAssetSource]
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
},
|
|
38
|
-
schema: {
|
|
39
|
-
types: [mediaTag]
|
|
40
|
-
},
|
|
41
|
-
tools: prev => {
|
|
42
|
-
return [...prev, tool]
|
|
43
|
-
}
|
|
44
|
-
})
|
|
1
|
+
export {media, mediaAssetSource} from './plugin'
|
|
2
|
+
export type {MediaToolOptions} from '@types'
|
package/src/plugin.tsx
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import {AssetSource, Tool as SanityTool, definePlugin} from 'sanity'
|
|
3
|
+
import {ImageIcon} from '@sanity/icons'
|
|
4
|
+
import FormBuilderTool from './components/FormBuilderTool'
|
|
5
|
+
import Tool from './components/Tool'
|
|
6
|
+
import mediaTag from './schemas/tag'
|
|
7
|
+
import {MediaToolOptions} from '@types'
|
|
8
|
+
import {ToolOptionsProvider} from './contexts/ToolOptionsContext'
|
|
9
|
+
|
|
10
|
+
const plugin = {
|
|
11
|
+
icon: ImageIcon,
|
|
12
|
+
name: 'media',
|
|
13
|
+
title: 'Media'
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export const mediaAssetSource = {
|
|
17
|
+
...plugin,
|
|
18
|
+
component: FormBuilderTool
|
|
19
|
+
} satisfies AssetSource
|
|
20
|
+
|
|
21
|
+
const tool = {
|
|
22
|
+
...plugin,
|
|
23
|
+
component: Tool
|
|
24
|
+
} satisfies SanityTool
|
|
25
|
+
|
|
26
|
+
export const media = definePlugin<MediaToolOptions | void>(options => ({
|
|
27
|
+
name: 'media',
|
|
28
|
+
studio: {
|
|
29
|
+
components: {
|
|
30
|
+
layout: props => (
|
|
31
|
+
<ToolOptionsProvider options={options}>{props.renderDefault(props)}</ToolOptionsProvider>
|
|
32
|
+
)
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
form: {
|
|
36
|
+
file: {
|
|
37
|
+
assetSources: prev => {
|
|
38
|
+
return [...prev, mediaAssetSource]
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
image: {
|
|
42
|
+
assetSources: prev => {
|
|
43
|
+
return [...prev, mediaAssetSource]
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
schema: {
|
|
48
|
+
types: [mediaTag]
|
|
49
|
+
},
|
|
50
|
+
tools: prev => {
|
|
51
|
+
return [...prev, tool]
|
|
52
|
+
}
|
|
53
|
+
}))
|
package/src/types/index.ts
CHANGED
|
@@ -10,6 +10,10 @@ import * as z from 'zod'
|
|
|
10
10
|
import {assetFormSchema, tagFormSchema, tagOptionSchema} from '../formSchema'
|
|
11
11
|
import {RootReducerState} from '../modules/types'
|
|
12
12
|
|
|
13
|
+
export type MediaToolOptions = {
|
|
14
|
+
maximumUploadSize?: number
|
|
15
|
+
}
|
|
16
|
+
|
|
13
17
|
type CustomFields = {
|
|
14
18
|
altText?: string
|
|
15
19
|
description?: string
|