sanity-plugin-media 2.2.4 → 2.3.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.2.4",
3
+ "version": "2.3.0",
4
4
  "description": "This version of `sanity-plugin-media` is for Sanity Studio V3.",
5
5
  "keywords": [
6
6
  "sanity",
@@ -61,7 +61,7 @@
61
61
  "@hookform/resolvers": "^3.1.1",
62
62
  "@reduxjs/toolkit": "^1.9.0",
63
63
  "@sanity/incompatible-plugin": "^1.0.4",
64
- "@sanity/ui": "^1.7.0",
64
+ "@sanity/ui": "^1.9.3",
65
65
  "@sanity/uuid": "^3.0.1",
66
66
  "@tanem/react-nprogress": "^5.0.0",
67
67
  "copy-to-clipboard": "^3.3.1",
@@ -121,10 +121,11 @@
121
121
  "typescript": "^4.8.4"
122
122
  },
123
123
  "peerDependencies": {
124
+ "@sanity/ui": "^1.0 || ^2.0",
124
125
  "react": "^18",
125
126
  "react-dom": "^18",
126
127
  "sanity": "^3.0.0",
127
- "styled-components": "^5.3.3"
128
+ "styled-components": "^5.0 || ^6.0"
128
129
  },
129
130
  "engines": {
130
131
  "node": ">=14"
@@ -1,12 +1,17 @@
1
1
  import {Flex} from '@sanity/ui'
2
- import React from 'react'
2
+ import React, {ComponentProps} from 'react'
3
3
  import Browser from '../Browser'
4
+ import {ToolOptionsProvider} from '../../contexts/ToolOptionsContext'
5
+ import {Tool as SanityTool} from 'sanity'
6
+ import {MediaToolOptions} from '@types'
4
7
 
5
- const Tool = () => {
8
+ const Tool = ({tool: {options}}: ComponentProps<SanityTool<MediaToolOptions>['component']>) => {
6
9
  return (
7
- <Flex direction="column" height="fill" flex={1}>
8
- <Browser />
9
- </Flex>
10
+ <ToolOptionsProvider options={options}>
11
+ <Flex direction="column" height="fill" flex={1}>
12
+ <Browser />
13
+ </Flex>
14
+ </ToolOptionsProvider>
10
15
  )
11
16
  }
12
17
 
@@ -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,34 @@
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
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
+ }
33
+
34
+ export default ToolOptionsContext
package/src/index.ts CHANGED
@@ -1,9 +1,10 @@
1
- import {definePlugin, Tool as SanityTool} from 'sanity'
1
+ import {definePlugin} from 'sanity'
2
2
  import {ImageIcon} from '@sanity/icons'
3
3
  import type {AssetSource} from 'sanity'
4
4
  import FormBuilderTool from './components/FormBuilderTool'
5
5
  import Tool from './components/Tool'
6
6
  import mediaTag from './schemas/tag'
7
+ import {MediaToolOptions} from '@types'
7
8
 
8
9
  const plugin = {
9
10
  icon: ImageIcon,
@@ -16,12 +17,7 @@ export const mediaAssetSource: AssetSource = {
16
17
  component: FormBuilderTool
17
18
  }
18
19
 
19
- const tool = {
20
- ...plugin,
21
- component: Tool
22
- } as SanityTool
23
-
24
- export const media = definePlugin({
20
+ export const media = definePlugin<MediaToolOptions | void>(options => ({
25
21
  name: 'media',
26
22
  form: {
27
23
  file: {
@@ -39,6 +35,13 @@ export const media = definePlugin({
39
35
  types: [mediaTag]
40
36
  },
41
37
  tools: prev => {
42
- return [...prev, tool]
38
+ return [
39
+ ...prev,
40
+ {
41
+ ...plugin,
42
+ options,
43
+ component: Tool
44
+ }
45
+ ]
43
46
  }
44
- })
47
+ }))
@@ -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