Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: multiple && !treeCheckable should use SHOW_ALL instead of SHOW_CHILD #439

Merged
merged 3 commits into from
Aug 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 46 additions & 34 deletions src/TreeSelect.tsx
Original file line number Diff line number Diff line change
@@ -1,33 +1,33 @@
import * as React from 'react';
import { BaseSelect } from 'rc-select';
import type { IconType } from 'rc-tree/lib/interface';
import type { ExpandAction } from 'rc-tree/lib/Tree';
import type {
BaseSelectRef,
BaseSelectPropsWithoutPrivate,
BaseSelectProps,
BaseSelectPropsWithoutPrivate,
BaseSelectRef,
SelectProps,
} from 'rc-select';
import { conductCheck } from 'rc-tree/lib/utils/conductUtil';
import { BaseSelect } from 'rc-select';
import useId from 'rc-select/lib/hooks/useId';
import type { IconType } from 'rc-tree/lib/interface';
import type { ExpandAction } from 'rc-tree/lib/Tree';
import { conductCheck } from 'rc-tree/lib/utils/conductUtil';
import useMergedState from 'rc-util/lib/hooks/useMergedState';
import warning from 'rc-util/lib/warning';
import * as React from 'react';
import useCache from './hooks/useCache';
import useCheckedKeys from './hooks/useCheckedKeys';
import useDataEntities from './hooks/useDataEntities';
import useFilterTreeData from './hooks/useFilterTreeData';
import useRefFunc from './hooks/useRefFunc';
import useTreeData from './hooks/useTreeData';
import LegacyContext from './LegacyContext';
import OptionList from './OptionList';
import TreeNode from './TreeNode';
import { formatStrategyValues, SHOW_ALL, SHOW_PARENT, SHOW_CHILD } from './utils/strategyUtil';
import type { CheckedStrategy } from './utils/strategyUtil';
import TreeSelectContext from './TreeSelectContext';
import type { TreeSelectContextProps } from './TreeSelectContext';
import LegacyContext from './LegacyContext';
import useTreeData from './hooks/useTreeData';
import { toArray, fillFieldNames, isNil } from './utils/valueUtil';
import useCache from './hooks/useCache';
import useRefFunc from './hooks/useRefFunc';
import useDataEntities from './hooks/useDataEntities';
import TreeSelectContext from './TreeSelectContext';
import { fillAdditionalInfo, fillLegacyProps } from './utils/legacyUtil';
import useCheckedKeys from './hooks/useCheckedKeys';
import useFilterTreeData from './hooks/useFilterTreeData';
import type { CheckedStrategy } from './utils/strategyUtil';
import { formatStrategyValues, SHOW_ALL, SHOW_CHILD, SHOW_PARENT } from './utils/strategyUtil';
import { fillFieldNames, isNil, toArray } from './utils/valueUtil';
import warningProps from './utils/warningPropsUtil';
import warning from 'rc-util/lib/warning';

export type OnInternalSelect = (value: RawValueType, info: { selected: boolean }) => void;

Expand Down Expand Up @@ -105,7 +105,7 @@ export interface LegacyDataNode extends DefaultOptionType {
}
export interface TreeSelectProps<
ValueType = any,
OptionType extends BaseOptionType = DefaultOptionType
OptionType extends BaseOptionType = DefaultOptionType,
> extends Omit<BaseSelectPropsWithoutPrivate, 'mode'> {
prefixCls?: string;
id?: string;
Expand Down Expand Up @@ -194,7 +194,7 @@ const TreeSelect = React.forwardRef<BaseSelectRef, TreeSelectProps>((props, ref)
treeNodeFilterProp = 'value',

// Selector
showCheckedStrategy = SHOW_CHILD,
showCheckedStrategy,
treeNodeLabelProp,

// Mode
Expand Down Expand Up @@ -246,6 +246,15 @@ const TreeSelect = React.forwardRef<BaseSelectRef, TreeSelectProps>((props, ref)

const [internalValue, setInternalValue] = useMergedState(defaultValue, { value });

// `multiple` && `!treeCheckable` should be show all
const mergedShowCheckedStrategy = React.useMemo(() => {
if (!treeCheckable) {
return SHOW_ALL;
}

return showCheckedStrategy || SHOW_CHILD;
}, [showCheckedStrategy, treeCheckable]);

// ========================== Warning ===========================
if (process.env.NODE_ENV !== 'production') {
warningProps(props);
Expand Down Expand Up @@ -357,7 +366,9 @@ const TreeSelect = React.forwardRef<BaseSelectRef, TreeSelectProps>((props, ref)
rawDisabled = entity.node.disabled;
} else if (rawLabel === undefined) {
// We try to find in current `labelInValue` value
const labelInValueItem = toLabeledValues(internalValue).find(labeledItem => labeledItem.value === rawValue);
const labelInValueItem = toLabeledValues(internalValue).find(
labeledItem => labeledItem.value === rawValue,
);
rawLabel = labelInValueItem.label;
}

Expand All @@ -373,10 +384,10 @@ const TreeSelect = React.forwardRef<BaseSelectRef, TreeSelectProps>((props, ref)
);

// =========================== Values ===========================
const rawMixedLabeledValues = React.useMemo(() => toLabeledValues(internalValue), [
toLabeledValues,
internalValue,
]);
const rawMixedLabeledValues = React.useMemo(
() => toLabeledValues(internalValue),
[toLabeledValues, internalValue],
);

// Split value into full check and half check
const [rawLabeledValues, rawHalfLabeledValues] = React.useMemo(() => {
Expand All @@ -395,9 +406,10 @@ const TreeSelect = React.forwardRef<BaseSelectRef, TreeSelectProps>((props, ref)
}, [rawMixedLabeledValues]);

// const [mergedValues] = useCache(rawLabeledValues);
const rawValues = React.useMemo(() => rawLabeledValues.map(item => item.value), [
rawLabeledValues,
]);
const rawValues = React.useMemo(
() => rawLabeledValues.map(item => item.value),
[rawLabeledValues],
);

// Convert value to key. Will fill missed keys for conduct check.
const [rawCheckedValues, rawHalfCheckedValues] = useCheckedKeys(
Expand All @@ -412,7 +424,7 @@ const TreeSelect = React.forwardRef<BaseSelectRef, TreeSelectProps>((props, ref)
// Collect keys which need to show
const displayKeys = formatStrategyValues(
rawCheckedValues,
showCheckedStrategy,
mergedShowCheckedStrategy,
keyEntities,
mergedFieldNames,
);
Expand Down Expand Up @@ -447,7 +459,7 @@ const TreeSelect = React.forwardRef<BaseSelectRef, TreeSelectProps>((props, ref)
rawCheckedValues,
rawLabeledValues,
convert2LabelValues,
showCheckedStrategy,
mergedShowCheckedStrategy,
keyEntities,
]);

Expand All @@ -474,7 +486,7 @@ const TreeSelect = React.forwardRef<BaseSelectRef, TreeSelectProps>((props, ref)
if (treeConduction) {
const formattedKeyList = formatStrategyValues(
newRawValues,
showCheckedStrategy,
mergedShowCheckedStrategy,
keyEntities,
mergedFieldNames,
);
Expand Down Expand Up @@ -743,9 +755,9 @@ if (process.env.NODE_ENV !== 'production') {
TreeSelect.displayName = 'TreeSelect';
}

const GenericTreeSelect = (TreeSelect as unknown) as (<
const GenericTreeSelect = TreeSelect as unknown as (<
ValueType = any,
OptionType extends BaseOptionType | DefaultOptionType = DefaultOptionType
OptionType extends BaseOptionType | DefaultOptionType = DefaultOptionType,
>(
props: React.PropsWithChildren<TreeSelectProps<ValueType, OptionType>> & {
ref?: React.Ref<BaseSelectRef>;
Expand Down
33 changes: 32 additions & 1 deletion tests/Select.multiple.spec.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
/* eslint-disable no-undef */
import React from 'react';
import { render } from '@testing-library/react';
import { mount } from 'enzyme';
import KeyCode from 'rc-util/lib/KeyCode';
import React from 'react';
import TreeSelect, { TreeNode } from '../src';
import focusTest from './shared/focusTest';

Expand Down Expand Up @@ -279,4 +280,34 @@ describe('TreeSelect.multiple', () => {
expect(onChange).toHaveBeenCalledWith([], expect.anything(), expect.anything());
expect(onDeselect).toHaveBeenCalledWith('not-exist', undefined);
});

it('should not omit value', () => {
const { container } = render(
<TreeSelect
value={['child1', 'child2', 'parent']}
multiple
treeData={[
{
label: 'parent',
value: 'parent',
children: [
{
label: 'child1',
value: 'child1',
},
{
label: 'child2',
value: 'child2',
},
],
},
]}
/>,
);

const values = Array.from(
container.querySelectorAll('.rc-tree-select-selection-item-content'),
).map(ele => ele.textContent);
expect(values).toEqual(['child1', 'child2', 'parent']);
});
});
4 changes: 4 additions & 0 deletions tests/__snapshots__/Select.checkable.spec.tsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ exports[`TreeSelect.checkable uncheck remove by selector not treeCheckStrictly 1
aria-controls="rc_select_TEST_OR_SSR_list"
aria-expanded="true"
aria-haspopup="listbox"
aria-label="Search"
aria-owns="rc_select_TEST_OR_SSR_list"
autocomplete="off"
class="rc-tree-select-selection-search-input"
Expand Down Expand Up @@ -297,6 +298,7 @@ exports[`TreeSelect.checkable uncheck remove by selector not treeCheckStrictly 2
aria-controls="rc_select_TEST_OR_SSR_list"
aria-expanded="true"
aria-haspopup="listbox"
aria-label="Search"
aria-owns="rc_select_TEST_OR_SSR_list"
autocomplete="off"
class="rc-tree-select-selection-search-input"
Expand Down Expand Up @@ -573,6 +575,7 @@ exports[`TreeSelect.checkable uncheck remove by tree check 1`] = `
aria-controls="rc_select_TEST_OR_SSR_list"
aria-expanded="true"
aria-haspopup="listbox"
aria-label="Search"
aria-owns="rc_select_TEST_OR_SSR_list"
autocomplete="off"
class="rc-tree-select-selection-search-input"
Expand Down Expand Up @@ -765,6 +768,7 @@ exports[`TreeSelect.checkable uncheck remove by tree check 2`] = `
aria-controls="rc_select_TEST_OR_SSR_list"
aria-expanded="true"
aria-haspopup="listbox"
aria-label="Search"
aria-owns="rc_select_TEST_OR_SSR_list"
autocomplete="off"
class="rc-tree-select-selection-search-input"
Expand Down
1 change: 1 addition & 0 deletions tests/__snapshots__/Select.multiple.spec.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ exports[`TreeSelect.multiple can hide search box by showSearch = false 1`] = `
aria-controls="rc_select_TEST_OR_SSR_list"
aria-expanded="false"
aria-haspopup="listbox"
aria-label="Search"
aria-owns="rc_select_TEST_OR_SSR_list"
autocomplete="off"
class="rc-tree-select-selection-search-input"
Expand Down
10 changes: 10 additions & 0 deletions tests/__snapshots__/Select.spec.tsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ exports[`TreeSelect.basic render renders TreeNode correctly 1`] = `
aria-controls="rc_select_TEST_OR_SSR_list"
aria-expanded="true"
aria-haspopup="listbox"
aria-label="Search"
aria-owns="rc_select_TEST_OR_SSR_list"
autocomplete="off"
class="rc-tree-select-selection-search-input"
Expand Down Expand Up @@ -208,6 +209,7 @@ exports[`TreeSelect.basic render renders TreeNode correctly with falsy child 1`]
aria-controls="rc_select_TEST_OR_SSR_list"
aria-expanded="true"
aria-haspopup="listbox"
aria-label="Search"
aria-owns="rc_select_TEST_OR_SSR_list"
autocomplete="off"
class="rc-tree-select-selection-search-input"
Expand Down Expand Up @@ -410,6 +412,7 @@ exports[`TreeSelect.basic render renders correctly 1`] = `
aria-controls="rc_select_TEST_OR_SSR_list"
aria-expanded="false"
aria-haspopup="listbox"
aria-label="Search"
aria-owns="rc_select_TEST_OR_SSR_list"
autocomplete="off"
class="awesome-selection-search-input"
Expand Down Expand Up @@ -452,6 +455,7 @@ exports[`TreeSelect.basic render renders disabled correctly 1`] = `
aria-controls="rc_select_TEST_OR_SSR_list"
aria-expanded="false"
aria-haspopup="listbox"
aria-label="Search"
aria-owns="rc_select_TEST_OR_SSR_list"
autocomplete="off"
class="rc-tree-select-selection-search-input"
Expand Down Expand Up @@ -495,6 +499,7 @@ exports[`TreeSelect.basic render renders tree correctly 1`] = `
aria-controls="rc_select_TEST_OR_SSR_list"
aria-expanded="false"
aria-haspopup="listbox"
aria-label="Search"
aria-owns="rc_select_TEST_OR_SSR_list"
autocomplete="off"
class="rc-tree-select-selection-search-input"
Expand Down Expand Up @@ -538,6 +543,7 @@ exports[`TreeSelect.basic render renders treeDataSimpleMode correctly 1`] = `
aria-controls="rc_select_TEST_OR_SSR_list"
aria-expanded="true"
aria-haspopup="listbox"
aria-label="Search"
aria-owns="rc_select_TEST_OR_SSR_list"
autocomplete="off"
class="rc-tree-select-selection-search-input"
Expand Down Expand Up @@ -677,6 +683,7 @@ exports[`TreeSelect.basic search nodes check tree changed by filter 1`] = `
aria-controls="rc_select_TEST_OR_SSR_list"
aria-expanded="true"
aria-haspopup="listbox"
aria-label="Search"
aria-owns="rc_select_TEST_OR_SSR_list"
autocomplete="off"
class="rc-tree-select-selection-search-input"
Expand Down Expand Up @@ -784,6 +791,7 @@ exports[`TreeSelect.basic search nodes check tree changed by filter 2`] = `
aria-controls="rc_select_TEST_OR_SSR_list"
aria-expanded="true"
aria-haspopup="listbox"
aria-label="Search"
aria-owns="rc_select_TEST_OR_SSR_list"
autocomplete="off"
class="rc-tree-select-selection-search-input"
Expand Down Expand Up @@ -917,6 +925,7 @@ exports[`TreeSelect.basic search nodes filter node but not remove then 1`] = `
aria-controls="rc_select_TEST_OR_SSR_list"
aria-expanded="true"
aria-haspopup="listbox"
aria-label="Search"
aria-owns="rc_select_TEST_OR_SSR_list"
autocomplete="off"
class="rc-tree-select-selection-search-input"
Expand Down Expand Up @@ -1049,6 +1058,7 @@ exports[`TreeSelect.basic search nodes renders search input 1`] = `
aria-controls="rc_select_TEST_OR_SSR_list"
aria-expanded="true"
aria-haspopup="listbox"
aria-label="Search"
aria-owns="rc_select_TEST_OR_SSR_list"
autocomplete="off"
class="rc-tree-select-selection-search-input"
Expand Down
Loading