sanity-plugin-media 4.3.5 → 5.0.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.
Files changed (166) hide show
  1. package/dist/index.d.ts +190 -413
  2. package/dist/index.d.ts.map +1 -0
  3. package/dist/index.js +2532 -3564
  4. package/dist/index.js.map +1 -1
  5. package/package.json +29 -35
  6. package/dist/index.cjs +0 -5753
  7. package/dist/index.cjs.map +0 -1
  8. package/dist/index.d.cts +0 -462
  9. package/sanity.json +0 -8
  10. package/src/__tests__/fixtures/createEpicTestStore.ts +0 -28
  11. package/src/__tests__/fixtures/listenMock.ts +0 -9
  12. package/src/__tests__/fixtures/mockSanityClient.ts +0 -84
  13. package/src/__tests__/fixtures/renderWithProviders.tsx +0 -55
  14. package/src/__tests__/fixtures/rootState.ts +0 -27
  15. package/src/__tests__/fixtures/withinDialog.ts +0 -28
  16. package/src/components/AssetGridVirtualized/index.tsx +0 -94
  17. package/src/components/AssetMetadata/index.tsx +0 -122
  18. package/src/components/AssetTableVirtualized/index.tsx +0 -73
  19. package/src/components/AutoTagInputWrapper/index.tsx +0 -87
  20. package/src/components/Browser/Browser.test.tsx +0 -45
  21. package/src/components/Browser/index.tsx +0 -90
  22. package/src/components/Browser/useBrowserInit.ts +0 -126
  23. package/src/components/ButtonAssetCopy/index.tsx +0 -65
  24. package/src/components/ButtonViewGroup/index.tsx +0 -39
  25. package/src/components/CardAsset/CardAsset.test.tsx +0 -323
  26. package/src/components/CardAsset/index.tsx +0 -290
  27. package/src/components/CardUpload/index.tsx +0 -161
  28. package/src/components/Controls/index.tsx +0 -136
  29. package/src/components/DebugControls/index.tsx +0 -80
  30. package/src/components/Dialog/index.tsx +0 -11
  31. package/src/components/DialogAssetEdit/Details.tsx +0 -181
  32. package/src/components/DialogAssetEdit/DialogAssetEdit.test.tsx +0 -216
  33. package/src/components/DialogAssetEdit/index.tsx +0 -492
  34. package/src/components/DialogConfirm/index.tsx +0 -88
  35. package/src/components/DialogSearchFacets/index.tsx +0 -42
  36. package/src/components/DialogTagCreate/DialogTagCreate.test.tsx +0 -121
  37. package/src/components/DialogTagCreate/index.tsx +0 -103
  38. package/src/components/DialogTagEdit/DialogTagEdit.test.tsx +0 -165
  39. package/src/components/DialogTagEdit/index.tsx +0 -190
  40. package/src/components/DialogTags/index.tsx +0 -45
  41. package/src/components/Dialogs/index.tsx +0 -76
  42. package/src/components/DocumentList/index.tsx +0 -62
  43. package/src/components/FileAssetPreview/index.tsx +0 -37
  44. package/src/components/FileIcon/index.tsx +0 -43
  45. package/src/components/FormBuilderTool/FormBuilderTool.test.tsx +0 -63
  46. package/src/components/FormBuilderTool/index.tsx +0 -69
  47. package/src/components/FormFieldInputLabel/index.tsx +0 -66
  48. package/src/components/FormFieldInputTags/index.tsx +0 -98
  49. package/src/components/FormFieldInputText/index.tsx +0 -41
  50. package/src/components/FormFieldInputTextarea/index.tsx +0 -43
  51. package/src/components/FormSubmitButton/index.tsx +0 -59
  52. package/src/components/Header/index.tsx +0 -80
  53. package/src/components/Image/index.tsx +0 -41
  54. package/src/components/Items/index.tsx +0 -68
  55. package/src/components/Notifications/index.tsx +0 -24
  56. package/src/components/OrderSelect/index.tsx +0 -66
  57. package/src/components/PickedBar/index.tsx +0 -77
  58. package/src/components/Progress/index.tsx +0 -38
  59. package/src/components/ReduxProvider/index.tsx +0 -96
  60. package/src/components/SearchFacet/index.tsx +0 -66
  61. package/src/components/SearchFacetNumber/index.tsx +0 -133
  62. package/src/components/SearchFacetSelect/index.tsx +0 -110
  63. package/src/components/SearchFacetString/index.tsx +0 -88
  64. package/src/components/SearchFacetTags/index.tsx +0 -121
  65. package/src/components/SearchFacets/index.tsx +0 -72
  66. package/src/components/SearchFacetsControl/index.tsx +0 -140
  67. package/src/components/TableHeader/index.tsx +0 -110
  68. package/src/components/TableHeaderItem/index.tsx +0 -61
  69. package/src/components/TableRowAsset/index.tsx +0 -420
  70. package/src/components/TableRowUpload/index.tsx +0 -164
  71. package/src/components/Tag/index.tsx +0 -200
  72. package/src/components/TagIcon/index.tsx +0 -22
  73. package/src/components/TagView/index.tsx +0 -39
  74. package/src/components/TagViewHeader/index.tsx +0 -70
  75. package/src/components/TagsPanel/index.tsx +0 -40
  76. package/src/components/TagsVirtualized/index.tsx +0 -160
  77. package/src/components/TextInputNumber/index.tsx +0 -32
  78. package/src/components/TextInputSearch/index.tsx +0 -60
  79. package/src/components/Tool/index.tsx +0 -13
  80. package/src/components/UploadDropzone/UploadDropzone.test.tsx +0 -40
  81. package/src/components/UploadDropzone/index.tsx +0 -173
  82. package/src/config/orders.ts +0 -28
  83. package/src/config/searchFacets.ts +0 -312
  84. package/src/constants.ts +0 -87
  85. package/src/contexts/AssetSourceDispatchContext.tsx +0 -37
  86. package/src/contexts/DropzoneDispatchContext.tsx +0 -34
  87. package/src/contexts/ToolOptionsContext.tsx +0 -65
  88. package/src/formSchema/index.test.ts +0 -56
  89. package/src/formSchema/index.ts +0 -39
  90. package/src/hooks/useBreakpointIndex.ts +0 -49
  91. package/src/hooks/useKeyPress.ts +0 -39
  92. package/src/hooks/useOnScreen.ts +0 -34
  93. package/src/hooks/usePortalPopoverProps.ts +0 -13
  94. package/src/hooks/useTypedSelector.ts +0 -7
  95. package/src/hooks/useVersionedClient.ts +0 -6
  96. package/src/index.ts +0 -5
  97. package/src/modules/assets/actions.ts +0 -42
  98. package/src/modules/assets/deleteAndUpdateEpics.test.ts +0 -87
  99. package/src/modules/assets/fetchEpic.test.ts +0 -73
  100. package/src/modules/assets/index.ts +0 -825
  101. package/src/modules/assets/reducer.test.ts +0 -91
  102. package/src/modules/assets/tagsAndListenerEpics.test.ts +0 -206
  103. package/src/modules/debug/index.ts +0 -28
  104. package/src/modules/dialog/actions.ts +0 -10
  105. package/src/modules/dialog/epics.test.ts +0 -168
  106. package/src/modules/dialog/index.ts +0 -238
  107. package/src/modules/dialog/reducer.test.ts +0 -185
  108. package/src/modules/index.ts +0 -124
  109. package/src/modules/notifications/epics.test.ts +0 -374
  110. package/src/modules/notifications/index.ts +0 -199
  111. package/src/modules/notifications/reducer.test.ts +0 -54
  112. package/src/modules/search/index.test.ts +0 -36
  113. package/src/modules/search/index.ts +0 -167
  114. package/src/modules/selected/index.ts +0 -22
  115. package/src/modules/selectors.test.ts +0 -21
  116. package/src/modules/selectors.ts +0 -17
  117. package/src/modules/tags/epics.test.ts +0 -96
  118. package/src/modules/tags/index.test.ts +0 -42
  119. package/src/modules/tags/index.ts +0 -540
  120. package/src/modules/types.ts +0 -3
  121. package/src/modules/uploads/actions.ts +0 -13
  122. package/src/modules/uploads/epics.test.ts +0 -109
  123. package/src/modules/uploads/index.test.ts +0 -59
  124. package/src/modules/uploads/index.ts +0 -282
  125. package/src/operators/checkTagName.test.ts +0 -29
  126. package/src/operators/checkTagName.ts +0 -33
  127. package/src/operators/debugThrottle.ts +0 -25
  128. package/src/plugin.tsx +0 -54
  129. package/src/schemas/tag.ts +0 -28
  130. package/src/styled/GlobalStyles/index.tsx +0 -40
  131. package/src/styled/react-select/creatable.tsx +0 -184
  132. package/src/styled/react-select/single.tsx +0 -184
  133. package/src/types/index.ts +0 -379
  134. package/src/types/sanity-ui.d.ts +0 -6
  135. package/src/utils/applyMediaTags.ts +0 -87
  136. package/src/utils/blocksToText.test.ts +0 -43
  137. package/src/utils/blocksToText.ts +0 -27
  138. package/src/utils/constructFilter.test.ts +0 -120
  139. package/src/utils/constructFilter.ts +0 -98
  140. package/src/utils/generatePreviewBlobUrl.test.ts +0 -70
  141. package/src/utils/generatePreviewBlobUrl.ts +0 -53
  142. package/src/utils/getAssetResolution.test.ts +0 -13
  143. package/src/utils/getAssetResolution.ts +0 -7
  144. package/src/utils/getDocumentAssetIds.test.ts +0 -50
  145. package/src/utils/getDocumentAssetIds.ts +0 -35
  146. package/src/utils/getSchemeColor.test.ts +0 -12
  147. package/src/utils/getSchemeColor.ts +0 -43
  148. package/src/utils/getTagSelectOptions.test.ts +0 -44
  149. package/src/utils/getTagSelectOptions.ts +0 -16
  150. package/src/utils/getUniqueDocuments.test.ts +0 -26
  151. package/src/utils/getUniqueDocuments.ts +0 -15
  152. package/src/utils/imageDprUrl.test.ts +0 -46
  153. package/src/utils/imageDprUrl.ts +0 -27
  154. package/src/utils/isSupportedAssetType.test.ts +0 -16
  155. package/src/utils/isSupportedAssetType.ts +0 -15
  156. package/src/utils/mediaField.ts +0 -73
  157. package/src/utils/sanitizeFormData.test.ts +0 -59
  158. package/src/utils/sanitizeFormData.ts +0 -26
  159. package/src/utils/typeGuards.test.ts +0 -18
  160. package/src/utils/typeGuards.ts +0 -9
  161. package/src/utils/uploadSanityAsset.test.ts +0 -29
  162. package/src/utils/uploadSanityAsset.ts +0 -97
  163. package/src/utils/withMaxConcurrency.test.ts +0 -43
  164. package/src/utils/withMaxConcurrency.ts +0 -55
  165. package/src/utils/zodFormResolver.ts +0 -17
  166. package/v2-incompatible.js +0 -11
@@ -1,59 +0,0 @@
1
- // @vitest-environment node
2
-
3
- import {describe, expect, it} from 'vitest'
4
-
5
- import sanitizeFormData from './sanitizeFormData'
6
-
7
- describe('sanitizeFormData', () => {
8
- it('maps empty string, undefined, and empty array to null', () => {
9
- expect(
10
- sanitizeFormData({
11
- a: '',
12
- b: undefined,
13
- c: [],
14
- }),
15
- ).toEqual({
16
- a: null,
17
- b: null,
18
- c: null,
19
- })
20
- })
21
-
22
- it('trims non-empty strings', () => {
23
- expect(sanitizeFormData({title: ' hello '})).toEqual({title: 'hello'})
24
- })
25
-
26
- it('recurses into plain objects', () => {
27
- expect(
28
- sanitizeFormData({
29
- opt: {
30
- media: {
31
- tags: [],
32
- },
33
- },
34
- }),
35
- ).toEqual({
36
- opt: {
37
- media: {
38
- tags: null,
39
- },
40
- },
41
- })
42
- })
43
-
44
- it('preserves null and non-empty arrays', () => {
45
- expect(
46
- sanitizeFormData({
47
- kept: null,
48
- tags: [{_ref: 't1'}],
49
- }),
50
- ).toEqual({
51
- kept: null,
52
- tags: [{_ref: 't1'}],
53
- })
54
- })
55
-
56
- it('preserves numbers and booleans', () => {
57
- expect(sanitizeFormData({n: 0, ok: false})).toEqual({n: 0, ok: false})
58
- })
59
- })
@@ -1,26 +0,0 @@
1
- // Recursively sanitize form data:
2
- // - convert empty strings, undefined values and empty arrays to null (to correctly unset / delete fields)
3
- // - trim whitespace on string fleids
4
-
5
- type FormData = Record<string, any>
6
-
7
- const sanitizeFormData = (formData: FormData): FormData => {
8
- return Object.keys(formData).reduce((acc: FormData, key) => {
9
- const val = formData[key]
10
-
11
- // TODO: refactor
12
- if (typeof val === 'object' && val !== null && val.constructor !== Array) {
13
- acc[key] = sanitizeFormData(val)
14
- } else if (val === '' || typeof val === 'undefined' || val?.length === 0) {
15
- acc[key] = null
16
- } else if (typeof val === 'string' && val) {
17
- acc[key] = formData[key].trim()
18
- } else {
19
- acc[key] = formData[key]
20
- }
21
-
22
- return acc
23
- }, {})
24
- }
25
-
26
- export default sanitizeFormData
@@ -1,18 +0,0 @@
1
- import {describe, expect, it} from 'vitest'
2
-
3
- import type {Asset} from '../types'
4
- import {isFileAsset, isImageAsset} from './typeGuards'
5
-
6
- describe('typeGuards', () => {
7
- it('isFileAsset narrows sanity.fileAsset', () => {
8
- const file = {_type: 'sanity.fileAsset'} as Asset
9
- expect(isFileAsset(file)).toBe(true)
10
- expect(isImageAsset(file)).toBe(false)
11
- })
12
-
13
- it('isImageAsset narrows sanity.imageAsset', () => {
14
- const image = {_type: 'sanity.imageAsset'} as Asset
15
- expect(isImageAsset(image)).toBe(true)
16
- expect(isFileAsset(image)).toBe(false)
17
- })
18
- })
@@ -1,9 +0,0 @@
1
- import type {Asset, FileAsset, ImageAsset} from '../types'
2
-
3
- export const isFileAsset = (asset: Asset): asset is FileAsset => {
4
- return (asset as FileAsset)._type === 'sanity.fileAsset'
5
- }
6
-
7
- export const isImageAsset = (asset: Asset): asset is ImageAsset => {
8
- return (asset as ImageAsset)._type === 'sanity.imageAsset'
9
- }
@@ -1,29 +0,0 @@
1
- import {firstValueFrom} from 'rxjs'
2
- import {afterEach, describe, expect, it} from 'vitest'
3
-
4
- import {hashFile$} from './uploadSanityAsset'
5
-
6
- describe('hashFile$', () => {
7
- const cryptoRef = globalThis.crypto
8
-
9
- afterEach(() => {
10
- Object.defineProperty(globalThis, 'crypto', {
11
- value: cryptoRef,
12
- configurable: true,
13
- writable: true,
14
- })
15
- })
16
-
17
- it('errors when Web Crypto is unavailable', async () => {
18
- Object.defineProperty(globalThis, 'crypto', {
19
- value: undefined,
20
- configurable: true,
21
- writable: true,
22
- })
23
-
24
- await expect(firstValueFrom(hashFile$(new File(['x'], 'blob.bin')))).rejects.toMatchObject({
25
- message: expect.stringMatching(/secure contexts/i),
26
- statusCode: 500,
27
- })
28
- })
29
- })
@@ -1,97 +0,0 @@
1
- // Sourced from:
2
- // https://github.com/sanity-io/sanity/blob/ccb777e115a8cdf20d81a9a2bc9d8c228568faff/packages/%40sanity/form-builder/src/sanity/inputs/client-adapters/assets.ts
3
-
4
- import type {SanityAssetDocument, SanityClient, SanityImageAssetDocument} from '@sanity/client'
5
- import {Observable, of, throwError} from 'rxjs'
6
- import {map, mergeMap} from 'rxjs/operators'
7
-
8
- import type {HttpError} from '../types'
9
- import {withMaxConcurrency} from './withMaxConcurrency'
10
-
11
- const fetchExisting$ = (client: SanityClient, type: string, hash: string) => {
12
- return client.observable.fetch('*[_type == $documentType && sha1hash == $hash][0]', {
13
- documentType: type,
14
- hash,
15
- })
16
- }
17
-
18
- const readFile$ = (file: File): Observable<ArrayBuffer> => {
19
- return new Observable((subscriber) => {
20
- const reader = new FileReader()
21
- reader.onload = () => {
22
- subscriber.next(reader.result as ArrayBuffer)
23
- subscriber.complete()
24
- }
25
- reader.onerror = (err) => {
26
- subscriber.error(err)
27
- }
28
- reader.readAsArrayBuffer(file)
29
- return () => {
30
- reader.abort()
31
- }
32
- })
33
- }
34
-
35
- const hexFromBuffer = (buffer: ArrayBuffer): string => {
36
- return Array.prototype.map
37
- .call(new Uint8Array(buffer), (x) => `00${x.toString(16)}`.slice(-2))
38
- .join('')
39
- }
40
-
41
- export const hashFile$ = (file: File): Observable<string> => {
42
- if (!window.crypto || !window.crypto.subtle || !window.FileReader) {
43
- return throwError({
44
- message: 'Unable to generate hash: uploads are only allowed in secure contexts',
45
- statusCode: 500,
46
- })
47
- }
48
- return readFile$(file).pipe(
49
- mergeMap((arrayBuffer) => window.crypto.subtle.digest('SHA-1', arrayBuffer)),
50
- map(hexFromBuffer),
51
- )
52
- }
53
-
54
- const uploadSanityAsset$ = (
55
- client: SanityClient,
56
- assetType: 'file' | 'image',
57
- file: File,
58
- hash: string,
59
- ) => {
60
- return of(null).pipe(
61
- // NOTE: the sanity api will still dedupe unique files, but this saves us from uploading the asset file entirely
62
- mergeMap(() => fetchExisting$(client, `sanity.${assetType}Asset`, hash)),
63
- // Cancel if the asset already exists
64
- mergeMap((existingAsset: SanityAssetDocument | SanityImageAssetDocument | null) => {
65
- if (existingAsset) {
66
- return throwError({
67
- message: 'Asset already exists',
68
- statusCode: 409,
69
- } as HttpError)
70
- }
71
-
72
- return of(null)
73
- }),
74
- mergeMap(() => {
75
- // Begin upload if no existing asset found
76
- return client.observable.assets
77
- .upload(assetType, file, {
78
- extract: ['blurhash', 'exif', 'location', 'lqip', 'palette'],
79
- preserveFilename: true,
80
- })
81
- .pipe(
82
- map((event) =>
83
- event.type === 'response'
84
- ? {
85
- // rewrite to a 'complete' event
86
- asset: event.body.document,
87
- id: event.body.document._id,
88
- type: 'complete',
89
- }
90
- : event,
91
- ),
92
- )
93
- }),
94
- )
95
- }
96
-
97
- export const uploadAsset$ = withMaxConcurrency(uploadSanityAsset$)
@@ -1,43 +0,0 @@
1
- import {Observable, firstValueFrom} from 'rxjs'
2
- import {describe, expect, it} from 'vitest'
3
-
4
- import {createThrottler, withMaxConcurrency} from './withMaxConcurrency'
5
-
6
- describe('createThrottler', () => {
7
- it('never runs more observables concurrently than the limit', async () => {
8
- let active = 0
9
- let maxActive = 0
10
- const request = createThrottler(2)
11
-
12
- const mk = () =>
13
- new Observable<number>((sub) => {
14
- active++
15
- maxActive = Math.max(maxActive, active)
16
- queueMicrotask(() => {
17
- active--
18
- sub.next(1)
19
- sub.complete()
20
- })
21
- })
22
-
23
- await Promise.all([
24
- firstValueFrom(request(mk())),
25
- firstValueFrom(request(mk())),
26
- firstValueFrom(request(mk())),
27
- ])
28
-
29
- expect(maxActive).toBe(2)
30
- })
31
- })
32
-
33
- describe('withMaxConcurrency', () => {
34
- it('wraps a function so each call returns a single-value observable', async () => {
35
- const fn = (n: number) =>
36
- new Observable<number>((sub) => {
37
- sub.next(n)
38
- sub.complete()
39
- })
40
- const wrapped = withMaxConcurrency(fn, 4)
41
- await expect(firstValueFrom(wrapped(7))).resolves.toBe(7)
42
- })
43
- })
@@ -1,55 +0,0 @@
1
- import {Subject, Subscription, Observable, from} from 'rxjs'
2
- // Takes a observable-returning function and returns a new function that limits on the number of
3
- // concurrent observables.
4
- import {first, mergeMap} from 'rxjs/operators'
5
-
6
- const DEFAULT_CONCURRENCY = 4
7
-
8
- function remove<T>(array: Array<T>, item: T): Array<T> {
9
- const index = array.indexOf(item)
10
- if (index > -1) {
11
- array.splice(index, 1)
12
- }
13
- return array
14
- }
15
-
16
- export const createThrottler = (concurrency: number = DEFAULT_CONCURRENCY) => {
17
- const currentSubscriptions: Array<Subscription> = []
18
- const pendingObservables: Array<Observable<any>> = []
19
- const ready$ = new Subject()
20
-
21
- function request(observable: Observable<any>): Observable<any> {
22
- return new Observable((observer) => {
23
- if (currentSubscriptions.length >= concurrency) {
24
- return scheduleAndWait$(observable)
25
- .pipe(mergeMap(request)) //
26
- .subscribe(observer)
27
- }
28
- const subscription = observable.subscribe(observer)
29
- currentSubscriptions.push(subscription)
30
- return () => {
31
- remove(currentSubscriptions, subscription)
32
- remove(pendingObservables, observable)
33
- subscription.unsubscribe()
34
- while (pendingObservables.length > 0 && currentSubscriptions.length < concurrency) {
35
- ready$.next(pendingObservables.shift())
36
- }
37
- }
38
- })
39
- }
40
-
41
- function scheduleAndWait$(observable: Observable<any>): Observable<any> {
42
- pendingObservables.push(observable)
43
- return ready$.asObservable().pipe(first((obs) => obs === observable))
44
- }
45
-
46
- return request
47
- }
48
-
49
- export const withMaxConcurrency = (
50
- func: (...args: any[]) => Observable<any>,
51
- concurrency: number = DEFAULT_CONCURRENCY,
52
- ) => {
53
- const throttler = createThrottler(concurrency)
54
- return (...args: Array<any>) => from(throttler(func(...args)))
55
- }
@@ -1,17 +0,0 @@
1
- import {zodResolver} from '@hookform/resolvers/zod'
2
- import type {FieldValues, Resolver} from 'react-hook-form'
3
-
4
- /**
5
- * `@hookform/resolvers/zod` resolves its own `zod` typings through dependency
6
- * hoisting, which in this monorepo lands on zod v4, while this plugin authors its
7
- * form schemas with zod v3. The resolver accepts v3 schema instances correctly at
8
- * runtime, so this thin wrapper only bridges the type-only v3/v4 mismatch. The
9
- * react-hook-form field types stay fully checked at the call sites.
10
- */
11
- export default function zodFormResolver<TFieldValues extends FieldValues>(
12
- schema: unknown,
13
- ): Resolver<TFieldValues> {
14
- return zodResolver(
15
- schema as Parameters<typeof zodResolver>[0],
16
- ) as unknown as Resolver<TFieldValues>
17
- }
@@ -1,11 +0,0 @@
1
- const {showIncompatiblePluginDialog} = require('@sanity/incompatible-plugin')
2
- const {name, version} = require('./package.json')
3
-
4
- export default showIncompatiblePluginDialog({
5
- name: name,
6
- versions: {
7
- v3: version,
8
- v2: '^1.4.13',
9
- },
10
- sanityExchangeUrl: 'https://www.sanity.io/plugins/sanity-plugin-media',
11
- })