Web:Components:Selector: modify for FilesSelector
This commit is contained in:
parent
8366547968
commit
5bdc16a152
@ -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 |
|
||||
|
@ -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,
|
||||
};
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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: [],
|
||||
};
|
||||
|
@ -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[];
|
||||
|
@ -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}
|
||||
|
@ -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[];
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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}
|
||||
|
@ -9,6 +9,7 @@ export type FooterProps = {
|
||||
withAccessRights?: boolean;
|
||||
accessRights?: AccessRight[];
|
||||
selectedAccessRight?: AccessRight | null;
|
||||
disableAcceptButton?: boolean;
|
||||
onAccept?: () => void;
|
||||
onCancel?: () => void;
|
||||
onChangeAccessRights?: (access: AccessRight) => void;
|
||||
|
@ -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}
|
||||
/>
|
||||
|
||||
|
@ -7,6 +7,7 @@ export type Item = {
|
||||
role?: string;
|
||||
isSelected?: boolean;
|
||||
email?: string;
|
||||
isDisabled?: boolean;
|
||||
};
|
||||
|
||||
export type Data = {
|
||||
|
@ -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 };
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user