sanity-plugin-media 4.3.6 → 5.0.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.
Files changed (162) hide show
  1. package/package.json +8 -17
  2. package/dist/index.cjs +0 -4721
  3. package/dist/index.cjs.map +0 -1
  4. package/dist/index.d.cts +0 -239
  5. package/dist/index.d.cts.map +0 -1
  6. package/sanity.json +0 -8
  7. package/src/__tests__/fixtures/createEpicTestStore.ts +0 -28
  8. package/src/__tests__/fixtures/listenMock.ts +0 -9
  9. package/src/__tests__/fixtures/mockSanityClient.ts +0 -84
  10. package/src/__tests__/fixtures/renderWithProviders.tsx +0 -55
  11. package/src/__tests__/fixtures/rootState.ts +0 -27
  12. package/src/__tests__/fixtures/withinDialog.ts +0 -28
  13. package/src/components/AssetGridVirtualized/index.tsx +0 -94
  14. package/src/components/AssetMetadata/index.tsx +0 -122
  15. package/src/components/AssetTableVirtualized/index.tsx +0 -73
  16. package/src/components/AutoTagInputWrapper/index.tsx +0 -85
  17. package/src/components/Browser/Browser.test.tsx +0 -45
  18. package/src/components/Browser/index.tsx +0 -90
  19. package/src/components/Browser/useBrowserInit.ts +0 -126
  20. package/src/components/ButtonAssetCopy/index.tsx +0 -65
  21. package/src/components/ButtonViewGroup/index.tsx +0 -39
  22. package/src/components/CardAsset/CardAsset.test.tsx +0 -323
  23. package/src/components/CardAsset/index.tsx +0 -290
  24. package/src/components/CardUpload/index.tsx +0 -161
  25. package/src/components/Controls/index.tsx +0 -136
  26. package/src/components/DebugControls/index.tsx +0 -80
  27. package/src/components/Dialog/index.tsx +0 -11
  28. package/src/components/DialogAssetEdit/Details.tsx +0 -181
  29. package/src/components/DialogAssetEdit/DialogAssetEdit.test.tsx +0 -216
  30. package/src/components/DialogAssetEdit/index.tsx +0 -493
  31. package/src/components/DialogConfirm/index.tsx +0 -90
  32. package/src/components/DialogSearchFacets/index.tsx +0 -42
  33. package/src/components/DialogTagCreate/DialogTagCreate.test.tsx +0 -121
  34. package/src/components/DialogTagCreate/index.tsx +0 -111
  35. package/src/components/DialogTagEdit/DialogTagEdit.test.tsx +0 -165
  36. package/src/components/DialogTagEdit/index.tsx +0 -201
  37. package/src/components/DialogTags/index.tsx +0 -45
  38. package/src/components/Dialogs/index.tsx +0 -76
  39. package/src/components/DocumentList/index.tsx +0 -62
  40. package/src/components/FileAssetPreview/index.tsx +0 -37
  41. package/src/components/FileIcon/index.tsx +0 -43
  42. package/src/components/FormBuilderTool/FormBuilderTool.test.tsx +0 -63
  43. package/src/components/FormBuilderTool/index.tsx +0 -69
  44. package/src/components/FormFieldInputLabel/index.tsx +0 -66
  45. package/src/components/FormFieldInputTags/index.tsx +0 -98
  46. package/src/components/FormFieldInputText/index.tsx +0 -41
  47. package/src/components/FormFieldInputTextarea/index.tsx +0 -43
  48. package/src/components/FormSubmitButton/index.tsx +0 -59
  49. package/src/components/Header/index.tsx +0 -80
  50. package/src/components/Image/index.tsx +0 -41
  51. package/src/components/Items/index.tsx +0 -68
  52. package/src/components/Notifications/index.tsx +0 -24
  53. package/src/components/OrderSelect/index.tsx +0 -66
  54. package/src/components/PickedBar/index.tsx +0 -77
  55. package/src/components/Progress/index.tsx +0 -38
  56. package/src/components/ReduxProvider/index.tsx +0 -96
  57. package/src/components/SearchFacet/index.tsx +0 -66
  58. package/src/components/SearchFacetNumber/index.tsx +0 -133
  59. package/src/components/SearchFacetSelect/index.tsx +0 -110
  60. package/src/components/SearchFacetString/index.tsx +0 -88
  61. package/src/components/SearchFacetTags/index.tsx +0 -121
  62. package/src/components/SearchFacets/index.tsx +0 -72
  63. package/src/components/SearchFacetsControl/index.tsx +0 -140
  64. package/src/components/TableHeader/index.tsx +0 -110
  65. package/src/components/TableHeaderItem/index.tsx +0 -61
  66. package/src/components/TableRowAsset/index.tsx +0 -419
  67. package/src/components/TableRowUpload/index.tsx +0 -164
  68. package/src/components/Tag/index.tsx +0 -200
  69. package/src/components/TagIcon/index.tsx +0 -22
  70. package/src/components/TagView/index.tsx +0 -39
  71. package/src/components/TagViewHeader/index.tsx +0 -70
  72. package/src/components/TagsPanel/index.tsx +0 -40
  73. package/src/components/TagsVirtualized/index.tsx +0 -160
  74. package/src/components/TextInputNumber/index.tsx +0 -32
  75. package/src/components/TextInputSearch/index.tsx +0 -60
  76. package/src/components/Tool/index.tsx +0 -13
  77. package/src/components/UploadDropzone/UploadDropzone.test.tsx +0 -40
  78. package/src/components/UploadDropzone/index.tsx +0 -173
  79. package/src/config/orders.ts +0 -28
  80. package/src/config/searchFacets.ts +0 -312
  81. package/src/constants.ts +0 -87
  82. package/src/contexts/AssetSourceDispatchContext.tsx +0 -38
  83. package/src/contexts/DropzoneDispatchContext.tsx +0 -32
  84. package/src/contexts/ToolOptionsContext.tsx +0 -66
  85. package/src/formSchema/index.test.ts +0 -56
  86. package/src/formSchema/index.ts +0 -39
  87. package/src/hooks/useBreakpointIndex.ts +0 -50
  88. package/src/hooks/useKeyPress.ts +0 -39
  89. package/src/hooks/usePortalPopoverProps.ts +0 -13
  90. package/src/hooks/useTypedSelector.ts +0 -7
  91. package/src/hooks/useVersionedClient.ts +0 -6
  92. package/src/index.ts +0 -5
  93. package/src/modules/assets/actions.ts +0 -42
  94. package/src/modules/assets/deleteAndUpdateEpics.test.ts +0 -87
  95. package/src/modules/assets/fetchEpic.test.ts +0 -73
  96. package/src/modules/assets/index.ts +0 -782
  97. package/src/modules/assets/reducer.test.ts +0 -91
  98. package/src/modules/assets/tagsAndListenerEpics.test.ts +0 -206
  99. package/src/modules/debug/index.ts +0 -28
  100. package/src/modules/dialog/actions.ts +0 -10
  101. package/src/modules/dialog/epics.test.ts +0 -168
  102. package/src/modules/dialog/index.ts +0 -238
  103. package/src/modules/dialog/reducer.test.ts +0 -185
  104. package/src/modules/index.ts +0 -117
  105. package/src/modules/notifications/epics.test.ts +0 -374
  106. package/src/modules/notifications/index.ts +0 -199
  107. package/src/modules/notifications/reducer.test.ts +0 -54
  108. package/src/modules/search/index.test.ts +0 -36
  109. package/src/modules/search/index.ts +0 -167
  110. package/src/modules/selected/index.ts +0 -22
  111. package/src/modules/selectors.test.ts +0 -21
  112. package/src/modules/selectors.ts +0 -17
  113. package/src/modules/tags/epics.test.ts +0 -96
  114. package/src/modules/tags/index.test.ts +0 -42
  115. package/src/modules/tags/index.ts +0 -540
  116. package/src/modules/types.ts +0 -3
  117. package/src/modules/uploads/actions.ts +0 -13
  118. package/src/modules/uploads/epics.test.ts +0 -109
  119. package/src/modules/uploads/index.test.ts +0 -59
  120. package/src/modules/uploads/index.ts +0 -272
  121. package/src/operators/checkTagName.test.ts +0 -29
  122. package/src/operators/checkTagName.ts +0 -33
  123. package/src/operators/debugThrottle.ts +0 -25
  124. package/src/plugin.tsx +0 -54
  125. package/src/schemas/tag.ts +0 -28
  126. package/src/styled/GlobalStyles/index.tsx +0 -40
  127. package/src/styled/react-select/creatable.tsx +0 -184
  128. package/src/styled/react-select/single.tsx +0 -184
  129. package/src/types/index.ts +0 -346
  130. package/src/types/sanity-ui.d.ts +0 -5
  131. package/src/utils/applyMediaTags.ts +0 -87
  132. package/src/utils/blocksToText.test.ts +0 -43
  133. package/src/utils/blocksToText.ts +0 -27
  134. package/src/utils/constructFilter.test.ts +0 -120
  135. package/src/utils/constructFilter.ts +0 -98
  136. package/src/utils/generatePreviewBlobUrl.test.ts +0 -68
  137. package/src/utils/generatePreviewBlobUrl.ts +0 -53
  138. package/src/utils/getAssetResolution.test.ts +0 -13
  139. package/src/utils/getAssetResolution.ts +0 -7
  140. package/src/utils/getDocumentAssetIds.test.ts +0 -50
  141. package/src/utils/getDocumentAssetIds.ts +0 -35
  142. package/src/utils/getSchemeColor.test.ts +0 -12
  143. package/src/utils/getSchemeColor.ts +0 -43
  144. package/src/utils/getTagSelectOptions.test.ts +0 -44
  145. package/src/utils/getTagSelectOptions.ts +0 -16
  146. package/src/utils/getUniqueDocuments.test.ts +0 -26
  147. package/src/utils/getUniqueDocuments.ts +0 -15
  148. package/src/utils/imageDprUrl.test.ts +0 -46
  149. package/src/utils/imageDprUrl.ts +0 -27
  150. package/src/utils/isSupportedAssetType.test.ts +0 -16
  151. package/src/utils/isSupportedAssetType.ts +0 -15
  152. package/src/utils/mediaField.ts +0 -73
  153. package/src/utils/sanitizeFormData.test.ts +0 -59
  154. package/src/utils/sanitizeFormData.ts +0 -26
  155. package/src/utils/typeGuards.test.ts +0 -18
  156. package/src/utils/typeGuards.ts +0 -9
  157. package/src/utils/uploadSanityAsset.test.ts +0 -29
  158. package/src/utils/uploadSanityAsset.ts +0 -97
  159. package/src/utils/withMaxConcurrency.test.ts +0 -43
  160. package/src/utils/withMaxConcurrency.ts +0 -55
  161. package/src/utils/zodFormResolver.ts +0 -17
  162. package/v2-incompatible.js +0 -11
@@ -1,161 +0,0 @@
1
- import {CloseIcon} from '@sanity/icons'
2
- import {Box, Button, Flex, Text} from '@sanity/ui'
3
- import filesize from 'filesize'
4
- import {useDispatch} from 'react-redux'
5
- import {useColorSchemeValue} from 'sanity'
6
- import {styled} from 'styled-components'
7
-
8
- import {PANEL_HEIGHT} from '../../constants'
9
- import useTypedSelector from '../../hooks/useTypedSelector'
10
- import {selectUploadById, uploadsActions} from '../../modules/uploads'
11
- import {getSchemeColor} from '../../utils/getSchemeColor'
12
- import FileIcon from '../FileIcon'
13
- import Image from '../Image'
14
-
15
- type Props = {
16
- id: string
17
- }
18
-
19
- const CardWrapper = styled(Flex)`
20
- box-sizing: border-box;
21
- height: 100%;
22
- overflow: hidden;
23
- position: relative;
24
- width: 100%;
25
- `
26
-
27
- const CardUpload = (props: Props) => {
28
- const {id} = props
29
-
30
- const scheme = useColorSchemeValue()
31
-
32
- // Redux
33
- const dispatch = useDispatch()
34
- const item = useTypedSelector((state) => selectUploadById(state, id))
35
-
36
- if (!item) {
37
- return null
38
- }
39
-
40
- const fileSize = filesize(item.size, {base: 10, round: 0})
41
- const percentLoaded = Math.round(item.percent || 0) // (0 - 100)
42
-
43
- const isComplete = item.status === 'complete'
44
- const isUploading = item.status === 'uploading'
45
- const isQueued = item.status === 'queued'
46
-
47
- let status
48
- if (isComplete) {
49
- status = 'Verifying'
50
- }
51
- if (isUploading) {
52
- status = `${percentLoaded}%`
53
- }
54
- if (isQueued) {
55
- status = 'Queued'
56
- }
57
-
58
- // Callbacks
59
- const handleCancelUpload = () => {
60
- dispatch(uploadsActions.uploadCancel({hash: item.hash}))
61
- }
62
-
63
- return (
64
- <CardWrapper padding={1}>
65
- <Flex
66
- direction="column"
67
- flex={1}
68
- style={{
69
- background: getSchemeColor(scheme, 'bg'),
70
- border: '1px solid transparent',
71
- height: '100%',
72
- position: 'relative',
73
- }}
74
- >
75
- {/* Progress bar */}
76
- <div
77
- style={{
78
- background: 'var(--card-fg-color)',
79
- bottom: 0,
80
- height: '1px',
81
- left: 0,
82
- position: 'absolute',
83
- width: '100%',
84
- transform: `scaleX(${percentLoaded * 0.01})`,
85
- transformOrigin: 'bottom left',
86
- transition: 'all 1000ms ease-out',
87
- }}
88
- />
89
-
90
- <Box flex={1} style={{position: 'relative'}}>
91
- {item.assetType === 'image' && item?.objectUrl && (
92
- <Image
93
- draggable={false}
94
- $scheme={scheme}
95
- src={item.objectUrl}
96
- style={{
97
- opacity: 0.4,
98
- }}
99
- />
100
- )}
101
-
102
- {item.assetType === 'file' && (
103
- <div style={{height: '100%', opacity: 0.1}}>
104
- <FileIcon width="80px" />
105
- </div>
106
- )}
107
-
108
- {/*
109
- Cancel upload button.
110
- Assets will only have a `complete` status _after_ it has been created on your dataset.
111
- As such, we also hide the cancel button when `percentLoaded === 100`, as cancelling when the asset
112
- has been fully uploaded (even with a status of `progress`) won't stop the asset from being created.
113
- */}
114
- {!isComplete && percentLoaded !== 100 && (
115
- <Flex
116
- align="center"
117
- direction="column"
118
- justify="center"
119
- style={{
120
- height: '100%',
121
- left: 0,
122
- position: 'absolute',
123
- top: 0,
124
- width: '100%',
125
- }}
126
- >
127
- <Button
128
- fontSize={4}
129
- icon={CloseIcon}
130
- mode="bleed"
131
- onClick={handleCancelUpload}
132
- padding={2}
133
- style={{background: 'none', boxShadow: 'none'}}
134
- tone="critical"
135
- />
136
- </Flex>
137
- )}
138
- </Box>
139
-
140
- {/* Footer */}
141
- <Flex
142
- align="center"
143
- justify="space-between"
144
- paddingX={2}
145
- style={{height: `${PANEL_HEIGHT}px`}}
146
- >
147
- <Box flex={1} marginRight={1}>
148
- <Text size={0} textOverflow="ellipsis">
149
- {item.name} ({fileSize})
150
- </Text>
151
- </Box>
152
- <Text size={0} style={{flexShrink: 0}} weight="semibold">
153
- {status}
154
- </Text>
155
- </Flex>
156
- </Flex>
157
- </CardWrapper>
158
- )
159
- }
160
-
161
- export default CardUpload
@@ -1,136 +0,0 @@
1
- import {Box, Button, Flex, Inline, useMediaIndex} from '@sanity/ui'
2
- import {useDispatch} from 'react-redux'
3
-
4
- import useTypedSelector from '../../hooks/useTypedSelector'
5
- import {dialogActions} from '../../modules/dialog'
6
- import {tagsActions} from '../../modules/tags'
7
- import ButtonViewGroup from '../ButtonViewGroup'
8
- import OrderSelect from '../OrderSelect'
9
- import Progress from '../Progress'
10
- import SearchFacets from '../SearchFacets'
11
- import SearchFacetsControl from '../SearchFacetsControl'
12
- import TagIcon from '../TagIcon'
13
- import TextInputSearch from '../TextInputSearch'
14
-
15
- const Controls = () => {
16
- // Redux
17
- const dispatch = useDispatch()
18
- const fetching = useTypedSelector((state) => state.assets.fetching)
19
- const pageIndex = useTypedSelector((state) => state.assets.pageIndex)
20
- const searchFacets = useTypedSelector((state) => state.search.facets)
21
- const tagsPanelVisible = useTypedSelector((state) => state.tags.panelVisible)
22
-
23
- const mediaIndex = useMediaIndex()
24
-
25
- // Callbacks
26
- const handleShowSearchFacetDialog = () => {
27
- dispatch(dialogActions.showSearchFacets())
28
- }
29
-
30
- const handleShowTagsDialog = () => {
31
- dispatch(dialogActions.showTags())
32
- }
33
-
34
- const toggleTagsPanelToggle = () => {
35
- dispatch(tagsActions.panelVisibleSet({panelVisible: !tagsPanelVisible}))
36
- }
37
-
38
- return (
39
- <Box
40
- paddingY={2}
41
- style={{
42
- borderBottom: '1px solid var(--card-border-color)',
43
- zIndex: 2,
44
- }}
45
- >
46
- {/* Rows: search / filters / orders */}
47
- <Box marginBottom={2}>
48
- <Flex
49
- align="flex-start"
50
- direction={['column', 'column', 'column', 'column', 'row']}
51
- justify="space-between"
52
- >
53
- {/* Search + Filters */}
54
- <Flex
55
- flex={1}
56
- style={{
57
- alignItems: 'flex-start',
58
- flex: 1,
59
- height: '100%',
60
- justifyContent: mediaIndex < 2 ? 'space-between' : 'flex-start',
61
- position: 'relative',
62
- width: '100%',
63
- }}
64
- >
65
- <Box marginX={2} style={{minWidth: '200px'}}>
66
- {/* Search */}
67
- <TextInputSearch />
68
- </Box>
69
-
70
- <Box display={['none', 'none', 'block']}>
71
- <SearchFacets />
72
-
73
- {/* Search Facets Control (add / clear) */}
74
- <SearchFacetsControl />
75
- </Box>
76
-
77
- <Box display={['block', 'block', 'none']} marginX={2}>
78
- <Inline space={2} style={{whiteSpace: 'nowrap'}}>
79
- {/* Filters button (small) */}
80
- <Button
81
- fontSize={1}
82
- mode="ghost"
83
- onClick={handleShowSearchFacetDialog}
84
- text={`Filters${searchFacets.length > 0 ? ` (${searchFacets.length})` : ''}`}
85
- tone="primary"
86
- />
87
-
88
- {/* Tags button (small) */}
89
- <Button
90
- fontSize={1}
91
- mode="ghost"
92
- onClick={handleShowTagsDialog}
93
- text={`Tags`}
94
- tone="primary"
95
- />
96
- </Inline>
97
- </Box>
98
- </Flex>
99
- </Flex>
100
- </Box>
101
-
102
- <Box>
103
- <Flex align="center" justify={['space-between']}>
104
- {/* Views */}
105
- <Box marginX={2}>
106
- <ButtonViewGroup />
107
- </Box>
108
-
109
- <Flex marginX={2}>
110
- {/* Orders */}
111
- <OrderSelect />
112
- {/* Tags panel toggle */}
113
- <Box display={['none', 'none', 'block']} marginLeft={2}>
114
- <Button
115
- fontSize={1}
116
- icon={
117
- <Box style={{transform: 'scale(0.75)'}}>
118
- <TagIcon />
119
- </Box>
120
- }
121
- onClick={toggleTagsPanelToggle}
122
- mode={tagsPanelVisible ? 'default' : 'ghost'}
123
- text={tagsPanelVisible ? 'Tags' : ''}
124
- />
125
- </Box>
126
- </Flex>
127
- </Flex>
128
- </Box>
129
-
130
- {/* Progress bar */}
131
- <Progress key={pageIndex} loading={fetching} />
132
- </Box>
133
- )
134
- }
135
-
136
- export default Controls
@@ -1,80 +0,0 @@
1
- import {PlugIcon} from '@sanity/icons'
2
- import {Box, Flex, Switch, Text, Tooltip} from '@sanity/ui'
3
- import {type ChangeEvent} from 'react'
4
- import {useDispatch} from 'react-redux'
5
-
6
- import useKeyPress from '../../hooks/useKeyPress'
7
- import useTypedSelector from '../../hooks/useTypedSelector'
8
- import {debugActions} from '../../modules/debug'
9
-
10
- const DebugControls = () => {
11
- // Redux
12
- const dispatch = useDispatch()
13
- const badConnection = useTypedSelector((state) => state.debug.badConnection)
14
- const debugEnabled = useTypedSelector((state) => state.debug.enabled)
15
-
16
- // Callbacks
17
- const handleChange = (e: ChangeEvent<HTMLInputElement>) => {
18
- const checked = e.target.checked
19
-
20
- dispatch(debugActions.setBadConnection(checked))
21
- }
22
-
23
- const handleToggleControls = () => {
24
- dispatch(debugActions.toggleEnabled())
25
- }
26
-
27
- // Close on escape key press
28
- useKeyPress('alt+ctrl+shift+/', handleToggleControls)
29
-
30
- if (!debugEnabled) {
31
- return null
32
- }
33
-
34
- return (
35
- <Box
36
- padding={4}
37
- style={{
38
- bottom: 0,
39
- left: 0,
40
- pointerEvents: 'none',
41
- position: 'fixed',
42
- width: '100%',
43
- }}
44
- >
45
- {/* Bad connection toggle */}
46
- <Flex align="center">
47
- <Box marginRight={3}>
48
- <Text muted size={1}>
49
- <PlugIcon />
50
- </Text>
51
- </Box>
52
- <Tooltip
53
- animate
54
- content={
55
- <Box padding={2}>
56
- <Text muted size={1}>
57
- {badConnection
58
- ? 'Bad connection: +3000ms & 50% chance to fail'
59
- : 'No connection throttling'}
60
- </Text>
61
- </Box>
62
- }
63
- fallbackPlacements={['right', 'left']}
64
- placement="bottom"
65
- portal
66
- >
67
- <Switch
68
- checked={badConnection}
69
- onChange={handleChange}
70
- style={{
71
- pointerEvents: 'auto',
72
- }}
73
- />
74
- </Tooltip>
75
- </Flex>
76
- </Box>
77
- )
78
- }
79
-
80
- export default DebugControls
@@ -1,11 +0,0 @@
1
- import {Dialog as SanityDialog} from '@sanity/ui'
2
- import {type ComponentProps} from 'react'
3
-
4
- const Dialog = (props: ComponentProps<typeof SanityDialog>) => {
5
- // HACK: Temporarily force fixed positioning on all @sanity/ui <Dialog /> components.
6
- // The studio is currently setting absolute positioning on all root-level dialogs on the mobile breakpoint,
7
- // causing unwanted scroll behaviour.
8
- return <SanityDialog {...props} style={{position: 'fixed'}} />
9
- }
10
-
11
- export default Dialog
@@ -1,181 +0,0 @@
1
- import {Card, Stack, Tab, TabList, TabPanel} from '@sanity/ui'
2
- import {useState} from 'react'
3
- import {type Control, type FieldErrors, type UseFormRegister} from 'react-hook-form'
4
-
5
- import type {Asset, AssetFormData, Locale, TagSelectOption} from '../../types'
6
- import FormFieldInputTags from '../FormFieldInputTags'
7
- import FormFieldInputText from '../FormFieldInputText'
8
- import FormFieldInputTextarea from '../FormFieldInputTextarea'
9
-
10
- type LocalizedErrors = Record<string, {message?: string} | undefined>
11
-
12
- // When locales are not configured, extract a plain string from a potentially localized field
13
- function toStringField(value: unknown): string | undefined {
14
- if (typeof value === 'string') return value
15
- if (typeof value === 'object' && value !== null) {
16
- const found = Object.values(value as Record<string, string>).find((v) => v)
17
- return found || undefined
18
- }
19
- return undefined
20
- }
21
-
22
- export type DetailsProps = {
23
- formUpdating: boolean
24
- handleCreateTag: (title: string) => void
25
- control: Control<AssetFormData>
26
- errors: FieldErrors<AssetFormData>
27
- register: UseFormRegister<AssetFormData>
28
- allTagOptions: TagSelectOption[]
29
- assetTagOptions: TagSelectOption[] | null
30
- currentAsset: Asset
31
- creditLine?: {
32
- enabled: boolean
33
- excludeSources?: string | string[] | undefined
34
- }
35
- locales?: Locale[]
36
- }
37
-
38
- export default function Details({
39
- formUpdating,
40
- handleCreateTag,
41
- control,
42
- errors,
43
- register,
44
- allTagOptions,
45
- assetTagOptions,
46
- currentAsset,
47
- creditLine,
48
- locales,
49
- }: DetailsProps) {
50
- const hasLocales = locales && locales.length > 0
51
- const [activeLocaleTab, setActiveLocaleTab] = useState(0)
52
- return (
53
- <Stack space={3}>
54
- {/* Tags */}
55
- <FormFieldInputTags
56
- control={control}
57
- disabled={formUpdating}
58
- error={errors?.opt?.media?.tags?.message}
59
- label="Tags"
60
- name="opt.media.tags"
61
- onCreateTag={handleCreateTag}
62
- options={allTagOptions}
63
- placeholder="Select or create..."
64
- value={assetTagOptions}
65
- />
66
- {/* Filename */}
67
- <FormFieldInputText
68
- {...register('originalFilename')}
69
- disabled={formUpdating}
70
- error={errors?.originalFilename?.message}
71
- label="Filename"
72
- name="originalFilename"
73
- value={currentAsset?.originalFilename}
74
- />
75
- {/* Localized fields grouped by language */}
76
- {hasLocales ? (
77
- <Card marginTop={2} shadow={1} padding={3} radius={1}>
78
- <Stack space={2}>
79
- <TabList space={2}>
80
- {locales.map((locale, idx) => (
81
- <Tab
82
- key={locale.id}
83
- id={`locale-tab-${locale.id}`}
84
- aria-controls={`locale-panel-${locale.id}`}
85
- selected={activeLocaleTab === idx}
86
- onClick={() => setActiveLocaleTab(idx)}
87
- label={locale.title}
88
- />
89
- ))}
90
- </TabList>
91
- {locales.map((locale, idx) => (
92
- <TabPanel
93
- key={locale.id}
94
- id={`locale-panel-${locale.id}`}
95
- aria-labelledby={`locale-tab-${locale.id}`}
96
- hidden={activeLocaleTab !== idx}
97
- >
98
- <Stack space={3}>
99
- <FormFieldInputText
100
- {...register(`title.${locale.id}` as const)}
101
- disabled={formUpdating}
102
- error={(errors?.title as LocalizedErrors)?.[locale.id]?.message}
103
- label="Title"
104
- name={`title.${locale.id}`}
105
- />
106
- <FormFieldInputText
107
- {...register(`altText.${locale.id}` as const)}
108
- disabled={formUpdating}
109
- error={(errors?.altText as LocalizedErrors)?.[locale.id]?.message}
110
- label="Alt Text"
111
- name={`altText.${locale.id}`}
112
- />
113
- <FormFieldInputTextarea
114
- {...register(`description.${locale.id}` as const)}
115
- disabled={formUpdating}
116
- error={(errors?.description as LocalizedErrors)?.[locale.id]?.message}
117
- label="Description"
118
- name={`description.${locale.id}`}
119
- rows={5}
120
- />
121
- {creditLine?.enabled && (
122
- <FormFieldInputText
123
- {...register(`creditLine.${locale.id}` as const)}
124
- error={(errors?.creditLine as LocalizedErrors)?.[locale.id]?.message}
125
- label="Credit"
126
- name={`creditLine.${locale.id}`}
127
- disabled={
128
- formUpdating ||
129
- creditLine?.excludeSources?.includes(currentAsset?.['source']?.name)
130
- }
131
- />
132
- )}
133
- </Stack>
134
- </TabPanel>
135
- ))}
136
- </Stack>
137
- </Card>
138
- ) : (
139
- <>
140
- <FormFieldInputText
141
- {...register('title')}
142
- disabled={formUpdating}
143
- error={errors?.title?.message}
144
- label="Title"
145
- name="title"
146
- value={toStringField(currentAsset?.title)}
147
- />
148
- <FormFieldInputText
149
- {...register('altText')}
150
- disabled={formUpdating}
151
- error={errors?.altText?.message}
152
- label="Alt Text"
153
- name="altText"
154
- value={toStringField(currentAsset?.altText)}
155
- />
156
- <FormFieldInputTextarea
157
- {...register('description')}
158
- disabled={formUpdating}
159
- error={errors?.description?.message}
160
- label="Description"
161
- name="description"
162
- rows={5}
163
- value={toStringField(currentAsset?.description)}
164
- />
165
- {creditLine?.enabled && (
166
- <FormFieldInputText
167
- {...register('creditLine')}
168
- error={errors?.creditLine?.message}
169
- label="Credit"
170
- name="creditLine"
171
- value={toStringField(currentAsset?.creditLine)}
172
- disabled={
173
- formUpdating || creditLine?.excludeSources?.includes(currentAsset?.['source']?.name)
174
- }
175
- />
176
- )}
177
- </>
178
- )}
179
- </Stack>
180
- )
181
- }