Compare commits
12 Commits
test/ts-ty
...
v3.0.0-bet
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0b9397399a | ||
|
|
cdcc35ccdb | ||
|
|
442189ec48 | ||
|
|
5d1cc760c9 | ||
|
|
2f90683c7d | ||
|
|
3f5403a52a | ||
|
|
9bccdfd60a | ||
|
|
62666a9897 | ||
|
|
eb27b84854 | ||
|
|
c3480811d3 | ||
|
|
12ba820de4 | ||
|
|
e65b6478c9 |
7
.vscode/launch.json
vendored
7
.vscode/launch.json
vendored
@@ -56,6 +56,13 @@
|
||||
"request": "launch",
|
||||
"type": "node-terminal"
|
||||
},
|
||||
{
|
||||
"command": "node --no-deprecation test/dev.js login-with-username",
|
||||
"cwd": "${workspaceFolder}",
|
||||
"name": "Run Dev Login-With-Username",
|
||||
"request": "launch",
|
||||
"type": "node-terminal"
|
||||
},
|
||||
{
|
||||
"command": "pnpm run dev plugin-cloud-storage",
|
||||
"cwd": "${workspaceFolder}",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "payload-monorepo",
|
||||
"version": "3.0.0-beta.73",
|
||||
"version": "3.0.0-beta.74",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "create-payload-app",
|
||||
"version": "3.0.0-beta.73",
|
||||
"version": "3.0.0-beta.74",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/db-mongodb",
|
||||
"version": "3.0.0-beta.73",
|
||||
"version": "3.0.0-beta.74",
|
||||
"description": "The officially supported MongoDB database adapter for Payload",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/db-postgres",
|
||||
"version": "3.0.0-beta.73",
|
||||
"version": "3.0.0-beta.74",
|
||||
"description": "The officially supported Postgres database adapter for Payload",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/db-sqlite",
|
||||
"version": "3.0.0-beta.73",
|
||||
"version": "3.0.0-beta.74",
|
||||
"description": "The officially supported SQLite database adapter for Payload",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { AnySQLiteColumn} from 'drizzle-orm/sqlite-core';
|
||||
import type { AnySQLiteColumn } from 'drizzle-orm/sqlite-core'
|
||||
|
||||
import { index, uniqueIndex } from 'drizzle-orm/sqlite-core'
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/drizzle",
|
||||
"version": "3.0.0-beta.73",
|
||||
"version": "3.0.0-beta.74",
|
||||
"description": "A library of shared functions used by different payload database adapters",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/email-nodemailer",
|
||||
"version": "3.0.0-beta.73",
|
||||
"version": "3.0.0-beta.74",
|
||||
"description": "Payload Nodemailer Email Adapter",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/email-resend",
|
||||
"version": "3.0.0-beta.73",
|
||||
"version": "3.0.0-beta.74",
|
||||
"description": "Payload Resend Email Adapter",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/graphql",
|
||||
"version": "3.0.0-beta.73",
|
||||
"version": "3.0.0-beta.74",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/live-preview-react",
|
||||
"version": "3.0.0-beta.73",
|
||||
"version": "3.0.0-beta.74",
|
||||
"description": "The official React SDK for Payload Live Preview",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/live-preview-vue",
|
||||
"version": "3.0.0-beta.73",
|
||||
"version": "3.0.0-beta.74",
|
||||
"description": "The official Vue SDK for Payload Live Preview",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/live-preview",
|
||||
"version": "3.0.0-beta.73",
|
||||
"version": "3.0.0-beta.74",
|
||||
"description": "The official live preview JavaScript SDK for Payload",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/next",
|
||||
"version": "3.0.0-beta.73",
|
||||
"version": "3.0.0-beta.74",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
@@ -1,45 +1,103 @@
|
||||
'use client'
|
||||
|
||||
import type { LoginWithUsernameOptions } from 'payload'
|
||||
import type { FieldPermissions, LoginWithUsernameOptions } from 'payload'
|
||||
|
||||
import { EmailField, TextField, useTranslation } from '@payloadcms/ui'
|
||||
import { EmailField, RenderFields, TextField, useTranslation } from '@payloadcms/ui'
|
||||
import { email, username } from 'payload/shared'
|
||||
import React from 'react'
|
||||
|
||||
type Props = {
|
||||
loginWithUsername?: LoginWithUsernameOptions | false
|
||||
}
|
||||
export const EmailAndUsernameFields: React.FC<Props> = ({ loginWithUsername }) => {
|
||||
function EmailFieldComponent(props: Props) {
|
||||
const { loginWithUsername } = props
|
||||
const { t } = useTranslation()
|
||||
|
||||
const requireEmail = !loginWithUsername || (loginWithUsername && loginWithUsername.requireEmail)
|
||||
const requireUsername = loginWithUsername && loginWithUsername.requireUsername
|
||||
const showEmailField =
|
||||
!loginWithUsername || loginWithUsername?.requireEmail || loginWithUsername?.allowEmailLogin
|
||||
|
||||
if (showEmailField) {
|
||||
return (
|
||||
<EmailField
|
||||
autoComplete="off"
|
||||
label={t('general:email')}
|
||||
name="email"
|
||||
path="email"
|
||||
required={requireEmail}
|
||||
validate={email}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
function UsernameFieldComponent(props: Props) {
|
||||
const { loginWithUsername } = props
|
||||
const { t } = useTranslation()
|
||||
|
||||
const requireUsername = loginWithUsername && loginWithUsername.requireUsername
|
||||
const showUsernameField = Boolean(loginWithUsername)
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
{showEmailField && (
|
||||
<EmailField
|
||||
autoComplete="email"
|
||||
label={t('general:email')}
|
||||
name="email"
|
||||
path="email"
|
||||
required={requireEmail}
|
||||
validate={email}
|
||||
/>
|
||||
)}
|
||||
if (showUsernameField) {
|
||||
return (
|
||||
<TextField
|
||||
label={t('authentication:username')}
|
||||
name="username"
|
||||
path="username"
|
||||
required={requireUsername}
|
||||
validate={username}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
{showUsernameField && (
|
||||
<TextField
|
||||
label={t('authentication:username')}
|
||||
name="username"
|
||||
path="username"
|
||||
required={requireUsername}
|
||||
validate={username}
|
||||
/>
|
||||
)}
|
||||
</React.Fragment>
|
||||
return null
|
||||
}
|
||||
|
||||
type RenderEmailAndUsernameFieldsProps = {
|
||||
className?: string
|
||||
loginWithUsername?: LoginWithUsernameOptions | false
|
||||
operation?: 'create' | 'update'
|
||||
permissions?: {
|
||||
[fieldName: string]: FieldPermissions
|
||||
}
|
||||
readOnly: boolean
|
||||
}
|
||||
export function RenderEmailAndUsernameFields(props: RenderEmailAndUsernameFieldsProps) {
|
||||
const { className, loginWithUsername, operation, permissions, readOnly } = props
|
||||
|
||||
return (
|
||||
<RenderFields
|
||||
className={className}
|
||||
fieldMap={[
|
||||
{
|
||||
name: 'email',
|
||||
type: 'text',
|
||||
CustomField: <EmailFieldComponent loginWithUsername={loginWithUsername} />,
|
||||
cellComponentProps: null,
|
||||
fieldComponentProps: { type: 'email', readOnly },
|
||||
fieldIsPresentational: false,
|
||||
isFieldAffectingData: true,
|
||||
localized: false,
|
||||
},
|
||||
{
|
||||
name: 'username',
|
||||
type: 'text',
|
||||
CustomField: <UsernameFieldComponent loginWithUsername={loginWithUsername} />,
|
||||
cellComponentProps: null,
|
||||
fieldComponentProps: { type: 'text', readOnly },
|
||||
fieldIsPresentational: false,
|
||||
isFieldAffectingData: true,
|
||||
localized: false,
|
||||
},
|
||||
]}
|
||||
forceRender
|
||||
operation={operation}
|
||||
path=""
|
||||
permissions={permissions}
|
||||
readOnly={readOnly}
|
||||
schemaPath=""
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ import {
|
||||
import { getFormState } from '@payloadcms/ui/shared'
|
||||
import React from 'react'
|
||||
|
||||
import { EmailAndUsernameFields } from '../../elements/EmailAndUsername/index.js'
|
||||
import { RenderEmailAndUsernameFields } from '../../elements/EmailAndUsername/index.js'
|
||||
|
||||
export const CreateFirstUserClient: React.FC<{
|
||||
initialState: FormState
|
||||
@@ -57,7 +57,12 @@ export const CreateFirstUserClient: React.FC<{
|
||||
redirect={admin}
|
||||
validationOperation="create"
|
||||
>
|
||||
<EmailAndUsernameFields loginWithUsername={loginWithUsername} />
|
||||
<RenderEmailAndUsernameFields
|
||||
className="emailAndUsername"
|
||||
loginWithUsername={loginWithUsername}
|
||||
operation="create"
|
||||
readOnly={false}
|
||||
/>
|
||||
<PasswordField
|
||||
label={t('authentication:newPassword')}
|
||||
name="password"
|
||||
|
||||
@@ -3,3 +3,7 @@
|
||||
margin-bottom: var(--base);
|
||||
}
|
||||
}
|
||||
|
||||
.emailAndUsername {
|
||||
margin-bottom: var(--base);
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ import { toast } from 'sonner'
|
||||
|
||||
import type { Props } from './types.js'
|
||||
|
||||
import { EmailAndUsernameFields } from '../../../../elements/EmailAndUsername/index.js'
|
||||
import { RenderEmailAndUsernameFields } from '../../../../elements/EmailAndUsername/index.js'
|
||||
import { APIKey } from './APIKey.js'
|
||||
import './index.scss'
|
||||
|
||||
@@ -47,7 +47,7 @@ export const Auth: React.FC<Props> = (props) => {
|
||||
const dispatchFields = useFormFields((reducer) => reducer[1])
|
||||
const modified = useFormModified()
|
||||
const { i18n, t } = useTranslation()
|
||||
const { isInitializing } = useDocumentInfo()
|
||||
const { docPermissions, isInitializing } = useDocumentInfo()
|
||||
|
||||
const {
|
||||
routes: { api },
|
||||
@@ -138,7 +138,12 @@ export const Auth: React.FC<Props> = (props) => {
|
||||
<div className={[baseClass, className].filter(Boolean).join(' ')}>
|
||||
{!disableLocalStrategy && (
|
||||
<React.Fragment>
|
||||
<EmailAndUsernameFields loginWithUsername={loginWithUsername} />
|
||||
<RenderEmailAndUsernameFields
|
||||
loginWithUsername={loginWithUsername}
|
||||
operation={operation}
|
||||
permissions={docPermissions?.fields}
|
||||
readOnly={readOnly}
|
||||
/>
|
||||
{(showPasswordFields || requirePassword) && (
|
||||
<div className={`${baseClass}__changing-password`}>
|
||||
<PasswordField
|
||||
|
||||
@@ -45,13 +45,10 @@ export const LoginField: React.FC<LoginFieldProps> = ({ type, required = true })
|
||||
path="username"
|
||||
required={required}
|
||||
validate={(value, options) => {
|
||||
const passesUsername = username(
|
||||
value,
|
||||
options as ValidateOptions<any, { email?: string }, any, string>,
|
||||
)
|
||||
const passesUsername = username(value, options)
|
||||
const passesEmail = email(
|
||||
value,
|
||||
options as ValidateOptions<any, { username?: string }, any, string>,
|
||||
options as ValidateOptions<any, { username?: string }, any, any>,
|
||||
)
|
||||
|
||||
if (!passesEmail && !passesUsername) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "payload",
|
||||
"version": "3.0.0-beta.73",
|
||||
"version": "3.0.0-beta.74",
|
||||
"description": "Node, React, Headless CMS and Application Framework built on Next.js",
|
||||
"keywords": [
|
||||
"admin panel",
|
||||
|
||||
@@ -6,7 +6,7 @@ import type { SanitizedCollectionConfig, TypeWithID } from '../collections/confi
|
||||
import type { SanitizedConfig } from '../config/types.js'
|
||||
import type { Field, FieldAffectingData, RichTextField, Validate } from '../fields/config/types.js'
|
||||
import type { SanitizedGlobalConfig } from '../globals/config/types.js'
|
||||
import type { JsonObject, PayloadRequest, RequestContext } from '../types/index.js'
|
||||
import type { JsonObject, Payload, PayloadRequest, RequestContext } from '../types/index.js'
|
||||
import type { WithServerSidePropsComponentProps } from './elements/WithServerSideProps.js'
|
||||
|
||||
export type RichTextFieldProps<Value extends object, AdapterProps, ExtraFieldProperties = {}> = {
|
||||
@@ -189,6 +189,7 @@ type RichTextAdapterBase<
|
||||
WithServerSideProps: React.FC<Omit<WithServerSidePropsComponentProps, 'serverOnlyProps'>>
|
||||
config: SanitizedConfig
|
||||
i18n: I18nClient
|
||||
payload: Payload
|
||||
schemaPath: string
|
||||
}) => Map<string, React.ReactNode>
|
||||
generateSchemaMap?: (args: {
|
||||
|
||||
@@ -15,7 +15,7 @@ export type ArrayFieldProps = {
|
||||
name?: string
|
||||
validate?: ArrayFieldValidation
|
||||
width?: string
|
||||
} & FormFieldBase
|
||||
} & Omit<FormFieldBase, 'validate'>
|
||||
|
||||
export type ArrayFieldLabelComponent = LabelComponent<'array'>
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ export type BlocksFieldProps = {
|
||||
slug?: string
|
||||
validate?: BlockFieldValidation
|
||||
width?: string
|
||||
} & FormFieldBase
|
||||
} & Omit<FormFieldBase, 'validate'>
|
||||
|
||||
export type ReducedBlock = {
|
||||
LabelComponent: Block['admin']['components']['Label']
|
||||
|
||||
@@ -12,7 +12,7 @@ export type CheckboxFieldProps = {
|
||||
path?: string
|
||||
validate?: CheckboxFieldValidation
|
||||
width?: string
|
||||
} & FormFieldBase
|
||||
} & Omit<FormFieldBase, 'validate'>
|
||||
|
||||
export type CheckboxFieldLabelComponent = LabelComponent<'checkbox'>
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ export type CodeFieldProps = {
|
||||
path?: string
|
||||
validate?: CodeFieldValidation
|
||||
width: string
|
||||
} & FormFieldBase
|
||||
} & Omit<FormFieldBase, 'validate'>
|
||||
|
||||
export type CodeFieldLabelComponent = LabelComponent<'code'>
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ export type DateFieldProps = {
|
||||
placeholder?: DateField['admin']['placeholder'] | string
|
||||
validate?: DateFieldValidation
|
||||
width?: string
|
||||
} & FormFieldBase
|
||||
} & Omit<FormFieldBase, 'validate'>
|
||||
|
||||
export type DateFieldLabelComponent = LabelComponent<'date'>
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ export type EmailFieldProps = {
|
||||
placeholder?: EmailField['admin']['placeholder']
|
||||
validate?: EmailFieldValidation
|
||||
width?: string
|
||||
} & FormFieldBase
|
||||
} & Omit<FormFieldBase, 'validate'>
|
||||
|
||||
export type EmailFieldLabelComponent = LabelComponent<'email'>
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ export type JSONFieldProps = {
|
||||
path?: string
|
||||
validate?: JSONFieldValidation
|
||||
width?: string
|
||||
} & FormFieldBase
|
||||
} & Omit<FormFieldBase, 'validate'>
|
||||
|
||||
export type JSONFieldLabelComponent = LabelComponent<'json'>
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ export type NumberFieldProps = {
|
||||
step?: number
|
||||
validate?: NumberFieldValidation
|
||||
width?: string
|
||||
} & FormFieldBase
|
||||
} & Omit<FormFieldBase, 'validate'>
|
||||
|
||||
export type NumberFieldLabelComponent = LabelComponent<'number'>
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ export type PointFieldProps = {
|
||||
step?: number
|
||||
validate?: PointFieldValidation
|
||||
width?: string
|
||||
} & FormFieldBase
|
||||
} & Omit<FormFieldBase, 'validate'>
|
||||
|
||||
export type PointFieldLabelComponent = LabelComponent<'point'>
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ export type RadioFieldProps = {
|
||||
validate?: RadioFieldValidation
|
||||
value?: string
|
||||
width?: string
|
||||
} & FormFieldBase
|
||||
} & Omit<FormFieldBase, 'validate'>
|
||||
|
||||
export type OnChange<T = string> = (value: T) => void
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ export type RelationshipFieldProps = {
|
||||
sortOptions?: RelationshipField['admin']['sortOptions']
|
||||
validate?: RelationshipFieldValidation
|
||||
width?: string
|
||||
} & FormFieldBase
|
||||
} & Omit<FormFieldBase, 'validate'>
|
||||
|
||||
export type RelationshipFieldLabelComponent = LabelComponent<'relationship'>
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ export type RichTextComponentProps = {
|
||||
richTextComponentMap?: Map<string, MappedField[] | React.ReactNode>
|
||||
validate?: RichTextFieldValidation
|
||||
width?: string
|
||||
} & FormFieldBase
|
||||
} & Omit<FormFieldBase, 'validate'>
|
||||
|
||||
export type RichTextFieldLabelComponent = LabelComponent<'richText'>
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ export type SelectFieldProps = {
|
||||
validate?: SelectFieldValidation
|
||||
value?: string
|
||||
width?: string
|
||||
} & FormFieldBase
|
||||
} & Omit<FormFieldBase, 'validate'>
|
||||
|
||||
export type SelectFieldLabelComponent = LabelComponent<'select'>
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ export type TextFieldProps = {
|
||||
placeholder?: TextField['admin']['placeholder']
|
||||
validate?: TextFieldValidation
|
||||
width?: string
|
||||
} & FormFieldBase
|
||||
} & Omit<FormFieldBase, 'validate'>
|
||||
|
||||
export type TextFieldLabelComponent = LabelComponent<'text'>
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ export type TextareaFieldProps = {
|
||||
rows?: number
|
||||
validate?: TextareaFieldValidation
|
||||
width?: string
|
||||
} & FormFieldBase
|
||||
} & Omit<FormFieldBase, 'validate'>
|
||||
|
||||
export type TextareaFieldLabelComponent = LabelComponent<'textarea'>
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ export type UploadFieldProps = {
|
||||
relationTo?: UploadField['relationTo']
|
||||
validate?: UploadFieldValidation
|
||||
width?: string
|
||||
} & FormFieldBase
|
||||
} & Omit<FormFieldBase, 'validate'>
|
||||
|
||||
export type UploadFieldLabelComponent = LabelComponent<'upload'>
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/plugin-cloud-storage",
|
||||
"version": "3.0.0-beta.73",
|
||||
"version": "3.0.0-beta.74",
|
||||
"description": "The official cloud storage plugin for Payload CMS",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/plugin-cloud",
|
||||
"version": "3.0.0-beta.73",
|
||||
"version": "3.0.0-beta.74",
|
||||
"description": "The official Payload Cloud plugin",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/plugin-form-builder",
|
||||
"version": "3.0.0-beta.73",
|
||||
"version": "3.0.0-beta.74",
|
||||
"description": "Form builder plugin for Payload CMS",
|
||||
"keywords": [
|
||||
"payload",
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
'use client'
|
||||
|
||||
import type { TextFieldProps } from 'payload'
|
||||
import type { SelectFieldValidation, TextFieldProps } from 'payload'
|
||||
|
||||
import { SelectField, useForm } from '@payloadcms/ui'
|
||||
import React, { useEffect, useState } from 'react'
|
||||
|
||||
import type { SelectFieldOption } from '../../types.js'
|
||||
|
||||
export const DynamicFieldSelector: React.FC<TextFieldProps> = (props) => {
|
||||
export const DynamicFieldSelector: React.FC<
|
||||
{ validate: SelectFieldValidation } & TextFieldProps
|
||||
> = (props) => {
|
||||
const { fields, getDataByPath } = useForm()
|
||||
|
||||
const [options, setOptions] = useState<SelectFieldOption[]>([])
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/plugin-nested-docs",
|
||||
"version": "3.0.0-beta.73",
|
||||
"version": "3.0.0-beta.74",
|
||||
"description": "The official Nested Docs plugin for Payload",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/plugin-redirects",
|
||||
"version": "3.0.0-beta.73",
|
||||
"version": "3.0.0-beta.74",
|
||||
"description": "Redirects plugin for Payload",
|
||||
"keywords": [
|
||||
"payload",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/plugin-relationship-object-ids",
|
||||
"version": "3.0.0-beta.73",
|
||||
"version": "3.0.0-beta.74",
|
||||
"description": "A Payload plugin to store all relationship IDs as ObjectIDs",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/plugin-search",
|
||||
"version": "3.0.0-beta.73",
|
||||
"version": "3.0.0-beta.74",
|
||||
"description": "Search plugin for Payload",
|
||||
"keywords": [
|
||||
"payload",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/plugin-seo",
|
||||
"version": "3.0.0-beta.73",
|
||||
"version": "3.0.0-beta.74",
|
||||
"description": "SEO plugin for Payload",
|
||||
"keywords": [
|
||||
"payload",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/plugin-stripe",
|
||||
"version": "3.0.0-beta.73",
|
||||
"version": "3.0.0-beta.74",
|
||||
"description": "Stripe plugin for Payload",
|
||||
"keywords": [
|
||||
"payload",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/richtext-lexical",
|
||||
"version": "3.0.0-beta.73",
|
||||
"version": "3.0.0-beta.74",
|
||||
"description": "The officially supported Lexical richtext adapter for Payload",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
@@ -41,24 +41,24 @@
|
||||
"translateNewKeys": "tsx scripts/translateNewKeys.ts"
|
||||
},
|
||||
"dependencies": {
|
||||
"@lexical/headless": "0.16.1",
|
||||
"@lexical/link": "0.16.1",
|
||||
"@lexical/list": "0.16.1",
|
||||
"@lexical/mark": "0.16.1",
|
||||
"@lexical/markdown": "0.16.1",
|
||||
"@lexical/react": "0.16.1",
|
||||
"@lexical/rich-text": "0.16.1",
|
||||
"@lexical/selection": "0.16.1",
|
||||
"@lexical/utils": "0.16.1",
|
||||
"@lexical/headless": "0.17.0",
|
||||
"@lexical/link": "0.17.0",
|
||||
"@lexical/list": "0.17.0",
|
||||
"@lexical/mark": "0.17.0",
|
||||
"@lexical/markdown": "0.17.0",
|
||||
"@lexical/react": "0.17.0",
|
||||
"@lexical/rich-text": "0.17.0",
|
||||
"@lexical/selection": "0.17.0",
|
||||
"@lexical/utils": "0.17.0",
|
||||
"@types/uuid": "10.0.0",
|
||||
"bson-objectid": "2.0.4",
|
||||
"dequal": "2.0.3",
|
||||
"lexical": "0.16.1",
|
||||
"lexical": "0.17.0",
|
||||
"react-error-boundary": "4.0.13",
|
||||
"uuid": "10.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@lexical/eslint-plugin": " 0.16.1",
|
||||
"@lexical/eslint-plugin": "0.17.0",
|
||||
"@payloadcms/eslint-config": "workspace:*",
|
||||
"@payloadcms/next": "workspace:*",
|
||||
"@payloadcms/translations": "workspace:*",
|
||||
@@ -75,20 +75,20 @@
|
||||
"peerDependencies": {
|
||||
"@faceless-ui/modal": "3.0.0-beta.2",
|
||||
"@faceless-ui/scroll-info": "2.0.0-beta.0",
|
||||
"@lexical/headless": "0.16.1",
|
||||
"@lexical/link": "0.16.1",
|
||||
"@lexical/list": "0.16.1",
|
||||
"@lexical/mark": "0.16.1",
|
||||
"@lexical/markdown": "0.16.1",
|
||||
"@lexical/react": "0.16.1",
|
||||
"@lexical/rich-text": "0.16.1",
|
||||
"@lexical/selection": "0.16.1",
|
||||
"@lexical/table": "0.16.1",
|
||||
"@lexical/utils": "0.16.1",
|
||||
"@lexical/headless": "0.17.0",
|
||||
"@lexical/link": "0.17.0",
|
||||
"@lexical/list": "0.17.0",
|
||||
"@lexical/mark": "0.17.0",
|
||||
"@lexical/markdown": "0.17.0",
|
||||
"@lexical/react": "0.17.0",
|
||||
"@lexical/rich-text": "0.17.0",
|
||||
"@lexical/selection": "0.17.0",
|
||||
"@lexical/table": "0.17.0",
|
||||
"@lexical/utils": "0.17.0",
|
||||
"@payloadcms/next": "workspace:*",
|
||||
"@payloadcms/translations": "workspace:*",
|
||||
"@payloadcms/ui": "workspace:*",
|
||||
"lexical": "0.16.1",
|
||||
"lexical": "0.17.0",
|
||||
"payload": "workspace:*",
|
||||
"react": "^19.0.0 || ^19.0.0-rc-6230622a1a-20240610",
|
||||
"react-dom": "^19.0.0 || ^19.0.0-rc-6230622a1a-20240610"
|
||||
|
||||
@@ -8,6 +8,7 @@ import { slashMenuBasicGroupWithItems } from '../shared/slashMenu/basicGroup.js'
|
||||
import { toolbarAddDropdownGroupWithItems } from '../shared/toolbar/addDropdownGroup.js'
|
||||
import { TableActionMenuPlugin } from './plugins/TableActionMenuPlugin/index.js'
|
||||
import { TableCellResizerPlugin } from './plugins/TableCellResizerPlugin/index.js'
|
||||
import { TableHoverActionsPlugin } from './plugins/TableHoverActionsPlugin/index.js'
|
||||
import {
|
||||
OPEN_TABLE_DRAWER_COMMAND,
|
||||
TableContext,
|
||||
@@ -29,6 +30,10 @@ export const TableFeatureClient = createClientFeature({
|
||||
Component: TableActionMenuPlugin,
|
||||
position: 'floatingAnchorElem',
|
||||
},
|
||||
{
|
||||
Component: TableHoverActionsPlugin,
|
||||
position: 'floatingAnchorElem',
|
||||
},
|
||||
],
|
||||
providers: [TableContext],
|
||||
slashMenu: {
|
||||
|
||||
@@ -6,6 +6,8 @@ import { sanitizeFields } from 'payload'
|
||||
// eslint-disable-next-line payload/no-imports-from-exports-dir
|
||||
import { TableFeatureClient } from '../../exports/client/index.js'
|
||||
import { createServerFeature } from '../../utilities/createServerFeature.js'
|
||||
import { convertLexicalNodesToHTML } from '../converters/html/converter/index.js'
|
||||
import { createNode } from '../typeUtilities.js'
|
||||
|
||||
const fields: Field[] = [
|
||||
{
|
||||
@@ -41,15 +43,75 @@ export const EXPERIMENTAL_TableFeature = createServerFeature({
|
||||
return schemaMap
|
||||
},
|
||||
nodes: [
|
||||
{
|
||||
createNode({
|
||||
converters: {
|
||||
html: {
|
||||
converter: async ({ converters, node, parent, req }) => {
|
||||
const childrenText = await convertLexicalNodesToHTML({
|
||||
converters,
|
||||
lexicalNodes: node.children,
|
||||
parent: {
|
||||
...node,
|
||||
parent,
|
||||
},
|
||||
req,
|
||||
})
|
||||
return `<table class="lexical-table" style="border-collapse: collapse;">${childrenText}</table>`
|
||||
},
|
||||
nodeTypes: [TableNode.getType()],
|
||||
},
|
||||
},
|
||||
node: TableNode,
|
||||
},
|
||||
{
|
||||
}),
|
||||
createNode({
|
||||
converters: {
|
||||
html: {
|
||||
converter: async ({ converters, node, parent, req }) => {
|
||||
const childrenText = await convertLexicalNodesToHTML({
|
||||
converters,
|
||||
lexicalNodes: node.children,
|
||||
parent: {
|
||||
...node,
|
||||
parent,
|
||||
},
|
||||
req,
|
||||
})
|
||||
|
||||
const tagName = node.headerState > 0 ? 'th' : 'td'
|
||||
const headerStateClass = `lexical-table-cell-header-${node.headerState}`
|
||||
const backgroundColor = node.backgroundColor
|
||||
? `background-color: ${node.backgroundColor};`
|
||||
: ''
|
||||
const colSpan = node.colSpan > 1 ? `colspan="${node.colSpan}"` : ''
|
||||
const rowSpan = node.rowSpan > 1 ? `rowspan="${node.rowSpan}"` : ''
|
||||
|
||||
return `<${tagName} class="lexical-table-cell ${headerStateClass}" style="border: 1px solid #ccc; padding: 8px; ${backgroundColor}" ${colSpan} ${rowSpan}>${childrenText}</${tagName}>`
|
||||
},
|
||||
nodeTypes: [TableCellNode.getType()],
|
||||
},
|
||||
},
|
||||
node: TableCellNode,
|
||||
},
|
||||
{
|
||||
}),
|
||||
createNode({
|
||||
converters: {
|
||||
html: {
|
||||
converter: async ({ converters, node, parent, req }) => {
|
||||
const childrenText = await convertLexicalNodesToHTML({
|
||||
converters,
|
||||
lexicalNodes: node.children,
|
||||
parent: {
|
||||
...node,
|
||||
parent,
|
||||
},
|
||||
req,
|
||||
})
|
||||
return `<tr class="lexical-table-row">${childrenText}</tr>`
|
||||
},
|
||||
nodeTypes: [TableRowNode.getType()],
|
||||
},
|
||||
},
|
||||
node: TableRowNode,
|
||||
},
|
||||
}),
|
||||
],
|
||||
}
|
||||
},
|
||||
|
||||
@@ -9,9 +9,6 @@
|
||||
|
||||
.table-cell-action-button {
|
||||
background-color: var(--theme-elevation-200);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
border: 0;
|
||||
padding: 2px;
|
||||
position: relative;
|
||||
|
||||
@@ -160,15 +160,19 @@ function TableActionMenu({
|
||||
const { y } = useScrollInfo()
|
||||
|
||||
useEffect(() => {
|
||||
return editor.registerMutationListener(TableCellNode, (nodeMutations) => {
|
||||
const nodeUpdated = nodeMutations.get(tableCellNode.getKey()) === 'updated'
|
||||
return editor.registerMutationListener(
|
||||
TableCellNode,
|
||||
(nodeMutations) => {
|
||||
const nodeUpdated = nodeMutations.get(tableCellNode.getKey()) === 'updated'
|
||||
|
||||
if (nodeUpdated) {
|
||||
editor.getEditorState().read(() => {
|
||||
updateTableCellNode(tableCellNode.getLatest())
|
||||
})
|
||||
}
|
||||
})
|
||||
if (nodeUpdated) {
|
||||
editor.getEditorState().read(() => {
|
||||
updateTableCellNode(tableCellNode.getLatest())
|
||||
})
|
||||
}
|
||||
},
|
||||
{ skipInitialization: true },
|
||||
)
|
||||
}, [editor, tableCellNode])
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
.TableCellResizer__resizer {
|
||||
position: absolute;
|
||||
}
|
||||
@@ -20,9 +20,9 @@ import * as React from 'react'
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
|
||||
import { createPortal } from 'react-dom'
|
||||
|
||||
import type { PluginComponent, PluginComponentWithAnchor } from '../../../typesClient.js'
|
||||
import type { PluginComponent } from '../../../typesClient.js'
|
||||
|
||||
import './index.scss'
|
||||
import { useEditorConfigContext } from '../../../../lexical/config/client/EditorConfigProvider.js'
|
||||
|
||||
type MousePosition = {
|
||||
x: number
|
||||
@@ -38,6 +38,7 @@ function TableCellResizer({ editor }: { editor: LexicalEditor }): JSX.Element {
|
||||
const targetRef = useRef<HTMLElement | null>(null)
|
||||
const resizerRef = useRef<HTMLDivElement | null>(null)
|
||||
const tableRectRef = useRef<ClientRect | null>(null)
|
||||
const editorConfig = useEditorConfigContext()
|
||||
|
||||
const mouseStartPosRef = useRef<MousePosition | null>(null)
|
||||
const [mouseCurrentPos, updateMouseCurrentPos] = useState<MousePosition | null>(null)
|
||||
@@ -117,14 +118,18 @@ function TableCellResizer({ editor }: { editor: LexicalEditor }): JSX.Element {
|
||||
}, 0)
|
||||
}
|
||||
|
||||
document.addEventListener('mousemove', onMouseMove)
|
||||
document.addEventListener('mousedown', onMouseDown)
|
||||
document.addEventListener('mouseup', onMouseUp)
|
||||
const removeRootListener = editor.registerRootListener((rootElement, prevRootElement) => {
|
||||
rootElement?.addEventListener('mousemove', onMouseMove)
|
||||
rootElement?.addEventListener('mousedown', onMouseDown)
|
||||
rootElement?.addEventListener('mouseup', onMouseUp)
|
||||
|
||||
prevRootElement?.removeEventListener('mousemove', onMouseMove)
|
||||
prevRootElement?.removeEventListener('mousedown', onMouseDown)
|
||||
prevRootElement?.removeEventListener('mouseup', onMouseUp)
|
||||
})
|
||||
|
||||
return () => {
|
||||
document.removeEventListener('mousemove', onMouseMove)
|
||||
document.removeEventListener('mousedown', onMouseDown)
|
||||
document.removeEventListener('mouseup', onMouseUp)
|
||||
removeRootListener()
|
||||
}
|
||||
}, [activeCell, draggingDirection, editor, resetState])
|
||||
|
||||
@@ -378,12 +383,12 @@ function TableCellResizer({ editor }: { editor: LexicalEditor }): JSX.Element {
|
||||
{activeCell != null && !isMouseDown && (
|
||||
<React.Fragment>
|
||||
<div
|
||||
className="TableCellResizer__resizer TableCellResizer__ui"
|
||||
className={`${editorConfig.editorConfig.lexical.theme.tableCellResizer} TableCellResizer__ui`}
|
||||
onMouseDown={toggleResize('right')}
|
||||
style={resizerStyles.right || undefined}
|
||||
/>
|
||||
<div
|
||||
className="TableCellResizer__resizer TableCellResizer__ui"
|
||||
className={`${editorConfig.editorConfig.lexical.theme.tableCellResizer} TableCellResizer__ui`}
|
||||
onMouseDown={toggleResize('bottom')}
|
||||
style={resizerStyles.bottom || undefined}
|
||||
/>
|
||||
|
||||
@@ -0,0 +1,243 @@
|
||||
/**
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
*/
|
||||
|
||||
import type { TableCellNode, TableRowNode } from '@lexical/table'
|
||||
import type { EditorConfig, NodeKey } from 'lexical'
|
||||
import type { JSX } from 'react'
|
||||
|
||||
import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext'
|
||||
import {
|
||||
$getTableColumnIndexFromTableCellNode,
|
||||
$getTableRowIndexFromTableCellNode,
|
||||
$insertTableColumn__EXPERIMENTAL,
|
||||
$insertTableRow__EXPERIMENTAL,
|
||||
$isTableCellNode,
|
||||
$isTableNode,
|
||||
TableNode,
|
||||
} from '@lexical/table'
|
||||
import { $findMatchingParent, mergeRegister } from '@lexical/utils'
|
||||
import { $getNearestNodeFromDOMNode } from 'lexical'
|
||||
import { useEffect, useRef, useState } from 'react'
|
||||
import * as React from 'react'
|
||||
import { createPortal } from 'react-dom'
|
||||
|
||||
import { useEditorConfigContext } from '../../../../lexical/config/client/EditorConfigProvider.js'
|
||||
import { useDebounce } from '../../utils/useDebounce.js'
|
||||
|
||||
const BUTTON_WIDTH_PX = 20
|
||||
|
||||
function TableHoverActionsContainer({ anchorElem }: { anchorElem: HTMLElement }): JSX.Element {
|
||||
const [editor] = useLexicalComposerContext()
|
||||
const editorConfig = useEditorConfigContext()
|
||||
const [isShownRow, setShownRow] = useState<boolean>(false)
|
||||
const [isShownColumn, setShownColumn] = useState<boolean>(false)
|
||||
const [shouldListenMouseMove, setShouldListenMouseMove] = useState<boolean>(false)
|
||||
const [position, setPosition] = useState({})
|
||||
const codeSetRef = useRef<Set<NodeKey>>(new Set())
|
||||
const tableDOMNodeRef = useRef<HTMLElement | null>(null)
|
||||
|
||||
const debouncedOnMouseMove = useDebounce(
|
||||
(event: MouseEvent) => {
|
||||
const { isOutside, tableDOMNode } = getMouseInfo(event, editorConfig.editorConfig?.lexical)
|
||||
|
||||
if (isOutside) {
|
||||
setShownRow(false)
|
||||
setShownColumn(false)
|
||||
return
|
||||
}
|
||||
|
||||
if (!tableDOMNode) {
|
||||
return
|
||||
}
|
||||
|
||||
tableDOMNodeRef.current = tableDOMNode
|
||||
|
||||
let hoveredRowNode: TableCellNode | null = null
|
||||
let hoveredColumnNode: TableCellNode | null = null
|
||||
let tableDOMElement: HTMLElement | null = null
|
||||
|
||||
editor.update(() => {
|
||||
const maybeTableCell = $getNearestNodeFromDOMNode(tableDOMNode)
|
||||
|
||||
if ($isTableCellNode(maybeTableCell)) {
|
||||
const table = $findMatchingParent(maybeTableCell, (node) => $isTableNode(node))
|
||||
if (!$isTableNode(table)) {
|
||||
return
|
||||
}
|
||||
|
||||
tableDOMElement = editor.getElementByKey(table?.getKey())
|
||||
|
||||
if (tableDOMElement) {
|
||||
const rowCount = table.getChildrenSize()
|
||||
const colCount =
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
|
||||
((table as TableNode).getChildAtIndex(0) as TableRowNode)?.getChildrenSize()
|
||||
|
||||
const rowIndex = $getTableRowIndexFromTableCellNode(maybeTableCell)
|
||||
const colIndex = $getTableColumnIndexFromTableCellNode(maybeTableCell)
|
||||
|
||||
if (rowIndex === rowCount - 1) {
|
||||
hoveredRowNode = maybeTableCell
|
||||
} else if (colIndex === colCount - 1) {
|
||||
hoveredColumnNode = maybeTableCell
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
if (tableDOMElement) {
|
||||
const {
|
||||
bottom: tableElemBottom,
|
||||
height: tableElemHeight,
|
||||
right: tableElemRight,
|
||||
width: tableElemWidth,
|
||||
x: tableElemX,
|
||||
y: tableElemY,
|
||||
} = (tableDOMElement as HTMLTableElement).getBoundingClientRect()
|
||||
|
||||
const { left: editorElemLeft, y: editorElemY } = anchorElem.getBoundingClientRect()
|
||||
|
||||
if (hoveredRowNode) {
|
||||
setShownColumn(false)
|
||||
setShownRow(true)
|
||||
setPosition({
|
||||
height: BUTTON_WIDTH_PX,
|
||||
left: tableElemX - editorElemLeft,
|
||||
top: tableElemBottom - editorElemY + 5,
|
||||
width: tableElemWidth,
|
||||
})
|
||||
} else if (hoveredColumnNode) {
|
||||
setShownColumn(true)
|
||||
setShownRow(false)
|
||||
setPosition({
|
||||
height: tableElemHeight,
|
||||
left: tableElemRight - editorElemLeft + 5,
|
||||
top: tableElemY - editorElemY,
|
||||
width: BUTTON_WIDTH_PX,
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
50,
|
||||
250,
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
if (!shouldListenMouseMove) {
|
||||
return
|
||||
}
|
||||
|
||||
document.addEventListener('mousemove', debouncedOnMouseMove)
|
||||
|
||||
return () => {
|
||||
setShownRow(false)
|
||||
setShownColumn(false)
|
||||
|
||||
document.removeEventListener('mousemove', debouncedOnMouseMove)
|
||||
}
|
||||
}, [shouldListenMouseMove, debouncedOnMouseMove])
|
||||
|
||||
useEffect(() => {
|
||||
return mergeRegister(
|
||||
editor.registerMutationListener(
|
||||
TableNode,
|
||||
(mutations) => {
|
||||
editor.getEditorState().read(() => {
|
||||
for (const [key, type] of mutations) {
|
||||
switch (type) {
|
||||
case 'created':
|
||||
codeSetRef.current.add(key)
|
||||
setShouldListenMouseMove(codeSetRef.current.size > 0)
|
||||
break
|
||||
|
||||
case 'destroyed':
|
||||
codeSetRef.current.delete(key)
|
||||
setShouldListenMouseMove(codeSetRef.current.size > 0)
|
||||
break
|
||||
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
{ skipInitialization: false },
|
||||
),
|
||||
)
|
||||
}, [editor])
|
||||
|
||||
const insertAction = (insertRow: boolean) => {
|
||||
editor.update(() => {
|
||||
if (tableDOMNodeRef.current) {
|
||||
const maybeTableNode = $getNearestNodeFromDOMNode(tableDOMNodeRef.current)
|
||||
maybeTableNode?.selectEnd()
|
||||
if (insertRow) {
|
||||
$insertTableRow__EXPERIMENTAL()
|
||||
setShownRow(false)
|
||||
} else {
|
||||
$insertTableColumn__EXPERIMENTAL()
|
||||
setShownColumn(false)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{isShownRow && (
|
||||
<button
|
||||
className={editorConfig.editorConfig.lexical.theme.tableAddRows}
|
||||
onClick={() => insertAction(true)}
|
||||
style={{ ...position }}
|
||||
/>
|
||||
)}
|
||||
{isShownColumn && (
|
||||
<button
|
||||
className={editorConfig.editorConfig.lexical.theme.tableAddColumns}
|
||||
onClick={() => insertAction(false)}
|
||||
style={{ ...position }}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
function getMouseInfo(
|
||||
event: MouseEvent,
|
||||
editorConfig: EditorConfig,
|
||||
): {
|
||||
isOutside: boolean
|
||||
tableDOMNode: HTMLElement | null
|
||||
} {
|
||||
const target = event.target
|
||||
|
||||
if (target && target instanceof HTMLElement) {
|
||||
const tableDOMNode = target.closest<HTMLElement>(
|
||||
`td.${editorConfig.theme.tableCell}, th.${editorConfig.theme.tableCell}`,
|
||||
)
|
||||
|
||||
const isOutside = !(
|
||||
tableDOMNode ||
|
||||
target.closest<HTMLElement>(`button.${editorConfig.theme.tableAddRows}`) ||
|
||||
target.closest<HTMLElement>(`button.${editorConfig.theme.tableAddColumns}`) ||
|
||||
target.closest<HTMLElement>(`div.${editorConfig.theme.tableCellResizer}`)
|
||||
)
|
||||
|
||||
return { isOutside, tableDOMNode }
|
||||
} else {
|
||||
return { isOutside: true, tableDOMNode: null }
|
||||
}
|
||||
}
|
||||
|
||||
export function TableHoverActionsPlugin({
|
||||
anchorElem = document.body,
|
||||
}: {
|
||||
anchorElem?: HTMLElement
|
||||
}): React.ReactPortal | null {
|
||||
return createPortal(<TableHoverActionsContainer anchorElem={anchorElem} />, anchorElem)
|
||||
}
|
||||
@@ -4,11 +4,11 @@
|
||||
&__table {
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0;
|
||||
max-width: 100%;
|
||||
overflow-y: scroll;
|
||||
overflow-x: scroll;
|
||||
table-layout: fixed;
|
||||
width: calc(100% - 25px);
|
||||
margin: 30px 0;
|
||||
width: max-content;
|
||||
margin: 0 25px 30px 0;
|
||||
|
||||
::selection {
|
||||
background: rgba(172, 206, 247);
|
||||
@@ -81,35 +81,39 @@
|
||||
}
|
||||
|
||||
&__tableAddColumns {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
width: 20px;
|
||||
background-color: #eee;
|
||||
height: 100%;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
&__tableAddColumns, &__tableAddRows {
|
||||
position: absolute;
|
||||
background-color: var(--theme-elevation-100);
|
||||
animation: table-controls 0.2s ease;
|
||||
border: 0;
|
||||
cursor: pointer;
|
||||
min-width: 24px;
|
||||
min-height: 24px;
|
||||
}
|
||||
|
||||
&__tableAddColumns:hover {
|
||||
background-color: #c9dbf0;
|
||||
&__tableAddColumns:after, &__tableAddRows:after {
|
||||
background-image: url(../../../../lexical/ui/icons/Add/index.svg);
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
display: block;
|
||||
content: ' ';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
opacity: 0.4;
|
||||
}
|
||||
|
||||
&__tableAddColumns:hover, &__tableAddRows:hover {
|
||||
background-color: var(--theme-elevation-200);
|
||||
}
|
||||
|
||||
&__tableAddRows {
|
||||
position: absolute;
|
||||
bottom: -25px;
|
||||
width: calc(100% - 25px);
|
||||
background-color: #eee;
|
||||
height: 20px;
|
||||
left: 0;
|
||||
animation: table-controls 0.2s ease;
|
||||
border: 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
&__tableAddRows:hover {
|
||||
background-color: #c9dbf0;
|
||||
}
|
||||
|
||||
@keyframes table-controls {
|
||||
@@ -162,5 +166,9 @@ html[data-theme='dark'] {
|
||||
&__tableCellHeader {
|
||||
background-color: var(--theme-elevation-50);
|
||||
}
|
||||
|
||||
&__tableAddColumns:after, &__tableAddRows:after {
|
||||
background-image: url(../../../../lexical/ui/icons/Add/light.svg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,244 @@
|
||||
// Copied & modified from https://github.com/lodash/lodash/blob/main/src/debounce.ts
|
||||
/*
|
||||
The MIT License
|
||||
|
||||
Copyright JS Foundation and other contributors <https://js.foundation/>
|
||||
|
||||
Based on Underscore.js, copyright Jeremy Ashkenas,
|
||||
DocumentCloud and Investigative Reporters & Editors <http://underscorejs.org/>
|
||||
|
||||
This software consists of voluntary contributions made by many
|
||||
individuals. For exact contribution history, see the revision history
|
||||
available at https://github.com/lodash/lodash
|
||||
|
||||
The following license applies to all parts of this software except as
|
||||
documented below:
|
||||
|
||||
====
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
====
|
||||
|
||||
Copyright and related rights for sample code are waived via CC0. Sample
|
||||
code is defined as all source code displayed within the prose of the
|
||||
documentation.
|
||||
|
||||
CC0: http://creativecommons.org/publicdomain/zero/1.0/
|
||||
|
||||
====
|
||||
|
||||
Files located in the node_modules and vendor directories are externally
|
||||
maintained libraries used by this software which have their own
|
||||
licenses; we recommend you read them, as their terms may differ from the
|
||||
terms above.
|
||||
*/
|
||||
|
||||
/** Error message constants. */
|
||||
const FUNC_ERROR_TEXT = 'Expected a function'
|
||||
|
||||
/* Built-in method references for those with the same name as other `lodash` methods. */
|
||||
const nativeMax = Math.max,
|
||||
nativeMin = Math.min
|
||||
|
||||
/**
|
||||
* Creates a debounced function that delays invoking `func` until after `wait`
|
||||
* milliseconds have elapsed since the last time the debounced function was
|
||||
* invoked. The debounced function comes with a `cancel` method to cancel
|
||||
* delayed `func` invocations and a `flush` method to immediately invoke them.
|
||||
* Provide `options` to indicate whether `func` should be invoked on the
|
||||
* leading and/or trailing edge of the `wait` timeout. The `func` is invoked
|
||||
* with the last arguments provided to the debounced function. Subsequent
|
||||
* calls to the debounced function return the result of the last `func`
|
||||
* invocation.
|
||||
*
|
||||
* **Note:** If `leading` and `trailing` options are `true`, `func` is
|
||||
* invoked on the trailing edge of the timeout only if the debounced function
|
||||
* is invoked more than once during the `wait` timeout.
|
||||
*
|
||||
* If `wait` is `0` and `leading` is `false`, `func` invocation is deferred
|
||||
* until to the next tick, similar to `setTimeout` with a timeout of `0`.
|
||||
*
|
||||
* See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/)
|
||||
* for details over the differences between `_.debounce` and `_.throttle`.
|
||||
*
|
||||
* @static
|
||||
* @memberOf _
|
||||
* @since 0.1.0
|
||||
* @category Function
|
||||
* @param {Function} func The function to debounce.
|
||||
* @param {number} [wait=0] The number of milliseconds to delay.
|
||||
* @param {Object} [options={}] The options object.
|
||||
* @param {boolean} [options.leading=false]
|
||||
* Specify invoking on the leading edge of the timeout.
|
||||
* @param {number} [options.maxWait]
|
||||
* The maximum time `func` is allowed to be delayed before it's invoked.
|
||||
* @param {boolean} [options.trailing=true]
|
||||
* Specify invoking on the trailing edge of the timeout.
|
||||
* @returns {Function} Returns the new debounced function.
|
||||
* @example
|
||||
*
|
||||
* // Avoid costly calculations while the window size is in flux.
|
||||
* jQuery(window).on('resize', _.debounce(calculateLayout, 150));
|
||||
*
|
||||
* // Invoke `sendMail` when clicked, debouncing subsequent calls.
|
||||
* jQuery(element).on('click', _.debounce(sendMail, 300, {
|
||||
* 'leading': true,
|
||||
* 'trailing': false
|
||||
* }));
|
||||
*
|
||||
* // Ensure `batchLog` is invoked once after 1 second of debounced calls.
|
||||
* var debounced = _.debounce(batchLog, 250, { 'maxWait': 1000 });
|
||||
* var source = new EventSource('/stream');
|
||||
* jQuery(source).on('message', debounced);
|
||||
*
|
||||
* // Cancel the trailing debounced invocation.
|
||||
* jQuery(window).on('popstate', debounced.cancel);
|
||||
*/
|
||||
function debounce(func, wait, options) {
|
||||
let lastArgs,
|
||||
lastThis,
|
||||
maxWait,
|
||||
result,
|
||||
timerId,
|
||||
lastCallTime,
|
||||
lastInvokeTime = 0,
|
||||
leading = false,
|
||||
maxing = false,
|
||||
trailing = true
|
||||
|
||||
if (typeof func != 'function') {
|
||||
throw new TypeError(FUNC_ERROR_TEXT)
|
||||
}
|
||||
wait = wait || 0
|
||||
if (typeof options === 'object') {
|
||||
leading = !!options.leading
|
||||
maxing = 'maxWait' in options
|
||||
maxWait = maxing ? nativeMax(options.maxWait || 0, wait) : maxWait
|
||||
trailing = 'trailing' in options ? !!options.trailing : trailing
|
||||
}
|
||||
|
||||
function invokeFunc(time) {
|
||||
const args = lastArgs,
|
||||
thisArg = lastThis
|
||||
|
||||
lastArgs = lastThis = undefined
|
||||
lastInvokeTime = time
|
||||
result = func.apply(thisArg, args)
|
||||
return result
|
||||
}
|
||||
|
||||
function leadingEdge(time) {
|
||||
// Reset any `maxWait` timer.
|
||||
lastInvokeTime = time
|
||||
// Start the timer for the trailing edge.
|
||||
timerId = setTimeout(timerExpired, wait)
|
||||
// Invoke the leading edge.
|
||||
return leading ? invokeFunc(time) : result
|
||||
}
|
||||
|
||||
function remainingWait(time) {
|
||||
const timeSinceLastCall = time - lastCallTime,
|
||||
timeSinceLastInvoke = time - lastInvokeTime,
|
||||
timeWaiting = wait - timeSinceLastCall
|
||||
|
||||
return maxing ? nativeMin(timeWaiting, maxWait - timeSinceLastInvoke) : timeWaiting
|
||||
}
|
||||
|
||||
function shouldInvoke(time) {
|
||||
const timeSinceLastCall = time - lastCallTime,
|
||||
timeSinceLastInvoke = time - lastInvokeTime
|
||||
|
||||
// Either this is the first call, activity has stopped and we're at the
|
||||
// trailing edge, the system time has gone backwards and we're treating
|
||||
// it as the trailing edge, or we've hit the `maxWait` limit.
|
||||
return (
|
||||
lastCallTime === undefined ||
|
||||
timeSinceLastCall >= wait ||
|
||||
timeSinceLastCall < 0 ||
|
||||
(maxing && timeSinceLastInvoke >= maxWait)
|
||||
)
|
||||
}
|
||||
|
||||
function timerExpired() {
|
||||
const time = Date.now()
|
||||
if (shouldInvoke(time)) {
|
||||
return trailingEdge(time)
|
||||
}
|
||||
// Restart the timer.
|
||||
timerId = setTimeout(timerExpired, remainingWait(time))
|
||||
}
|
||||
|
||||
function trailingEdge(time) {
|
||||
timerId = undefined
|
||||
|
||||
// Only invoke if we have `lastArgs` which means `func` has been
|
||||
// debounced at least once.
|
||||
if (trailing && lastArgs) {
|
||||
return invokeFunc(time)
|
||||
}
|
||||
lastArgs = lastThis = undefined
|
||||
return result
|
||||
}
|
||||
|
||||
function cancel() {
|
||||
if (timerId !== undefined) {
|
||||
clearTimeout(timerId)
|
||||
}
|
||||
lastInvokeTime = 0
|
||||
lastArgs = lastCallTime = lastThis = timerId = undefined
|
||||
}
|
||||
|
||||
function flush() {
|
||||
return timerId === undefined ? result : trailingEdge(Date.now())
|
||||
}
|
||||
|
||||
function debounced() {
|
||||
const time = Date.now(),
|
||||
isInvoking = shouldInvoke(time)
|
||||
|
||||
// eslint-disable-next-line prefer-rest-params
|
||||
lastArgs = arguments
|
||||
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
||||
lastThis = this
|
||||
lastCallTime = time
|
||||
|
||||
if (isInvoking) {
|
||||
if (timerId === undefined) {
|
||||
return leadingEdge(lastCallTime)
|
||||
}
|
||||
if (maxing) {
|
||||
// Handle invocations in a tight loop.
|
||||
clearTimeout(timerId)
|
||||
timerId = setTimeout(timerExpired, wait)
|
||||
return invokeFunc(lastCallTime)
|
||||
}
|
||||
}
|
||||
if (timerId === undefined) {
|
||||
timerId = setTimeout(timerExpired, wait)
|
||||
}
|
||||
return result
|
||||
}
|
||||
debounced.cancel = cancel
|
||||
debounced.flush = flush
|
||||
return debounced
|
||||
}
|
||||
|
||||
export default debounce
|
||||
@@ -0,0 +1,26 @@
|
||||
import { useMemo, useRef } from 'react'
|
||||
|
||||
import debounce from './debounce.js'
|
||||
|
||||
export function useDebounce<T extends (...args: never[]) => void>(
|
||||
fn: T,
|
||||
ms: number,
|
||||
maxWait?: number,
|
||||
) {
|
||||
const funcRef = useRef<T | null>(null)
|
||||
funcRef.current = fn
|
||||
|
||||
return useMemo(
|
||||
() =>
|
||||
debounce(
|
||||
(...args: Parameters<T>) => {
|
||||
if (funcRef.current) {
|
||||
funcRef.current(...args)
|
||||
}
|
||||
},
|
||||
ms,
|
||||
{ maxWait },
|
||||
),
|
||||
[ms, maxWait],
|
||||
)
|
||||
}
|
||||
@@ -77,8 +77,19 @@ function startsWithSeparator(textContent: string): boolean {
|
||||
return isSeparator(textContent[0])
|
||||
}
|
||||
|
||||
function startsWithFullStop(textContent: string): boolean {
|
||||
return /^\.[a-z\d]+/i.test(textContent)
|
||||
/**
|
||||
* Check if the text content starts with a fullstop followed by a top-level domain.
|
||||
* Meaning if the text content can be a beginning of a top level domain.
|
||||
* @param textContent
|
||||
* @param isEmail
|
||||
* @returns boolean
|
||||
*/
|
||||
function startsWithTLD(textContent: string, isEmail: boolean): boolean {
|
||||
if (isEmail) {
|
||||
return /^\.[a-z]{2,}/i.test(textContent)
|
||||
} else {
|
||||
return /^\.[a-z0-9]+/i.test(textContent)
|
||||
}
|
||||
}
|
||||
|
||||
function isPreviousNodeValid(node: LexicalNode): boolean {
|
||||
@@ -343,13 +354,15 @@ function handleBadNeighbors(
|
||||
const nextSibling = textNode.getNextSibling()
|
||||
const text = textNode.getTextContent()
|
||||
|
||||
if (
|
||||
$isAutoLinkNode(previousSibling) &&
|
||||
(!startsWithSeparator(text) || startsWithFullStop(text))
|
||||
) {
|
||||
previousSibling.append(textNode)
|
||||
handleLinkEdit(previousSibling, matchers, onChange)
|
||||
onChange(null, previousSibling.getFields()?.url ?? null)
|
||||
if ($isAutoLinkNode(previousSibling)) {
|
||||
const isEmailURI = previousSibling.getFields()?.url
|
||||
? previousSibling.getFields()?.url?.startsWith('mailto:')
|
||||
: false
|
||||
if (!startsWithSeparator(text) || startsWithTLD(text, isEmailURI)) {
|
||||
previousSibling.append(textNode)
|
||||
handleLinkEdit(previousSibling, matchers, onChange)
|
||||
onChange(null, previousSibling.getFields()?.url ?? null)
|
||||
}
|
||||
}
|
||||
|
||||
if ($isAutoLinkNode(nextSibling) && !endsWithSeparator(text)) {
|
||||
|
||||
@@ -99,6 +99,7 @@ export function convertParagraphNode(
|
||||
format: '',
|
||||
indent: 0,
|
||||
textFormat: 0,
|
||||
textStyle: '',
|
||||
version: 1,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,7 +101,7 @@ html[data-theme='dark'] {
|
||||
}
|
||||
}
|
||||
|
||||
> .editor-placeholder {
|
||||
> .editor-scroller > .editor > div > .editor-placeholder {
|
||||
top: calc(var(--base) * 1.25);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import type {
|
||||
import type {
|
||||
Field,
|
||||
JsonObject,
|
||||
Payload,
|
||||
PayloadRequest,
|
||||
ReplaceAny,
|
||||
RequestContext,
|
||||
@@ -283,6 +284,7 @@ export type ServerFeature<ServerProps, ClientFeatureProps> = {
|
||||
generateComponentMap?: (args: {
|
||||
config: SanitizedConfig
|
||||
i18n: I18nClient
|
||||
payload: Payload
|
||||
props: ServerProps
|
||||
schemaPath: string
|
||||
}) => {
|
||||
|
||||
@@ -25,12 +25,12 @@
|
||||
}
|
||||
|
||||
&--show-gutter {
|
||||
> .rich-text-lexical__wrap > .editor-container > .editor-placeholder {
|
||||
> .rich-text-lexical__wrap > .editor-container > .editor-scroller > .editor > div > .editor-placeholder {
|
||||
left: 3rem;
|
||||
}
|
||||
}
|
||||
|
||||
&:not(&--show-gutter) > .rich-text-lexical__wrap > .editor-container > .editor-placeholder {
|
||||
&:not(&--show-gutter) > .rich-text-lexical__wrap > .editor-container > .editor-scroller > .editor > div > .editor-placeholder {
|
||||
left: 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,6 @@ import { HistoryPlugin } from '@lexical/react/LexicalHistoryPlugin.js'
|
||||
import { OnChangePlugin } from '@lexical/react/LexicalOnChangePlugin.js'
|
||||
import { RichTextPlugin } from '@lexical/react/LexicalRichTextPlugin.js'
|
||||
import { TabIndentationPlugin } from '@lexical/react/LexicalTabIndentationPlugin.js'
|
||||
import { useTranslation } from '@payloadcms/ui'
|
||||
import { BLUR_COMMAND, COMMAND_PRIORITY_LOW, FOCUS_COMMAND } from 'lexical'
|
||||
import * as React from 'react'
|
||||
import { useEffect, useState } from 'react'
|
||||
@@ -29,7 +28,6 @@ export const LexicalEditor: React.FC<
|
||||
const { editorConfig, editorContainerRef, onChange } = props
|
||||
const editorConfigContext = useEditorConfigContext()
|
||||
const [editor] = useLexicalComposerContext()
|
||||
const { t } = useTranslation<{}, string>()
|
||||
|
||||
const [floatingAnchorElem, setFloatingAnchorElem] = useState<HTMLDivElement | null>(null)
|
||||
const onRef = (_floatingAnchorElem: HTMLDivElement) => {
|
||||
@@ -122,7 +120,6 @@ export const LexicalEditor: React.FC<
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
placeholder={<p className="editor-placeholder">{t('lexical:general:placeholder')}</p>}
|
||||
/>
|
||||
<OnChangePlugin
|
||||
// Selection changes can be ignored here, reducing the
|
||||
|
||||
@@ -1,10 +1,19 @@
|
||||
import type { JSX } from 'react'
|
||||
|
||||
import { ContentEditable } from '@lexical/react/LexicalContentEditable.js'
|
||||
import { useTranslation } from '@payloadcms/ui'
|
||||
import * as React from 'react'
|
||||
|
||||
import './ContentEditable.scss'
|
||||
|
||||
export function LexicalContentEditable({ className }: { className?: string }): JSX.Element {
|
||||
return <ContentEditable className={className ?? 'ContentEditable__root'} />
|
||||
const { t } = useTranslation<{}, string>()
|
||||
|
||||
return (
|
||||
<ContentEditable
|
||||
aria-placeholder={t('lexical:general:placeholder')}
|
||||
className={className ?? 'ContentEditable__root'}
|
||||
placeholder={<p className="editor-placeholder">{t('lexical:general:placeholder')}</p>}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2,7 +2,14 @@ import React from 'react'
|
||||
|
||||
export const TableIcon: React.FC = () => {
|
||||
return (
|
||||
<svg fill="none" height="20" viewBox="0 0 20 20" width="20" xmlns="http://www.w3.org/2000/svg">
|
||||
<svg
|
||||
className="icon"
|
||||
fill="none"
|
||||
height="20"
|
||||
viewBox="0 0 20 20"
|
||||
width="20"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
clipRule="evenodd"
|
||||
d="M5.33333 4.5C4.8731 4.5 4.5 4.8731 4.5 5.33333V7.5H9.5V4.5H5.33333ZM5.33333 3.5C4.32081 3.5 3.5 4.32081 3.5 5.33333V14.6667C3.5 15.6792 4.32081 16.5 5.33333 16.5H14.6667C15.6792 16.5 16.5 15.6792 16.5 14.6667V5.33333C16.5 4.32081 15.6792 3.5 14.6667 3.5H5.33333ZM10.5 4.5V7.5H15.5V5.33333C15.5 4.8731 15.1269 4.5 14.6667 4.5H10.5ZM15.5 8.5H10.5V11.5H15.5V8.5ZM15.5 12.5H10.5V15.5H14.6667C15.1269 15.5 15.5 15.1269 15.5 14.6667V12.5ZM9.5 15.5V12.5H4.5V14.6667C4.5 15.1269 4.8731 15.5 5.33333 15.5H9.5ZM4.5 11.5H9.5V8.5H4.5V11.5Z"
|
||||
|
||||
@@ -19,7 +19,7 @@ export const UploadIcon: React.FC = () => (
|
||||
/>
|
||||
<path
|
||||
d="M7.99984 9.33366C8.73622 9.33366 9.33317 8.73671 9.33317 8.00033C9.33317 7.26395 8.73622 6.66699 7.99984 6.66699C7.26346 6.66699 6.6665 7.26395 6.6665 8.00033C6.6665 8.73671 7.26346 9.33366 7.99984 9.33366Z"
|
||||
stroke="#currentColor"
|
||||
stroke="currentColor"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
|
||||
@@ -21,6 +21,7 @@ export const defaultRichTextValue: SerializedEditorState = {
|
||||
format: '',
|
||||
indent: 0,
|
||||
textFormat: 0,
|
||||
textStyle: '',
|
||||
version: 1,
|
||||
} as SerializedParagraphNode,
|
||||
],
|
||||
|
||||
@@ -10,7 +10,7 @@ export const getGenerateComponentMap =
|
||||
(args: {
|
||||
resolvedFeatureMap: ResolvedServerFeatureMap
|
||||
}): RichTextAdapter['generateComponentMap'] =>
|
||||
({ WithServerSideProps, config, i18n, schemaPath }) => {
|
||||
({ WithServerSideProps, config, i18n, payload, schemaPath }) => {
|
||||
const componentMap = new Map()
|
||||
|
||||
// turn args.resolvedFeatureMap into an array of [key, value] pairs, ordered by value.order, lowest order first:
|
||||
@@ -35,6 +35,7 @@ export const getGenerateComponentMap =
|
||||
const components = resolvedFeature.generateComponentMap({
|
||||
config,
|
||||
i18n,
|
||||
payload,
|
||||
props: resolvedFeature.sanitizedServerFeatureProps,
|
||||
schemaPath,
|
||||
})
|
||||
@@ -80,6 +81,7 @@ export const getGenerateComponentMap =
|
||||
fieldSchema: fields,
|
||||
i18n,
|
||||
parentPath: `${schemaPath}.lexical_internal_feature.${featureKey}.fields.${schemaKey}`,
|
||||
payload,
|
||||
readOnly: false,
|
||||
})
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/richtext-slate",
|
||||
"version": "3.0.0-beta.73",
|
||||
"version": "3.0.0-beta.74",
|
||||
"description": "The officially supported Slate richtext adapter for Payload",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
|
||||
@@ -58,7 +58,7 @@ const RichTextField: React.FC<
|
||||
richTextComponentMap: Map<string, React.ReactNode>
|
||||
validate?: RichTextFieldValidation
|
||||
width?: string
|
||||
} & FormFieldBase
|
||||
} & Omit<FormFieldBase, 'validate'>
|
||||
> = (props) => {
|
||||
const {
|
||||
name,
|
||||
|
||||
@@ -12,7 +12,7 @@ import { defaultLeaves as leafTypes } from './field/leaves/index.js'
|
||||
|
||||
export const getGenerateComponentMap =
|
||||
(args: AdapterArguments): RichTextAdapter['generateComponentMap'] =>
|
||||
({ WithServerSideProps, config, i18n }) => {
|
||||
({ WithServerSideProps, config, i18n, payload }) => {
|
||||
const componentMap = new Map()
|
||||
|
||||
;(args?.admin?.leaves || Object.values(leafTypes)).forEach((leaf) => {
|
||||
@@ -67,6 +67,7 @@ export const getGenerateComponentMap =
|
||||
config,
|
||||
fieldSchema: args.admin?.link?.fields as Field[],
|
||||
i18n,
|
||||
payload,
|
||||
readOnly: false,
|
||||
})
|
||||
|
||||
@@ -93,6 +94,7 @@ export const getGenerateComponentMap =
|
||||
config,
|
||||
fieldSchema: args?.admin?.upload?.collections[collection.slug]?.fields,
|
||||
i18n,
|
||||
payload,
|
||||
readOnly: false,
|
||||
})
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/storage-azure",
|
||||
"version": "3.0.0-beta.73",
|
||||
"version": "3.0.0-beta.74",
|
||||
"description": "Payload storage adapter for Azure Blob Storage",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/storage-gcs",
|
||||
"version": "3.0.0-beta.73",
|
||||
"version": "3.0.0-beta.74",
|
||||
"description": "Payload storage adapter for Google Cloud Storage",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/storage-s3",
|
||||
"version": "3.0.0-beta.73",
|
||||
"version": "3.0.0-beta.74",
|
||||
"description": "Payload storage adapter for Amazon S3",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/storage-uploadthing",
|
||||
"version": "3.0.0-beta.73",
|
||||
"version": "3.0.0-beta.74",
|
||||
"description": "Payload storage adapter for uploadthing",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/storage-vercel-blob",
|
||||
"version": "3.0.0-beta.73",
|
||||
"version": "3.0.0-beta.74",
|
||||
"description": "Payload storage adapter for Vercel Blob Storage",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/translations",
|
||||
"version": "3.0.0-beta.73",
|
||||
"version": "3.0.0-beta.74",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/ui",
|
||||
"version": "3.0.0-beta.73",
|
||||
"version": "3.0.0-beta.74",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
}
|
||||
|
||||
&--is-multi {
|
||||
width: calc(100% + base(0.5));
|
||||
width: calc(100% + base(0.25));
|
||||
|
||||
&.rs__value-container--has-value {
|
||||
padding: 0;
|
||||
|
||||
@@ -10,6 +10,12 @@
|
||||
}
|
||||
}
|
||||
|
||||
.has-many {
|
||||
.rs__input-container {
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
html[data-theme='light'] {
|
||||
.field-type.text {
|
||||
&.error {
|
||||
|
||||
@@ -2,6 +2,7 @@ import type { I18nClient } from '@payloadcms/translations'
|
||||
import type {
|
||||
AdminViewProps,
|
||||
EditViewProps,
|
||||
Payload,
|
||||
SanitizedCollectionConfig,
|
||||
SanitizedConfig,
|
||||
} from 'payload'
|
||||
@@ -26,6 +27,7 @@ export const mapCollections = (args: {
|
||||
collections: SanitizedCollectionConfig[]
|
||||
config: SanitizedConfig
|
||||
i18n: I18nClient
|
||||
payload: Payload
|
||||
readOnly?: boolean
|
||||
}): {
|
||||
[key: SanitizedCollectionConfig['slug']]: CollectionComponentMap
|
||||
@@ -38,6 +40,7 @@ export const mapCollections = (args: {
|
||||
config,
|
||||
i18n,
|
||||
i18n: { t },
|
||||
payload,
|
||||
readOnly: readOnlyOverride,
|
||||
} = args
|
||||
|
||||
@@ -189,6 +192,7 @@ export const mapCollections = (args: {
|
||||
config,
|
||||
fieldSchema: fields,
|
||||
i18n,
|
||||
payload,
|
||||
readOnly: readOnlyOverride,
|
||||
}),
|
||||
isPreviewEnabled: !!collectionConfig?.admin?.preview,
|
||||
|
||||
@@ -22,6 +22,7 @@ import type {
|
||||
MappedTab,
|
||||
NumberFieldProps,
|
||||
Option,
|
||||
Payload,
|
||||
PointFieldProps,
|
||||
RadioFieldProps,
|
||||
ReducedBlock,
|
||||
@@ -67,6 +68,7 @@ export const mapFields = (args: {
|
||||
filter?: (field: Field) => boolean
|
||||
i18n: I18nClient
|
||||
parentPath?: string
|
||||
payload: Payload
|
||||
readOnly?: boolean
|
||||
}): FieldMap => {
|
||||
const {
|
||||
@@ -78,6 +80,7 @@ export const mapFields = (args: {
|
||||
i18n,
|
||||
i18n: { t },
|
||||
parentPath,
|
||||
payload,
|
||||
readOnly: readOnlyOverride,
|
||||
} = args
|
||||
|
||||
@@ -193,6 +196,7 @@ export const mapFields = (args: {
|
||||
filter,
|
||||
i18n,
|
||||
parentPath: path,
|
||||
payload,
|
||||
readOnly: readOnlyOverride,
|
||||
}),
|
||||
isSortable: field.admin?.isSortable,
|
||||
@@ -217,6 +221,7 @@ export const mapFields = (args: {
|
||||
filter,
|
||||
i18n,
|
||||
parentPath: `${path}.${block.slug}`,
|
||||
payload,
|
||||
readOnly: readOnlyOverride,
|
||||
})
|
||||
|
||||
@@ -303,6 +308,7 @@ export const mapFields = (args: {
|
||||
filter,
|
||||
i18n,
|
||||
parentPath: path,
|
||||
payload,
|
||||
readOnly: readOnlyOverride,
|
||||
}),
|
||||
initCollapsed: field.admin?.initCollapsed,
|
||||
@@ -364,6 +370,7 @@ export const mapFields = (args: {
|
||||
filter,
|
||||
i18n,
|
||||
parentPath: path,
|
||||
payload,
|
||||
readOnly: readOnlyOverride,
|
||||
}),
|
||||
hideGutter: field.admin?.hideGutter,
|
||||
@@ -494,6 +501,7 @@ export const mapFields = (args: {
|
||||
WithServerSideProps,
|
||||
config,
|
||||
i18n,
|
||||
payload,
|
||||
schemaPath: path,
|
||||
})
|
||||
|
||||
@@ -526,6 +534,7 @@ export const mapFields = (args: {
|
||||
filter,
|
||||
i18n,
|
||||
parentPath: path,
|
||||
payload,
|
||||
readOnly: readOnlyOverride,
|
||||
}),
|
||||
readOnly: field.admin?.readOnly,
|
||||
@@ -548,6 +557,7 @@ export const mapFields = (args: {
|
||||
filter,
|
||||
i18n,
|
||||
parentPath: path,
|
||||
payload,
|
||||
readOnly: readOnlyOverride,
|
||||
})
|
||||
|
||||
@@ -835,7 +845,7 @@ export const mapFields = (args: {
|
||||
// TODO: For all fields (not just this one) we need to add the name to both .fieldComponentPropsBase.name AND .name. This can probably be improved
|
||||
result.push({
|
||||
name: 'id',
|
||||
type: 'text',
|
||||
type: payload.db.defaultIDType === 'number' ? 'number' : 'text',
|
||||
CustomField: null,
|
||||
cellComponentProps: {
|
||||
name: 'id',
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { I18nClient } from '@payloadcms/translations'
|
||||
import type { EditViewProps, SanitizedConfig, SanitizedGlobalConfig } from 'payload'
|
||||
import type { EditViewProps, Payload, SanitizedConfig, SanitizedGlobalConfig } from 'payload'
|
||||
|
||||
import { isReactComponentOrFunction } from 'payload/shared'
|
||||
import React from 'react'
|
||||
@@ -23,6 +23,7 @@ export const mapGlobals = ({
|
||||
config: SanitizedConfig
|
||||
globals: SanitizedGlobalConfig[]
|
||||
i18n: I18nClient
|
||||
payload: Payload
|
||||
readOnly?: boolean
|
||||
}
|
||||
}): {
|
||||
@@ -35,6 +36,7 @@ export const mapGlobals = ({
|
||||
globals,
|
||||
i18n,
|
||||
i18n: { t },
|
||||
payload,
|
||||
readOnly: readOnlyOverride,
|
||||
} = args
|
||||
|
||||
@@ -122,6 +124,7 @@ export const mapGlobals = ({
|
||||
config,
|
||||
fieldSchema: fields,
|
||||
i18n,
|
||||
payload,
|
||||
readOnly: readOnlyOverride,
|
||||
}),
|
||||
isPreviewEnabled: !!globalConfig?.admin?.preview,
|
||||
|
||||
@@ -52,6 +52,7 @@ export const buildComponentMap = (args: {
|
||||
collections: config.collections,
|
||||
config,
|
||||
i18n,
|
||||
payload,
|
||||
readOnly,
|
||||
})
|
||||
|
||||
@@ -62,6 +63,7 @@ export const buildComponentMap = (args: {
|
||||
config,
|
||||
globals: config.globals,
|
||||
i18n,
|
||||
payload,
|
||||
readOnly,
|
||||
},
|
||||
})
|
||||
|
||||
304
pnpm-lock.yaml
generated
304
pnpm-lock.yaml
generated
@@ -1177,35 +1177,35 @@ importers:
|
||||
specifier: 2.0.0-beta.0
|
||||
version: 2.0.0-beta.0(react-dom@19.0.0-rc-fb9a90fa48-20240614)(react@19.0.0-rc-fb9a90fa48-20240614)
|
||||
'@lexical/headless':
|
||||
specifier: 0.16.1
|
||||
version: 0.16.1
|
||||
specifier: 0.17.0
|
||||
version: 0.17.0
|
||||
'@lexical/link':
|
||||
specifier: 0.16.1
|
||||
version: 0.16.1
|
||||
specifier: 0.17.0
|
||||
version: 0.17.0
|
||||
'@lexical/list':
|
||||
specifier: 0.16.1
|
||||
version: 0.16.1
|
||||
specifier: 0.17.0
|
||||
version: 0.17.0
|
||||
'@lexical/mark':
|
||||
specifier: 0.16.1
|
||||
version: 0.16.1
|
||||
specifier: 0.17.0
|
||||
version: 0.17.0
|
||||
'@lexical/markdown':
|
||||
specifier: 0.16.1
|
||||
version: 0.16.1
|
||||
specifier: 0.17.0
|
||||
version: 0.17.0
|
||||
'@lexical/react':
|
||||
specifier: 0.16.1
|
||||
version: 0.16.1(react-dom@19.0.0-rc-fb9a90fa48-20240614)(react@19.0.0-rc-fb9a90fa48-20240614)(yjs@13.6.18)
|
||||
specifier: 0.17.0
|
||||
version: 0.17.0(react-dom@19.0.0-rc-fb9a90fa48-20240614)(react@19.0.0-rc-fb9a90fa48-20240614)(yjs@13.6.18)
|
||||
'@lexical/rich-text':
|
||||
specifier: 0.16.1
|
||||
version: 0.16.1
|
||||
specifier: 0.17.0
|
||||
version: 0.17.0
|
||||
'@lexical/selection':
|
||||
specifier: 0.16.1
|
||||
version: 0.16.1
|
||||
specifier: 0.17.0
|
||||
version: 0.17.0
|
||||
'@lexical/table':
|
||||
specifier: 0.16.1
|
||||
version: 0.16.1
|
||||
specifier: 0.17.0
|
||||
version: 0.17.0
|
||||
'@lexical/utils':
|
||||
specifier: 0.16.1
|
||||
version: 0.16.1
|
||||
specifier: 0.17.0
|
||||
version: 0.17.0
|
||||
'@types/uuid':
|
||||
specifier: 10.0.0
|
||||
version: 10.0.0
|
||||
@@ -1216,8 +1216,8 @@ importers:
|
||||
specifier: 2.0.3
|
||||
version: 2.0.3
|
||||
lexical:
|
||||
specifier: 0.16.1
|
||||
version: 0.16.1
|
||||
specifier: 0.17.0
|
||||
version: 0.17.0
|
||||
react:
|
||||
specifier: ^19.0.0-rc-6230622a1a-20240610
|
||||
version: 19.0.0-rc-fb9a90fa48-20240614
|
||||
@@ -1232,8 +1232,8 @@ importers:
|
||||
version: 10.0.0
|
||||
devDependencies:
|
||||
'@lexical/eslint-plugin':
|
||||
specifier: ' 0.16.1'
|
||||
version: 0.16.1(eslint@9.6.0)
|
||||
specifier: 0.17.0
|
||||
version: 0.17.0(eslint@9.6.0)
|
||||
'@payloadcms/eslint-config':
|
||||
specifier: workspace:*
|
||||
version: link:../eslint-config
|
||||
@@ -1555,11 +1555,11 @@ importers:
|
||||
specifier: ^3.525.0
|
||||
version: 3.614.0
|
||||
'@lexical/headless':
|
||||
specifier: 0.16.1
|
||||
version: 0.16.1
|
||||
specifier: 0.17.0
|
||||
version: 0.17.0
|
||||
'@lexical/markdown':
|
||||
specifier: 0.16.1
|
||||
version: 0.16.1
|
||||
specifier: 0.17.0
|
||||
version: 0.17.0
|
||||
'@payloadcms/db-mongodb':
|
||||
specifier: workspace:*
|
||||
version: link:../packages/db-mongodb
|
||||
@@ -1690,8 +1690,8 @@ importers:
|
||||
specifier: 4.0.0
|
||||
version: 4.0.0
|
||||
lexical:
|
||||
specifier: 0.16.1
|
||||
version: 0.16.1
|
||||
specifier: 0.17.0
|
||||
version: 0.17.0
|
||||
payload:
|
||||
specifier: workspace:*
|
||||
version: link:../packages/payload
|
||||
@@ -5693,154 +5693,154 @@ packages:
|
||||
resolution: {integrity: sha512-dfLbk+PwWvFzSxwk3n5ySL0hfBog779o8h68wK/7/APo/7cgyWp5jcXockbxdk5kFRkbeXWm4Fbi9FrdN381sA==}
|
||||
dev: false
|
||||
|
||||
/@lexical/clipboard@0.16.1:
|
||||
resolution: {integrity: sha512-0dWs/SwKS5KPpuf6fUVVt9vSCl6HAqcDGhSITw/okv0rrIlXTUT6WhVsMJtXfFxTyVvwMeOecJHvQH3i/jRQtA==}
|
||||
/@lexical/clipboard@0.17.0:
|
||||
resolution: {integrity: sha512-wYtC6VJhuSxUZc69VTU+vBgzB4HQqhve2hLrr3v+3tR2aimx3KnKphCCP1TexCntxpEnOTPXafEgpOW/EVQE+Q==}
|
||||
dependencies:
|
||||
'@lexical/html': 0.16.1
|
||||
'@lexical/list': 0.16.1
|
||||
'@lexical/selection': 0.16.1
|
||||
'@lexical/utils': 0.16.1
|
||||
lexical: 0.16.1
|
||||
'@lexical/html': 0.17.0
|
||||
'@lexical/list': 0.17.0
|
||||
'@lexical/selection': 0.17.0
|
||||
'@lexical/utils': 0.17.0
|
||||
lexical: 0.17.0
|
||||
|
||||
/@lexical/code@0.16.1:
|
||||
resolution: {integrity: sha512-pOC28rRZ2XkmI2nIJm50DbKaCJtk5D0o7r6nORYp4i0z+lxt5Sf2m82DL9ksUHJRqKy87pwJDpoWvJ2SAI0ohw==}
|
||||
/@lexical/code@0.17.0:
|
||||
resolution: {integrity: sha512-8zrgHzf27aYySfUVeSKw8YP/LkRlXHSwD03BKlkSZAb4HX/WC60SGmdXUhtyTIBucqe0pnuGsRYfR9euD0/tfw==}
|
||||
dependencies:
|
||||
'@lexical/utils': 0.16.1
|
||||
lexical: 0.16.1
|
||||
'@lexical/utils': 0.17.0
|
||||
lexical: 0.17.0
|
||||
prismjs: 1.29.0
|
||||
|
||||
/@lexical/devtools-core@0.16.1(react-dom@19.0.0-rc-fb9a90fa48-20240614)(react@19.0.0-rc-fb9a90fa48-20240614):
|
||||
resolution: {integrity: sha512-8CvGERGL7ySDVGLU+YPeq+JupIXsOFlXa3EuJ88koLKqXxYenwMleZgGqayFp6lCP78xqPKnATVeoOZUt/NabQ==}
|
||||
/@lexical/devtools-core@0.17.0(react-dom@19.0.0-rc-fb9a90fa48-20240614)(react@19.0.0-rc-fb9a90fa48-20240614):
|
||||
resolution: {integrity: sha512-0ftqWsoCb96oTc8Ok+uvjGAXZpsN9oc6ml3d46BdufdZyxHXC4qU3YVoPfLkgAHzH+4fQlNypu7u3Ym3dZ2rJg==}
|
||||
peerDependencies:
|
||||
react: ^19.0.0-rc-6230622a1a-20240610
|
||||
react-dom: ^19.0.0-rc-6230622a1a-20240610
|
||||
dependencies:
|
||||
'@lexical/html': 0.16.1
|
||||
'@lexical/link': 0.16.1
|
||||
'@lexical/mark': 0.16.1
|
||||
'@lexical/table': 0.16.1
|
||||
'@lexical/utils': 0.16.1
|
||||
lexical: 0.16.1
|
||||
'@lexical/html': 0.17.0
|
||||
'@lexical/link': 0.17.0
|
||||
'@lexical/mark': 0.17.0
|
||||
'@lexical/table': 0.17.0
|
||||
'@lexical/utils': 0.17.0
|
||||
lexical: 0.17.0
|
||||
react: 19.0.0-rc-fb9a90fa48-20240614
|
||||
react-dom: 19.0.0-rc-fb9a90fa48-20240614(react@19.0.0-rc-fb9a90fa48-20240614)
|
||||
dev: false
|
||||
|
||||
/@lexical/dragon@0.16.1:
|
||||
resolution: {integrity: sha512-Rvd60GIYN5kpjjBumS34EnNbBaNsoseI0AlzOdtIV302jiHPCLH0noe9kxzu9nZy+MZmjZy8Dx2zTbQT2mueRw==}
|
||||
/@lexical/dragon@0.17.0:
|
||||
resolution: {integrity: sha512-XSsrHVwhjBIVF9VN9MFm6Go8fquj5H/jlYuyNzemHq0tOli8NaoSovGc5q0LwXr88RPsuIt1jluazR7Q1+kxTQ==}
|
||||
dependencies:
|
||||
lexical: 0.16.1
|
||||
lexical: 0.17.0
|
||||
dev: false
|
||||
|
||||
/@lexical/eslint-plugin@0.16.1(eslint@9.6.0):
|
||||
resolution: {integrity: sha512-C68eSFBAJ5H8vDae46l9iPUYYw6btC4ZAOr2vMdri8tuN4Aid5c2skDv/Ruiyk12SWsgzz9jHiyo5Fsa1ESLdg==}
|
||||
/@lexical/eslint-plugin@0.17.0(eslint@9.6.0):
|
||||
resolution: {integrity: sha512-O6RyQBXAdi90jlthWwfOuxYG4zqzWkpNwsX1V6N8t5iH80Te04LsnfG+hIB/5V8rxm8WPkTjMrqAX3UEZy5Shg==}
|
||||
peerDependencies:
|
||||
eslint: '>=7.31.0 || ^8.0.0'
|
||||
dependencies:
|
||||
eslint: 9.6.0
|
||||
dev: true
|
||||
|
||||
/@lexical/hashtag@0.16.1:
|
||||
resolution: {integrity: sha512-G+YOxStAKs3q1utqm9KR4D4lCkwIH52Rctm4RgaVTI+4lvTaybeDRGFV75P/pI/qlF7/FvAYHTYEzCjtC3GNMQ==}
|
||||
/@lexical/hashtag@0.17.0:
|
||||
resolution: {integrity: sha512-E6nSoz9haB6JypQtYxG5OYr36AHgam/FBMu77OWNl1KsJbkP8nInm+P22QFsNnEvs4Hk6/0FJ5g42+lTEnGmIg==}
|
||||
dependencies:
|
||||
'@lexical/utils': 0.16.1
|
||||
lexical: 0.16.1
|
||||
'@lexical/utils': 0.17.0
|
||||
lexical: 0.17.0
|
||||
dev: false
|
||||
|
||||
/@lexical/headless@0.16.1:
|
||||
resolution: {integrity: sha512-L00TQk9vD1o7c25QMNdwD7MvkmQYP/jebG2M8GbX/3KSjHag2QB8MwcFlccSGXBhmbVm1X1Zo7z7urxY//3atw==}
|
||||
/@lexical/headless@0.17.0:
|
||||
resolution: {integrity: sha512-yKvXcq2F6S1lwDLcwv+bHht/al1LcFmidPT3rjISRxLX+/YjUcUT8MmvV773Du4piV4rFPbVlBPFBZfHJkDxXw==}
|
||||
dependencies:
|
||||
lexical: 0.16.1
|
||||
lexical: 0.17.0
|
||||
|
||||
/@lexical/history@0.16.1:
|
||||
resolution: {integrity: sha512-WQhScx0TJeKSQAnEkRpIaWdUXqirrNrom2MxbBUc/32zEUMm9FzV7nRGknvUabEFUo7vZq6xTZpOExQJqHInQA==}
|
||||
/@lexical/history@0.17.0:
|
||||
resolution: {integrity: sha512-SfeUKAXf9pZpqee9rMOTt33V0J0p/AS9TZLT9Un9dU6wAaHfv6NFax1ND0JoG1a9YkTc539mufxVLNjsNRc0ag==}
|
||||
dependencies:
|
||||
'@lexical/utils': 0.16.1
|
||||
lexical: 0.16.1
|
||||
'@lexical/utils': 0.17.0
|
||||
lexical: 0.17.0
|
||||
dev: false
|
||||
|
||||
/@lexical/html@0.16.1:
|
||||
resolution: {integrity: sha512-vbtAdCvQ3PaAqa5mFmtmrvbiAvjCu1iXBAJ0bsHqFXCF2Sba5LwHVe8dUAOTpfEZEMbiHfjul6b5fj4vNPGF2A==}
|
||||
/@lexical/html@0.17.0:
|
||||
resolution: {integrity: sha512-sI458CEP/j+Gd2YEo1+vTax31ZAjdq5jmRJMgSKxzKlkVYAUY9eH5u3Y3awPLwLVXJHiIopMX02GeZytibuTiw==}
|
||||
dependencies:
|
||||
'@lexical/selection': 0.16.1
|
||||
'@lexical/utils': 0.16.1
|
||||
lexical: 0.16.1
|
||||
'@lexical/selection': 0.17.0
|
||||
'@lexical/utils': 0.17.0
|
||||
lexical: 0.17.0
|
||||
|
||||
/@lexical/link@0.16.1:
|
||||
resolution: {integrity: sha512-zG36gEnEqbIe6tK/MhXi7wn/XMY/zdivnPcOY5WyC3derkEezeLSSIFsC1u5UNeK5pbpNMSy4LDpLhi1Ww4Y5w==}
|
||||
/@lexical/link@0.17.0:
|
||||
resolution: {integrity: sha512-Kux6yvPit6y0ksPpwimv3seVrXAsggkqB6oT6oAVBaDpYuygVEwNDqg/rCTtB3mHQ4eeuU33mdK7MSXZ34bZRQ==}
|
||||
dependencies:
|
||||
'@lexical/utils': 0.16.1
|
||||
lexical: 0.16.1
|
||||
'@lexical/utils': 0.17.0
|
||||
lexical: 0.17.0
|
||||
|
||||
/@lexical/list@0.16.1:
|
||||
resolution: {integrity: sha512-i9YhLAh5N6YO9dP+R1SIL9WEdCKeTiQQYVUzj84vDvX5DIBxMPUjTmMn3LXu9T+QO3h1s2L/vJusZASrl45eAw==}
|
||||
/@lexical/list@0.17.0:
|
||||
resolution: {integrity: sha512-anDuSUykTv+lqyCwl1m+sThrB15OKCa00Eo68/d2HQSHDD3KNWgSx709dcR17bD9oT204yOhMJbQGywuzcEyGQ==}
|
||||
dependencies:
|
||||
'@lexical/utils': 0.16.1
|
||||
lexical: 0.16.1
|
||||
'@lexical/utils': 0.17.0
|
||||
lexical: 0.17.0
|
||||
|
||||
/@lexical/mark@0.16.1:
|
||||
resolution: {integrity: sha512-CZRGMLcxn5D+jzf1XnH+Z+uUugmpg1mBwTbGybCPm8UWpBrKDHkrscfMgWz62iRWz0cdVjM5+0zWpNElxFTRjQ==}
|
||||
/@lexical/mark@0.17.0:
|
||||
resolution: {integrity: sha512-Ynqh9KHXUcB9qLOTGC9s+bbWtawOwRStkeIeAugTqrwckyYWeDaePpyJ6IhBBJy1E1CfpiZn71NDeP+FuRjnXQ==}
|
||||
dependencies:
|
||||
'@lexical/utils': 0.16.1
|
||||
lexical: 0.16.1
|
||||
'@lexical/utils': 0.17.0
|
||||
lexical: 0.17.0
|
||||
dev: false
|
||||
|
||||
/@lexical/markdown@0.16.1:
|
||||
resolution: {integrity: sha512-0sBLttMvfQO/hVaIqpHdvDowpgV2CoRuWo2CNwvRLZPPWvPVjL4Nkb73wmi8zAZsAOTbX2aw+g4m/+k5oJqNig==}
|
||||
/@lexical/markdown@0.17.0:
|
||||
resolution: {integrity: sha512-6IuJ2l5p/Ma+VBUIStIRXwTC01GEzx21gvqqywuqBUzAOiMr1oRM+DGsQgrzZrcjX+LzUlZ5ZgjuWtK8XKVAZw==}
|
||||
dependencies:
|
||||
'@lexical/code': 0.16.1
|
||||
'@lexical/link': 0.16.1
|
||||
'@lexical/list': 0.16.1
|
||||
'@lexical/rich-text': 0.16.1
|
||||
'@lexical/text': 0.16.1
|
||||
'@lexical/utils': 0.16.1
|
||||
lexical: 0.16.1
|
||||
'@lexical/code': 0.17.0
|
||||
'@lexical/link': 0.17.0
|
||||
'@lexical/list': 0.17.0
|
||||
'@lexical/rich-text': 0.17.0
|
||||
'@lexical/text': 0.17.0
|
||||
'@lexical/utils': 0.17.0
|
||||
lexical: 0.17.0
|
||||
|
||||
/@lexical/offset@0.16.1:
|
||||
resolution: {integrity: sha512-/i2J04lQmFeydUZIF8tKXLQTXiJDTQ6GRnkfv1OpxU4amc0rwGa7+qAz/PuF1n58rP6InpLmSHxgY5JztXa2jw==}
|
||||
/@lexical/offset@0.17.0:
|
||||
resolution: {integrity: sha512-onE6SD2mIAwBLTT5v5fVBVtRg/NpQj+o10vTWJ1ImvEUERpSoCyHMTy3IMoSMuCRwuOG9C0cFEret2u+QS8Icw==}
|
||||
dependencies:
|
||||
lexical: 0.16.1
|
||||
lexical: 0.17.0
|
||||
dev: false
|
||||
|
||||
/@lexical/overflow@0.16.1:
|
||||
resolution: {integrity: sha512-xh5YpoxwA7K4wgMQF/Sjl8sdjaxqesLCtH5ZrcMsaPlmucDIEEs+i8xxk+kDUTEY7y+3FvRxs4lGNgX8RVWkvQ==}
|
||||
/@lexical/overflow@0.17.0:
|
||||
resolution: {integrity: sha512-dh+nQAmeobKvZFodWyzNh1ZjX043Patk/1Lwct9XmtAGMUdXL+tB0bbguWVcDfY8OYu1CTQGfbdq2oMEJYzwsg==}
|
||||
dependencies:
|
||||
lexical: 0.16.1
|
||||
lexical: 0.17.0
|
||||
dev: false
|
||||
|
||||
/@lexical/plain-text@0.16.1:
|
||||
resolution: {integrity: sha512-GjY4ylrBZIaAVIF8IFnmW0XGyHAuRmWA6gKB8iTTlsjgFrCHFIYC74EeJSp309O0Hflg9rRBnKoX1TYruFHVwA==}
|
||||
/@lexical/plain-text@0.17.0:
|
||||
resolution: {integrity: sha512-AEk+3ttbRyRi7m9UbU1CdLUtGsXh4FFZkBC12twV3U82lZHOdHocLlTutP+lcbYlGjeq6UF43NxOSGzsYEunsA==}
|
||||
dependencies:
|
||||
'@lexical/clipboard': 0.16.1
|
||||
'@lexical/selection': 0.16.1
|
||||
'@lexical/utils': 0.16.1
|
||||
lexical: 0.16.1
|
||||
'@lexical/clipboard': 0.17.0
|
||||
'@lexical/selection': 0.17.0
|
||||
'@lexical/utils': 0.17.0
|
||||
lexical: 0.17.0
|
||||
dev: false
|
||||
|
||||
/@lexical/react@0.16.1(react-dom@19.0.0-rc-fb9a90fa48-20240614)(react@19.0.0-rc-fb9a90fa48-20240614)(yjs@13.6.18):
|
||||
resolution: {integrity: sha512-SsGgLt9iKfrrMRy9lFb6ROVPUYOgv6b+mCn9Al+TLqs/gBReDBi3msA7m526nrtBUKYUnjHdQ1QXIJzuKgOxcg==}
|
||||
/@lexical/react@0.17.0(react-dom@19.0.0-rc-fb9a90fa48-20240614)(react@19.0.0-rc-fb9a90fa48-20240614)(yjs@13.6.18):
|
||||
resolution: {integrity: sha512-HZ3joq+5g2++2vo/6scTd60Y2bsu8ya8EUdopyudnmGZGKAcAPue9pLOlBaEpsYZ7vqTuGjiPgtEBfFzDy9rlg==}
|
||||
peerDependencies:
|
||||
react: ^19.0.0-rc-6230622a1a-20240610
|
||||
react-dom: ^19.0.0-rc-6230622a1a-20240610
|
||||
dependencies:
|
||||
'@lexical/clipboard': 0.16.1
|
||||
'@lexical/code': 0.16.1
|
||||
'@lexical/devtools-core': 0.16.1(react-dom@19.0.0-rc-fb9a90fa48-20240614)(react@19.0.0-rc-fb9a90fa48-20240614)
|
||||
'@lexical/dragon': 0.16.1
|
||||
'@lexical/hashtag': 0.16.1
|
||||
'@lexical/history': 0.16.1
|
||||
'@lexical/link': 0.16.1
|
||||
'@lexical/list': 0.16.1
|
||||
'@lexical/mark': 0.16.1
|
||||
'@lexical/markdown': 0.16.1
|
||||
'@lexical/overflow': 0.16.1
|
||||
'@lexical/plain-text': 0.16.1
|
||||
'@lexical/rich-text': 0.16.1
|
||||
'@lexical/selection': 0.16.1
|
||||
'@lexical/table': 0.16.1
|
||||
'@lexical/text': 0.16.1
|
||||
'@lexical/utils': 0.16.1
|
||||
'@lexical/yjs': 0.16.1(yjs@13.6.18)
|
||||
lexical: 0.16.1
|
||||
'@lexical/clipboard': 0.17.0
|
||||
'@lexical/code': 0.17.0
|
||||
'@lexical/devtools-core': 0.17.0(react-dom@19.0.0-rc-fb9a90fa48-20240614)(react@19.0.0-rc-fb9a90fa48-20240614)
|
||||
'@lexical/dragon': 0.17.0
|
||||
'@lexical/hashtag': 0.17.0
|
||||
'@lexical/history': 0.17.0
|
||||
'@lexical/link': 0.17.0
|
||||
'@lexical/list': 0.17.0
|
||||
'@lexical/mark': 0.17.0
|
||||
'@lexical/markdown': 0.17.0
|
||||
'@lexical/overflow': 0.17.0
|
||||
'@lexical/plain-text': 0.17.0
|
||||
'@lexical/rich-text': 0.17.0
|
||||
'@lexical/selection': 0.17.0
|
||||
'@lexical/table': 0.17.0
|
||||
'@lexical/text': 0.17.0
|
||||
'@lexical/utils': 0.17.0
|
||||
'@lexical/yjs': 0.17.0(yjs@13.6.18)
|
||||
lexical: 0.17.0
|
||||
react: 19.0.0-rc-fb9a90fa48-20240614
|
||||
react-dom: 19.0.0-rc-fb9a90fa48-20240614(react@19.0.0-rc-fb9a90fa48-20240614)
|
||||
react-error-boundary: 3.1.4(react@19.0.0-rc-fb9a90fa48-20240614)
|
||||
@@ -5848,45 +5848,45 @@ packages:
|
||||
- yjs
|
||||
dev: false
|
||||
|
||||
/@lexical/rich-text@0.16.1:
|
||||
resolution: {integrity: sha512-4uEVXJur7tdSbqbmsToCW4YVm0AMh4y9LK077Yq2O9hSuA5dqpI8UbTDnxZN2D7RfahNvwlqp8eZKFB1yeiJGQ==}
|
||||
/@lexical/rich-text@0.17.0:
|
||||
resolution: {integrity: sha512-XJc8gQBSwppCkESQaNcGtyTaPXZaeCQDcUVpnDjDK0vM/ZZN8TErxbujwbSqA3kO2dBds9N8WxNboSwuncMBcQ==}
|
||||
dependencies:
|
||||
'@lexical/clipboard': 0.16.1
|
||||
'@lexical/selection': 0.16.1
|
||||
'@lexical/utils': 0.16.1
|
||||
lexical: 0.16.1
|
||||
'@lexical/clipboard': 0.17.0
|
||||
'@lexical/selection': 0.17.0
|
||||
'@lexical/utils': 0.17.0
|
||||
lexical: 0.17.0
|
||||
|
||||
/@lexical/selection@0.16.1:
|
||||
resolution: {integrity: sha512-+nK3RvXtyQvQDq7AZ46JpphmM33pwuulwiRfeXR5T9iFQTtgWOEjsAi/KKX7vGm70BxACfiSxy5QCOgBWFwVJg==}
|
||||
/@lexical/selection@0.17.0:
|
||||
resolution: {integrity: sha512-UTjlvyhFY/lmHtBaIaVRwYnRfO9gR4I32+PT7vHQr4v3VfcgS63YEGSgEZy3Gh1pfeJqaZATN58+jCuMAQXlWQ==}
|
||||
dependencies:
|
||||
lexical: 0.16.1
|
||||
lexical: 0.17.0
|
||||
|
||||
/@lexical/table@0.16.1:
|
||||
resolution: {integrity: sha512-GWb0/MM1sVXpi1p2HWWOBldZXASMQ4c6WRNYnRmq7J/aB5N66HqQgJGKp3m66Kz4k1JjhmZfPs7F018qIBhnFQ==}
|
||||
/@lexical/table@0.17.0:
|
||||
resolution: {integrity: sha512-RQF7IG0rGL2/bPaPFUIMgDA3QMdDflvXSnE7Udgbj9yMqSKhYkaERVfNyoLckDUSuusGJd6XV+qum6JWn0nSNA==}
|
||||
dependencies:
|
||||
'@lexical/utils': 0.16.1
|
||||
lexical: 0.16.1
|
||||
'@lexical/utils': 0.17.0
|
||||
lexical: 0.17.0
|
||||
|
||||
/@lexical/text@0.16.1:
|
||||
resolution: {integrity: sha512-Os/nKQegORTrKKN6vL3/FMVszyzyqaotlisPynvTaHTUC+yY4uyjM2hlF93i5a2ixxyiPLF9bDroxUP96TMPXg==}
|
||||
/@lexical/text@0.17.0:
|
||||
resolution: {integrity: sha512-kFH0V6yjW8YswmoY7vHT4zHFDflGfamuUxTPHROpdnq/JMjHeaVwtmFBdrP0gknaC8XMRXdr3EsemQ7cbOoDPA==}
|
||||
dependencies:
|
||||
lexical: 0.16.1
|
||||
lexical: 0.17.0
|
||||
|
||||
/@lexical/utils@0.16.1:
|
||||
resolution: {integrity: sha512-BVyJxDQi/rIxFTDjf2zE7rMDKSuEaeJ4dybHRa/hRERt85gavGByQawSLeQlTjLaYLVsy+x7wCcqh2fNhlLf0g==}
|
||||
/@lexical/utils@0.17.0:
|
||||
resolution: {integrity: sha512-B/n0rRGDmdMrqi2qnprLt6SntC6jb4JItLmPl8zDDdg7/HxMdLq3F93vogeiXQJn0mlNqgiENWHvLAy5K2C2uQ==}
|
||||
dependencies:
|
||||
'@lexical/list': 0.16.1
|
||||
'@lexical/selection': 0.16.1
|
||||
'@lexical/table': 0.16.1
|
||||
lexical: 0.16.1
|
||||
'@lexical/list': 0.17.0
|
||||
'@lexical/selection': 0.17.0
|
||||
'@lexical/table': 0.17.0
|
||||
lexical: 0.17.0
|
||||
|
||||
/@lexical/yjs@0.16.1(yjs@13.6.18):
|
||||
resolution: {integrity: sha512-QHw1bmzB/IypIV1tRWMH4hhwE1xX7wV+HxbzBS8oJAkoU5AYXM/kyp/sQicgqiwVfpai1Px7zatOoUDFgbyzHQ==}
|
||||
/@lexical/yjs@0.17.0(yjs@13.6.18):
|
||||
resolution: {integrity: sha512-xJv3frcK/jskssLbzdY4yfBaM7+LWaZD4YjYkJ/bvRDTey2w+McF+SvsJ/yBA8YF1oaL3rT+0aIQJ7rfH+AxjA==}
|
||||
peerDependencies:
|
||||
yjs: '>=13.5.22'
|
||||
dependencies:
|
||||
'@lexical/offset': 0.16.1
|
||||
lexical: 0.16.1
|
||||
'@lexical/offset': 0.17.0
|
||||
lexical: 0.17.0
|
||||
yjs: 13.6.18
|
||||
dev: false
|
||||
|
||||
@@ -12284,8 +12284,8 @@ packages:
|
||||
prelude-ls: 1.2.1
|
||||
type-check: 0.4.0
|
||||
|
||||
/lexical@0.16.1:
|
||||
resolution: {integrity: sha512-+R05d3+N945OY8pTUjTqQrWoApjC+ctzvjnmNETtx9WmVAaiW0tQVG+AYLt5pDGY8dQXtd4RPorvnxBTECt9SA==}
|
||||
/lexical@0.17.0:
|
||||
resolution: {integrity: sha512-cCFmANO5rIf34NF0go/hxp5S3V5Z8G2Rsa1FJy50qF2WM5EJNJ/MqN75TApjfgMkfrbO6gau3X12nCqwsT7aDg==}
|
||||
|
||||
/lib0@0.2.94:
|
||||
resolution: {integrity: sha512-hZ3p54jL4Wpu7IOg26uC7dnEWiMyNlUrb9KoG7+xYs45WkQwpVvKFndVq2+pqLYKe1u8Fp3+zAfZHVvTK34PvQ==}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -3,12 +3,6 @@ import type { IndexDirection, IndexOptions } from 'mongoose'
|
||||
import type { PaginatedDocs, Payload } from 'payload'
|
||||
|
||||
import { reload } from '@payloadcms/next/utilities'
|
||||
import fs from 'fs/promises'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import path from 'path'
|
||||
import { generateTypes } from 'payload/node'
|
||||
const filename = fileURLToPath(import.meta.url)
|
||||
const dirname = path.dirname(filename)
|
||||
|
||||
import type { NextRESTClient } from '../helpers/NextRESTClient.js'
|
||||
import type { GroupField, RichTextField } from './payload-types.js'
|
||||
@@ -1701,19 +1695,4 @@ describe('Fields', () => {
|
||||
expect(result.docs).toHaveLength(1)
|
||||
})
|
||||
})
|
||||
|
||||
describe('TypeScript generated types', () => {
|
||||
/**
|
||||
* Check that the generated types have not unintentionally changed.
|
||||
*
|
||||
* If they must change:
|
||||
*
|
||||
* AFTER REVIEWING THE CHANGES, update the snapshot with `pnpm test:int fields --updateSnapshot`
|
||||
*/
|
||||
it('should not unintentionally change the generated types', async () => {
|
||||
await generateTypes(payload.config)
|
||||
const payloadTypes = await fs.readFile(path.resolve(dirname, './payload-types.ts'), 'utf-8')
|
||||
expect(payloadTypes).toMatchSnapshot()
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -74,7 +74,6 @@ export interface Config {
|
||||
export interface UserAuthOperations {
|
||||
forgotPassword: {
|
||||
email: string;
|
||||
password: string;
|
||||
};
|
||||
login: {
|
||||
email: string;
|
||||
@@ -86,7 +85,6 @@ export interface UserAuthOperations {
|
||||
};
|
||||
unlock: {
|
||||
email: string;
|
||||
password: string;
|
||||
};
|
||||
}
|
||||
/**
|
||||
@@ -281,7 +279,7 @@ export interface User {
|
||||
hash?: string | null;
|
||||
loginAttempts?: number | null;
|
||||
lockUntil?: string | null;
|
||||
password: string | null;
|
||||
password?: string | null;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
|
||||
@@ -12,7 +12,11 @@ const Hooks: CollectionConfig = {
|
||||
hooks: {
|
||||
beforeOperation: [
|
||||
({ operation, req }) => {
|
||||
if (typeof req.payload.db.beginTransaction === 'function' && !req.transactionID && ['create', 'delete', 'update'].includes(operation)) {
|
||||
if (
|
||||
typeof req.payload.db.beginTransaction === 'function' &&
|
||||
!req.transactionID &&
|
||||
['create', 'delete', 'update'].includes(operation)
|
||||
) {
|
||||
throw new Error('transactionID is missing in beforeOperation hook')
|
||||
}
|
||||
},
|
||||
|
||||
@@ -23,8 +23,8 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@aws-sdk/client-s3": "^3.525.0",
|
||||
"@lexical/headless": "0.16.1",
|
||||
"@lexical/markdown": "0.16.1",
|
||||
"@lexical/headless": "0.17.0",
|
||||
"@lexical/markdown": "0.17.0",
|
||||
"@payloadcms/db-mongodb": "workspace:*",
|
||||
"@payloadcms/db-postgres": "workspace:*",
|
||||
"@payloadcms/db-sqlite": "workspace:*",
|
||||
@@ -68,7 +68,7 @@
|
||||
"file-type": "17.1.6",
|
||||
"http-status": "1.6.2",
|
||||
"jwt-decode": "4.0.0",
|
||||
"lexical": "0.16.1",
|
||||
"lexical": "0.17.0",
|
||||
"payload": "workspace:*",
|
||||
"qs-esm": "7.0.2",
|
||||
"server-only": "^0.0.1",
|
||||
|
||||
Reference in New Issue
Block a user