mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-07-13 16:16:46 +08:00
init: the first public commit for AFFiNE
This commit is contained in:
@@ -0,0 +1,48 @@
|
||||
import { useCallback } from 'react';
|
||||
import { styled } from '../styled';
|
||||
import type { FC, CSSProperties, ChangeEvent } from 'react';
|
||||
|
||||
/**
|
||||
* WARNING: This component is about to be deprecated, use Select replace
|
||||
*
|
||||
* **/
|
||||
const StyledSelect = styled('select')({
|
||||
border: '1px solid #aaa',
|
||||
});
|
||||
|
||||
interface Props {
|
||||
value: string;
|
||||
options?: Array<{ label?: string; value?: string; key?: string }>;
|
||||
onChange: (value: string) => void;
|
||||
extraStyle?: CSSProperties;
|
||||
}
|
||||
|
||||
export const OldSelect: FC<Props> = ({
|
||||
value,
|
||||
options,
|
||||
onChange,
|
||||
extraStyle,
|
||||
}: Props) => {
|
||||
const onSelectChange = useCallback(
|
||||
(e: ChangeEvent<HTMLSelectElement>) => {
|
||||
onChange(e.target.value);
|
||||
},
|
||||
[onChange]
|
||||
);
|
||||
|
||||
return (
|
||||
<StyledSelect
|
||||
style={extraStyle}
|
||||
value={value}
|
||||
onChange={onSelectChange}
|
||||
>
|
||||
{options?.map(option => {
|
||||
return (
|
||||
<option key={option.value} value={option.value}>
|
||||
{option.label}
|
||||
</option>
|
||||
);
|
||||
})}
|
||||
</StyledSelect>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,45 @@
|
||||
/* eslint-disable no-restricted-imports */
|
||||
import OptionUnstyled, {
|
||||
optionUnstyledClasses,
|
||||
} from '@mui/base/OptionUnstyled';
|
||||
|
||||
import { styled } from '../styled';
|
||||
|
||||
/**
|
||||
* Option is extend by mui OptionUnstyled
|
||||
*
|
||||
* OptionUnstyled API:
|
||||
*
|
||||
* - [SelectUnstyled API](https://mui.com/zh/base/api/option-unstyled/)
|
||||
*
|
||||
* **/
|
||||
|
||||
export const Option = styled(OptionUnstyled)(({ theme }) => ({
|
||||
height: '32px',
|
||||
listStyle: 'none',
|
||||
padding: '0 12px',
|
||||
borderRadius: '5px',
|
||||
cursor: 'pointer',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
'&:last-of-type': {
|
||||
borderBottom: 'none',
|
||||
},
|
||||
|
||||
[`&.${optionUnstyledClasses.selected}`]: {
|
||||
backgroundColor: '#F5F7F8',
|
||||
},
|
||||
|
||||
[`&.${optionUnstyledClasses.highlighted}`]: {
|
||||
backgroundColor: '#F5F7F8',
|
||||
},
|
||||
|
||||
[`&.${optionUnstyledClasses.highlighted}.${optionUnstyledClasses.selected}`]:
|
||||
{},
|
||||
|
||||
[`&.${optionUnstyledClasses.disabled}`]: {},
|
||||
|
||||
[`&:hover:not(.${optionUnstyledClasses.disabled})`]: {
|
||||
backgroundColor: '#F5F7F8',
|
||||
},
|
||||
}));
|
||||
@@ -0,0 +1,47 @@
|
||||
import { forwardRef, type ForwardedRef } from 'react';
|
||||
/* eslint-disable no-restricted-imports */
|
||||
import OptionGroupUnstyled, {
|
||||
OptionGroupUnstyledProps,
|
||||
} from '@mui/base/OptionGroupUnstyled';
|
||||
import { styled } from '../styled';
|
||||
|
||||
const StyledGroupRoot = styled('li')`
|
||||
list-style: none;
|
||||
`;
|
||||
|
||||
const StyledGroupHeader = styled('span')`
|
||||
display: block;
|
||||
padding: 15px 0 5px 10px;
|
||||
font-size: 0.75em;
|
||||
font-weight: 600;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.05rem;
|
||||
color: #6f7e8c;
|
||||
`;
|
||||
|
||||
const StyledGroupOptions = styled('ul')`
|
||||
list-style: none;
|
||||
margin-left: 0;
|
||||
padding: 0;
|
||||
|
||||
> li {
|
||||
padding-left: 20px;
|
||||
}
|
||||
`;
|
||||
|
||||
/**
|
||||
* TODO: The designer has not yet given a style for OptionGroup, the sample style is used here
|
||||
* **/
|
||||
export const OptionGroup = forwardRef(function CustomOptionGroup(
|
||||
props: OptionGroupUnstyledProps,
|
||||
ref: ForwardedRef<HTMLLIElement>
|
||||
) {
|
||||
const components: OptionGroupUnstyledProps['components'] = {
|
||||
Root: StyledGroupRoot,
|
||||
Label: StyledGroupHeader,
|
||||
List: StyledGroupOptions,
|
||||
...props.components,
|
||||
};
|
||||
|
||||
return <OptionGroupUnstyled {...props} ref={ref} components={components} />;
|
||||
});
|
||||
@@ -0,0 +1,129 @@
|
||||
import {
|
||||
forwardRef,
|
||||
type CSSProperties,
|
||||
type ForwardedRef,
|
||||
type RefAttributes,
|
||||
type ReactNode,
|
||||
} from 'react';
|
||||
/* eslint-disable no-restricted-imports */
|
||||
import SelectUnstyled, {
|
||||
type SelectUnstyledProps,
|
||||
selectUnstyledClasses,
|
||||
} from '@mui/base/SelectUnstyled';
|
||||
/* eslint-disable no-restricted-imports */
|
||||
import PopperUnstyled from '@mui/base/PopperUnstyled';
|
||||
import { styled } from '../styled';
|
||||
|
||||
type ExtendSelectProps = {
|
||||
// Width is always used custom, it will be set to root button and popover
|
||||
width?: number | string;
|
||||
style?: CSSProperties;
|
||||
listboxStyle?: CSSProperties;
|
||||
placeholder?: ReactNode;
|
||||
};
|
||||
|
||||
/**
|
||||
* Select is extend by mui SelectUnstyled
|
||||
*
|
||||
* SelectUnstyled Demos:
|
||||
*
|
||||
* - [SelectUnstyled](https://mui.com/zh/base/react-select/)
|
||||
*
|
||||
* SelectUnstyled API:
|
||||
*
|
||||
* - [SelectUnstyled API](https://mui.com/zh/base/api/select-unstyled/)
|
||||
*
|
||||
* **/
|
||||
export const Select = forwardRef(function CustomSelect<TValue>(
|
||||
props: ExtendSelectProps & SelectUnstyledProps<TValue>,
|
||||
ref: ForwardedRef<HTMLUListElement>
|
||||
) {
|
||||
const { width = '100%', style, listboxStyle, placeholder } = props;
|
||||
const components: SelectUnstyledProps<TValue>['components'] = {
|
||||
// Root: generateStyledRoot({ width, ...style }),
|
||||
Root: forwardRef((rootProps, rootRef) => (
|
||||
<StyledRoot
|
||||
ref={rootRef}
|
||||
{...rootProps}
|
||||
style={{
|
||||
width,
|
||||
...style,
|
||||
}}
|
||||
>
|
||||
{rootProps.children || (
|
||||
<StyledPlaceholder>{placeholder}</StyledPlaceholder>
|
||||
)}
|
||||
</StyledRoot>
|
||||
)),
|
||||
Listbox: forwardRef((listboxProps, listboxRef) => (
|
||||
<StyledListbox
|
||||
ref={listboxRef}
|
||||
{...listboxProps}
|
||||
style={{ width, ...listboxStyle }}
|
||||
/>
|
||||
)),
|
||||
Popper: StyledPopper,
|
||||
...props.components,
|
||||
};
|
||||
|
||||
return <SelectUnstyled {...props} ref={ref} components={components} />;
|
||||
}) as <TValue>(
|
||||
props: ExtendSelectProps &
|
||||
SelectUnstyledProps<TValue> &
|
||||
RefAttributes<HTMLUListElement>
|
||||
) => JSX.Element;
|
||||
|
||||
const StyledRoot = styled('div')(({ theme }) => ({
|
||||
height: '32px',
|
||||
border: `1px solid ${theme.affine.palette.borderColor}`,
|
||||
borderRadius: '10px',
|
||||
color: theme.affine.palette.secondaryText,
|
||||
padding: '0 12px',
|
||||
fontSize: '14px',
|
||||
transition: 'border .1s',
|
||||
textAlign: 'left',
|
||||
paddingLeft: '12px',
|
||||
paddingRight: ' 30px',
|
||||
background: '#fff',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
position: 'relative',
|
||||
|
||||
'&:hover': {},
|
||||
|
||||
[`&.${selectUnstyledClasses.focusVisible}`]: {},
|
||||
|
||||
[`&.${selectUnstyledClasses.expanded}`]: {
|
||||
borderColor: `${theme.affine.palette.primary}`,
|
||||
'&::after': {
|
||||
content: '"▴"',
|
||||
},
|
||||
},
|
||||
'&::after': {
|
||||
content: '"▾"',
|
||||
position: ' absolute',
|
||||
top: '0',
|
||||
bottom: '0',
|
||||
right: '12px',
|
||||
margin: 'auto',
|
||||
lineHeight: '32px',
|
||||
},
|
||||
}));
|
||||
|
||||
const StyledListbox = styled('ul')(({ theme }) => ({
|
||||
fontSize: '14px',
|
||||
padding: '8px 4px',
|
||||
color: theme.affine.palette.secondaryText,
|
||||
background: '#fff',
|
||||
borderRadius: '10px',
|
||||
overflow: 'auto',
|
||||
boxShadow: theme.affine.shadows.shadowSxDownLg,
|
||||
}));
|
||||
|
||||
const StyledPopper = styled(PopperUnstyled)`
|
||||
z-index: 1;
|
||||
`;
|
||||
|
||||
const StyledPlaceholder = styled('div')(({ theme }) => ({
|
||||
color: `${theme.affine.palette.borderColor}`,
|
||||
}));
|
||||
@@ -0,0 +1,4 @@
|
||||
export { Select } from './Select';
|
||||
export { Option } from './Option';
|
||||
export { OptionGroup } from './OptionGroup';
|
||||
export { OldSelect } from './OldSelect';
|
||||
Reference in New Issue
Block a user