Skip to content

Commit da8e23e

Browse files
authored
Revert "refactor(Autocomplete)!: use Option component to define autocomplete …"
This reverts commit 9488e41.
1 parent 6f0a4b1 commit da8e23e

File tree

13 files changed

+100
-144
lines changed

13 files changed

+100
-144
lines changed

apps/docs/src/content/03-components/form-controls/autocomplete/examples/default.tsx

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import {
2-
Option,
2+
ContextMenu,
33
Label,
44
TextField,
5+
MenuItem,
56
Autocomplete,
67
} from "@mittwald/flow-react-components";
78
import { useState } from "react";
@@ -18,9 +19,9 @@ export default () => {
1819
].map((d) => {
1920
const email = `${input.split("@")[0]}@${d}`;
2021
return (
21-
<Option key={email} value={email} textValue={email}>
22+
<MenuItem key={email} id={email} textValue={email}>
2223
{email}
23-
</Option>
24+
</MenuItem>
2425
);
2526
});
2627
};
@@ -30,7 +31,7 @@ export default () => {
3031
<TextField value={input} onChange={setInput}>
3132
<Label>Email</Label>
3233
</TextField>
33-
{generateSuggestItems()}
34+
<ContextMenu>{generateSuggestItems()}</ContextMenu>
3435
</Autocomplete>
3536
);
3637
};

apps/docs/src/content/03-components/form-controls/autocomplete/examples/filter.tsx

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import {
2-
Option,
2+
ContextMenu,
33
Label,
44
TextField,
5+
MenuItem,
56
Autocomplete,
67
} from "@mittwald/flow-react-components";
78
import { useState } from "react";
@@ -18,9 +19,9 @@ export default () => {
1819
].map((d) => {
1920
const email = `${input.split("@")[0]}@${d}`;
2021
return (
21-
<Option key={email} value={email} textValue={email}>
22+
<MenuItem key={email} id={email} textValue={email}>
2223
{email}
23-
</Option>
24+
</MenuItem>
2425
);
2526
});
2627
};
@@ -37,7 +38,7 @@ export default () => {
3738
<TextField value={input} onChange={setInput}>
3839
<Label>Email</Label>
3940
</TextField>
40-
{generateSuggestItems()}
41+
<ContextMenu>{generateSuggestItems()}</ContextMenu>
4142
</Autocomplete>
4243
);
4344
};

apps/docs/src/content/03-components/form-controls/autocomplete/examples/form.tsx

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ import {
44
Autocomplete,
55
Section,
66
TextField,
7-
Option,
7+
ContextMenu,
8+
MenuItem,
89
} from "@mittwald/flow-react-components";
910
import { useForm } from "react-hook-form";
1011
import {
@@ -31,9 +32,9 @@ export default () => {
3132
].map((d) => {
3233
const email = `${currentEmailValue.split("@")[0]}@${d}`;
3334
return (
34-
<Option key={email} value={email} textValue={email}>
35+
<MenuItem key={email} id={email} textValue={email}>
3536
{email}
36-
</Option>
37+
</MenuItem>
3738
);
3839
});
3940
};
@@ -51,7 +52,9 @@ export default () => {
5152
<TextField>
5253
<Label>Test</Label>
5354
</TextField>
54-
{generateSuggestItems()}
55+
<ContextMenu>
56+
{generateSuggestItems()}
57+
</ContextMenu>
5558
</Autocomplete>
5659
</Field>
5760
<Button type="submit">Speichern</Button>

apps/docs/src/content/03-components/form-controls/autocomplete/examples/search.tsx

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import {
2+
ContextMenu,
23
Label,
4+
MenuItem,
35
Autocomplete,
46
SearchField,
5-
Option,
67
} from "@mittwald/flow-react-components";
78
import { useState } from "react";
89

@@ -18,9 +19,9 @@ export default () => {
1819
].map((d) => {
1920
const email = `${input.split("@")[0]}@${d}`;
2021
return (
21-
<Option key={email} value={email} textValue={email}>
22+
<MenuItem key={email} id={email} textValue={email}>
2223
{email}
23-
</Option>
24+
</MenuItem>
2425
);
2526
});
2627
};
@@ -30,7 +31,7 @@ export default () => {
3031
<SearchField value={input} onChange={setInput}>
3132
<Label>Email</Label>
3233
</SearchField>
33-
{generateSuggestItems()}
34+
<ContextMenu>{generateSuggestItems()}</ContextMenu>
3435
</Autocomplete>
3536
);
3637
};

apps/remote-dom-demo/src/app/remote/react-hook-form/page.tsx

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ import {
1313
TextField,
1414
PasswordCreationField,
1515
Autocomplete,
16+
ContextMenu,
17+
MenuItem,
1618
} from "@mittwald/flow-remote-react-components";
1719
import {
1820
Form,
@@ -60,12 +62,14 @@ export default function Page() {
6062
<TextField>
6163
<Label>Email</Label>
6264
</TextField>
63-
<Option textValue="Foo" value="Foo">
64-
Foo
65-
</Option>
66-
<Option textValue="Bar" value="Bar">
67-
Bar
68-
</Option>
65+
<ContextMenu>
66+
<MenuItem textValue="Foo" id="Foo">
67+
Foo
68+
</MenuItem>
69+
<MenuItem textValue="Bar" id="Bar">
70+
Bar
71+
</MenuItem>
72+
</ContextMenu>
6973
</Autocomplete>
7074
</Field>
7175
<Field name="comment">

apps/remote-dom-demo/src/app/remote/simple-form/page.tsx

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ import {
1313
CheckboxGroup,
1414
Checkbox,
1515
Button,
16+
ContextMenu,
17+
MenuItem,
1618
Autocomplete,
1719
} from "@mittwald/flow-remote-react-components";
1820
import { useState } from "react";
@@ -51,12 +53,14 @@ export default function Page() {
5153
</RadioGroup>
5254
<Autocomplete>
5355
<TextField name="text" aria-label="Text" />
54-
<Option textValue="Foo" value="Foo">
55-
Foo
56-
</Option>
57-
<Option textValue="Bar" value="Bar">
58-
Bar
59-
</Option>
56+
<ContextMenu>
57+
<MenuItem textValue="Foo" id="Foo">
58+
Foo
59+
</MenuItem>
60+
<MenuItem textValue="Bar" id="Bar">
61+
Bar
62+
</MenuItem>
63+
</ContextMenu>
6064
</Autocomplete>
6165

6266
<Select name="select" aria-label="Select">
Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,3 @@
1-
.autocomplete {
2-
display: flex;
3-
}
4-
51
.empty {
62
padding: var(--size-px--xs) var(--size-px--s);
73
}

packages/components/src/components/Autocomplete/Autocomplete.tsx

Lines changed: 38 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,13 @@ import {
77
flowComponent,
88
type FlowComponentProps,
99
} from "@/lib/componentFactory/flowComponent";
10+
import { useLocalizedStringFormatter } from "react-aria";
11+
import styles from "./Autocomplete.module.scss";
12+
import locales from "./locales/*.locale.json";
13+
import { Text } from "@/components/Text";
1014
import type { SearchFieldProps } from "@/components/SearchField";
1115
import type { TextFieldProps } from "@/components/TextField";
12-
import Options from "@/components/Options";
13-
import { TunnelExit } from "@mittwald/react-tunnel";
14-
import locales from "./locales/*.locale.json";
15-
import Text from "@/components/Text";
16-
import styles from "./Autocomplete.module.scss";
17-
import {
18-
UNSAFE_PortalProvider,
19-
useFocusWithin,
20-
useLocalizedStringFormatter,
21-
} from "react-aria";
16+
2217
export interface AutocompleteProps
2318
extends PropsWithChildren,
2419
PropsWithClassName,
@@ -28,21 +23,17 @@ export interface AutocompleteProps
2823
/** @flr-generate all */
2924
export const Autocomplete = flowComponent("Autocomplete", (props) => {
3025
const { children, ...rest } = props;
26+
const stringFormatter = useLocalizedStringFormatter(locales);
3127

3228
const { contains } = Aria.useFilter({ sensitivity: "base" });
33-
const stringFormatter = useLocalizedStringFormatter(locales);
34-
const container = useRef(null);
29+
3530
const triggerRef = useRef<HTMLInputElement>(null);
3631

37-
const controller = useOverlayController("Popover", {
32+
const controller = useOverlayController("ContextMenu", {
3833
reuseControllerFromContext: false,
3934
});
4035
const menuIsOpen = controller.useIsOpen();
4136

42-
const focusWithin = useFocusWithin({
43-
onBlurWithin: controller.close,
44-
});
45-
4637
const inputProps: SearchFieldProps & TextFieldProps = {
4738
onKeyDown: (e) => {
4839
if (e.key === "Enter" && menuIsOpen) {
@@ -52,18 +43,32 @@ export const Autocomplete = flowComponent("Autocomplete", (props) => {
5243
ref: triggerRef,
5344
};
5445

55-
const renderEmptyState = () => (
56-
<Text className={styles.empty}>
57-
{stringFormatter.format("autocomplete.empty")}
58-
</Text>
59-
);
60-
6146
const propsContext: PropsContext = {
47+
ContextMenu: {
48+
placement: "bottom start",
49+
controller,
50+
isNonModal: true,
51+
renderEmptyState: () => (
52+
<Text className={styles.empty}>
53+
{stringFormatter.format("autocomplete.empty")}
54+
</Text>
55+
),
56+
onAction: (key) => {
57+
const input = triggerRef.current;
58+
if (input) {
59+
const nativeInputValueSetter = Object.getOwnPropertyDescriptor(
60+
window.HTMLInputElement.prototype,
61+
"value",
62+
)?.set;
63+
nativeInputValueSetter?.call(input, String(key));
64+
const event = new Event("input", { bubbles: true });
65+
input.dispatchEvent(event);
66+
}
67+
},
68+
triggerRef,
69+
},
6270
SearchField: inputProps,
6371
TextField: inputProps,
64-
Option: {
65-
tunnelId: "options",
66-
},
6772
};
6873

6974
const handleOnInputChange = (value: string) => {
@@ -74,49 +79,19 @@ export const Autocomplete = flowComponent("Autocomplete", (props) => {
7479
}
7580
};
7681

77-
const handleOptionAction = (key: Aria.Key) => {
78-
const inputElement = triggerRef.current;
79-
if (inputElement) {
80-
// Set value on input element and trigger change event
81-
const nativeInputValueSetter = Object.getOwnPropertyDescriptor(
82-
window.HTMLInputElement.prototype,
83-
"value",
84-
)?.set;
85-
nativeInputValueSetter?.call(inputElement, String(key));
86-
const event = new Event("change", { bubbles: true });
87-
inputElement.dispatchEvent(event);
88-
}
89-
controller.close();
90-
};
91-
9282
return (
9383
<PropsContextProvider
9484
props={propsContext}
9585
mergeInParentContext
9686
dependencies={[menuIsOpen, controller]}
9787
>
98-
<div {...focusWithin.focusWithinProps} ref={container}>
99-
<UNSAFE_PortalProvider getContainer={() => container.current}>
100-
<Aria.Autocomplete
101-
onInputChange={handleOnInputChange}
102-
filter={contains}
103-
disableAutoFocusFirst
104-
{...rest}
105-
>
106-
{children}
107-
<Options
108-
onAction={handleOptionAction}
109-
triggerRef={triggerRef}
110-
controller={controller}
111-
renderEmptyState={renderEmptyState}
112-
isNonModal
113-
placement="bottom start"
114-
>
115-
<TunnelExit id="options" />
116-
</Options>
117-
</Aria.Autocomplete>
118-
</UNSAFE_PortalProvider>
119-
</div>
88+
<Aria.Autocomplete
89+
onInputChange={handleOnInputChange}
90+
filter={contains}
91+
{...rest}
92+
>
93+
{children}
94+
</Aria.Autocomplete>
12095
</PropsContextProvider>
12196
);
12297
});

packages/components/src/components/Autocomplete/stories/Default.stories.tsx

Lines changed: 5 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ import type { Chat } from "@/components/Chat";
44
import { Autocomplete } from "@/components/Autocomplete";
55
import { Label } from "@/components/Label";
66
import { SearchField } from "@/components/SearchField";
7-
import Option from "@/components/Option";
7+
import { MenuItem } from "@/components/MenuItem";
8+
import { ContextMenu } from "@/components/ContextMenu";
89

910
const meta: Meta<typeof Chat> = {
1011
title: "Form Controls/Autocomplete",
@@ -17,9 +18,9 @@ const meta: Meta<typeof Chat> = {
1718
return ["example.com", "test.org", "email.net", "mail.com"].map((d) => {
1819
const email = `${value.split("@")[0]}@${d}`;
1920
return (
20-
<Option key={email} value={email} textValue={email}>
21+
<MenuItem key={email} id={email} textValue={email}>
2122
{email}
22-
</Option>
23+
</MenuItem>
2324
);
2425
});
2526
};
@@ -31,26 +32,13 @@ const meta: Meta<typeof Chat> = {
3132
<SearchField onChange={setInput} value={input}>
3233
<Label>Test</Label>
3334
</SearchField>
34-
{suggestEmail(input)}
35+
<ContextMenu>{suggestEmail(input)}</ContextMenu>
3536
</Autocomplete>
3637
);
3738
},
3839
};
3940
export default meta;
4041

41-
export const FixedOptions: Story = {
42-
render: () => (
43-
<Autocomplete>
44-
<SearchField>
45-
<Label>Test</Label>
46-
</SearchField>
47-
<Option value="example.com">example.com</Option>
48-
<Option value="domain.de">domain.de</Option>
49-
<Option value="test.org">test.org</Option>
50-
</Autocomplete>
51-
),
52-
};
53-
5442
type Story = StoryObj<typeof Autocomplete>;
5543

5644
export const Default: Story = {};

0 commit comments

Comments
 (0)