Skip to content

Commit

Permalink
feat: new list proposal
Browse files Browse the repository at this point in the history
  • Loading branch information
IsaevAlexandr committed Nov 16, 2023
1 parent c346834 commit acbf76d
Show file tree
Hide file tree
Showing 39 changed files with 1,835 additions and 3 deletions.
10 changes: 9 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@
"require": "./build/cjs/components/utils/addComponentKeysets.js",
"import": "./build/esm/components/utils/addComponentKeysets.js"
},
"./unstable": {
"types": "./build/esm/unstable.d.ts",
"require": "./build/cjs/unstable.js",
"import": "./build/esm/unstable.js"
},
"./styles/*": "./styles/*"
},
"main": "./build/cjs/index.js",
Expand All @@ -46,6 +51,9 @@
],
"i18n": [
"./build/esm/components/utils/addComponentKeysets.d.ts"
],
"unstable": [
"./build/esm/unstable.d.ts"
]
}
},
Expand Down Expand Up @@ -165,4 +173,4 @@
"prettier --write"
]
}
}
}
18 changes: 18 additions & 0 deletions src/components/ListNext/ListRadiuses.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
@use '../variables';

$block: '.#{variables.$ns}list-radiuses';

#{$block} {
&_s {
border-radius: 5px;
}
&_m {
border-radius: 6px;
}
&_l {
border-radius: 8px;
}
&_xl {
border-radius: 10px;
}
}
27 changes: 27 additions & 0 deletions src/components/ListNext/__stories__/FlattenRenderer.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import React from 'react';

import type {Meta, StoryFn} from '@storybook/react';

import {Flex} from '../../layout';

import {FlattenList, FlattenListProps} from './components/FlattenList';

export default {
title: 'Unstable/ListNext/FlattenRenderer(Virtualized)',
component: FlattenList,
} as Meta;

const DefaultTemplate: StoryFn<FlattenListProps> = (props) => {
return (
<Flex width={400} style={{height: 500}}>
<FlattenList {...props} />
</Flex>
);
};

export const Examples = DefaultTemplate.bind({});

Examples.args = {
size: 's',
itemsCount: 1000,
};
18 changes: 18 additions & 0 deletions src/components/ListNext/__stories__/ListInfinityScroll.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import React from 'react';

import type {Meta, StoryFn} from '@storybook/react';

import {InfinityScrollList, InfinityScrollListProps} from './components/InfinityScrollList';

export default {
title: 'Unstable/ListNext/InfinityScrollList',
component: InfinityScrollList,
} as Meta;

const ListInfinityScroll: StoryFn<InfinityScrollListProps> = (props) => {
return <InfinityScrollList {...props} />;
};
export const Examples = ListInfinityScroll.bind({});
Examples.args = {
size: 'm',
};
25 changes: 25 additions & 0 deletions src/components/ListNext/__stories__/PopupWithToggler.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import React from 'react';

import type {Meta, StoryFn} from '@storybook/react';

import {Flex} from '../../layout';

import {PopupWithTogglerList, PopupWithTogglerListProps} from './components/PopupWithTogglerList';

export default {
title: 'Unstable/ListNext/PopupWithToggler',
component: PopupWithTogglerList,
} as Meta;

const PopupWithTogglerScroll: StoryFn<PopupWithTogglerListProps> = (props) => {
return (
<Flex>
<PopupWithTogglerList {...props} />
</Flex>
);
};
export const Examples = PopupWithTogglerScroll.bind({});
Examples.args = {
itemsCount: 10,
size: 'm',
};
27 changes: 27 additions & 0 deletions src/components/ListNext/__stories__/RecursiveRenderer.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import React from 'react';

import type {Meta, StoryFn} from '@storybook/react';

import {Flex} from '../../layout';

import {RecursiveList, RecursiveListProps} from './components/RecursiveList';

export default {
title: 'Unstable/ListNext/RecursiveRenderer',
component: RecursiveList,
} as Meta;

const DefaultTemplate: StoryFn<RecursiveListProps> = (props) => {
return (
<Flex width={400}>
<RecursiveList {...props} />
</Flex>
);
};

export const Examples = DefaultTemplate.bind({});

Examples.args = {
size: 's',
itemsCount: 10,
};
102 changes: 102 additions & 0 deletions src/components/ListNext/__stories__/components/FlattenList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
import React from 'react';

import get from 'lodash/get';

import {TextInput} from '../../../controls';
import {Flex} from '../../../layout';
import {ListGroupItemView} from '../../components/ListGroupItemView/ListGroupItemView';
import {ListItemView} from '../../components/ListItemView/ListItemView';
import {VirtualizedListContainer} from '../../components/VirtualizedListContainer/VirtualizedListContainer';
import {useFlattenListItems} from '../../hooks/useFlattenListItems';
import {useListFilter} from '../../hooks/useListFilter';
import {useListItemsState} from '../../hooks/useListItemsState';
import {useListKeydown} from '../../hooks/useListKeydown';
import {useListState} from '../../hooks/useListState';
import type {ListItemId, ListSizeTypes} from '../../types';
import {computeItemSize} from '../../utils/computeItemSize';
import {listStateToProps} from '../../utils/listStateToProps';
import {createRandomizedData} from '../utils/makeData';

export interface FlattenListProps {
itemsCount: number;
size: ListSizeTypes;
}

export const FlattenList = ({itemsCount, size}: FlattenListProps) => {
const containerRef = React.useRef(null);
const items = React.useMemo(
() => createRandomizedData<{title: string}>(itemsCount),
[itemsCount],
);

const filterState = useListFilter({items});
const {byId, groupsState, itemsState, disabled, selected, expanded} = useListItemsState({
items: filterState.items,
});
const listState = useListState({disabled, selected, expanded});

const flattenIdsOrder = useFlattenListItems({
items: filterState.items,
expanded: listState.expanded,
});

const onItemClick = React.useCallback(
(id: ListItemId) => {
if (id in groupsState) {
listState.setExpanded((state) => ({
...state,
[id]: id in state ? !state[id] : false,
}));
} else {
listState.setSelected((state) => ({
// can select only one item
[id]: !state[id],
}));
}

listState.setActiveItemId(id);
},
[groupsState, listState],
);

useListKeydown({
containerRef,
onItemClick,
order: flattenIdsOrder,
...listState,
});

return (
<Flex direction="column" gap="5" grow>
<TextInput
autoComplete="off"
value={filterState.filter}
onUpdate={filterState.onChange}
ref={filterState.filterRef}
/>
<Flex as="div" direction="column" grow ref={containerRef} tabIndex={-1} role="listbox">
<VirtualizedListContainer
items={flattenIdsOrder}
itemSize={(index) =>
computeItemSize(
size,
Boolean(get(byId[flattenIdsOrder[index]], 'subtitle')),
)
}
>
{({item: id, index: _index}) => {
const {isGroup, ...props} = listStateToProps(
{groupsState, itemsState, ...listState},
id,
onItemClick,
);

const View = isGroup ? ListGroupItemView : ListItemView;

return <View size={size} {...props} {...byId[id]} />;
}}
</VirtualizedListContainer>
</Flex>
</Flex>
);
};
Loading

0 comments on commit acbf76d

Please sign in to comment.