Commit Graph

62 Commits

Author SHA1 Message Date
Jacob Fletcher
ed44ec0a9c fix(ui): does not render row labels until form state returns (#10002)
Extension of #9933. Custom components are returned by form state,
meaning that if we don't wait for form state to return before rendering
row labels, the default row label component will render in briefly
before being swapped by a custom component (if applicable). Using the
new `isLoading` prop on array and block rows, we can conditionally
render them just as we currently do for the row fields themselves.
2024-12-16 21:44:19 +00:00
Jacob Fletcher
796df37461 fix(ui): awaits form state before rendering conditional fields (#9933)
When a condition exists on a field and it resolves to `false`, it
currently "blinks" in and out when rendered within an array or block
row. This is because when add rows to form state, we iterate over the
_fields_ of that row and render their respective components. Then when
conditions are checked for that field, we're expecting `passesCondition`
to be explicitly `false`, ultimately _rendering_ the field for a brief
moment before form state returns with evaluated conditions. The fix is
to set these fields into local form state with a new `isLoading: true`
prop, then display a loader within the row until form state returns with
its proper conditions.
2024-12-13 16:42:52 +00:00
Patrik
58b7415385 feat(ui): adds beforeInput & afterInput props for arrays, blocks, collapsible, group, radio, & relationship fields. (#9674)
The following fields did not have the ability to add beforeInput &
afterInput:
- Arrays
- Blocks
- Collapsibles
- Groups
- Radios
- Relationships

### How?

Adds the ability to define and add before and after inputs to these
fields in your config.

Here are examples of the above fields with beforeInputs & afterInputs
defined (I.e. `#before-input` & `#after-input`):

`Arrays`:
![Screenshot 2024-12-02 at 1 22
15 PM](https://github.com/user-attachments/assets/8a2d5351-acab-4b28-b9bd-b19e1942da7e)


`Blocks`:
![Screenshot 2024-12-02 at 1 35
53 PM](https://github.com/user-attachments/assets/e9b5f22b-2671-4efb-8ee4-b4de3a1addc5)


`Collapsible`:
![Screenshot 2024-12-02 at 1 46
34 PM](https://github.com/user-attachments/assets/38f7a016-8a79-4ece-90d2-0b1761db19cd)


`Groups`:
![Screenshot 2024-12-02 at 1 52
34 PM](https://github.com/user-attachments/assets/dc6a123b-ee01-4021-bbbf-ac1b8c086072)


`Radios`:
![Screenshot 2024-12-02 at 1 59
35 PM](https://github.com/user-attachments/assets/4ddd16a1-2ad2-44f5-a7e9-86aa6e4e947b)


`Relationships`:
![Screenshot 2024-12-02 at 1 21
55 PM](https://github.com/user-attachments/assets/b4679baf-6157-41c9-8485-ca570be979d2)
2024-12-02 19:37:16 +00:00
Riley Pearce
27acdaee7a fix(ui): add disabled attribute to blocks drawer toggler (#9424)
### What?

When `update` access control is set to `false`, the blocks drawer can
still be accessed. Blocks still cannot be saved to the document, making
this more of a QoL improvement.

### Why?

The blocks `DrawerToggler` is missing the `disabled` attribute.

### How?

Adding the `disabled` attribute to the blocks `DrawerToggler`.

### Reproduction steps

https://github.com/rilrom/payload/tree/issue/disabled-add-block-button

1. Navigate to the posts collection.
2. Click the 'Add blocks' button.
3. Blocks can be selected (however they are still readonly in the
document and cannot be saved).

### Recordings

Before


https://github.com/user-attachments/assets/da12829d-5b27-4da9-bbd1-067d679a89ba

After


https://github.com/user-attachments/assets/67166477-b83a-4495-98ae-2d272542103b
2024-11-22 08:59:38 -07:00
Alessio Gravili
c67291d538 fix(ui): invalid permissions passed to group and named tab sub-fields (#9366)
Fixes https://github.com/payloadcms/payload/issues/9363

This fixes the following issues that caused fields to be either hidden,
or incorrectly set to readOnly in certain configurations:
- In some cases, permissions were sanitized incorrectly. This PR
rewrites the sanitizePermissions function and adds new unit tests
- after a document save, the client was receiving unsanitized
permissions. Moving the sanitization logic to the endpoint fixes this
- Various incorrect handling of permissions in our form state endpoints
/ RenderFields
2024-11-20 13:03:35 -07:00
Jacob Fletcher
0f3f6e73da fix(ui): addFieldRow set modified (#9324)
Fixes #9264. When externally updating array or block rows through the
`addFieldRow` or `replaceFieldRow` methods, nested rich text fields
along with any custom components within them are never rendered. This is
because unless the form is explicitly set to modified, as the default
array and blocks fields currently do, the newly generated form-state
will skip the rendering step. Now, the underlying callbacks themselves
automatically set the form to modified to trigger rendering.
2024-11-19 08:52:50 -05:00
Paul
26ffbca914 feat: sanitise access endpoint (#7335)
Protects the `/api/access` endpoint behind authentication and sanitizes
the result, making it more secure and significantly smaller. To do this:

1. The `permission` keyword is completely omitted from the result
2. Only _truthy_ access results are returned
3. All nested permissions are consolidated when possible

---------

Co-authored-by: Dan Ribbens <dan.ribbens@gmail.com>
Co-authored-by: Jacob Fletcher <jacobsfletch@gmail.com>
Co-authored-by: James <james@trbl.design>
2024-11-15 15:08:06 -05:00
James Mikrut
e6d04436a8 fix(ui): fixes layout shift when form is submitted (#9184)
Some fields cause layout shift when you submit the form. This PR reduces
that flicker.
2024-11-14 02:57:01 +00:00
Jarrod Flesch
bcbca0e44a chore: improves field types (#9172)
### What?
Ensures `path` is required and only present on the fields that expect it
(all fields except row).

Deprecates `useFieldComponents` and `FieldComponentsProvider` and
instead extends the RenderField component to account for all field
types. This also improves type safety within `RenderField`.

### Why?
`path` being optional just adds DX overhead and annoyance. 

### How?
Added `FieldPaths` type which is added to iterable field types. Placed
`path` back onto the ClientFieldBase type.
2024-11-13 13:53:47 -05:00
Jacob Fletcher
c96fa613bc feat!: on demand rsc (#8364)
Currently, Payload renders all custom components on initial compile of
the admin panel. This is problematic for two key reasons:
1. Custom components do not receive contextual data, i.e. fields do not
receive their field data, edit views do not receive their document data,
etc.
2. Components are unnecessarily rendered before they are used

This was initially required to support React Server Components within
the Payload Admin Panel for two key reasons:
1. Fields can be dynamically rendered within arrays, blocks, etc.
2. Documents can be recursively rendered within a "drawer" UI, i.e.
relationship fields
3. Payload supports server/client component composition 

In order to achieve this, components need to be rendered on the server
and passed as "slots" to the client. Currently, the pattern for this is
to render custom server components in the "client config". Then when a
view or field is needed to be rendered, we first check the client config
for a "pre-rendered" component, otherwise render our client-side
fallback component.

But for the reasons listed above, this pattern doesn't exactly make
custom server components very useful within the Payload Admin Panel,
which is where this PR comes in. Now, instead of pre-rendering all
components on initial compile, we're able to render custom components
_on demand_, only as they are needed.

To achieve this, we've established [this
pattern](https://github.com/payloadcms/payload/pull/8481) of React
Server Functions in the Payload Admin Panel. With Server Functions, we
can iterate the Payload Config and return JSX through React's
`text/x-component` content-type. This means we're able to pass
contextual props to custom components, such as data for fields and
views.

## Breaking Changes

1. Add the following to your root layout file, typically located at
`(app)/(payload)/layout.tsx`:

    ```diff
    /* THIS FILE WAS GENERATED AUTOMATICALLY BY PAYLOAD. */
    /* DO NOT MODIFY IT BECAUSE IT COULD BE REWRITTEN AT ANY TIME. */
    + import type { ServerFunctionClient } from 'payload'

    import config from '@payload-config'
    import { RootLayout } from '@payloadcms/next/layouts'
    import { handleServerFunctions } from '@payloadcms/next/utilities'
    import React from 'react'

    import { importMap } from './admin/importMap.js'
    import './custom.scss'

    type Args = {
      children: React.ReactNode
    }

+ const serverFunctions: ServerFunctionClient = async function (args) {
    +  'use server'
    +  return handleServerFunctions({
    +    ...args,
    +    config,
    +    importMap,
    +  })
    + }

    const Layout = ({ children }: Args) => (
      <RootLayout
        config={config}
        importMap={importMap}
    +  serverFunctions={serverFunctions}
      >
        {children}
      </RootLayout>
    )

    export default Layout
    ```

2. If you were previously posting to the `/api/form-state` endpoint, it
no longer exists. Instead, you'll need to invoke the `form-state` Server
Function, which can be done through the _new_ `getFormState` utility:

    ```diff
    - import { getFormState } from '@payloadcms/ui'
    - const { state } = await getFormState({
    -   apiRoute: '',
    -   body: {
    -     // ...
    -   },
    -   serverURL: ''
    - })

    + const { getFormState } = useServerFunctions()
    +
    + const { state } = await getFormState({
    +   // ...
    + })
    ```

## Breaking Changes

```diff
- useFieldProps()
- useCellProps()
```

More details coming soon.

---------

Co-authored-by: Alessio Gravili <alessio@gravili.de>
Co-authored-by: Jarrod Flesch <jarrodmflesch@gmail.com>
Co-authored-by: James <james@trbl.design>
2024-11-11 13:59:05 -05:00
Paul
7c62e2a327 feat(ui)!: scope all payload css to payload-default layer (#8545)
All payload css is now encapsulated inside CSS layers under `@layer
payload-default`

Any custom css will now have the highest possible specificity.
We have also provided a new layer `@layer payload` if you want to use
layers and ensure that your styles are applied after payload.

To override existing styles in a way that the existing rules of
specificity would be respected you can use the default layer like so
```css
@layer payload-default {
  // my styles within the payload specificity
}
```
2024-10-04 13:02:56 -06:00
Jacob Fletcher
a6f13f7330 fix(ui): properly extracts label from field in FieldLabel component (#8190)
Although the `<FieldLabel />` component receives a `field` prop, it does
not use this prop to extract the `label` from the field. This is
currently only an issue when rendering this component directly, such as
within `admin.components.Label`. The label simply won't appear unless
explicitly provided, despite it being passed as `field.label`. This is
not an issue when rendering field components themselves, because they
properly thread this value through as a top-level prop.

Here's an example of the issue:

```tsx
import type { TextFieldLabelServerComponent } from 'payload'

import { FieldLabel } from '@payloadcms/ui'
import React from 'react'

export const MyCustomLabelComponent: TextFieldLabelServerComponent = ({ clientField }) => {
  return (
    <FieldLabel
      field={clientField}
      label={clientField.label} // this should not be needed!
    />
  )
}
```

Here is the end result:

```tsx
import type { TextFieldLabelServerComponent } from 'payload'

import { FieldLabel } from '@payloadcms/ui'
import React from 'react'

export const MyCustomLabelComponent: TextFieldLabelServerComponent = ({ clientField }) => {
  return <FieldLabel field={clientField} />
}
```
2024-09-12 14:45:17 -04:00
Jacob Fletcher
465e47a219 fix!: properly names BlocksField and related types (#8174)
The `BlockField` type is not representative of the underlying "blocks"
field type, which is plural, i.e. `BlocksField`. This is a semantic
change that will better align the type with the field.

## Breaking Changes

Types related to the `blocks` field have change names. If you were using
the `BlockField` or related types in your own applications, simply
change the import name to be plural and instead of singular.

Old (singular):

```ts
import type {
  BlockField,
  BlockFieldClient,
  BlockFieldValidation,
  BlockFieldDescriptionClientComponent,
  BlockFieldDescriptionServerComponent,
  BlockFieldErrorClientComponent,
  BlocksFieldErrorServerComponent,
  BlockFieldLabelClientComponent,
  BlockFieldLabelServerComponent,
} from 'payload'
```

New (plural):

```ts
import type {
  BlocksField,
  BlocksFieldClient,
  BlocksFieldValidation,
  BlocksFieldDescriptionClientComponent,
  BlocksFieldDescriptionServerComponent,
  BlocksFieldErrorClientComponent,
  BlocksFieldErrorServerComponent,
  BlocksFieldLabelClientComponent,
  BlocksFieldLabelServerComponent,
} from 'payload'
```
2024-09-11 16:05:03 +00:00
Jacob Fletcher
8e1a5c8dba feat!: explicitly types field components (#8136)
## Description

Currently, there is no way of typing custom server field components.
This is because internally, all field components are client components,
and so these were never fully typed. For example, the docs currently
indicate for all custom fields to be typed in this way:

Old:
    
```tsx
export const MyClientTextFieldComponent: React.FC<TextFieldProps>
```

But if your component is a server component, you will never receive the
fully typed `field` prop, `payload` prop, etc. unless you've typed that
yourself using some of the underlying utilities. So to fix this, every
field now explicitly exports a type for each environment:

New:

- Client component:
    ```tsx
    'use client'
    export const MyClientTextFieldComponent: TextFieldClientComponent
    ```

- Server component:
    ```tsx
    export const MyServerTextFieldComponent: TextFieldServerComponent
    ```

This pattern applies to every field type, where the field name is
prepended onto the component type.

```ts
import type {
  TextFieldClientComponent,
  TextFieldServerComponent,
  TextFieldClientProps,
  TextFieldServerProps,
  TextareaFieldClientComponent,
  TextareaFieldServerComponent,
  TextareaFieldClientProps,
  TextareaFieldServerProps,
  // ...and so on for each field type
} from 'payload'
```

## BREAKING CHANGES

We are no longer exporting `TextFieldProps` etc. for each field type.
Instead, we now export props for each client/server environment
explicitly. If you were previously importing one of these types into
your custom component, simply change the import name to reflect your
environment.

Old:

```tsx
import type { TextFieldProps } from 'payload'
``` 

New:

```tsx
import type { TextFieldClientProps, TextFieldServerProps } from 'payload'
``` 

Related: #7754. 

- [x] I have read and understand the
[CONTRIBUTING.md](https://github.com/payloadcms/payload/blob/main/CONTRIBUTING.md)
document in this repository.

## Type of change

- [x] New feature (non-breaking change which adds functionality)
- [x] This change requires a documentation update

## Checklist:

- [x] Existing test suite passes locally with my changes
- [x] I have made corresponding changes to the documentation
2024-09-09 20:15:10 +00:00
Germán Jabloñski
7fa68d17f5 fix(ui): wrong block indication when an error occurred (#7963) 2024-09-09 10:20:03 -04:00
Alessio Gravili
86fdad0bb8 chore: significantly improve eslint performance, lint and prettier everything 2024-08-29 21:25:50 -04:00
Elliot DeNolf
142616e6ad chore(eslint): curly [skip-lint] (#7959)
Now enforcing curly brackets on all if statements. Includes auto-fixer.


```ts
//  Bad
if (foo) foo++;

//  Good
if (foo) {
  foo++;
}
```




Note: this did not lint the `drizzle` package or any `db-*` packages.
This will be done in the future.
2024-08-29 10:15:36 -04:00
Tylan Davis
93e81314df fix(ui, richtext-lexical): corrects clickable areas on block headers (#7791)
## Description

Fixes an issue where Block component section titles were taking up the
entire clickable area of block headers.

- [x] I have read and understand the
[CONTRIBUTING.md](https://github.com/payloadcms/payload/blob/main/CONTRIBUTING.md)
document in this repository.

## Type of change

<!-- Please delete options that are not relevant. -->

- [x] Bug fix (non-breaking change which fixes an issue)

## Checklist:

- [ ] I have added tests that prove my fix is effective or that my
feature works
- [x] Existing test suite passes locally with my changes
- [ ] I have made corresponding changes to the documentation
2024-08-21 10:45:05 -04:00
Jacob Fletcher
3a91deb0a4 feat: threads field config through components and strictly types props (#7754)
## Description

Threads the field config to all "field subcomponents" through props,
i.e. field label, description, error, etc. This way, the field config
that controls any particular component is easily accessible and strongly
typed, i.e. `props.field.maxLength`. This is true for both server and
client components, whose server-side props are now also contextually
typed. This behavior was temporarily removed in #7474 due to bloating
HTML, but has since been resolved in #7620. This PR also makes
significant improvements to component types by exporting explicit types
for _every component of every field_, each with its own client/server
variation. Now, a custom component can look something like this:

```tsx
import type { TextFieldLabelServerComponent } from 'payload'

import React from 'react'

export const CustomLabel: TextFieldLabelServerComponent = (props) => {
  return (
    <div>{`The max length of this field is: ${props?.field?.maxLength}`}</div>
  )
}
```

The following types are now available:

```ts
import type {
  TextFieldClientComponent,
  TextFieldServerComponent,
  TextFieldLabelClientComponent,
  TextFieldLabelServerComponent,
  TextFieldDescriptionClientComponent,
  TextFieldDescriptionServerComponent,
  TextFieldErrorClientComponent,
  TextFieldErrorServerComponent,
  // ...and so one for each field
} from 'payload'
```

BREAKING CHANGES:

In order to strictly type these components, a few breaking changes have
been made _solely to type definitions_. This only effects you if you are
heavily using custom components.

Old
```ts
import type { ErrorComponent, LabelComponent, DescriptionComponent } from 'payload'
```

New:
```ts
import type {
  FieldErrorClientComponent,
  FieldErrorServerComponent,
  FieldLabelClientComponent,
  FieldLabelServerComponent,
  FieldDescriptionClientComponent,
  FieldDescriptionServerComponent,
  // Note: these are the generic, underlying types of the more stricter types described above ^
  // For example, you should use the type that is explicit for your particular field and environment
  // i.e. `TextFieldLabelClientComponent` and not simply `FieldLabelClientComponent`
} from 'payload'
```

- [x] I have read and understand the
[CONTRIBUTING.md](https://github.com/payloadcms/payload/blob/main/CONTRIBUTING.md)
document in this repository.

## Type of change

- [x] Bug fix (non-breaking change which fixes an issue)

## Checklist:

- [x] I have added tests that prove my fix is effective or that my
feature works
- [x] Existing test suite passes locally with my changes
2024-08-20 04:25:10 +00:00
Alessio Gravili
c65f5027d6 fix(ui): ensure field components safely access field.admin property (#7670) 2024-08-14 12:06:01 -04:00
Alessio Gravili
90b7b20699 feat!: beta-next (#7620)
This PR makes three major changes to the codebase:

1. [Component Paths](#component-paths)
Instead of importing custom components into your config directly, they
are now defined as file paths and rendered only when needed. That way
the Payload config will be significantly more lightweight, and ensures
that the Payload config is 100% server-only and Node-safe. Related
discussion: https://github.com/payloadcms/payload/discussions/6938

2. [Client Config](#client-config)
Deprecates the component map by merging its logic into the client
config. The main goal of this change is for performance and
simplification. There was no need to deeply iterate over the Payload
config twice, once for the component map, and another for the client
config. Instead, we can do everything in the client config one time.
This has also dramatically simplified the client side prop drilling
through the UI library. Now, all components can share the same client
config which matches the exact shape of their Payload config (with the
exception of non-serializable props and mapped custom components).

3. [Custom client component are no longer
server-rendered](#custom-client-components-are-no-longer-server-rendered)
Previously, custom components would be server-rendered, no matter if
they are server or client components. Now, only server components are
rendered on the server. Client components are automatically detected,
and simply get passed through as `MappedComponent` to be rendered fully
client-side.

## Component Paths

Instead of importing custom components into your config directly, they
are now defined as file paths and rendered only when needed. That way
the Payload config will be significantly more lightweight, and ensures
that the Payload config is 100% server-only and Node-safe. Related
discussion: https://github.com/payloadcms/payload/discussions/6938

In order to reference any custom components in the Payload config, you
now have to specify a string path to the component instead of importing
it.

Old:

```ts
import { MyComponent2} from './MyComponent2.js'

admin: {
  components: {
    Label: MyComponent2
  },
},
```

New:

```ts
admin: {
  components: {
    Label: '/collections/Posts/MyComponent2.js#MyComponent2', // <= has to be a relative path based on a baseDir configured in the Payload config - NOT relative based on the importing file
  },
},
```

### Local API within Next.js routes

Previously, if you used the Payload Local API within Next.js pages, all
the client-side modules are being added to the bundle for that specific
page, even if you only need server-side functionality.

This `/test` route, which uses the Payload local API, was previously 460
kb. It is now down to 91 kb and does not bundle the Payload client-side
admin panel anymore.

All tests done
[here](https://github.com/payloadcms/payload-3.0-demo/tree/feat/path-test)
with beta.67/PR, db-mongodb and default richtext-lexical:

**dev /admin before:**
![CleanShot 2024-07-29 at 22 49
12@2x](https://github.com/user-attachments/assets/4428e766-b368-4bcf-8c18-d0187ab64f3e)

**dev /admin after:**
![CleanShot 2024-07-29 at 22 50
49@2x](https://github.com/user-attachments/assets/f494c848-7247-4b02-a650-a3fab4000de6)

---

**dev /test before:**
![CleanShot 2024-07-29 at 22 56
18@2x](https://github.com/user-attachments/assets/1a7e9500-b859-4761-bf63-abbcdac6f8d6)

**dev /test after:**
![CleanShot 2024-07-29 at 22 47
45@2x](https://github.com/user-attachments/assets/f89aa76d-f2d5-4572-9753-2267f034a45a)

---

**build before:**
![CleanShot 2024-07-29 at 22 57
14@2x](https://github.com/user-attachments/assets/5f8f7281-2a4a-40a5-a788-c30ddcdd51b5)

**build after::**
![CleanShot 2024-07-29 at 22 56
39@2x](https://github.com/user-attachments/assets/ea8772fd-512f-4db0-9a81-4b014715a1b7)

### Usage of the Payload Local API / config outside of Next.js

This will make it a lot easier to use the Payload config / local API in
other, server-side contexts. Previously, you might encounter errors due
to client files (like .scss files) not being allowed to be imported.

## Client Config

Deprecates the component map by merging its logic into the client
config. The main goal of this change is for performance and
simplification. There was no need to deeply iterate over the Payload
config twice, once for the component map, and another for the client
config. Instead, we can do everything in the client config one time.
This has also dramatically simplified the client side prop drilling
through the UI library. Now, all components can share the same client
config which matches the exact shape of their Payload config (with the
exception of non-serializable props and mapped custom components).

This is breaking change. The `useComponentMap` hook no longer exists,
and most component props have changed (for the better):

```ts
const { componentMap } = useComponentMap() // old
const { config } = useConfig() // new
```

The `useConfig` hook has also changed in shape, `config` is now a
property _within_ the context obj:

```ts
const config = useConfig() // old
const { config } = useConfig() // new
```

## Custom Client Components are no longer server rendered

Previously, custom components would be server-rendered, no matter if
they are server or client components. Now, only server components are
rendered on the server. Client components are automatically detected,
and simply get passed through as `MappedComponent` to be rendered fully
client-side.

The benefit of this change:

Custom client components can now receive props. Previously, the only way
for them to receive dynamic props from a parent client component was to
use hooks, e.g. `useFieldProps()`. Now, we do have the option of passing
in props to the custom components directly, if they are client
components. This will be simpler than having to look for the correct
hook.

This makes rendering them on the client a little bit more complex, as
you now have to check if that component is a server component (=>
already has been rendered) or a client component (=> not rendered yet,
has to be rendered here). However, this added complexity has been
alleviated through the easy-to-use `<RenderMappedComponent />` helper.

This helper now also handles rendering arrays of custom components (e.g.
beforeList, beforeLogin ...), which actually makes rendering custom
components easier in some cases.

## Misc improvements

This PR includes misc, breaking changes. For example, we previously
allowed unions between components and config object for the same
property. E.g. for the custom view property, you were allowed to pass in
a custom component or an object with other properties, alongside a
custom component.

Those union types are now gone. You can now either pass an object, or a
component. The previous `{ View: MyViewComponent}` is now `{ View: {
Component: MyViewComponent} }` or `{ View: { Default: { Component:
MyViewComponent} } }`.

This dramatically simplifies the way we read & process those properties,
especially in buildComponentMap. We can now simply check for the
existence of one specific property, which always has to be a component,
instead of running cursed runtime checks on a shared union property
which could contain a component, but could also contain functions or
objects.

![CleanShot 2024-07-29 at 23 07
07@2x](https://github.com/user-attachments/assets/1e75aa4c-7a4c-419f-9070-216bb7b9a5e5)

![CleanShot 2024-07-29 at 23 09
40@2x](https://github.com/user-attachments/assets/b4c96450-6b7e-496c-a4f7-59126bfd0991)

- [x] I have read and understand the
[CONTRIBUTING.md](https://github.com/payloadcms/payload/blob/main/CONTRIBUTING.md)
document in this repository.

---------

Co-authored-by: PatrikKozak <patrik@payloadcms.com>
Co-authored-by: Paul <paul@payloadcms.com>
Co-authored-by: Paul Popus <paul@nouance.io>
Co-authored-by: Jacob Fletcher <jacobsfletch@gmail.com>
Co-authored-by: James <james@trbl.design>
2024-08-13 12:54:33 -04:00
Tylan Davis
0d552fd523 chore: adjusts admin UI styling (#7557)
## Description

- Improves mobile styling of Payload admin UI.
- Reduces font size on dashboard cards.
- Improves the block/collapsible/array field styling.

- [x] I have read and understand the
[CONTRIBUTING.md](https://github.com/payloadcms/payload/blob/main/CONTRIBUTING.md)
document in this repository.

## Type of change

<!-- Please delete options that are not relevant. -->

- [x] Chore (non-breaking change which does not add functionality)

## Checklist:

- [ ] I have added tests that prove my fix is effective or that my
feature works
- [x] Existing test suite passes locally with my changes
- [ ] I have made corresponding changes to the documentation
2024-08-09 11:19:36 -04:00
Tylan Davis
68553ff974 feat!: updated admin UI (#7424)
## Description

- Updates admin UI with more condensed spacing throughout.
- Improves hover states and read-only states for various components.
- Removes the `Merriweather` font from `next/font` and replaces with
stack of system serif fonts and fallbacks (Georgia, etc). Closes #7257

## BREAKING CHANGES
- Custom components and styling that don't utilize Payload's CSS/SCSS
variables may need adjustments to match the updated styling.
- If you are using the `Merriweather` font, you will need to manually
configure `next/font` in your own project.

---------

Co-authored-by: Paul Popus <paul@nouance.io>
2024-08-05 15:08:00 +00:00
Jarrod Flesch
5cd0c7ec7d fix: layout preferences for array/blocks were being saved twice in dev mode (#7396)
Fixes an issue where preferences for array/block collapsible's were not
being set correctly. React strict mode surfaced this issue.
2024-07-29 09:59:05 -04:00
Jacob Fletcher
97837f0708 feat(ui)!: passes field props to custom components (#7360)
## Description

Currently, there is no way to read field props from within a custom
field component, i.e. `admin.components.Description`. For example, if
you set `maxLength: 100` on your field, your custom description
component cannot read it from `props.maxLength` or any other methods.
Because these components are rendered on the server, there is also no
way of using `admin.component.Field` to inject custom props yourself,
either. To support this, we can simply pass the base component props
into these components on the server, as expected. This has also led to
custom field component props becoming more strictly typed within the
config.

This change is considered breaking only because the types have changed.
This only affects you if you were previously importing the following
types into your own custom components. To migrate, simply change the
import paths for that type.

Old:
```ts
import type {
  ArrayFieldProps,
  ReducedBlock,
  BlocksFieldProps,
  CheckboxFieldProps,
  CodeFieldProps,
  CollapsibleFieldProps,
  DateFieldProps,
  EmailFieldProps,
  GroupFieldProps,
  HiddenFieldProps,
  JSONFieldProps,
  NumberFieldProps,
  PointFieldProps,
  RadioFieldProps,
  RelationshipFieldProps,
  RichTextComponentProps,
  RowFieldProps,
  SelectFieldProps,
  TabsFieldProps,
  TextFieldProps,
  TextareaFieldProps,
  UploadFieldProps,
  ErrorProps,
  FormFieldBase, 
  FieldComponentProps,
  FieldMap,
  MappedField,
  MappedTab,
  ReducedBlock,
} from '@payloadcms/ui'
```

New:
```ts
import type {
  FormFieldBase, 
  // etc.
} from 'payload'
```

Custom field components are now much more strongly typed. To make this
happen, an explicit type for every custom component has been generated
for every field type. The convention is to append
`DescriptionComponent`, `LabelComponent`, and `ErrorComponent` onto the
end of the field name, i.e. `TextFieldDescriptionComponent`. Here's an
example:

```ts
import type { TextFieldDescriptionComponent } from 'payload'

import React from 'react'

export const CustomDescription: TextFieldDescriptionComponent = (props) => {
  return (
    <div id="custom-field-description">{`The max length of this field is: ${props?.maxLength}`}</div>
  )
}
```

Here's the full list of all new types:

Label Components:

```ts
import type {
  ArrayFieldLabelComponent,
  BlocksFieldLabelComponent,
  CheckboxFieldLabelComponent,
  CodeFieldLabelComponent,
  CollapsibleFieldLabelComponent,
  DateFieldLabelComponent,
  EmailFieldLabelComponent,
  GroupFieldLabelComponent,
  HiddenFieldLabelComponent,
  JSONFieldLabelComponent,
  NumberFieldLabelComponent,
  PointFieldLabelComponent,
  RadioFieldLabelComponent,
  RelationshipFieldLabelComponent,
  RichTextFieldLabelComponent,
  RowFieldLabelComponent,
  SelectFieldLabelComponent,
  TabsFieldLabelComponent,
  TextFieldLabelComponent,
  TextareaFieldLabelComponent,
  UploadFieldLabelComponent
} from 'payload'
```

Error Components:

```tsx
import type {
  ArrayFieldErrorComponent,
  BlocksFieldErrorComponent,
  CheckboxFieldErrorComponent,
  CodeFieldErrorComponent,
  CollapsibleFieldErrorComponent,
  DateFieldErrorComponent,
  EmailFieldErrorComponent,
  GroupFieldErrorComponent,
  HiddenFieldErrorComponent,
  JSONFieldErrorComponent,
  NumberFieldErrorComponent,
  PointFieldErrorComponent,
  RadioFieldErrorComponent,
  RelationshipFieldErrorComponent,
  RichTextFieldErrorComponent,
  RowFieldErrorComponent,
  SelectFieldErrorComponent,
  TabsFieldErrorComponent,
  TextFieldErrorComponent,
  TextareaFieldErrorComponent,
  UploadFieldErrorComponent
} from 'payload'
```

Description Components:

```tsx
import type {
  ArrayFieldDescriptionComponent,
  BlocksFieldDescriptionComponent,
  CheckboxFieldDescriptionComponent,
  CodeFieldDescriptionComponent,
  CollapsibleFieldDescriptionComponent,
  DateFieldDescriptionComponent,
  EmailFieldDescriptionComponent,
  GroupFieldDescriptionComponent,
  HiddenFieldDescriptionComponent,
  JSONFieldDescriptionComponent,
  NumberFieldDescriptionComponent,
  PointFieldDescriptionComponent,
  RadioFieldDescriptionComponent,
  RelationshipFieldDescriptionComponent,
  RichTextFieldDescriptionComponent,
  RowFieldDescriptionComponent,
  SelectFieldDescriptionComponent,
  TabsFieldDescriptionComponent,
  TextFieldDescriptionComponent,
  TextareaFieldDescriptionComponent,
  UploadFieldDescriptionComponent
} from 'payload'
```

This PR also:
- Standardizes the `FieldBase['label']` type with a new `LabelStatic`
type. This makes type usage much more consistent across components.
- Simplifies some of the typings in the field component map, removes
unneeded `<Omit>`, etc.
- Fixes misc. linting issues around voiding promises

- [x] I have read and understand the
[CONTRIBUTING.md](https://github.com/payloadcms/payload/blob/main/CONTRIBUTING.md)
document in this repository.

## Type of change

- [x] New feature (non-breaking change which adds functionality)

## Checklist:

- [x] I have added tests that prove my fix is effective or that my
feature works
- [x] Existing test suite passes locally with my changes
- [x] I have made corresponding changes to the documentation
2024-07-26 14:03:25 -04:00
Paul
e734d51760 chore(ui)!: update the names of internal components so that they respect eslint rules (#7362)
So `_Upload` becomes `UploadComponent` which doesnt break the naming
convention of react components and **we no longer export these internal
components**
2024-07-26 17:50:23 +00:00
Alessio Gravili
676dfa3ecf feat(richtext-lexical): inline blocks (#7102) 2024-07-17 00:42:36 +00:00
Alessio Gravili
83fd4c6622 chore: run lint and prettier on entire codebase 2024-07-11 15:27:01 -04:00
Jarrod Flesch
cedd916816 fix: corrects permission access reading for disabling fields (#6815)
Fixes issues where access control was not properly affecting the read-only setting on fields.
2024-06-17 18:33:45 -04:00
Jacob Fletcher
9e76c8f4e3 feat!: prebundle payload, ui, richtext-lexical (#6579)
# Breaking Changes

### New file import locations

Exports from the `payload` package have been _significantly_ cleaned up.
Now, just about everything is able to be imported from `payload`
directly, rather than an assortment of subpath exports. This means that
things like `import { buildConfig } from 'payload/config'` are now just
imported via `import { buildConfig } from 'payload'`. The mental model
is significantly simpler for developers, but you might need to update
some of your imports.

Payload now exposes only three exports:

1. `payload` - all types and server-only Payload code
2. `payload/shared` - utilities that can be used in either the browser
or in Node environments
3. `payload/node` - heavy utilities that should only be imported in Node
scripts and never be imported into bundled code like Next.js

### UI library pre-bundling

With this release, we've dramatically sped up the compile time for
Payload by pre-bundling our entire UI package for use inside of the
Payload admin itself. There are new exports that should be used within
Payload custom components:

1. `@payloadcms/ui/client` - all client components 
2. `@payloadcms/ui/server` - all server components

For all of your custom Payload admin UI components, you should be
importing from one of these two pre-compiled barrel files rather than
importing from the more deeply nested exports directly. That will keep
compile times nice and speedy, and will also make sure that the bundled
JS for your admin UI is kept small.

For example, whereas before, if you imported the Payload `Button`, you
would have imported it like this:

```ts
import { Button } from '@payloadcms/ui/elements/Button'
```

Now, you would import it like this:

```ts
import { Button } from '@payloadcms/ui/client'
```

This is a significant DX / performance optimization that we're pretty
pumped about.

However, if you are importing or re-using Payload UI components
_outside_ of the Payload admin UI, for example in your own frontend
apps, you can import from the individual component exports which will
make sure that the bundled JS is kept to a minimum in your frontend
apps. So in your own frontend, you can continue to import directly to
the components that you want to consume rather than importing from the
pre-compiled barrel files.

Individual component exports will now come with their corresponding CSS
and everything will work perfectly as-expected.

### Specific exports have changed

- `'@payloadcms/ui/templates/Default'` and
`'@payloadcms/ui/templates/Minimal`' are now exported from
`'@payloadcms/next/templates'`
- Old: `import { LogOut } from '@payloadcms/ui/icons/LogOut'` new:
`import { LogOutIcon } from '@payloadcms/ui/icons/LogOut'`

## Background info

In effort to make local dev as fast as possible, we need to import as
few files as possible so that the compiler has less to process. One way
we've achieved this in the Admin Panel was to _remove_ all .scss imports
from all components in the `@payloadcms/ui` module using a build
process. This stripped all `import './index.scss'` statements out of
each component before injecting them into `dist`. Instead, it bundles
all of the CSS into a single `main.css` file, and we import _that_ at
the root of the app.

While this concept is _still_ the right solution to the problem, this
particular approach is not viable when using these components outside
the Admin Panel, where not only does this root stylesheet not exist, but
where it would also bloat your app with unused styles. Instead, we need
to _keep_ these .scss imports in place so they are imported directly
alongside your components, as expected. Then, we need create a _new_
build step that _separately_ compiles the components _without_ their
stylesheets—this way your app can consume either as needed from the new
`client` and `server` barrel files within `@payloadcms/ui`, i.e. from
within `@payloadcms/next` and all other admin-specific packages and
plugins.

This way, all other applications will simply import using the direct
file paths, just as they did before. Except now they come with
stylesheets.

And we've gotten a pretty awesome initial compilation performance boost.

---------

Co-authored-by: James <james@trbl.design>
Co-authored-by: Alessio Gravili <alessio@gravili.de>
2024-06-17 14:25:36 -04:00
Alessio Gravili
e7159c033e fix(ui,richtext-*): path from context should always have precedence over path from props, even if it's an empty string (#6782) 2024-06-15 05:42:16 +00:00
Jacob Fletcher
17707852e0 chore: migrates @faceless-ui imports to esm (#6681) 2024-06-07 22:59:39 -04:00
Jacob Fletcher
92f458dad2 feat(next,ui): improves loading states (#6434) 2024-05-29 14:01:13 -04:00
Alessio Gravili
96181d91a6 chore(ui): add ability to compile using react compiler (#6483)
This does not enable the react compiler by default
2024-05-27 22:54:36 -04:00
Alessio Gravili
ed4766188d fix(ui): tooltip positioning issues (#6439) 2024-05-20 20:37:53 +00:00
Alessio Gravili
79f4907cb3 feat!: add missing server-only props to custom RSCs, improve req.user type, clean-up ui imports (#6355) 2024-05-14 17:27:15 -04:00
Alessio Gravili
f716122eab feat!: typed i18n (#6343) 2024-05-14 11:10:31 -04:00
Alessio Gravili
cfeac79b99 feat!: fix non-functional custom RSC component handling, separate label and description props, fix non-functional label function handling (#6264)
Breaking Changes:

- Globals config: `admin.description` no longer accepts a custom component. You will have to move it to `admin.components.elements.Description`
- Collections config: `admin.description` no longer accepts a custom component. You will have to move it to `admin.components.edit.Description`
- All Fields: `field.admin.description` no longer accepts a custom component. You will have to move it to `field.admin.components.Description`
- Collapsible Field: `field.label` no longer accepts a custom component. You will have to move it to `field.admin.components.RowLabel`
- Array Field: `field.admin.components.RowLabel` no longer accepts strings or records
- If you are using our exported field components in your own app, their `labelProps` property has been stripped down and no longer contains the `label` and `required` prop. Those can now only be configured at the top-level
2024-05-09 17:12:01 -04:00
Kendell Joseph
4c6aaafe88 feat(ui): toggle sortable arrays and blocks (#6008) 2024-05-08 13:28:26 -04:00
Jarrod Flesch
94af06466b chore: re-exports languages in payload (#5771) 2024-04-10 15:55:01 -04:00
Jacob Fletcher
4b4c245507 fix(ui): properly initializes collapsible context (#5725) 2024-04-08 12:48:44 -04:00
Jarrod Flesch
17352c9a56 chore: change pw buttons, field readOnly prop, admin panel thumbnailURL fallback (#5694) 2024-04-05 13:51:17 -04:00
Jacob Fletcher
77efdc3ccf fix(ui): adds support for direct field label props (#5517) 2024-03-28 13:22:09 -04:00
Jarrod Flesch
8636685252 fix: simplifies field error paths (#5504) 2024-03-28 13:15:44 -04:00
Alessio Gravili
e6d4445a8a chore: fix build 2024-03-27 16:03:23 -04:00
Alessio Gravili
db8e805a96 fix: improve error path merging from server, make sure no new or removed rows/values coming from the server are being considered outside addFieldRow 2024-03-27 15:55:19 -04:00
Alessio Gravili
436c4f2736 fix: missing withConditions for Upload, Select, Password, Blocks, Array fields (#5471)
* fix: missing withConditions for Upload, Select, Password, Blocks, Array fields. Fixes Lexical e2e tests

* chore: skip failing lexical test for now
2024-03-26 10:38:48 -04:00
Patrik
a9b46a4d63 fix(ui): properly formats collapsible field IDs (#5435)
* test: passing collapsible fields test suite

* chore: passes indexPath into ArrayRow & updates path in collapsible field

* fix: collapsible paths and indexPath prop types

* chore: improves path and schemaPath syntax

* leftover

* chore: updates selectors in collapsibles tests

* chore: updates selector in live-preview test suite

---------

Co-authored-by: Jacob Fletcher <jacobsfletch@gmail.com>
2024-03-25 14:16:35 -04:00
Alessio Gravili
8d78d07415 fix: prioritize props path in useField - fixes sub-fields initialized from within fields, like blockName (#5451) 2024-03-25 13:21:01 -04:00
Jacob Fletcher
64d6163f13 chore(ui): consolidates field label, error, and description components 2024-03-21 12:08:20 -04:00