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
package/package.json
CHANGED
|
@@ -1,61 +1,87 @@
|
|
|
1
1
|
{
|
|
2
|
-
"
|
|
2
|
+
"name": "sanity-plugin-cloudinary",
|
|
3
|
+
"version": "1.0.0-v3-studio.3",
|
|
4
|
+
"description": "> **NOTE**",
|
|
5
|
+
"author": "Sanity.io <hello@sanity.io>",
|
|
3
6
|
"license": "MIT",
|
|
7
|
+
"source": "./src/index.ts",
|
|
8
|
+
"main": "./lib/index.js",
|
|
9
|
+
"module": "./lib/index.esm.js",
|
|
10
|
+
"types": "./lib/src/index.d.ts",
|
|
11
|
+
"exports": {
|
|
12
|
+
".": {
|
|
13
|
+
"types": "./lib/src/index.d.ts",
|
|
14
|
+
"source": "./src/index.ts",
|
|
15
|
+
"import": "./lib/index.esm.js",
|
|
16
|
+
"require": "./lib/index.js",
|
|
17
|
+
"default": "./lib/index.esm.js"
|
|
18
|
+
}
|
|
19
|
+
},
|
|
4
20
|
"files": [
|
|
5
|
-
"
|
|
21
|
+
"src",
|
|
22
|
+
"lib",
|
|
23
|
+
"v2-incompatible.js",
|
|
6
24
|
"sanity.json"
|
|
7
25
|
],
|
|
8
26
|
"engines": {
|
|
9
|
-
"node": ">=
|
|
27
|
+
"node": ">=14.0.0"
|
|
10
28
|
},
|
|
11
29
|
"scripts": {
|
|
12
|
-
"build": "
|
|
13
|
-
"watch": "
|
|
14
|
-
"prepublishOnly": "
|
|
30
|
+
"build": "pkg-utils build",
|
|
31
|
+
"watch": "pkg-utils watch",
|
|
32
|
+
"prepublishOnly": "npm run build",
|
|
33
|
+
"clean": "rimraf lib",
|
|
34
|
+
"lint": "eslint .",
|
|
35
|
+
"prebuild": "npm run clean && plugin-kit verify-package --silent && pkg-utils",
|
|
36
|
+
"link-watch": "plugin-kit link-watch",
|
|
37
|
+
"prepare": "husky install"
|
|
15
38
|
},
|
|
16
39
|
"peerDependencies": {
|
|
17
|
-
"
|
|
18
|
-
"
|
|
19
|
-
"
|
|
20
|
-
"react": "^17.0",
|
|
21
|
-
"react-dom": "^17.0"
|
|
22
|
-
},
|
|
23
|
-
"husky": {
|
|
24
|
-
"hooks": {
|
|
25
|
-
"pre-commit": "sanipack verify"
|
|
26
|
-
}
|
|
27
|
-
},
|
|
28
|
-
"prettier": {
|
|
29
|
-
"printWidth": 80,
|
|
30
|
-
"semi": true,
|
|
31
|
-
"singleQuote": true,
|
|
32
|
-
"trailingComma": "es5"
|
|
40
|
+
"react": "^18.0.0",
|
|
41
|
+
"react-dom": "^18.0.0",
|
|
42
|
+
"sanity": "dev-preview || 3.0.0-rc.0"
|
|
33
43
|
},
|
|
34
|
-
"name": "sanity-plugin-cloudinary",
|
|
35
|
-
"author": "Sanity.io <hello@sanity.io>",
|
|
36
44
|
"devDependencies": {
|
|
37
|
-
"@
|
|
38
|
-
"@
|
|
39
|
-
"@sanity/
|
|
40
|
-
"@sanity/
|
|
41
|
-
"@
|
|
42
|
-
"@types/react": "^
|
|
45
|
+
"@commitlint/cli": "^17.2.0",
|
|
46
|
+
"@commitlint/config-conventional": "^17.2.0",
|
|
47
|
+
"@sanity/pkg-utils": "^1.16.2",
|
|
48
|
+
"@sanity/plugin-kit": "^2.0.7",
|
|
49
|
+
"@sanity/semantic-release-preset": "^2.0.2",
|
|
50
|
+
"@types/react": "^18.0.0",
|
|
51
|
+
"@types/styled-components": "^5.1.26",
|
|
43
52
|
"@types/video.js": "^7.3.15",
|
|
44
|
-
"
|
|
45
|
-
"
|
|
46
|
-
"
|
|
53
|
+
"@typescript-eslint/eslint-plugin": "^5.42.0",
|
|
54
|
+
"@typescript-eslint/parser": "^5.42.0",
|
|
55
|
+
"eslint": "^8.26.0",
|
|
56
|
+
"eslint-config-prettier": "^8.5.0",
|
|
57
|
+
"eslint-config-sanity": "^6.0.0",
|
|
58
|
+
"eslint-plugin-prettier": "^4.2.1",
|
|
59
|
+
"eslint-plugin-react": "^7.31.10",
|
|
60
|
+
"eslint-plugin-react-hooks": "^4.6.0",
|
|
61
|
+
"husky": "^8.0.1",
|
|
62
|
+
"lint-staged": "^13.0.3",
|
|
47
63
|
"postcss": "^8.0.0",
|
|
48
|
-
"
|
|
49
|
-
"
|
|
50
|
-
"
|
|
51
|
-
"
|
|
52
|
-
"
|
|
53
|
-
"typescript": "^4.2.2"
|
|
64
|
+
"prettier": "^2.7.1",
|
|
65
|
+
"react": "^18.0.0",
|
|
66
|
+
"rimraf": "^3.0.2",
|
|
67
|
+
"sanity": "dev-preview || 3.0.0-rc.0",
|
|
68
|
+
"typescript": "^4.8.4"
|
|
54
69
|
},
|
|
55
70
|
"dependencies": {
|
|
71
|
+
"@sanity/icons": "^1.3.6",
|
|
72
|
+
"@sanity/incompatible-plugin": "^1.0.4",
|
|
73
|
+
"@sanity/studio-secrets": "^2.0.0-v3-studio.6",
|
|
74
|
+
"@sanity/ui": "^1.0.0-beta.31",
|
|
56
75
|
"nanoid": "^3.1.22",
|
|
57
|
-
"sanity-secrets": "^0.0.6",
|
|
58
76
|
"styled-components": "^5.2.1",
|
|
59
77
|
"video.js": "^7.11.7"
|
|
60
|
-
}
|
|
78
|
+
},
|
|
79
|
+
"repository": {
|
|
80
|
+
"type": "git",
|
|
81
|
+
"url": "git@github.com:sanity-io/sanity-plugin-cloudinary.git"
|
|
82
|
+
},
|
|
83
|
+
"bugs": {
|
|
84
|
+
"url": "https://github.com/sanity-io/sanity-plugin-cloudinary/issues"
|
|
85
|
+
},
|
|
86
|
+
"homepage": "https://github.com/sanity-io/sanity-plugin-cloudinary#readme"
|
|
61
87
|
}
|
package/sanity.json
CHANGED
|
@@ -1,20 +1,8 @@
|
|
|
1
1
|
{
|
|
2
|
-
"paths": {
|
|
3
|
-
"source": "src",
|
|
4
|
-
"compiled": "dist"
|
|
5
|
-
},
|
|
6
2
|
"parts": [
|
|
7
3
|
{
|
|
8
|
-
"implements": "part:@sanity/base/
|
|
9
|
-
"path": "
|
|
10
|
-
},
|
|
11
|
-
{
|
|
12
|
-
"implements": "part:@sanity/base/schema-type",
|
|
13
|
-
"path": "schema/cloudinaryAsset"
|
|
14
|
-
},
|
|
15
|
-
{
|
|
16
|
-
"implements": "part:@sanity/form-builder/input/array/functions",
|
|
17
|
-
"path": "arrayFunctions"
|
|
4
|
+
"implements": "part:@sanity/base/sanity-root",
|
|
5
|
+
"path": "./v2-incompatible.js"
|
|
18
6
|
}
|
|
19
7
|
]
|
|
20
|
-
}
|
|
8
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import {Button} from '@sanity/ui'
|
|
3
|
+
import {PatchEvent, setIfMissing, insert} from 'sanity'
|
|
4
|
+
|
|
5
|
+
import {useSecrets} from '@sanity/studio-secrets'
|
|
6
|
+
import SecretsConfigView, {namespace} from './components/SecretsConfigView'
|
|
7
|
+
import {cloudinaryAssetSchema} from './schema/cloudinaryAsset'
|
|
8
|
+
import {openMediaSelector} from './utils'
|
|
9
|
+
import {InsertHandlerParams} from './typings'
|
|
10
|
+
|
|
11
|
+
interface ApiConfig {
|
|
12
|
+
cloudName: string
|
|
13
|
+
apiKey: string
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const AssetListFunctions = (props: any) => {
|
|
17
|
+
const {secrets, loading} = useSecrets<ApiConfig>(namespace)
|
|
18
|
+
const [showSettings, setShowSettings] = React.useState(false)
|
|
19
|
+
|
|
20
|
+
const cloudinaryType = props.type.of.find(
|
|
21
|
+
(t: {name: string}) => t.name === cloudinaryAssetSchema.name
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
const handleSelect = (selected: InsertHandlerParams) => {
|
|
25
|
+
const {onCreateValue, onChange} = props
|
|
26
|
+
const items = selected.assets.map((asset) =>
|
|
27
|
+
Object.assign(
|
|
28
|
+
{},
|
|
29
|
+
asset,
|
|
30
|
+
{
|
|
31
|
+
// Schema version. In case we ever change our schema.
|
|
32
|
+
_version: 1,
|
|
33
|
+
},
|
|
34
|
+
onCreateValue(cloudinaryType)
|
|
35
|
+
)
|
|
36
|
+
)
|
|
37
|
+
onChange(PatchEvent.from([setIfMissing([]), insert(items, 'after', [-1])]))
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const actions = (
|
|
41
|
+
<>
|
|
42
|
+
<Button
|
|
43
|
+
disabled={props.readOnly || loading}
|
|
44
|
+
mode="ghost"
|
|
45
|
+
onClick={() =>
|
|
46
|
+
secrets &&
|
|
47
|
+
openMediaSelector(
|
|
48
|
+
secrets.cloudName,
|
|
49
|
+
secrets.apiKey,
|
|
50
|
+
true, // multi-selection
|
|
51
|
+
handleSelect
|
|
52
|
+
)
|
|
53
|
+
}
|
|
54
|
+
>
|
|
55
|
+
Add multiple
|
|
56
|
+
</Button>
|
|
57
|
+
<Button onClick={() => setShowSettings(true)}>Configure</Button>
|
|
58
|
+
</>
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
return (
|
|
62
|
+
<>
|
|
63
|
+
{showSettings && <SecretsConfigView onClose={() => setShowSettings(false)} />}
|
|
64
|
+
{/* <DefaultArrayFunctions {...props}>*/}
|
|
65
|
+
{cloudinaryType && actions}
|
|
66
|
+
{/* </DefaultArrayFunctions>*/}
|
|
67
|
+
</>
|
|
68
|
+
)
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export default AssetListFunctions
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import {DiffFromTo} from 'sanity'
|
|
3
|
+
import VideoPlayer from './VideoPlayer'
|
|
4
|
+
import {assetUrl} from '../utils'
|
|
5
|
+
import {CloudinaryAsset} from '../typings'
|
|
6
|
+
|
|
7
|
+
type Props = {
|
|
8
|
+
value: CloudinaryAsset | undefined
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const CloudinaryDiffPreview = ({value}: Props) => {
|
|
12
|
+
if (!value) {
|
|
13
|
+
return null
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const url = assetUrl(value)
|
|
17
|
+
|
|
18
|
+
if (value.resource_type === 'video') {
|
|
19
|
+
return (
|
|
20
|
+
<section
|
|
21
|
+
style={{
|
|
22
|
+
display: 'flex',
|
|
23
|
+
flexWrap: 'wrap',
|
|
24
|
+
justifyContent: 'space-between',
|
|
25
|
+
}}
|
|
26
|
+
>
|
|
27
|
+
<VideoPlayer src={url} kind="diff" />
|
|
28
|
+
</section>
|
|
29
|
+
)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return <img alt="preview" src={url} style={{maxWidth: '100%', height: 'auto'}} />
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
type DiffProps = {
|
|
36
|
+
diff: any
|
|
37
|
+
schemaType: any
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const AssetDiff = ({diff, schemaType}: DiffProps) => {
|
|
41
|
+
return <DiffFromTo diff={diff} schemaType={schemaType} previewComponent={CloudinaryDiffPreview} />
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export default AssetDiff
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import VideoPlayer from './VideoPlayer'
|
|
3
|
+
import {assetUrl} from '../utils'
|
|
4
|
+
import {Box} from '@sanity/ui'
|
|
5
|
+
import {CloudinaryAsset} from '../typings'
|
|
6
|
+
|
|
7
|
+
type ComponentProps = {
|
|
8
|
+
layout?: 'default' | 'block'
|
|
9
|
+
value: CloudinaryAsset | undefined
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const AssetPreview = ({value, layout}: ComponentProps) => {
|
|
13
|
+
const url = value && assetUrl(value)
|
|
14
|
+
if (!value || !url) {
|
|
15
|
+
return null
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
switch (value.resource_type) {
|
|
19
|
+
case 'video':
|
|
20
|
+
return (
|
|
21
|
+
<Box>
|
|
22
|
+
<VideoPlayer src={url} kind="player" />
|
|
23
|
+
</Box>
|
|
24
|
+
)
|
|
25
|
+
default:
|
|
26
|
+
return (
|
|
27
|
+
<Box>
|
|
28
|
+
<img
|
|
29
|
+
alt="preview"
|
|
30
|
+
src={url}
|
|
31
|
+
style={{
|
|
32
|
+
maxWidth: layout === 'default' ? '80px' : '100%',
|
|
33
|
+
height: 'auto',
|
|
34
|
+
}}
|
|
35
|
+
/>
|
|
36
|
+
</Box>
|
|
37
|
+
)
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export default AssetPreview
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import React, {useCallback, useState} from 'react'
|
|
2
|
+
import WidgetInput from './WidgetInput'
|
|
3
|
+
import {nanoid} from 'nanoid'
|
|
4
|
+
import {ObjectInputProps, PatchEvent, set} from 'sanity'
|
|
5
|
+
import {CloudinaryAsset} from '../typings'
|
|
6
|
+
import {useSecrets} from '@sanity/studio-secrets'
|
|
7
|
+
import {InsertHandlerParams} from '../typings'
|
|
8
|
+
import {openMediaSelector} from '../utils'
|
|
9
|
+
import SecretsConfigView, {namespace, Secrets} from './SecretsConfigView'
|
|
10
|
+
|
|
11
|
+
const CloudinaryInput = (props: ObjectInputProps) => {
|
|
12
|
+
const [showSettings, setShowSettings] = useState(false)
|
|
13
|
+
const {secrets} = useSecrets<Secrets>(namespace)
|
|
14
|
+
const {onChange, schemaType: type} = props
|
|
15
|
+
const value = (props.value as CloudinaryAsset) || undefined
|
|
16
|
+
|
|
17
|
+
const handleSelect = useCallback(
|
|
18
|
+
(payload: InsertHandlerParams) => {
|
|
19
|
+
const [asset] = payload.assets
|
|
20
|
+
if (!asset) {
|
|
21
|
+
return
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
onChange(
|
|
25
|
+
PatchEvent.from([
|
|
26
|
+
set(
|
|
27
|
+
Object.assign(
|
|
28
|
+
{
|
|
29
|
+
_type: type.name,
|
|
30
|
+
_version: 1,
|
|
31
|
+
...(value?._key ? {_key: value._key} : {_key: nanoid()}),
|
|
32
|
+
},
|
|
33
|
+
asset
|
|
34
|
+
)
|
|
35
|
+
),
|
|
36
|
+
])
|
|
37
|
+
)
|
|
38
|
+
},
|
|
39
|
+
[onChange, type, value?._key]
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
const action = secrets
|
|
43
|
+
? () =>
|
|
44
|
+
openMediaSelector(
|
|
45
|
+
secrets.cloudName,
|
|
46
|
+
secrets.apiKey,
|
|
47
|
+
false, // single selection
|
|
48
|
+
handleSelect,
|
|
49
|
+
value
|
|
50
|
+
)
|
|
51
|
+
: () => setShowSettings(true)
|
|
52
|
+
|
|
53
|
+
return (
|
|
54
|
+
<>
|
|
55
|
+
{showSettings && <SecretsConfigView onClose={() => setShowSettings(false)} />}
|
|
56
|
+
<WidgetInput onSetup={() => setShowSettings(true)} openMediaSelector={action} {...props} />
|
|
57
|
+
</>
|
|
58
|
+
)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export default CloudinaryInput
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import {SettingsView} from '@sanity/studio-secrets'
|
|
3
|
+
|
|
4
|
+
export type Secrets = {
|
|
5
|
+
cloudName: string
|
|
6
|
+
apiKey: string
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const pluginConfigKeys = [
|
|
10
|
+
{
|
|
11
|
+
key: 'cloudName',
|
|
12
|
+
title: 'Cloud name',
|
|
13
|
+
description: '',
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
key: 'apiKey',
|
|
17
|
+
title: 'API key',
|
|
18
|
+
description: '',
|
|
19
|
+
},
|
|
20
|
+
]
|
|
21
|
+
|
|
22
|
+
export const namespace = 'cloudinary'
|
|
23
|
+
|
|
24
|
+
type Props = {
|
|
25
|
+
onClose: () => void
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const SecretsConfigView = (props: Props) => {
|
|
29
|
+
return (
|
|
30
|
+
<SettingsView
|
|
31
|
+
title="Cloudinary config"
|
|
32
|
+
namespace={namespace}
|
|
33
|
+
keys={pluginConfigKeys}
|
|
34
|
+
onClose={props.onClose}
|
|
35
|
+
/>
|
|
36
|
+
)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export default SecretsConfigView
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import React, { CSSProperties } from 'react';
|
|
2
|
+
import videojs, { VideoJsPlayer } from 'video.js';
|
|
3
|
+
|
|
4
|
+
type PlayerKind = 'player' | 'diff';
|
|
5
|
+
|
|
6
|
+
export type VideoPlayerProps = {
|
|
7
|
+
src: string;
|
|
8
|
+
kind: PlayerKind;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export default class VideoPlayer extends React.Component<
|
|
12
|
+
VideoPlayerProps,
|
|
13
|
+
any
|
|
14
|
+
> {
|
|
15
|
+
videoNode?: HTMLVideoElement;
|
|
16
|
+
player?: VideoJsPlayer;
|
|
17
|
+
|
|
18
|
+
componentDidMount() {
|
|
19
|
+
const { src } = this.props;
|
|
20
|
+
this.player = videojs(this.videoNode, {
|
|
21
|
+
sources: [{ src }],
|
|
22
|
+
controls: true,
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
componentWillUnmount() {
|
|
27
|
+
if (this.player) {
|
|
28
|
+
this.player.dispose();
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
render() {
|
|
33
|
+
const { kind } = this.props;
|
|
34
|
+
const className: Record<PlayerKind, string> = {
|
|
35
|
+
player: 'video-js vjs-16-9 vjs-big-play-centered',
|
|
36
|
+
diff: 'video-js vjs-layout-tiny vjs-fluid',
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
const style: CSSProperties = { position: 'relative' };
|
|
40
|
+
|
|
41
|
+
return (
|
|
42
|
+
<div>
|
|
43
|
+
<link
|
|
44
|
+
href="https://vjs.zencdn.net/7.8.4/video-js.css"
|
|
45
|
+
rel="stylesheet"
|
|
46
|
+
/>
|
|
47
|
+
<div data-vjs-player>
|
|
48
|
+
<video
|
|
49
|
+
onClick={event => event.stopPropagation()}
|
|
50
|
+
style={kind === 'diff' ? style : {}}
|
|
51
|
+
className={className[kind]}
|
|
52
|
+
ref={node => {
|
|
53
|
+
if (node) {
|
|
54
|
+
this.videoNode = node;
|
|
55
|
+
}
|
|
56
|
+
}}
|
|
57
|
+
></video>
|
|
58
|
+
</div>
|
|
59
|
+
</div>
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import React, {useCallback} from 'react'
|
|
2
|
+
import {ObjectInputProps, PatchEvent, unset} from 'sanity'
|
|
3
|
+
import {Button, Flex, Grid, Stack} from '@sanity/ui'
|
|
4
|
+
import {PlugIcon} from '@sanity/icons'
|
|
5
|
+
import styled from 'styled-components'
|
|
6
|
+
import AssetPreview from './AssetPreview'
|
|
7
|
+
import {CloudinaryAsset} from '../typings'
|
|
8
|
+
|
|
9
|
+
const SetupButtonContainer = styled.div`
|
|
10
|
+
position: relative;
|
|
11
|
+
display: block;
|
|
12
|
+
font-size: 0.8em;
|
|
13
|
+
transform: translate(0%, -10%);
|
|
14
|
+
`
|
|
15
|
+
|
|
16
|
+
type WidgetInputProps = ObjectInputProps & {openMediaSelector: () => void; onSetup: () => void}
|
|
17
|
+
|
|
18
|
+
const WidgetInput = (props: WidgetInputProps) => {
|
|
19
|
+
const {onChange, readOnly, value, openMediaSelector} = props
|
|
20
|
+
|
|
21
|
+
const removeValue = useCallback(() => {
|
|
22
|
+
onChange(PatchEvent.from([unset()]))
|
|
23
|
+
}, [onChange])
|
|
24
|
+
|
|
25
|
+
return (
|
|
26
|
+
<Stack>
|
|
27
|
+
<SetupButtonContainer>
|
|
28
|
+
<Flex flex={1} justify="flex-end">
|
|
29
|
+
<Button
|
|
30
|
+
color="primary"
|
|
31
|
+
icon={PlugIcon}
|
|
32
|
+
mode="bleed"
|
|
33
|
+
title="Configure"
|
|
34
|
+
onClick={props.onSetup}
|
|
35
|
+
tabIndex={1}
|
|
36
|
+
/>
|
|
37
|
+
</Flex>
|
|
38
|
+
</SetupButtonContainer>
|
|
39
|
+
|
|
40
|
+
<Flex style={{textAlign: 'center'}} marginBottom={2}>
|
|
41
|
+
<AssetPreview value={value as CloudinaryAsset} />
|
|
42
|
+
</Flex>
|
|
43
|
+
|
|
44
|
+
<Grid gap={1} style={{gridTemplateColumns: 'repeat(auto-fit, minmax(100px, 1fr))'}}>
|
|
45
|
+
<Button
|
|
46
|
+
disabled={readOnly}
|
|
47
|
+
mode="ghost"
|
|
48
|
+
title="Select an asset"
|
|
49
|
+
tone="default"
|
|
50
|
+
onClick={openMediaSelector}
|
|
51
|
+
text="Select…"
|
|
52
|
+
/>
|
|
53
|
+
<Button
|
|
54
|
+
disabled={readOnly || !value}
|
|
55
|
+
tone="critical"
|
|
56
|
+
mode="ghost"
|
|
57
|
+
title="Remove asset"
|
|
58
|
+
text="Remove"
|
|
59
|
+
onClick={removeValue}
|
|
60
|
+
/>
|
|
61
|
+
</Grid>
|
|
62
|
+
</Stack>
|
|
63
|
+
)
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export default WidgetInput
|