Skip to content
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
3 changes: 3 additions & 0 deletions docs/demo/field-names.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
## FieldNames

<code src="../../examples/fieldNames.tsx">
58 changes: 11 additions & 47 deletions examples/debug.tsx
Original file line number Diff line number Diff line change
@@ -1,54 +1,18 @@
/* eslint-disable react/no-array-index-key */

import React from 'react';
import TreeSelect, { TreeNode } from '../src';
import TreeSelect from '../src';
import '../assets/index.less';

class Demo extends React.Component {
state = {
value: undefined,
};
export default () => {
const [treeData, setTreeData] = React.useState([]);

onChange = value => {
console.log(value);
this.setState({ value });
};
React.useEffect(() => {
setTimeout(() => {
console.clear();
setTreeData([{ value: 'light', title: 'bamboo' }]);
}, 1000);
}, []);

render() {
return (
<TreeSelect
showSearch
style={{ width: '100%' }}
value={this.state.value}
dropdownStyle={{ maxHeight: 400, overflow: 'auto' }}
placeholder="Please select"
allowClear
treeDefaultExpandAll
onChange={this.onChange}
labelRender={entity => {
let current = entity;
const nodes = [];

while (current) {
nodes.unshift(current.data.title);
current = current.parent;
}

return nodes.join('>');
}}
>
<TreeNode value="parent 1" title="parent 1" key="0-1">
<TreeNode value="parent 1-0" title="parent 1-0" key="0-1-1">
<TreeNode value="leaf1" title="my leaf" key="random" />
<TreeNode value="leaf2" title="your leaf" key="random1" />
</TreeNode>
<TreeNode value="parent 1-1" title="parent 1-1" key="random2">
<TreeNode value="sss" title={<b style={{ color: '#08c' }}>sss</b>} key="random3" />
</TreeNode>
</TreeNode>
</TreeSelect>
);
}
}

export default Demo;
return <TreeSelect value="light" treeData={treeData} />;
};
33 changes: 33 additions & 0 deletions examples/fieldNames.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import '../assets/index.less';
import React from 'react';
import 'rc-dialog/assets/index.css';
import TreeSelect from '../src';

export default () => {
return (
<TreeSelect
treeDefaultExpandAll
treeData={[
{
myLabel: 'Parent',
myValue: 'parent',
myChildren: [
{
myLabel: 'Sub 1',
myValue: 'sub_1',
},
{
myLabel: 'Sub 2',
myValue: 'sub_2',
},
],
},
]}
fieldNames={{
label: 'myLabel',
value: 'myValue',
children: 'myChildren',
}}
/>
);
};
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,8 @@
"dependencies": {
"@babel/runtime": "^7.10.1",
"classnames": "2.x",
"rc-select": "^12.0.0",
"rc-tree": "^4.0.0",
"rc-select": "~13.0.0-alpha.1",
"rc-tree": "~5.0.0",
"rc-util": "^5.0.5"
}
}
15 changes: 8 additions & 7 deletions src/OptionList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ const OptionList: React.RefForwardingComponent<
// ========================== Values ==========================
const valueKeys = React.useMemo(
() =>
checkedKeys.map((val) => {
checkedKeys.map(val => {
const entity = getEntityByValue(val);
return entity ? entity.key : null;
}),
Expand Down Expand Up @@ -153,7 +153,7 @@ const OptionList: React.RefForwardingComponent<

React.useEffect(() => {
if (searchValue) {
setSearchExpandedKeys(flattenOptions.map((o) => o.key));
setSearchExpandedKeys(flattenOptions.map(o => o.key));
}
}, [searchValue]);

Expand All @@ -167,7 +167,7 @@ const OptionList: React.RefForwardingComponent<
};

// ========================== Events ==========================
const onListMouseDown: React.MouseEventHandler<HTMLDivElement> = (event) => {
const onListMouseDown: React.MouseEventHandler<HTMLDivElement> = event => {
event.preventDefault();
};

Expand All @@ -190,7 +190,7 @@ const OptionList: React.RefForwardingComponent<

React.useImperativeHandle(ref, () => ({
scrollTo: treeRef.current?.scrollTo,
onKeyDown: (event) => {
onKeyDown: event => {
const { which } = event;
switch (which) {
// >>> Arrow keys
Expand All @@ -203,7 +203,7 @@ const OptionList: React.RefForwardingComponent<

// >>> Select item
case KeyCode.ENTER: {
const { selectable, value } = activeEntity?.data || {};
const { selectable, value } = activeEntity?.data.node || {};
if (selectable !== false) {
onInternalSelect(null, {
node: { key: activeKey },
Expand Down Expand Up @@ -281,8 +281,9 @@ const OptionList: React.RefForwardingComponent<
);
};

const RefOptionList =
React.forwardRef<ReviseRefOptionListProps, OptionListProps<DataNode[]>>(OptionList);
const RefOptionList = React.forwardRef<ReviseRefOptionListProps, OptionListProps<DataNode[]>>(
OptionList,
);
RefOptionList.displayName = 'OptionList';

export default RefOptionList;
32 changes: 21 additions & 11 deletions src/generate.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { getLabeledValue } from 'rc-select/lib/utils/valueUtil';
import { convertDataToEntities } from 'rc-tree/lib/utils/treeUtil';
import { conductCheck } from 'rc-tree/lib/utils/conductUtil';
import type { IconType } from 'rc-tree/lib/interface';
import omit from 'rc-util/lib/omit';
import type { FilterFunc } from 'rc-select/lib/interface/generator';
import { INTERNAL_PROPS_MARK } from 'rc-select/lib/interface/generator';
import useMergedState from 'rc-util/lib/hooks/useMergedState';
Expand All @@ -22,6 +23,7 @@ import type {
LegacyDataNode,
SelectSource,
FlattenDataNode,
FieldNames,
} from './interface';
import {
flattenOptions,
Expand All @@ -32,6 +34,7 @@ import {
removeValue,
getRawValueLabeled,
toArray,
fillFieldNames,
} from './utils/valueUtil';
import warningProps from './utils/warningPropsUtil';
import { SelectContext } from './Context';
Expand All @@ -43,8 +46,8 @@ import { formatStrategyKeys, SHOW_ALL, SHOW_PARENT, SHOW_CHILD } from './utils/s
import { fillAdditionalInfo } from './utils/legacyUtil';
import useSelectValues from './hooks/useSelectValues';

const OMIT_PROPS = [
'expandedKeys',
const OMIT_PROPS: (keyof TreeSelectProps)[] = [
'expandedKeys' as any,
'treeData',
'treeCheckable',
'showCheckedStrategy',
Expand All @@ -63,6 +66,7 @@ const OMIT_PROPS = [
'treeMotion',
'onTreeExpand',
'onTreeLoad',
'labelRender',
'loadData',
'treeDataSimpleMode',
'treeNodeLabelProp',
Expand All @@ -81,6 +85,7 @@ export interface TreeSelectProps<ValueType = DefaultValueType>
| 'optionLabelProp'
| 'tokenSeparators'
| 'filterOption'
| 'fieldNames'
> {
multiple?: boolean;
showArrow?: boolean;
Expand All @@ -99,6 +104,7 @@ export interface TreeSelectProps<ValueType = DefaultValueType>

maxTagPlaceholder?: (omittedValues: LabelValueType[]) => React.ReactNode;

fieldNames?: FieldNames;
loadData?: (dataNode: LegacyDataNode) => Promise<unknown>;
treeNodeFilterProp?: string;
treeNodeLabelProp?: string;
Expand Down Expand Up @@ -155,13 +161,7 @@ export default function generate(config: {
filterOptions,
isValueDisabled,
findValueOption,
omitDOMProps: (props: object) => {
const cloneProps = { ...props };
OMIT_PROPS.forEach(prop => {
delete cloneProps[prop];
});
return cloneProps;
},
omitDOMProps: (props: TreeSelectProps<any>) => omit(props, OMIT_PROPS),
});

RefSelect.displayName = 'Select';
Expand All @@ -171,6 +171,7 @@ export default function generate(config: {
// =================================================================================
const RefTreeSelect = React.forwardRef<RefSelectProps, TreeSelectProps>((props, ref) => {
const {
fieldNames,
multiple,
treeCheckable,
treeCheckStrictly,
Expand Down Expand Up @@ -207,17 +208,25 @@ export default function generate(config: {
const mergedLabelInValue = treeCheckStrictly || labelInValue;

// ======================= Tree Data =======================
// FieldNames
const mergedFieldNames = fillFieldNames(fieldNames, true);

// Legacy both support `label` or `title` if not set.
// We have to fallback to function to handle this
const getTreeNodeTitle = (node: DataNode): React.ReactNode => {
if (!treeData) {
return node.title;
}

if (mergedFieldNames?.label) {
return node[mergedFieldNames.label];
}

return node.label || node.title;
};

const getTreeNodeLabelProp = (entity: FlattenDataNode): React.ReactNode => {
const node = entity.data;
const { node } = entity.data;

if (labelRender) {
return labelRender(entity);
Expand All @@ -233,6 +242,7 @@ export default function generate(config: {
const mergedTreeData = useTreeData(treeData, children, {
getLabelProp: getTreeNodeTitle,
simpleMode: treeDataSimpleMode,
fieldNames: mergedFieldNames,
});

const flattedOptions = useMemo(() => flattenOptions(mergedTreeData), [mergedTreeData]);
Expand Down Expand Up @@ -404,7 +414,7 @@ export default function generate(config: {
? null
: eventValues.map(val => {
const entity = getEntityByValue(val);
return entity ? getTreeNodeLabelProp(entity) : null;
return entity ? entity.data.title : null;
}),
additionalInfo,
);
Expand Down
9 changes: 4 additions & 5 deletions src/hooks/useKeyValueMapping.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,15 @@ export function isDisabled(dataNode: FlattenDataNode, skipType: SkipType): boole
return true;
}

const { disabled, disableCheckbox } = dataNode.data;
const { disabled, disableCheckbox } = dataNode.data.node;

switch (skipType) {
case 'select':
return disabled;
case 'checkbox':
return disabled || disableCheckbox;
}

return false;
default:
return disabled;
}
}

export default function useKeyValueMapping(
Expand Down
Loading