feat: add shortcut in select like pendant, resolved #528

This commit is contained in:
qishaoxuan 2022-07-25 19:06:22 +08:00
parent 21fbadb399
commit dd75c36a4a

View File

@ -1,4 +1,10 @@
import React, { CSSProperties, useEffect, useState } from 'react'; import React, {
CSSProperties,
useEffect,
useState,
KeyboardEvent,
useRef,
} from 'react';
import { Add, Delete, Close } from '@mui/icons-material'; import { Add, Delete, Close } from '@mui/icons-material';
import { ModifyPanelContentProps } from './types'; import { ModifyPanelContentProps } from './types';
import { import {
@ -10,7 +16,13 @@ import {
RecastBlockValue, RecastBlockValue,
RecastMetaProperty, RecastMetaProperty,
} from '../../recast-block'; } from '../../recast-block';
import { Checkbox, Radio, styled, useTheme } from '@toeverything/components/ui'; import {
Checkbox,
Radio,
styled,
useTheme,
Tooltip,
} from '@toeverything/components/ui';
import { HighLightIconInput } from './IconInput'; import { HighLightIconInput } from './IconInput';
import { import {
PendantIconConfig, PendantIconConfig,
@ -33,10 +45,13 @@ type OptionItemType = {
background: CSSProperties['background']; background: CSSProperties['background'];
color: CSSProperties['color']; color: CSSProperties['color'];
}; };
onEnter?: (e: KeyboardEvent) => void;
focused?: boolean;
}; };
type SelectPropsType = { type SelectPropsType = {
isMulti?: boolean; isMulti?: boolean;
onEnter?: (e: KeyboardEvent) => void;
} & ModifyPanelContentProps; } & ModifyPanelContentProps;
export const BasicSelect = ({ export const BasicSelect = ({
@ -53,9 +68,11 @@ export const BasicSelect = ({
onValueChange: (value: any) => void; onValueChange: (value: any) => void;
onPropertyChange?: (newProperty: any) => void; onPropertyChange?: (newProperty: any) => void;
iconConfig?: PendantIconConfig; iconConfig?: PendantIconConfig;
onEnter?: (e: KeyboardEvent) => void;
}) => { }) => {
const [options, setOptions] = useState<OptionType[]>(initialOptions); const [options, setOptions] = useState<OptionType[]>(initialOptions);
const [selectIds, setSelectIds] = useState<OptionIdType[]>(initialValue); const [selectIds, setSelectIds] = useState<OptionIdType[]>(initialValue);
const [focusedId, setFocusedId] = useState<OptionIdType>();
const insertOption = (insertId: OptionIdType) => { const insertOption = (insertId: OptionIdType) => {
const newOption = genBasicOption({ const newOption = genBasicOption({
@ -98,14 +115,18 @@ export const BasicSelect = ({
useEffect(() => { useEffect(() => {
onValueChange(isMulti ? selectIds : selectIds[0]); onValueChange(isMulti ? selectIds : selectIds[0]);
}, [selectIds]); }, [selectIds, onValueChange]);
useEffect(() => { useEffect(() => {
if (options.every(o => !o.name)) { if (options.every(o => !o.name)) {
return; return;
} }
onPropertyChange?.([...options.filter(o => o.name)]); onPropertyChange?.([...options.filter(o => o.name)]);
}, [options]); }, [options, onPropertyChange]);
useEffect(() => {
setFocusedId(options[options.length - 1].id);
}, [options.length]);
return ( return (
<div className=""> <div className="">
@ -115,6 +136,7 @@ export const BasicSelect = ({
return ( return (
<OptionItem <OptionItem
key={option.id} key={option.id}
focused={focusedId === option.id}
isMulti={isMulti} isMulti={isMulti}
checked={checked} checked={checked}
option={option} option={option}
@ -127,6 +149,9 @@ export const BasicSelect = ({
color: option?.color, color: option?.color,
background: option?.background, background: option?.background,
}} }}
onEnter={() => {
insertOption(options[options.length - 1].id);
}}
/> />
); );
})} })}
@ -183,15 +208,34 @@ const OptionItem = ({
checked, checked,
isMulti, isMulti,
iconConfig, iconConfig,
onEnter,
focused,
}: OptionItemType) => { }: OptionItemType) => {
const theme = useTheme(); const theme = useTheme();
const inputRef = useRef<HTMLInputElement>();
useEffect(() => {
inputRef.current?.focus();
}, [focused]);
return ( return (
<HighLightIconInput <HighLightIconInput
componentsProps={{
input: {
ref: ref => (inputRef.current = ref),
},
}}
iconName={iconConfig?.name} iconName={iconConfig?.name}
color={iconConfig?.color} color={iconConfig?.color}
background={iconConfig?.background} background={iconConfig?.background}
value={option.name} value={option.name}
placeholder="Option content" placeholder="Option content"
onKeyDown={e => {
if (e.keyCode === 13) {
onEnter?.(e);
}
if (e.ctrlKey && e.keyCode === 8) {
onDelete?.(option.id);
}
}}
onChange={e => { onChange={e => {
onNameChange(option.id, e.target.value); onNameChange(option.id, e.target.value);
}} }}
@ -222,12 +266,14 @@ const OptionItem = ({
onDelete(option.id); onDelete(option.id);
}} }}
> >
<Close <Tooltip content="ctrl + backspace">
style={{ <Close
fontSize: 12, style={{
color: theme.affine.palette.icons, fontSize: 12,
}} color: theme.affine.palette.icons,
/> }}
/>
</Tooltip>
</StyledCloseButton> </StyledCloseButton>
} }
/> />