mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-25 18:26:05 +08:00
feat: add tab-index in select
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
import React, { type CSSProperties, useState } from 'react';
|
import React, { forwardRef, type CSSProperties, useState } from 'react';
|
||||||
import { Input, styled, InputProps } from '@toeverything/components/ui';
|
import { Input, styled, InputProps } from '@toeverything/components/ui';
|
||||||
import { StyledHighLightWrapper } from '../StyledComponent';
|
import { StyledHighLightWrapper } from '../StyledComponent';
|
||||||
import { IconNames } from '../types';
|
import { IconNames } from '../types';
|
||||||
@@ -29,38 +29,39 @@ export const PendantIcon = ({
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const IconInput = ({
|
export const IconInput = forwardRef<HTMLInputElement, IconInputProps>(
|
||||||
iconName,
|
({ iconName, iconStyle, color, background, ...inputProps }, ref) => {
|
||||||
iconStyle,
|
return (
|
||||||
color,
|
<>
|
||||||
background,
|
<PendantIcon
|
||||||
...inputProps
|
iconName={iconName}
|
||||||
}: IconInputProps) => {
|
iconStyle={iconStyle}
|
||||||
return (
|
color={color}
|
||||||
<>
|
background={background}
|
||||||
<PendantIcon
|
/>
|
||||||
iconName={iconName}
|
<Input
|
||||||
iconStyle={iconStyle}
|
ref={ref}
|
||||||
color={color}
|
style={{
|
||||||
background={background}
|
flexGrow: '1',
|
||||||
/>
|
}}
|
||||||
<Input
|
noBorder
|
||||||
style={{
|
{...inputProps}
|
||||||
flexGrow: '1',
|
/>
|
||||||
border: 'none',
|
</>
|
||||||
}}
|
);
|
||||||
{...inputProps}
|
}
|
||||||
/>
|
);
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
type HighLightIconInputProps = {
|
type HighLightIconInputProps = {
|
||||||
startElement?: React.ReactNode;
|
startElement?: React.ReactNode;
|
||||||
endElement?: React.ReactNode;
|
endElement?: React.ReactNode;
|
||||||
|
tabIndex?: number;
|
||||||
} & IconInputProps;
|
} & IconInputProps;
|
||||||
|
|
||||||
export const HighLightIconInput = (props: HighLightIconInputProps) => {
|
export const HighLightIconInput = forwardRef<
|
||||||
|
HTMLInputElement,
|
||||||
|
HighLightIconInputProps
|
||||||
|
>((props, ref) => {
|
||||||
const {
|
const {
|
||||||
onFocus,
|
onFocus,
|
||||||
onBlur,
|
onBlur,
|
||||||
@@ -74,6 +75,7 @@ export const HighLightIconInput = (props: HighLightIconInputProps) => {
|
|||||||
<StyledHighLightWrapper isFocus={focus}>
|
<StyledHighLightWrapper isFocus={focus}>
|
||||||
{startElement}
|
{startElement}
|
||||||
<IconInput
|
<IconInput
|
||||||
|
ref={ref}
|
||||||
onFocus={e => {
|
onFocus={e => {
|
||||||
setFocus(true);
|
setFocus(true);
|
||||||
onFocus?.(e);
|
onFocus?.(e);
|
||||||
@@ -87,7 +89,7 @@ export const HighLightIconInput = (props: HighLightIconInputProps) => {
|
|||||||
{endElement}
|
{endElement}
|
||||||
</StyledHighLightWrapper>
|
</StyledHighLightWrapper>
|
||||||
);
|
);
|
||||||
};
|
});
|
||||||
|
|
||||||
const StyledIconWrapper = styled('div')`
|
const StyledIconWrapper = styled('div')`
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import React, {
|
|||||||
KeyboardEvent,
|
KeyboardEvent,
|
||||||
useRef,
|
useRef,
|
||||||
} from 'react';
|
} from 'react';
|
||||||
import { Add, Delete, Close } from '@mui/icons-material';
|
import { Add, Close } from '@mui/icons-material';
|
||||||
import { ModifyPanelContentProps } from './types';
|
import { ModifyPanelContentProps } from './types';
|
||||||
import {
|
import {
|
||||||
MultiSelectProperty,
|
MultiSelectProperty,
|
||||||
@@ -38,6 +38,7 @@ type OptionItemType = {
|
|||||||
};
|
};
|
||||||
onEnter?: (e: KeyboardEvent) => void;
|
onEnter?: (e: KeyboardEvent) => void;
|
||||||
focused?: boolean;
|
focused?: boolean;
|
||||||
|
tabIndex?: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
type SelectPropsType = {
|
type SelectPropsType = {
|
||||||
@@ -138,6 +139,7 @@ export const BasicSelect = ({
|
|||||||
onEnter={() => {
|
onEnter={() => {
|
||||||
insertOption(options[options.length - 1].id);
|
insertOption(options[options.length - 1].id);
|
||||||
}}
|
}}
|
||||||
|
tabIndex={index + 1}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
@@ -196,6 +198,7 @@ const OptionItem = ({
|
|||||||
iconConfig,
|
iconConfig,
|
||||||
onEnter,
|
onEnter,
|
||||||
focused,
|
focused,
|
||||||
|
tabIndex,
|
||||||
}: OptionItemType) => {
|
}: OptionItemType) => {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const inputRef = useRef<HTMLInputElement>();
|
const inputRef = useRef<HTMLInputElement>();
|
||||||
@@ -204,11 +207,8 @@ const OptionItem = ({
|
|||||||
}, [focused]);
|
}, [focused]);
|
||||||
return (
|
return (
|
||||||
<HighLightIconInput
|
<HighLightIconInput
|
||||||
componentsProps={{
|
tabIndex={tabIndex}
|
||||||
input: {
|
ref={inputRef}
|
||||||
ref: inputRef,
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
iconName={iconConfig?.name}
|
iconName={iconConfig?.name}
|
||||||
color={iconConfig?.color}
|
color={iconConfig?.color}
|
||||||
background={iconConfig?.background}
|
background={iconConfig?.background}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ export default ({
|
|||||||
initialValue,
|
initialValue,
|
||||||
iconConfig,
|
iconConfig,
|
||||||
}: ModifyPanelContentProps) => {
|
}: ModifyPanelContentProps) => {
|
||||||
const [text, setText] = useState(initialValue?.value || '');
|
const [text, setText] = useState((initialValue?.value as string) || '');
|
||||||
return (
|
return (
|
||||||
<HighLightIconInput
|
<HighLightIconInput
|
||||||
iconName={iconConfig?.iconName}
|
iconName={iconConfig?.iconName}
|
||||||
|
|||||||
@@ -1,57 +1,62 @@
|
|||||||
import { forwardRef, type ForwardedRef } from 'react';
|
import React, {
|
||||||
/* eslint-disable no-restricted-imports */
|
forwardRef,
|
||||||
import InputUnstyled, {
|
type ForwardedRef,
|
||||||
inputUnstyledClasses,
|
type InputHTMLAttributes,
|
||||||
type InputUnstyledProps,
|
type CSSProperties,
|
||||||
} from '@mui/base/InputUnstyled';
|
} from 'react';
|
||||||
import { styled } from '../styled';
|
import { styled } from '../styled';
|
||||||
|
|
||||||
/**
|
export type InputProps = {
|
||||||
* Input is extend by mui InputUnstyled
|
startAdornment?: React.ReactNode;
|
||||||
*
|
endAdornment?: React.ReactNode;
|
||||||
* InputUnstyled Demos:
|
style?: CSSProperties;
|
||||||
*
|
noBorder?: boolean;
|
||||||
* - [Input](https://mui.com/base/react-input/)
|
} & InputHTMLAttributes<HTMLInputElement>;
|
||||||
*
|
|
||||||
* InputUnstyled API:
|
|
||||||
*
|
|
||||||
* - [InputUnstyled API](https://mui.com/base/api/input-unstyled/)
|
|
||||||
*
|
|
||||||
* **/
|
|
||||||
export type InputProps = InputUnstyledProps;
|
|
||||||
|
|
||||||
export const Input = forwardRef(function CustomInput(
|
export const Input = forwardRef(
|
||||||
props: InputUnstyledProps,
|
(props: InputProps, ref: ForwardedRef<HTMLInputElement>) => {
|
||||||
ref: ForwardedRef<HTMLDivElement>
|
// const { getRootProps, getInputProps } = useInput(props);
|
||||||
) {
|
const {
|
||||||
const { components, ...other } = props;
|
style,
|
||||||
return (
|
startAdornment = null,
|
||||||
<InputUnstyled
|
endAdornment = null,
|
||||||
components={{
|
onClick,
|
||||||
Root: StyledInputRoot,
|
noBorder = false,
|
||||||
Input: StyledInputElement,
|
...inputProps
|
||||||
...components,
|
} = props;
|
||||||
}}
|
|
||||||
{...other}
|
|
||||||
ref={ref}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
const StyledInputRoot = styled('div')(({ theme }) => ({
|
return (
|
||||||
height: '32px',
|
<StyledInputRoot
|
||||||
display: 'flex',
|
noBorder={noBorder}
|
||||||
border: `1px solid ${theme.affine.palette.borderColor}`,
|
style={style}
|
||||||
borderRadius: '10px',
|
onClick={onClick}
|
||||||
color: `${theme.affine.palette.secondaryText}`,
|
>
|
||||||
padding: '0 12px',
|
{startAdornment}
|
||||||
fontSize: '14px',
|
<StyledInputElement ref={ref} {...inputProps} />
|
||||||
lineHeight: '1.5',
|
{endAdornment}
|
||||||
transition: 'border .1s',
|
</StyledInputRoot>
|
||||||
[`&.${inputUnstyledClasses.focused}`]: {
|
);
|
||||||
borderColor: `${theme.affine.palette.primary}`,
|
}
|
||||||
},
|
);
|
||||||
}));
|
|
||||||
|
const StyledInputRoot = styled('div')<{ noBorder: boolean }>(
|
||||||
|
({ noBorder, theme }) => ({
|
||||||
|
height: '32px',
|
||||||
|
display: 'flex',
|
||||||
|
border: noBorder
|
||||||
|
? 'none'
|
||||||
|
: `1px solid ${theme.affine.palette.borderColor}`,
|
||||||
|
borderRadius: '10px',
|
||||||
|
color: `${theme.affine.palette.secondaryText}`,
|
||||||
|
padding: '0 12px',
|
||||||
|
fontSize: '14px',
|
||||||
|
lineHeight: '1.5',
|
||||||
|
transition: 'border .1s',
|
||||||
|
'&:focus-within': {
|
||||||
|
borderColor: `${theme.affine.palette.primary}`,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
const StyledInputElement = styled('input')(({ theme }) => ({
|
const StyledInputElement = styled('input')(({ theme }) => ({
|
||||||
fontSize: '14px',
|
fontSize: '14px',
|
||||||
|
|||||||
Reference in New Issue
Block a user