Skip to content

Commit

Permalink
fix: review fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
IsaevAlexandr committed Jan 17, 2024
1 parent b5f8772 commit df03760
Show file tree
Hide file tree
Showing 39 changed files with 314 additions and 267 deletions.
2 changes: 2 additions & 0 deletions src/components/TreeSelect/TreeSelect.scss
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ $block: '.#{variables.$ns}tree-select';
}

&__popup {
padding: 4px 0;
border-radius: 6px;
overflow: hidden;
min-width: 300px;
}
Expand Down
42 changes: 22 additions & 20 deletions src/components/TreeSelect/TreeSelect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,10 @@ import React from 'react';
import {useForkRef, useUniqId} from '../../hooks';
import {SelectControl} from '../Select/components';
import {SelectPopup} from '../Select/components/SelectPopup/SelectPopup';
import {borderRadius} from '../borderRadius';
import {Flex} from '../layout';
import {useMobile} from '../mobile';
import {
type ListItemId,
ListItemView,
getItemRenderState,
isKnownStructureGuard,
scrollToListItem,
Expand All @@ -18,6 +16,7 @@ import {
} from '../useList';
import {type CnMods, block} from '../utils/cn';

import {TreeSelectItem} from './TreeSelectItem';
import {TreeListContainer} from './components/TreeListContainer/TreeListContainer';
import {useTreeSelectSelection, useValue} from './hooks/useTreeSelectSelection';
import type {RenderControlProps, TreeSelectProps} from './types';
Expand Down Expand Up @@ -83,17 +82,17 @@ export const TreeSelect = React.forwardRef(function TreeSelect<T>(

const listParsedState = useList({
items,
expandedById: listState.expandedById,
getId,
...listState,
});

const wrappedOnUpdate = React.useCallback(
(ids: ListItemId[]) =>
onUpdate?.(
ids,
ids.map((id) => listParsedState.byId[id]),
ids.map((id) => listParsedState.itemsById[id]),
),
[listParsedState.byId, onUpdate],
[listParsedState.itemsById, onUpdate],
);

const {open, toggleOpen, handleClearValue, handleMultipleSelection, handleSingleSelection} =
Expand Down Expand Up @@ -139,8 +138,8 @@ export const TreeSelect = React.forwardRef(function TreeSelect<T>(
id,
isGroup: id in listParsedState.groupsState,
isLastItem:
listParsedState.flattenIdsOrder[
listParsedState.flattenIdsOrder.length - 1
listParsedState.existedFlattenIds[
listParsedState.existedFlattenIds.length - 1
] === id,
disabled: listState.disabledById[id],
});
Expand All @@ -152,7 +151,7 @@ export const TreeSelect = React.forwardRef(function TreeSelect<T>(
onItemClick,
listState,
listParsedState.groupsState,
listParsedState.flattenIdsOrder,
listParsedState.existedFlattenIds,
groupsBehavior,
multiple,
handleMultipleSelection,
Expand All @@ -167,7 +166,7 @@ export const TreeSelect = React.forwardRef(function TreeSelect<T>(
const lastSelectedItemId = value[value.length - 1];
containerRef.current?.focus();

const firstItemId = listParsedState.flattenIdsOrder[0];
const firstItemId = listParsedState.existedFlattenIds[0];

listState.setActiveItemId(lastSelectedItemId ?? firstItemId);

Expand Down Expand Up @@ -207,10 +206,10 @@ export const TreeSelect = React.forwardRef(function TreeSelect<T>(
selectedOptionsContent={React.Children.toArray(
value.map((id) => {
if ('renderControlContent' in props) {
return props.renderControlContent(listParsedState.byId[id]).title;
return props.renderControlContent(listParsedState.itemsById[id]).title;
}

const items = listParsedState.byId[id];
const items = listParsedState.itemsById[id];

if (isKnownStructureGuard(items)) {
return items.title;
Expand Down Expand Up @@ -247,7 +246,7 @@ export const TreeSelect = React.forwardRef(function TreeSelect<T>(
{togglerNode}
<SelectPopup
ref={controlWrapRef}
className={b('popup', borderRadius({size}, popupClassName))}
className={b('popup', popupClassName)}
controlRef={controlRef}
width={popupWidth}
open={open}
Expand All @@ -264,7 +263,7 @@ export const TreeSelect = React.forwardRef(function TreeSelect<T>(
{...listParsedState}
{...listState}
renderItem={(id, renderContextProps) => {
const [item, state, context] = getItemRenderState({
const renderState = getItemRenderState({
id,
size,
onItemClick: handleItemClick,
Expand All @@ -273,19 +272,22 @@ export const TreeSelect = React.forwardRef(function TreeSelect<T>(
});

// assign components scope logic
state.hasSelectionIcon = context.groupState
? groupsBehavior === 'selectable'
: undefined;
renderState.props.hasSelectionIcon = Boolean(multiple);

if (renderItem) {
return renderItem(item, state, context, renderContextProps);
return renderItem(
renderState.data,
renderState.props,
renderState.context,
renderContextProps,
);
}

const itemData = listParsedState.byId[id];
const itemData = listParsedState.itemsById[id];

return (
<ListItemView
{...state}
<TreeSelectItem
{...renderState.props}
// eslint-disable-next-line no-nested-ternary
{...('renderControlContent' in props
? props.renderControlContent(itemData)
Expand Down
7 changes: 7 additions & 0 deletions src/components/TreeSelect/TreeSelectItem/TreeSelectItem.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
@use '../../variables';

$block: '.#{variables.$ns}tree-select-item';

#{$block} {
padding: 0 4px;
}
26 changes: 26 additions & 0 deletions src/components/TreeSelect/TreeSelectItem/TreeSelectItem.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import React from 'react';

import {ListItemView, ListItemViewProps} from '../../useList';
import {block} from '../../utils/cn';

import './TreeSelectItem.scss';

const b = block('tree-select-item');

export interface TreeSelectItemProps extends Omit<ListItemViewProps, 'as'> {
as?: 'div' | 'li';
itemClassName?: string;
}

export const TreeSelectItem = React.forwardRef(function TreeSelectItem(
{as = 'div', className, itemClassName, ...props}: TreeSelectItemProps,
ref?: any,
) {
const Tag: React.ElementType = as;

return (
<Tag ref={ref} className={b(null, className)}>
<ListItemView as={as} {...props} className={itemClassName} />
</Tag>
);
});
1 change: 1 addition & 0 deletions src/components/TreeSelect/TreeSelectItem/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './TreeSelectItem';
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,6 @@ const WithGroupSelectionControlledStateAndCustomIconTemplate: StoryFn<
export const WithGroupSelectionControlledStateAndCustomIcon =
WithGroupSelectionControlledStateAndCustomIconTemplate.bind({});
WithGroupSelectionControlledStateAndCustomIcon.args = {
multiple: true,
groupsBehavior: 'selectable',
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ import React from 'react';
import {Label} from '../../../Label';
import {Loader} from '../../../Loader';
import {Flex, spacing} from '../../../layout';
import {ListItemView} from '../../../useList';
import {IntersectionContainer} from '../../../useList/__stories__/components/IntersectionContainer/IntersectionContainer';
import {useInfinityFetch} from '../../../useList/__stories__/utils/useInfinityFetch';
import {TreeSelect} from '../../TreeSelect';
import {TreeSelectItem} from '../../TreeSelectItem';
import type {TreeSelectProps} from '../../types';

import {RenderVirtualizedContainer} from './RenderVirtualizedContainer';
Expand All @@ -33,10 +33,9 @@ export const InfinityScrollExample = ({itemsCount = 5, ...props}: InfinityScroll
{...props}
items={data}
value={value}
popupClassName={spacing({p: 2})}
renderItem={(item, state, {isLastItem, groupState}) => {
const node = (
<ListItemView
<TreeSelectItem
{...state}
{...item}
endSlot={
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@ import type {RenderContainerProps} from '../../types';
export const RenderVirtualizedContainer = <T,>({
id,
containerRef,
flattenIdsOrder,
existedFlattenIds,
renderItem,
size,
}: RenderContainerProps<T>) => {
return (
<ListContainerView fixedHeight id={id} ref={containerRef}>
<VirtualizedListContainer
items={flattenIdsOrder}
items={existedFlattenIds}
itemSize={(_index) => computeItemSize(size)}
>
{renderItem}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,19 @@ import {

import {Icon} from '../../../Icon';
import {Flex} from '../../../layout';
import {ListContainerView, ListItemView, ListItemViewProps} from '../../../useList';
import {ListContainerView} from '../../../useList';
import {createRandomizedData} from '../../../useList/__stories__/utils/makeData';
import {reorderArray} from '../../../useList/__stories__/utils/reorderArray';
import {TreeSelect} from '../../TreeSelect';
import {TreeSelectItem, TreeSelectItemProps} from '../../TreeSelectItem';
import type {TreeSelectProps} from '../../types';

const DraggableListItem = ({
provided,
...props
}: {provided?: DraggableProvided} & ListItemViewProps) => {
}: {provided?: DraggableProvided} & TreeSelectItemProps) => {
return (
<ListItemView
<TreeSelectItem
{...provided?.dragHandleProps}
{...provided?.draggableProps}
ref={provided?.innerRef}
Expand Down Expand Up @@ -60,7 +61,7 @@ export const WithDndListExample = (props: WithDndListExampleProps) => {
setValue([id]);
}
}}
renderContainer={({renderItem, flattenIdsOrder, containerRef, id}) => {
renderContainer={({renderItem, existedFlattenIds, containerRef, id}) => {
return (
<DragDropContext onDragEnd={handleDrugEnd}>
<Droppable
Expand All @@ -70,7 +71,7 @@ export const WithDndListExample = (props: WithDndListExampleProps) => {
snapshot: DraggableStateSnapshot,
rubric: DraggableRubric,
) => {
return renderItem(flattenIdsOrder[rubric.source.index], {
return renderItem(existedFlattenIds[rubric.source.index], {
provided,
active: snapshot.isDragging,
});
Expand All @@ -82,7 +83,7 @@ export const WithDndListExample = (props: WithDndListExampleProps) => {
{...droppableProvided.droppableProps}
ref={droppableProvided.innerRef}
>
{flattenIdsOrder.map((id) => renderItem(id))}
{existedFlattenIds.map((id) => renderItem(id))}
{droppableProvided.placeholder}
</div>
</ListContainerView>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,17 +56,17 @@ export const WithFiltrationAndControlsExample = ({
autoFocus
hasClear
placeholder="Type for search..."
className={spacing({p: 2})}
className={spacing({px: 2, py: 1})}
style={{boxSizing: 'border-box'}}
autoComplete="off"
value={filterState.filter}
onUpdate={filterState.onChange}
onUpdate={filterState.onFilterUpdate}
ref={filterState.filterRef}
/>
}
renderContainer={renderContainer}
slotAfterListBody={
<Flex gap="2" className={spacing({p: 2})}>
<Flex gap="2" className={spacing({px: 2, py: 1})}>
<Button
width="max"
onClick={() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,10 @@ import {ChevronDown, ChevronUp, Database, PlugConnection} from '@gravity-ui/icon
import {Button} from '../../../Button';
import {Icon} from '../../../Icon';
import {Flex, spacing} from '../../../layout';
import {
type KnownItemStructure,
ListItemId,
ListItemView,
getListParsedState,
} from '../../../useList';
import {type KnownItemStructure, ListItemId, getListParsedState} from '../../../useList';
import {createRandomizedData} from '../../../useList/__stories__/utils/makeData';
import {TreeSelect} from '../../TreeSelect';
import {TreeSelectItem} from '../../TreeSelectItem';
import type {TreeSelectProps} from '../../types';

/**
Expand Down Expand Up @@ -55,11 +51,10 @@ export const WithGroupSelectionControlledStateAndCustomIconExample = ({
size="l"
renderControlContent={mapCustomDataStructureToKnownProps}
expandedById={expandedById}
popupClassName={spacing({p: 2})}
value={value}
renderItem={(item, state, {groupState}) => {
return (
<ListItemView
<TreeSelectItem
{...state}
{...mapCustomDataStructureToKnownProps(item)}
startSlot={
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@ import {Button} from '../../../Button';
import {DropdownMenu} from '../../../DropdownMenu';
import {Icon} from '../../../Icon';
import {Flex, spacing} from '../../../layout';
import {ListItemId, ListItemView} from '../../../useList';
import type {ListItemId} from '../../../useList';
import {createRandomizedData} from '../../../useList/__stories__/utils/makeData';
import {TreeSelect} from '../../TreeSelect';
import {TreeSelectItem} from '../../TreeSelectItem';
import type {TreeSelectProps} from '../../types';

export interface WithItemLinksAndActionsExampleProps
Expand Down Expand Up @@ -48,7 +49,7 @@ export const WithItemLinksAndActionsExample = (props: WithItemLinksAndActionsExa
href="#"
style={{textDecoration: 'none', color: 'inherit', width: '100%'}}
>
<ListItemView
<TreeSelectItem
{...item}
{...state}
endSlot={
Expand Down
1 change: 1 addition & 0 deletions src/components/TreeSelect/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export {TreeSelect} from './TreeSelect';
export {TreeSelectItem, type TreeSelectItemProps} from './TreeSelectItem';
export type {TreeSelectProps, RenderItem} from './types';
13 changes: 9 additions & 4 deletions src/components/TreeSelect/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import type {QAProps} from '../types';
import type {
KnownItemStructure,
ListItemId,
ListItemSizeType,
ListItemType,
ListParsedState,
ListSizeTypes,
ListState,
OverrideItemContext,
RenderItemContext,
Expand All @@ -18,7 +18,7 @@ export type RenderControlProps = {
toggleOpen(): void;
clearValue(): void;
ref: React.Ref<HTMLButtonElement>;
size: ListSizeTypes;
size: ListItemSizeType;
value: ListItemId[];
id: string;
activeItemId?: ListItemId;
Expand All @@ -36,9 +36,10 @@ export type RenderItem<T> = (
export type RenderContainerProps<T> = ListParsedState<T> &
ListState & {
id: string;
size: ListSizeTypes;
size: ListItemSizeType;
renderItem(id: ListItemId, renderContextProps?: Object): React.JSX.Element;
containerRef: React.RefObject<HTMLDivElement>;
className?: string;
};

interface TreeSelectBaseProps<T> extends QAProps, Partial<Omit<ListState, 'selectedById'>> {
Expand All @@ -63,7 +64,11 @@ interface TreeSelectBaseProps<T> extends QAProps, Partial<Omit<ListState, 'selec
* @default - 'expandable
*/
groupsBehavior?: 'expandable' | 'selectable';
size: ListSizeTypes;
/**
* List popup has fixes size - 6px. This prop is used to control only list item size view.
* To override popup border radius use `popupClassName` class
*/
size: ListItemSizeType;
/**
* Use slots if you don't need access to internal TreeListState.
* In other situations use `renderContainer` method
Expand Down
Loading

0 comments on commit df03760

Please sign in to comment.