Compare commits
16 Commits
v3.0.0-bet
...
v3.0.0-bet
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
df023a52fd | ||
|
|
d267cad482 | ||
|
|
fa38dfc16c | ||
|
|
8e1a5c8dba | ||
|
|
a8c60c1c02 | ||
|
|
d44fb2db37 | ||
|
|
852f9fc1fd | ||
|
|
e2d803800d | ||
|
|
7fa68d17f5 | ||
|
|
9ec431a5bd | ||
|
|
cadf815ef6 | ||
|
|
638382e7fd | ||
|
|
08fdbcacc0 | ||
|
|
b27e42c484 | ||
|
|
32cc1a5761 | ||
|
|
38be69b7d3 |
@@ -431,14 +431,14 @@ export const MyClientComponent: React.FC = () => {
|
||||
See [Using Hooks](#using-hooks) for more details.
|
||||
</Banner>
|
||||
|
||||
All [Field Components](./fields) automatically receive their respective Client Field Config through a common [`field`](./fields#the-field-prop) prop:
|
||||
All [Field Components](./fields) automatically receive their respective Field Config through a common [`field`](./fields#the-field-prop) prop:
|
||||
|
||||
```tsx
|
||||
'use client'
|
||||
import React from 'react'
|
||||
import type { TextFieldProps } from 'payload'
|
||||
import type { TextFieldClientComponent } from 'payload'
|
||||
|
||||
export const MyClientFieldComponent = ({ field: { name } }: TextFieldProps) => {
|
||||
export const MyClientFieldComponent: TextFieldClientComponent = ({ field: { name } }) => {
|
||||
return (
|
||||
<p>
|
||||
{`This field's name is ${name}`}
|
||||
|
||||
@@ -136,7 +136,7 @@ All Field Components receive the following props:
|
||||
| Property | Description |
|
||||
| ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **`docPreferences`** | An object that contains the [Preferences](./preferences) for the document.
|
||||
| **`field`** | The sanitized, client-friendly version of the field's config. [More details](#the-field-prop) |
|
||||
| **`field`** | The field's config. [More details](#the-field-prop) |
|
||||
| **`locale`** | The locale of the field. [More details](../configuration/localization). |
|
||||
| **`readOnly`** | A boolean value that represents if the field is read-only or not. |
|
||||
| **`user`** | The currently authenticated user. [More details](../authentication/overview). |
|
||||
@@ -175,46 +175,46 @@ export const CustomTextField: React.FC = () => {
|
||||
|
||||
#### TypeScript
|
||||
|
||||
When building Custom Field Components, you can import the component props to ensure type safety in your component. There is an explicit type for the Field Component, one for every [Field Type](../fields/overview). The convention is to append `Props` to the type of field, i.e. `TextFieldProps`.
|
||||
When building Custom Field Components, you can import the component type to ensure type safety. There is an explicit type for the Field Component, one for every [Field Type](../fields/overview) and for every client/server environment. The convention is to prepend the field type onto the target type, i.e. `TextFieldClientComponent`:
|
||||
|
||||
```tsx
|
||||
import type {
|
||||
ArrayFieldProps,
|
||||
BlocksFieldProps,
|
||||
CheckboxFieldProps,
|
||||
CodeFieldProps,
|
||||
CollapsibleFieldProps,
|
||||
DateFieldProps,
|
||||
EmailFieldProps,
|
||||
GroupFieldProps,
|
||||
HiddenFieldProps,
|
||||
JSONFieldProps,
|
||||
NumberFieldProps,
|
||||
PointFieldProps,
|
||||
RadioFieldProps,
|
||||
RelationshipFieldProps,
|
||||
RichTextFieldProps,
|
||||
RowFieldProps,
|
||||
SelectFieldProps,
|
||||
TabsFieldProps,
|
||||
TextFieldProps,
|
||||
TextareaFieldProps,
|
||||
UploadFieldProps
|
||||
TextFieldClientComponent,
|
||||
TextFieldServerComponent,
|
||||
TextFieldClientProps,
|
||||
TextFieldServerProps,
|
||||
// ...and so on for each Field Type
|
||||
} from 'payload'
|
||||
```
|
||||
|
||||
### The `field` Prop
|
||||
|
||||
All Field Components are passed a client-friendly version of their Field Config through a common `field` prop. Since the raw Field Config is [non-serializable](https://react.dev/reference/rsc/use-client#serializable-types), Payload sanitized it into a [Client Config](./components#accessing-the-payload-config) that is safe to pass into Client Components.
|
||||
All Field Components are passed their own Field Config through a common `field` prop. Within a Server Component, this is the raw Field Config. Within Client Components, however, the raw Field Config is [non-serializable](https://react.dev/reference/rsc/use-client#serializable-types). Instead, Client Components receives a [Client Config](./components#accessing-the-payload-config), which is a sanitizes version of the Field Config that is safe to pass into Client Components.
|
||||
|
||||
The exact shape of this prop is unique to the specific [Field Type](../fields/overview) being rendered, minus all non-serializable properties. Any [Custom Components](../components) are also resolved into a "mapped component" that is safe to pass.
|
||||
|
||||
```tsx
|
||||
import React from 'react'
|
||||
import type { TextFieldServerComponent } from 'payload'
|
||||
|
||||
export const MyServerTextField: TextFieldServerComponent = ({ payload, field: { name } }) => {
|
||||
const result = await payload.find({
|
||||
collection: 'myCollection',
|
||||
depth: 1,
|
||||
})
|
||||
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
Client Component:
|
||||
|
||||
```tsx
|
||||
'use client'
|
||||
import React from 'react'
|
||||
import type { TextFieldProps } from 'payload'
|
||||
import type { TextFieldClientComponent } from 'payload'
|
||||
|
||||
export const MyClientFieldComponent: React.FC<TextFieldProps> = ({ field: { name } }) => {
|
||||
export const MyClientTextField: TextFieldClientComponent = ({ field: { name } }) => {
|
||||
return (
|
||||
<p>
|
||||
{`This field's name is ${name}`}
|
||||
@@ -238,40 +238,18 @@ The following additional properties are also provided to the `field` prop:
|
||||
|
||||
#### TypeScript
|
||||
|
||||
When building Custom Field Components, you can import the client field props to ensure type safety in your component. There is an explicit type for the Field Component, one for every [Field Type](../fields/overview). The convention is to append `Client` to the type of field, i.e. `TextFieldClient`.
|
||||
When building Custom Field Components, you can import the client field props to ensure type safety in your component. There is an explicit type for the Field Component, one for every [Field Type](../fields/overview) and server/client environment. The convention is to prepend the field type onto the target type, i.e. `TextFieldClientComponent`:
|
||||
|
||||
```tsx
|
||||
import type {
|
||||
ArrayFieldClient,
|
||||
BlocksFieldClient,
|
||||
CheckboxFieldClient,
|
||||
CodeFieldClient,
|
||||
CollapsibleFieldClient,
|
||||
DateFieldClient,
|
||||
EmailFieldClient,
|
||||
GroupFieldClient,
|
||||
HiddenFieldClient,
|
||||
JSONFieldClient,
|
||||
NumberFieldClient,
|
||||
PointFieldClient,
|
||||
RadioFieldClient,
|
||||
RelationshipFieldClient,
|
||||
RichTextFieldClient,
|
||||
RowFieldClient,
|
||||
SelectFieldClient,
|
||||
TabsFieldClient,
|
||||
TextFieldClient,
|
||||
TextareaFieldClient,
|
||||
UploadFieldClient
|
||||
TextFieldClientComponent,
|
||||
TextFieldServerComponent,
|
||||
TextFieldClientProps,
|
||||
TextFieldServerProps,
|
||||
// ...and so on for each Field Type
|
||||
} from 'payload'
|
||||
```
|
||||
|
||||
When working on the client, you will never have access to objects of type `Field`. This is reserved for the server-side. Instead, you can use `ClientField` which is a union type of all the client fields:
|
||||
|
||||
```tsx
|
||||
import type { ClientField } from 'payload'
|
||||
```
|
||||
|
||||
### The Cell Component
|
||||
|
||||
The Cell Component is rendered in the table of the List View. It represents the value of the field when displayed in a table cell.
|
||||
@@ -353,7 +331,7 @@ When building Custom Label Components, you can import the component props to ens
|
||||
import type {
|
||||
TextFieldLabelServerComponent,
|
||||
TextFieldLabelClientComponent,
|
||||
// And so on for each Field Type
|
||||
// ...and so on for each Field Type
|
||||
} from 'payload'
|
||||
```
|
||||
|
||||
|
||||
@@ -5,13 +5,13 @@ export const recordLastLoggedInTenant: AfterLoginHook = async ({ req, user }) =>
|
||||
const relatedOrg = await req.payload
|
||||
.find({
|
||||
collection: 'tenants',
|
||||
depth: 0,
|
||||
limit: 1,
|
||||
where: {
|
||||
'domains.domain': {
|
||||
in: [req.headers.host],
|
||||
},
|
||||
},
|
||||
depth: 0,
|
||||
limit: 1,
|
||||
})
|
||||
?.then((res) => res.docs?.[0])
|
||||
|
||||
@@ -24,7 +24,10 @@ export const recordLastLoggedInTenant: AfterLoginHook = async ({ req, user }) =>
|
||||
req,
|
||||
})
|
||||
} catch (err: unknown) {
|
||||
req.payload.logger.error(`Error recording last logged in tenant for user ${user.id}: ${err}`)
|
||||
req.payload.logger.error({
|
||||
err,
|
||||
msg: `Error recording last logged in tenant for user ${user.id}`,
|
||||
})
|
||||
}
|
||||
|
||||
return user
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "payload-monorepo",
|
||||
"version": "3.0.0-beta.100",
|
||||
"version": "3.0.0-beta.102",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "create-payload-app",
|
||||
"version": "3.0.0-beta.100",
|
||||
"version": "3.0.0-beta.102",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/db-mongodb",
|
||||
"version": "3.0.0-beta.100",
|
||||
"version": "3.0.0-beta.102",
|
||||
"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.100",
|
||||
"version": "3.0.0-beta.102",
|
||||
"description": "The officially supported Postgres database adapter for Payload",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
|
||||
@@ -23,7 +23,7 @@ const connectWithReconnect = async function ({
|
||||
} else {
|
||||
try {
|
||||
result = await adapter.pool.connect()
|
||||
} catch (err) {
|
||||
} catch (ignore) {
|
||||
setTimeout(() => {
|
||||
payload.logger.info('Reconnecting to postgres')
|
||||
void connectWithReconnect({ adapter, payload, reconnect: true })
|
||||
@@ -38,7 +38,7 @@ const connectWithReconnect = async function ({
|
||||
if (err.code === 'ECONNRESET') {
|
||||
void connectWithReconnect({ adapter, payload, reconnect: true })
|
||||
}
|
||||
} catch (err) {
|
||||
} catch (ignore) {
|
||||
// swallow error
|
||||
}
|
||||
})
|
||||
@@ -76,7 +76,7 @@ export const connect: Connect = async function connect(
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
this.payload.logger.error(`Error: cannot connect to Postgres. Details: ${err.message}`, err)
|
||||
this.payload.logger.error({ err, msg: `Error: cannot connect to Postgres: ${err.message}` })
|
||||
if (typeof this.rejectInitializing === 'function') {
|
||||
this.rejectInitializing()
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/db-sqlite",
|
||||
"version": "3.0.0-beta.100",
|
||||
"version": "3.0.0-beta.102",
|
||||
"description": "The officially supported SQLite database adapter for Payload",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
|
||||
@@ -37,7 +37,7 @@ export const connect: Connect = async function connect(
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
this.payload.logger.error(`Error: cannot connect to SQLite. Details: ${err.message}`, err)
|
||||
this.payload.logger.error({ err, msg: `Error: cannot connect to SQLite: ${err.message}` })
|
||||
if (typeof this.rejectInitializing === 'function') {
|
||||
this.rejectInitializing()
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/db-vercel-postgres",
|
||||
"version": "3.0.0-beta.100",
|
||||
"version": "3.0.0-beta.102",
|
||||
"description": "Vercel Postgres adapter for Payload",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
|
||||
@@ -39,7 +39,7 @@ export const connect: Connect = async function connect(
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
this.payload.logger.error(`Error: cannot connect to Postgres. Details: ${err.message}`, err)
|
||||
this.payload.logger.error({ err, msg: `Error: cannot connect to Postgres: ${err.message}` })
|
||||
if (typeof this.rejectInitializing === 'function') {
|
||||
this.rejectInitializing()
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/drizzle",
|
||||
"version": "3.0.0-beta.100",
|
||||
"version": "3.0.0-beta.102",
|
||||
"description": "A library of shared functions used by different payload database adapters",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
|
||||
@@ -37,6 +37,7 @@ export const beginTransaction: BeginTransaction = async function beginTransactio
|
||||
return done
|
||||
}
|
||||
reject = () => {
|
||||
// eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors
|
||||
rej()
|
||||
return done
|
||||
}
|
||||
@@ -57,7 +58,7 @@ export const beginTransaction: BeginTransaction = async function beginTransactio
|
||||
resolve,
|
||||
}
|
||||
} catch (err) {
|
||||
this.payload.logger.error(`Error: cannot begin transaction: ${err.message}`, err)
|
||||
this.payload.logger.error({ err, msg: `Error: cannot begin transaction: ${err.message}` })
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/email-nodemailer",
|
||||
"version": "3.0.0-beta.100",
|
||||
"version": "3.0.0-beta.102",
|
||||
"description": "Payload Nodemailer Email Adapter",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/email-resend",
|
||||
"version": "3.0.0-beta.100",
|
||||
"version": "3.0.0-beta.102",
|
||||
"description": "Payload Resend Email Adapter",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/graphql",
|
||||
"version": "3.0.0-beta.100",
|
||||
"version": "3.0.0-beta.102",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/live-preview-react",
|
||||
"version": "3.0.0-beta.100",
|
||||
"version": "3.0.0-beta.102",
|
||||
"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.100",
|
||||
"version": "3.0.0-beta.102",
|
||||
"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.100",
|
||||
"version": "3.0.0-beta.102",
|
||||
"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.100",
|
||||
"version": "3.0.0-beta.102",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
@@ -28,7 +28,6 @@ import {
|
||||
useListQuery,
|
||||
useModal,
|
||||
useRouteCache,
|
||||
useSearchParams,
|
||||
useStepNav,
|
||||
useTranslation,
|
||||
useWindowInfo,
|
||||
@@ -54,8 +53,7 @@ export const DefaultListView: React.FC = () => {
|
||||
newDocumentURL,
|
||||
} = useListInfo()
|
||||
|
||||
const { data, defaultLimit, handlePageChange, handlePerPageChange } = useListQuery()
|
||||
const { searchParams } = useSearchParams()
|
||||
const { data, defaultLimit, handlePageChange, handlePerPageChange, params } = useListQuery()
|
||||
const { openModal } = useModal()
|
||||
const { clearRouteCache } = useRouteCache()
|
||||
const { setCollectionSlug, setOnSuccess } = useBulkUpload()
|
||||
@@ -226,9 +224,7 @@ export const DefaultListView: React.FC = () => {
|
||||
</div>
|
||||
<PerPage
|
||||
handleChange={(limit) => void handlePerPageChange(limit)}
|
||||
limit={
|
||||
isNumber(searchParams?.limit) ? Number(searchParams.limit) : defaultLimit
|
||||
}
|
||||
limit={isNumber(params?.limit) ? Number(params.limit) : defaultLimit}
|
||||
limits={collectionConfig?.admin?.pagination?.limits}
|
||||
resetPage={data.totalDocs <= data.pagingCounter}
|
||||
/>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "payload",
|
||||
"version": "3.0.0-beta.100",
|
||||
"version": "3.0.0-beta.102",
|
||||
"description": "Node, React, Headless CMS and Application Framework built on Next.js",
|
||||
"keywords": [
|
||||
"admin panel",
|
||||
|
||||
@@ -13,7 +13,7 @@ import type {
|
||||
} from '../fields/config/types.js'
|
||||
import type { SanitizedGlobalConfig } from '../globals/config/types.js'
|
||||
import type { JsonObject, Payload, PayloadRequest, RequestContext } from '../types/index.js'
|
||||
import type { RichTextFieldProps } from './fields/RichText.js'
|
||||
import type { RichTextFieldClientProps } from './fields/RichText.js'
|
||||
import type { CreateMappedComponent } from './types.js'
|
||||
|
||||
export type AfterReadRichTextHookArgs<
|
||||
@@ -261,7 +261,7 @@ export type RichTextAdapter<
|
||||
ExtraFieldProperties = any,
|
||||
> = {
|
||||
CellComponent: PayloadComponent<never>
|
||||
FieldComponent: PayloadComponent<never, RichTextFieldProps>
|
||||
FieldComponent: PayloadComponent<never, RichTextFieldClientProps>
|
||||
} & RichTextAdapterBase<Value, AdapterProps, ExtraFieldProperties>
|
||||
|
||||
export type RichTextAdapterProvider<
|
||||
|
||||
@@ -3,21 +3,38 @@ import type { MarkOptional } from 'ts-essentials'
|
||||
import type { ArrayField, ArrayFieldClient } from '../../fields/config/types.js'
|
||||
import type { ArrayFieldValidation } from '../../fields/validations.js'
|
||||
import type { FieldErrorClientComponent, FieldErrorServerComponent } from '../forms/Error.js'
|
||||
import type {
|
||||
ClientFieldBase,
|
||||
FieldClientComponent,
|
||||
FieldServerComponent,
|
||||
ServerFieldBase,
|
||||
} from '../forms/Field.js'
|
||||
import type {
|
||||
FieldDescriptionClientComponent,
|
||||
FieldDescriptionServerComponent,
|
||||
FieldLabelClientComponent,
|
||||
FieldLabelServerComponent,
|
||||
FormFieldBase,
|
||||
MappedComponent,
|
||||
} from '../types.js'
|
||||
|
||||
type ArrayFieldClientWithoutType = MarkOptional<ArrayFieldClient, 'type'>
|
||||
|
||||
export type ArrayFieldProps = {
|
||||
type ArrayFieldBaseClientProps = {
|
||||
readonly CustomRowLabel?: MappedComponent
|
||||
readonly validate?: ArrayFieldValidation
|
||||
} & Omit<FormFieldBase<ArrayFieldClientWithoutType>, 'validate'>
|
||||
}
|
||||
|
||||
export type ArrayFieldClientProps = ArrayFieldBaseClientProps &
|
||||
ClientFieldBase<ArrayFieldClientWithoutType>
|
||||
|
||||
export type ArrayFieldServerProps = ServerFieldBase<ArrayField>
|
||||
|
||||
export type ArrayFieldServerComponent = FieldServerComponent<ArrayField>
|
||||
|
||||
export type ArrayFieldClientComponent = FieldClientComponent<
|
||||
ArrayFieldClientWithoutType,
|
||||
ArrayFieldBaseClientProps
|
||||
>
|
||||
|
||||
export type ArrayFieldLabelServerComponent = FieldLabelServerComponent<ArrayField>
|
||||
|
||||
|
||||
@@ -3,19 +3,36 @@ import type { MarkOptional } from 'ts-essentials'
|
||||
import type { BlockField, BlockFieldClient } from '../../fields/config/types.js'
|
||||
import type { BlockFieldValidation } from '../../fields/validations.js'
|
||||
import type { FieldErrorClientComponent, FieldErrorServerComponent } from '../forms/Error.js'
|
||||
import type {
|
||||
ClientFieldBase,
|
||||
FieldClientComponent,
|
||||
FieldServerComponent,
|
||||
ServerFieldBase,
|
||||
} from '../forms/Field.js'
|
||||
import type {
|
||||
FieldDescriptionClientComponent,
|
||||
FieldDescriptionServerComponent,
|
||||
FieldLabelClientComponent,
|
||||
FieldLabelServerComponent,
|
||||
FormFieldBase,
|
||||
} from '../types.js'
|
||||
|
||||
type BlocksFieldClientWithoutType = MarkOptional<BlockFieldClient, 'type'>
|
||||
|
||||
export type BlockFieldProps = {
|
||||
type BlocksFieldBaseClientProps = {
|
||||
readonly validate?: BlockFieldValidation
|
||||
} & Omit<FormFieldBase<BlocksFieldClientWithoutType>, 'validate'>
|
||||
}
|
||||
|
||||
export type BlocksFieldClientProps = BlocksFieldBaseClientProps &
|
||||
ClientFieldBase<BlocksFieldClientWithoutType>
|
||||
|
||||
export type BlocksFieldServerProps = ServerFieldBase<BlockField>
|
||||
|
||||
export type BlocksFieldServerComponent = FieldServerComponent<BlockField>
|
||||
|
||||
export type BlocksFieldClientComponent = FieldClientComponent<
|
||||
BlocksFieldClientWithoutType,
|
||||
BlocksFieldBaseClientProps
|
||||
>
|
||||
|
||||
export type BlockFieldLabelServerComponent = FieldLabelServerComponent<BlockField>
|
||||
|
||||
|
||||
@@ -3,24 +3,41 @@ import type { MarkOptional } from 'ts-essentials'
|
||||
import type { CheckboxField, CheckboxFieldClient } from '../../fields/config/types.js'
|
||||
import type { CheckboxFieldValidation } from '../../fields/validations.js'
|
||||
import type { FieldErrorClientComponent, FieldErrorServerComponent } from '../forms/Error.js'
|
||||
import type {
|
||||
ClientFieldBase,
|
||||
FieldClientComponent,
|
||||
FieldServerComponent,
|
||||
ServerFieldBase,
|
||||
} from '../forms/Field.js'
|
||||
import type {
|
||||
FieldDescriptionClientComponent,
|
||||
FieldDescriptionServerComponent,
|
||||
FieldLabelClientComponent,
|
||||
FieldLabelServerComponent,
|
||||
FormFieldBase,
|
||||
} from '../types.js'
|
||||
|
||||
type CheckboxFieldClientWithoutType = MarkOptional<CheckboxFieldClient, 'type'>
|
||||
|
||||
export type CheckboxFieldProps = {
|
||||
type CheckboxFieldBaseClientProps = {
|
||||
readonly checked?: boolean
|
||||
readonly disableFormData?: boolean
|
||||
readonly id?: string
|
||||
readonly onChange?: (value: boolean) => void
|
||||
readonly partialChecked?: boolean
|
||||
readonly validate?: CheckboxFieldValidation
|
||||
} & Omit<FormFieldBase<CheckboxFieldClientWithoutType>, 'validate'>
|
||||
}
|
||||
|
||||
export type CheckboxFieldClientProps = CheckboxFieldBaseClientProps &
|
||||
ClientFieldBase<CheckboxFieldClientWithoutType>
|
||||
|
||||
export type CheckboxFieldServerProps = ServerFieldBase<CheckboxField>
|
||||
|
||||
export type CheckboxFieldServerComponent = FieldServerComponent<CheckboxField>
|
||||
|
||||
export type CheckboxFieldClientComponent = FieldClientComponent<
|
||||
CheckboxFieldClientWithoutType,
|
||||
CheckboxFieldBaseClientProps
|
||||
>
|
||||
|
||||
export type CheckboxFieldLabelServerComponent = FieldLabelServerComponent<CheckboxField>
|
||||
|
||||
|
||||
@@ -3,20 +3,37 @@ import type { MarkOptional } from 'ts-essentials'
|
||||
import type { CodeField, CodeFieldClient } from '../../fields/config/types.js'
|
||||
import type { CodeFieldValidation } from '../../fields/validations.js'
|
||||
import type { FieldErrorClientComponent, FieldErrorServerComponent } from '../forms/Error.js'
|
||||
import type {
|
||||
ClientFieldBase,
|
||||
FieldClientComponent,
|
||||
FieldServerComponent,
|
||||
ServerFieldBase,
|
||||
} from '../forms/Field.js'
|
||||
import type {
|
||||
FieldDescriptionClientComponent,
|
||||
FieldDescriptionServerComponent,
|
||||
FieldLabelClientComponent,
|
||||
FieldLabelServerComponent,
|
||||
FormFieldBase,
|
||||
} from '../types.js'
|
||||
|
||||
type CodeFieldClientWithoutType = MarkOptional<CodeFieldClient, 'type'>
|
||||
|
||||
export type CodeFieldProps = {
|
||||
type CodeFieldBaseClientProps = {
|
||||
readonly autoComplete?: string
|
||||
readonly validate?: CodeFieldValidation
|
||||
} & Omit<FormFieldBase<CodeFieldClientWithoutType>, 'validate'>
|
||||
readonly valiCode?: CodeFieldValidation
|
||||
}
|
||||
|
||||
export type CodeFieldClientProps = ClientFieldBase<CodeFieldClientWithoutType> &
|
||||
CodeFieldBaseClientProps
|
||||
|
||||
export type CodeFieldServerProps = ServerFieldBase<CodeField>
|
||||
|
||||
export type CodeFieldServerComponent = FieldServerComponent<CodeField>
|
||||
|
||||
export type CodeFieldClientComponent = FieldClientComponent<
|
||||
CodeFieldClientWithoutType,
|
||||
CodeFieldBaseClientProps
|
||||
>
|
||||
|
||||
export type CodeFieldLabelServerComponent = FieldLabelServerComponent<CodeField>
|
||||
|
||||
|
||||
@@ -2,17 +2,29 @@ import type { MarkOptional } from 'ts-essentials'
|
||||
|
||||
import type { CollapsibleField, CollapsibleFieldClient } from '../../fields/config/types.js'
|
||||
import type { FieldErrorClientComponent, FieldErrorServerComponent } from '../forms/Error.js'
|
||||
import type {
|
||||
ClientFieldBase,
|
||||
FieldClientComponent,
|
||||
FieldServerComponent,
|
||||
ServerFieldBase,
|
||||
} from '../forms/Field.js'
|
||||
import type {
|
||||
FieldDescriptionClientComponent,
|
||||
FieldDescriptionServerComponent,
|
||||
FieldLabelClientComponent,
|
||||
FieldLabelServerComponent,
|
||||
FormFieldBase,
|
||||
} from '../types.js'
|
||||
|
||||
type CollapsibleFieldClientWithoutType = MarkOptional<CollapsibleFieldClient, 'type'>
|
||||
|
||||
export type CollapsibleFieldProps = FormFieldBase<CollapsibleFieldClientWithoutType>
|
||||
export type CollapsibleFieldClientProps = ClientFieldBase<CollapsibleFieldClientWithoutType>
|
||||
|
||||
export type CollapsibleFieldServerProps = ServerFieldBase<CollapsibleField>
|
||||
|
||||
export type CollapsibleFieldServerComponent = FieldServerComponent<CollapsibleField>
|
||||
|
||||
export type CollapsibleFieldClientComponent =
|
||||
FieldClientComponent<CollapsibleFieldClientWithoutType>
|
||||
|
||||
export type CollapsibleFieldLabelServerComponent = FieldLabelServerComponent<CollapsibleField>
|
||||
|
||||
|
||||
@@ -3,19 +3,36 @@ import type { MarkOptional } from 'ts-essentials'
|
||||
import type { DateField, DateFieldClient } from '../../fields/config/types.js'
|
||||
import type { DateFieldValidation } from '../../fields/validations.js'
|
||||
import type { FieldErrorClientComponent, FieldErrorServerComponent } from '../forms/Error.js'
|
||||
import type {
|
||||
ClientFieldBase,
|
||||
FieldClientComponent,
|
||||
FieldServerComponent,
|
||||
ServerFieldBase,
|
||||
} from '../forms/Field.js'
|
||||
import type {
|
||||
FieldDescriptionClientComponent,
|
||||
FieldDescriptionServerComponent,
|
||||
FieldLabelClientComponent,
|
||||
FieldLabelServerComponent,
|
||||
FormFieldBase,
|
||||
} from '../types.js'
|
||||
|
||||
type DateFieldClientWithoutType = MarkOptional<DateFieldClient, 'type'>
|
||||
|
||||
export type DateFieldProps = {
|
||||
type DateFieldBaseClientProps = {
|
||||
readonly validate?: DateFieldValidation
|
||||
} & Omit<FormFieldBase<DateFieldClientWithoutType>, 'validate'>
|
||||
}
|
||||
|
||||
export type DateFieldClientProps = ClientFieldBase<DateFieldClientWithoutType> &
|
||||
DateFieldBaseClientProps
|
||||
|
||||
export type DateFieldServerProps = ServerFieldBase<DateField>
|
||||
|
||||
export type DateFieldServerComponent = FieldServerComponent<DateField>
|
||||
|
||||
export type DateFieldClientComponent = FieldClientComponent<
|
||||
DateFieldClientWithoutType,
|
||||
DateFieldBaseClientProps
|
||||
>
|
||||
|
||||
export type DateFieldLabelServerComponent = FieldLabelServerComponent<DateField>
|
||||
|
||||
|
||||
@@ -3,20 +3,37 @@ import type { MarkOptional } from 'ts-essentials'
|
||||
import type { EmailField, EmailFieldClient } from '../../fields/config/types.js'
|
||||
import type { EmailFieldValidation } from '../../fields/validations.js'
|
||||
import type { FieldErrorClientComponent, FieldErrorServerComponent } from '../forms/Error.js'
|
||||
import type {
|
||||
ClientFieldBase,
|
||||
FieldClientComponent,
|
||||
FieldServerComponent,
|
||||
ServerFieldBase,
|
||||
} from '../forms/Field.js'
|
||||
import type {
|
||||
FieldDescriptionClientComponent,
|
||||
FieldDescriptionServerComponent,
|
||||
FieldLabelClientComponent,
|
||||
FieldLabelServerComponent,
|
||||
FormFieldBase,
|
||||
} from '../types.js'
|
||||
|
||||
type EmailFieldClientWithoutType = MarkOptional<EmailFieldClient, 'type'>
|
||||
|
||||
export type EmailFieldProps = {
|
||||
type EmailFieldBaseClientProps = {
|
||||
readonly autoComplete?: string
|
||||
readonly validate?: EmailFieldValidation
|
||||
} & Omit<FormFieldBase<EmailFieldClientWithoutType>, 'validate'>
|
||||
}
|
||||
|
||||
export type EmailFieldClientProps = ClientFieldBase<EmailFieldClientWithoutType> &
|
||||
EmailFieldBaseClientProps
|
||||
|
||||
export type EmailFieldServerProps = ServerFieldBase<EmailField>
|
||||
|
||||
export type EmailFieldServerComponent = FieldServerComponent<EmailField>
|
||||
|
||||
export type EmailFieldClientComponent = FieldClientComponent<
|
||||
EmailFieldClientWithoutType,
|
||||
EmailFieldBaseClientProps
|
||||
>
|
||||
|
||||
export type EmailFieldLabelServerComponent = FieldLabelServerComponent<EmailField>
|
||||
|
||||
|
||||
@@ -2,17 +2,28 @@ import type { MarkOptional } from 'ts-essentials'
|
||||
|
||||
import type { GroupField, GroupFieldClient } from '../../fields/config/types.js'
|
||||
import type { FieldErrorClientComponent, FieldErrorServerComponent } from '../forms/Error.js'
|
||||
import type {
|
||||
ClientFieldBase,
|
||||
FieldClientComponent,
|
||||
FieldServerComponent,
|
||||
ServerFieldBase,
|
||||
} from '../forms/Field.js'
|
||||
import type {
|
||||
FieldDescriptionClientComponent,
|
||||
FieldDescriptionServerComponent,
|
||||
FieldLabelClientComponent,
|
||||
FieldLabelServerComponent,
|
||||
FormFieldBase,
|
||||
} from '../types.js'
|
||||
|
||||
type GroupFieldClientWithoutType = MarkOptional<GroupFieldClient, 'type'>
|
||||
|
||||
export type GroupFieldProps = FormFieldBase<GroupFieldClientWithoutType>
|
||||
export type GroupFieldClientProps = ClientFieldBase<GroupFieldClientWithoutType>
|
||||
|
||||
export type GroupFieldServerProps = ServerFieldBase<GroupField>
|
||||
|
||||
export type GroupFieldServerComponent = FieldServerComponent<GroupField>
|
||||
|
||||
export type GroupFieldClientComponent = FieldClientComponent<GroupFieldClientWithoutType>
|
||||
|
||||
export type GroupFieldLabelServerComponent = FieldLabelServerComponent<GroupField>
|
||||
|
||||
|
||||
@@ -3,19 +3,36 @@ import type { MarkOptional } from 'ts-essentials'
|
||||
import type { JSONField, JSONFieldClient } from '../../fields/config/types.js'
|
||||
import type { JSONFieldValidation } from '../../fields/validations.js'
|
||||
import type { FieldErrorClientComponent, FieldErrorServerComponent } from '../forms/Error.js'
|
||||
import type {
|
||||
ClientFieldBase,
|
||||
FieldClientComponent,
|
||||
FieldServerComponent,
|
||||
ServerFieldBase,
|
||||
} from '../forms/Field.js'
|
||||
import type {
|
||||
FieldDescriptionClientComponent,
|
||||
FieldDescriptionServerComponent,
|
||||
FieldLabelClientComponent,
|
||||
FieldLabelServerComponent,
|
||||
FormFieldBase,
|
||||
} from '../types.js'
|
||||
|
||||
type JSONFieldClientWithoutType = MarkOptional<JSONFieldClient, 'type'>
|
||||
|
||||
export type JSONFieldProps = {
|
||||
type JSONFieldBaseClientProps = {
|
||||
readonly validate?: JSONFieldValidation
|
||||
} & Omit<FormFieldBase<JSONFieldClientWithoutType>, 'validate'>
|
||||
}
|
||||
|
||||
export type JSONFieldClientProps = ClientFieldBase<JSONFieldClientWithoutType> &
|
||||
JSONFieldBaseClientProps
|
||||
|
||||
export type JSONFieldServerProps = ServerFieldBase<JSONField>
|
||||
|
||||
export type JSONFieldServerComponent = FieldServerComponent<JSONField>
|
||||
|
||||
export type JSONFieldClientComponent = FieldClientComponent<
|
||||
JSONFieldClientWithoutType,
|
||||
JSONFieldBaseClientProps
|
||||
>
|
||||
|
||||
export type JSONFieldLabelServerComponent = FieldLabelServerComponent<JSONField>
|
||||
|
||||
|
||||
@@ -3,20 +3,37 @@ import type { MarkOptional } from 'ts-essentials'
|
||||
import type { NumberField, NumberFieldClient } from '../../fields/config/types.js'
|
||||
import type { NumberFieldValidation } from '../../fields/validations.js'
|
||||
import type { FieldErrorClientComponent, FieldErrorServerComponent } from '../forms/Error.js'
|
||||
import type {
|
||||
ClientFieldBase,
|
||||
FieldClientComponent,
|
||||
FieldServerComponent,
|
||||
ServerFieldBase,
|
||||
} from '../forms/Field.js'
|
||||
import type {
|
||||
FieldDescriptionClientComponent,
|
||||
FieldDescriptionServerComponent,
|
||||
FieldLabelClientComponent,
|
||||
FieldLabelServerComponent,
|
||||
FormFieldBase,
|
||||
} from '../types.js'
|
||||
|
||||
type NumberFieldClientWithoutType = MarkOptional<NumberFieldClient, 'type'>
|
||||
|
||||
export type NumberFieldProps = {
|
||||
type NumberFieldBaseClientProps = {
|
||||
readonly onChange?: (e: number) => void
|
||||
readonly validate?: NumberFieldValidation
|
||||
} & Omit<FormFieldBase<NumberFieldClientWithoutType>, 'validate'>
|
||||
}
|
||||
|
||||
export type NumberFieldClientProps = ClientFieldBase<NumberFieldClientWithoutType> &
|
||||
NumberFieldBaseClientProps
|
||||
|
||||
export type NumberFieldServerProps = ServerFieldBase<NumberField>
|
||||
|
||||
export type NumberFieldServerComponent = FieldServerComponent<NumberField>
|
||||
|
||||
export type NumberFieldClientComponent = FieldClientComponent<
|
||||
NumberFieldClientWithoutType,
|
||||
NumberFieldBaseClientProps
|
||||
>
|
||||
|
||||
export type NumberFieldLabelServerComponent = FieldLabelServerComponent<NumberField>
|
||||
|
||||
|
||||
@@ -3,19 +3,36 @@ import type { MarkOptional } from 'ts-essentials'
|
||||
import type { PointField, PointFieldClient } from '../../fields/config/types.js'
|
||||
import type { PointFieldValidation } from '../../fields/validations.js'
|
||||
import type { FieldErrorClientComponent, FieldErrorServerComponent } from '../forms/Error.js'
|
||||
import type {
|
||||
ClientFieldBase,
|
||||
FieldClientComponent,
|
||||
FieldServerComponent,
|
||||
ServerFieldBase,
|
||||
} from '../forms/Field.js'
|
||||
import type {
|
||||
FieldDescriptionClientComponent,
|
||||
FieldDescriptionServerComponent,
|
||||
FieldLabelClientComponent,
|
||||
FieldLabelServerComponent,
|
||||
FormFieldBase,
|
||||
} from '../types.js'
|
||||
|
||||
type PointFieldClientWithoutType = MarkOptional<PointFieldClient, 'type'>
|
||||
|
||||
export type PointFieldProps = {
|
||||
type PointFieldBaseClientProps = {
|
||||
readonly validate?: PointFieldValidation
|
||||
} & Omit<FormFieldBase<PointFieldClientWithoutType>, 'validate'>
|
||||
}
|
||||
|
||||
export type PointFieldClientProps = ClientFieldBase<PointFieldClientWithoutType> &
|
||||
PointFieldBaseClientProps
|
||||
|
||||
export type PointFieldServerProps = ServerFieldBase<PointField>
|
||||
|
||||
export type PointFieldServerComponent = FieldServerComponent<PointField>
|
||||
|
||||
export type PointFieldClientComponent = FieldClientComponent<
|
||||
PointFieldClientWithoutType,
|
||||
PointFieldBaseClientProps
|
||||
>
|
||||
|
||||
export type PointFieldLabelServerComponent = FieldLabelServerComponent<PointField>
|
||||
|
||||
|
||||
@@ -3,21 +3,38 @@ import type { MarkOptional } from 'ts-essentials'
|
||||
import type { RadioField, RadioFieldClient } from '../../fields/config/types.js'
|
||||
import type { RadioFieldValidation } from '../../fields/validations.js'
|
||||
import type { FieldErrorClientComponent, FieldErrorServerComponent } from '../forms/Error.js'
|
||||
import type {
|
||||
ClientFieldBase,
|
||||
FieldClientComponent,
|
||||
FieldServerComponent,
|
||||
ServerFieldBase,
|
||||
} from '../forms/Field.js'
|
||||
import type {
|
||||
FieldDescriptionClientComponent,
|
||||
FieldDescriptionServerComponent,
|
||||
FieldLabelClientComponent,
|
||||
FieldLabelServerComponent,
|
||||
FormFieldBase,
|
||||
} from '../types.js'
|
||||
|
||||
type RadioFieldClientWithoutType = MarkOptional<RadioFieldClient, 'type'>
|
||||
|
||||
export type RadioFieldProps = {
|
||||
type RadioFieldBaseClientProps = {
|
||||
readonly onChange?: OnChange
|
||||
readonly validate?: RadioFieldValidation
|
||||
readonly value?: string
|
||||
} & Omit<FormFieldBase<RadioFieldClientWithoutType>, 'validate'>
|
||||
}
|
||||
|
||||
export type RadioFieldClientProps = ClientFieldBase<RadioFieldClientWithoutType> &
|
||||
RadioFieldBaseClientProps
|
||||
|
||||
export type RadioFieldServerProps = ServerFieldBase<RadioField>
|
||||
|
||||
export type RadioFieldServerComponent = FieldServerComponent<RadioField>
|
||||
|
||||
export type RadioFieldClientComponent = FieldClientComponent<
|
||||
RadioFieldClientWithoutType,
|
||||
RadioFieldBaseClientProps
|
||||
>
|
||||
|
||||
export type OnChange<T = string> = (value: T) => void
|
||||
|
||||
|
||||
@@ -3,19 +3,36 @@ import type { MarkOptional } from 'ts-essentials'
|
||||
import type { RelationshipField, RelationshipFieldClient } from '../../fields/config/types.js'
|
||||
import type { RelationshipFieldValidation } from '../../fields/validations.js'
|
||||
import type { FieldErrorClientComponent, FieldErrorServerComponent } from '../forms/Error.js'
|
||||
import type {
|
||||
ClientFieldBase,
|
||||
FieldClientComponent,
|
||||
FieldServerComponent,
|
||||
ServerFieldBase,
|
||||
} from '../forms/Field.js'
|
||||
import type {
|
||||
FieldDescriptionClientComponent,
|
||||
FieldDescriptionServerComponent,
|
||||
FieldLabelClientComponent,
|
||||
FieldLabelServerComponent,
|
||||
FormFieldBase,
|
||||
} from '../types.js'
|
||||
|
||||
type RelationshipFieldClientWithoutType = MarkOptional<RelationshipFieldClient, 'type'>
|
||||
|
||||
export type RelationshipFieldProps = {
|
||||
type RelationshipFieldBaseClientProps = {
|
||||
readonly validate?: RelationshipFieldValidation
|
||||
} & Omit<FormFieldBase<RelationshipFieldClientWithoutType>, 'validate'>
|
||||
}
|
||||
|
||||
export type RelationshipFieldClientProps = ClientFieldBase<RelationshipFieldClientWithoutType> &
|
||||
RelationshipFieldBaseClientProps
|
||||
|
||||
export type RelationshipFieldServerProps = ServerFieldBase<RelationshipField>
|
||||
|
||||
export type RelationshipFieldServerComponent = FieldServerComponent<RelationshipField>
|
||||
|
||||
export type RelationshipFieldClientComponent = FieldClientComponent<
|
||||
RelationshipFieldClientWithoutType,
|
||||
RelationshipFieldBaseClientProps
|
||||
>
|
||||
|
||||
export type RelationshipFieldLabelServerComponent = FieldLabelServerComponent<RelationshipField>
|
||||
|
||||
|
||||
@@ -3,23 +3,44 @@ import type { MarkOptional } from 'ts-essentials'
|
||||
import type { RichTextField, RichTextFieldClient } from '../../fields/config/types.js'
|
||||
import type { RichTextFieldValidation } from '../../fields/validations.js'
|
||||
import type { FieldErrorClientComponent, FieldErrorServerComponent } from '../forms/Error.js'
|
||||
import type {
|
||||
ClientFieldBase,
|
||||
FieldClientComponent,
|
||||
FieldServerComponent,
|
||||
ServerFieldBase,
|
||||
} from '../forms/Field.js'
|
||||
import type {
|
||||
FieldDescriptionClientComponent,
|
||||
FieldDescriptionServerComponent,
|
||||
FieldLabelClientComponent,
|
||||
FieldLabelServerComponent,
|
||||
FormFieldBase,
|
||||
} from '../types.js'
|
||||
|
||||
type RichTextFieldClientWithoutType = MarkOptional<RichTextFieldClient, 'type'>
|
||||
|
||||
export type RichTextFieldProps<
|
||||
type RichTextFieldBaseClientProps<
|
||||
TValue extends object = any,
|
||||
TAdapterProps = any,
|
||||
TExtraProperties = object,
|
||||
> = {
|
||||
readonly validate?: RichTextFieldValidation
|
||||
} & Omit<FormFieldBase<RichTextFieldClientWithoutType>, 'validate'>
|
||||
}
|
||||
|
||||
export type RichTextFieldClientProps<
|
||||
TValue extends object = any,
|
||||
TAdapterProps = any,
|
||||
TExtraProperties = object,
|
||||
> = ClientFieldBase<RichTextFieldClientWithoutType> &
|
||||
RichTextFieldBaseClientProps<TValue, TAdapterProps, TExtraProperties>
|
||||
|
||||
export type RichTextFieldServerProps = ServerFieldBase<RichTextField>
|
||||
|
||||
export type RichTextFieldServerComponent = FieldServerComponent<RichTextField>
|
||||
|
||||
export type RichTextFieldClientComponent = FieldClientComponent<
|
||||
RichTextFieldClientWithoutType,
|
||||
RichTextFieldBaseClientProps
|
||||
>
|
||||
|
||||
export type RichTextFieldLabelServerComponent = FieldLabelServerComponent<RichTextField>
|
||||
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
import type { MarkOptional } from 'ts-essentials'
|
||||
|
||||
import type { RowField, RowFieldClient } from '../../fields/config/types.js'
|
||||
import type {
|
||||
ClientFieldBase,
|
||||
FieldClientComponent,
|
||||
FieldServerComponent,
|
||||
ServerFieldBase,
|
||||
} from '../forms/Field.js'
|
||||
import type {
|
||||
FieldDescriptionClientComponent,
|
||||
FieldDescriptionServerComponent,
|
||||
@@ -8,15 +14,26 @@ import type {
|
||||
FieldErrorServerComponent,
|
||||
FieldLabelClientComponent,
|
||||
FieldLabelServerComponent,
|
||||
FormFieldBase,
|
||||
} from '../types.js'
|
||||
|
||||
type RowFieldClientWithoutType = MarkOptional<RowFieldClient, 'type'>
|
||||
|
||||
export type RowFieldProps = {
|
||||
type RowFieldBaseClientProps = {
|
||||
readonly forceRender?: boolean
|
||||
readonly indexPath: string
|
||||
} & FormFieldBase<RowFieldClientWithoutType>
|
||||
}
|
||||
|
||||
export type RowFieldClientProps = ClientFieldBase<RowFieldClientWithoutType> &
|
||||
RowFieldBaseClientProps
|
||||
|
||||
export type RowFieldServerProps = ServerFieldBase<RowField>
|
||||
|
||||
export type RowFieldServerComponent = FieldServerComponent<RowField>
|
||||
|
||||
export type RowFieldClientComponent = FieldClientComponent<
|
||||
RowFieldClientWithoutType,
|
||||
RowFieldBaseClientProps
|
||||
>
|
||||
|
||||
export type RowFieldLabelServerComponent = FieldLabelServerComponent<RowField>
|
||||
|
||||
|
||||
@@ -3,21 +3,38 @@ import type { MarkOptional } from 'ts-essentials'
|
||||
import type { SelectField, SelectFieldClient } from '../../fields/config/types.js'
|
||||
import type { SelectFieldValidation } from '../../fields/validations.js'
|
||||
import type { FieldErrorClientComponent, FieldErrorServerComponent } from '../forms/Error.js'
|
||||
import type {
|
||||
ClientFieldBase,
|
||||
FieldClientComponent,
|
||||
FieldServerComponent,
|
||||
ServerFieldBase,
|
||||
} from '../forms/Field.js'
|
||||
import type {
|
||||
FieldDescriptionClientComponent,
|
||||
FieldDescriptionServerComponent,
|
||||
FieldLabelClientComponent,
|
||||
FieldLabelServerComponent,
|
||||
FormFieldBase,
|
||||
} from '../types.js'
|
||||
|
||||
type SelectFieldClientWithoutType = MarkOptional<SelectFieldClient, 'type'>
|
||||
|
||||
export type SelectFieldProps = {
|
||||
type SelectFieldBaseClientProps = {
|
||||
readonly onChange?: (e: string | string[]) => void
|
||||
readonly validate?: SelectFieldValidation
|
||||
readonly value?: string
|
||||
} & Omit<FormFieldBase<SelectFieldClientWithoutType>, 'validate'>
|
||||
}
|
||||
|
||||
export type SelectFieldClientProps = ClientFieldBase<SelectFieldClientWithoutType> &
|
||||
SelectFieldBaseClientProps
|
||||
|
||||
export type SelectFieldServerProps = ServerFieldBase<SelectField>
|
||||
|
||||
export type SelectFieldServerComponent = FieldServerComponent<SelectField>
|
||||
|
||||
export type SelectFieldClientComponent = FieldClientComponent<
|
||||
SelectFieldClientWithoutType,
|
||||
SelectFieldBaseClientProps
|
||||
>
|
||||
|
||||
export type SelectFieldLabelServerComponent = FieldLabelServerComponent<SelectField>
|
||||
|
||||
|
||||
@@ -8,21 +8,32 @@ import type {
|
||||
UnnamedTab,
|
||||
} from '../../fields/config/types.js'
|
||||
import type { FieldErrorClientComponent, FieldErrorServerComponent } from '../forms/Error.js'
|
||||
import type {
|
||||
ClientFieldBase,
|
||||
FieldClientComponent,
|
||||
FieldServerComponent,
|
||||
ServerFieldBase,
|
||||
} from '../forms/Field.js'
|
||||
import type {
|
||||
FieldDescriptionClientComponent,
|
||||
FieldDescriptionServerComponent,
|
||||
FieldLabelClientComponent,
|
||||
FieldLabelServerComponent,
|
||||
FormFieldBase,
|
||||
} from '../types.js'
|
||||
|
||||
export type ClientTab =
|
||||
| ({ fields: ClientField[] } & Omit<NamedTab, 'fields'>)
|
||||
| ({ fields: ClientField[] } & Omit<UnnamedTab, 'fields'>)
|
||||
|
||||
export type TabsFieldClientWithoutType = MarkOptional<TabsFieldClient, 'type'>
|
||||
type TabsFieldClientWithoutType = MarkOptional<TabsFieldClient, 'type'>
|
||||
|
||||
export type TabsFieldProps = FormFieldBase<TabsFieldClientWithoutType>
|
||||
export type TabsFieldClientProps = ClientFieldBase<TabsFieldClientWithoutType>
|
||||
|
||||
export type TabsFieldServerProps = ServerFieldBase<TabsField>
|
||||
|
||||
export type TabsFieldServerComponent = FieldServerComponent<TabsField>
|
||||
|
||||
export type TabsFieldClientComponent = FieldClientComponent<TabsFieldClientWithoutType>
|
||||
|
||||
export type TabsFieldLabelServerComponent = FieldLabelServerComponent<TabsField>
|
||||
|
||||
|
||||
@@ -4,21 +4,38 @@ import type { MarkOptional } from 'ts-essentials'
|
||||
import type { TextField, TextFieldClient } from '../../fields/config/types.js'
|
||||
import type { TextFieldValidation } from '../../fields/validations.js'
|
||||
import type { FieldErrorClientComponent, FieldErrorServerComponent } from '../forms/Error.js'
|
||||
import type {
|
||||
ClientFieldBase,
|
||||
FieldClientComponent,
|
||||
FieldServerComponent,
|
||||
ServerFieldBase,
|
||||
} from '../forms/Field.js'
|
||||
import type {
|
||||
FieldDescriptionClientComponent,
|
||||
FieldDescriptionServerComponent,
|
||||
FieldLabelClientComponent,
|
||||
FieldLabelServerComponent,
|
||||
FormFieldBase,
|
||||
} from '../types.js'
|
||||
|
||||
type TextFieldClientWithoutType = MarkOptional<TextFieldClient, 'type'>
|
||||
|
||||
export type TextFieldProps = {
|
||||
type TextFieldBaseClientProps = {
|
||||
readonly inputRef?: React.RefObject<HTMLInputElement>
|
||||
readonly onKeyDown?: React.KeyboardEventHandler<HTMLInputElement>
|
||||
readonly validate?: TextFieldValidation
|
||||
} & Omit<FormFieldBase<TextFieldClientWithoutType>, 'validate'>
|
||||
}
|
||||
|
||||
export type TextFieldClientProps = ClientFieldBase<TextFieldClientWithoutType> &
|
||||
TextFieldBaseClientProps
|
||||
|
||||
export type TextFieldServerProps = ServerFieldBase<TextField>
|
||||
|
||||
export type TextFieldServerComponent = FieldServerComponent<TextField>
|
||||
|
||||
export type TextFieldClientComponent = FieldClientComponent<
|
||||
TextFieldClientWithoutType,
|
||||
TextFieldBaseClientProps
|
||||
>
|
||||
|
||||
export type TextFieldLabelServerComponent = FieldLabelServerComponent<TextField>
|
||||
|
||||
|
||||
@@ -4,21 +4,38 @@ import type { MarkOptional } from 'ts-essentials'
|
||||
import type { TextareaField, TextareaFieldClient } from '../../fields/config/types.js'
|
||||
import type { TextareaFieldValidation } from '../../fields/validations.js'
|
||||
import type { FieldErrorClientComponent, FieldErrorServerComponent } from '../forms/Error.js'
|
||||
import type {
|
||||
ClientFieldBase,
|
||||
FieldClientComponent,
|
||||
FieldServerComponent,
|
||||
ServerFieldBase,
|
||||
} from '../forms/Field.js'
|
||||
import type {
|
||||
FieldDescriptionClientComponent,
|
||||
FieldDescriptionServerComponent,
|
||||
FieldLabelClientComponent,
|
||||
FieldLabelServerComponent,
|
||||
FormFieldBase,
|
||||
} from '../types.js'
|
||||
|
||||
type TextareaFieldClientWithoutType = MarkOptional<TextareaFieldClient, 'type'>
|
||||
|
||||
export type TextareaFieldProps = {
|
||||
type TextareaFieldBaseClientProps = {
|
||||
readonly inputRef?: React.Ref<HTMLInputElement>
|
||||
readonly onKeyDown?: React.KeyboardEventHandler<HTMLInputElement>
|
||||
readonly validate?: TextareaFieldValidation
|
||||
} & Omit<FormFieldBase<TextareaFieldClientWithoutType>, 'validate'>
|
||||
}
|
||||
|
||||
export type TextareaFieldClientProps = ClientFieldBase<TextareaFieldClientWithoutType> &
|
||||
TextareaFieldBaseClientProps
|
||||
|
||||
export type TextareaFieldServerProps = ServerFieldBase<TextareaField>
|
||||
|
||||
export type TextareaFieldServerComponent = FieldServerComponent<TextareaField>
|
||||
|
||||
export type TextareaFieldClientComponent = FieldClientComponent<
|
||||
TextareaFieldClientWithoutType,
|
||||
TextareaFieldBaseClientProps
|
||||
>
|
||||
|
||||
export type TextareaFieldLabelServerComponent = FieldLabelServerComponent<TextareaField>
|
||||
|
||||
|
||||
@@ -3,19 +3,36 @@ import type { MarkOptional } from 'ts-essentials'
|
||||
import type { UploadField, UploadFieldClient } from '../../fields/config/types.js'
|
||||
import type { UploadFieldValidation } from '../../fields/validations.js'
|
||||
import type { FieldErrorClientComponent, FieldErrorServerComponent } from '../forms/Error.js'
|
||||
import type {
|
||||
ClientFieldBase,
|
||||
FieldClientComponent,
|
||||
FieldServerComponent,
|
||||
ServerFieldBase,
|
||||
} from '../forms/Field.js'
|
||||
import type {
|
||||
FieldDescriptionClientComponent,
|
||||
FieldDescriptionServerComponent,
|
||||
FieldLabelClientComponent,
|
||||
FieldLabelServerComponent,
|
||||
FormFieldBase,
|
||||
} from '../types.js'
|
||||
|
||||
type UploadFieldClientWithoutType = MarkOptional<UploadFieldClient, 'type'>
|
||||
|
||||
export type UploadFieldProps = {
|
||||
type UploadFieldBaseClientProps = {
|
||||
readonly validate?: UploadFieldValidation
|
||||
} & Omit<FormFieldBase<UploadFieldClientWithoutType>, 'validate'>
|
||||
}
|
||||
|
||||
export type UploadFieldClientProps = ClientFieldBase<UploadFieldClientWithoutType> &
|
||||
UploadFieldBaseClientProps
|
||||
|
||||
export type UploadFieldServerProps = ServerFieldBase<UploadField>
|
||||
|
||||
export type UploadFieldServerComponent = FieldServerComponent<UploadField>
|
||||
|
||||
export type UploadFieldClientComponent = FieldClientComponent<
|
||||
UploadFieldClientWithoutType,
|
||||
UploadFieldBaseClientProps
|
||||
>
|
||||
|
||||
export type UploadFieldLabelServerComponent = FieldLabelServerComponent<UploadField>
|
||||
|
||||
|
||||
@@ -1,13 +1,10 @@
|
||||
import type { MarkOptional } from 'ts-essentials'
|
||||
|
||||
import type { LabelFunction, ServerProps } from '../../config/types.js'
|
||||
import type { ClientField, Field } from '../../fields/config/types.js'
|
||||
import type { Field } from '../../fields/config/types.js'
|
||||
import type { MappedComponent } from '../types.js'
|
||||
import type { ClientFieldWithOptionalType } from './Field.js'
|
||||
|
||||
export type DescriptionFunction = LabelFunction
|
||||
|
||||
type ClientFieldWithOptionalType = MarkOptional<ClientField, 'type'>
|
||||
|
||||
export type FieldDescriptionClientComponent<
|
||||
TFieldClient extends ClientFieldWithOptionalType = ClientFieldWithOptionalType,
|
||||
> = React.ComponentType<FieldDescriptionClientProps<TFieldClient>>
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import type { MarkOptional } from 'ts-essentials'
|
||||
|
||||
import type { ServerProps } from '../../config/types.js'
|
||||
import type { ClientField, Field } from '../../fields/config/types.js'
|
||||
import type { Field } from '../../fields/config/types.js'
|
||||
import type { MappedComponent } from '../types.js'
|
||||
import type { ClientFieldWithOptionalType } from './Field.js'
|
||||
|
||||
export type GenericErrorProps = {
|
||||
readonly alignCaret?: 'center' | 'left' | 'right'
|
||||
@@ -12,8 +11,6 @@ export type GenericErrorProps = {
|
||||
readonly showError?: boolean
|
||||
}
|
||||
|
||||
type ClientFieldWithOptionalType = MarkOptional<ClientField, 'type'>
|
||||
|
||||
export type FieldErrorClientProps<
|
||||
TFieldClient extends ClientFieldWithOptionalType = ClientFieldWithOptionalType,
|
||||
> = {
|
||||
|
||||
@@ -2,24 +2,36 @@ import type { MarkOptional } from 'ts-essentials'
|
||||
|
||||
import type { User } from '../../auth/types.js'
|
||||
import type { Locale } from '../../config/types.js'
|
||||
import type { ClientField, Validate } from '../../fields/config/types.js'
|
||||
import type { ClientField, Field, Validate } from '../../fields/config/types.js'
|
||||
import type { DocumentPreferences } from '../../preferences/types.js'
|
||||
import type { FieldDescriptionClientProps } from './Description.js'
|
||||
import type { FieldErrorClientProps } from './Error.js'
|
||||
import type { FieldLabelClientProps } from './Label.js'
|
||||
import type { FieldDescriptionClientProps, FieldDescriptionServerProps } from './Description.js'
|
||||
import type { FieldErrorClientProps, FieldErrorServerProps } from './Error.js'
|
||||
import type { FieldLabelClientProps, FieldLabelServerProps } from './Label.js'
|
||||
|
||||
export type FormFieldBase<
|
||||
TFieldClient extends MarkOptional<ClientField, 'type'> = MarkOptional<ClientField, 'type'>,
|
||||
export type ClientFieldWithOptionalType = MarkOptional<ClientField, 'type'>
|
||||
|
||||
export type ClientFieldBase<
|
||||
TFieldClient extends ClientFieldWithOptionalType = ClientFieldWithOptionalType,
|
||||
> = {
|
||||
readonly descriptionProps?: FieldDescriptionClientProps<TFieldClient>
|
||||
readonly docPreferences?: DocumentPreferences
|
||||
readonly errorProps?: FieldErrorClientProps<TFieldClient>
|
||||
readonly field: TFieldClient
|
||||
readonly labelProps?: FieldLabelClientProps<TFieldClient>
|
||||
} & FormFieldBase
|
||||
|
||||
export type ServerFieldBase<TFieldServer extends Field = Field> = {
|
||||
readonly descriptionProps?: FieldDescriptionServerProps<TFieldServer>
|
||||
readonly errorProps?: FieldErrorServerProps<TFieldServer>
|
||||
readonly field: TFieldServer
|
||||
readonly labelProps?: FieldLabelServerProps<TFieldServer>
|
||||
} & FormFieldBase
|
||||
|
||||
export type FormFieldBase = {
|
||||
readonly docPreferences?: DocumentPreferences
|
||||
/**
|
||||
* `forceRender` is added by RenderField automatically.
|
||||
*/
|
||||
readonly forceRender?: boolean
|
||||
readonly labelProps?: FieldLabelClientProps<TFieldClient>
|
||||
readonly locale?: Locale
|
||||
/**
|
||||
* `readOnly` is added by RenderField automatically. This should be used instead of `field.admin.readOnly`.
|
||||
@@ -28,3 +40,13 @@ export type FormFieldBase<
|
||||
readonly user?: User
|
||||
readonly validate?: Validate
|
||||
}
|
||||
|
||||
export type FieldClientComponent<
|
||||
TFieldClient extends ClientFieldWithOptionalType = ClientFieldWithOptionalType,
|
||||
AdditionalProps extends Record<string, unknown> = Record<string, unknown>,
|
||||
> = React.ComponentType<AdditionalProps & ClientFieldBase<TFieldClient>>
|
||||
|
||||
export type FieldServerComponent<
|
||||
TFieldServer extends Field = Field,
|
||||
AdditionalProps extends Record<string, unknown> = Record<string, unknown>,
|
||||
> = React.ComponentType<AdditionalProps & ServerFieldBase<TFieldServer>>
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import type { MarkOptional } from 'ts-essentials'
|
||||
|
||||
import type { ServerProps, StaticLabel } from '../../config/types.js'
|
||||
import type { ClientField, Field } from '../../fields/config/types.js'
|
||||
import type { MappedComponent } from '../types.js'
|
||||
import type { ClientFieldWithOptionalType } from './Field.js'
|
||||
|
||||
export type GenericLabelProps = {
|
||||
readonly as?: 'label' | 'span'
|
||||
@@ -13,8 +12,6 @@ export type GenericLabelProps = {
|
||||
readonly unstyled?: boolean
|
||||
}
|
||||
|
||||
type ClientFieldWithOptionalType = MarkOptional<ClientField, 'type'>
|
||||
|
||||
export type FieldLabelClientProps<
|
||||
TFieldClient extends ClientFieldWithOptionalType = ClientFieldWithOptionalType,
|
||||
> = {
|
||||
|
||||
@@ -24,13 +24,16 @@ export type {
|
||||
} from './elements/WithServerSideProps.js'
|
||||
|
||||
export type {
|
||||
ArrayFieldClientComponent,
|
||||
ArrayFieldClientProps,
|
||||
ArrayFieldDescriptionClientComponent,
|
||||
ArrayFieldDescriptionServerComponent,
|
||||
ArrayFieldErrorClientComponent,
|
||||
ArrayFieldErrorServerComponent,
|
||||
ArrayFieldLabelClientComponent,
|
||||
ArrayFieldLabelServerComponent,
|
||||
ArrayFieldProps,
|
||||
ArrayFieldServerComponent,
|
||||
ArrayFieldServerProps,
|
||||
} from './fields/Array.js'
|
||||
|
||||
export type {
|
||||
@@ -40,190 +43,247 @@ export type {
|
||||
BlockFieldErrorServerComponent,
|
||||
BlockFieldLabelClientComponent,
|
||||
BlockFieldLabelServerComponent,
|
||||
BlockFieldProps,
|
||||
BlocksFieldClientComponent,
|
||||
BlocksFieldClientProps,
|
||||
BlocksFieldServerComponent,
|
||||
BlocksFieldServerProps,
|
||||
} from './fields/Blocks.js'
|
||||
|
||||
export type {
|
||||
CheckboxFieldClientComponent,
|
||||
CheckboxFieldClientProps,
|
||||
CheckboxFieldDescriptionClientComponent,
|
||||
CheckboxFieldDescriptionServerComponent,
|
||||
CheckboxFieldErrorClientComponent,
|
||||
CheckboxFieldErrorServerComponent,
|
||||
CheckboxFieldLabelClientComponent,
|
||||
CheckboxFieldLabelServerComponent,
|
||||
CheckboxFieldProps,
|
||||
CheckboxFieldServerComponent,
|
||||
CheckboxFieldServerProps,
|
||||
} from './fields/Checkbox.js'
|
||||
|
||||
export type {
|
||||
CodeFieldClientComponent,
|
||||
CodeFieldClientProps,
|
||||
CodeFieldDescriptionClientComponent,
|
||||
CodeFieldDescriptionServerComponent,
|
||||
CodeFieldErrorClientComponent,
|
||||
CodeFieldErrorServerComponent,
|
||||
CodeFieldLabelClientComponent,
|
||||
CodeFieldLabelServerComponent,
|
||||
CodeFieldProps,
|
||||
CodeFieldServerComponent,
|
||||
CodeFieldServerProps,
|
||||
} from './fields/Code.js'
|
||||
|
||||
export type {
|
||||
CollapsibleFieldClientComponent,
|
||||
CollapsibleFieldClientProps,
|
||||
CollapsibleFieldDescriptionClientComponent,
|
||||
CollapsibleFieldDescriptionServerComponent,
|
||||
CollapsibleFieldErrorClientComponent,
|
||||
CollapsibleFieldErrorServerComponent,
|
||||
CollapsibleFieldLabelClientComponent,
|
||||
CollapsibleFieldLabelServerComponent,
|
||||
CollapsibleFieldProps,
|
||||
CollapsibleFieldServerComponent,
|
||||
CollapsibleFieldServerProps,
|
||||
} from './fields/Collapsible.js'
|
||||
|
||||
export type {
|
||||
DateFieldClientComponent,
|
||||
DateFieldClientProps,
|
||||
DateFieldDescriptionClientComponent,
|
||||
DateFieldDescriptionServerComponent,
|
||||
DateFieldErrorClientComponent,
|
||||
DateFieldErrorServerComponent,
|
||||
DateFieldLabelClientComponent,
|
||||
DateFieldLabelServerComponent,
|
||||
DateFieldProps,
|
||||
DateFieldServerComponent,
|
||||
DateFieldServerProps,
|
||||
} from './fields/Date.js'
|
||||
|
||||
export type {
|
||||
EmailFieldClientComponent,
|
||||
EmailFieldClientProps,
|
||||
EmailFieldDescriptionClientComponent,
|
||||
EmailFieldDescriptionServerComponent,
|
||||
EmailFieldErrorClientComponent,
|
||||
EmailFieldErrorServerComponent,
|
||||
EmailFieldLabelClientComponent,
|
||||
EmailFieldLabelServerComponent,
|
||||
EmailFieldProps,
|
||||
EmailFieldServerComponent,
|
||||
EmailFieldServerProps,
|
||||
} from './fields/Email.js'
|
||||
|
||||
export type {
|
||||
GroupFieldClientComponent,
|
||||
GroupFieldClientProps,
|
||||
GroupFieldDescriptionClientComponent,
|
||||
GroupFieldDescriptionServerComponent,
|
||||
GroupFieldErrorClientComponent,
|
||||
GroupFieldErrorServerComponent,
|
||||
GroupFieldLabelClientComponent,
|
||||
GroupFieldLabelServerComponent,
|
||||
GroupFieldProps,
|
||||
GroupFieldServerComponent,
|
||||
GroupFieldServerProps,
|
||||
} from './fields/Group.js'
|
||||
|
||||
export type { HiddenFieldProps } from './fields/Hidden.js'
|
||||
|
||||
export type {
|
||||
JSONFieldClientComponent,
|
||||
JSONFieldClientProps,
|
||||
JSONFieldDescriptionClientComponent,
|
||||
JSONFieldDescriptionServerComponent,
|
||||
JSONFieldErrorClientComponent,
|
||||
JSONFieldErrorServerComponent,
|
||||
JSONFieldLabelClientComponent,
|
||||
JSONFieldLabelServerComponent,
|
||||
JSONFieldProps,
|
||||
JSONFieldServerComponent,
|
||||
JSONFieldServerProps,
|
||||
} from './fields/JSON.js'
|
||||
|
||||
export type {
|
||||
NumberFieldClientComponent,
|
||||
NumberFieldClientProps,
|
||||
NumberFieldDescriptionClientComponent,
|
||||
NumberFieldDescriptionServerComponent,
|
||||
NumberFieldErrorClientComponent,
|
||||
NumberFieldErrorServerComponent,
|
||||
NumberFieldLabelClientComponent,
|
||||
NumberFieldLabelServerComponent,
|
||||
NumberFieldProps,
|
||||
NumberFieldServerComponent,
|
||||
NumberFieldServerProps,
|
||||
} from './fields/Number.js'
|
||||
|
||||
export type {
|
||||
PointFieldClientComponent,
|
||||
PointFieldClientProps,
|
||||
PointFieldDescriptionClientComponent,
|
||||
PointFieldDescriptionServerComponent,
|
||||
PointFieldErrorClientComponent,
|
||||
PointFieldErrorServerComponent,
|
||||
PointFieldLabelClientComponent,
|
||||
PointFieldLabelServerComponent,
|
||||
PointFieldProps,
|
||||
PointFieldServerComponent,
|
||||
PointFieldServerProps,
|
||||
} from './fields/Point.js'
|
||||
|
||||
export type {
|
||||
RadioFieldClientComponent,
|
||||
RadioFieldClientProps,
|
||||
RadioFieldDescriptionClientComponent,
|
||||
RadioFieldDescriptionServerComponent,
|
||||
RadioFieldErrorClientComponent,
|
||||
RadioFieldErrorServerComponent,
|
||||
RadioFieldLabelClientComponent,
|
||||
RadioFieldLabelServerComponent,
|
||||
RadioFieldProps,
|
||||
RadioFieldServerComponent,
|
||||
RadioFieldServerProps,
|
||||
} from './fields/Radio.js'
|
||||
|
||||
export type {
|
||||
RelationshipFieldClientComponent,
|
||||
RelationshipFieldClientProps,
|
||||
RelationshipFieldDescriptionClientComponent,
|
||||
RelationshipFieldDescriptionServerComponent,
|
||||
RelationshipFieldErrorClientComponent,
|
||||
RelationshipFieldErrorServerComponent,
|
||||
RelationshipFieldLabelClientComponent,
|
||||
RelationshipFieldLabelServerComponent,
|
||||
RelationshipFieldProps,
|
||||
RelationshipFieldServerComponent,
|
||||
RelationshipFieldServerProps,
|
||||
} from './fields/Relationship.js'
|
||||
|
||||
export type {
|
||||
RichTextFieldClientComponent,
|
||||
RichTextFieldClientProps,
|
||||
RichTextFieldDescriptionClientComponent,
|
||||
RichTextFieldDescriptionServerComponent,
|
||||
RichTextFieldErrorClientComponent,
|
||||
RichTextFieldErrorServerComponent,
|
||||
RichTextFieldLabelClientComponent,
|
||||
RichTextFieldLabelServerComponent,
|
||||
RichTextFieldProps,
|
||||
RichTextFieldServerComponent,
|
||||
RichTextFieldServerProps,
|
||||
} from './fields/RichText.js'
|
||||
|
||||
export type {
|
||||
RowFieldClientComponent,
|
||||
RowFieldClientProps,
|
||||
RowFieldDescriptionClientComponent,
|
||||
RowFieldDescriptionServerComponent,
|
||||
RowFieldErrorClientComponent,
|
||||
RowFieldErrorServerComponent,
|
||||
RowFieldLabelClientComponent,
|
||||
RowFieldLabelServerComponent,
|
||||
RowFieldProps,
|
||||
RowFieldServerComponent,
|
||||
RowFieldServerProps,
|
||||
} from './fields/Row.js'
|
||||
|
||||
export type {
|
||||
SelectFieldClientComponent,
|
||||
SelectFieldClientProps,
|
||||
SelectFieldDescriptionClientComponent,
|
||||
SelectFieldDescriptionServerComponent,
|
||||
SelectFieldErrorClientComponent,
|
||||
SelectFieldErrorServerComponent,
|
||||
SelectFieldLabelClientComponent,
|
||||
SelectFieldLabelServerComponent,
|
||||
SelectFieldProps,
|
||||
SelectFieldServerComponent,
|
||||
SelectFieldServerProps,
|
||||
} from './fields/Select.js'
|
||||
|
||||
export type {
|
||||
ClientTab,
|
||||
TabsFieldClientComponent,
|
||||
TabsFieldClientProps,
|
||||
TabsFieldDescriptionClientComponent,
|
||||
TabsFieldDescriptionServerComponent,
|
||||
TabsFieldErrorClientComponent,
|
||||
TabsFieldErrorServerComponent,
|
||||
TabsFieldLabelClientComponent,
|
||||
TabsFieldLabelServerComponent,
|
||||
TabsFieldProps,
|
||||
TabsFieldServerComponent,
|
||||
TabsFieldServerProps,
|
||||
} from './fields/Tabs.js'
|
||||
|
||||
export type {
|
||||
TextFieldClientComponent,
|
||||
TextFieldClientProps,
|
||||
TextFieldDescriptionClientComponent,
|
||||
TextFieldDescriptionServerComponent,
|
||||
TextFieldErrorClientComponent,
|
||||
TextFieldErrorServerComponent,
|
||||
TextFieldLabelClientComponent,
|
||||
TextFieldLabelServerComponent,
|
||||
TextFieldProps,
|
||||
TextFieldServerComponent,
|
||||
TextFieldServerProps,
|
||||
} from './fields/Text.js'
|
||||
|
||||
export type {
|
||||
TextareaFieldClientComponent,
|
||||
TextareaFieldClientProps,
|
||||
TextareaFieldDescriptionClientComponent,
|
||||
TextareaFieldDescriptionServerComponent,
|
||||
TextareaFieldErrorClientComponent,
|
||||
TextareaFieldErrorServerComponent,
|
||||
TextareaFieldLabelClientComponent,
|
||||
TextareaFieldLabelServerComponent,
|
||||
TextareaFieldProps,
|
||||
TextareaFieldServerComponent,
|
||||
TextareaFieldServerProps,
|
||||
} from './fields/Textarea.js'
|
||||
|
||||
export type {
|
||||
UploadFieldClientComponent,
|
||||
UploadFieldClientProps,
|
||||
UploadFieldDescriptionClientComponent,
|
||||
UploadFieldDescriptionServerComponent,
|
||||
UploadFieldErrorClientComponent,
|
||||
UploadFieldErrorServerComponent,
|
||||
UploadFieldLabelClientComponent,
|
||||
UploadFieldLabelServerComponent,
|
||||
UploadFieldProps,
|
||||
UploadFieldServerComponent,
|
||||
UploadFieldServerProps,
|
||||
} from './fields/Upload.js'
|
||||
|
||||
export type {
|
||||
|
||||
@@ -2,8 +2,6 @@ import type { TypedUser } from '../../index.js'
|
||||
import type { PayloadRequest } from '../../types/index.js'
|
||||
import type { Permissions } from '../types.js'
|
||||
|
||||
import { commitTransaction } from '../../utilities/commitTransaction.js'
|
||||
import { initTransaction } from '../../utilities/initTransaction.js'
|
||||
import { killTransaction } from '../../utilities/killTransaction.js'
|
||||
import { executeAuthStrategies } from '../executeAuthStrategies.js'
|
||||
import { getAccessResults } from '../getAccessResults.js'
|
||||
@@ -25,8 +23,6 @@ export const auth = async (args: Required<AuthArgs>): Promise<AuthResult> => {
|
||||
const { payload } = req
|
||||
|
||||
try {
|
||||
const shouldCommit = await initTransaction(req)
|
||||
|
||||
const { responseHeaders, user } = await executeAuthStrategies({
|
||||
headers,
|
||||
payload,
|
||||
@@ -39,10 +35,6 @@ export const auth = async (args: Required<AuthArgs>): Promise<AuthResult> => {
|
||||
req,
|
||||
})
|
||||
|
||||
if (shouldCommit) {
|
||||
await commitTransaction(req)
|
||||
}
|
||||
|
||||
return {
|
||||
permissions,
|
||||
responseHeaders,
|
||||
|
||||
@@ -12,8 +12,6 @@ import type { User } from '../types.js'
|
||||
import { buildAfterOperation } from '../../collections/operations/utils.js'
|
||||
import { AuthenticationError, LockedAuth, ValidationError } from '../../errors/index.js'
|
||||
import { afterRead } from '../../fields/hooks/afterRead/index.js'
|
||||
import { commitTransaction } from '../../utilities/commitTransaction.js'
|
||||
import { initTransaction } from '../../utilities/initTransaction.js'
|
||||
import { killTransaction } from '../../utilities/killTransaction.js'
|
||||
import sanitizeInternalFields from '../../utilities/sanitizeInternalFields.js'
|
||||
import { getFieldsToSign } from '../getFieldsToSign.js'
|
||||
@@ -43,8 +41,6 @@ export const loginOperation = async <TSlug extends CollectionSlug>(
|
||||
let args = incomingArgs
|
||||
|
||||
try {
|
||||
const shouldCommit = await initTransaction(args.req)
|
||||
|
||||
// /////////////////////////////////////
|
||||
// beforeOperation - Collection
|
||||
// /////////////////////////////////////
|
||||
@@ -202,10 +198,6 @@ export const loginOperation = async <TSlug extends CollectionSlug>(
|
||||
})
|
||||
}
|
||||
|
||||
if (shouldCommit) {
|
||||
await commitTransaction(req)
|
||||
}
|
||||
|
||||
throw new AuthenticationError(req.t)
|
||||
}
|
||||
|
||||
@@ -334,10 +326,6 @@ export const loginOperation = async <TSlug extends CollectionSlug>(
|
||||
// Return results
|
||||
// /////////////////////////////////////
|
||||
|
||||
if (shouldCommit) {
|
||||
await commitTransaction(req)
|
||||
}
|
||||
|
||||
return result
|
||||
} catch (error: unknown) {
|
||||
await killTransaction(args.req)
|
||||
|
||||
@@ -14,6 +14,7 @@ import baseVersionFields from '../../versions/baseFields.js'
|
||||
import { versionDefaults } from '../../versions/defaults.js'
|
||||
import { authDefaults, defaults, loginWithUsernameDefaults } from './defaults.js'
|
||||
import { sanitizeAuthFields, sanitizeUploadFields } from './reservedFieldNames.js'
|
||||
import { validateUseAsTitle } from './useAsTitle.js'
|
||||
|
||||
export const sanitizeCollection = async (
|
||||
config: Config,
|
||||
@@ -44,6 +45,8 @@ export const sanitizeCollection = async (
|
||||
validRelationships,
|
||||
})
|
||||
|
||||
validateUseAsTitle(sanitized)
|
||||
|
||||
if (sanitized.timestamps !== false) {
|
||||
// add default timestamps fields only as needed
|
||||
let hasUpdatedAt = null
|
||||
|
||||
204
packages/payload/src/collections/config/useAsTitle.spec.ts
Normal file
204
packages/payload/src/collections/config/useAsTitle.spec.ts
Normal file
@@ -0,0 +1,204 @@
|
||||
import type { Config } from '../../config/types.js'
|
||||
import type { CollectionConfig } from '../../index.js'
|
||||
|
||||
import { InvalidConfiguration } from '../../errors/InvalidConfiguration.js'
|
||||
import { sanitizeCollection } from './sanitize.js'
|
||||
|
||||
describe('sanitize - collections -', () => {
|
||||
const config = {
|
||||
collections: [],
|
||||
globals: [],
|
||||
} as Partial<Config>
|
||||
|
||||
describe('validate useAsTitle -', () => {
|
||||
const defaultCollection: CollectionConfig = {
|
||||
slug: 'collection-with-defaults',
|
||||
fields: [
|
||||
{
|
||||
name: 'title',
|
||||
type: 'text',
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
it('should throw on invalid field', async () => {
|
||||
const collectionConfig: CollectionConfig = {
|
||||
...defaultCollection,
|
||||
admin: {
|
||||
useAsTitle: 'invalidField',
|
||||
},
|
||||
}
|
||||
await expect(async () => {
|
||||
await sanitizeCollection(
|
||||
// @ts-expect-error
|
||||
{
|
||||
...config,
|
||||
collections: [collectionConfig],
|
||||
},
|
||||
collectionConfig,
|
||||
)
|
||||
}).rejects.toThrow(InvalidConfiguration)
|
||||
})
|
||||
|
||||
it('should not throw on valid field', async () => {
|
||||
const collectionConfig: CollectionConfig = {
|
||||
...defaultCollection,
|
||||
admin: {
|
||||
useAsTitle: 'title',
|
||||
},
|
||||
}
|
||||
await expect(async () => {
|
||||
await sanitizeCollection(
|
||||
// @ts-expect-error
|
||||
{
|
||||
...config,
|
||||
collections: [collectionConfig],
|
||||
},
|
||||
collectionConfig,
|
||||
)
|
||||
}).not.toThrow()
|
||||
})
|
||||
|
||||
it('should not throw on valid field inside tabs', async () => {
|
||||
const collectionConfig: CollectionConfig = {
|
||||
...defaultCollection,
|
||||
admin: {
|
||||
useAsTitle: 'title',
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
type: 'tabs',
|
||||
tabs: [
|
||||
{
|
||||
label: 'General',
|
||||
fields: [
|
||||
{
|
||||
name: 'title',
|
||||
type: 'text',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
}
|
||||
await expect(async () => {
|
||||
await sanitizeCollection(
|
||||
// @ts-expect-error
|
||||
{
|
||||
...config,
|
||||
collections: [collectionConfig],
|
||||
},
|
||||
collectionConfig,
|
||||
)
|
||||
}).not.toThrow()
|
||||
})
|
||||
|
||||
it('should not throw on valid field inside collapsibles', async () => {
|
||||
const collectionConfig: CollectionConfig = {
|
||||
...defaultCollection,
|
||||
admin: {
|
||||
useAsTitle: 'title',
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
type: 'collapsible',
|
||||
label: 'Collapsible',
|
||||
fields: [
|
||||
{
|
||||
name: 'title',
|
||||
type: 'text',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
}
|
||||
await expect(async () => {
|
||||
await sanitizeCollection(
|
||||
// @ts-expect-error
|
||||
{
|
||||
...config,
|
||||
collections: [collectionConfig],
|
||||
},
|
||||
collectionConfig,
|
||||
)
|
||||
}).not.toThrow()
|
||||
})
|
||||
|
||||
it('should throw on nested useAsTitle', async () => {
|
||||
const collectionConfig: CollectionConfig = {
|
||||
...defaultCollection,
|
||||
admin: {
|
||||
useAsTitle: 'content.title',
|
||||
},
|
||||
}
|
||||
await expect(async () => {
|
||||
await sanitizeCollection(
|
||||
// @ts-expect-error
|
||||
{
|
||||
...config,
|
||||
collections: [collectionConfig],
|
||||
},
|
||||
collectionConfig,
|
||||
)
|
||||
}).rejects.toThrow(InvalidConfiguration)
|
||||
})
|
||||
|
||||
it('should not throw on default field: id', async () => {
|
||||
const collectionConfig: CollectionConfig = {
|
||||
...defaultCollection,
|
||||
admin: {
|
||||
useAsTitle: 'id',
|
||||
},
|
||||
}
|
||||
await expect(async () => {
|
||||
await sanitizeCollection(
|
||||
// @ts-expect-error
|
||||
{
|
||||
...config,
|
||||
collections: [collectionConfig],
|
||||
},
|
||||
collectionConfig,
|
||||
)
|
||||
}).not.toThrow()
|
||||
})
|
||||
|
||||
it('should not throw on default field: email if auth is enabled', async () => {
|
||||
const collectionConfig: CollectionConfig = {
|
||||
...defaultCollection,
|
||||
auth: true,
|
||||
admin: {
|
||||
useAsTitle: 'email',
|
||||
},
|
||||
}
|
||||
await expect(async () => {
|
||||
await sanitizeCollection(
|
||||
// @ts-expect-error
|
||||
{
|
||||
...config,
|
||||
collections: [collectionConfig],
|
||||
},
|
||||
collectionConfig,
|
||||
)
|
||||
}).not.toThrow()
|
||||
})
|
||||
it('should throw on default field: email if auth is not enabled', async () => {
|
||||
const collectionConfig: CollectionConfig = {
|
||||
...defaultCollection,
|
||||
admin: {
|
||||
useAsTitle: 'email',
|
||||
},
|
||||
}
|
||||
await expect(async () => {
|
||||
await sanitizeCollection(
|
||||
// @ts-expect-error
|
||||
{
|
||||
...config,
|
||||
collections: [collectionConfig],
|
||||
},
|
||||
collectionConfig,
|
||||
)
|
||||
}).rejects.toThrow(InvalidConfiguration)
|
||||
})
|
||||
})
|
||||
})
|
||||
43
packages/payload/src/collections/config/useAsTitle.ts
Normal file
43
packages/payload/src/collections/config/useAsTitle.ts
Normal file
@@ -0,0 +1,43 @@
|
||||
import type { CollectionConfig } from '../../index.js'
|
||||
|
||||
import { InvalidConfiguration } from '../../errors/InvalidConfiguration.js'
|
||||
import { fieldAffectsData } from '../../fields/config/types.js'
|
||||
import flattenFields from '../../utilities/flattenTopLevelFields.js'
|
||||
|
||||
/**
|
||||
* Validate useAsTitle for collections.
|
||||
*/
|
||||
export const validateUseAsTitle = (config: CollectionConfig) => {
|
||||
if (config.admin.useAsTitle.includes('.')) {
|
||||
throw new InvalidConfiguration(
|
||||
`"useAsTitle" cannot be a nested field. Please specify a top-level field in the collection "${config.slug}"`,
|
||||
)
|
||||
}
|
||||
|
||||
if (config?.admin && config.admin?.useAsTitle && config.admin.useAsTitle !== 'id') {
|
||||
const fields = flattenFields(config.fields)
|
||||
const useAsTitleField = fields.find((field) => {
|
||||
if (fieldAffectsData(field) && config.admin) {
|
||||
return field.name === config.admin.useAsTitle
|
||||
}
|
||||
return false
|
||||
})
|
||||
|
||||
// If auth is enabled then we don't need to
|
||||
if (config.auth) {
|
||||
if (config.admin.useAsTitle !== 'email') {
|
||||
if (!useAsTitleField) {
|
||||
throw new InvalidConfiguration(
|
||||
`The field "${config.admin.useAsTitle}" specified in "admin.useAsTitle" does not exist in the collection "${config.slug}"`,
|
||||
)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!useAsTitleField) {
|
||||
throw new InvalidConfiguration(
|
||||
`The field "${config.admin.useAsTitle}" specified in "admin.useAsTitle" does not exist in the collection "${config.slug}"`,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -136,8 +136,8 @@ const batchAndLoadDocs =
|
||||
depth,
|
||||
docID: doc.id,
|
||||
draft,
|
||||
fallbackLocale: req.fallbackLocale,
|
||||
locale: req.locale,
|
||||
fallbackLocale,
|
||||
locale,
|
||||
overrideAccess,
|
||||
showHiddenFields,
|
||||
transactionID: req.transactionID,
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
import ObjectIdImport from 'bson-objectid'
|
||||
|
||||
import type { FieldHook } from '../config/types.js'
|
||||
|
||||
const ObjectId = (ObjectIdImport.default ||
|
||||
ObjectIdImport) as unknown as typeof ObjectIdImport.default
|
||||
/**
|
||||
* Arrays and Blocks need to clear ids beforeDuplicate
|
||||
*/
|
||||
export const baseBeforeDuplicateArrays: FieldHook = ({ value }) => {
|
||||
if (value) {
|
||||
value = value.map((item) => {
|
||||
item.id = new ObjectId().toHexString()
|
||||
return item
|
||||
})
|
||||
return value
|
||||
}
|
||||
}
|
||||
@@ -12,6 +12,7 @@ import {
|
||||
} from '../../errors/index.js'
|
||||
import { MissingEditorProp } from '../../errors/MissingEditorProp.js'
|
||||
import { formatLabels, toWords } from '../../utilities/formatLabels.js'
|
||||
import { baseBeforeDuplicateArrays } from '../baseFields/baseBeforeDuplicateArrays.js'
|
||||
import { baseBlockFields } from '../baseFields/baseBlockFields.js'
|
||||
import { baseIDField } from '../baseFields/baseIDField.js'
|
||||
import { setDefaultBeforeDuplicate } from '../setDefaultBeforeDuplicate.js'
|
||||
@@ -130,6 +131,15 @@ export const sanitizeFields = async ({
|
||||
|
||||
if (field.type === 'array' && field.fields) {
|
||||
field.fields.push(baseIDField)
|
||||
if (field.localized) {
|
||||
if (!field.hooks) {
|
||||
field.hooks = {}
|
||||
}
|
||||
if (!field.hooks.beforeDuplicate) {
|
||||
field.hooks.beforeDuplicate = []
|
||||
}
|
||||
field.hooks.beforeDuplicate.push(baseBeforeDuplicateArrays)
|
||||
}
|
||||
}
|
||||
|
||||
if ((field.type === 'blocks' || field.type === 'array') && field.label) {
|
||||
@@ -210,6 +220,15 @@ export const sanitizeFields = async ({
|
||||
}
|
||||
|
||||
if (field.type === 'blocks' && field.blocks) {
|
||||
if (field.localized) {
|
||||
if (!field.hooks) {
|
||||
field.hooks = {}
|
||||
}
|
||||
if (!field.hooks.beforeDuplicate) {
|
||||
field.hooks.beforeDuplicate = []
|
||||
}
|
||||
field.hooks.beforeDuplicate.push(baseBeforeDuplicateArrays)
|
||||
}
|
||||
for (const block of field.blocks) {
|
||||
if (block._sanitized === true) {
|
||||
continue
|
||||
|
||||
@@ -7,92 +7,92 @@ import type { DeepUndefinable } from 'ts-essentials'
|
||||
|
||||
import type { RichTextAdapter, RichTextAdapterProvider } from '../../admin/RichText.js'
|
||||
import type {
|
||||
ArrayFieldClientProps,
|
||||
ArrayFieldErrorClientComponent,
|
||||
ArrayFieldErrorServerComponent,
|
||||
ArrayFieldLabelClientComponent,
|
||||
ArrayFieldLabelServerComponent,
|
||||
ArrayFieldProps,
|
||||
BlockFieldErrorClientComponent,
|
||||
BlockFieldErrorServerComponent,
|
||||
BlockFieldProps,
|
||||
BlocksFieldClientProps,
|
||||
CheckboxFieldClientProps,
|
||||
CheckboxFieldErrorClientComponent,
|
||||
CheckboxFieldErrorServerComponent,
|
||||
CheckboxFieldLabelClientComponent,
|
||||
CheckboxFieldLabelServerComponent,
|
||||
CheckboxFieldProps,
|
||||
ClientTab,
|
||||
CodeFieldClientProps,
|
||||
CodeFieldErrorClientComponent,
|
||||
CodeFieldErrorServerComponent,
|
||||
CodeFieldLabelClientComponent,
|
||||
CodeFieldLabelServerComponent,
|
||||
CodeFieldProps,
|
||||
CollapsibleFieldClientProps,
|
||||
CollapsibleFieldLabelClientComponent,
|
||||
CollapsibleFieldLabelServerComponent,
|
||||
CollapsibleFieldProps,
|
||||
ConditionalDateProps,
|
||||
DateFieldClientProps,
|
||||
DateFieldErrorClientComponent,
|
||||
DateFieldErrorServerComponent,
|
||||
DateFieldLabelClientComponent,
|
||||
DateFieldLabelServerComponent,
|
||||
DateFieldProps,
|
||||
Description,
|
||||
EmailFieldClientProps,
|
||||
EmailFieldErrorClientComponent,
|
||||
EmailFieldErrorServerComponent,
|
||||
EmailFieldLabelClientComponent,
|
||||
EmailFieldLabelServerComponent,
|
||||
EmailFieldProps,
|
||||
FieldDescriptionClientComponent,
|
||||
FieldDescriptionServerComponent,
|
||||
GroupFieldClientProps,
|
||||
GroupFieldLabelClientComponent,
|
||||
GroupFieldLabelServerComponent,
|
||||
GroupFieldProps,
|
||||
HiddenFieldProps,
|
||||
JSONFieldClientProps,
|
||||
JSONFieldErrorClientComponent,
|
||||
JSONFieldErrorServerComponent,
|
||||
JSONFieldLabelClientComponent,
|
||||
JSONFieldLabelServerComponent,
|
||||
JSONFieldProps,
|
||||
MappedComponent,
|
||||
NumberFieldClientProps,
|
||||
NumberFieldErrorClientComponent,
|
||||
NumberFieldErrorServerComponent,
|
||||
NumberFieldLabelClientComponent,
|
||||
NumberFieldLabelServerComponent,
|
||||
NumberFieldProps,
|
||||
PointFieldClientProps,
|
||||
PointFieldErrorClientComponent,
|
||||
PointFieldErrorServerComponent,
|
||||
PointFieldLabelClientComponent,
|
||||
PointFieldLabelServerComponent,
|
||||
PointFieldProps,
|
||||
RadioFieldClientProps,
|
||||
RadioFieldErrorClientComponent,
|
||||
RadioFieldErrorServerComponent,
|
||||
RadioFieldLabelClientComponent,
|
||||
RadioFieldLabelServerComponent,
|
||||
RadioFieldProps,
|
||||
RelationshipFieldClientProps,
|
||||
RelationshipFieldErrorClientComponent,
|
||||
RelationshipFieldErrorServerComponent,
|
||||
RelationshipFieldLabelClientComponent,
|
||||
RelationshipFieldLabelServerComponent,
|
||||
RelationshipFieldProps,
|
||||
RichTextFieldProps,
|
||||
RowFieldProps,
|
||||
RichTextFieldClientProps,
|
||||
RowFieldClientProps,
|
||||
RowLabelComponent,
|
||||
SelectFieldClientProps,
|
||||
SelectFieldErrorClientComponent,
|
||||
SelectFieldErrorServerComponent,
|
||||
SelectFieldLabelClientComponent,
|
||||
SelectFieldLabelServerComponent,
|
||||
SelectFieldProps,
|
||||
StaticDescription,
|
||||
TabsFieldProps,
|
||||
TabsFieldClientProps,
|
||||
TextareaFieldClientProps,
|
||||
TextareaFieldErrorClientComponent,
|
||||
TextareaFieldErrorServerComponent,
|
||||
TextareaFieldLabelClientComponent,
|
||||
TextareaFieldLabelServerComponent,
|
||||
TextareaFieldProps,
|
||||
TextFieldErrorClientComponent,
|
||||
TextFieldErrorServerComponent,
|
||||
TextFieldLabelClientComponent,
|
||||
TextFieldLabelServerComponent,
|
||||
UploadFieldProps,
|
||||
UploadFieldClientProps,
|
||||
} from '../../admin/types.js'
|
||||
import type { SanitizedCollectionConfig, TypeWithID } from '../../collections/config/types.js'
|
||||
import type {
|
||||
@@ -1425,26 +1425,26 @@ export type ClientField =
|
||||
| UploadFieldClient
|
||||
|
||||
export type ClientFieldProps =
|
||||
| ArrayFieldProps
|
||||
| BlockFieldProps
|
||||
| CheckboxFieldProps
|
||||
| CodeFieldProps
|
||||
| CollapsibleFieldProps
|
||||
| DateFieldProps
|
||||
| EmailFieldProps
|
||||
| GroupFieldProps
|
||||
| ArrayFieldClientProps
|
||||
| BlocksFieldClientProps
|
||||
| CheckboxFieldClientProps
|
||||
| CodeFieldClientProps
|
||||
| CollapsibleFieldClientProps
|
||||
| DateFieldClientProps
|
||||
| EmailFieldClientProps
|
||||
| GroupFieldClientProps
|
||||
| HiddenFieldProps
|
||||
| JSONFieldProps
|
||||
| NumberFieldProps
|
||||
| PointFieldProps
|
||||
| RadioFieldProps
|
||||
| RelationshipFieldProps
|
||||
| RichTextFieldProps
|
||||
| RowFieldProps
|
||||
| SelectFieldProps
|
||||
| TabsFieldProps
|
||||
| TextareaFieldProps
|
||||
| UploadFieldProps
|
||||
| JSONFieldClientProps
|
||||
| NumberFieldClientProps
|
||||
| PointFieldClientProps
|
||||
| RadioFieldClientProps
|
||||
| RelationshipFieldClientProps
|
||||
| RichTextFieldClientProps
|
||||
| RowFieldClientProps
|
||||
| SelectFieldClientProps
|
||||
| TabsFieldClientProps
|
||||
| TextareaFieldClientProps
|
||||
| UploadFieldClientProps
|
||||
|
||||
type ExtractFieldTypes<T> = T extends { type: infer U } ? U : never
|
||||
|
||||
|
||||
@@ -1,15 +1,12 @@
|
||||
import type { Document, Where } from '../../types/index.js'
|
||||
import type { PreferenceRequest } from '../types.js'
|
||||
|
||||
import defaultAccess from '../../auth/defaultAccess.js'
|
||||
import executeAccess from '../../auth/executeAccess.js'
|
||||
import { NotFound } from '../../errors/NotFound.js'
|
||||
import { UnauthorizedError } from '../../errors/UnathorizedError.js'
|
||||
|
||||
async function deleteOperation(args: PreferenceRequest): Promise<Document> {
|
||||
export async function deleteOperation(args: PreferenceRequest): Promise<Document> {
|
||||
const {
|
||||
key,
|
||||
overrideAccess,
|
||||
req: { payload },
|
||||
req,
|
||||
user,
|
||||
@@ -19,10 +16,6 @@ async function deleteOperation(args: PreferenceRequest): Promise<Document> {
|
||||
throw new UnauthorizedError(req.t)
|
||||
}
|
||||
|
||||
if (!overrideAccess) {
|
||||
await executeAccess({ req }, defaultAccess)
|
||||
}
|
||||
|
||||
const where: Where = {
|
||||
and: [
|
||||
{ key: { equals: key } },
|
||||
@@ -42,5 +35,3 @@ async function deleteOperation(args: PreferenceRequest): Promise<Document> {
|
||||
}
|
||||
throw new NotFound(req.t)
|
||||
}
|
||||
|
||||
export default deleteOperation
|
||||
|
||||
@@ -2,7 +2,7 @@ import type { TypedCollection } from '../../index.js'
|
||||
import type { Where } from '../../types/index.js'
|
||||
import type { PreferenceRequest } from '../types.js'
|
||||
|
||||
async function findOne(args: PreferenceRequest): Promise<TypedCollection['_preference']> {
|
||||
export async function findOne(args: PreferenceRequest): Promise<TypedCollection['_preference']> {
|
||||
const {
|
||||
key,
|
||||
req: { payload },
|
||||
@@ -22,11 +22,14 @@ async function findOne(args: PreferenceRequest): Promise<TypedCollection['_prefe
|
||||
],
|
||||
}
|
||||
|
||||
return await payload.db.findOne({
|
||||
const { docs } = await payload.db.find({
|
||||
collection: 'payload-preferences',
|
||||
limit: 1,
|
||||
pagination: false,
|
||||
req,
|
||||
sort: '-updatedAt',
|
||||
where,
|
||||
})
|
||||
}
|
||||
|
||||
export default findOne
|
||||
return docs?.[0] || null
|
||||
}
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
import type { Where } from '../../types/index.js'
|
||||
import type { PreferenceUpdateRequest } from '../types.js'
|
||||
|
||||
import defaultAccess from '../../auth/defaultAccess.js'
|
||||
import executeAccess from '../../auth/executeAccess.js'
|
||||
import { UnauthorizedError } from '../../errors/UnathorizedError.js'
|
||||
|
||||
async function update(args: PreferenceUpdateRequest) {
|
||||
export async function update(args: PreferenceUpdateRequest) {
|
||||
const {
|
||||
key,
|
||||
overrideAccess,
|
||||
req: { payload },
|
||||
req,
|
||||
user,
|
||||
@@ -20,10 +18,12 @@ async function update(args: PreferenceUpdateRequest) {
|
||||
|
||||
const collection = 'payload-preferences'
|
||||
|
||||
const filter = {
|
||||
key: { equals: key },
|
||||
'user.relationTo': { equals: user.collection },
|
||||
'user.value': { equals: user.id },
|
||||
const where: Where = {
|
||||
and: [
|
||||
{ key: { equals: key } },
|
||||
{ 'user.value': { equals: user.id } },
|
||||
{ 'user.relationTo': { equals: user.collection } },
|
||||
],
|
||||
}
|
||||
|
||||
const preference = {
|
||||
@@ -35,27 +35,23 @@ async function update(args: PreferenceUpdateRequest) {
|
||||
value,
|
||||
}
|
||||
|
||||
if (!overrideAccess) {
|
||||
await executeAccess({ req }, defaultAccess)
|
||||
}
|
||||
let result
|
||||
|
||||
try {
|
||||
// try/catch because we attempt to update without first reading to check if it exists first to save on db calls
|
||||
await payload.db.updateOne({
|
||||
result = await payload.db.updateOne({
|
||||
collection,
|
||||
data: preference,
|
||||
req,
|
||||
where: filter,
|
||||
where,
|
||||
})
|
||||
} catch (err: unknown) {
|
||||
await payload.db.create({
|
||||
result = await payload.db.create({
|
||||
collection,
|
||||
data: preference,
|
||||
req,
|
||||
})
|
||||
}
|
||||
|
||||
return preference
|
||||
return result
|
||||
}
|
||||
|
||||
export default update
|
||||
|
||||
@@ -3,7 +3,7 @@ import httpStatus from 'http-status'
|
||||
import type { PayloadHandler } from '../../config/types.js'
|
||||
import type { PayloadRequest } from '../../types/index.js'
|
||||
|
||||
import deleteOperation from '../operations/delete.js'
|
||||
import { deleteOperation } from '../operations/delete.js'
|
||||
|
||||
export const deleteHandler: PayloadHandler = async (incomingReq): Promise<Response> => {
|
||||
// We cannot import the addDataAndFileToRequest utility here from the 'next' package because of dependency issues
|
||||
|
||||
@@ -3,7 +3,7 @@ import httpStatus from 'http-status'
|
||||
import type { PayloadHandler } from '../../config/types.js'
|
||||
import type { PayloadRequest } from '../../types/index.js'
|
||||
|
||||
import findOne from '../operations/findOne.js'
|
||||
import { findOne } from '../operations/findOne.js'
|
||||
|
||||
export const findByIDHandler: PayloadHandler = async (incomingReq): Promise<Response> => {
|
||||
// We cannot import the addDataAndFileToRequest utility here from the 'next' package because of dependency issues
|
||||
|
||||
@@ -3,7 +3,7 @@ import httpStatus from 'http-status'
|
||||
import type { PayloadHandler } from '../../config/types.js'
|
||||
import type { PayloadRequest } from '../../types/index.js'
|
||||
|
||||
import update from '../operations/update.js'
|
||||
import { update } from '../operations/update.js'
|
||||
|
||||
export const updateHandler: PayloadHandler = async (incomingReq) => {
|
||||
// We cannot import the addDataAndFileToRequest utility here from the 'next' package because of dependency issues
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/plugin-cloud-storage",
|
||||
"version": "3.0.0-beta.100",
|
||||
"version": "3.0.0-beta.102",
|
||||
"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.100",
|
||||
"version": "3.0.0-beta.102",
|
||||
"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.100",
|
||||
"version": "3.0.0-beta.102",
|
||||
"description": "Form builder plugin for Payload CMS",
|
||||
"keywords": [
|
||||
"payload",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
'use client'
|
||||
|
||||
import type { SelectFieldProps, SelectFieldValidation } from 'payload'
|
||||
import type { SelectFieldClientProps, SelectFieldValidation } from 'payload'
|
||||
|
||||
import { SelectField, useForm } from '@payloadcms/ui'
|
||||
import React, { useEffect, useState } from 'react'
|
||||
@@ -8,7 +8,7 @@ import React, { useEffect, useState } from 'react'
|
||||
import type { SelectFieldOption } from '../../types.js'
|
||||
|
||||
export const DynamicFieldSelector: React.FC<
|
||||
{ validate: SelectFieldValidation } & SelectFieldProps
|
||||
{ validate: SelectFieldValidation } & SelectFieldClientProps
|
||||
> = (props) => {
|
||||
const { fields, getDataByPath } = useForm()
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
'use client'
|
||||
|
||||
import type { Data, TextFieldProps } from 'payload'
|
||||
import type { Data, TextFieldClientComponent } from 'payload'
|
||||
|
||||
import { TextField, useLocale, useWatchForm } from '@payloadcms/ui'
|
||||
import React, { useEffect, useState } from 'react'
|
||||
@@ -10,7 +10,7 @@ type FieldWithID = {
|
||||
name: string
|
||||
}
|
||||
|
||||
export const DynamicPriceSelector: React.FC<TextFieldProps> = (props) => {
|
||||
export const DynamicPriceSelector: TextFieldClientComponent = (props) => {
|
||||
const { field } = props
|
||||
|
||||
const { fields, getData, getDataByPath } = useWatchForm()
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/plugin-nested-docs",
|
||||
"version": "3.0.0-beta.100",
|
||||
"version": "3.0.0-beta.102",
|
||||
"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.100",
|
||||
"version": "3.0.0-beta.102",
|
||||
"description": "Redirects plugin for Payload",
|
||||
"keywords": [
|
||||
"payload",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/plugin-relationship-object-ids",
|
||||
"version": "3.0.0-beta.100",
|
||||
"version": "3.0.0-beta.102",
|
||||
"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.100",
|
||||
"version": "3.0.0-beta.102",
|
||||
"description": "Search plugin for Payload",
|
||||
"keywords": [
|
||||
"payload",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/plugin-seo",
|
||||
"version": "3.0.0-beta.100",
|
||||
"version": "3.0.0-beta.102",
|
||||
"description": "SEO plugin for Payload",
|
||||
"keywords": [
|
||||
"payload",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
'use client'
|
||||
|
||||
import type { FieldType, Options } from '@payloadcms/ui'
|
||||
import type { TextareaFieldProps } from 'payload'
|
||||
import type { TextareaFieldClientProps } from 'payload'
|
||||
|
||||
import {
|
||||
FieldLabel,
|
||||
@@ -25,7 +25,7 @@ const { maxLength, minLength } = defaults.description
|
||||
|
||||
type MetaDescriptionProps = {
|
||||
readonly hasGenerateDescriptionFn: boolean
|
||||
} & TextareaFieldProps
|
||||
} & TextareaFieldClientProps
|
||||
|
||||
export const MetaDescriptionComponent: React.FC<MetaDescriptionProps> = (props) => {
|
||||
const {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
'use client'
|
||||
|
||||
import type { FieldType, Options } from '@payloadcms/ui'
|
||||
import type { UploadFieldProps } from 'payload'
|
||||
import type { UploadFieldClientProps } from 'payload'
|
||||
|
||||
import {
|
||||
FieldLabel,
|
||||
@@ -23,7 +23,7 @@ import { Pill } from '../../ui/Pill.js'
|
||||
|
||||
type MetaImageProps = {
|
||||
readonly hasGenerateImageFn: boolean
|
||||
} & UploadFieldProps
|
||||
} & UploadFieldClientProps
|
||||
|
||||
export const MetaImageComponent: React.FC<MetaImageProps> = (props) => {
|
||||
const {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
'use client'
|
||||
|
||||
import type { FieldType, Options } from '@payloadcms/ui'
|
||||
import type { TextFieldProps } from 'payload'
|
||||
import type { TextFieldClientProps } from 'payload'
|
||||
|
||||
import {
|
||||
FieldLabel,
|
||||
@@ -26,7 +26,7 @@ const { maxLength, minLength } = defaults.title
|
||||
|
||||
type MetaTitleProps = {
|
||||
readonly hasGenerateTitleFn: boolean
|
||||
} & TextFieldProps
|
||||
} & TextFieldClientProps
|
||||
|
||||
export const MetaTitleComponent: React.FC<MetaTitleProps> = (props) => {
|
||||
const {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/plugin-stripe",
|
||||
"version": "3.0.0-beta.100",
|
||||
"version": "3.0.0-beta.102",
|
||||
"description": "Stripe plugin for Payload",
|
||||
"keywords": [
|
||||
"payload",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/richtext-lexical",
|
||||
"version": "3.0.0-beta.100",
|
||||
"version": "3.0.0-beta.102",
|
||||
"description": "The officially supported Lexical richtext adapter for Payload",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
|
||||
@@ -82,7 +82,7 @@
|
||||
}
|
||||
|
||||
&__indent {
|
||||
--lexical-indent-base-value: base(2);
|
||||
--lexical-indent-base-value: 40px;
|
||||
}
|
||||
|
||||
&__textBold {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { EditorConfig as LexicalEditorConfig, SerializedEditorState } from 'lexical'
|
||||
import type { RichTextAdapter, RichTextFieldProps, SanitizedConfig } from 'payload'
|
||||
import type { RichTextAdapter, RichTextFieldClientProps, SanitizedConfig } from 'payload'
|
||||
|
||||
import type {
|
||||
BaseClientFeatureProps,
|
||||
@@ -74,7 +74,7 @@ export type LexicalRichTextAdapterProvider =
|
||||
export type LexicalRichTextFieldProps = {
|
||||
admin: LexicalFieldAdminProps
|
||||
lexicalEditorConfig: LexicalEditorConfig
|
||||
} & RichTextFieldProps<SerializedEditorState, AdapterProps, object>
|
||||
} & RichTextFieldClientProps<SerializedEditorState, AdapterProps, object>
|
||||
|
||||
export type AdapterProps = {
|
||||
editorConfig: SanitizedServerEditorConfig
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/richtext-slate",
|
||||
"version": "3.0.0-beta.100",
|
||||
"version": "3.0.0-beta.102",
|
||||
"description": "The officially supported Slate richtext adapter for Payload",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { Field, PayloadComponent, RichTextFieldProps, SanitizedConfig } from 'payload'
|
||||
import type { Field, PayloadComponent, RichTextFieldClientProps, SanitizedConfig } from 'payload'
|
||||
import type { Editor } from 'slate'
|
||||
|
||||
export type TextNode = { [x: string]: unknown; text: string }
|
||||
@@ -70,4 +70,4 @@ export type AdapterArguments = {
|
||||
}
|
||||
}
|
||||
|
||||
export type SlateFieldProps = RichTextFieldProps<any[], AdapterArguments, AdapterArguments>
|
||||
export type SlateFieldProps = RichTextFieldClientProps<any[], AdapterArguments, AdapterArguments>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/storage-azure",
|
||||
"version": "3.0.0-beta.100",
|
||||
"version": "3.0.0-beta.102",
|
||||
"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.100",
|
||||
"version": "3.0.0-beta.102",
|
||||
"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.100",
|
||||
"version": "3.0.0-beta.102",
|
||||
"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.100",
|
||||
"version": "3.0.0-beta.102",
|
||||
"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.100",
|
||||
"version": "3.0.0-beta.102",
|
||||
"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.100",
|
||||
"version": "3.0.0-beta.102",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/ui",
|
||||
"version": "3.0.0-beta.100",
|
||||
"version": "3.0.0-beta.102",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
@@ -82,12 +82,12 @@
|
||||
background-color: var(--theme-elevation-100);
|
||||
}
|
||||
|
||||
img {
|
||||
width: 25px;
|
||||
height: 25px;
|
||||
.thumbnail {
|
||||
width: base(1.2);
|
||||
height: base(1.2);
|
||||
flex-shrink: 0;
|
||||
object-fit: cover;
|
||||
border-radius: var(--style-radius-m);
|
||||
border-radius: var(--style-radius-s);
|
||||
}
|
||||
|
||||
p {
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
import { useModal } from '@faceless-ui/modal'
|
||||
import { useWindowInfo } from '@faceless-ui/window-info'
|
||||
import { isImage } from 'payload/shared'
|
||||
import React from 'react'
|
||||
import AnimateHeightImport from 'react-animate-height'
|
||||
|
||||
@@ -13,6 +14,7 @@ import { Drawer } from '../../Drawer/index.js'
|
||||
import { ErrorPill } from '../../ErrorPill/index.js'
|
||||
import { Pill } from '../../Pill/index.js'
|
||||
import { ShimmerEffect } from '../../ShimmerEffect/index.js'
|
||||
import { Thumbnail } from '../../Thumbnail/index.js'
|
||||
import { Actions } from '../ActionsBar/index.js'
|
||||
import { AddFilesView } from '../AddFilesView/index.js'
|
||||
import { useFormsManager } from '../FormsManager/index.js'
|
||||
@@ -144,7 +146,12 @@ export function FileSidebar() {
|
||||
onClick={() => setActiveIndex(index)}
|
||||
type="button"
|
||||
>
|
||||
<img alt={currentFile.name} src={URL.createObjectURL(currentFile)} />
|
||||
<Thumbnail
|
||||
className={`${baseClass}__thumbnail`}
|
||||
fileSrc={
|
||||
isImage(currentFile.type) ? URL.createObjectURL(currentFile) : undefined
|
||||
}
|
||||
/>
|
||||
<div className={`${baseClass}__fileDetails`}>
|
||||
<p className={`${baseClass}__fileName`} title={currentFile.name}>
|
||||
{currentFile.name}
|
||||
|
||||
@@ -14,7 +14,6 @@ import { ChevronIcon } from '../../icons/Chevron/index.js'
|
||||
import { SearchIcon } from '../../icons/Search/index.js'
|
||||
import { useListInfo } from '../../providers/ListInfo/index.js'
|
||||
import { useListQuery } from '../../providers/ListQuery/index.js'
|
||||
import { useSearchParams } from '../../providers/SearchParams/index.js'
|
||||
import { useTranslation } from '../../providers/Translation/index.js'
|
||||
import { ColumnSelector } from '../ColumnSelector/index.js'
|
||||
import { DeleteMany } from '../DeleteMany/index.js'
|
||||
@@ -48,17 +47,13 @@ export type ListControlsProps = {
|
||||
export const ListControls: React.FC<ListControlsProps> = (props) => {
|
||||
const { collectionConfig, enableColumns = true, enableSort = false, fields } = props
|
||||
|
||||
const { handleSearchChange } = useListQuery()
|
||||
const { handleSearchChange, params } = useListQuery()
|
||||
const { beforeActions, collectionSlug, disableBulkDelete, disableBulkEdit } = useListInfo()
|
||||
const { searchParams } = useSearchParams()
|
||||
const titleField = useUseTitleField(collectionConfig, fields)
|
||||
const { i18n, t } = useTranslation()
|
||||
const {
|
||||
breakpoints: { s: smallBreak },
|
||||
} = useWindowInfo()
|
||||
const [search, setSearch] = useState(
|
||||
typeof searchParams?.search === 'string' ? searchParams?.search : '',
|
||||
)
|
||||
|
||||
const searchLabel =
|
||||
(titleField &&
|
||||
@@ -81,21 +76,21 @@ export const ListControls: React.FC<ListControlsProps> = (props) => {
|
||||
t('general:searchBy', { label: getTranslation(searchLabel, i18n) }),
|
||||
)
|
||||
|
||||
const hasWhereParam = useRef(Boolean(searchParams?.where))
|
||||
const hasWhereParam = useRef(Boolean(params?.where))
|
||||
|
||||
const shouldInitializeWhereOpened = validateWhereQuery(searchParams?.where)
|
||||
const shouldInitializeWhereOpened = validateWhereQuery(params?.where)
|
||||
const [visibleDrawer, setVisibleDrawer] = useState<'columns' | 'sort' | 'where'>(
|
||||
shouldInitializeWhereOpened ? 'where' : undefined,
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
if (hasWhereParam.current && !searchParams?.where) {
|
||||
if (hasWhereParam.current && !params?.where) {
|
||||
setVisibleDrawer(undefined)
|
||||
hasWhereParam.current = false
|
||||
} else if (searchParams?.where) {
|
||||
} else if (params?.where) {
|
||||
hasWhereParam.current = true
|
||||
}
|
||||
}, [setVisibleDrawer, searchParams?.where])
|
||||
}, [setVisibleDrawer, params?.where])
|
||||
|
||||
useEffect(() => {
|
||||
if (listSearchableFields?.length > 0) {
|
||||
@@ -134,11 +129,10 @@ export const ListControls: React.FC<ListControlsProps> = (props) => {
|
||||
handleChange={(search) => {
|
||||
return void handleSearchChange(search)
|
||||
}}
|
||||
initialParams={searchParams}
|
||||
// @ts-expect-error @todo: fix types
|
||||
initialParams={params}
|
||||
key={collectionSlug}
|
||||
label={searchLabelTranslated.current}
|
||||
setValue={setSearch}
|
||||
value={search}
|
||||
/>
|
||||
<div className={`${baseClass}__buttons`}>
|
||||
<div className={`${baseClass}__buttons-wrap`}>
|
||||
@@ -216,7 +210,7 @@ export const ListControls: React.FC<ListControlsProps> = (props) => {
|
||||
collectionPluralLabel={collectionConfig?.labels?.plural}
|
||||
collectionSlug={collectionConfig.slug}
|
||||
fields={fields}
|
||||
key={String(hasWhereParam.current && !searchParams?.where)}
|
||||
key={String(hasWhereParam.current && !params?.where)}
|
||||
/>
|
||||
</AnimateHeight>
|
||||
{enableSort && (
|
||||
|
||||
@@ -3,13 +3,14 @@ import type { ClientCollectionConfig, Where } from 'payload'
|
||||
|
||||
import { useModal } from '@faceless-ui/modal'
|
||||
import { getTranslation } from '@payloadcms/translations'
|
||||
import React, { useCallback, useEffect, useReducer, useState } from 'react'
|
||||
import React, { useCallback, useEffect, useReducer, useRef, useState } from 'react'
|
||||
|
||||
import type { ListDrawerProps } from './types.js'
|
||||
|
||||
import { SelectMany } from '../../elements/SelectMany/index.js'
|
||||
import { FieldLabel } from '../../fields/FieldLabel/index.js'
|
||||
import { usePayloadAPI } from '../../hooks/usePayloadAPI.js'
|
||||
import { useThrottledEffect } from '../../hooks/useThrottledEffect.js'
|
||||
import { XIcon } from '../../icons/X/index.js'
|
||||
import { useAuth } from '../../providers/Auth/index.js'
|
||||
import { useConfig } from '../../providers/Config/index.js'
|
||||
@@ -54,13 +55,25 @@ export const ListDrawerContent: React.FC<ListDrawerProps> = ({
|
||||
}) => {
|
||||
const { i18n, t } = useTranslation()
|
||||
const { permissions } = useAuth()
|
||||
const { setPreference } = usePreferences()
|
||||
const { getPreference, setPreference } = usePreferences()
|
||||
const { closeModal, isModalOpen } = useModal()
|
||||
const [limit, setLimit] = useState<number>()
|
||||
// Track the page limit so we can reset the page number when it changes
|
||||
const previousLimit = useRef<number>(limit || null)
|
||||
const [sort, setSort] = useState<string>(null)
|
||||
const [page, setPage] = useState<number>(1)
|
||||
const [where, setWhere] = useState<Where>(null)
|
||||
const [search, setSearch] = useState<string>('')
|
||||
const [showLoadingOverlay, setShowLoadingOverlay] = useState<boolean>(true)
|
||||
const hasInitialised = useRef(false)
|
||||
|
||||
const params = {
|
||||
limit,
|
||||
page,
|
||||
search,
|
||||
sort,
|
||||
where,
|
||||
}
|
||||
|
||||
const {
|
||||
config: {
|
||||
@@ -94,12 +107,6 @@ export const ListDrawerContent: React.FC<ListDrawerProps> = ({
|
||||
: undefined,
|
||||
)
|
||||
|
||||
// const [fields, setFields] = useState<Field[]>(() => formatFields(selectedCollectionConfig))
|
||||
|
||||
useEffect(() => {
|
||||
// setFields(formatFields(selectedCollectionConfig))
|
||||
}, [selectedCollectionConfig])
|
||||
|
||||
// allow external control of selected collection, same as the initial state logic above
|
||||
useEffect(() => {
|
||||
if (selectedCollection) {
|
||||
@@ -111,7 +118,7 @@ export const ListDrawerContent: React.FC<ListDrawerProps> = ({
|
||||
}
|
||||
}, [selectedCollection, enabledCollectionConfigs, onSelect, t])
|
||||
|
||||
const preferenceKey = `${selectedCollectionConfig.slug}-list`
|
||||
const preferencesKey = `${selectedCollectionConfig.slug}-list`
|
||||
|
||||
// this is the 'create new' drawer
|
||||
const [DocumentDrawer, DocumentDrawerToggler, { drawerSlug: documentDrawerSlug }] =
|
||||
@@ -147,6 +154,7 @@ export const ListDrawerContent: React.FC<ListDrawerProps> = ({
|
||||
admin: { listSearchableFields, useAsTitle } = {},
|
||||
versions,
|
||||
} = selectedCollectionConfig
|
||||
|
||||
const params: {
|
||||
cacheBust?: number
|
||||
depth?: number
|
||||
@@ -194,6 +202,17 @@ export const ListDrawerContent: React.FC<ListDrawerProps> = ({
|
||||
if (cacheBust) {
|
||||
params.cacheBust = cacheBust
|
||||
}
|
||||
if (limit) {
|
||||
params.limit = limit
|
||||
|
||||
if (limit !== previousLimit.current) {
|
||||
previousLimit.current = limit
|
||||
|
||||
// Reset page if limit changes
|
||||
// eslint-disable-next-line @eslint-react/hooks-extra/no-direct-set-state-in-use-effect
|
||||
setPage(1)
|
||||
}
|
||||
}
|
||||
if (copyOfWhere) {
|
||||
params.where = copyOfWhere
|
||||
}
|
||||
@@ -202,7 +221,18 @@ export const ListDrawerContent: React.FC<ListDrawerProps> = ({
|
||||
}
|
||||
|
||||
setParams(params)
|
||||
}, [page, sort, where, search, cacheBust, filterOptions, selectedCollectionConfig, t, setParams])
|
||||
}, [
|
||||
page,
|
||||
sort,
|
||||
where,
|
||||
search,
|
||||
limit,
|
||||
cacheBust,
|
||||
filterOptions,
|
||||
selectedCollectionConfig,
|
||||
t,
|
||||
setParams,
|
||||
])
|
||||
|
||||
useEffect(() => {
|
||||
const newPreferences = {
|
||||
@@ -210,8 +240,49 @@ export const ListDrawerContent: React.FC<ListDrawerProps> = ({
|
||||
sort,
|
||||
}
|
||||
|
||||
void setPreference(preferenceKey, newPreferences, true)
|
||||
}, [sort, limit, setPreference, preferenceKey])
|
||||
if (limit || sort) {
|
||||
void setPreference(preferencesKey, newPreferences, true)
|
||||
}
|
||||
}, [sort, limit, setPreference, preferencesKey])
|
||||
|
||||
// Get existing preferences if they exist
|
||||
useEffect(() => {
|
||||
if (preferencesKey && !limit) {
|
||||
const getInitialPref = async () => {
|
||||
const existingPreferences = await getPreference<{ limit?: number }>(preferencesKey)
|
||||
|
||||
if (existingPreferences?.limit) {
|
||||
setLimit(existingPreferences?.limit)
|
||||
}
|
||||
}
|
||||
void getInitialPref()
|
||||
}
|
||||
}, [getPreference, limit, preferencesKey])
|
||||
|
||||
useThrottledEffect(
|
||||
() => {
|
||||
if (isLoadingList) {
|
||||
setShowLoadingOverlay(true)
|
||||
}
|
||||
},
|
||||
1750,
|
||||
[isLoadingList, setShowLoadingOverlay],
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
if (isOpen) {
|
||||
hasInitialised.current = true
|
||||
} else {
|
||||
hasInitialised.current = false
|
||||
}
|
||||
}, [isOpen])
|
||||
|
||||
useEffect(() => {
|
||||
if (!isLoadingList && showLoadingOverlay) {
|
||||
// eslint-disable-next-line @eslint-react/hooks-extra/no-direct-set-state-in-use-effect
|
||||
setShowLoadingOverlay(false)
|
||||
}
|
||||
}, [isLoadingList, showLoadingOverlay])
|
||||
|
||||
const onCreateNew = useCallback(
|
||||
({ doc }) => {
|
||||
@@ -232,108 +303,111 @@ export const ListDrawerContent: React.FC<ListDrawerProps> = ({
|
||||
return null
|
||||
}
|
||||
|
||||
if (isLoadingList) {
|
||||
return <LoadingOverlay />
|
||||
}
|
||||
|
||||
return (
|
||||
<ListInfoProvider
|
||||
beforeActions={
|
||||
enableRowSelections ? [<SelectMany key="select-many" onClick={onBulkSelect} />] : undefined
|
||||
}
|
||||
collectionConfig={selectedCollectionConfig}
|
||||
collectionSlug={selectedCollectionConfig.slug}
|
||||
disableBulkDelete
|
||||
disableBulkEdit
|
||||
hasCreatePermission={hasCreatePermission}
|
||||
Header={
|
||||
<header className={`${baseClass}__header`}>
|
||||
<div className={`${baseClass}__header-wrap`}>
|
||||
<div className={`${baseClass}__header-content`}>
|
||||
<h2 className={`${baseClass}__header-text`}>
|
||||
{!customHeader
|
||||
? getTranslation(selectedCollectionConfig?.labels?.plural, i18n)
|
||||
: customHeader}
|
||||
</h2>
|
||||
{hasCreatePermission && (
|
||||
<DocumentDrawerToggler className={`${baseClass}__create-new-button`}>
|
||||
<Pill>{t('general:createNew')}</Pill>
|
||||
</DocumentDrawerToggler>
|
||||
)}
|
||||
<>
|
||||
{showLoadingOverlay && <LoadingOverlay />}
|
||||
<ListInfoProvider
|
||||
beforeActions={
|
||||
enableRowSelections
|
||||
? [<SelectMany key="select-many" onClick={onBulkSelect} />]
|
||||
: undefined
|
||||
}
|
||||
collectionConfig={selectedCollectionConfig}
|
||||
collectionSlug={selectedCollectionConfig.slug}
|
||||
disableBulkDelete
|
||||
disableBulkEdit
|
||||
hasCreatePermission={hasCreatePermission}
|
||||
Header={
|
||||
<header className={`${baseClass}__header`}>
|
||||
<div className={`${baseClass}__header-wrap`}>
|
||||
<div className={`${baseClass}__header-content`}>
|
||||
<h2 className={`${baseClass}__header-text`}>
|
||||
{!customHeader
|
||||
? getTranslation(selectedCollectionConfig?.labels?.plural, i18n)
|
||||
: customHeader}
|
||||
</h2>
|
||||
{hasCreatePermission && (
|
||||
<DocumentDrawerToggler className={`${baseClass}__create-new-button`}>
|
||||
<Pill>{t('general:createNew')}</Pill>
|
||||
</DocumentDrawerToggler>
|
||||
)}
|
||||
</div>
|
||||
<button
|
||||
aria-label={t('general:close')}
|
||||
className={`${baseClass}__header-close`}
|
||||
onClick={() => {
|
||||
closeModal(drawerSlug)
|
||||
}}
|
||||
type="button"
|
||||
>
|
||||
<XIcon />
|
||||
</button>
|
||||
</div>
|
||||
<button
|
||||
aria-label={t('general:close')}
|
||||
className={`${baseClass}__header-close`}
|
||||
onClick={() => {
|
||||
closeModal(drawerSlug)
|
||||
}}
|
||||
type="button"
|
||||
>
|
||||
<XIcon />
|
||||
</button>
|
||||
</div>
|
||||
{(selectedCollectionConfig?.admin?.description ||
|
||||
selectedCollectionConfig?.admin?.components?.Description) && (
|
||||
<div className={`${baseClass}__sub-header`}>
|
||||
<ViewDescription
|
||||
Description={selectedCollectionConfig.admin?.components?.Description}
|
||||
description={selectedCollectionConfig.admin?.description}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
{moreThanOneAvailableCollection && (
|
||||
<div className={`${baseClass}__select-collection-wrap`}>
|
||||
<FieldLabel field={null} label={t('upload:selectCollectionToBrowse')} />
|
||||
<ReactSelect
|
||||
className={`${baseClass}__select-collection`}
|
||||
onChange={setSelectedOption} // this is only changing the options which is not rerunning my effect
|
||||
options={enabledCollectionConfigs.map((coll) => ({
|
||||
label: getTranslation(coll.labels.singular, i18n),
|
||||
value: coll.slug,
|
||||
}))}
|
||||
value={selectedOption}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</header>
|
||||
}
|
||||
newDocumentURL={null}
|
||||
>
|
||||
<ListQueryProvider
|
||||
data={data}
|
||||
defaultLimit={limit || selectedCollectionConfig?.admin?.pagination?.defaultLimit}
|
||||
defaultSort={sort}
|
||||
handlePageChange={setPage}
|
||||
handlePerPageChange={setLimit}
|
||||
handleSearchChange={setSearch}
|
||||
handleSortChange={setSort}
|
||||
handleWhereChange={setWhere}
|
||||
modifySearchParams={false}
|
||||
preferenceKey={preferenceKey}
|
||||
{(selectedCollectionConfig?.admin?.description ||
|
||||
selectedCollectionConfig?.admin?.components?.Description) && (
|
||||
<div className={`${baseClass}__sub-header`}>
|
||||
<ViewDescription
|
||||
Description={selectedCollectionConfig.admin?.components?.Description}
|
||||
description={selectedCollectionConfig.admin?.description}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
{moreThanOneAvailableCollection && (
|
||||
<div className={`${baseClass}__select-collection-wrap`}>
|
||||
<FieldLabel field={null} label={t('upload:selectCollectionToBrowse')} />
|
||||
<ReactSelect
|
||||
className={`${baseClass}__select-collection`}
|
||||
onChange={setSelectedOption} // this is only changing the options which is not rerunning my effect
|
||||
options={enabledCollectionConfigs.map((coll) => ({
|
||||
label: getTranslation(coll.labels.singular, i18n),
|
||||
value: coll.slug,
|
||||
}))}
|
||||
value={selectedOption}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</header>
|
||||
}
|
||||
newDocumentURL={null}
|
||||
>
|
||||
<TableColumnsProvider
|
||||
cellProps={[
|
||||
{
|
||||
className: `${baseClass}__first-cell`,
|
||||
link: false,
|
||||
onClick: ({ collectionSlug: rowColl, rowData }) => {
|
||||
if (typeof onSelect === 'function') {
|
||||
onSelect({
|
||||
collectionSlug: rowColl,
|
||||
docID: rowData.id as string,
|
||||
})
|
||||
}
|
||||
},
|
||||
},
|
||||
]}
|
||||
collectionSlug={selectedCollectionConfig.slug}
|
||||
enableRowSelections={enableRowSelections}
|
||||
preferenceKey={preferenceKey}
|
||||
<ListQueryProvider
|
||||
data={data}
|
||||
defaultLimit={limit || selectedCollectionConfig?.admin?.pagination?.defaultLimit}
|
||||
defaultSort={sort}
|
||||
handlePageChange={setPage}
|
||||
handlePerPageChange={setLimit}
|
||||
handleSearchChange={setSearch}
|
||||
handleSortChange={setSort}
|
||||
handleWhereChange={setWhere}
|
||||
modifySearchParams={false}
|
||||
// @ts-expect-error todo: fix types
|
||||
params={params}
|
||||
preferenceKey={preferencesKey}
|
||||
>
|
||||
<RenderComponent mappedComponent={List} />
|
||||
<DocumentDrawer onSave={onCreateNew} />
|
||||
</TableColumnsProvider>
|
||||
</ListQueryProvider>
|
||||
</ListInfoProvider>
|
||||
<TableColumnsProvider
|
||||
cellProps={[
|
||||
{
|
||||
className: `${baseClass}__first-cell`,
|
||||
link: false,
|
||||
onClick: ({ collectionSlug: rowColl, rowData }) => {
|
||||
if (typeof onSelect === 'function') {
|
||||
onSelect({
|
||||
collectionSlug: rowColl,
|
||||
docID: rowData.id as string,
|
||||
})
|
||||
}
|
||||
},
|
||||
},
|
||||
]}
|
||||
collectionSlug={selectedCollectionConfig.slug}
|
||||
enableRowSelections={enableRowSelections}
|
||||
preferenceKey={preferencesKey}
|
||||
>
|
||||
<RenderComponent mappedComponent={List} />
|
||||
<DocumentDrawer onSave={onCreateNew} />
|
||||
</TableColumnsProvider>
|
||||
</ListQueryProvider>
|
||||
</ListInfoProvider>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
'use client'
|
||||
import React, { useEffect, useRef } from 'react'
|
||||
import React, { useEffect, useRef, useState } from 'react'
|
||||
|
||||
export type SearchFilterProps = {
|
||||
fieldName?: string
|
||||
@@ -12,32 +12,53 @@ export type SearchFilterProps = {
|
||||
|
||||
import type { ParsedQs } from 'qs-esm'
|
||||
|
||||
import { usePathname } from 'next/navigation.js'
|
||||
|
||||
import { useDebounce } from '../../hooks/useDebounce.js'
|
||||
import './index.scss'
|
||||
|
||||
const baseClass = 'search-filter'
|
||||
|
||||
export const SearchFilter: React.FC<SearchFilterProps> = (props) => {
|
||||
const { handleChange, initialParams, label, setValue, value } = props
|
||||
|
||||
const previousSearch = useRef(
|
||||
typeof initialParams?.search === 'string' ? initialParams?.search : '',
|
||||
const { handleChange, initialParams, label } = props
|
||||
const pathname = usePathname()
|
||||
const [search, setSearch] = useState(
|
||||
typeof initialParams?.search === 'string' ? initialParams?.search : undefined,
|
||||
)
|
||||
|
||||
const debouncedSearch = useDebounce(value, 300)
|
||||
/**
|
||||
* Tracks whether the state should be updated based on the search value.
|
||||
* If the value is updated from the URL, we don't want to update the state as it causes additional renders.
|
||||
*/
|
||||
const shouldUpdateState = useRef(true)
|
||||
|
||||
/**
|
||||
* Tracks the previous search value to compare with the current debounced search value.
|
||||
*/
|
||||
const previousSearch = useRef(
|
||||
typeof initialParams?.search === 'string' ? initialParams?.search : undefined,
|
||||
)
|
||||
|
||||
const debouncedSearch = useDebounce(search, 300)
|
||||
|
||||
useEffect(() => {
|
||||
if (debouncedSearch !== previousSearch.current) {
|
||||
if (initialParams?.search !== previousSearch.current) {
|
||||
shouldUpdateState.current = false
|
||||
// eslint-disable-next-line @eslint-react/hooks-extra/no-direct-set-state-in-use-effect
|
||||
setSearch(initialParams?.search as string)
|
||||
previousSearch.current = initialParams?.search as string
|
||||
}
|
||||
}, [initialParams?.search, pathname])
|
||||
|
||||
useEffect(() => {
|
||||
if (debouncedSearch !== previousSearch.current && shouldUpdateState.current) {
|
||||
if (handleChange) {
|
||||
handleChange(debouncedSearch)
|
||||
}
|
||||
|
||||
previousSearch.current = debouncedSearch
|
||||
}
|
||||
}, [debouncedSearch, previousSearch, handleChange])
|
||||
|
||||
// Cleans up the search input when the component is unmounted
|
||||
useEffect(() => () => setValue(''), [])
|
||||
}, [debouncedSearch, handleChange])
|
||||
|
||||
return (
|
||||
<div className={baseClass}>
|
||||
@@ -45,10 +66,13 @@ export const SearchFilter: React.FC<SearchFilterProps> = (props) => {
|
||||
aria-label={label}
|
||||
className={`${baseClass}__input`}
|
||||
id="search-filter-input"
|
||||
onChange={(e) => setValue(e.target.value)}
|
||||
onChange={(e) => {
|
||||
shouldUpdateState.current = true
|
||||
setSearch(e.target.value)
|
||||
}}
|
||||
placeholder={label}
|
||||
type="text"
|
||||
value={value || ''}
|
||||
value={search || ''}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -5,7 +5,6 @@ import React from 'react'
|
||||
|
||||
import { ChevronIcon } from '../../icons/Chevron/index.js'
|
||||
import { useListQuery } from '../../providers/ListQuery/index.js'
|
||||
import { useSearchParams } from '../../providers/SearchParams/index.js'
|
||||
import { useTranslation } from '../../providers/Translation/index.js'
|
||||
import './index.scss'
|
||||
|
||||
@@ -20,11 +19,10 @@ const baseClass = 'sort-column'
|
||||
|
||||
export const SortColumn: React.FC<SortColumnProps> = (props) => {
|
||||
const { name, disable = false, Label, label } = props
|
||||
const { searchParams } = useSearchParams()
|
||||
const { handleSortChange } = useListQuery()
|
||||
const { handleSortChange, params } = useListQuery()
|
||||
const { t } = useTranslation()
|
||||
|
||||
const { sort } = searchParams
|
||||
const { sort } = params
|
||||
|
||||
const desc = `-${name}`
|
||||
const asc = name
|
||||
|
||||
@@ -91,6 +91,8 @@
|
||||
|
||||
&__dropzoneContent {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: base(0.4);
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
}
|
||||
@@ -106,6 +108,7 @@
|
||||
}
|
||||
|
||||
&__dragAndDropText {
|
||||
flex-shrink: 0;
|
||||
margin: 0;
|
||||
text-transform: lowercase;
|
||||
align-self: center;
|
||||
|
||||
@@ -7,7 +7,6 @@ import React, { useEffect, useState } from 'react'
|
||||
import type { WhereBuilderProps } from './types.js'
|
||||
|
||||
import { useListQuery } from '../../providers/ListQuery/index.js'
|
||||
import { useSearchParams } from '../../providers/SearchParams/index.js'
|
||||
import { useTranslation } from '../../providers/Translation/index.js'
|
||||
import { Button } from '../Button/index.js'
|
||||
import { Condition } from './Condition/index.js'
|
||||
@@ -31,11 +30,11 @@ export const WhereBuilder: React.FC<WhereBuilderProps> = (props) => {
|
||||
const [reducedFields, setReducedColumns] = useState(() => reduceClientFields({ fields, i18n }))
|
||||
|
||||
useEffect(() => {
|
||||
// eslint-disable-next-line @eslint-react/hooks-extra/no-direct-set-state-in-use-effect
|
||||
setReducedColumns(reduceClientFields({ fields, i18n }))
|
||||
}, [fields, i18n])
|
||||
|
||||
const { searchParams } = useSearchParams()
|
||||
const { handleWhereChange } = useListQuery()
|
||||
const { handleWhereChange, params } = useListQuery()
|
||||
const [shouldUpdateQuery, setShouldUpdateQuery] = React.useState(false)
|
||||
|
||||
// This handles initializing the where conditions from the search query (URL). That way, if you pass in
|
||||
@@ -67,7 +66,7 @@ export const WhereBuilder: React.FC<WhereBuilderProps> = (props) => {
|
||||
*/
|
||||
|
||||
const [conditions, setConditions] = React.useState(() => {
|
||||
const whereFromSearch = searchParams.where
|
||||
const whereFromSearch = params.where
|
||||
if (whereFromSearch) {
|
||||
if (validateWhereQuery(whereFromSearch)) {
|
||||
return whereFromSearch.or
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
'use client'
|
||||
import type { ArrayFieldProps, ArrayField as ArrayFieldType } from 'payload'
|
||||
import type {
|
||||
ArrayFieldClientComponent,
|
||||
ArrayFieldClientProps,
|
||||
ArrayField as ArrayFieldType,
|
||||
} from 'payload'
|
||||
|
||||
import { getTranslation } from '@payloadcms/translations'
|
||||
import React, { useCallback } from 'react'
|
||||
@@ -29,7 +33,7 @@ import './index.scss'
|
||||
|
||||
const baseClass = 'array-field'
|
||||
|
||||
export const ArrayFieldComponent: React.FC<ArrayFieldProps> = (props) => {
|
||||
export const ArrayFieldComponent: ArrayFieldClientComponent = (props) => {
|
||||
const {
|
||||
descriptionProps,
|
||||
errorProps,
|
||||
@@ -88,7 +92,7 @@ export const ArrayFieldComponent: React.FC<ArrayFieldProps> = (props) => {
|
||||
})()
|
||||
|
||||
// Handle labeling for Arrays, Global Arrays, and Blocks
|
||||
const getLabels = (p: ArrayFieldProps): Partial<ArrayFieldType['labels']> => {
|
||||
const getLabels = (p: ArrayFieldClientProps): Partial<ArrayFieldType['labels']> => {
|
||||
if ('labels' in p && p?.labels) {
|
||||
return p.labels
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
'use client'
|
||||
import type { BlockFieldProps } from 'payload'
|
||||
import type { BlocksFieldClientComponent } from 'payload'
|
||||
|
||||
import { getTranslation } from '@payloadcms/translations'
|
||||
import React, { Fragment, useCallback } from 'react'
|
||||
@@ -32,7 +32,7 @@ import './index.scss'
|
||||
|
||||
const baseClass = 'blocks-field'
|
||||
|
||||
const BlocksFieldComponent: React.FC<BlockFieldProps> = (props) => {
|
||||
const BlocksFieldComponent: BlocksFieldClientComponent = (props) => {
|
||||
const { i18n, t } = useTranslation()
|
||||
|
||||
const {
|
||||
@@ -284,7 +284,7 @@ const BlocksFieldComponent: React.FC<BlockFieldProps> = (props) => {
|
||||
|
||||
if (blockToRender) {
|
||||
const rowErrorCount = errorPaths.filter((errorPath) =>
|
||||
errorPath.startsWith(`${path}.${i}`),
|
||||
errorPath.startsWith(`${path}.${i}.`),
|
||||
).length
|
||||
return (
|
||||
<DraggableSortableItem disabled={disabled || !isSortable} id={row.id} key={row.id}>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user