fix(core): handle composition event for Input component (#8351)

close AF-1065
This commit is contained in:
JimmFly
2024-09-25 02:02:23 +00:00
parent ed8e4e30f0
commit 2df2003bd7
10 changed files with 166 additions and 98 deletions

View File

@@ -1,5 +1,11 @@
import type { MenuProps } from '@affine/component';
import { IconButton, Input, Menu, Scrollable } from '@affine/component';
import {
IconButton,
Input,
Menu,
RowInput,
Scrollable,
} from '@affine/component';
import { useNavigateHelper } from '@affine/core/components/hooks/use-navigate-helper';
import { WorkspaceLegacyProperties } from '@affine/core/modules/properties';
import type { Tag } from '@affine/core/modules/tag';
@@ -239,12 +245,9 @@ export const TagsEditor = ({ pageId, readonly }: TagsEditorProps) => {
[setOpen, setSelectedTagIds]
);
const onInputChange = useCallback(
(e: React.ChangeEvent<HTMLInputElement>) => {
setInputValue(e.target.value);
},
[]
);
const onInputChange = useCallback((value: string) => {
setInputValue(value);
}, []);
const onToggleTag = useCallback(
(id: string) => {
@@ -297,14 +300,15 @@ export const TagsEditor = ({ pageId, readonly }: TagsEditorProps) => {
},
[onCreateTag, onToggleTag, focusInput, tagIds.length]
);
const onEnter = useCallback(() => {
if (safeFocusedIndex >= 0) {
onSelectTagOption(tagOptions[safeFocusedIndex]);
}
}, [onSelectTagOption, safeFocusedIndex, tagOptions]);
const onInputKeyDown = useCallback(
(e: React.KeyboardEvent<HTMLInputElement>) => {
if (e.key === 'Enter') {
if (safeFocusedIndex >= 0) {
onSelectTagOption(tagOptions[safeFocusedIndex]);
}
} else if (e.key === 'Backspace' && inputValue === '' && tagIds.length) {
if (e.key === 'Backspace' && inputValue === '' && tagIds.length) {
const tagToRemove =
safeInlineFocusedIndex < 0 || safeInlineFocusedIndex >= tagIds.length
? tagIds.length - 1
@@ -341,7 +345,6 @@ export const TagsEditor = ({ pageId, readonly }: TagsEditorProps) => {
inputValue,
tagIds,
safeFocusedIndex,
onSelectTagOption,
tagOptions,
safeInlineFocusedIndex,
tags,
@@ -358,11 +361,12 @@ export const TagsEditor = ({ pageId, readonly }: TagsEditorProps) => {
focusedIndex={safeInlineFocusedIndex}
onRemove={focusInput}
>
<input
<RowInput
ref={inputRef}
value={inputValue}
onChange={onInputChange}
onKeyDown={onInputKeyDown}
onEnter={onEnter}
autoFocus
className={styles.searchInput}
placeholder="Type here ..."
@@ -380,7 +384,7 @@ export const TagsEditor = ({ pageId, readonly }: TagsEditorProps) => {
>
{tagOptions.map((tag, idx) => {
const commonProps = {
focused: safeFocusedIndex === idx,
...(safeFocusedIndex === idx ? { focused: 'true' } : {}),
onClick: () => onSelectTagOption(tag),
onMouseEnter: () => setFocusedIndex(idx),
['data-testid']: 'tag-selector-item',

View File

@@ -6,6 +6,7 @@ import {
MenuTrigger,
RadioGroup,
type RadioItem,
RowInput,
Scrollable,
Switch,
useConfirmModal,
@@ -33,7 +34,6 @@ import {
} from '@toeverything/infra';
import clsx from 'clsx';
import {
type ChangeEvent,
forwardRef,
type HTMLAttributes,
type PropsWithChildren,
@@ -171,8 +171,8 @@ const FontMenuItems = ({ onSelect }: { onSelect: (font: string) => void }) => {
const searchText = useLiveData(systemFontFamily.searchText$);
const onInputChange = useCallback(
(e: ChangeEvent<HTMLInputElement>) => {
systemFontFamily.search(e.target.value);
(value: string) => {
systemFontFamily.search(value);
},
[systemFontFamily]
);
@@ -187,7 +187,7 @@ const FontMenuItems = ({ onSelect }: { onSelect: (font: string) => void }) => {
<div>
<div className={styles.InputContainer}>
<SearchIcon className={styles.searchIcon} />
<input
<RowInput
value={searchText ?? ''}
onChange={onInputChange}
onKeyDown={onInputKeyDown}

View File

@@ -2,6 +2,7 @@ import {
Button,
Divider,
Menu,
RowInput,
Scrollable,
useConfirmModal,
} from '@affine/component';
@@ -285,12 +286,9 @@ export const SwitchTag = ({ onClick }: SwitchTagProps) => {
inputValue ? tagList.filterTagsByName$(inputValue) : tagList.tags$
);
const onInputChange = useCallback(
(e: React.ChangeEvent<HTMLInputElement>) => {
setInputValue(e.target.value);
},
[]
);
const onInputChange = useCallback((value: string) => {
setInputValue(value);
}, []);
const handleClick = useCallback(() => {
setInputValue('');
@@ -301,7 +299,7 @@ export const SwitchTag = ({ onClick }: SwitchTagProps) => {
<div className={styles.tagsEditorRoot}>
<div className={styles.tagsEditorSelectedTags}>
<SearchIcon className={styles.searchIcon} />
<input
<RowInput
value={inputValue}
onChange={onInputChange}
autoFocus

View File

@@ -1,4 +1,4 @@
import { Button } from '@affine/component';
import { Button, RowInput } from '@affine/component';
import { useI18n } from '@affine/i18n';
import { type PropsWithChildren, type ReactNode, useCallback } from 'react';
@@ -37,8 +37,8 @@ export const SelectorLayout = ({
const t = useI18n();
const onSearchChange = useCallback(
(e: React.ChangeEvent<HTMLInputElement>) => {
onSearch?.(e.target.value);
(value: string) => {
onSearch?.(value);
},
[onSearch]
);
@@ -46,7 +46,7 @@ export const SelectorLayout = ({
return (
<div className={styles.root}>
<header className={styles.header}>
<input
<RowInput
className={styles.search}
placeholder={searchPlaceholder}
onChange={onSearchChange}

View File

@@ -15,7 +15,6 @@ import {
WorkspacesService,
} from '@toeverything/infra';
import { useSetAtom } from 'jotai';
import type { KeyboardEvent } from 'react';
import { useCallback, useLayoutEffect, useState } from 'react';
import { AuthService } from '../../../modules/cloud';
@@ -76,14 +75,11 @@ const NameWorkspaceContent = ({
);
}, [enable, onConfirmName, workspaceName]);
const handleKeyDown = useCallback(
(event: KeyboardEvent<HTMLInputElement>) => {
if (event.key === 'Enter' && workspaceName) {
handleCreateWorkspace();
}
},
[handleCreateWorkspace, workspaceName]
);
const onEnter = useCallback(() => {
if (workspaceName) {
handleCreateWorkspace();
}
}, [handleCreateWorkspace, workspaceName]);
// Currently, when we create a new workspace and upload an avatar at the same time,
// an error occurs after the creation is successful: get blob 404 not found
@@ -117,7 +113,7 @@ const NameWorkspaceContent = ({
<Input
autoFocus
data-testid="create-workspace-input"
onKeyDown={handleKeyDown}
onEnter={onEnter}
placeholder={t['com.affine.nameWorkspace.placeholder']()}
maxLength={64}
minLength={0}

View File

@@ -1,4 +1,4 @@
import { IconButton, observeResize } from '@affine/component';
import { IconButton, observeResize, RowInput } from '@affine/component';
import {
ArrowDownSmallIcon,
ArrowUpSmallIcon,
@@ -10,7 +10,6 @@ import { useLiveData, useService } from '@toeverything/infra';
import { assignInlineVars } from '@vanilla-extract/dynamic';
import clsx from 'clsx';
import {
type ChangeEventHandler,
type CompositionEventHandler,
type KeyboardEventHandler,
type SetStateAction,
@@ -102,9 +101,8 @@ export const FindInPageModal = () => {
toggle(visible);
}, [visible]);
const handleValueChange: ChangeEventHandler<HTMLInputElement> = useCallback(
e => {
const value = e.target.value;
const handleValueChange = useCallback(
(value: string) => {
setValue(value);
if (!composing) {
findInPage.findInPage(value);
@@ -227,7 +225,7 @@ export const FindInPageModal = () => {
>
<SearchIcon className={styles.searchIcon} />
<div className={styles.inputMain}>
<input
<RowInput
type="text"
autoFocus
value={value}