Skip to content

Commit

Permalink
[PickerTogglerTag]: made to use in PickerToggler renderItem by defaul…
Browse files Browse the repository at this point in the history
…t or independently.
  • Loading branch information
vik753 committed Mar 22, 2024
1 parent c1291e5 commit de21b86
Show file tree
Hide file tree
Showing 5 changed files with 93 additions and 66 deletions.
2 changes: 1 addition & 1 deletion uui-components/src/i18n.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export const i18n = {
showAll: 'SHOW ALL',
},
pickerToggler: {
createItemValue: (length: number, entityName: string) => `${length} ${entityName} selected`,
createCollapsedName: (length: number, entityName: string) => `+ ${length} ${entityName} selected`,
},
pickerInput: {
defaultPlaceholder: (entity: string) => `Please select ${entity}`,
Expand Down
44 changes: 25 additions & 19 deletions uui-components/src/pickers/PickerToggler.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import * as React from 'react';
import { IPickerToggler, IHasIcon, IHasCX, ICanBeReadonly, Icon, uuiMod, uuiElement, uuiMarkers, DataRowProps, cx, IHasRawProps, ICanFocus, isEventTargetInsideClickable } from '@epam/uui-core';
import { IPickerToggler, IHasIcon, IHasCX, ICanBeReadonly, Icon, uuiMod, uuiElement, uuiMarkers, cx, IHasRawProps, ICanFocus, isEventTargetInsideClickable, DataRowProps } from '@epam/uui-core';
import { IconContainer } from '../layout';
import css from './PickerToggler.module.scss';
import { i18n } from '../i18n';
import { useCallback } from 'react';
import { getMaxItems } from './helpers';

export interface PickerTogglerProps<TItem = any, TId = any>
Expand All @@ -27,6 +26,7 @@ export interface PickerTogglerProps<TItem = any, TId = any>
* HTML ID attribute for the toggler input
*/
id?: string;
collapsedNames?: string[];
}

function PickerTogglerComponent<TItem, TId>(props: PickerTogglerProps<TItem, TId>, ref: React.ForwardedRef<HTMLElement>) {
Expand All @@ -37,7 +37,7 @@ function PickerTogglerComponent<TItem, TId>(props: PickerTogglerProps<TItem, TId

React.useImperativeHandle(ref, () => toggleContainer.current, [toggleContainer.current]);

const handleClick = useCallback(
const handleClick = React.useCallback(
(event: Event) => {
if (props.isInteractedOutside(event) && inFocus) {
blur();
Expand Down Expand Up @@ -104,26 +104,32 @@ function PickerTogglerComponent<TItem, TId>(props: PickerTogglerProps<TItem, TId

const renderItems = () => {
const maxItems = getMaxItems(props.maxItems);
if (props.selectedRowsCount > maxItems) {
return props.renderItem?.({
value: i18n.pickerToggler.createItemValue(props.selectedRowsCount, props.entityName || ''),
onCheck: () => {
props.onClear?.();

const multiItems = props.selection?.map((row) => {
const newMultiItems = { ...row,
caption: props.getName(row.value),
isCollapsed: false,
isDisabled: row.isDisabled,
onClear: () => {
row.onCheck?.(row);
// When we delete item it disappears from the DOM and focus is passed to the Body. So in this case we have to return focus on the toggleContainer by hand.
toggleContainer.current?.focus();
},
} };
return props.renderItem?.(newMultiItems);
});

if (props.selectedRowsCount > maxItems) {
const collapsedItem = props.renderItem?.({
caption: i18n.pickerToggler.createCollapsedName(props.selectedRowsCount - maxItems, props.entityName || ''),
isCollapsed: true,
onClear: null,
isDisabled: false,
id: 'collapsed',
} as any);
} else {
return props.selection?.map((row) => {
const newRow = { ...row,
onCheck: () => {
row.onCheck?.(row);
// When we delete item it disappears from the DOM and focus is passed to the Body. So in this case we have to return focus on the toggleContainer by hand.
toggleContainer.current?.focus();
} };
return props.renderItem?.(newRow);
});
multiItems.push(collapsedItem);
}

return multiItems;
};

const renderInput = () => {
Expand Down
8 changes: 8 additions & 0 deletions uui-components/src/pickers/hooks/usePickerInput.ts
Original file line number Diff line number Diff line change
Expand Up @@ -268,11 +268,18 @@ export function usePickerInput<TItem, TId, TProps>(props: UsePickerInputProps<TI
return dataSourceState.search;
};

const getCollapsedNames = (allSelectedRow: DataRowProps<TItem, TId>[], selectedRows: DataRowProps<TItem, TId>[]) => {
return [...allSelectedRow.filter((a) => !selectedRows.some((b) => a.id === b.id))]
.map((row: { value: { name?: string } }) => row?.value?.name);
};

const getTogglerProps = (): PickerTogglerProps<TItem, TId> => {
const selectedRowsCount = view.getSelectedRowsCount();
const allowedMaxItems = getMaxItems(props.maxItems);
const itemsToTake = selectedRowsCount > allowedMaxItems ? allowedMaxItems : selectedRowsCount;
const selectedRows = getSelectedRows(itemsToTake);
const allSelectedRow = getSelectedRows();
const collapsedNames = getCollapsedNames(allSelectedRow, selectedRows);
const {
isDisabled,
autoFocus,
Expand Down Expand Up @@ -312,6 +319,7 @@ export function usePickerInput<TItem, TId, TProps>(props: UsePickerInputProps<TI
onBlur: props.onBlur,
selection: selectedRows,
selectedRowsCount,
collapsedNames,
placeholder: getPlaceholder(),
getName: (i: any) => getName(i),
entityName: getEntityName(selectedRowsCount),
Expand Down
60 changes: 14 additions & 46 deletions uui/components/pickers/PickerToggler.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,19 @@
import * as React from 'react';
import { DataRowProps } from '@epam/uui-core';
import { PickerToggler as UuiPickerToggler, PickerTogglerProps } from '@epam/uui-components';
import { TextPlaceholder } from '../typography';
import { systemIcons } from '../../icons/icons';
import { Tag } from '../widgets';
import * as types from '../types';
import { getMaxItems } from './helpers';
import { PickerToggler as UuiPickerToggler, PickerTogglerProps } from '@epam/uui-components';
import { DataRowProps } from '@epam/uui-core';
import { PickerTogglerTag, PickerTogglerTagProps } from './PickerTogglerTag';
import css from './PickerToggler.module.scss';
import { systemIcons } from '../../icons/icons';

const defaultSize = '36';
const defaultMode = types.EditMode.FORM;

export interface PickerTogglerMods extends types.IHasEditMode {
/**
* Defines component size
* @default 36
*/
* Defines component size
* @default 36
*/
size?: '24' | '30' | '36' | '42' | '48';
}

Expand All @@ -28,43 +26,13 @@ function applyPickerTogglerMods(mods: PickerTogglerMods) {
}

function PickerTogglerComponent<TItem extends string, TId>(props: PickerTogglerProps<TItem, TId> & PickerTogglerMods, ref: React.ForwardedRef<HTMLElement>) {
const getPickerTogglerButtonSize = (propSize: types.ControlSize) => {
switch (propSize) {
case '48':
return '42';
case '42':
return '36';
case '36':
return '30';
case '30':
return '24';
case '24':
return '18';
}
};

const getCaption = (row: DataRowProps<TItem, TId>) => {
const maxItems = getMaxItems(props.maxItems);

if (row.isLoading) {
return <TextPlaceholder />;
} else if (!props.getName || props.selectedRowsCount > maxItems) {
return row.value;
} else {
return props.getName(row.value);
}
};

const renderItem = (row: DataRowProps<TItem, TId>) => (
<Tag
key={ row.rowKey }
caption={ getCaption(row) }
tabIndex={ -1 }
size={ props.size ? getPickerTogglerButtonSize(props.size) : '30' }
onClear={ () => {
row.onCheck?.(row);
} }
isDisabled={ props.isDisabled || props.isReadonly || row?.checkbox?.isDisabled }
const renderItem = (itemProps: DataRowProps<TItem, TId> & PickerTogglerTagProps) => (
<PickerTogglerTag
{ ...itemProps }
key={ itemProps.id as string }
size={ props.size }
collapsedNames={ props.collapsedNames?.join(', ') }
isDisabled={ props.isDisabled || props.isReadonly || itemProps.isDisabled }
/>
);

Expand Down
45 changes: 45 additions & 0 deletions uui/components/pickers/PickerTogglerTag.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import * as React from 'react';
import * as types from '../types';
import { Tag, TagProps } from '../widgets';
import { Tooltip } from '../overlays';

export interface PickerTogglerTagProps extends TagProps {
size?: types.ControlSize;
collapsedNames?: string;
isCollapsed?: boolean;
}

const getPickerTogglerButtonSize = (propSize?: types.ControlSize):TagProps['size'] => {
switch (propSize) {
case '48':
return '42';
case '42':
return '36';
case '36':
return '30';
case '30':
return '24';
case '24':
return '18';
default:
return '30';
}
};

export function PickerTogglerTag(props: PickerTogglerTagProps) {
const tagProps = {
...props,
tabIndex: -1,
size: getPickerTogglerButtonSize(props.size),
};

if (props.isCollapsed && props.collapsedNames?.length) {
return (
<Tooltip content={ props.collapsedNames } openDelay={ 400 }>
<Tag { ...tagProps } />
</Tooltip>
);
}

return <Tag { ...tagProps } />;
}

0 comments on commit de21b86

Please sign in to comment.