Skip to content

Commit 6435be5

Browse files
committed
feat: add parent property to select option item
1 parent cab5c0f commit 6435be5

File tree

5 files changed

+166
-69
lines changed

5 files changed

+166
-69
lines changed

src/multiselect/interfaces.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ export namespace MultiselectProps {
9393
disabled: boolean;
9494
highlighted: boolean;
9595
selected: boolean;
96+
parent: MultiselectOptionGroupItem | null;
9697
}
9798
export interface MultiselectOptionGroupItem {
9899
type: 'group';

src/select/interfaces.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,7 @@ export namespace SelectProps {
213213
highlighted: boolean;
214214
selected: boolean;
215215
disabled: boolean;
216+
parent: SelectOptionGroupItem | null;
216217
}
217218
export interface SelectOptionGroupItem {
218219
type: 'group';

src/select/parts/item.tsx

Lines changed: 65 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,51 @@ export interface ItemProps<T = SelectProps.SelectOptionItemRenderer> {
3737
withScrollbar?: boolean;
3838
sticky?: boolean;
3939
renderOption?: T;
40+
parentProps?: ItemParentProps;
4041
}
4142

43+
export interface ItemParentProps {
44+
index: number;
45+
virtualIndex?: number;
46+
option: DropdownOption;
47+
disabled: boolean;
48+
}
49+
const toSelectOptionGroupItem = (props: ItemParentProps): SelectProps.SelectOptionGroupItem => {
50+
return {
51+
type: 'group',
52+
index: props.virtualIndex ?? props.index,
53+
option: props.option.option as OptionGroup,
54+
disabled: props.disabled,
55+
};
56+
};
57+
58+
const toSelectOptionItem = (props: {
59+
index: number;
60+
virtualIndex?: number;
61+
option: DropdownOption;
62+
disabled: boolean;
63+
selected: boolean;
64+
highlighted: boolean;
65+
parentProps?: ItemParentProps;
66+
}): SelectProps.SelectOptionItem => {
67+
return {
68+
type: 'item',
69+
index: props.virtualIndex ?? props.index,
70+
option: props.option.option as OptionDefinition,
71+
selected: props.selected,
72+
highlighted: props.highlighted,
73+
disabled: props.disabled,
74+
parent: props.parentProps
75+
? toSelectOptionGroupItem({
76+
index: props.parentProps?.index,
77+
virtualIndex: props.parentProps?.virtualIndex,
78+
option: props.parentProps?.option,
79+
disabled: props.disabled,
80+
})
81+
: null,
82+
};
83+
};
84+
4285
const Item = (
4386
{
4487
index,
@@ -59,6 +102,7 @@ const Item = (
59102
withScrollbar,
60103
sticky,
61104
renderOption,
105+
parentProps,
62106
...restProps
63107
}: ItemProps,
64108
ref: React.Ref<HTMLDivElement>
@@ -78,38 +122,33 @@ const Item = (
78122
const [canShowTooltip, setCanShowTooltip] = useState(true);
79123
useEffect(() => setCanShowTooltip(true), [highlighted]);
80124

81-
const globalIndex = virtualIndex ?? index;
125+
const getSelectItemProps = (option: DropdownOption): SelectProps.SelectItem => {
126+
if (option.type === 'parent') {
127+
return toSelectOptionGroupItem({
128+
option: option,
129+
index: index,
130+
virtualIndex: virtualIndex,
131+
disabled: !!disabled,
132+
});
133+
} else {
134+
return toSelectOptionItem({
135+
option: option,
136+
index: index,
137+
virtualIndex: virtualIndex,
138+
disabled: !!disabled,
139+
highlighted: !!highlighted,
140+
selected: !!selected,
141+
parentProps: parentProps,
142+
});
143+
}
144+
};
82145

83146
const renderOptionWrapper = (option: DropdownOption) => {
84147
if (!renderOption) {
85148
return null;
86149
}
87150

88-
let item: SelectProps.SelectItem;
89-
90-
switch (option.type) {
91-
case 'parent':
92-
item = {
93-
index: globalIndex,
94-
type: 'group',
95-
option: option.option as OptionGroup,
96-
disabled: !!disabled,
97-
};
98-
break;
99-
case 'child':
100-
default:
101-
item = {
102-
index: globalIndex,
103-
type: 'item',
104-
option: option.option as OptionDefinition,
105-
selected: !!selected,
106-
highlighted: !!highlighted,
107-
disabled: !!disabled,
108-
};
109-
break;
110-
}
111-
112-
return renderOption({ item, filterText: filteringValue });
151+
return renderOption({ item: getSelectItemProps(option), filterText: filteringValue });
113152
};
114153
const renderResult = renderOptionWrapper(option);
115154

src/select/parts/multiselect-item.tsx

Lines changed: 84 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,62 @@ import SelectableItem from '../../internal/components/selectable-item';
1212
import Tooltip from '../../internal/components/tooltip';
1313
import useHiddenDescription from '../../internal/hooks/use-hidden-description';
1414
import { MultiselectProps } from '../../multiselect/interfaces';
15-
import { ItemProps } from './item';
15+
import { ItemParentProps, ItemProps } from './item';
1616

1717
import styles from './styles.css.js';
1818
interface MultiselectItemProps extends ItemProps<MultiselectProps.MultiselectOptionItemRenderer> {
1919
indeterminate?: boolean;
20+
parentProps?: MultiselectItemParentProps;
2021
}
2122

23+
export interface MultiselectItemParentProps extends ItemParentProps {
24+
indeterminate: boolean;
25+
highlighted: boolean;
26+
selected: boolean;
27+
}
28+
const toMultiselectOptionGroupItem = (
29+
props: MultiselectItemParentProps
30+
): MultiselectProps.MultiselectOptionGroupItem => {
31+
return {
32+
type: 'group',
33+
index: props.virtualIndex ?? props.index,
34+
option: props.option.option as OptionGroup,
35+
indeterminate: props.indeterminate ?? false,
36+
selected: props.selected,
37+
highlighted: props.highlighted,
38+
disabled: props.disabled,
39+
};
40+
};
41+
const toMultiselectOptionItem = (props: {
42+
index: number;
43+
virtualIndex?: number;
44+
option: DropdownOption;
45+
disabled: boolean;
46+
selected: boolean;
47+
highlighted: boolean;
48+
parentProps?: MultiselectItemParentProps;
49+
}): MultiselectProps.MultiselectOptionItem => {
50+
return {
51+
type: 'item',
52+
index: props.virtualIndex ?? props.index,
53+
option: props.option.option as OptionDefinition,
54+
selected: props.selected,
55+
highlighted: props.highlighted,
56+
disabled: props.disabled,
57+
parent: props.parentProps
58+
? toMultiselectOptionGroupItem({
59+
index: props.parentProps?.index,
60+
virtualIndex: props.parentProps?.virtualIndex,
61+
option: props.parentProps?.option,
62+
disabled: props.disabled,
63+
highlighted: props.parentProps?.highlighted ?? false,
64+
indeterminate: props.parentProps?.indeterminate ?? false,
65+
selected: props.parentProps?.selected ?? false,
66+
})
67+
: null,
68+
};
69+
};
70+
2271
const MultiSelectItem = (
2372
{
2473
index,
@@ -40,6 +89,7 @@ const MultiSelectItem = (
4089
withScrollbar,
4190
sticky,
4291
renderOption,
92+
parentProps,
4393
...restProps
4494
}: MultiselectItemProps,
4595
ref: React.Ref<HTMLDivElement>
@@ -63,50 +113,45 @@ const MultiSelectItem = (
63113

64114
const [canShowTooltip, setCanShowTooltip] = useState(true);
65115
useEffect(() => setCanShowTooltip(true), [highlighted]);
66-
const globalIndex = virtualIndex ?? index;
116+
117+
const getMultiselectItemProps = (option: DropdownOption): MultiselectProps.MultiselectItem => {
118+
if (option.type === 'parent') {
119+
return toMultiselectOptionGroupItem({
120+
option: option,
121+
index: index,
122+
virtualIndex: virtualIndex,
123+
disabled: !!disabled,
124+
highlighted: !!highlighted,
125+
selected: !!selected,
126+
indeterminate: indeterminate ?? false,
127+
});
128+
} else if (option.type === 'select-all') {
129+
return {
130+
type: 'select-all',
131+
option: option.option as OptionDefinition,
132+
indeterminate: indeterminate ?? false,
133+
selected: !!selected,
134+
highlighted: !!highlighted,
135+
};
136+
} else {
137+
return toMultiselectOptionItem({
138+
option: option,
139+
index: index,
140+
virtualIndex: virtualIndex,
141+
disabled: !!disabled,
142+
highlighted: !!highlighted,
143+
selected: !!selected,
144+
parentProps: parentProps,
145+
});
146+
}
147+
};
67148

68149
const renderOptionWrapper = (option: DropdownOption) => {
69150
if (!renderOption) {
70151
return null;
71152
}
72153

73-
let item: MultiselectProps.MultiselectItem;
74-
75-
switch (option.type) {
76-
case 'select-all':
77-
item = {
78-
type: 'select-all',
79-
option: option.option as OptionDefinition,
80-
indeterminate: indeterminate ?? false,
81-
selected: !!selected,
82-
highlighted: !!highlighted,
83-
};
84-
break;
85-
case 'parent':
86-
item = {
87-
index: globalIndex,
88-
type: 'group',
89-
option: option.option as OptionGroup,
90-
indeterminate: indeterminate ?? false,
91-
selected: !!selected,
92-
highlighted: !!highlighted,
93-
disabled: !!disabled,
94-
};
95-
break;
96-
case 'child':
97-
default:
98-
item = {
99-
index: globalIndex,
100-
type: 'item',
101-
option: option.option as OptionDefinition,
102-
selected: !!selected,
103-
highlighted: !!highlighted,
104-
disabled: !!disabled,
105-
};
106-
break;
107-
}
108-
109-
return renderOption({ item, filterText: filteringValue });
154+
return renderOption({ item: getMultiselectItemProps(option), filterText: filteringValue });
110155
};
111156

112157
const renderResult = renderOptionWrapper(option);

src/select/utils/render-options.tsx

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ import { HighlightType } from '../../internal/components/options-list/utils/use-
88
import { VirtualItem } from '../../internal/vendor/react-virtual';
99
import { MultiselectProps } from '../../multiselect/interfaces';
1010
import { SelectProps } from '../interfaces';
11-
import Item from '../parts/item';
12-
import MultiselectItem from '../parts/multiselect-item';
11+
import Item, { ItemParentProps } from '../parts/item';
12+
import MultiselectItem, { MultiselectItemParentProps } from '../parts/multiselect-item';
1313
import OptionGroup from '../parts/option-group';
1414
import { getItemProps } from './get-item-props';
1515

@@ -60,7 +60,7 @@ export const renderOptions = ({
6060
});
6161
};
6262

63-
const renderListItem = (props: any, index: number) => {
63+
const renderListItem = (props: any, index: number, parentProps?: ItemParentProps | MultiselectItemParentProps) => {
6464
const virtualItem = virtualItems && virtualItems[index];
6565
const globalIndex = virtualItem ? virtualItem.index : index;
6666

@@ -85,6 +85,7 @@ export const renderOptions = ({
8585
withScrollbar={withScrollbar}
8686
sticky={isSticky}
8787
renderOption={renderOption}
88+
parentProps={parentProps}
8889
/>
8990
);
9091
};
@@ -106,7 +107,17 @@ export const renderOptions = ({
106107
>
107108
{renderListItem(props, index)}
108109
{children.map(child => (
109-
<React.Fragment key={child.index}>{renderListItem(getNestedItemProps(child), child.index)}</React.Fragment>
110+
<React.Fragment key={child.index}>
111+
{renderListItem(getNestedItemProps(child), child.index, {
112+
option: nestedDropdownOption.option,
113+
disabled: nestedDropdownOption.option.disabled ?? false,
114+
index: index,
115+
virtualIndex: virtualItems?.[index]?.index ?? undefined,
116+
highlighted: props.highlighted ?? false,
117+
selected: props.selected ?? false,
118+
indeterminate: props.indeterminate ?? false,
119+
})}
120+
</React.Fragment>
110121
))}
111122
</OptionGroup>
112123
);

0 commit comments

Comments
 (0)