diff --git a/cypress/snapshots/ui/components/Pickers/DatePicker.component-test.tsx/plasma-ui DatePicker -- with single item.snap.png b/cypress/snapshots/ui/components/Pickers/DatePicker.component-test.tsx/plasma-ui DatePicker -- with single item.snap.png
new file mode 100644
index 000000000..521c72bec
Binary files /dev/null and b/cypress/snapshots/ui/components/Pickers/DatePicker.component-test.tsx/plasma-ui DatePicker -- with single item.snap.png differ
diff --git a/cypress/snapshots/ui/components/Pickers/TimePicker.component-test.tsx/plasma-ui TimePicker update value -- with single item.snap.png b/cypress/snapshots/ui/components/Pickers/TimePicker.component-test.tsx/plasma-ui TimePicker update value -- with single item.snap.png
new file mode 100644
index 000000000..61c6dad77
Binary files /dev/null and b/cypress/snapshots/ui/components/Pickers/TimePicker.component-test.tsx/plasma-ui TimePicker update value -- with single item.snap.png differ
diff --git a/packages/plasma-ui/src/components/Pickers/DatePicker.component-test.tsx b/packages/plasma-ui/src/components/Pickers/DatePicker.component-test.tsx
index 4bf27ba49..225f020f0 100644
--- a/packages/plasma-ui/src/components/Pickers/DatePicker.component-test.tsx
+++ b/packages/plasma-ui/src/components/Pickers/DatePicker.component-test.tsx
@@ -133,4 +133,28 @@ describe('plasma-ui: DatePicker', () => {
cy.wait(100);
cy.matchImageSnapshot();
});
+
+ it('with single item', () => {
+ mount(
+
+ <>
+
+
+ >
+ ,
+ );
+
+ cy.matchImageSnapshot();
+ });
});
diff --git a/packages/plasma-ui/src/components/Pickers/Picker.tsx b/packages/plasma-ui/src/components/Pickers/Picker.tsx
index eb923c24a..11c1b01b5 100644
--- a/packages/plasma-ui/src/components/Pickers/Picker.tsx
+++ b/packages/plasma-ui/src/components/Pickers/Picker.tsx
@@ -120,6 +120,7 @@ interface StyledWrapperProps {
$size: PickerSize;
$disabled?: boolean;
$controls?: boolean;
+ $isSingleItem?: boolean;
}
const StyledWrapper = styled.div`
position: relative;
@@ -158,6 +159,14 @@ const StyledWrapper = styled.div`
padding-top: 1.25rem;
padding-bottom: 1.25rem;
`}
+
+ ${({ $isSingleItem }) =>
+ $isSingleItem &&
+ css`
+ ${StyledCarousel} {
+ overflow: hidden;
+ }
+ `}
`;
// Значение, отвечающее за количество элементов,
@@ -176,7 +185,16 @@ function getAllIndices(items: PickerItemType[], value: string | number | Date) {
return res;
}
-const findItemIndex = (items: PickerItemType[], value: string | number | Date, infiniteScroll: boolean) => {
+const findItemIndex = (
+ items: PickerItemType[],
+ value: string | number | Date,
+ infiniteScroll: boolean,
+ isSingleItem: boolean,
+) => {
+ if (infiniteScroll && isSingleItem) {
+ return Math.floor(items.length / 2);
+ }
+
if (infiniteScroll) {
const middleIndex = 1;
return getAllIndices(items, value)[middleIndex];
@@ -209,7 +227,16 @@ const getIndex = (index: number, cmd: GetIndexCmd, min: number, max: number, inf
}
};
-const getItems = (items: PickerItemType[], infiniteScroll: boolean) => {
+const getItems = (
+ items: PickerItemType[],
+ infiniteScroll: boolean,
+ visibleItems: PickerVisibleItems,
+ isSingleItem: boolean,
+) => {
+ if (infiniteScroll && isSingleItem) {
+ return new Array(visibleItems).fill(items[0]);
+ }
+
if (infiniteScroll) {
const virtualItems = items.map((item) => ({ ...item, isVirtual: true }));
return [...virtualItems, ...items, ...virtualItems];
@@ -288,34 +315,36 @@ export const Picker: FC = ({
'aria-label': ariaLabel,
...rest
}) => {
+ const isSingleItem = items.length === 1;
+ const min = 0;
+ const max = items.length - 1;
+
const theme = useContext(ThemeContext);
// by default 'true' on high perfomance devices
- const infiniteScroll = rest.infiniteScroll ?? !theme.lowPerformance;
-
- const virtualItems = useMemo(() => getItems(items, infiniteScroll), [items, infiniteScroll]);
+ const infiniteScroll = rest.infiniteScroll ?? !theme?.lowPerformance;
- const min = 0;
- const max = items.length - 1;
+ const virtualItems = useMemo(() => getItems(items, infiniteScroll, visibleItems, isSingleItem), [
+ items,
+ infiniteScroll,
+ visibleItems,
+ isSingleItem,
+ ]);
const isFirstRender = useFirstRender();
const [isFocused, setIsFocused] = useState(false);
- const [index, setIndex] = useState(findItemIndex(virtualItems, value, infiniteScroll));
+ const [index, setIndex] = useState(findItemIndex(virtualItems, value, infiniteScroll, isSingleItem));
const [hasScrollAnim, setScrollAnim] = useState(true);
const wrapperRef = useRef(null);
const carouselRef = useRef(null);
- const toPrev = useCallback(() => !disabled && setIndex(getIndex(index, '-', min, max, infiniteScroll)), [
- index,
- min,
- max,
- infiniteScroll,
- ]);
- const toNext = useCallback(() => !disabled && setIndex(getIndex(index, '+', min, max, infiniteScroll)), [
- index,
- min,
- max,
- infiniteScroll,
- ]);
+ const toPrev = useCallback(
+ () => !isSingleItem && !disabled && setIndex(getIndex(index, '-', min, max, infiniteScroll)),
+ [isSingleItem, index, min, max, infiniteScroll],
+ );
+ const toNext = useCallback(
+ () => !isSingleItem && !disabled && setIndex(getIndex(index, '+', min, max, infiniteScroll)),
+ [isSingleItem, index, min, max, infiniteScroll],
+ );
const jump = useCallback(
(cmd: GetIndexCmd) => {
if (disabled) {
@@ -340,7 +369,7 @@ export const Picker: FC = ({
// Изменяет индекс выделенного элемента
// при обновлении значения value извне
useIsomorphicLayoutEffect(() => {
- const newIndex = findItemIndex(virtualItems, value, infiniteScroll);
+ const newIndex = findItemIndex(virtualItems, value, infiniteScroll, isSingleItem);
// Отключаем анимацию скролла, если значение компонента осталось
// прежним, но индекс изменился
@@ -360,7 +389,7 @@ export const Picker: FC = ({
}
setIndex(newIndex);
- }, [value, virtualItems, infiniteScroll, max]);
+ }, [value, virtualItems, infiniteScroll, max, isSingleItem]);
// Навигация с помощью пульта/клавиатуры
// Не перелистывает, если компонент неактивен
@@ -412,19 +441,19 @@ export const Picker: FC = ({
if (prevValue === virtualItems[i]?.value) {
setScrollAnim(false);
setIndex(i);
- const newIndex = findItemIndex(virtualItems, virtualItems[i].value, infiniteScroll);
+ const newIndex = findItemIndex(virtualItems, virtualItems[i].value, infiniteScroll, isSingleItem);
setIndex(newIndex);
}
// Включаем анимацию скролла, после изменения индекса
setScrollAnim(true);
},
- [virtualItems, infiniteScroll, value, onChange, prevValue],
+ [virtualItems, infiniteScroll, value, onChange, prevValue, isSingleItem],
);
const onDetectActiveItem = useCallback(
(i: number) => {
- if (!infiniteScroll || (!isTopPosition(i) && !isBottomPosition(i, virtualItems.length))) {
+ if (isSingleItem || !infiniteScroll || (!isTopPosition(i) && !isBottomPosition(i, virtualItems.length))) {
return;
}
@@ -443,7 +472,7 @@ export const Picker: FC = ({
setIndex(i - (max - min) - 1);
}
},
- [virtualItems, infiniteScroll, max, min, index],
+ [virtualItems, infiniteScroll, max, min, index, isSingleItem],
);
return (
@@ -453,6 +482,7 @@ export const Picker: FC = ({
$size={size}
$disabled={disabled}
$visibleItems={visibleItems}
+ $isSingleItem={isSingleItem}
$controls={controls}
onFocus={onFocus}
onBlur={onBlur}
diff --git a/packages/plasma-ui/src/components/Pickers/TimePicker.component-test.tsx b/packages/plasma-ui/src/components/Pickers/TimePicker.component-test.tsx
index f80498e44..c63d0557e 100644
--- a/packages/plasma-ui/src/components/Pickers/TimePicker.component-test.tsx
+++ b/packages/plasma-ui/src/components/Pickers/TimePicker.component-test.tsx
@@ -185,4 +185,28 @@ describe('plasma-ui: TimePicker update value', () => {
cy.matchImageSnapshot();
});
+
+ it('with single item', () => {
+ mount(
+
+ <>
+
+
+ >
+ ,
+ );
+
+ cy.matchImageSnapshot();
+ });
});