mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-12 20:38:52 +00:00
fix(core): handle composition event for Input component (#8351)
close AF-1065
This commit is contained in:
@@ -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',
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -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}
|
||||
|
||||
Reference in New Issue
Block a user