Skip to content

Commit

Permalink
Add AutocompleteField and AsyncAutocompleteField components (#2141)
Browse files Browse the repository at this point in the history
**Examples**

```tsx
<AutocompleteField
    name="autocomplete"
    label="Autocomplete"
    options={[
        { value: "chocolate", label: "Chocolate" },
        { value: "strawberry", label: "Strawberry" },
        { value: "vanilla", label: "Vanilla" },
    ]}
    getOptionLabel={(option: Option) => option.label}
    isOptionEqualToValue={(option: Option, value: Option) => option.value === value.value}
    fullWidth
/>
```

```tsx
<AsyncAutocompleteField
    name="asyncAutocomplete"
    label="Async Autocomplete"
    loadOptions={async () => {
        // Load options here
    }}
    getOptionLabel={(option: Option) => option.label}
    isOptionEqualToValue={(option: Option, value: Option) => option.value === value.value}
    fullWidth
/>
```
  • Loading branch information
johnnyomair authored Jun 11, 2024
1 parent c51b250 commit 796e832
Show file tree
Hide file tree
Showing 5 changed files with 113 additions and 1 deletion.
35 changes: 35 additions & 0 deletions .changeset/olive-panthers-act.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
---
"@comet/admin": minor
---

Add `AutocompleteField` and `AsyncAutocompleteField` components

**Examples**

```tsx
<AutocompleteField
name="autocomplete"
label="Autocomplete"
options={[
{ value: "chocolate", label: "Chocolate" },
{ value: "strawberry", label: "Strawberry" },
{ value: "vanilla", label: "Vanilla" },
]}
getOptionLabel={(option: Option) => option.label}
isOptionEqualToValue={(option: Option, value: Option) => option.value === value.value}
fullWidth
/>
```

```tsx
<AsyncAutocompleteField
name="asyncAutocomplete"
label="Async Autocomplete"
loadOptions={async () => {
// Load options here
}}
getOptionLabel={(option: Option) => option.label}
isOptionEqualToValue={(option: Option, value: Option) => option.value === value.value}
fullWidth
/>
```
25 changes: 25 additions & 0 deletions packages/admin/admin/src/form/fields/AsyncAutocompleteField.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { AutocompleteProps } from "@mui/material";
import React from "react";

import { Field, FieldProps } from "../Field";
import { FinalFormAsyncAutocomplete } from "../FinalFormAsyncAutocomplete";

export type AsyncAutocompleteFieldProps<
T extends Record<string, any>,
Multiple extends boolean | undefined,
DisableClearable extends boolean | undefined,
FreeSolo extends boolean | undefined,
> = FieldProps<T, HTMLInputElement | HTMLTextAreaElement> & {
loadOptions: () => Promise<T[]>;
} & Omit<AutocompleteProps<T, Multiple, DisableClearable, FreeSolo>, "options" | "renderInput"> & {
clearable?: boolean;
};

export function AsyncAutocompleteField<
T extends Record<string, any>,
Multiple extends boolean | undefined,
DisableClearable extends boolean | undefined,
FreeSolo extends boolean | undefined,
>(props: AsyncAutocompleteFieldProps<T, Multiple, DisableClearable, FreeSolo>) {
return <Field component={FinalFormAsyncAutocomplete} {...props} />;
}
26 changes: 26 additions & 0 deletions packages/admin/admin/src/form/fields/AutocompleteField.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { AutocompleteProps } from "@mui/material";
import React from "react";

import { AsyncOptionsProps } from "../../hooks/useAsyncOptionsProps";
import FinalFormAutocomplete from "../Autocomplete";
import { Field, FieldProps } from "../Field";

export type AutocompleteFieldProps<
T extends Record<string, any>,
Multiple extends boolean | undefined,
DisableClearable extends boolean | undefined,
FreeSolo extends boolean | undefined,
> = FieldProps<T, HTMLInputElement | HTMLTextAreaElement> &
Partial<AsyncOptionsProps<T>> &
Omit<AutocompleteProps<T, Multiple, DisableClearable, FreeSolo>, "renderInput"> & {
clearable?: boolean;
};

export function AutocompleteField<
T extends Record<string, any>,
Multiple extends boolean | undefined,
DisableClearable extends boolean | undefined,
FreeSolo extends boolean | undefined,
>(props: AutocompleteFieldProps<T, Multiple, DisableClearable, FreeSolo>) {
return <Field component={FinalFormAutocomplete} {...props} />;
}
2 changes: 2 additions & 0 deletions packages/admin/admin/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,9 @@ export { FinalFormAutocomplete, FinalFormAutocompleteProps } from "./form/Autoco
export { FinalFormCheckbox, FinalFormCheckboxProps } from "./form/Checkbox";
export { Field, FieldProps } from "./form/Field";
export { FieldContainer, FieldContainerClassKey, FieldContainerComponent, FieldContainerProps } from "./form/FieldContainer";
export { AsyncAutocompleteField, AsyncAutocompleteFieldProps } from "./form/fields/AsyncAutocompleteField";
export { AsyncSelectField, AsyncSelectFieldProps } from "./form/fields/AsyncSelectField";
export { AutocompleteField, AutocompleteFieldProps } from "./form/fields/AutocompleteField";
export { CheckboxField, CheckboxFieldProps } from "./form/fields/CheckboxField";
export { SearchField, SearchFieldProps } from "./form/fields/SearchField";
export { SelectField, SelectFieldProps } from "./form/fields/SelectField";
Expand Down
26 changes: 25 additions & 1 deletion storybook/src/admin/form/AllFieldComponents.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import {
AsyncAutocompleteField,
AsyncSelectField,
AutocompleteField,
CheckboxField,
Field,
FieldContainer,
Expand All @@ -23,18 +25,22 @@ import * as React from "react";
import { Form } from "react-final-form";

function Story() {
type Option = { value: string; label: string };

const options = [
{ value: "chocolate", label: "Chocolate" },
{ value: "strawberry", label: "Strawberry" },
{ value: "vanilla", label: "Vanilla" },
];

const initalValues = React.useMemo(() => ({ multiSelect: [] }), []);

return (
<Form
onSubmit={(values) => {
alert(JSON.stringify(values, undefined, 2));
}}
initialValues={{ multiSelect: [] }}
initialValues={initalValues}
render={({ handleSubmit, values }) => (
<form onSubmit={handleSubmit}>
<Grid container mb={2} spacing={2}>
Expand All @@ -61,6 +67,24 @@ function Story() {
getOptionLabel={(option) => option.label}
fullWidth
/>
<AutocompleteField
name="autocomplete"
label="Autocomplete"
options={options}
getOptionLabel={(option: Option) => option.label}
isOptionEqualToValue={(option: Option, value: Option) => option.value === value.value}
fullWidth
/>
<AsyncAutocompleteField
name="asyncAutocomplete"
label="Async Autocomplete"
loadOptions={async () => {
return new Promise<typeof options>((resolve) => setTimeout(() => resolve(options), 1000));
}}
getOptionLabel={(option: Option) => option.label}
isOptionEqualToValue={(option: Option, value: Option) => option.value === value.value}
fullWidth
/>
<CheckboxField
name="singleCheckboxWithLink"
label={
Expand Down

0 comments on commit 796e832

Please sign in to comment.