sanity-plugin-media 4.0.0 → 4.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/README.md +32 -1
- package/dist/index.d.mts +197 -1
- package/dist/index.d.ts +197 -1
- package/dist/index.js +180 -134
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +202 -155
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/components/AssetMetadata/index.tsx +1 -1
- package/src/components/DialogAssetEdit/Details.tsx +101 -0
- package/src/components/DialogAssetEdit/index.tsx +27 -69
- package/src/components/FormSubmitButton/index.tsx +1 -1
- package/src/components/Header/index.tsx +12 -8
- package/src/components/TableRowAsset/index.tsx +1 -1
- package/src/components/UploadDropzone/index.tsx +4 -2
- package/src/contexts/ToolOptionsContext.tsx +10 -2
- package/src/modules/assets/index.ts +3 -1
- package/src/types/index.ts +8 -0
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {DownloadIcon} from '@sanity/icons'
|
|
2
2
|
import {Box, Button, Flex, Inline, Stack, Text} from '@sanity/ui'
|
|
3
3
|
import type {Asset, AssetItem} from '../../types'
|
|
4
|
-
import format from 'date-fns
|
|
4
|
+
import { format } from 'date-fns'
|
|
5
5
|
import filesize from 'filesize'
|
|
6
6
|
import {type ReactNode} from 'react'
|
|
7
7
|
import getAssetResolution from '../../utils/getAssetResolution'
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import {Stack} from '@sanity/ui'
|
|
2
|
+
import type {Asset, AssetFormData, TagSelectOption} from '../../types'
|
|
3
|
+
import {type Control, type FieldErrors, type UseFormRegister} from 'react-hook-form'
|
|
4
|
+
|
|
5
|
+
import FormFieldInputTags from '../FormFieldInputTags'
|
|
6
|
+
import FormFieldInputText from '../FormFieldInputText'
|
|
7
|
+
import FormFieldInputTextarea from '../FormFieldInputTextarea'
|
|
8
|
+
|
|
9
|
+
export type DetailsProps = {
|
|
10
|
+
formUpdating: boolean
|
|
11
|
+
handleCreateTag: (title: string) => void
|
|
12
|
+
control: Control<AssetFormData>
|
|
13
|
+
errors: FieldErrors<AssetFormData>
|
|
14
|
+
register: UseFormRegister<AssetFormData>
|
|
15
|
+
allTagOptions: TagSelectOption[]
|
|
16
|
+
assetTagOptions: TagSelectOption[] | null
|
|
17
|
+
currentAsset: Asset
|
|
18
|
+
creditLine?: {
|
|
19
|
+
enabled: boolean
|
|
20
|
+
excludeSources?: string | string[] | undefined
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export default function Details({
|
|
25
|
+
formUpdating,
|
|
26
|
+
handleCreateTag,
|
|
27
|
+
control,
|
|
28
|
+
errors,
|
|
29
|
+
register,
|
|
30
|
+
allTagOptions,
|
|
31
|
+
assetTagOptions,
|
|
32
|
+
currentAsset,
|
|
33
|
+
creditLine
|
|
34
|
+
}: DetailsProps) {
|
|
35
|
+
return (
|
|
36
|
+
<Stack space={3}>
|
|
37
|
+
{/* Tags */}
|
|
38
|
+
<FormFieldInputTags
|
|
39
|
+
control={control}
|
|
40
|
+
disabled={formUpdating}
|
|
41
|
+
error={errors?.opt?.media?.tags?.message}
|
|
42
|
+
label="Tags"
|
|
43
|
+
name="opt.media.tags"
|
|
44
|
+
onCreateTag={handleCreateTag}
|
|
45
|
+
options={allTagOptions}
|
|
46
|
+
placeholder="Select or create..."
|
|
47
|
+
value={assetTagOptions}
|
|
48
|
+
/>
|
|
49
|
+
{/* Filename */}
|
|
50
|
+
<FormFieldInputText
|
|
51
|
+
{...register('originalFilename')}
|
|
52
|
+
disabled={formUpdating}
|
|
53
|
+
error={errors?.originalFilename?.message}
|
|
54
|
+
label="Filename"
|
|
55
|
+
name="originalFilename"
|
|
56
|
+
value={currentAsset?.originalFilename}
|
|
57
|
+
/>
|
|
58
|
+
{/* Title */}
|
|
59
|
+
<FormFieldInputText
|
|
60
|
+
{...register('title')}
|
|
61
|
+
disabled={formUpdating}
|
|
62
|
+
error={errors?.title?.message}
|
|
63
|
+
label="Title"
|
|
64
|
+
name="title"
|
|
65
|
+
value={currentAsset?.title}
|
|
66
|
+
/>
|
|
67
|
+
{/* Alt text */}
|
|
68
|
+
<FormFieldInputText
|
|
69
|
+
{...register('altText')}
|
|
70
|
+
disabled={formUpdating}
|
|
71
|
+
error={errors?.altText?.message}
|
|
72
|
+
label="Alt Text"
|
|
73
|
+
name="altText"
|
|
74
|
+
value={currentAsset?.altText}
|
|
75
|
+
/>
|
|
76
|
+
{/* Description */}
|
|
77
|
+
<FormFieldInputTextarea
|
|
78
|
+
{...register('description')}
|
|
79
|
+
disabled={formUpdating}
|
|
80
|
+
error={errors?.description?.message}
|
|
81
|
+
label="Description"
|
|
82
|
+
name="description"
|
|
83
|
+
rows={5}
|
|
84
|
+
value={currentAsset?.description}
|
|
85
|
+
/>
|
|
86
|
+
{/* CreditLine */}
|
|
87
|
+
{creditLine?.enabled && (
|
|
88
|
+
<FormFieldInputText
|
|
89
|
+
{...register('creditLine')}
|
|
90
|
+
error={errors?.creditLine?.message}
|
|
91
|
+
label="Credit"
|
|
92
|
+
name="creditLine"
|
|
93
|
+
value={currentAsset?.creditLine}
|
|
94
|
+
disabled={
|
|
95
|
+
formUpdating || creditLine?.excludeSources?.includes(currentAsset?.source?.name)
|
|
96
|
+
}
|
|
97
|
+
/>
|
|
98
|
+
)}
|
|
99
|
+
</Stack>
|
|
100
|
+
)
|
|
101
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {zodResolver} from '@hookform/resolvers/zod'
|
|
2
2
|
import type {MutationEvent} from '@sanity/client'
|
|
3
|
-
import {Box, Button, Card, Flex,
|
|
3
|
+
import {Box, Button, Card, Flex, Tab, TabList, TabPanel, Text} from '@sanity/ui'
|
|
4
4
|
import type {Asset, AssetFormData, DialogAssetEditProps, TagSelectOption} from '../../types'
|
|
5
5
|
import groq from 'groq'
|
|
6
6
|
import {type ReactNode, useCallback, useEffect, useRef, useState} from 'react'
|
|
@@ -22,12 +22,14 @@ import AssetMetadata from '../AssetMetadata'
|
|
|
22
22
|
import Dialog from '../Dialog'
|
|
23
23
|
import DocumentList from '../DocumentList'
|
|
24
24
|
import FileAssetPreview from '../FileAssetPreview'
|
|
25
|
-
import FormFieldInputTags from '../FormFieldInputTags'
|
|
26
|
-
import FormFieldInputText from '../FormFieldInputText'
|
|
27
|
-
import FormFieldInputTextarea from '../FormFieldInputTextarea'
|
|
28
25
|
import FormSubmitButton from '../FormSubmitButton'
|
|
29
26
|
import Image from '../Image'
|
|
30
27
|
import {useToolOptions} from '../../contexts/ToolOptionsContext'
|
|
28
|
+
import Details, {type DetailsProps} from './Details'
|
|
29
|
+
|
|
30
|
+
function renderDefaultDetails(props: DetailsProps) {
|
|
31
|
+
return <Details {...props} />
|
|
32
|
+
}
|
|
31
33
|
|
|
32
34
|
type Props = {
|
|
33
35
|
children: ReactNode
|
|
@@ -61,7 +63,7 @@ const DialogAssetEdit = (props: Props) => {
|
|
|
61
63
|
const assetTagOptions = useTypedSelector(selectTagSelectOptions(currentAsset))
|
|
62
64
|
|
|
63
65
|
// Check if credit line options are configured
|
|
64
|
-
const {creditLine} = useToolOptions()
|
|
66
|
+
const {creditLine, components: {details: CustomDetails} = {}} = useToolOptions()
|
|
65
67
|
|
|
66
68
|
const generateDefaultValues = useCallback(
|
|
67
69
|
(asset?: Asset): AssetFormData => {
|
|
@@ -239,6 +241,19 @@ const DialogAssetEdit = (props: Props) => {
|
|
|
239
241
|
return null
|
|
240
242
|
}
|
|
241
243
|
|
|
244
|
+
const detailsProps = {
|
|
245
|
+
control,
|
|
246
|
+
errors,
|
|
247
|
+
formUpdating,
|
|
248
|
+
register,
|
|
249
|
+
setValue,
|
|
250
|
+
assetTagOptions,
|
|
251
|
+
allTagOptions,
|
|
252
|
+
handleCreateTag,
|
|
253
|
+
currentAsset,
|
|
254
|
+
creditLine
|
|
255
|
+
}
|
|
256
|
+
|
|
242
257
|
return (
|
|
243
258
|
<Dialog
|
|
244
259
|
animate
|
|
@@ -304,71 +319,14 @@ const DialogAssetEdit = (props: Props) => {
|
|
|
304
319
|
hidden={tabSection !== 'details'}
|
|
305
320
|
id="details-panel"
|
|
306
321
|
>
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
disabled={formUpdating}
|
|
312
|
-
error={errors?.opt?.media?.tags?.message}
|
|
313
|
-
label="Tags"
|
|
314
|
-
name="opt.media.tags"
|
|
315
|
-
onCreateTag={handleCreateTag}
|
|
316
|
-
options={allTagOptions}
|
|
317
|
-
placeholder="Select or create..."
|
|
318
|
-
value={assetTagOptions}
|
|
322
|
+
{CustomDetails ? (
|
|
323
|
+
<CustomDetails
|
|
324
|
+
{...detailsProps}
|
|
325
|
+
renderDefaultDetails={renderDefaultDetails}
|
|
319
326
|
/>
|
|
320
|
-
|
|
321
|
-
<
|
|
322
|
-
|
|
323
|
-
disabled={formUpdating}
|
|
324
|
-
error={errors?.originalFilename?.message}
|
|
325
|
-
label="Filename"
|
|
326
|
-
name="originalFilename"
|
|
327
|
-
value={currentAsset?.originalFilename}
|
|
328
|
-
/>
|
|
329
|
-
{/* Title */}
|
|
330
|
-
<FormFieldInputText
|
|
331
|
-
{...register('title')}
|
|
332
|
-
disabled={formUpdating}
|
|
333
|
-
error={errors?.title?.message}
|
|
334
|
-
label="Title"
|
|
335
|
-
name="title"
|
|
336
|
-
value={currentAsset?.title}
|
|
337
|
-
/>
|
|
338
|
-
{/* Alt text */}
|
|
339
|
-
<FormFieldInputText
|
|
340
|
-
{...register('altText')}
|
|
341
|
-
disabled={formUpdating}
|
|
342
|
-
error={errors?.altText?.message}
|
|
343
|
-
label="Alt Text"
|
|
344
|
-
name="altText"
|
|
345
|
-
value={currentAsset?.altText}
|
|
346
|
-
/>
|
|
347
|
-
{/* Description */}
|
|
348
|
-
<FormFieldInputTextarea
|
|
349
|
-
{...register('description')}
|
|
350
|
-
disabled={formUpdating}
|
|
351
|
-
error={errors?.description?.message}
|
|
352
|
-
label="Description"
|
|
353
|
-
name="description"
|
|
354
|
-
rows={5}
|
|
355
|
-
value={currentAsset?.description}
|
|
356
|
-
/>
|
|
357
|
-
{/* CreditLine */}
|
|
358
|
-
{creditLine?.enabled && (
|
|
359
|
-
<FormFieldInputText
|
|
360
|
-
{...register('creditLine')}
|
|
361
|
-
error={errors?.creditLine?.message}
|
|
362
|
-
label="Credit"
|
|
363
|
-
name="creditLine"
|
|
364
|
-
value={currentAsset?.creditLine}
|
|
365
|
-
disabled={
|
|
366
|
-
formUpdating ||
|
|
367
|
-
creditLine?.excludeSources?.includes(currentAsset?.source?.name)
|
|
368
|
-
}
|
|
369
|
-
/>
|
|
370
|
-
)}
|
|
371
|
-
</Stack>
|
|
327
|
+
) : (
|
|
328
|
+
<Details {...detailsProps} />
|
|
329
|
+
)}
|
|
372
330
|
</TabPanel>
|
|
373
331
|
|
|
374
332
|
{/* Panel: References */}
|
|
@@ -5,6 +5,7 @@ import pluralize from 'pluralize'
|
|
|
5
5
|
import {useAssetSourceActions} from '../../contexts/AssetSourceDispatchContext'
|
|
6
6
|
import {useDropzoneActions} from '../../contexts/DropzoneDispatchContext'
|
|
7
7
|
import useTypedSelector from '../../hooks/useTypedSelector'
|
|
8
|
+
import {useToolOptions} from '../../contexts/ToolOptionsContext'
|
|
8
9
|
|
|
9
10
|
type Props = {
|
|
10
11
|
onClose?: () => void
|
|
@@ -20,6 +21,8 @@ const Header = (props: Props) => {
|
|
|
20
21
|
const assetTypes = useTypedSelector(state => state.assets.assetTypes)
|
|
21
22
|
const selectedDocument = useTypedSelector(state => state.selected.document)
|
|
22
23
|
|
|
24
|
+
const {directUploads} = useToolOptions()
|
|
25
|
+
|
|
23
26
|
// Row: Current document / close button
|
|
24
27
|
return (
|
|
25
28
|
<Box paddingY={2}>
|
|
@@ -46,14 +49,15 @@ const Header = (props: Props) => {
|
|
|
46
49
|
|
|
47
50
|
<Flex marginX={2}>
|
|
48
51
|
{/* Upload */}
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
52
|
+
{directUploads && (
|
|
53
|
+
<Button
|
|
54
|
+
fontSize={1}
|
|
55
|
+
icon={UploadIcon}
|
|
56
|
+
mode="bleed"
|
|
57
|
+
onClick={open}
|
|
58
|
+
text={`Upload ${assetTypes.length === 1 ? pluralize(assetTypes[0]) : 'assets'}`}
|
|
59
|
+
/>
|
|
60
|
+
)}
|
|
57
61
|
|
|
58
62
|
{/* Close */}
|
|
59
63
|
{onClose && (
|
|
@@ -64,7 +64,8 @@ const UploadDropzone = (props: Props) => {
|
|
|
64
64
|
const {children} = props
|
|
65
65
|
|
|
66
66
|
const {
|
|
67
|
-
dropzone: {maxSize}
|
|
67
|
+
dropzone: {maxSize},
|
|
68
|
+
directUploads
|
|
68
69
|
} = useToolOptions()
|
|
69
70
|
|
|
70
71
|
const {onSelect} = useAssetSourceActions()
|
|
@@ -143,7 +144,8 @@ const UploadDropzone = (props: Props) => {
|
|
|
143
144
|
noDrag: !!onSelect,
|
|
144
145
|
onDrop: handleDrop,
|
|
145
146
|
maxSize,
|
|
146
|
-
onDropRejected: handleDropRejected
|
|
147
|
+
onDropRejected: handleDropRejected,
|
|
148
|
+
disabled: !directUploads
|
|
147
149
|
})
|
|
148
150
|
|
|
149
151
|
return (
|
|
@@ -4,7 +4,9 @@ import type {DropzoneOptions} from 'react-dropzone'
|
|
|
4
4
|
|
|
5
5
|
type ContextProps = {
|
|
6
6
|
dropzone: Pick<DropzoneOptions, 'maxSize'>
|
|
7
|
+
components: MediaToolOptions['components']
|
|
7
8
|
creditLine: MediaToolOptions['creditLine']
|
|
9
|
+
directUploads: MediaToolOptions['directUploads']
|
|
8
10
|
}
|
|
9
11
|
|
|
10
12
|
const ToolOptionsContext = createContext<ContextProps | null>(null)
|
|
@@ -25,15 +27,21 @@ export const ToolOptionsProvider = ({options, children}: PropsWithChildren<Props
|
|
|
25
27
|
|
|
26
28
|
return {
|
|
27
29
|
dropzone: {maxSize: options?.maximumUploadSize},
|
|
30
|
+
components: {
|
|
31
|
+
details: options?.components?.details
|
|
32
|
+
},
|
|
28
33
|
creditLine: {
|
|
29
34
|
enabled: options?.creditLine?.enabled || false,
|
|
30
35
|
excludeSources: creditLineExcludeSources
|
|
31
|
-
}
|
|
36
|
+
},
|
|
37
|
+
directUploads: options?.directUploads ?? true
|
|
32
38
|
}
|
|
33
39
|
}, [
|
|
34
40
|
options?.creditLine?.enabled,
|
|
41
|
+
options?.components,
|
|
35
42
|
options?.creditLine?.excludeSources,
|
|
36
|
-
options?.maximumUploadSize
|
|
43
|
+
options?.maximumUploadSize,
|
|
44
|
+
options?.directUploads
|
|
37
45
|
])
|
|
38
46
|
|
|
39
47
|
return <ToolOptionsContext.Provider value={value}>{children}</ToolOptionsContext.Provider>
|
package/src/types/index.ts
CHANGED
|
@@ -5,17 +5,25 @@ import type {
|
|
|
5
5
|
SanityDocument,
|
|
6
6
|
SanityImageAssetDocument
|
|
7
7
|
} from '@sanity/client'
|
|
8
|
+
import type {ComponentType, JSX} from 'react'
|
|
8
9
|
import type {Epic} from 'redux-observable'
|
|
9
10
|
import * as z from 'zod'
|
|
10
11
|
import {assetFormSchema, tagFormSchema, tagOptionSchema} from '../formSchema'
|
|
11
12
|
import type {RootReducerState} from '../modules/types'
|
|
13
|
+
import type {DetailsProps} from '../components/DialogAssetEdit/Details'
|
|
12
14
|
|
|
13
15
|
export type MediaToolOptions = {
|
|
14
16
|
maximumUploadSize?: number
|
|
17
|
+
components?: {
|
|
18
|
+
details?: ComponentType<
|
|
19
|
+
DetailsProps & {renderDefaultDetails: (props: DetailsProps) => JSX.Element}
|
|
20
|
+
>
|
|
21
|
+
}
|
|
15
22
|
creditLine: {
|
|
16
23
|
enabled: boolean
|
|
17
24
|
excludeSources?: string | string[]
|
|
18
25
|
}
|
|
26
|
+
directUploads?: boolean
|
|
19
27
|
}
|
|
20
28
|
|
|
21
29
|
type CustomFields = {
|