chore(richtext-lexical): add noImplicitAny to the richtext-lexical package (#8763)
This commit is contained in:
@@ -21,11 +21,17 @@ export function parseJSXToAST({
|
||||
// Remove "position" keys
|
||||
const parseTree = (tree: object) => {
|
||||
for (const key in tree) {
|
||||
// @ts-expect-error - vestiges of when tsconfig was not strict. Feel free to improve
|
||||
if (key === 'position' && tree[key].start && tree[key].end) {
|
||||
// @ts-expect-error - vestiges of when tsconfig was not strict. Feel free to improve
|
||||
delete tree[key]
|
||||
// @ts-expect-error - vestiges of when tsconfig was not strict. Feel free to improve
|
||||
} else if (typeof tree[key] === 'object') {
|
||||
// @ts-expect-error - vestiges of when tsconfig was not strict. Feel free to improve
|
||||
parseTree(tree[key])
|
||||
// @ts-expect-error - vestiges of when tsconfig was not strict. Feel free to improve
|
||||
} else if (Array.isArray(tree[key])) {
|
||||
// @ts-expect-error - vestiges of when tsconfig was not strict. Feel free to improve
|
||||
for (const item of tree[key]) {
|
||||
parseTree(item)
|
||||
}
|
||||
|
||||
@@ -162,7 +162,7 @@ export const BlockComponent: React.FC<Props> = (props) => {
|
||||
const { i18n, t } = useTranslation<object, string>()
|
||||
|
||||
const onChange = useCallback(
|
||||
async ({ formState: prevFormState, submit }) => {
|
||||
async ({ formState: prevFormState, submit }: { formState: FormState; submit: boolean }) => {
|
||||
abortAndIgnore(onChangeAbortControllerRef.current)
|
||||
|
||||
const controller = new AbortController()
|
||||
@@ -246,7 +246,9 @@ export const BlockComponent: React.FC<Props> = (props) => {
|
||||
})
|
||||
}, [editor, nodeKey])
|
||||
|
||||
// @ts-expect-error - vestiges of when tsconfig was not strict. Feel free to improve
|
||||
const CustomLabel = initialState?.['_components']?.customComponents?.BlockLabel
|
||||
// @ts-expect-error - vestiges of when tsconfig was not strict. Feel free to improve
|
||||
const CustomBlock = initialState?.['_components']?.customComponents?.Block
|
||||
|
||||
const blockDisplayName = clientBlock?.labels?.singular
|
||||
|
||||
@@ -3,7 +3,7 @@ import React from 'react'
|
||||
|
||||
import { useInlineBlockComponentContext } from '../index.js'
|
||||
|
||||
export const InlineBlockContainer = ({ children }) => {
|
||||
export const InlineBlockContainer = ({ children }: { children: React.ReactNode }) => {
|
||||
const { InlineBlockContainer } = useInlineBlockComponentContext()
|
||||
|
||||
return InlineBlockContainer ? <InlineBlockContainer>{children}</InlineBlockContainer> : null
|
||||
|
||||
@@ -219,7 +219,7 @@ export const InlineBlockComponent: React.FC<Props> = (props) => {
|
||||
* HANDLE ONCHANGE
|
||||
*/
|
||||
const onChange = useCallback(
|
||||
async ({ formState: prevFormState }) => {
|
||||
async ({ formState: prevFormState }: { formState: FormState }) => {
|
||||
abortAndIgnore(onChangeAbortControllerRef.current)
|
||||
|
||||
const controller = new AbortController()
|
||||
@@ -258,7 +258,7 @@ export const InlineBlockComponent: React.FC<Props> = (props) => {
|
||||
* HANDLE FORM SUBMIT
|
||||
*/
|
||||
const onFormSubmit = useCallback(
|
||||
(formState) => {
|
||||
(formState: FormState) => {
|
||||
const newData: any = reduceFieldsToValues(formState)
|
||||
newData.blockType = formData.blockType
|
||||
editor.update(() => {
|
||||
@@ -270,8 +270,9 @@ export const InlineBlockComponent: React.FC<Props> = (props) => {
|
||||
},
|
||||
[editor, nodeKey, formData],
|
||||
)
|
||||
|
||||
// @ts-expect-error - vestiges of when tsconfig was not strict. Feel free to improve
|
||||
const CustomLabel = initialState?.['_components']?.customComponents?.BlockLabel
|
||||
// @ts-expect-error - vestiges of when tsconfig was not strict. Feel free to improve
|
||||
const CustomBlock = initialState?.['_components']?.customComponents?.Block
|
||||
|
||||
const RemoveButton = useMemo(
|
||||
@@ -314,7 +315,7 @@ export const InlineBlockComponent: React.FC<Props> = (props) => {
|
||||
|
||||
const InlineBlockContainer = useMemo(
|
||||
() =>
|
||||
({ children }) => (
|
||||
({ children }: { children: React.ReactNode }) => (
|
||||
<div
|
||||
className={[
|
||||
baseClass,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
'use client'
|
||||
|
||||
import type { I18nClient } from '@payloadcms/translations'
|
||||
import type { BlocksFieldClient, ClientBlock } from 'payload'
|
||||
|
||||
import { getTranslation } from '@payloadcms/translations'
|
||||
@@ -82,7 +83,7 @@ export const BlocksFeatureClient = createClientFeature(
|
||||
} as SlashMenuItem
|
||||
}),
|
||||
key: 'blocks',
|
||||
label: ({ i18n }) => {
|
||||
label: ({ i18n }: { i18n: I18nClient<object, 'lexical:blocks:label'> }) => {
|
||||
return i18n.t('lexical:blocks:label')
|
||||
},
|
||||
}
|
||||
@@ -110,7 +111,11 @@ export const BlocksFeatureClient = createClientFeature(
|
||||
} as SlashMenuItem
|
||||
}),
|
||||
key: 'inlineBlocks',
|
||||
label: ({ i18n }) => {
|
||||
label: ({
|
||||
i18n,
|
||||
}: {
|
||||
i18n: I18nClient<object, 'lexical:blocks:inlineBlocks:label'>
|
||||
}) => {
|
||||
return i18n.t('lexical:blocks:inlineBlocks:label')
|
||||
},
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-nocheck - not worth it migrate jsdoc to tsdoc
|
||||
'use client'
|
||||
// Copied & modified from https://github.com/lodash/lodash/blob/main/src/debounce.ts
|
||||
/*
|
||||
@@ -242,4 +244,5 @@ function debounce(func, wait, options) {
|
||||
return debounced
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-restricted-exports
|
||||
export default debounce
|
||||
|
||||
@@ -87,18 +87,15 @@ const Component: React.FC<Props> = (props) => {
|
||||
})
|
||||
}, [editor, nodeKey])
|
||||
|
||||
const updateRelationship = React.useCallback(
|
||||
({ doc }) => {
|
||||
setParams({
|
||||
...initialParams,
|
||||
cacheBust, // do this to get the usePayloadAPI to re-fetch the data even though the URL string hasn't changed
|
||||
})
|
||||
const updateRelationship = React.useCallback(() => {
|
||||
setParams({
|
||||
...initialParams,
|
||||
cacheBust, // do this to get the usePayloadAPI to re-fetch the data even though the URL string hasn't changed
|
||||
})
|
||||
|
||||
closeDocumentDrawer()
|
||||
dispatchCacheBust()
|
||||
},
|
||||
[cacheBust, setParams, closeDocumentDrawer],
|
||||
)
|
||||
closeDocumentDrawer()
|
||||
dispatchCacheBust()
|
||||
}, [cacheBust, setParams, closeDocumentDrawer])
|
||||
|
||||
const $onDelete = useCallback(
|
||||
(payload: KeyboardEvent) => {
|
||||
|
||||
@@ -68,7 +68,7 @@ const RelationshipDrawerComponent: React.FC<Props> = ({ enabledCollectionSlugs }
|
||||
}, [editor, openListDrawer])
|
||||
|
||||
const onSelect = useCallback(
|
||||
({ collectionSlug, docID }) => {
|
||||
({ collectionSlug, docID }: { collectionSlug: string; docID: number | string }) => {
|
||||
insertRelationship({
|
||||
editor,
|
||||
relationTo: collectionSlug,
|
||||
|
||||
@@ -209,7 +209,7 @@ function InlineToolbar({
|
||||
const isLinkEditorVisible =
|
||||
possibleLinkEditor !== null &&
|
||||
'style' in possibleLinkEditor &&
|
||||
possibleLinkEditor?.style?.['opacity'] === '1'
|
||||
possibleLinkEditor?.style?.['opacity' as keyof typeof possibleLinkEditor.style] === '1'
|
||||
|
||||
const rootElement = editor.getRootElement()
|
||||
if (
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
'use client'
|
||||
import type { ClientCollectionConfig, Data } from 'payload'
|
||||
import type { ClientCollectionConfig, Data, FormState, JsonObject } from 'payload'
|
||||
|
||||
import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext.js'
|
||||
import { useLexicalNodeSelection } from '@lexical/react/useLexicalNodeSelection.js'
|
||||
@@ -183,7 +183,7 @@ const Component: React.FC<ElementProps> = (props) => {
|
||||
).collections?.[relatedCollection.slug]?.hasExtraFields
|
||||
|
||||
const onExtraFieldsDrawerSubmit = useCallback(
|
||||
(_, data) => {
|
||||
(_: FormState, data: JsonObject) => {
|
||||
// Update lexical node (with key nodeKey) with new data
|
||||
editor.update(() => {
|
||||
const uploadNode: null | UploadNode = $getNodeByKey(nodeKey)
|
||||
|
||||
@@ -77,7 +77,7 @@ const UploadDrawerComponent: React.FC<Props> = ({ enabledCollectionSlugs }) => {
|
||||
}, [editor, openListDrawer])
|
||||
|
||||
const onSelect = useCallback(
|
||||
({ collectionSlug, docID }) => {
|
||||
({ collectionSlug, docID }: { collectionSlug: string; docID: number | string }) => {
|
||||
closeListDrawer()
|
||||
insertUpload({
|
||||
editor,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
'use client'
|
||||
import type { EditorState, SerializedEditorState } from 'lexical'
|
||||
import type { Validate } from 'payload'
|
||||
|
||||
import { FieldLabel, useEditDepth, useField, withCondition } from '@payloadcms/ui'
|
||||
import { mergeFieldStyles } from '@payloadcms/ui/shared'
|
||||
@@ -10,9 +11,9 @@ import type { SanitizedClientEditorConfig } from '../lexical/config/types.js'
|
||||
import type { LexicalRichTextFieldProps } from '../types.js'
|
||||
|
||||
import { LexicalProvider } from '../lexical/LexicalProvider.js'
|
||||
import '../lexical/theme/EditorTheme.scss'
|
||||
import './bundled.css'
|
||||
import './index.scss'
|
||||
import '../lexical/theme/EditorTheme.scss'
|
||||
|
||||
const baseClass = 'rich-text-lexical'
|
||||
|
||||
@@ -41,11 +42,13 @@ const RichTextComponent: React.FC<
|
||||
|
||||
const editDepth = useEditDepth()
|
||||
|
||||
const memoizedValidate = useCallback(
|
||||
const memoizedValidate = useCallback<Validate>(
|
||||
(value, validationOptions) => {
|
||||
if (typeof validate === 'function') {
|
||||
// @ts-expect-error - vestiges of when tsconfig was not strict. Feel free to improve
|
||||
return validate(value, { ...validationOptions, required })
|
||||
}
|
||||
return true
|
||||
},
|
||||
// Important: do not add props to the dependencies array.
|
||||
// This would cause an infinite loop and endless re-rendering.
|
||||
@@ -63,7 +66,6 @@ const RichTextComponent: React.FC<
|
||||
value,
|
||||
} = useField<SerializedEditorState>({
|
||||
path,
|
||||
// @ts-expect-error: TODO: Fix this
|
||||
validate: memoizedValidate,
|
||||
})
|
||||
|
||||
@@ -115,7 +117,7 @@ const RichTextComponent: React.FC<
|
||||
)
|
||||
}
|
||||
|
||||
function fallbackRender({ error }): React.ReactElement {
|
||||
function fallbackRender({ error }: { error: Error }) {
|
||||
// Call resetErrorBoundary() to reset the error boundary and retry the render.
|
||||
|
||||
return (
|
||||
|
||||
@@ -73,8 +73,8 @@ export const RscEntryLexicalField: React.FC<
|
||||
}
|
||||
|
||||
for (const key in props) {
|
||||
if (!props[key]) {
|
||||
delete props[key]
|
||||
if (props[key as keyof LexicalRichTextFieldProps] === undefined) {
|
||||
delete props[key as keyof LexicalRichTextFieldProps]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -66,7 +66,7 @@ export function lexicalEditor(props?: LexicalEditorProps): LexicalRichTextAdapte
|
||||
})
|
||||
}
|
||||
|
||||
let features: FeatureProviderServer<any, any, any>[] = []
|
||||
let features: FeatureProviderServer<unknown, unknown, unknown>[] = []
|
||||
let resolvedFeatureMap: ResolvedServerFeatureMap
|
||||
|
||||
let finalSanitizedEditorConfig: SanitizedServerEditorConfig // For server only
|
||||
@@ -124,12 +124,12 @@ export function lexicalEditor(props?: LexicalEditorProps): LexicalRichTextAdapte
|
||||
|
||||
const featureI18n = finalSanitizedEditorConfig.features.i18n
|
||||
for (const lang in i18n) {
|
||||
if (!featureI18n[lang]) {
|
||||
featureI18n[lang] = {
|
||||
if (!featureI18n[lang as keyof typeof featureI18n]) {
|
||||
featureI18n[lang as keyof typeof featureI18n] = {
|
||||
lexical: {},
|
||||
}
|
||||
}
|
||||
|
||||
// @ts-expect-error - vestiges of when tsconfig was not strict. Feel free to improve
|
||||
featureI18n[lang].lexical.general = i18n[lang]
|
||||
}
|
||||
|
||||
@@ -207,6 +207,8 @@ export function lexicalEditor(props?: LexicalEditorProps): LexicalRichTextAdapte
|
||||
) {
|
||||
return value
|
||||
}
|
||||
// TO-DO: We should not use context, as it is intended for external use only
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const context: any = _context
|
||||
const nodeIDMap: {
|
||||
[key: string]: SerializedLexicalNode
|
||||
@@ -439,6 +441,8 @@ export function lexicalEditor(props?: LexicalEditorProps): LexicalRichTextAdapte
|
||||
return value
|
||||
}
|
||||
|
||||
// TO-DO: We should not use context, as it is intended for external use only
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const context: any = _context
|
||||
const nodeIDMap: {
|
||||
[key: string]: SerializedLexicalNode
|
||||
|
||||
@@ -26,7 +26,14 @@ export type LexicalProviderProps = {
|
||||
value: SerializedEditorState
|
||||
}
|
||||
|
||||
const NestProviders = ({ children, providers }) => {
|
||||
const NestProviders = ({
|
||||
children,
|
||||
providers,
|
||||
}: {
|
||||
children: React.ReactNode
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
providers: any[]
|
||||
}) => {
|
||||
if (!providers?.length) {
|
||||
return children
|
||||
}
|
||||
|
||||
@@ -69,11 +69,12 @@ export const sanitizeServerFeatures = (
|
||||
|
||||
if (feature?.i18n) {
|
||||
for (const lang in feature.i18n) {
|
||||
if (!sanitized.i18n[lang]) {
|
||||
sanitized.i18n[lang] = {
|
||||
if (!sanitized.i18n[lang as keyof typeof sanitized.i18n]) {
|
||||
sanitized.i18n[lang as keyof typeof sanitized.i18n] = {
|
||||
lexical: {},
|
||||
}
|
||||
}
|
||||
// @ts-expect-error - vestiges of when tsconfig was not strict. Feel free to improve
|
||||
sanitized.i18n[lang].lexical[feature.key] = feature.i18n[lang]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -126,7 +126,7 @@ function useAddBlockHandle(
|
||||
}, [anchorElem, hoveredElement, blockHandleHorizontalOffset])
|
||||
|
||||
const handleAddClick = useCallback(
|
||||
(event) => {
|
||||
(event: React.MouseEvent<HTMLButtonElement, MouseEvent>) => {
|
||||
let hoveredElementToUse = hoveredElement
|
||||
if (!hoveredElementToUse?.node) {
|
||||
return
|
||||
@@ -189,6 +189,7 @@ function useAddBlockHandle(
|
||||
return createPortal(
|
||||
<React.Fragment>
|
||||
<button
|
||||
aria-label="Add block"
|
||||
className="icon add-block-menu"
|
||||
onClick={(event) => {
|
||||
handleAddClick(event)
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
'use client'
|
||||
export function debounce(func: (...args: any[]) => void, wait: number) {
|
||||
let timeout
|
||||
return function (...args: any[]) {
|
||||
export function debounce(func: (...args: undefined[]) => void, wait: number) {
|
||||
let timeout: number | string | undefined
|
||||
return function (...args: undefined[]) {
|
||||
const later = () => {
|
||||
clearTimeout(timeout)
|
||||
timeout = null
|
||||
timeout = undefined
|
||||
func(...args)
|
||||
}
|
||||
|
||||
|
||||
@@ -75,7 +75,7 @@ export const DrawerContent: React.FC<Omit<FieldsDrawerProps, 'drawerSlug' | 'dra
|
||||
}, [schemaFieldsPath, id, data, getFormState, collectionSlug, globalSlug, getDocPreferences])
|
||||
|
||||
const onChange = useCallback(
|
||||
async ({ formState: prevFormState }) => {
|
||||
async ({ formState: prevFormState }: { formState: FormState }) => {
|
||||
abortAndIgnore(onChangeAbortControllerRef.current)
|
||||
|
||||
const controller = new AbortController()
|
||||
|
||||
@@ -6,6 +6,7 @@ import type { ResolvedServerFeatureMap } from '../features/typesServer.js'
|
||||
|
||||
export const getGenerateImportMap =
|
||||
(args: { resolvedFeatureMap: ResolvedServerFeatureMap }): RichTextAdapter['generateImportMap'] =>
|
||||
// @ts-expect-error - vestiges of when tsconfig was not strict. Feel free to improve
|
||||
({ addToImportMap, baseDir, config, importMap, imports }) => {
|
||||
addToImportMap('@payloadcms/richtext-lexical/rsc#RscEntryLexicalCell')
|
||||
addToImportMap('@payloadcms/richtext-lexical/rsc#RscEntryLexicalField')
|
||||
@@ -22,6 +23,7 @@ export const getGenerateImportMap =
|
||||
imports,
|
||||
})
|
||||
} else if (resolvedFeature.componentImports?.length) {
|
||||
// @ts-expect-error - vestiges of when tsconfig was not strict. Feel free to improve
|
||||
resolvedFeature.componentImports.forEach((component) => {
|
||||
addToImportMap(component)
|
||||
})
|
||||
|
||||
@@ -62,6 +62,7 @@ export function frontmatterToObject(frontmatter: string): Record<string, any> {
|
||||
const [key, ...valueParts] = line.split(':')
|
||||
const value = valueParts.join(':').trim()
|
||||
|
||||
// @ts-expect-error - vestiges of when tsconfig was not strict. Feel free to improve
|
||||
result[key.trim()] = value
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable no-console */
|
||||
import type { CollectionConfig, Field, GlobalConfig, Payload } from 'payload'
|
||||
|
||||
import { migrateDocumentFieldsRecursively } from './migrateDocumentFieldsRecursively.js'
|
||||
@@ -15,7 +16,7 @@ import { migrateDocumentFieldsRecursively } from './migrateDocumentFieldsRecursi
|
||||
export async function migrateSlateToLexical({ payload }: { payload: Payload }) {
|
||||
const collections = payload.config.collections
|
||||
|
||||
const errors = []
|
||||
const errors: unknown[] = []
|
||||
|
||||
const allLocales = payload.config.localization ? payload.config.localization.localeCodes : [null]
|
||||
|
||||
@@ -56,7 +57,7 @@ async function migrateGlobal({
|
||||
locale,
|
||||
payload,
|
||||
}: {
|
||||
errors: any[]
|
||||
errors: unknown[]
|
||||
global: GlobalConfig
|
||||
locale: null | string
|
||||
payload: Payload
|
||||
@@ -105,7 +106,7 @@ async function migrateCollection({
|
||||
}: {
|
||||
collection: CollectionConfig
|
||||
cur: number
|
||||
errors: any[]
|
||||
errors: unknown[]
|
||||
locale: null | string
|
||||
max: number
|
||||
payload: Payload
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { SerializedEditorState, SerializedParagraphNode } from 'lexical'
|
||||
import type { SerializedEditorState, SerializedParagraphNode, SerializedTextNode } from 'lexical'
|
||||
import type { RichTextField, Validate } from 'payload'
|
||||
|
||||
import type { SanitizedServerEditorConfig } from '../lexical/config/types.js'
|
||||
@@ -32,7 +32,7 @@ export const richTextValidateHOC = ({
|
||||
} else if (paragraphNode?.children?.length === 1) {
|
||||
const paragraphNodeChild = paragraphNode?.children[0]
|
||||
if (paragraphNodeChild.type === 'text') {
|
||||
if (!paragraphNodeChild?.['text']?.length) {
|
||||
if (!(paragraphNodeChild as SerializedTextNode | undefined)?.['text']?.length) {
|
||||
hasOnlyEmptyParagraph = true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
"emitDeclarationOnly": true,
|
||||
"esModuleInterop": true,
|
||||
"strictNullChecks": true,
|
||||
"noImplicitAny": true,
|
||||
"outDir": "./dist" /* Specify an output folder for all emitted files. */,
|
||||
"rootDir": "./src" /* Specify the root folder within your source files. */,
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user