Skip to content

Commit 3d53b0f

Browse files
aojunhao123小豪
andauthored
feat: add disabled api for panel (#543)
* feat: add disabled api for panel * feat: add test case * docs: add demo * fix: test case fixed * feat: adjust demo position * feat: improve demo * chore: reorganize code for better readability * test: update snapshot * fix: lint fix * chore: adjust code structure * test: update snapshot * chore: code optimization --------- Co-authored-by: 小豪 <[email protected]>
1 parent ac5908d commit 3d53b0f

File tree

5 files changed

+61
-10
lines changed

5 files changed

+61
-10
lines changed

examples/panel.tsx

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ export default () => {
6161

6262
const [value2, setValue2] = React.useState<string[][]>([]);
6363

64+
const [disabled, setDisabled] = React.useState(false);
65+
6466
return (
6567
<>
6668
<h1>Panel</h1>
@@ -71,13 +73,21 @@ export default () => {
7173
>
7274
Set Value
7375
</button>
76+
<button
77+
onClick={() => {
78+
setDisabled(prev => !prev);
79+
}}
80+
>
81+
{disabled ? 'enable panel' : 'disable panel'}
82+
</button>
7483
<Cascader.Panel
7584
value={value}
7685
options={addressOptions}
7786
onChange={nextValue => {
7887
console.log('Change:', nextValue);
7988
setValue(nextValue);
8089
}}
90+
disabled={disabled}
8191
/>
8292

8393
<Cascader.Panel
@@ -88,9 +98,10 @@ export default () => {
8898
console.log('Change:', nextValue);
8999
setValue2(nextValue);
90100
}}
101+
disabled={disabled}
91102
/>
92103

93-
<Cascader.Panel options={addressOptions} direction="rtl" />
104+
<Cascader.Panel options={addressOptions} disabled={disabled} direction="rtl" />
94105

95106
<Cascader.Panel notFoundContent="Empty!!!" />
96107
</>

src/OptionList/Column.tsx

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ export interface ColumnProps<OptionType extends DefaultOptionType = DefaultOptio
2323
halfCheckedSet: Set<React.Key>;
2424
loadingKeys: React.Key[];
2525
isSelectable: (option: DefaultOptionType) => boolean;
26+
disabled?: boolean;
2627
}
2728

2829
export default function Column<OptionType extends DefaultOptionType = DefaultOptionType>({
@@ -38,6 +39,7 @@ export default function Column<OptionType extends DefaultOptionType = DefaultOpt
3839
halfCheckedSet,
3940
loadingKeys,
4041
isSelectable,
42+
disabled: propsDisabled,
4143
}: ColumnProps<OptionType>) {
4244
const menuPrefixCls = `${prefixCls}-menu`;
4345
const menuItemPrefixCls = `${prefixCls}-menu-item`;
@@ -54,6 +56,8 @@ export default function Column<OptionType extends DefaultOptionType = DefaultOpt
5456

5557
const hoverOpen = expandTrigger === 'hover';
5658

59+
const isOptionDisabled = (disabled?: boolean) => propsDisabled || disabled;
60+
5761
// ============================ Option ============================
5862
const optionInfoList = React.useMemo(
5963
() =>
@@ -115,7 +119,7 @@ export default function Column<OptionType extends DefaultOptionType = DefaultOpt
115119
}) => {
116120
// >>>>> Open
117121
const triggerOpenPath = () => {
118-
if (disabled) {
122+
if (isOptionDisabled(disabled)) {
119123
return;
120124
}
121125
const nextValueCells = [...fullPath];
@@ -127,7 +131,7 @@ export default function Column<OptionType extends DefaultOptionType = DefaultOpt
127131

128132
// >>>>> Selection
129133
const triggerSelect = () => {
130-
if (isSelectable(option)) {
134+
if (isSelectable(option) && !isOptionDisabled(disabled)) {
131135
onSelect(fullPath, isMergedLeaf);
132136
}
133137
};
@@ -148,7 +152,7 @@ export default function Column<OptionType extends DefaultOptionType = DefaultOpt
148152
[`${menuItemPrefixCls}-expand`]: !isMergedLeaf,
149153
[`${menuItemPrefixCls}-active`]:
150154
activeValue === value || activeValue === fullPathKey,
151-
[`${menuItemPrefixCls}-disabled`]: disabled,
155+
[`${menuItemPrefixCls}-disabled`]: isOptionDisabled(disabled),
152156
[`${menuItemPrefixCls}-loading`]: isLoading,
153157
})}
154158
style={dropdownMenuColumnStyle}
@@ -185,7 +189,7 @@ export default function Column<OptionType extends DefaultOptionType = DefaultOpt
185189
prefixCls={`${prefixCls}-checkbox`}
186190
checked={checked}
187191
halfChecked={halfChecked}
188-
disabled={disabled || disableCheckbox}
192+
disabled={isOptionDisabled(disabled) || disableCheckbox}
189193
disableCheckbox={disableCheckbox}
190194
onClick={(e: React.MouseEvent<HTMLSpanElement>) => {
191195
if (disableCheckbox) {

src/OptionList/List.tsx

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,27 @@ import useKeyboard from './useKeyboard';
2121

2222
export type RawOptionListProps = Pick<
2323
ReturnType<typeof useBaseProps>,
24-
'prefixCls' | 'multiple' | 'searchValue' | 'toggleOpen' | 'notFoundContent' | 'direction' | 'open'
24+
| 'prefixCls'
25+
| 'multiple'
26+
| 'searchValue'
27+
| 'toggleOpen'
28+
| 'notFoundContent'
29+
| 'direction'
30+
| 'open'
31+
| 'disabled'
2532
>;
2633

2734
const RawOptionList = React.forwardRef<RefOptionListProps, RawOptionListProps>((props, ref) => {
28-
const { prefixCls, multiple, searchValue, toggleOpen, notFoundContent, direction, open } = props;
35+
const {
36+
prefixCls,
37+
multiple,
38+
searchValue,
39+
toggleOpen,
40+
notFoundContent,
41+
direction,
42+
open,
43+
disabled,
44+
} = props;
2945

3046
const containerRef = React.useRef<HTMLDivElement>(null);
3147
const rtl = direction === 'rtl';
@@ -100,10 +116,14 @@ const RawOptionList = React.forwardRef<RefOptionListProps, RawOptionListProps>((
100116
};
101117

102118
const isSelectable = (option: DefaultOptionType) => {
103-
const { disabled } = option;
119+
if (disabled) {
120+
return false;
121+
}
104122

123+
const { disabled: optionDisabled } = option;
105124
const isMergedLeaf = isLeaf(option, fieldNames);
106-
return !disabled && (isMergedLeaf || changeOnSelect || multiple);
125+
126+
return !optionDisabled && (isMergedLeaf || changeOnSelect || multiple);
107127
};
108128

109129
const onPathSelect = (valuePath: SingleValueType, leaf: boolean, fromKeyboard = false) => {

src/Panel.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@ export type PickType =
3535
| 'className'
3636
| 'style'
3737
| 'direction'
38-
| 'notFoundContent';
38+
| 'notFoundContent'
39+
| 'disabled';
3940

4041
export type PanelProps<
4142
OptionType extends DefaultOptionType = DefaultOptionType,
@@ -68,6 +69,7 @@ export default function Panel<
6869
loadingIcon,
6970
direction,
7071
notFoundContent = 'Not Found',
72+
disabled,
7173
} = props as Pick<InternalCascaderProps, PickType>;
7274

7375
// ======================== Multiple ========================
@@ -200,6 +202,7 @@ export default function Panel<
200202
toggleOpen={noop}
201203
open
202204
direction={direction}
205+
disabled={disabled}
203206
/>
204207
)}
205208
</div>

tests/Panel.spec.tsx

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,4 +97,17 @@ describe('Cascader.Panel', () => {
9797
const checkedLi = container.querySelector('[aria-checked="true"]');
9898
expect(checkedLi?.textContent).toEqual('Little');
9999
});
100+
101+
it('disabled', () => {
102+
const onChange = jest.fn();
103+
const { container } = render(
104+
<Cascader.Panel options={options} onChange={onChange} disabled={true} />,
105+
);
106+
107+
expect(container.querySelector('.rc-cascader-menu-item-disabled')).toBeTruthy();
108+
109+
const selectOption = container.querySelector('.rc-cascader-menu-item')!;
110+
fireEvent.click(selectOption);
111+
expect(onChange).not.toHaveBeenCalled();
112+
});
100113
});

0 commit comments

Comments
 (0)