Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/cloudinary-vanilla-extract.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"sanity-plugin-cloudinary": patch
---

Migrate styling from styled-components to vanilla-extract (zero-runtime CSS)
20 changes: 18 additions & 2 deletions plugins/sanity-plugin-cloudinary/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,25 @@
"types": "./dist/index.d.ts",
"exports": {
".": "./src/index.ts",
"./bundle.css": {
"types": "./dist/bundle-css.d.ts",
"browser": "./dist/bundle.css",
"style": "./dist/bundle.css",
"node": "./dist/bundle-css.js",
"default": "./dist/bundle-css.js"
},
"./package.json": "./package.json"
},
"publishConfig": {
"exports": {
".": "./dist/index.js",
"./bundle.css": {
"types": "./dist/bundle-css.d.ts",
"browser": "./dist/bundle.css",
"style": "./dist/bundle.css",
"node": "./dist/bundle-css.js",
"default": "./dist/bundle-css.js"
},
"./package.json": "./package.json"
}
},
Expand All @@ -41,13 +55,16 @@
"@sanity/icons": "catalog:",
"@sanity/studio-secrets": "workspace:^",
"@sanity/ui": "catalog:",
"clsx": "catalog:",
"nanoid": "catalog:"
},
"devDependencies": {
"@sanity/tsconfig": "catalog:",
"@sanity/tsdown-config": "catalog:",
"@sanity/vanilla-extract-vite-plugin": "catalog:",
"@types/react": "catalog:",
"@types/react-dom": "catalog:",
"@vanilla-extract/css": "catalog:",
"babel-plugin-react-compiler": "catalog:",
"react": "catalog:",
"react-dom": "catalog:",
Expand All @@ -58,8 +75,7 @@
"peerDependencies": {
"react": "catalog:peer",
"react-dom": "catalog:peer",
"sanity": "catalog:peer",
"styled-components": "catalog:peer"
"sanity": "catalog:peer"
},
"engines": {
"node": ">=20.19 <22 || >=22.12"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import {style} from '@vanilla-extract/css'

export const videoDiff = style({
display: 'flex',
flexWrap: 'wrap',
justifyContent: 'space-between',
})

export const previewImage = style({
maxWidth: '100%',
height: 'auto',
})
12 changes: 4 additions & 8 deletions plugins/sanity-plugin-cloudinary/src/components/AssetDiff.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import {assetUrl} from '../utils'
import {namespace, type Secrets} from './SecretsConfigView'
import VideoPlayer from './VideoPlayer'

import {previewImage, videoDiff} from './AssetDiff.css'

type Props = {
value: CloudinaryAsset | undefined
}
Expand All @@ -22,19 +24,13 @@ const CloudinaryDiffPreview = ({value}: Props) => {

if (value.resource_type === 'video' && url) {
return (
<section
style={{
display: 'flex',
flexWrap: 'wrap',
justifyContent: 'space-between',
}}
>
<section className={videoDiff}>
<VideoPlayer src={url} kind="diff" />
</section>
)
}

return <img alt="preview" src={url} style={{maxWidth: '100%', height: 'auto'}} />
return <img alt="preview" src={url} className={previewImage} />
}

type DiffProps = {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import {style} from '@vanilla-extract/css'

export const fullWidthButton = style({
selectors: {
// Match the previous inline `width: 100%` against Button's own width rules.
'&&': {
width: '100%',
},
},
})
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import {PlugIcon} from '@sanity/icons/Plug'
import {useSecrets} from '@sanity/studio-secrets'
import {Box, Button, Flex} from '@sanity/ui'
import {useCallback, useState} from 'react'
import {clsx} from 'clsx/lite'
import {type ComponentProps, useCallback, useState} from 'react'
import {
type ArrayInputFunctionsProps,
ArrayOfObjectsFunctions,
Expand All @@ -17,6 +18,12 @@ import type {InsertHandlerParams} from '../types'
import {openMediaSelector} from '../utils'
import SecretsConfigView, {namespace} from './SecretsConfigView'

import {fullWidthButton} from './AssetListFunctions.css'

function FullWidthButton({className, ...props}: ComponentProps<typeof Button>) {
return <Button {...props} className={clsx(fullWidthButton, className)} />
}

interface ApiConfig {
cloudName: string
apiKey: string
Expand Down Expand Up @@ -82,8 +89,7 @@ export const AssetListFunctions = (
{cloudinaryType && (
<>
<Box flex={1}>
<Button
style={{width: '100%'}}
<FullWidthButton
disabled={props.readOnly || loading}
mode="bleed"
text="Add multiple"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import {style, styleVariants} from '@vanilla-extract/css'

export const videoPreview = styleVariants({
default: {
maxWidth: '80px',
},
block: {
maxWidth: '100%',
},
})

export const rawFileLabel = style({
marginLeft: '0.5em',
})

export const thumbnailFlex = style({
width: '100%',
})

export const thumbnailImage = style({
maxWidth: '80px',
height: 'auto',
display: 'block',
})

export const fullWidthPreview = style({
width: '100%',
})

export const fullWidthImage = style({
width: '100%',
height: 'auto',
display: 'block',
})
69 changes: 43 additions & 26 deletions plugins/sanity-plugin-cloudinary/src/components/AssetPreview.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,50 @@
import {DocumentIcon} from '@sanity/icons/Document'
import {useSecrets} from '@sanity/studio-secrets'
import {Flex, Text} from '@sanity/ui'
import {clsx} from 'clsx/lite'
import type {ComponentProps} from 'react'

import type {CloudinaryAsset} from '../types'
import {assetUrl} from '../utils'
import {namespace, type Secrets} from './SecretsConfigView'
import VideoPlayer from './VideoPlayer'

interface ComponentProps {
import {
fullWidthImage,
fullWidthPreview,
rawFileLabel,
thumbnailFlex,
thumbnailImage,
videoPreview,
} from './AssetPreview.css'

interface AssetPreviewProps {
layout?: 'default' | 'block'
value: CloudinaryAsset | undefined
}

const AssetPreview = ({value, layout}: ComponentProps) => {
function VideoPreviewFlex({
layout,
className,
...props
}: ComponentProps<typeof Flex> & {layout?: 'default' | 'block'}) {
const layoutClass = videoPreview[layout === 'default' ? 'default' : 'block']
return <Flex {...props} className={clsx(layoutClass, className)} />
}

function RawFileLabel({className, ...props}: ComponentProps<typeof Text>) {
return <Text {...props} className={clsx(rawFileLabel, className)} />
}

function ThumbnailFlex({className, ...props}: ComponentProps<typeof Flex>) {
return <Flex {...props} className={clsx(thumbnailFlex, className)} />
}

function FullWidthPreview({className, ...props}: ComponentProps<'div'>) {
return <div {...props} className={clsx(fullWidthPreview, className)} />
}

const AssetPreview = ({value, layout}: AssetPreviewProps) => {
const {secrets} = useSecrets<Secrets>(namespace)
const cloudName = secrets?.cloudName

Expand All @@ -28,22 +60,15 @@ const AssetPreview = ({value, layout}: ComponentProps) => {
switch (value.resource_type) {
case 'video':
return (
<Flex
align="center"
style={{
maxWidth: layout === 'default' ? '80px' : '100%',
}}
>
<VideoPreviewFlex align="center" layout={layout}>
<VideoPlayer src={url} kind="player" />
</Flex>
</VideoPreviewFlex>
)
case 'raw':
return (
<Flex align="center">
<DocumentIcon />
<Text size={1} style={{marginLeft: '0.5em'}}>
{value.display_name ?? 'Raw file'}
</Text>
<RawFileLabel size={1}>{value.display_name ?? 'Raw file'}</RawFileLabel>
</Flex>
)
default: {
Expand All @@ -59,21 +84,13 @@ const AssetPreview = ({value, layout}: ComponentProps) => {
: url

return layout === 'default' ? (
<Flex align="center" justify="center" style={{width: '100%'}}>
<img
alt="preview"
src={previewSrc}
style={{maxWidth: '80px', height: 'auto', display: 'block'}}
/>
</Flex>
<ThumbnailFlex align="center" justify="center">
<img alt="preview" src={previewSrc} className={thumbnailImage} />
</ThumbnailFlex>
) : (
<div style={{width: '100%'}}>
<img
alt="preview"
src={previewSrc}
style={{width: '100%', height: 'auto', display: 'block'}}
/>
</div>
<FullWidthPreview>
<img alt="preview" src={previewSrc} className={fullWidthImage} />
</FullWidthPreview>
)
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import {style} from '@vanilla-extract/css'

export const previewFlex = style({
textAlign: 'center',
width: '100%',
})

export const actionGrid = style({
gridTemplateColumns: 'repeat(auto-fit, minmax(100px, 1fr))',
})
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import {PlugIcon} from '@sanity/icons/Plug'
import {useSecrets} from '@sanity/studio-secrets'
import {Button, Flex, Grid, Stack} from '@sanity/ui'
import {clsx} from 'clsx/lite'
import {nanoid} from 'nanoid'
import {useCallback, useMemo, useRef, useState} from 'react'
import {type ComponentProps, useCallback, useMemo, useRef, useState} from 'react'
import {type ObjectInputProps, getPublishedId, PatchEvent, set, unset, useClient} from 'sanity'

import {cloudinaryAssetSchema} from '../schema/cloudinaryAsset'
Expand All @@ -11,6 +12,16 @@ import {normalizeCloudinaryAsset, openMediaSelector} from '../utils'
import ReferencePreview from './ReferencePreview'
import SecretsConfigView, {namespace, type Secrets} from './SecretsConfigView'

import {actionGrid, previewFlex} from './CloudinaryReferenceInput.css'

function PreviewFlex({className, ...props}: ComponentProps<typeof Flex>) {
return <Flex {...props} className={clsx(previewFlex, className)} />
}

function ActionGrid({className, ...props}: ComponentProps<typeof Grid>) {
return <Grid {...props} className={clsx(actionGrid, className)} />
}

const API_VERSION = '2023-01-01'

// Fallback so the button doesn't stay disabled if the media library never reports it opened
Expand Down Expand Up @@ -228,12 +239,12 @@ const CloudinaryReferenceInput = (props: ObjectInputProps) => {
/>
</Flex>

<Flex marginBottom={2} style={{textAlign: 'center', width: '100%'}}>
<PreviewFlex marginBottom={2}>
<ReferencePreview value={reference} revision={previewRevision} />
</Flex>
</PreviewFlex>

<Stack gap={2}>
<Grid gap={1} style={{gridTemplateColumns: 'repeat(auto-fit, minmax(100px, 1fr))'}}>
<ActionGrid gap={1}>
<Button
text={selectButtonText}
onClick={handleOpenSelector}
Expand All @@ -252,7 +263,7 @@ const CloudinaryReferenceInput = (props: ObjectInputProps) => {
disabled={actionsDisabled}
/>
) : null}
</Grid>
</ActionGrid>
</Stack>
</Stack>
)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import {style} from '@vanilla-extract/css'

export const setupButtonContainer = style({
position: 'relative',
display: 'block',
fontSize: '0.8em',
transform: 'translate(0%, -10%)',
})

export const previewFlex = style({
textAlign: 'center',
width: '100%',
})

export const actionGrid = style({
gridTemplateColumns: 'repeat(auto-fit, minmax(100px, 1fr))',
})
Loading
Loading