Skip to content

Commit

Permalink
fix: ๐Ÿ› replace defaultProps with useDefaultProps (#2622)
Browse files Browse the repository at this point in the history
* fix: ๐Ÿ› replace defaultProps with useDefaultProps

* fix: ๐Ÿ› replace defaultProps with useDefaultProps
  • Loading branch information
li-jia-nan authored Dec 11, 2023
1 parent 1b8e398 commit 540df37
Show file tree
Hide file tree
Showing 6 changed files with 71 additions and 59 deletions.
2 changes: 1 addition & 1 deletion src/select/base/Option.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export interface SelectOptionProps

const componentType = 'select';

const Option = (props: SelectOptionProps) => {
const Option: React.FC<SelectOptionProps> = (props) => {
const {
disabled: propDisabled,
label: propLabel,
Expand Down
16 changes: 9 additions & 7 deletions src/select/base/OptionGroup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import useConfig from '../../hooks/useConfig';

import { TdOptionGroupProps, SelectValue } from '../type';
import { optionGroupDefaultProps } from '../defaultProps';
import useDefaultProps from '../../hooks/useDefaultProps';

export interface SelectGOptionGroupProps extends TdOptionGroupProps {
selectedValue?: SelectValue;
Expand All @@ -16,15 +17,18 @@ export interface SelectGOptionGroupProps extends TdOptionGroupProps {
multiple?: boolean;
}

const OptionGroup = (props: SelectGOptionGroupProps) => {
const { children, label, selectedValue, onSelect, divider, multiple } = props;
const OptionGroup: React.FC<SelectGOptionGroupProps> = (props) => {
const { children, label, selectedValue, onSelect, divider, multiple } = useDefaultProps<SelectGOptionGroupProps>(
props,
optionGroupDefaultProps,
);

const { classPrefix } = useConfig();

const childrenWithProps = Children.map(children, (child) => {
if (isValidElement(child)) {
const addedProps = { selectedValue, onSelect, multiple };
return cloneElement(child, { ...addedProps });
if (isValidElement<SelectGOptionGroupProps>(child)) {
const addedProps: SelectGOptionGroupProps = { selectedValue, onSelect, multiple };
return cloneElement<SelectGOptionGroupProps>(child, { ...addedProps });
}
return child;
});
Expand All @@ -42,6 +46,4 @@ const OptionGroup = (props: SelectGOptionGroupProps) => {
return;
};

OptionGroup.defaultProps = optionGroupDefaultProps;

export default OptionGroup;
17 changes: 10 additions & 7 deletions src/select/base/PopupContent.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { Children, Ref, forwardRef, isValidElement, cloneElement, useRef, CSSProperties } from 'react';
import React, { Children, isValidElement, cloneElement, useRef, CSSProperties } from 'react';
import classNames from 'classnames';
import { useLocaleReceiver } from '../../locale/LocalReceiver';
import { getSelectValueArr } from '../util/helper';
Expand Down Expand Up @@ -48,7 +48,7 @@ interface SelectPopupProps
getPopupInstance?: () => HTMLDivElement;
}

const PopupContent = forwardRef((props: SelectPopupProps, ref: Ref<HTMLDivElement>) => {
const PopupContent = React.forwardRef<HTMLDivElement, SelectPopupProps>((props, ref) => {
const {
value,
size,
Expand All @@ -66,16 +66,17 @@ const PopupContent = forwardRef((props: SelectPopupProps, ref: Ref<HTMLDivElemen
panelBottomContent,
onChange,
onCheckAllChange,
getPopupInstance,
options: propsOptions,
scroll: propsScroll,
} = props;

// ๅ›ฝ้™…ๅŒ–ๆ–‡ๆœฌๅˆๅง‹ๅŒ–
const [local, t] = useLocaleReceiver('select');
const emptyText = t(local.empty);
const popupContentRef = useRef<HTMLElement>(null);
const popupContentRef = useRef<HTMLDivElement>(null);

popupContentRef.current = props.getPopupInstance();
popupContentRef.current = getPopupInstance();

const { visibleData, handleRowMounted, isVirtual, panelStyle, cursorStyle } = usePanelVirtualScroll({
popupContentRef,
Expand All @@ -84,7 +85,9 @@ const PopupContent = forwardRef((props: SelectPopupProps, ref: Ref<HTMLDivElemen
});

const { classPrefix } = useConfig();
if (!children && !propsOptions) return null;
if (!children && !propsOptions) {
return null;
}

const onSelect: SelectOptionProps['onSelect'] = (selectedValue, { label, selected, event, restData }) => {
const isValObj = valueType === 'object';
Expand Down Expand Up @@ -158,8 +161,8 @@ const PopupContent = forwardRef((props: SelectPopupProps, ref: Ref<HTMLDivElemen
{...(isVirtual
? {
isVirtual,
bufferSize: props.scroll?.bufferSize,
scrollType: props.scroll?.type,
bufferSize: propsScroll?.bufferSize,
scrollType: propsScroll?.type,
}
: {})}
{...restData}
Expand Down
47 changes: 27 additions & 20 deletions src/select/base/Select.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import React, {
useEffect,
Ref,
useMemo,
KeyboardEvent,
useRef,
Expand Down Expand Up @@ -32,6 +31,7 @@ import { PopupVisibleChangeContext } from '../../popup';
import useOptions from '../hooks/useOptions';
import composeRefs from '../../_util/composeRefs';
import { parseContentTNode } from '../../_util/parseTNode';
import useDefaultProps from '../../hooks/useDefaultProps';

export interface SelectProps<T = SelectOption> extends TdSelectProps<T>, StyledProps {
// ๅญ่Š‚็‚น
Expand All @@ -43,7 +43,8 @@ export interface SelectProps<T = SelectOption> extends TdSelectProps<T>, StyledP
type OptionsType = TdOptionProps[];

const Select = forwardRefWithStatics(
(props: SelectProps, ref: Ref<HTMLDivElement>) => {
(originalProps: SelectProps, ref: React.Ref<HTMLDivElement>) => {
const props = useDefaultProps<SelectProps>(originalProps, selectDefaultProps);
// ๅ›ฝ้™…ๅŒ–ๆ–‡ๆœฌๅˆๅง‹ๅŒ–
const [local, t] = useLocaleReceiver('select');
const emptyText = t(local.loadingText);
Expand Down Expand Up @@ -91,6 +92,8 @@ const Select = forwardRefWithStatics(
tagInputProps,
tagProps,
scroll,
suffixIcon,
onPopupVisibleChange,
} = props;

const [value, onChange] = useControlled(props, 'value', props.onChange);
Expand All @@ -100,7 +103,7 @@ const Select = forwardRefWithStatics(

const name = `${classPrefix}-select`; // t-select

const [showPopup, setShowPopup] = useControlled(props, 'popupVisible', props.onPopupVisibleChange);
const [showPopup, setShowPopup] = useControlled(props, 'popupVisible', onPopupVisibleChange);
const [inputValue, onInputChange] = useControlled(props, 'inputValue', props.onInputChange);

const { currentOptions, setCurrentOptions, tmpPropOptions, valueToOption, selectedOptions } = useOptions(
Expand Down Expand Up @@ -177,7 +180,9 @@ const Select = forwardRefWithStatics(
}
};
const onCheckAllChange = (checkAll: boolean, e: React.MouseEvent<HTMLLIElement>) => {
if (!props.multiple) return;
if (!multiple) {
return;
}
const selectableOptions = currentOptions
.filter((option) => !option.checkAll && !option.disabled)
.map((option) => option.value);
Expand Down Expand Up @@ -209,7 +214,9 @@ const Select = forwardRefWithStatics(
// ๅค„็†filter้€ป่พ‘
const handleFilter = (value: string) => {
let filteredOptions: OptionsType = [];
if (filterable && isFunction(onSearch)) return;
if (filterable && isFunction(onSearch)) {
return;
}

if (!value) {
setCurrentOptions(tmpPropOptions);
Expand All @@ -236,11 +243,14 @@ const Select = forwardRefWithStatics(

// ๅค„็†่พ“ๅ…ฅๆก†้€ป่พ‘
const handleInputChange = (value: string, context: SelectInputValueChangeContext) => {
if (context.trigger !== 'clear') onInputChange(value, { e: context.e, trigger: 'input' });
if (value === undefined) return;

if (context.trigger !== 'clear') {
onInputChange(value, { e: context.e, trigger: 'input' });
}
if (value === undefined) {
return;
}
if (isFunction(onSearch)) {
onSearch(value, { e: context.e });
onSearch(value, { e: context.e as KeyboardEvent<HTMLDivElement> });
return;
}
};
Expand All @@ -264,8 +274,9 @@ const Select = forwardRefWithStatics(

// ๆธฒๆŸ“ๅŽ็ฝฎๅ›พๆ ‡
const renderSuffixIcon = () => {
if (props.suffixIcon) return props.suffixIcon;

if (suffixIcon) {
return suffixIcon;
}
if (loading) {
return (
<Loading className={classNames(`${name}__right-icon`, `${name}__active-icon`)} loading={true} size="small" />
Expand Down Expand Up @@ -364,7 +375,9 @@ const Select = forwardRefWithStatics(

// ๅฐ†็ฌฌไธ€ไธช้€‰ไธญ็š„ option ็ฝฎไบŽๅˆ—่กจๅฏ่ง่Œƒๅ›ด็š„ๆœ€ๅŽไธ€ไฝ
const updateScrollTop = (content: HTMLDivElement) => {
if (!content) return;
if (!content) {
return;
}
const firstSelectedNode: HTMLDivElement = content.querySelector(`.${classPrefix}-is-selected`);
if (firstSelectedNode) {
const { paddingBottom } = getComputedStyle(firstSelectedNode);
Expand Down Expand Up @@ -439,21 +452,15 @@ const Select = forwardRefWithStatics(
onBlur={(_, context) => {
onBlur?.({ value, e: context.e as React.FocusEvent<HTMLDivElement> });
}}
onClear={(context) => {
onClearValue(context);
}}
onClear={onClearValue}
{...selectInputProps}
/>
</div>
);
},
{
Option,
OptionGroup,
},
{ Option, OptionGroup },
);

Select.displayName = 'Select';
Select.defaultProps = selectDefaultProps;

export default Select;
16 changes: 9 additions & 7 deletions src/select/hooks/useOptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,16 @@ import { getValueToOption } from '../util/helper';
import Option from '../base/Option';

// ๅค„็† options ็š„้€ป่พ‘
export default function UseOptions(
function UseOptions(
keys: SelectKeysType,
options: SelectOption[],
children: ReactNode,
valueType: 'object' | 'value',
value: SelectValue<SelectOption>,
) {
const [valueToOption, setValueToOption] = useState({});
const [currentOptions, setCurrentOptions] = useState([]);
const [tmpPropOptions, setTmpPropOptions] = useState([]);
const [valueToOption, setValueToOption] = useState({});
const [selectedOptions, setSelectedOptions] = useState([]);

// ๅค„็†่ฎพ็ฝฎ option ็š„้€ป่พ‘
Expand All @@ -27,19 +27,19 @@ export default function UseOptions(
arrayChildren.filter((v: ReactElement) => v.type === Option).length === arrayChildren.length;

if (isChildrenFilterable) {
transformedOptions = arrayChildren.map((v) => {
if (React.isValidElement(v)) {
transformedOptions = arrayChildren?.map<SelectOption>((v) => {
if (React.isValidElement<SelectOption>(v)) {
return {
...v.props,
label: v.props.label || (v.props.children as string),
label: v.props.label || v.props.children,
};
}
return { label: v };
});
}
if (keys) {
// ๅฆ‚ๆžœๆœ‰ๅฎšๅˆถ keys ๅ…ˆๅš่ฝฌๆข
transformedOptions = transformedOptions?.map((option) => ({
transformedOptions = transformedOptions?.map<SelectOption>((option) => ({
...option,
value: get(option, keys?.value || 'value'),
label: get(option, keys?.label || 'label'),
Expand All @@ -58,7 +58,7 @@ export default function UseOptions(
const labelKey = keys?.label || 'label';
if (Array.isArray(value)) {
return value
.map((item) => {
.map((item: SelectValue<SelectOption>) => {
if (valueType === 'value') {
return (
valueToOption[item as string | number] ||
Expand Down Expand Up @@ -100,3 +100,5 @@ export default function UseOptions(
setSelectedOptions,
};
}

export default UseOptions;
32 changes: 15 additions & 17 deletions src/select/hooks/usePanelVirtualScroll.ts
Original file line number Diff line number Diff line change
@@ -1,33 +1,31 @@
import { useEffect, useMemo, MutableRefObject, useCallback, CSSProperties } from 'react';
import useVirtualScroll from '../../hooks/useVirtualScroll';
import { TdSelectProps } from '../type';
import { TScroll } from '../../common';

const usePanelVirtualScroll = ({
popupContentRef,
scroll,
options,
}: {
interface PanelVirtualScroll {
scroll?: TdSelectProps['scroll'];
popupContentRef: MutableRefObject<HTMLElement>;
popupContentRef: MutableRefObject<HTMLDivElement>;
options: TdSelectProps['options'];
}) => {
}

const usePanelVirtualScroll = ({ popupContentRef, scroll, options }: PanelVirtualScroll) => {
const scrollThreshold = scroll?.threshold || 100;
const scrollType = scroll?.type;

const isVirtual = useMemo(
const isVirtual = useMemo<boolean>(
() => scrollType === 'virtual' && options?.length > scrollThreshold,
[scrollType, scrollThreshold, options],
);

const scrollParams = useMemo(
() =>
({
type: 'virtual',
isFixedRowHeight: scroll?.isFixedRowHeight || false,
rowHeight: scroll?.rowHeight || 28, // ้ป˜่ฎคๆฏ่กŒ้ซ˜ๅบฆ28
bufferSize: scroll?.bufferSize || 20,
threshold: scrollThreshold,
} as const),
const scrollParams = useMemo<TScroll>(
() => ({
type: 'virtual',
isFixedRowHeight: scroll?.isFixedRowHeight || false,
rowHeight: scroll?.rowHeight || 28, // ้ป˜่ฎคๆฏ่กŒ้ซ˜ๅบฆ28
bufferSize: scroll?.bufferSize || 20,
threshold: scrollThreshold,
}),
[scroll, scrollThreshold],
);
const {
Expand Down

0 comments on commit 540df37

Please sign in to comment.