Skip to content

Commit

Permalink
Merge branch 'next' into feat/studio-manifests-cont
Browse files Browse the repository at this point in the history
  • Loading branch information
snorrees committed Oct 1, 2024
2 parents a150e86 + df0e18a commit 7b96c23
Show file tree
Hide file tree
Showing 27 changed files with 291 additions and 391 deletions.
3 changes: 0 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -99,9 +99,6 @@
},
"prettier": "@sanity/prettier-config",
"devDependencies": {
"@babel/preset-env": "^7.24.7",
"@babel/preset-react": "^7.24.7",
"@babel/preset-typescript": "^7.24.7",
"@google-cloud/storage": "^7.11.0",
"@playwright/test": "1.44.1",
"@repo/dev-aliases": "workspace:*",
Expand Down
8 changes: 8 additions & 0 deletions packages/@repo/test-config/.depcheckrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"ignores": [
"@babel/preset-env",
"@babel/preset-react",
"@babel/preset-typescript",
"babel-plugin-transform-vite-meta-hot"
]
}
7 changes: 4 additions & 3 deletions packages/@repo/test-config/jest/createJestConfig.mjs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
/* eslint-disable tsdoc/syntax */

import devAliases from '@repo/dev-aliases'

import path from 'node:path'

import devAliases from '@repo/dev-aliases'
import {escapeRegExp, omit} from 'lodash-es'

import {resolveDirName} from './resolveDirName.mjs'

const dirname = resolveDirName(import.meta.url)
Expand Down Expand Up @@ -71,7 +72,6 @@ export function createJestConfig(config = {}) {
resolver: path.resolve(dirname, './resolver.cjs'),
testEnvironment: path.resolve(dirname, './jsdom.jest.env.ts'),
setupFiles: [...setupFiles, path.resolve(dirname, './setup.ts')],
// testEnvironment: 'jsdom',
testEnvironmentOptions: {
url: 'http://localhost:3333',
},
Expand Down Expand Up @@ -103,6 +103,7 @@ export function createJestConfig(config = {}) {
'@babel/preset-typescript',
['@babel/preset-react', {runtime: 'automatic'}],
],
plugins: ['babel-plugin-transform-vite-meta-hot'],
},
],
},
Expand Down
4 changes: 4 additions & 0 deletions packages/@repo/test-config/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,12 @@
"./vitest": "./vitest/index.mjs"
},
"devDependencies": {
"@babel/preset-env": "^7.24.7",
"@babel/preset-react": "^7.24.7",
"@babel/preset-typescript": "^7.24.7",
"@jest/globals": "^29.7.0",
"@repo/dev-aliases": "workspace:*",
"babel-plugin-transform-vite-meta-hot": "^1.0.0",
"dotenv": "^16.4.5",
"jest-environment-jsdom": "^29.7.0",
"lodash-es": "^4.17.21",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,16 +70,16 @@ export default (html: string, doc: Document): Document => {
for (let i = mappedElements.snapshotLength - 1; i >= 0; i--) {
const mappedElm = mappedElements.snapshotItem(i) as HTMLElement
const tags = elementMap[mappedElm.className]
const text = new Text(mappedElm.textContent || '')
const text = doc.createTextNode(mappedElm.textContent || '')
if (!tags) {
continue
}

const parentElement = document.createElement(tags[0])
const parentElement = doc.createElement(tags[0])
let parent = parentElement
let child = parentElement
tags.slice(1).forEach((tag) => {
child = document.createElement(tag)
child = doc.createElement(tag)
parent.appendChild(child)
parent = child
})
Expand Down
4 changes: 4 additions & 0 deletions packages/sanity/src/core/error/ErrorLogger.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,5 +64,9 @@ function isKnownError(err: Error): boolean {
return true
}

if ('ViteDevServerStoppedError' in err && err.ViteDevServerStoppedError) {
return true
}

return false
}
Original file line number Diff line number Diff line change
Expand Up @@ -67,28 +67,6 @@ function BaseImageInputComponent(props: BaseImageInputProps): JSX.Element {

const uploadSubscription = useRef<null | Subscription>(null)

/**
* The upload progress state wants to use the same height as any previous image
* to avoid layout shifts and jumps
*/
const previewElementRef = useRef<{el: HTMLDivElement | null; height: number}>({
el: null,
height: 0,
})
const setPreviewElementHeight = useCallback((node: HTMLDivElement | null) => {
if (node) {
previewElementRef.current.el = node
previewElementRef.current.height = node.offsetHeight
} else {
/**
* If `node` is `null` then it means the `FileTarget` in `ImageInputAsset` is being unmounted and we want to
* capture its height before it's removed from the DOM.
*/

previewElementRef.current.height = previewElementRef.current.el?.offsetHeight || 0
previewElementRef.current.el = null
}
}, [])
const getFileTone = useCallback(() => {
const acceptedFiles = hoveringFiles.filter((file) => resolveUploader(schemaType, file))
const rejectedFilesCount = hoveringFiles.length - acceptedFiles.length
Expand Down Expand Up @@ -201,9 +179,6 @@ function BaseImageInputComponent(props: BaseImageInputProps): JSX.Element {

const handleClearField = useCallback(() => {
onChange([unset(['asset']), unset(['crop']), unset(['hotspot'])])

previewElementRef.current.el = null
previewElementRef.current.height = 0
}, [onChange])
const handleRemoveButtonClick = useCallback(() => {
// When removing the image, we should also remove any crop and hotspot
Expand All @@ -224,9 +199,6 @@ function BaseImageInputComponent(props: BaseImageInputProps): JSX.Element {
.map((key) => unset([key]))

onChange(isEmpty && !valueIsArrayElement() ? unset() : removeKeys)

previewElementRef.current.el = null
previewElementRef.current.height = 0
}, [onChange, value, valueIsArrayElement])
const handleOpenDialog = useCallback(() => {
onPathFocus(['hotspot'])
Expand Down Expand Up @@ -303,15 +275,16 @@ function BaseImageInputComponent(props: BaseImageInputProps): JSX.Element {
menuButtonElement?.focus()
}, [menuButtonElement])

const renderPreview = useCallback(() => {
const renderPreview = useCallback<() => JSX.Element>(() => {
if (!value) {
return <></>
}
return (
<ImageInputPreview
directUploads={directUploads}
handleOpenDialog={handleOpenDialog}
hoveringFiles={hoveringFiles}
imageUrlBuilder={imageUrlBuilder}
// if there previously was a preview image, preserve the height to avoid jumps
initialHeight={previewElementRef.current.height}
readOnly={readOnly}
resolveUploader={resolveUploader}
schemaType={schemaType}
Expand Down Expand Up @@ -404,8 +377,6 @@ function BaseImageInputComponent(props: BaseImageInputProps): JSX.Element {
uploadState={uploadState}
onCancel={isUploading ? handleCancelUpload : undefined}
onStale={handleStaleUpload}
// if there previously was a preview image, preserve the height to avoid jumps
height={previewElementRef.current.height}
/>
)
},
Expand All @@ -420,7 +391,6 @@ function BaseImageInputComponent(props: BaseImageInputProps): JSX.Element {
// eslint-disable-next-line react/display-name
return (inputProps: Omit<InputProps, 'renderDefault'>) => (
<ImageInputAsset
ref={setPreviewElementHeight}
elementProps={elementProps}
handleClearUploadState={handleClearUploadState}
handleFilesOut={handleFilesOut}
Expand All @@ -437,6 +407,7 @@ function BaseImageInputComponent(props: BaseImageInputProps): JSX.Element {
renderUploadState={renderUploadState}
tone={getFileTone()}
value={value}
imageUrlBuilder={imageUrlBuilder}
/>
)
}, [
Expand All @@ -449,13 +420,13 @@ function BaseImageInputComponent(props: BaseImageInputProps): JSX.Element {
handleFilesOver,
handleSelectFiles,
hoveringFiles,
imageUrlBuilder,
isStale,
readOnly,
renderAssetMenu,
renderPreview,
renderUploadPlaceholder,
renderUploadState,
setPreviewElementHeight,
value,
])
const renderHotspotInput = useCallback(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,36 +1,36 @@
import {type UploadState} from '@sanity/types'
import {Box, type CardTone} from '@sanity/ui'
import {type FocusEvent, forwardRef, memo, useMemo} from 'react'
import {type FocusEvent, memo, useMemo} from 'react'

import {ChangeIndicator} from '../../../../changeIndicators'
import {type InputProps} from '../../../types'
import {FileTarget} from '../common/styles'
import {UploadWarning} from '../common/UploadWarning'
import {type ImageUrlBuilder} from '../types'
import {type BaseImageInputProps, type BaseImageInputValue, type FileInfo} from './types'
import {usePreviewImageSource} from './usePreviewImageSource'

const ASSET_FIELD_PATH = ['asset'] as const

function ImageInputAssetComponent(
props: {
elementProps: BaseImageInputProps['elementProps']
handleClearUploadState: () => void
handleFilesOut: () => void
handleFilesOver: (hoveringFiles: FileInfo[]) => void
handleFileTargetFocus: (event: FocusEvent<Element, Element>) => void
handleSelectFiles: (files: File[]) => void
hoveringFiles: FileInfo[]
inputProps: Omit<InputProps, 'renderDefault'>
isStale: boolean
readOnly: boolean | undefined
renderAssetMenu(): JSX.Element | null
renderPreview: () => JSX.Element
renderUploadPlaceholder(): JSX.Element
renderUploadState(uploadState: UploadState): JSX.Element
tone: CardTone
value: BaseImageInputValue | undefined
},
forwardedRef: React.ForwardedRef<HTMLDivElement>,
) {
function ImageInputAssetComponent(props: {
elementProps: BaseImageInputProps['elementProps']
handleClearUploadState: () => void
handleFilesOut: () => void
handleFilesOver: (hoveringFiles: FileInfo[]) => void
handleFileTargetFocus: (event: FocusEvent<Element, Element>) => void
handleSelectFiles: (files: File[]) => void
hoveringFiles: FileInfo[]
imageUrlBuilder: ImageUrlBuilder
inputProps: Omit<InputProps, 'renderDefault'>
isStale: boolean
readOnly: boolean | undefined
renderAssetMenu(): JSX.Element | null
renderPreview: () => JSX.Element
renderUploadPlaceholder(): JSX.Element
renderUploadState(uploadState: UploadState): JSX.Element
tone: CardTone
value: BaseImageInputValue | undefined
}) {
const {
elementProps,
handleClearUploadState,
Expand All @@ -48,13 +48,15 @@ function ImageInputAssetComponent(
renderUploadState,
tone,
value,
imageUrlBuilder,
} = props

const hasValueOrUpload = Boolean(value?._upload || value?.asset)
const path = useMemo(() => inputProps.path.concat(ASSET_FIELD_PATH), [inputProps.path])
const {customProperties} = usePreviewImageSource({value, imageUrlBuilder})

return (
<>
<div style={customProperties}>
{isStale && (
<Box marginBottom={2}>
<UploadWarning onClearStale={handleClearUploadState} />
Expand All @@ -79,15 +81,15 @@ function ImageInputAssetComponent(
>
{!value?.asset && renderUploadPlaceholder()}
{!value?._upload && value?.asset && (
<div style={{position: 'relative'}} ref={forwardedRef}>
<div style={{position: 'relative'}}>
{renderPreview()}
{renderAssetMenu()}
</div>
)}
</FileTarget>
)}
</ChangeIndicator>
</>
</div>
)
}
export const ImageInputAsset = memo(forwardRef(ImageInputAssetComponent))
export const ImageInputAsset = memo(ImageInputAssetComponent)
Original file line number Diff line number Diff line change
@@ -1,49 +1,40 @@
import {isImageSource} from '@sanity/asset-utils'
import {type ImageSchemaType} from '@sanity/types'
import {memo, useMemo} from 'react'
import {useDevicePixelRatio} from 'use-device-pixel-ratio'

import {useTranslation} from '../../../../i18n'
import {type UploaderResolver} from '../../../studio/uploads/types'
import {type ImageUrlBuilder} from '../types'
import {ImagePreview} from './ImagePreview'
import {type BaseImageInputValue, type FileInfo} from './types'
import {usePreviewImageSource} from './usePreviewImageSource'

export const ImageInputPreview = memo(function ImageInputPreviewComponent(props: {
directUploads: boolean | undefined
handleOpenDialog: () => void
hoveringFiles: FileInfo[]
imageUrlBuilder: ImageUrlBuilder
initialHeight: number | undefined
readOnly: boolean | undefined
resolveUploader: UploaderResolver
schemaType: ImageSchemaType
value: BaseImageInputValue | undefined
value: BaseImageInputValue
}) {
const {
directUploads,
handleOpenDialog,
hoveringFiles,
imageUrlBuilder,
initialHeight,
readOnly,
resolveUploader,
schemaType,
value,
} = props

const isValueImageSource = useMemo(() => isImageSource(value), [value])
if (!value || !isValueImageSource) {
return null
}

return (
<RenderImageInputPreview
directUploads={directUploads}
handleOpenDialog={handleOpenDialog}
hoveringFiles={hoveringFiles}
imageUrlBuilder={imageUrlBuilder}
initialHeight={initialHeight}
readOnly={readOnly}
resolveUploader={resolveUploader}
schemaType={schemaType}
Expand All @@ -57,7 +48,6 @@ function RenderImageInputPreview(props: {
handleOpenDialog: () => void
hoveringFiles: FileInfo[]
imageUrlBuilder: ImageUrlBuilder
initialHeight: number | undefined
readOnly: boolean | undefined
resolveUploader: UploaderResolver
schemaType: ImageSchemaType
Expand All @@ -68,7 +58,6 @@ function RenderImageInputPreview(props: {
handleOpenDialog,
hoveringFiles,
imageUrlBuilder,
initialHeight,
readOnly,
resolveUploader,
schemaType,
Expand All @@ -84,20 +73,17 @@ function RenderImageInputPreview(props: {
() => hoveringFiles.length - acceptedFiles.length,
[acceptedFiles, hoveringFiles],
)
const dpr = useDevicePixelRatio()
const imageUrl = useMemo(
() => imageUrlBuilder.width(2000).fit('max').image(value).dpr(dpr).auto('format').url(),
[dpr, imageUrlBuilder, value],
)

const {url} = usePreviewImageSource({value, imageUrlBuilder})

return (
<ImagePreview
alt={t('inputs.image.preview-uploaded-image')}
drag={!value?._upload && hoveringFiles.length > 0}
initialHeight={initialHeight}
isRejected={rejectedFilesCount > 0 || !directUploads}
onDoubleClick={handleOpenDialog}
readOnly={readOnly}
src={imageUrl}
src={url}
/>
)
}
Loading

0 comments on commit 7b96c23

Please sign in to comment.