sanity-plugin-cloudinary 0.2.2 → 1.0.0-v3-studio.3
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/LICENSE +1 -1
- package/README.md +160 -66
- package/lib/index.esm.js +2 -0
- package/lib/index.esm.js.map +1 -0
- package/lib/index.js +2 -0
- package/lib/index.js.map +1 -0
- package/lib/src/index.d.ts +35 -0
- package/package.json +67 -41
- package/sanity.json +3 -15
- package/src/arrayFunctions.tsx +71 -0
- package/src/components/AssetDiff.tsx +44 -0
- package/src/components/AssetPreview.tsx +41 -0
- package/src/components/CloudinaryInput.tsx +61 -0
- package/src/components/SecretsConfigView.tsx +39 -0
- package/src/components/VideoPlayer.tsx +62 -0
- package/src/components/WidgetInput.tsx +66 -0
- package/src/components/asset-source/CloudinaryAssetSource.tsx +155 -0
- package/src/components/asset-source/Icon.tsx +93 -0
- package/src/index.ts +30 -0
- package/src/schema/cloudinaryAsset.ts +101 -0
- package/src/schema/cloudinaryAssetDerived.ts +26 -0
- package/src/typings.d.ts +74 -0
- package/src/utils.ts +115 -0
- package/v2-incompatible.js +11 -0
- package/dist/arrayFunctions.js +0 -82
- package/dist/arrayFunctions.js.map +0 -1
- package/dist/components/AssetDiff.js +0 -62
- package/dist/components/AssetDiff.js.map +0 -1
- package/dist/components/AssetPreview.js +0 -46
- package/dist/components/AssetPreview.js.map +0 -1
- package/dist/components/CloudinaryInput.js +0 -90
- package/dist/components/CloudinaryInput.js.map +0 -1
- package/dist/components/SecretsConfigView.js +0 -37
- package/dist/components/SecretsConfigView.js.map +0 -1
- package/dist/components/VideoPlayer.js +0 -70
- package/dist/components/VideoPlayer.js.map +0 -1
- package/dist/components/WidgetInput.js +0 -87
- package/dist/components/WidgetInput.js.map +0 -1
- package/dist/index.js +0 -24
- package/dist/index.js.map +0 -1
- package/dist/schema/cloudinary.js +0 -19
- package/dist/schema/cloudinary.js.map +0 -1
- package/dist/schema/cloudinaryAsset.js +0 -100
- package/dist/schema/cloudinaryAsset.js.map +0 -1
- package/dist/schema/cloudinaryAssetDerived.js +0 -22
- package/dist/schema/cloudinaryAssetDerived.js.map +0 -1
- package/dist/typings.d.js +0 -8
- package/dist/typings.d.js.map +0 -1
- package/dist/utils.js +0 -92
- package/dist/utils.js.map +0 -1
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
/* eslint-disable camelcase */
|
|
2
|
+
import React, {useCallback, useEffect, useRef, useState} from 'react'
|
|
3
|
+
import {Box, Button, Dialog, Flex, Spinner, Stack, Text} from '@sanity/ui'
|
|
4
|
+
import {CloudinaryMediaLibrary, InsertHandlerParams} from '../../typings'
|
|
5
|
+
import {createMediaLibrary, decodeSourceId, encodeFilename, encodeSourceId} from '../../utils'
|
|
6
|
+
import styled from 'styled-components'
|
|
7
|
+
import {useSecrets} from '@sanity/studio-secrets'
|
|
8
|
+
import SecretsConfigView, {namespace, Secrets} from '../SecretsConfigView'
|
|
9
|
+
import {AssetSourceComponentProps, ImageAsset} from 'sanity'
|
|
10
|
+
import {PlugIcon} from '@sanity/icons'
|
|
11
|
+
|
|
12
|
+
export const Widget = styled.div`
|
|
13
|
+
height: 70vh;
|
|
14
|
+
`
|
|
15
|
+
|
|
16
|
+
export function CloudinaryAssetSource(props: AssetSourceComponentProps) {
|
|
17
|
+
const {onClose} = props
|
|
18
|
+
|
|
19
|
+
const [loadingMessage, setLoadingMessage] = useState<string | undefined>(
|
|
20
|
+
'Loading Cloudinary Media Libary'
|
|
21
|
+
)
|
|
22
|
+
const library = useRef<CloudinaryMediaLibrary | undefined>()
|
|
23
|
+
const contentRef = useRef<HTMLDivElement | null>(null)
|
|
24
|
+
const {secrets} = useSecrets<Secrets>(namespace)
|
|
25
|
+
const cloudName = secrets?.cloudName
|
|
26
|
+
const apiKey = secrets?.apiKey
|
|
27
|
+
const [widgetId] = useState(() => `cloundinaryWidget-${Date.now()}`)
|
|
28
|
+
const [showSettings, setShowSettings] = useState(false)
|
|
29
|
+
|
|
30
|
+
const propsRef = useRef(props)
|
|
31
|
+
|
|
32
|
+
useEffect(() => {
|
|
33
|
+
// because we have to access props after loading js in a callback,
|
|
34
|
+
// we cannot pass props as dependecnies as that will cause infinite updates
|
|
35
|
+
// this takes a snapshot of props, so we can access them later
|
|
36
|
+
propsRef.current = props
|
|
37
|
+
}, [props])
|
|
38
|
+
|
|
39
|
+
const handleClose = useCallback(() => {
|
|
40
|
+
if (library.current) {
|
|
41
|
+
library.current.hide()
|
|
42
|
+
}
|
|
43
|
+
onClose()
|
|
44
|
+
}, [onClose, library])
|
|
45
|
+
|
|
46
|
+
useEffect(() => {
|
|
47
|
+
if (!cloudName || !apiKey) {
|
|
48
|
+
return
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
createMediaLibrary({
|
|
52
|
+
cloudName,
|
|
53
|
+
apiKey,
|
|
54
|
+
inlineContainer: `#${widgetId}`,
|
|
55
|
+
libraryCreated: (lib: CloudinaryMediaLibrary) => {
|
|
56
|
+
library.current = lib
|
|
57
|
+
const selectedAssets = propsRef.current.selectedAssets
|
|
58
|
+
const firstSelectedAsset = selectedAssets ? selectedAssets[0] : null
|
|
59
|
+
|
|
60
|
+
// eslint-disable-next-line no-undef
|
|
61
|
+
const iframe: ChildNode | null | undefined =
|
|
62
|
+
contentRef.current && contentRef.current.firstChild
|
|
63
|
+
if (iframe && iframe instanceof HTMLIFrameElement) {
|
|
64
|
+
setLoadingMessage(undefined)
|
|
65
|
+
let asset
|
|
66
|
+
if (
|
|
67
|
+
propsRef.current.selectionType === 'single' &&
|
|
68
|
+
firstSelectedAsset &&
|
|
69
|
+
firstSelectedAsset.source &&
|
|
70
|
+
firstSelectedAsset.source.id
|
|
71
|
+
) {
|
|
72
|
+
asset = decodeSourceId(firstSelectedAsset.source.id)
|
|
73
|
+
}
|
|
74
|
+
const folder = asset
|
|
75
|
+
? {
|
|
76
|
+
path: asset.public_id.split('/').slice(0, -1).join('/'),
|
|
77
|
+
resource_type: 'image',
|
|
78
|
+
}
|
|
79
|
+
: {path: '', resource_type: 'image'}
|
|
80
|
+
if (lib && contentRef.current) {
|
|
81
|
+
lib.show({folder, asset})
|
|
82
|
+
contentRef.current.style.visibility = 'visible'
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
insertHandler: ({assets}: InsertHandlerParams) => {
|
|
87
|
+
if (!library.current) {
|
|
88
|
+
return
|
|
89
|
+
}
|
|
90
|
+
const imageAssets = assets.filter((asset) => asset.resource_type === 'image')
|
|
91
|
+
if (imageAssets.length === 0) {
|
|
92
|
+
throw new Error('The selection did not contain any images.')
|
|
93
|
+
}
|
|
94
|
+
library.current.hide()
|
|
95
|
+
propsRef.current.onSelect(
|
|
96
|
+
imageAssets.map((asset) => {
|
|
97
|
+
const url =
|
|
98
|
+
asset.derived && asset.derived[0] ? asset.derived[0].secure_url : asset.secure_url
|
|
99
|
+
return {
|
|
100
|
+
kind: 'url',
|
|
101
|
+
value: url,
|
|
102
|
+
assetDocumentProps: {
|
|
103
|
+
_type: 'sanity.imageAsset',
|
|
104
|
+
originalFilename: encodeFilename(asset),
|
|
105
|
+
source: {
|
|
106
|
+
id: encodeSourceId(asset),
|
|
107
|
+
name: `cloudinary:${cloudName}`,
|
|
108
|
+
},
|
|
109
|
+
} as ImageAsset,
|
|
110
|
+
}
|
|
111
|
+
})
|
|
112
|
+
)
|
|
113
|
+
},
|
|
114
|
+
})
|
|
115
|
+
}, [cloudName, apiKey, widgetId])
|
|
116
|
+
|
|
117
|
+
const hasConfig = apiKey && cloudName
|
|
118
|
+
return (
|
|
119
|
+
<Dialog
|
|
120
|
+
id="cloudinary-asset-source"
|
|
121
|
+
header="Select image from Cloudinary"
|
|
122
|
+
onClose={handleClose}
|
|
123
|
+
open
|
|
124
|
+
width={4}
|
|
125
|
+
>
|
|
126
|
+
<Box padding={4}>
|
|
127
|
+
{showSettings && <SecretsConfigView onClose={() => setShowSettings(false)} />}
|
|
128
|
+
<Flex flex={1} justify="flex-end">
|
|
129
|
+
<Button
|
|
130
|
+
color="primary"
|
|
131
|
+
icon={PlugIcon}
|
|
132
|
+
mode="bleed"
|
|
133
|
+
title="Configure"
|
|
134
|
+
onClick={() => setShowSettings(true)}
|
|
135
|
+
tabIndex={1}
|
|
136
|
+
text={hasConfig ? undefined : 'Configure Cloudinary plugin'}
|
|
137
|
+
/>
|
|
138
|
+
</Flex>
|
|
139
|
+
|
|
140
|
+
{hasConfig && loadingMessage && (
|
|
141
|
+
<Stack space={3}>
|
|
142
|
+
<Flex align="center" justify="center">
|
|
143
|
+
<Spinner muted />
|
|
144
|
+
</Flex>
|
|
145
|
+
<Text size={1} muted align="center">
|
|
146
|
+
{loadingMessage}
|
|
147
|
+
</Text>
|
|
148
|
+
</Stack>
|
|
149
|
+
)}
|
|
150
|
+
|
|
151
|
+
<Widget style={{visibility: 'hidden'}} ref={contentRef} id={widgetId} />
|
|
152
|
+
</Box>
|
|
153
|
+
</Dialog>
|
|
154
|
+
)
|
|
155
|
+
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
|
|
3
|
+
export function CloudinaryIcon() {
|
|
4
|
+
return (
|
|
5
|
+
<svg
|
|
6
|
+
version="1.1"
|
|
7
|
+
id="Layer_1"
|
|
8
|
+
x="0px"
|
|
9
|
+
y="0px"
|
|
10
|
+
width="1em"
|
|
11
|
+
height="1em"
|
|
12
|
+
viewBox="0 0 141.732 141.747"
|
|
13
|
+
enableBackground="new 0 0 141.732 141.747"
|
|
14
|
+
>
|
|
15
|
+
<g>
|
|
16
|
+
<path
|
|
17
|
+
fill="#0071CE"
|
|
18
|
+
d="M115.585,109.242c-1.609,0-3.107-1.024-3.635-2.637c-0.657-2.008,0.438-4.169,2.447-4.826
|
|
19
|
+
c7.278-2.382,11.98-8.761,11.98-16.252c0-9.487-7.718-17.206-17.205-17.206c-0.659,0-1.368,0.052-2.231,0.164l-3.741,0.485
|
|
20
|
+
l-0.537-3.735c-2.299-16.016-16.251-28.094-32.454-28.094c-13.395,0-25.32,8.019-30.377,20.43l-0.952,2.335l-2.52,0.046
|
|
21
|
+
c-11.581,0.213-21.003,9.804-21.003,21.379c0,8.45,4.906,16.156,12.498,19.631c1.921,0.88,2.766,3.15,1.886,5.071
|
|
22
|
+
c-0.88,1.921-3.149,2.764-5.07,1.887C14.363,103.202,7.703,92.766,7.703,81.331c0-14.88,11.465-27.345,26.028-28.876
|
|
23
|
+
c6.71-14.03,20.773-22.965,36.477-22.965c18.796,0,35.135,13.178,39.372,31.184c13.519,0.219,24.45,11.284,24.45,24.854
|
|
24
|
+
c0,10.693-6.934,20.146-17.253,23.523C116.382,109.18,115.98,109.242,115.585,109.242z"
|
|
25
|
+
/>
|
|
26
|
+
<path
|
|
27
|
+
fill="#DC8327"
|
|
28
|
+
d="M57.12,111.02c-0.001-0.001-0.001-0.001-0.002-0.001c-0.001,0-0.002-0.001-0.003-0.001h-0.001
|
|
29
|
+
c0,0-0.001-0.001-0.001-0.001l-0.001-0.001c0,0-0.001,0-0.001-0.001h-0.001l-0.001-0.001c0.001-0.001-0.001-0.001-0.001-0.001
|
|
30
|
+
l-0.001-0.001c0,0-0.001,0-0.001,0l-0.001-0.001c0.001,0.001-0.001-0.001-0.001-0.001s-0.002-0.001-0.003-0.001l-0.001-0.001H57.1
|
|
31
|
+
c-0.001-0.001-0.001-0.001-0.001-0.001l-0.001-0.001c-0.003-0.001-0.002-0.001-0.003-0.001c-0.001,0.001-0.001-0.001-0.002-0.001
|
|
32
|
+
l-0.001-0.001c0,0-0.001-0.001-0.002-0.001l-0.001-0.001c-0.001-0.001-0.003-0.001-0.004-0.001s-0.003-0.001-0.004-0.001
|
|
33
|
+
c-0.001-0.001-0.001-0.001-0.002-0.001h-0.001c-0.001-0.001-0.002-0.001-0.003-0.001c-0.001-0.001-0.003-0.001-0.003-0.001
|
|
34
|
+
c-0.001,0-0.001,0-0.001,0l-0.002-0.001c-0.001,0-0.001-0.001-0.001-0.001h-0.001c-0.059-0.021-0.122-0.034-0.188-0.037h-0.002
|
|
35
|
+
h-0.002c-0.001,0-0.001,0-0.002,0c0,0,0,0-0.001,0c0,0-0.001,0-0.001,0h-0.001c-0.001-0.001-0.001-0.001-0.001-0.001
|
|
36
|
+
c-0.001,0-0.002,0-0.002,0c-0.001,0-0.002,0-0.002,0h-0.001h-0.001h-0.001c-0.001,0-0.002,0-0.002,0h-0.001H56.86h-0.001h-0.001
|
|
37
|
+
c-0.001,0-0.001,0-0.001,0h-0.001h-0.001h-0.001h-0.001c-0.001,0-0.001,0-0.001,0c-1.656,0-3.011-1.348-3.021-3V74.29h2.567
|
|
38
|
+
c0.004,0,0.009,0,0.013,0c0.393,0.017,0.661-0.285,0.661-0.648c0-0.271-0.166-0.503-0.402-0.6l-12.379-8.544
|
|
39
|
+
c-0.222-0.153-0.515-0.153-0.737,0l-12.476,8.611c-0.234,0.161-0.335,0.456-0.251,0.727c0.085,0.271,0.335,0.455,0.619,0.455h2.58
|
|
40
|
+
l0.002,33.674c0.013,2.328,1.883,4.228,4.262,4.288c0.027,0.003,0.053,0.005,0.08,0.005h18.481c0.004,0,0.007,0,0.011,0
|
|
41
|
+
c0.17-0.003,0.324-0.071,0.438-0.18c0,0,0,0,0.001-0.001c0.002-0.002,0.004-0.004,0.005-0.005c0.001-0.001,0.002-0.001,0.003-0.003
|
|
42
|
+
c0,0,0.001-0.001,0.001-0.001l0.001-0.001l0.001-0.001l0.001-0.001l0.001-0.001c0.001-0.001,0.001-0.001,0.001-0.001
|
|
43
|
+
c0.002-0.001,0.001-0.001,0.002-0.002c0,0,0,0,0.001-0.001l0.001-0.001c0,0,0,0,0.001-0.001c0.112-0.116,0.182-0.273,0.183-0.447
|
|
44
|
+
v-0.002v-0.001v-0.001v-0.001v-0.001v-0.001v-0.001v-0.002C57.498,111.345,57.343,111.121,57.12,111.02z"
|
|
45
|
+
/>
|
|
46
|
+
<path
|
|
47
|
+
fill="#F4B21B"
|
|
48
|
+
d="M83.889,111.02c0,0-0.001-0.001-0.002-0.001c-0.001,0-0.002-0.001-0.003-0.001h-0.001
|
|
49
|
+
c-0.001-0.001-0.001-0.001-0.001-0.001l-0.001-0.001h-0.001c0,0-0.001-0.001-0.001-0.001c0,0-0.001-0.001-0.001-0.001
|
|
50
|
+
c0.001-0.001-0.001-0.001-0.002-0.001l-0.001-0.001h-0.001c-0.001,0-0.001-0.001-0.001-0.001c-0.002,0.001-0.002-0.001-0.002-0.001
|
|
51
|
+
l-0.002-0.001l-0.001-0.001h-0.001c0,0-0.001-0.001-0.001-0.001l-0.001-0.001c-0.001-0.001-0.002-0.001-0.002-0.001
|
|
52
|
+
c-0.001,0.001-0.001-0.001-0.003-0.001l-0.001-0.001l-0.001-0.001c0,0-0.001,0-0.002-0.001c-0.001-0.001-0.003-0.001-0.004-0.001
|
|
53
|
+
s-0.003-0.001-0.004-0.001c-0.001-0.001-0.001-0.001-0.002-0.001c-0.001,0-0.001,0-0.002-0.001c0,0-0.001,0-0.002-0.001
|
|
54
|
+
c-0.003-0.001-0.001-0.001-0.002-0.001c-0.003,0-0.001,0-0.002-0.001c0,0-0.001-0.001-0.002-0.001l-0.001-0.001h-0.001
|
|
55
|
+
c-0.059-0.021-0.122-0.034-0.188-0.037h-0.002c-0.001,0-0.001,0-0.001,0c-0.001,0-0.002,0-0.002,0s-0.001,0-0.001,0h-0.001h-0.001
|
|
56
|
+
l-0.001-0.001c-0.001,0-0.002,0-0.002,0c-0.001,0-0.002,0-0.002,0h-0.001c-0.001,0-0.001,0-0.001,0h-0.001
|
|
57
|
+
c-0.001,0-0.002,0-0.002,0s-0.001,0-0.002,0h-0.001c0,0-0.001,0-0.001,0h-0.001c-0.001,0-0.001,0-0.001,0h-0.001h-0.001h-0.001
|
|
58
|
+
h-0.001c-0.001,0-0.001,0-0.001,0c-1.655,0-3.01-1.348-3.02-3V81.829h2.579c0.009-0.001,0.016-0.001,0.026,0
|
|
59
|
+
c0.358,0,0.648-0.29,0.648-0.648c0-0.271-0.166-0.503-0.402-0.6l-12.38-8.544c-0.222-0.153-0.515-0.153-0.737,0L57.86,80.647
|
|
60
|
+
c-0.234,0.161-0.335,0.456-0.251,0.727c0.085,0.271,0.335,0.455,0.619,0.455h2.568l0.002,26.135
|
|
61
|
+
c0.011,2.329,1.884,4.23,4.264,4.289c0.026,0.003,0.052,0.004,0.078,0.004h18.481c0.004,0,0.007,0,0.011,0
|
|
62
|
+
c0.17-0.003,0.324-0.071,0.438-0.18c0,0,0,0,0.001-0.001c0.002-0.002,0.006-0.004,0.005-0.005c0.001-0.001,0.002-0.001,0.003-0.003
|
|
63
|
+
c0.001-0.001,0.001-0.001,0.001-0.001l0.001-0.001l0.001-0.001c0,0,0.001,0,0.001-0.001l0.001-0.001
|
|
64
|
+
c0.001,0,0.001-0.001,0.001-0.001c0.003-0.001,0.002-0.001,0.002-0.002c0,0,0,0,0.001-0.001c0,0,0,0,0.001-0.001
|
|
65
|
+
c0,0,0,0,0.001-0.001c0.112-0.116,0.182-0.273,0.183-0.447v-0.002v-0.001v-0.001v-0.001v-0.001v-0.001v-0.001v-0.002
|
|
66
|
+
C84.267,111.345,84.112,111.121,83.889,111.02z"
|
|
67
|
+
/>
|
|
68
|
+
<path
|
|
69
|
+
fill="#F2D864"
|
|
70
|
+
d="M110.667,111.02l-0.002-0.001c-0.001,0-0.002-0.001-0.003-0.001h-0.001
|
|
71
|
+
c-0.001-0.001-0.001-0.001-0.001-0.001l-0.001-0.001c-0.001,0-0.001,0-0.001-0.001h-0.001l-0.001-0.001
|
|
72
|
+
c-0.001-0.001-0.001-0.001-0.001-0.001s-0.001,0-0.001-0.001h-0.001c0,0-0.001-0.001-0.001-0.001
|
|
73
|
+
c-0.001,0.001-0.001-0.001-0.002-0.001c0.001-0.001-0.001-0.001-0.002-0.001l-0.001-0.001c-0.001,0-0.001,0-0.001,0
|
|
74
|
+
c-0.001-0.001-0.001-0.001-0.001-0.001l-0.001-0.001c-0.003-0.001-0.002-0.001-0.002-0.001c-0.001,0.001-0.001-0.001-0.003-0.001
|
|
75
|
+
l-0.001-0.001c0.001-0.001-0.001-0.001-0.002-0.001c0,0-0.001,0-0.001-0.001c-0.001-0.001-0.003-0.001-0.004-0.001
|
|
76
|
+
s-0.003-0.001-0.004-0.001l-0.002-0.001c0,0-0.001,0-0.002-0.001l-0.002-0.001c-0.003-0.001-0.003-0.001-0.002-0.001
|
|
77
|
+
c-0.003,0-0.003,0-0.002-0.001c-0.001,0-0.001-0.001-0.001-0.001c-0.001,0-0.002-0.001-0.002-0.001h-0.001
|
|
78
|
+
c-0.059-0.021-0.122-0.034-0.188-0.037h-0.001c-0.001,0-0.002,0-0.002,0c-0.001,0-0.002,0-0.003,0h-0.001h-0.001h-0.001
|
|
79
|
+
c-0.001-0.001-0.001-0.001-0.002-0.001c0,0-0.001,0-0.002,0c0,0-0.001,0-0.002,0h-0.001c0,0-0.001,0-0.001,0h-0.001
|
|
80
|
+
c-0.001,0-0.002,0-0.002,0h-0.002c0,0,0,0-0.001,0c0,0-0.001,0-0.001,0h-0.001c0,0-0.001,0-0.001,0h-0.001h-0.001h-0.001H110.4
|
|
81
|
+
c0,0-0.001,0-0.001,0c-1.655,0-3.01-1.348-3.02-3V89.365h2.573c0.004,0,0.009,0,0.013,0c0.365-0.009,0.661-0.285,0.661-0.648
|
|
82
|
+
c0-0.271-0.166-0.503-0.402-0.6l-12.38-8.544c-0.221-0.153-0.515-0.153-0.737,0l-12.476,8.61c-0.234,0.161-0.335,0.456-0.251,0.727
|
|
83
|
+
c0.085,0.271,0.335,0.455,0.619,0.455h2.573l0.002,18.599c0.013,2.329,1.885,4.231,4.264,4.289
|
|
84
|
+
c0.026,0.003,0.052,0.004,0.078,0.004h18.481c0.004,0,0.007,0,0.011,0c0.17-0.003,0.324-0.071,0.438-0.18l0.001-0.001
|
|
85
|
+
c0.002-0.002,0.005-0.004,0.005-0.005c0.001-0.001,0.002-0.001,0.003-0.003c0,0,0.001-0.001,0.001-0.001l0.001-0.001l0.001-0.001
|
|
86
|
+
l0.001-0.001l0.001-0.001l0.001-0.001c0.003-0.001,0.001-0.001,0.002-0.002c0,0,0,0,0.001-0.001l0.001-0.001c0,0,0,0,0.001-0.001
|
|
87
|
+
c0.112-0.116,0.182-0.273,0.183-0.447v-0.002v-0.001v-0.001v-0.001v-0.001v-0.001v-0.001v-0.002
|
|
88
|
+
C111.045,111.345,110.889,111.121,110.667,111.02z"
|
|
89
|
+
/>
|
|
90
|
+
</g>
|
|
91
|
+
</svg>
|
|
92
|
+
)
|
|
93
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import {cloudinaryAssetSchema} from './schema/cloudinaryAsset'
|
|
2
|
+
import {cloudinaryAssetDerivedSchema} from './schema/cloudinaryAssetDerived'
|
|
3
|
+
import {definePlugin, AssetSource} from 'sanity'
|
|
4
|
+
import {CloudinaryIcon} from './components/asset-source/Icon'
|
|
5
|
+
import {CloudinaryAssetSource} from './components/asset-source/CloudinaryAssetSource'
|
|
6
|
+
|
|
7
|
+
export {cloudinaryAssetSchema, cloudinaryAssetDerivedSchema}
|
|
8
|
+
|
|
9
|
+
export const cloudinarySchemaPlugin = definePlugin({
|
|
10
|
+
name: 'cloudinary-schema',
|
|
11
|
+
schema: {
|
|
12
|
+
types: [cloudinaryAssetSchema, cloudinaryAssetDerivedSchema],
|
|
13
|
+
},
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
export const cloudinaryImageSource: AssetSource = {
|
|
17
|
+
name: 'cloudinary-image',
|
|
18
|
+
title: 'Cloudinary',
|
|
19
|
+
icon: CloudinaryIcon,
|
|
20
|
+
component: CloudinaryAssetSource,
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export const cloudinaryAssetSourcePlugin = definePlugin({
|
|
24
|
+
name: 'cloudinart-asset-source',
|
|
25
|
+
form: {
|
|
26
|
+
image: {
|
|
27
|
+
assetSources: [cloudinaryImageSource],
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
})
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/* eslint-disable */
|
|
2
|
+
import CloudinaryInput from '../components/CloudinaryInput'
|
|
3
|
+
import AssetDiff from '../components/AssetDiff'
|
|
4
|
+
import AssetPreview from '../components/AssetPreview'
|
|
5
|
+
import {defineType} from 'sanity'
|
|
6
|
+
|
|
7
|
+
export const cloudinaryAssetSchema = defineType({
|
|
8
|
+
type: 'object',
|
|
9
|
+
name: 'cloudinary.asset',
|
|
10
|
+
fields: [
|
|
11
|
+
{
|
|
12
|
+
type: 'string',
|
|
13
|
+
name: 'public_id',
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
type: 'string',
|
|
17
|
+
name: 'resource_type',
|
|
18
|
+
// "image", "?"
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
type: 'string',
|
|
22
|
+
name: 'type',
|
|
23
|
+
// "upload", "?"
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
type: 'string',
|
|
27
|
+
name: 'format',
|
|
28
|
+
// "jpg"
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
type: 'number',
|
|
32
|
+
name: 'version',
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
type: 'url',
|
|
36
|
+
name: 'url',
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
type: 'url',
|
|
40
|
+
name: 'secure_url',
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
type: 'number',
|
|
44
|
+
name: 'width',
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
type: 'number',
|
|
48
|
+
name: 'height',
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
type: 'number',
|
|
52
|
+
name: 'bytes',
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
type: 'number',
|
|
56
|
+
name: 'duration',
|
|
57
|
+
// can be null
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
type: 'array',
|
|
61
|
+
name: 'tags',
|
|
62
|
+
of: [{type: 'string'}],
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
type: 'datetime',
|
|
66
|
+
name: 'created_at',
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
type: 'array',
|
|
70
|
+
name: 'derived',
|
|
71
|
+
of: [{type: 'cloudinary.assetDerived'}],
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
type: 'string',
|
|
75
|
+
name: 'access_mode',
|
|
76
|
+
},
|
|
77
|
+
// context array of unknown content
|
|
78
|
+
// metadata array of unknown content
|
|
79
|
+
],
|
|
80
|
+
...({
|
|
81
|
+
components: {
|
|
82
|
+
input: CloudinaryInput,
|
|
83
|
+
diff: AssetDiff,
|
|
84
|
+
preview: AssetPreview,
|
|
85
|
+
},
|
|
86
|
+
} as {}), //TODO revert this change when rc.1 is released
|
|
87
|
+
preview: {
|
|
88
|
+
select: {
|
|
89
|
+
url: 'url',
|
|
90
|
+
resource_type: 'resource_type',
|
|
91
|
+
derived: 'derived.0.url',
|
|
92
|
+
},
|
|
93
|
+
prepare({url, derived, resource_type}) {
|
|
94
|
+
return {
|
|
95
|
+
title: url,
|
|
96
|
+
resource_type,
|
|
97
|
+
url: derived || url,
|
|
98
|
+
}
|
|
99
|
+
},
|
|
100
|
+
},
|
|
101
|
+
})
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import {defineType} from 'sanity'
|
|
2
|
+
|
|
3
|
+
export type CloudinaryAssetDerived = {
|
|
4
|
+
raw_transformation: string
|
|
5
|
+
url: string
|
|
6
|
+
secure_url: string
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export const cloudinaryAssetDerivedSchema = defineType({
|
|
10
|
+
type: 'object',
|
|
11
|
+
name: 'cloudinary.assetDerived',
|
|
12
|
+
fields: [
|
|
13
|
+
{
|
|
14
|
+
type: 'string',
|
|
15
|
+
name: 'raw_transformation',
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
type: 'url',
|
|
19
|
+
name: 'url',
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
type: 'url',
|
|
23
|
+
name: 'secure_url',
|
|
24
|
+
},
|
|
25
|
+
],
|
|
26
|
+
})
|
package/src/typings.d.ts
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import {CSSProperties} from 'react'
|
|
2
|
+
import {CloudinaryAssetDerived} from './schema/cloudinaryAssetDerived'
|
|
3
|
+
|
|
4
|
+
declare module '*.css' {
|
|
5
|
+
const content: {[className: string]: CSSProperties}
|
|
6
|
+
export default content
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export type CloudinaryDerivative = {
|
|
10
|
+
url: string
|
|
11
|
+
secure_url: string
|
|
12
|
+
raw_transformation: string
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export type CloudinaryAssetResponse = {
|
|
16
|
+
public_id: string
|
|
17
|
+
resource_type: string
|
|
18
|
+
type: string
|
|
19
|
+
url: string
|
|
20
|
+
tags: string[]
|
|
21
|
+
secure_url: string
|
|
22
|
+
format: string
|
|
23
|
+
width: number
|
|
24
|
+
height: number
|
|
25
|
+
bytes: number
|
|
26
|
+
derived?: CloudinaryDerivative[]
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export type InsertHandlerParams = {
|
|
30
|
+
assets: CloudinaryAssetResponse[]
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export interface CloudinaryMediaLibrary {
|
|
34
|
+
show: (config?: {asset: any; folder: any}) => void
|
|
35
|
+
hide: () => void
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export type CloudinaryAsset = {
|
|
39
|
+
_type: string
|
|
40
|
+
_key?: string
|
|
41
|
+
_version: number
|
|
42
|
+
public_id: string
|
|
43
|
+
resource_type: string
|
|
44
|
+
type: string
|
|
45
|
+
format: string
|
|
46
|
+
version: number
|
|
47
|
+
url: string
|
|
48
|
+
secure_url: string
|
|
49
|
+
derived?: CloudinaryAssetDerived[]
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export type AssetDocument = {
|
|
53
|
+
_id: string
|
|
54
|
+
label?: string
|
|
55
|
+
title?: string
|
|
56
|
+
description?: string
|
|
57
|
+
source?: {
|
|
58
|
+
id: string
|
|
59
|
+
name: string
|
|
60
|
+
url?: string
|
|
61
|
+
}
|
|
62
|
+
creditLine?: string
|
|
63
|
+
originalFilename?: string
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
declare global {
|
|
67
|
+
// eslint-disable-next-line no-unused-vars
|
|
68
|
+
interface Window {
|
|
69
|
+
cloudinary: {
|
|
70
|
+
openMediaLibrary: (config: any, callbacks: any) => void
|
|
71
|
+
createMediaLibrary: (config: any, callbacks?: any) => CloudinaryMediaLibrary
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
package/src/utils.ts
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/* eslint-disable camelcase */
|
|
2
|
+
import {
|
|
3
|
+
CloudinaryAsset,
|
|
4
|
+
CloudinaryAssetResponse,
|
|
5
|
+
CloudinaryMediaLibrary,
|
|
6
|
+
InsertHandlerParams,
|
|
7
|
+
} from './typings'
|
|
8
|
+
|
|
9
|
+
const widgetSrc = 'https://media-library.cloudinary.com/global/all.js'
|
|
10
|
+
|
|
11
|
+
export function assetUrl(asset: CloudinaryAsset) {
|
|
12
|
+
if (asset.derived && asset.derived.length > 0) {
|
|
13
|
+
const [derived] = asset.derived
|
|
14
|
+
if (derived.secure_url) {
|
|
15
|
+
return derived.secure_url
|
|
16
|
+
}
|
|
17
|
+
return derived.url
|
|
18
|
+
}
|
|
19
|
+
if (asset.secure_url) {
|
|
20
|
+
return asset.secure_url
|
|
21
|
+
}
|
|
22
|
+
return asset.url
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export const openMediaSelector = (
|
|
26
|
+
cloudName: string,
|
|
27
|
+
apiKey: string,
|
|
28
|
+
multiple: boolean,
|
|
29
|
+
insertHandler: (params: InsertHandlerParams) => void,
|
|
30
|
+
selectedAsset?: CloudinaryAsset
|
|
31
|
+
) => {
|
|
32
|
+
loadJS(widgetSrc, () => {
|
|
33
|
+
const options: Record<string, any> = {
|
|
34
|
+
cloud_name: cloudName,
|
|
35
|
+
api_key: apiKey,
|
|
36
|
+
insert_caption: 'Select',
|
|
37
|
+
multiple,
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (selectedAsset) {
|
|
41
|
+
options.asset = {
|
|
42
|
+
public_id: selectedAsset.public_id,
|
|
43
|
+
type: selectedAsset.type,
|
|
44
|
+
resource_type: selectedAsset.resource_type,
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
window.cloudinary.openMediaLibrary(options, {insertHandler})
|
|
49
|
+
})
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export const createMediaLibrary = ({
|
|
53
|
+
cloudName,
|
|
54
|
+
apiKey,
|
|
55
|
+
inlineContainer,
|
|
56
|
+
libraryCreated,
|
|
57
|
+
insertHandler,
|
|
58
|
+
}: {
|
|
59
|
+
cloudName: string
|
|
60
|
+
apiKey: string
|
|
61
|
+
inlineContainer: string
|
|
62
|
+
libraryCreated: (library: CloudinaryMediaLibrary) => void
|
|
63
|
+
insertHandler: (params: InsertHandlerParams) => void
|
|
64
|
+
}) => {
|
|
65
|
+
loadJS(widgetSrc, () => {
|
|
66
|
+
const options: Record<string, any> = {
|
|
67
|
+
cloud_name: cloudName,
|
|
68
|
+
api_key: apiKey,
|
|
69
|
+
insert_caption: 'Select',
|
|
70
|
+
inline_container: inlineContainer,
|
|
71
|
+
remove_header: true,
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
libraryCreated(window.cloudinary.createMediaLibrary(options, {insertHandler}))
|
|
75
|
+
})
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export function loadJS(url: string, callback: () => void) {
|
|
79
|
+
const existingScript = document.getElementById('damWidget')
|
|
80
|
+
if (!existingScript) {
|
|
81
|
+
const script = document.createElement('script')
|
|
82
|
+
script.src = url
|
|
83
|
+
script.id = 'damWidget'
|
|
84
|
+
document.body.appendChild(script)
|
|
85
|
+
script.onload = () => {
|
|
86
|
+
if (callback) {
|
|
87
|
+
return callback()
|
|
88
|
+
}
|
|
89
|
+
return true
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
if (existingScript && callback) {
|
|
93
|
+
return callback()
|
|
94
|
+
}
|
|
95
|
+
return true
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export function encodeSourceId(asset: CloudinaryAssetResponse): string {
|
|
99
|
+
const {resource_type, public_id, type} = asset
|
|
100
|
+
return btoa(JSON.stringify({public_id, resource_type, type})) // Sort keys alphabetically!
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export function encodeFilename(asset: CloudinaryAssetResponse) {
|
|
104
|
+
return `${asset.public_id.split('/').slice(-1)[0]}.${asset.format}`
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export function decodeSourceId(sourceId: string): CloudinaryAssetResponse | undefined {
|
|
108
|
+
let sourceIdDecoded: any
|
|
109
|
+
try {
|
|
110
|
+
sourceIdDecoded = JSON.parse(atob(sourceId))
|
|
111
|
+
} catch (err) {
|
|
112
|
+
// Do nothing
|
|
113
|
+
}
|
|
114
|
+
return sourceIdDecoded
|
|
115
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
const {showIncompatiblePluginDialog} = require('@sanity/incompatible-plugin')
|
|
2
|
+
const {name, version, sanityExchangeUrl} = require('./package.json')
|
|
3
|
+
|
|
4
|
+
export default showIncompatiblePluginDialog({
|
|
5
|
+
name: name,
|
|
6
|
+
versions: {
|
|
7
|
+
v3: version,
|
|
8
|
+
v2: undefined,
|
|
9
|
+
},
|
|
10
|
+
sanityExchangeUrl,
|
|
11
|
+
})
|