Web:Components:Selector: modify for FilesSelector

This commit is contained in:
Timofey Boyko 2023-06-16 12:41:23 +03:00
parent 8366547968
commit 5bdc16a152
14 changed files with 101 additions and 48 deletions

View File

@ -44,12 +44,13 @@ import Selector from "@docspace/components/selector";
breadCrumbs={[]}
onSelectBreadCrumb={function noRefCheck() {}}
breadCrumbsLoader={<></>}
hideSearch={false}
withSearch={true}
isBreadCrumbsLoading={false}
withFooterInput={false}
footerInputHeader={""}
footerCheckboxLabel={""}
currentFooterInputValue={""}
alwaysShowFooter={false}
/>
```
@ -64,7 +65,7 @@ import Selector from "@docspace/components/selector";
| `withoutBackButton` | `bool` | - | - | - | Hide header back button |
| `onBackClick` | `func` | - | - | - | What the header arrow will trigger when clicked |
| `searchPlaceholder` | `string` | - | - | - | Placeholder for search input |
| `hideSearch` | `bool` | - | - | - | Hide search input |
| `withSearch` | `bool` | - | - | true | Show search input |
| `onSearch` | `func` | - | - | - | What the search input will trigger when user stopped typing |
| `onClearSearch` | `func` | - | - | - | What the clear icon of search input will trigger when clicked |
| `items` | `array` | - | - | - | Displaying items |
@ -106,3 +107,5 @@ import Selector from "@docspace/components/selector";
| `footerCheckboxLabel` | `string` | - | - | - | Title of checkbox |
| `footerInputHeader` | `string` | - | - | - | Header of new name block |
| `withFooterInput` | `bool` | - | - | false | Show name change input |
| `alwaysShowFooter` | `bool` | - | - | false | Always show buttons |
| `disableAcceptButton` | `bool` | - | - | false | Disable click at accept button |

View File

@ -203,8 +203,10 @@ Default.args = {
onSelectBreadCrumb: (item) => {},
breadCrumbsLoader: <StyledBreadCrumbsLoader />,
withoutBackButton: false,
hideSearch: false,
withSearch: false,
isBreadCrumbsLoading: false,
alwaysShowFooter: false,
disableAcceptButton: false,
};
BreadCrumbs.args = {
@ -253,12 +255,14 @@ BreadCrumbs.args = {
onSelectBreadCrumb: (item) => {},
breadCrumbsLoader: <StyledBreadCrumbsLoader />,
withoutBackButton: false,
hideSearch: false,
withSearch: false,
isBreadCrumbsLoading: false,
withFooterInput: false,
footerInputHeader: "",
footerCheckboxLabel: "",
currentFooterInputValue: "",
alwaysShowFooter: false,
disableAcceptButton: false,
};
NewName.args = {
@ -305,10 +309,12 @@ NewName.args = {
onSelectBreadCrumb: (item) => {},
breadCrumbsLoader: <StyledBreadCrumbsLoader />,
withoutBackButton: false,
hideSearch: false,
withSearch: false,
isBreadCrumbsLoading: false,
withFooterInput: true,
footerInputHeader: "File name",
footerCheckboxLabel: "Open saved document in new tab",
currentFooterInputValue: "OldFIleName.docx",
alwaysShowFooter: false,
disableAcceptButton: false,
};

View File

@ -20,13 +20,13 @@ export type SelectorProps = {
headerLabel: string;
withoutBackButton?: boolean;
onBackClick?: () => void;
hideSearch?: boolean;
withSearch?: boolean;
searchPlaceholder?: string;
searchValue?: string;
onSearch?: (value: string) => void;
onClearSearch?: () => void;
items: Item[];
onSelect: (item: Item) => void;
onSelect: (item: any) => void;
isMultiSelect?: boolean;
selectedItems?: Item[];
acceptButtonLabel: string;
@ -55,14 +55,14 @@ export type SelectorProps = {
searchEmptyScreenDescription?: string;
hasNextPage?: boolean;
isNextPageLoading?: boolean;
loadNextPage?: (startIndex: number) => void;
loadNextPage?: (startIndex: number, ...rest: any) => Promise<void>;
totalItems: number;
isLoading?: boolean;
searchLoader?: any;
rowLoader?: any;
withBreadCrumbs?: boolean;
breadCrumbs?: BreadCrumb[];
onSelectBreadCrumb?: (item: BreadCrumb) => void;
onSelectBreadCrumb?: (item: any) => void;
breadCrumbsLoader?: any;
isBreadCrumbsLoading?: boolean;
@ -70,4 +70,6 @@ export type SelectorProps = {
footerInputHeader?: string;
currentFooterInputValue?: string;
footerCheckboxLabel?: string;
alwaysShowFooter?: boolean;
disableAcceptButton?: boolean;
};

View File

@ -25,7 +25,7 @@ const Selector = ({
breadCrumbs,
onSelectBreadCrumb,
hideSearch,
withSearch,
searchLoader,
searchPlaceholder,
searchValue,
@ -72,6 +72,9 @@ const Selector = ({
footerInputHeader,
footerCheckboxLabel,
currentFooterInputValue,
alwaysShowFooter,
disableAcceptButton,
}: SelectorProps) => {
const [footerVisible, setFooterVisible] = React.useState<boolean>(false);
const [isSearch, setIsSearch] = React.useState<boolean>(false);
@ -96,7 +99,7 @@ const Selector = ({
(value: string) => {
onSearch && onSearch(value);
setIsSearch(!!value);
setIsSearch(true);
},
[onSearch]
);
@ -109,6 +112,7 @@ const Selector = ({
const onSelectAction = (item: Item) => {
onSelect &&
onSelect({
...item,
id: item.id,
email: item.email || "",
avatar: item.avatar,
@ -295,7 +299,7 @@ const Selector = ({
/>
<Body
footerVisible={footerVisible}
footerVisible={footerVisible || !!alwaysShowFooter}
isSearch={isSearch}
isAllIndeterminate={
newSelectedItems.length !== renderedItems.length &&
@ -334,11 +338,11 @@ const Selector = ({
onSelectBreadCrumb={onSelectBreadCrumb}
breadCrumbsLoader={breadCrumbsLoader}
isBreadCrumbsLoading={isBreadCrumbsLoading}
hideSearch={hideSearch}
withSearch={withSearch}
withFooterInput={withFooterInput}
/>
{footerVisible && (
{(footerVisible || alwaysShowFooter) && (
<Footer
isMultiSelect={isMultiSelect}
acceptButtonLabel={acceptButtonLabel}
@ -358,6 +362,7 @@ const Selector = ({
setNewFooterInputValue={setNewFooterInputValue}
isFooterCheckboxChecked={isFooterCheckboxChecked}
setIsFooterCheckboxChecked={setIsFooterCheckboxChecked}
disableAcceptButton={disableAcceptButton}
/>
)}
</StyledSelector>
@ -465,8 +470,10 @@ Selector.defaultProps = {
withCancelButton: false,
withoutBackButton: false,
isBreadCrumbsLoading: false,
hideSearch: false,
withSearch: true,
withFooterInput: false,
alwaysShowFooter: false,
disableAcceptButton: false,
selectedItems: [],
};

View File

@ -8,7 +8,7 @@ export type BodyProps = {
isAllChecked?: boolean;
placeholder?: string;
value?: string;
hideSearch?: boolean;
withSearch?: boolean;
onSearch: (value: string) => void;
onClearSearch: () => void;
items: Item[];

View File

@ -53,7 +53,7 @@ const Body = ({
breadCrumbs,
onSelectBreadCrumb,
breadCrumbsLoader,
hideSearch,
withSearch,
isBreadCrumbsLoading,
withFooterInput,
}: BodyProps) => {
@ -63,7 +63,6 @@ const Body = ({
const listOptionsRef = React.useRef<any>(null);
const itemsCount = hasNextPage ? items.length + 1 : items.length;
const withSearch = isSearch || itemsCount > 0;
const resetCache = React.useCallback(() => {
if (listOptionsRef && listOptionsRef.current) {
@ -101,7 +100,7 @@ const Body = ({
let listHeight = bodyHeight - CONTAINER_PADDING;
if (withSearch) listHeight -= SEARCH_HEIGHT;
if (withSearch || isSearch || itemsCount > 0) listHeight -= SEARCH_HEIGHT;
if (withBreadCrumbs) listHeight -= BREAD_CRUMBS_HEIGHT;
@ -130,7 +129,7 @@ const Body = ({
{isBreadCrumbsLoading ? (
searchLoader
) : withSearch && !hideSearch ? (
) : withSearch || isSearch || (itemsCount > 0 && withSearch) ? (
<Search
placeholder={placeholder}
value={value}

View File

@ -1,6 +1,8 @@
export type BreadCrumb = {
id: string | number;
label: string;
isRoom?: boolean;
minWidth?: string;
onClick?: (e: any, open: any, item: BreadCrumb) => void;
};
@ -9,6 +11,8 @@ export type DisplayedItem = {
label: string;
isArrow: boolean;
isList: boolean;
isRoom?: boolean;
listItems?: BreadCrumb[];
};

View File

@ -20,7 +20,7 @@ const StyledBreadCrumbs = styled.div<{
grid-template-columns: ${(props) => props.gridTemplateColumns};
grid-column-gap: 4px;
grid-column-gap: 8px;
align-items: center;

View File

@ -19,18 +19,29 @@ const BreadCrumbs = ({ breadCrumbs, onSelectBreadCrumb }: BreadCrumbsProps) => {
[]
);
const onClickItem = React.useCallback((e, open, item: BreadCrumb) => {
onSelectBreadCrumb && onSelectBreadCrumb(item);
}, []);
const onClickItem = React.useCallback(
(e, open, item: BreadCrumb) => {
onSelectBreadCrumb && onSelectBreadCrumb(item);
},
[breadCrumbs]
);
const calculateDisplayedItems = React.useCallback(
(items: BreadCrumb[]) => {
const itemsLength = items.length;
const oldItems: BreadCrumb[] = [];
items.forEach((item) =>
oldItems.push({
...item,
id: item.id.toString(),
})
);
if (itemsLength > 0) {
const newItems: DisplayedItem[] = [];
if (itemsLength <= 3) {
items.forEach((item, index) => {
oldItems.forEach((item, index) => {
newItems.push({
...item,
isArrow: false,
@ -38,7 +49,7 @@ const BreadCrumbs = ({ breadCrumbs, onSelectBreadCrumb }: BreadCrumbsProps) => {
listItems: [],
});
if (index !== items.length - 1) {
if (index !== oldItems.length - 1) {
newItems.push({
id: `arrow-${index}`,
label: "",
@ -50,7 +61,7 @@ const BreadCrumbs = ({ breadCrumbs, onSelectBreadCrumb }: BreadCrumbsProps) => {
});
} else {
newItems.push({
...items[0],
...oldItems[0],
isArrow: false,
isList: false,
listItems: [],
@ -81,7 +92,7 @@ const BreadCrumbs = ({ breadCrumbs, onSelectBreadCrumb }: BreadCrumbsProps) => {
});
newItems.push({
...items[itemsLength - 2],
...oldItems[itemsLength - 2],
isArrow: false,
isList: false,
listItems: [],
@ -96,17 +107,21 @@ const BreadCrumbs = ({ breadCrumbs, onSelectBreadCrumb }: BreadCrumbsProps) => {
});
newItems.push({
...items[itemsLength - 1],
...oldItems[itemsLength - 1],
isArrow: false,
isList: false,
listItems: [],
});
items.splice(0, 1);
items.splice(items.length - 2, 2);
oldItems.splice(0, 1);
oldItems.splice(oldItems.length - 2, 2);
items.forEach((item) => {
newItems[2].listItems?.push({ ...item, onClick: onClickItem });
oldItems.forEach((item) => {
newItems[2].listItems?.push({
...item,
minWidth: "150px",
onClick: onClickItem,
});
});
}
@ -124,13 +139,13 @@ const BreadCrumbs = ({ breadCrumbs, onSelectBreadCrumb }: BreadCrumbsProps) => {
let gridTemplateColumns = "minmax(1px, max-content)";
if (displayedItems.length > 3) {
if (displayedItems.length > 5) {
gridTemplateColumns =
"minmax(1px, max-content) 12px 16px 12px minmax(1px, max-content) 12px minmax(1px, max-content)";
} else if (displayedItems.length === 3) {
} else if (displayedItems.length === 5) {
gridTemplateColumns =
"minmax(1px, max-content) 12px minmax(1px, max-content) 12px minmax(1px, max-content)";
} else if (displayedItems.length === 2) {
} else if (displayedItems.length === 3) {
gridTemplateColumns =
"minmax(1px, max-content) 12px minmax(1px, max-content)";
}
@ -162,7 +177,11 @@ const BreadCrumbs = ({ breadCrumbs, onSelectBreadCrumb }: BreadCrumbsProps) => {
if (index === displayedItems.length - 1) return;
onSelectBreadCrumb &&
onSelectBreadCrumb({ id: item.id, label: item.label });
onSelectBreadCrumb({
id: item.id,
label: item.label,
isRoom: item.isRoom,
});
}}
>
{item.label}

View File

@ -9,6 +9,7 @@ export type FooterProps = {
withAccessRights?: boolean;
accessRights?: AccessRight[];
selectedAccessRight?: AccessRight | null;
disableAcceptButton?: boolean;
onAccept?: () => void;
onCancel?: () => void;
onChangeAccessRights?: (access: AccessRight) => void;

View File

@ -24,6 +24,7 @@ const Footer = React.memo(
accessRights,
selectedAccessRight,
onAccept,
disableAcceptButton,
onCancel,
onChangeAccessRights,
@ -82,6 +83,7 @@ const Footer = React.memo(
primary
scale
size={"normal"}
isDisabled={disableAcceptButton}
onClick={onAccept}
/>

View File

@ -7,6 +7,7 @@ export type Item = {
role?: string;
isSelected?: boolean;
email?: string;
isDisabled?: boolean;
};
export type Data = {

View File

@ -9,6 +9,7 @@ const selectedCss = css`
const StyledItem = styled.div<{
isSelected: boolean | undefined;
isDisabled?: boolean;
isMultiSelect: boolean;
}>`
display: flex;
@ -18,8 +19,6 @@ const StyledItem = styled.div<{
box-sizing: border-box;
${(props) => props.isSelected && !props.isMultiSelect && selectedCss}
.room-logo,
.user-avatar {
min-width: 32px;
@ -46,12 +45,20 @@ const StyledItem = styled.div<{
}
}
@media (hover: hover) {
&:hover {
cursor: pointer;
background: ${(props) => props.theme.selector.item.hoverBackground};
}
}
${(props) =>
props.isDisabled
? css`
opacity: 0.5;
`
: css`
${props.isSelected && !props.isMultiSelect && selectedCss}
@media (hover: hover) {
&:hover {
cursor: pointer;
background: ${props.theme.selector.item.hoverBackground};
}
}
`}
`;
StyledItem.defaultProps = { theme: Base };

View File

@ -38,7 +38,7 @@ const Item = React.memo(({ index, style, data }: ItemProps) => {
if (!item || (item && !item.id))
return <div style={style}>{rowLoader}</div>;
const { label, avatar, icon, role, isSelected } = item;
const { label, avatar, icon, role, isSelected, isDisabled } = item;
const currentRole = role ? role : "user";
@ -50,8 +50,9 @@ const Item = React.memo(({ index, style, data }: ItemProps) => {
const onClick = (e: React.MouseEvent<HTMLDivElement>) => {
if (
(e.target instanceof HTMLElement || e.target instanceof SVGElement) &&
!!e.target.closest(".checkbox")
((e.target instanceof HTMLElement || e.target instanceof SVGElement) &&
!!e.target.closest(".checkbox")) ||
isDisabled
)
return;
@ -65,6 +66,7 @@ const Item = React.memo(({ index, style, data }: ItemProps) => {
style={style}
onClick={onClick}
className="test-22"
isDisabled={isDisabled}
>
{!isLogo ? (
<Avatar