Skip to content

Commit

Permalink
feat: add AutoField component for using Puck fields inside custom fields
Browse files Browse the repository at this point in the history
  • Loading branch information
chrisvxd committed May 13, 2024
1 parent bc34746 commit 106028b
Show file tree
Hide file tree
Showing 7 changed files with 181 additions and 41 deletions.
1 change: 1 addition & 0 deletions apps/docs/pages/docs/api-reference/components/_meta.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
{
"auto-field": {},
"drawer": {},
"drawer-item": {},
"drop-zone": {},
Expand Down
96 changes: 96 additions & 0 deletions apps/docs/pages/docs/api-reference/components/auto-field.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
---
title: <AutoField>
---

import { ConfigPreview } from "@/docs/components/Preview";
import { AutoField } from "@/core/components/AutoField";

# \<AutoField\>

Render a Puck field based on a [Field](/docs/api-reference/fields) object. Use this when building [custom fields](/docs/extending-puck/custom-fields) that need to use Puck-style fields internally.

<ConfigPreview
label="Example"
componentConfig={{
fields: {
title: {
type: "custom",
render: ({ onChange, value }) => {
return (
<AutoField
field={{ type: "text" }}
onChange={onChange}
value={value}
/>
);
},
},
},
defaultProps: {
title: "Hello, world",
},
render: ({ title }) => {
return <p style={{ margin: 0 }}>{title}</p>;
},
}}
/>

```tsx {1,4} copy
import { Autofield } from "@measured/puck";

const CustomField = ({ onChange, value }) => (
<AutoField field={{ type: "text" }} onChange={onChange} value={value} />
);

const config = {
components: {
Example: {
fields: {
title: {
type: "custom",
render: MyCustomField,
},
},
},
},
};
```

## Props

| Prop | Example | Type | Status |
| ----------------------- | ---------------------------- | ----------------------------------- | -------- |
| [`field`](#field) | `{ type: "text" }` | [Field](/docs/api-reference/fields) | Required |
| [`onChange`](#onchange) | `onChange("Goodbye, world")` | Function | Required |
| [`value`](#value) | `"Hello, world"` | Any | Required |
| [`id`](#id) | `"my-input"` | String | - |
| [`readOnly`](#readonly) | `true` | Boolean | - |

## Required Props

### `field`

An object containing the user defined [Field](/docs/api-reference/fields) configuration.

### `onChange`

A callback that triggers when the value changes.

### `value`

The current value for the field.

## Optional Props

### `id`

An optional ID for this field. Will be generated if not specified.

### `readOnly`

A boolean describing whether or not this field is `readOnly`.

## Further reading

- [Custom fields](/docs/extending-puck/custom-fields)
- [The `<FieldLabel>` API reference](/docs/api-reference/components/field-label)
50 changes: 13 additions & 37 deletions apps/docs/pages/docs/api-reference/overrides/field-types.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,12 @@ Override each [field type](/docs/api-reference/fields).
```tsx copy
const overrides = {
fieldType: {
number: ({ name }) => <input name={name} type="number" />,
text: ({ name }) => <input name={name} type="text" />,
number: ({ onChange }) => (
<input type="number" onChange={(e) => onChange(e.currentTarget.value)} />
),
text: ({ onChange }) => (
<input type="text" onChange={(e) => onChange(e.currentTarget.value)} />
),
// ...
},
};
Expand All @@ -20,46 +24,18 @@ You can specify a custom render method for each known [field type](/docs/api-ref

## Render Props

| Prop | Example | Type |
| ----------------------------------- | ---------------------------- | ----------------------------------- |
| [`children`](#children) | `<input />` | ReactNode |
| [`field`](#field) | `{ type: "text" }` | [Field](/docs/api-reference/fields) |
| [`id`](#id) | `"my-input"` | String |
| [`label`](#label) | `"Title"` | String |
| [`name`](#name) | `"title"` | String |
| [`onChange`](#onchange) | `onChange("Goodbye, world")` | Function |
| [`readOnly`](#readonly) | `false` | Boolean |
| [`readOnlyFields`](#readonlyfields) | `{ title: true }` | Object |
| [`value`](#value) | `"Hello, world"` | Any |
Extends the [`<AutoField>` API](/docs/api-reference/components/auto-field).

| Prop | Example | Type |
| ----------------------- | ----------- | -------------------------------------------------------------- |
| [`children`](#children) | `<input />` | ReactNode |
| [`name`](#name) | `"title"` | string |
| `...` | `{}` | [`<AutoField>` API](/docs/api-reference/components/auto-field) |

### `children`

The default node for this field type.

### `field`

An object containing the user defined [Field](/docs/api-reference/fields) configuration.

### `id`

A unique ID for this field.

### `label`

The label for this field.

### `name`

The name of the prop this field is rendering for.

### `onChange`

A callback to set a new value for this input.

### `readOnly`

A boolean describing whether or not this field is set to `readOnly` by [`resolveData`](/docs/api-reference/configuration/component-config#resolvedatadata-params).

### `value`

The current value for the prop.
68 changes: 65 additions & 3 deletions apps/docs/pages/docs/extending-puck/custom-fields.mdx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ConfigPreview } from "@/docs/components/Preview";
import { FieldLabel } from "@/core/components/AutoField";
import { AutoField, FieldLabel } from "@/core/components/AutoField";

# Custom Fields

Expand Down Expand Up @@ -71,7 +71,7 @@ The [`onChange` function](/docs/api-reference/fields/custom#onchangevalue-ui) up

You can add your own label, but it's recommended to use the [`<FieldLabel>` component](/docs/api-reference/components/field-label) provided by Puck to seamlessly integrate into the Puck field UI.

```tsx copy showLineNumbers {1, 9-14}
```tsx copy showLineNumbers {1, 11-13}
import { FieldLabel } from "@measured/puck";

const config = {
Expand All @@ -80,7 +80,7 @@ const config = {
fields: {
title: {
type: "custom",
label: "Label Example"
label: "Label Example",
render: ({ field }) => (
<FieldLabel label={field.label}>
<input {/*...*/} />
Expand Down Expand Up @@ -128,6 +128,66 @@ const config = {
}}
/>

## Rendering Puck fields internally

Use the [`<AutoField>` component](/docs/api-reference/components/auto-field) to render Puck fields within your custom field.

```tsx copy showLineNumbers {1, 12-16}
import { AutoField } from "@measured/puck";

const config = {
components: {
Example: {
fields: {
title: {
type: "custom",
label: "Label Example",
render: ({ field, value, onChange }) => (
<FieldLabel label={field.label}>
<AutoField
field={{ type: "text" }}
onChange={(value) => onChange(value)}
value={value}
/>
</FieldLabel>
),
},
// ...
},
},
},
};
```

<ConfigPreview
label="Example"
componentConfig={{
fields: {
title: {
type: "custom",
label: "AutoField Example",
render: ({ field, value, onChange }) => {
return (
<FieldLabel label={field.label}>
<AutoField
field={{ type: "text" }}
value={value}
onChange={onChange}
/>
</FieldLabel>
);
},
},
},
defaultProps: {
title: "Hello, world",
},
render: ({ title }) => {
return <p style={{ margin: 0 }}>{title}</p>;
},
}}
/>

## Updating the UI state

The [`onChange` function](/docs/api-reference/fields/custom#onchangevalue-ui) can also be used to modify the [Puck UI state](/docs/api-reference/app-state#ui) at the same time as updating the field value:
Expand Down Expand Up @@ -165,4 +225,6 @@ const config = {

## Further reading

- [The `<AutoField>` API reference](/docs/api-reference/components/auto-field)
- [The `<FieldLabel>` API reference](/docs/api-reference/components/field-label)
- [The `custom` field API reference](/docs/api-reference/fields/custom)
3 changes: 2 additions & 1 deletion packages/core/components/AutoField/styles.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,8 @@ select.Input-input {
}

.Input--readOnly > .Input-input,
.Input--readOnly > select.Input-input {
.Input--readOnly > select.Input-input,
.Input-input:read-only {
background-color: var(--puck-color-grey-11);
border-color: var(--puck-color-grey-09);
color: var(--puck-color-grey-04);
Expand Down
2 changes: 2 additions & 0 deletions packages/core/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ export type { PuckAction } from "./reducer/actions";

export * from "./types/Config";
export * from "./types/Fields";

export * from "./components/AutoField";
export * from "./components/Button";
export { Drawer } from "./components/Drawer";

Expand Down
2 changes: 2 additions & 0 deletions packages/core/types/Overrides.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ export type FieldRenderFunctions = Omit<
[Type in Field["type"]]: React.FunctionComponent<
FieldProps<Extract<Field, { type: Type }>> & {
children: ReactNode;
name: string;
}
>;
},
Expand All @@ -61,6 +62,7 @@ export type FieldRenderFunctions = Omit<
[key: string]: React.FunctionComponent<
FieldProps<any> & {
children: ReactNode;
name: string;
}
>;
};

0 comments on commit 106028b

Please sign in to comment.