Skip to content

Commit

Permalink
feat: add renderFooter API to external field
Browse files Browse the repository at this point in the history
  • Loading branch information
camhammel authored Nov 14, 2024
1 parent 8ea38c3 commit ccec96e
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 7 deletions.
9 changes: 8 additions & 1 deletion apps/demo/config/blocks/Hero/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,14 @@ export const Hero: ComponentConfig<HeroProps> = {
quote: {
type: "external",
placeholder: "Select a quote",
showSearch: true,
showSearch: false,
renderFooter: ({ items }) => {
return (
<div>
{items.length} result{items.length === 1 ? "" : "s"}
</div>
);
},
filterFields: {
author: {
type: "select",
Expand Down
55 changes: 54 additions & 1 deletion apps/docs/pages/docs/api-reference/fields/external.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,9 @@ const config = {
| [`initialFilters`](#initialfilters) | `{ "rating": 1 }` | Object | - |
| [`initialQuery`](#initialquery) | `initialQuery: "Hello, world"` | String | - |
| [`mapProp()`](#mappropitem) | `mapProp: async ({ title }) => title` | Function | - |
| [`mapRow()`](#mappropitem) | `mapRow: async ({ title }) => title` | Function | - |
| [`mapRow()`](#maprowitem) | `mapRow: async ({ title }) => title` | Function | - |
| [`placeholder`](#placeholder) | `placeholder: "Select content"` | String | - |
| [`renderFooter()`](#renderfooterprops) | `renderFooter: (props) => <p>Hello</p>` | Function | - |
| [`showSearch`](#showsearch) | `showSearch: true` | Boolean | - |

## Required params
Expand Down Expand Up @@ -541,6 +542,58 @@ const config = {
}}
/>

### `renderFooter(props)`

Customize what will be displayed in the footer of the modal.

```tsx {13} copy
const config = {
components: {
Example: {
fields: {
data: {
type: "external",
fetchList: async () => {
return [
{ title: "Hello, world", description: "Lorem ipsum 1" },
{ title: "Goodbye, world", description: "Lorem ipsum 2" },
];
},
renderFooter: ({ items }) => (
<b>Custom footer with {items.length} results</b>
),
},
},
render: ({ data }) => {
return <p>{data || "No data selected"}</p>;
},
// ...
},
},
};
```

<ConfigPreview
label="Example"
componentConfig={{
fields: {
data: {
type: "external",
fetchList: async () => {
return [
{ title: "Hello, world", description: "Lorem ipsum 1" },
{ title: "Goodbye, world", description: "Lorem ipsum 2" },
];
},
renderFooter: ({ items }) => <span>{items.length} results</span>,
},
},
render: ({ data }) => {
return <p>{data?.title || "No data selected"}</p>;
},
}}
/>

### `showSearch`

Show a search input, the value of which will be passed to `fetchList` as the `query` param.
Expand Down
17 changes: 14 additions & 3 deletions packages/core/components/ExternalInput/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,18 @@ export const ExternalInput = ({
[id, field]
);

const Footer = useCallback(
(props: { items: any[] }) =>
field.renderFooter ? (
field.renderFooter(props)
) : (
<span className={getClassNameModal("footer")}>
{props.items.length} result{props.items.length === 1 ? "" : "s"}
</span>
),
[field.renderFooter]
);

useEffect(() => {
search(searchQuery, filters);
}, []);
Expand Down Expand Up @@ -275,9 +287,8 @@ export const ExternalInput = ({
</div>
</div>
</div>

<div className={getClassNameModal("footer")}>
{mappedData.length} result{mappedData.length === 1 ? "" : "s"}
<div className={getClassNameModal("footerContainer")}>
<Footer items={mappedData} />
</div>
</form>
</Modal>
Expand Down
7 changes: 5 additions & 2 deletions packages/core/components/ExternalInput/styles.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -327,12 +327,15 @@
align-self: center;
}

.ExternalInputModal-footer {
.ExternalInputModal-footerContainer {
background-color: var(--puck-color-grey-12);
border-top: 1px solid var(--puck-color-grey-09);
color: var(--puck-color-grey-04);
padding: 16px;
}

.ExternalInputModal-footer {
font-weight: 500;
font-size: 14px;
padding: 16px;
text-align: right;
}
1 change: 1 addition & 0 deletions packages/core/types/Fields.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ export type ExternalField<
mapRow?: (value: any) => Record<string, string | number | ReactElement>;
getItemSummary?: (item: Props, index?: number) => string;
showSearch?: boolean;
renderFooter?: (props: { items: any[] }) => ReactElement;
initialQuery?: string;
filterFields?: Record<string, Field>;
initialFilters?: Record<string, any>;
Expand Down

0 comments on commit ccec96e

Please sign in to comment.