sanity-plugin-media 2.1.0 → 2.1.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/lib/index.esm.js +1 -1
- package/lib/index.esm.js.map +1 -1
- package/lib/index.js +1 -1
- package/lib/index.js.map +1 -1
- package/package.json +4 -5
- package/src/components/DialogAssetEdit/index.tsx +95 -118
- package/src/components/DialogTagCreate/index.tsx +10 -21
- package/src/components/DialogTagEdit/index.tsx +25 -40
- package/src/components/FormFieldInputLabel/index.tsx +2 -3
- package/src/components/FormFieldInputTags/index.tsx +6 -5
- package/src/components/FormFieldInputText/index.tsx +3 -3
- package/src/components/FormFieldInputTextarea/index.tsx +1 -2
- package/src/components/SearchFacetTags/index.tsx +3 -3
- package/src/formSchema/index.ts +22 -0
- package/src/modules/tags/index.ts +2 -2
- package/src/types/index.ts +9 -6
- package/src/utils/getTagSelectOptions.ts +3 -3
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import {Box} from '@sanity/ui'
|
|
2
2
|
import React from 'react'
|
|
3
|
-
import {Controller
|
|
3
|
+
import {Controller} from 'react-hook-form'
|
|
4
4
|
import CreatableSelect from 'react-select/creatable'
|
|
5
5
|
import useTypedSelector from '../../hooks/useTypedSelector'
|
|
6
6
|
import {reactSelectComponents, reactSelectStyles} from '../../styled/react-select/creatable'
|
|
7
|
-
import type {
|
|
7
|
+
import type {TagSelectOption} from '../../types'
|
|
8
8
|
import FormFieldInputLabel from '../FormFieldInputLabel'
|
|
9
9
|
|
|
10
10
|
type Props = {
|
|
11
11
|
control: any
|
|
12
12
|
description?: string
|
|
13
13
|
disabled?: boolean
|
|
14
|
-
error?:
|
|
14
|
+
error?: string
|
|
15
15
|
label: string
|
|
16
16
|
name: string
|
|
17
17
|
onCreateTag: (tagName: string) => void
|
|
@@ -20,7 +20,7 @@ type Props = {
|
|
|
20
20
|
value: string
|
|
21
21
|
}[]
|
|
22
22
|
placeholder?: string
|
|
23
|
-
value?:
|
|
23
|
+
value?: TagSelectOption[] | null
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
const FormFieldInputTags = (props: Props) => {
|
|
@@ -54,7 +54,8 @@ const FormFieldInputTags = (props: Props) => {
|
|
|
54
54
|
control={control}
|
|
55
55
|
defaultValue={value}
|
|
56
56
|
name={name}
|
|
57
|
-
render={({
|
|
57
|
+
render={({field}) => {
|
|
58
|
+
const {onBlur, onChange, value: controllerValue} = field
|
|
58
59
|
// TODO: investigate overriding `onChange` and updating form state manually.
|
|
59
60
|
// `opt.media.tags` is initialised with `null` as a defaultValue in react-hook-form
|
|
60
61
|
// Ideally, we'd be able to set `opt.media.tags` as null when all items are cleared, rather than
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import {Box, TextInput} from '@sanity/ui'
|
|
2
2
|
import React, {forwardRef} from 'react'
|
|
3
|
-
import {FieldError} from 'react-hook-form'
|
|
4
3
|
|
|
5
4
|
import FormFieldInputLabel from '../FormFieldInputLabel'
|
|
6
5
|
|
|
7
6
|
type Props = {
|
|
8
7
|
description?: string
|
|
9
8
|
disabled?: boolean
|
|
10
|
-
error?:
|
|
9
|
+
error?: string
|
|
11
10
|
label: string
|
|
12
11
|
name: string
|
|
13
12
|
placeholder?: string
|
|
@@ -17,7 +16,7 @@ type Props = {
|
|
|
17
16
|
type Ref = HTMLInputElement
|
|
18
17
|
|
|
19
18
|
const FormFieldInputText = forwardRef<Ref, Props>((props: Props, ref) => {
|
|
20
|
-
const {description, disabled, error, label, name, placeholder, value} = props
|
|
19
|
+
const {description, disabled, error, label, name, placeholder, value, ...rest} = props
|
|
21
20
|
|
|
22
21
|
return (
|
|
23
22
|
<Box>
|
|
@@ -25,6 +24,7 @@ const FormFieldInputText = forwardRef<Ref, Props>((props: Props, ref) => {
|
|
|
25
24
|
<FormFieldInputLabel description={description} error={error} label={label} name={name} />
|
|
26
25
|
{/* Input */}
|
|
27
26
|
<TextInput
|
|
27
|
+
{...rest}
|
|
28
28
|
autoComplete="off"
|
|
29
29
|
autoFocus
|
|
30
30
|
defaultValue={value}
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import {Box, TextArea} from '@sanity/ui'
|
|
2
2
|
import React, {forwardRef} from 'react'
|
|
3
|
-
import {FieldError} from 'react-hook-form'
|
|
4
3
|
|
|
5
4
|
import FormFieldInputLabel from '../FormFieldInputLabel'
|
|
6
5
|
|
|
7
6
|
type Props = {
|
|
8
7
|
description?: string
|
|
9
8
|
disabled?: boolean
|
|
10
|
-
error?:
|
|
9
|
+
error?: string
|
|
11
10
|
label: string
|
|
12
11
|
name: string
|
|
13
12
|
placeholder?: string
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {SelectIcon} from '@sanity/icons'
|
|
2
2
|
import {Box, Button, Menu, MenuButton, MenuDivider, MenuItem} from '@sanity/ui'
|
|
3
3
|
import {
|
|
4
|
-
|
|
4
|
+
TagSelectOption,
|
|
5
5
|
SearchFacetInputSearchableProps,
|
|
6
6
|
SearchFacetOperatorType,
|
|
7
7
|
WithId
|
|
@@ -31,7 +31,7 @@ const SearchFacetTags = ({facet}: Props) => {
|
|
|
31
31
|
|
|
32
32
|
const popoverProps = usePortalPopoverProps()
|
|
33
33
|
|
|
34
|
-
const handleChange = (option:
|
|
34
|
+
const handleChange = (option: TagSelectOption) => {
|
|
35
35
|
dispatch(
|
|
36
36
|
searchActions.facetsUpdateById({
|
|
37
37
|
id: facet.id,
|
|
@@ -100,7 +100,7 @@ const SearchFacetTags = ({facet}: Props) => {
|
|
|
100
100
|
isSearchable
|
|
101
101
|
name="tags"
|
|
102
102
|
noOptionsMessage={() => 'No tags'}
|
|
103
|
-
onChange={value => handleChange(value as
|
|
103
|
+
onChange={value => handleChange(value as TagSelectOption)}
|
|
104
104
|
options={allTagOptions}
|
|
105
105
|
placeholder={tagsFetching ? 'Loading...' : 'Select...'}
|
|
106
106
|
styles={reactSelectStyles}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import * as z from 'zod'
|
|
2
|
+
|
|
3
|
+
export const tagOptionSchema = z.object({
|
|
4
|
+
label: z.string().trim().min(1, {message: 'Label cannot be empty'}),
|
|
5
|
+
value: z.string().trim().min(1, {message: 'Value cannot be empty'})
|
|
6
|
+
})
|
|
7
|
+
|
|
8
|
+
export const assetFormSchema = z.object({
|
|
9
|
+
altText: z.string().trim().optional(),
|
|
10
|
+
description: z.string().trim().optional(),
|
|
11
|
+
opt: z.object({
|
|
12
|
+
media: z.object({
|
|
13
|
+
tags: z.array(tagOptionSchema).nullable()
|
|
14
|
+
})
|
|
15
|
+
}),
|
|
16
|
+
originalFilename: z.string().trim().min(1, {message: 'Filename cannot be empty'}),
|
|
17
|
+
title: z.string().trim().optional()
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
export const tagFormSchema = z.object({
|
|
21
|
+
name: z.string().min(1, {message: 'Name cannot be empty'})
|
|
22
|
+
})
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {createSelector, createSlice, PayloadAction} from '@reduxjs/toolkit'
|
|
2
2
|
import type {ClientError, Transaction} from '@sanity/client'
|
|
3
|
-
import type {Asset, HttpError, MyEpic,
|
|
3
|
+
import type {Asset, HttpError, MyEpic, TagSelectOption, Tag, TagItem} from '@types'
|
|
4
4
|
import groq from 'groq'
|
|
5
5
|
import {Selector} from 'react-redux'
|
|
6
6
|
import {ofType} from 'redux-observable'
|
|
@@ -523,7 +523,7 @@ export const selectTagById = createSelector(
|
|
|
523
523
|
// Map tag references to react-select options, skipping over items with no linked tags
|
|
524
524
|
export const selectTagSelectOptions =
|
|
525
525
|
(asset?: Asset) =>
|
|
526
|
-
(state: RootReducerState):
|
|
526
|
+
(state: RootReducerState): TagSelectOption[] | null => {
|
|
527
527
|
const tags = asset?.opt?.media?.tags?.reduce((acc: TagItem[], v) => {
|
|
528
528
|
const tagItem = state.tags.byIds[v._ref]
|
|
529
529
|
if (tagItem?.tag) {
|
package/src/types/index.ts
CHANGED
|
@@ -6,6 +6,8 @@ import type {
|
|
|
6
6
|
SanityImageAssetDocument
|
|
7
7
|
} from '@sanity/client'
|
|
8
8
|
import type {Epic} from 'redux-observable'
|
|
9
|
+
import * as z from 'zod'
|
|
10
|
+
import {assetFormSchema, tagFormSchema, tagOptionSchema} from '../formSchema'
|
|
9
11
|
import {RootReducerState} from '../modules/types'
|
|
10
12
|
|
|
11
13
|
type CustomFields = {
|
|
@@ -30,6 +32,8 @@ type SearchFacetInputCommon = {
|
|
|
30
32
|
|
|
31
33
|
export type Asset = FileAsset | ImageAsset
|
|
32
34
|
|
|
35
|
+
export type AssetFormData = z.infer<typeof assetFormSchema>
|
|
36
|
+
|
|
33
37
|
export type AssetItem = {
|
|
34
38
|
_type: 'asset'
|
|
35
39
|
asset: Asset
|
|
@@ -164,11 +168,6 @@ export type Order = {
|
|
|
164
168
|
|
|
165
169
|
export type OrderDirection = 'asc' | 'desc'
|
|
166
170
|
|
|
167
|
-
export type ReactSelectOption = {
|
|
168
|
-
label: string
|
|
169
|
-
value: string
|
|
170
|
-
}
|
|
171
|
-
|
|
172
171
|
export type SanityReference = {
|
|
173
172
|
_ref: string
|
|
174
173
|
_type: 'reference'
|
|
@@ -210,7 +209,7 @@ export type SearchFacetInputSearchableProps = SearchFacetInputCommon & {
|
|
|
210
209
|
name: string
|
|
211
210
|
options?: SearchFacetInputSelectListItemProps[]
|
|
212
211
|
type: 'searchable'
|
|
213
|
-
value?:
|
|
212
|
+
value?: TagSelectOption
|
|
214
213
|
}
|
|
215
214
|
|
|
216
215
|
export type SearchFacetInputSelectProps = SearchFacetInputCommon & {
|
|
@@ -312,6 +311,8 @@ export type Tag = SanityDocument & {
|
|
|
312
311
|
|
|
313
312
|
export type TagActions = 'applyAll' | 'delete' | 'edit' | 'removeAll' | 'search'
|
|
314
313
|
|
|
314
|
+
export type TagFormData = z.infer<typeof tagFormSchema>
|
|
315
|
+
|
|
315
316
|
export type TagItem = {
|
|
316
317
|
_type: 'tag'
|
|
317
318
|
tag: Tag
|
|
@@ -320,6 +321,8 @@ export type TagItem = {
|
|
|
320
321
|
updating: boolean
|
|
321
322
|
}
|
|
322
323
|
|
|
324
|
+
export type TagSelectOption = z.infer<typeof tagOptionSchema>
|
|
325
|
+
|
|
323
326
|
export type UploadItem = {
|
|
324
327
|
_type: 'upload'
|
|
325
328
|
assetType: AssetType
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {TagSelectOption, TagItem} from '@types'
|
|
2
2
|
|
|
3
|
-
const getTagSelectOptions = (tags: TagItem[]):
|
|
4
|
-
return tags.reduce((acc:
|
|
3
|
+
const getTagSelectOptions = (tags: TagItem[]): TagSelectOption[] => {
|
|
4
|
+
return tags.reduce((acc: TagSelectOption[], val) => {
|
|
5
5
|
const tag = val?.tag
|
|
6
6
|
if (tag) {
|
|
7
7
|
acc.push({
|