chore(richtext-lexical): improve types of UploadData (#10982)
One step closer to being able to remove `noUncheckedIndexedAccess` in `packages/richtext-lexical/tsconfig.json`. I'm introducing UploadData_P4 which is a more precise version of UploadData. I'm doing it as a different type because there's a chance it'll be a breaking change for some users. UploadData is used in many places, but I'm currently replacing it only in `packages/richtext-lexical/src/exports/react/components/RichText/converter/converters/upload.tsx`, because in the other files it's too rooted to other types like UploadNode.
This commit is contained in:
@@ -12,6 +12,16 @@ export type FileSize = {
|
|||||||
width: null | number
|
width: null | number
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: deprecate in Payload v4.
|
||||||
|
/**
|
||||||
|
* FileSizeImproved is a more precise type, and will replace FileSize in Payload v4.
|
||||||
|
* This type is for internal use only as it will be deprecated in the future.
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
export type FileSizeImproved = {
|
||||||
|
url: null | string
|
||||||
|
} & FileSize
|
||||||
|
|
||||||
export type FileSizes = {
|
export type FileSizes = {
|
||||||
[size: string]: FileSize
|
[size: string]: FileSize
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,23 +1,25 @@
|
|||||||
import type { FileData, FileSize, TypeWithID } from 'payload'
|
import type { FileSizeImproved } from 'payload'
|
||||||
|
|
||||||
|
import type { UploadDataImproved } from '../../../../../../features/upload/server/nodes/UploadNode.js'
|
||||||
import type { SerializedUploadNode } from '../../../../../../nodeTypes.js'
|
import type { SerializedUploadNode } from '../../../../../../nodeTypes.js'
|
||||||
import type { JSXConverters } from '../types.js'
|
import type { JSXConverters } from '../types.js'
|
||||||
|
|
||||||
export const UploadJSXConverter: JSXConverters<SerializedUploadNode> = {
|
export const UploadJSXConverter: JSXConverters<SerializedUploadNode> = {
|
||||||
upload: ({ node }) => {
|
upload: ({ node }) => {
|
||||||
const uploadDocument: {
|
// TO-DO (v4): SerializedUploadNode should use UploadData_P4
|
||||||
value?: FileData & TypeWithID
|
const uploadDocument = node as UploadDataImproved
|
||||||
} = node as any
|
if (typeof uploadDocument.value !== 'object') {
|
||||||
|
return null
|
||||||
const url = uploadDocument?.value?.url
|
}
|
||||||
|
const url = uploadDocument.value.url
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If the upload is not an image, return a link to the upload
|
* If the upload is not an image, return a link to the upload
|
||||||
*/
|
*/
|
||||||
if (!uploadDocument?.value?.mimeType?.startsWith('image')) {
|
if (!uploadDocument.value.mimeType.startsWith('image')) {
|
||||||
return (
|
return (
|
||||||
<a href={url} rel="noopener noreferrer">
|
<a href={url} rel="noopener noreferrer">
|
||||||
{uploadDocument.value?.filename}
|
{uploadDocument.value.filename}
|
||||||
</a>
|
</a>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -25,13 +27,13 @@ export const UploadJSXConverter: JSXConverters<SerializedUploadNode> = {
|
|||||||
/**
|
/**
|
||||||
* If the upload is a simple image with no different sizes, return a simple img tag
|
* If the upload is a simple image with no different sizes, return a simple img tag
|
||||||
*/
|
*/
|
||||||
if (!uploadDocument?.value?.sizes || !Object.keys(uploadDocument?.value?.sizes).length) {
|
if (!Object.keys(uploadDocument.value.sizes).length) {
|
||||||
return (
|
return (
|
||||||
<img
|
<img
|
||||||
alt={uploadDocument?.value?.filename}
|
alt={uploadDocument.value.filename}
|
||||||
height={uploadDocument?.value?.height}
|
height={uploadDocument.value.height}
|
||||||
src={url}
|
src={url}
|
||||||
width={uploadDocument?.value?.width}
|
width={uploadDocument.value.width}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -42,13 +44,12 @@ export const UploadJSXConverter: JSXConverters<SerializedUploadNode> = {
|
|||||||
const pictureJSX: React.ReactNode[] = []
|
const pictureJSX: React.ReactNode[] = []
|
||||||
|
|
||||||
// Iterate through each size in the data.sizes object
|
// Iterate through each size in the data.sizes object
|
||||||
for (const size in uploadDocument.value?.sizes) {
|
for (const size in uploadDocument.value.sizes) {
|
||||||
const imageSize: {
|
const imageSize = uploadDocument.value.sizes[size] as FileSizeImproved
|
||||||
url?: string
|
|
||||||
} & FileSize = uploadDocument.value?.sizes[size]
|
|
||||||
|
|
||||||
// Skip if any property of the size object is null
|
// Skip if any property of the size object is null
|
||||||
if (
|
if (
|
||||||
|
!imageSize ||
|
||||||
!imageSize.width ||
|
!imageSize.width ||
|
||||||
!imageSize.height ||
|
!imageSize.height ||
|
||||||
!imageSize.mimeType ||
|
!imageSize.mimeType ||
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import type {
|
|||||||
NodeKey,
|
NodeKey,
|
||||||
Spread,
|
Spread,
|
||||||
} from 'lexical'
|
} from 'lexical'
|
||||||
import type { CollectionSlug, DataFromCollectionSlug, JsonObject } from 'payload'
|
import type { FileData, JsonObject, TypedCollection, TypeWithID } from 'payload'
|
||||||
import type { JSX } from 'react'
|
import type { JSX } from 'react'
|
||||||
|
|
||||||
import { DecoratorBlockNode } from '@lexical/react/LexicalDecoratorBlockNode.js'
|
import { DecoratorBlockNode } from '@lexical/react/LexicalDecoratorBlockNode.js'
|
||||||
@@ -17,15 +17,28 @@ import { $applyNodeReplacement } from 'lexical'
|
|||||||
import * as React from 'react'
|
import * as React from 'react'
|
||||||
|
|
||||||
export type UploadData<TUploadExtraFieldsData extends JsonObject = JsonObject> = {
|
export type UploadData<TUploadExtraFieldsData extends JsonObject = JsonObject> = {
|
||||||
[TCollectionSlug in CollectionSlug]: {
|
fields: TUploadExtraFieldsData
|
||||||
fields: TUploadExtraFieldsData
|
/** Every lexical node that has sub-fields needs to have a unique ID. This is the ID of this upload node, not the ID of the linked upload document */
|
||||||
// Every lexical node that has sub-fields needs to have a unique ID. This is the ID of this upload node, not the ID of the linked upload document
|
id: string
|
||||||
id: string
|
relationTo: string
|
||||||
relationTo: TCollectionSlug
|
/** Value can be just the document ID, or the full, populated document */
|
||||||
// Value can be just the document ID, or the full, populated document
|
value: number | string | TypedCollection
|
||||||
value: DataFromCollectionSlug<TCollectionSlug> | number | string
|
}
|
||||||
}
|
|
||||||
}[CollectionSlug]
|
// TODO: deprecate in Payload v4.
|
||||||
|
/**
|
||||||
|
* UploadDataImproved is a more precise type, and will replace UploadData in Payload v4.
|
||||||
|
* This type is for internal use only as it will be deprecated in the future.
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
export type UploadDataImproved<TUploadExtraFieldsData extends JsonObject = JsonObject> = {
|
||||||
|
fields: TUploadExtraFieldsData
|
||||||
|
// Every lexical node that has sub-fields needs to have a unique ID. This is the ID of this upload node, not the ID of the linked upload document
|
||||||
|
id: string
|
||||||
|
relationTo: string
|
||||||
|
// Value can be just the document ID, or the full, populated document
|
||||||
|
value: (FileData & TypeWithID) | number | string
|
||||||
|
}
|
||||||
|
|
||||||
export function isGoogleDocCheckboxImg(img: HTMLImageElement): boolean {
|
export function isGoogleDocCheckboxImg(img: HTMLImageElement): boolean {
|
||||||
return (
|
return (
|
||||||
|
|||||||
Reference in New Issue
Block a user