Widget: Allow resizing from all corners and sides (#15680)
https://github.com/user-attachments/assets/3e4e1da2-87e6-440e-8371-835ef6eccf59
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import { PageLayoutGridLayoutDragSelector } from '@/page-layout/components/PageLayoutGridLayoutDragSelector';
|
||||
import { PageLayoutGridOverlay } from '@/page-layout/components/PageLayoutGridOverlay';
|
||||
import { PageLayoutGridResizeHandle } from '@/page-layout/components/PageLayoutGridResizeHandle';
|
||||
import { ReactGridLayoutCardWrapper } from '@/page-layout/components/ReactGridLayoutCardWrapper';
|
||||
import { EMPTY_LAYOUT } from '@/page-layout/constants/EmptyLayout';
|
||||
import {
|
||||
PAGE_LAYOUT_CONFIG,
|
||||
@@ -13,6 +14,7 @@ import { pageLayoutCurrentBreakpointComponentState } from '@/page-layout/states/
|
||||
import { pageLayoutCurrentLayoutsComponentState } from '@/page-layout/states/pageLayoutCurrentLayoutsComponentState';
|
||||
import { pageLayoutDraggedAreaComponentState } from '@/page-layout/states/pageLayoutDraggedAreaComponentState';
|
||||
import { pageLayoutDraggingWidgetIdComponentState } from '@/page-layout/states/pageLayoutDraggingWidgetIdComponentState';
|
||||
import { pageLayoutResizingWidgetIdComponentState } from '@/page-layout/states/pageLayoutResizingWidgetIdComponentState';
|
||||
import { addPendingPlaceholderToLayouts } from '@/page-layout/utils/addPendingPlaceholderToLayouts';
|
||||
import { filterPendingPlaceholderFromLayouts } from '@/page-layout/utils/filterPendingPlaceholderFromLayouts';
|
||||
import { prepareGridLayoutItemsWithPlaceholders } from '@/page-layout/utils/prepareGridLayoutItemsWithPlaceholders';
|
||||
@@ -78,6 +80,10 @@ export const PageLayoutGridLayout = ({ tabId }: PageLayoutGridLayoutProps) => {
|
||||
pageLayoutDraggingWidgetIdComponentState,
|
||||
);
|
||||
|
||||
const setResizingWidgetId = useSetRecoilComponentState(
|
||||
pageLayoutResizingWidgetIdComponentState,
|
||||
);
|
||||
|
||||
const { handleLayoutChange } = usePageLayoutHandleLayoutChange();
|
||||
|
||||
const handleLayoutChangeWithoutPendingPlaceholder = (
|
||||
@@ -165,13 +171,19 @@ export const PageLayoutGridLayout = ({ tabId }: PageLayoutGridLayoutProps) => {
|
||||
resizeHandle={
|
||||
isPageLayoutInEditMode ? <PageLayoutGridResizeHandle /> : undefined
|
||||
}
|
||||
resizeHandles={['se']}
|
||||
resizeHandles={['n', 's', 'e', 'w', 'ne', 'nw', 'se', 'sw']}
|
||||
onDragStart={(_layout, _oldItem, newItem) => {
|
||||
setDraggingWidgetId(newItem.i);
|
||||
}}
|
||||
onDragStop={() => {
|
||||
setDraggingWidgetId(null);
|
||||
}}
|
||||
onResizeStart={(_layout, _oldItem, newItem) => {
|
||||
setResizingWidgetId(newItem.i);
|
||||
}}
|
||||
onResizeStop={() => {
|
||||
setResizingWidgetId(null);
|
||||
}}
|
||||
onLayoutChange={handleLayoutChangeWithoutPendingPlaceholder}
|
||||
onBreakpointChange={(newBreakpoint) =>
|
||||
setPageLayoutCurrentBreakpoint(
|
||||
@@ -180,13 +192,13 @@ export const PageLayoutGridLayout = ({ tabId }: PageLayoutGridLayoutProps) => {
|
||||
}
|
||||
>
|
||||
{gridLayoutItems.map((item) => (
|
||||
<div key={item.id} data-select-disable="true">
|
||||
<ReactGridLayoutCardWrapper key={item.id}>
|
||||
{item.type === 'placeholder' ? (
|
||||
<WidgetPlaceholder />
|
||||
) : (
|
||||
<WidgetRenderer widget={item.widget} />
|
||||
)}
|
||||
</div>
|
||||
</ReactGridLayoutCardWrapper>
|
||||
))}
|
||||
</ResponsiveGridLayout>
|
||||
</StyledGridContainer>
|
||||
|
||||
+216
-38
@@ -1,10 +1,19 @@
|
||||
import { useTheme } from '@emotion/react';
|
||||
import { css, useTheme } from '@emotion/react';
|
||||
import styled from '@emotion/styled';
|
||||
import { forwardRef } from 'react';
|
||||
import { IconRadiusBottomRight } from 'twenty-ui/display';
|
||||
import {
|
||||
IconRadiusBottomLeft,
|
||||
IconRadiusBottomRight,
|
||||
IconRadiusTopLeft,
|
||||
IconRadiusTopRight,
|
||||
} from 'twenty-ui/display';
|
||||
|
||||
type WidgetHandleAxis = 'n' | 's' | 'e' | 'w' | 'ne' | 'nw' | 'se' | 'sw';
|
||||
type WidgetHorizontalHandleAxis = 'n' | 's';
|
||||
type WidgetVerticalHandleAxis = 'e' | 'w';
|
||||
|
||||
type PageLayoutGridResizeHandleProps = {
|
||||
handleAxis?: string;
|
||||
handleAxis?: WidgetHandleAxis;
|
||||
onMouseDown?: React.MouseEventHandler<HTMLDivElement>;
|
||||
onMouseUp?: React.MouseEventHandler<HTMLDivElement>;
|
||||
onTouchEnd?: React.TouchEventHandler<HTMLDivElement>;
|
||||
@@ -12,49 +21,218 @@ type PageLayoutGridResizeHandleProps = {
|
||||
style?: React.CSSProperties;
|
||||
};
|
||||
|
||||
const StyledIcon = styled(IconRadiusBottomRight)`
|
||||
bottom: ${({ theme }) => theme.spacing(1)};
|
||||
const StyledBottomRightIcon = styled(IconRadiusBottomRight)`
|
||||
color: transparent;
|
||||
cursor: nwse-resize;
|
||||
position: absolute;
|
||||
right: ${({ theme }) => theme.spacing(1)};
|
||||
color: ${({ theme }) => theme.border.color.strong};
|
||||
display: none;
|
||||
|
||||
:hover {
|
||||
color: ${({ theme }) => theme.font.color.tertiary};
|
||||
}
|
||||
`;
|
||||
|
||||
const StyledBottomLeftIcon = styled(IconRadiusBottomLeft)`
|
||||
color: transparent;
|
||||
cursor: nesw-resize;
|
||||
|
||||
:hover {
|
||||
color: ${({ theme }) => theme.font.color.tertiary};
|
||||
}
|
||||
`;
|
||||
|
||||
const StyledTopLeftIcon = styled(IconRadiusTopLeft)`
|
||||
color: transparent;
|
||||
cursor: nwse-resize;
|
||||
|
||||
:hover {
|
||||
color: ${({ theme }) => theme.font.color.tertiary};
|
||||
}
|
||||
`;
|
||||
|
||||
const StyledTopRightIcon = styled(IconRadiusTopRight)`
|
||||
color: transparent;
|
||||
cursor: nesw-resize;
|
||||
|
||||
:hover {
|
||||
color: ${({ theme }) => theme.font.color.tertiary};
|
||||
}
|
||||
`;
|
||||
|
||||
const StyledVerticalHandle = styled.div`
|
||||
border-radius: ${({ theme }) => theme.border.radius.sm};
|
||||
height: ${({ theme }) => theme.spacing(5)};
|
||||
width: ${({ theme }) => theme.icon.stroke.lg}px;
|
||||
`;
|
||||
|
||||
const StyledHorizontalHandle = styled.div`
|
||||
border-radius: ${({ theme }) => theme.border.radius.sm};
|
||||
height: ${({ theme }) => theme.icon.stroke.lg}px;
|
||||
width: ${({ theme }) => theme.spacing(5)};
|
||||
`;
|
||||
|
||||
const StyledHorizontalHandleWrapper = styled.div<{
|
||||
widgetHandleAxis: WidgetHorizontalHandleAxis;
|
||||
}>`
|
||||
border-radius: ${({ theme }) => theme.border.radius.sm};
|
||||
cursor: row-resize;
|
||||
transform: ${({ widgetHandleAxis }) =>
|
||||
widgetHandleAxis === 'n' ? 'translateY(-50%)' : 'translateY(50%)'};
|
||||
padding: ${({ theme }) => theme.spacing(2)} ${({ theme }) => theme.spacing(2)};
|
||||
|
||||
:hover {
|
||||
& > div {
|
||||
background-color: ${({ theme }) => theme.font.color.tertiary};
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const StyledVerticalHandleWrapper = styled.div<{
|
||||
widgetHandleAxis: WidgetVerticalHandleAxis;
|
||||
}>`
|
||||
cursor: col-resize;
|
||||
border-radius: ${({ theme }) => theme.border.radius.sm};
|
||||
transform: ${({ widgetHandleAxis }) =>
|
||||
widgetHandleAxis === 'w' ? 'translateX(-50%)' : 'translateX(50%)'};
|
||||
padding: ${({ theme }) => theme.spacing(2)} ${({ theme }) => theme.spacing(2)};
|
||||
|
||||
:hover {
|
||||
& > div {
|
||||
background-color: ${({ theme }) => theme.font.color.tertiary};
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const StyledResizeHandleWrapper = styled.div<{
|
||||
widgetHandleAxis?: WidgetHandleAxis;
|
||||
}>`
|
||||
position: absolute;
|
||||
${({ theme, widgetHandleAxis }) => {
|
||||
if (widgetHandleAxis === 'w') {
|
||||
return css`
|
||||
left: ${theme.spacing(2)};
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
`;
|
||||
}
|
||||
if (widgetHandleAxis === 'e') {
|
||||
return css`
|
||||
right: ${theme.spacing(2)};
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
`;
|
||||
}
|
||||
if (widgetHandleAxis === 'n') {
|
||||
return css`
|
||||
top: ${theme.spacing(2)};
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
`;
|
||||
}
|
||||
if (widgetHandleAxis === 's') {
|
||||
return css`
|
||||
bottom: ${theme.spacing(2)};
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
`;
|
||||
}
|
||||
if (widgetHandleAxis === 'se') {
|
||||
return css`
|
||||
bottom: ${theme.spacing(0.5)};
|
||||
right: ${theme.spacing(0.5)};
|
||||
`;
|
||||
}
|
||||
if (widgetHandleAxis === 'sw') {
|
||||
return css`
|
||||
bottom: ${theme.spacing(0.5)};
|
||||
left: ${theme.spacing(0.5)};
|
||||
`;
|
||||
}
|
||||
if (widgetHandleAxis === 'ne') {
|
||||
return css`
|
||||
right: ${theme.spacing(0.5)};
|
||||
top: ${theme.spacing(0.5)};
|
||||
`;
|
||||
}
|
||||
if (widgetHandleAxis === 'nw') {
|
||||
return css`
|
||||
left: ${theme.spacing(0.5)};
|
||||
top: ${theme.spacing(0.5)};
|
||||
`;
|
||||
}
|
||||
}}
|
||||
`;
|
||||
|
||||
const isVerticalHandle = (
|
||||
widgetHandleAxis?: WidgetHandleAxis,
|
||||
): widgetHandleAxis is WidgetVerticalHandleAxis =>
|
||||
widgetHandleAxis === 'w' || widgetHandleAxis === 'e';
|
||||
|
||||
const isHorizontalHandle = (
|
||||
widgetHandleAxis?: WidgetHandleAxis,
|
||||
): widgetHandleAxis is WidgetHorizontalHandleAxis =>
|
||||
widgetHandleAxis === 'n' || widgetHandleAxis === 's';
|
||||
|
||||
export const PageLayoutGridResizeHandle = forwardRef<
|
||||
HTMLDivElement,
|
||||
PageLayoutGridResizeHandleProps
|
||||
>((props, ref) => {
|
||||
const theme = useTheme();
|
||||
const {
|
||||
handleAxis = 'se',
|
||||
onMouseDown,
|
||||
onMouseUp,
|
||||
onTouchEnd,
|
||||
className,
|
||||
style,
|
||||
} = props;
|
||||
>(
|
||||
(
|
||||
{
|
||||
handleAxis: widgetHandleAxis,
|
||||
onMouseDown,
|
||||
onMouseUp,
|
||||
onTouchEnd,
|
||||
className,
|
||||
style,
|
||||
},
|
||||
ref,
|
||||
) => {
|
||||
const theme = useTheme();
|
||||
|
||||
if (handleAxis !== 'se') return null;
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={ref}
|
||||
onMouseDown={onMouseDown}
|
||||
onMouseUp={onMouseUp}
|
||||
onTouchEnd={onTouchEnd}
|
||||
className={className}
|
||||
style={style}
|
||||
>
|
||||
<StyledIcon
|
||||
size={theme.spacing(4)}
|
||||
stroke={theme.spacing(1)}
|
||||
className="widget-card-resize-handle"
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
});
|
||||
return (
|
||||
<StyledResizeHandleWrapper
|
||||
ref={ref}
|
||||
onMouseDown={onMouseDown}
|
||||
onMouseUp={onMouseUp}
|
||||
onTouchEnd={onTouchEnd}
|
||||
className={className}
|
||||
style={style}
|
||||
widgetHandleAxis={widgetHandleAxis}
|
||||
>
|
||||
{isVerticalHandle(widgetHandleAxis) && (
|
||||
<StyledVerticalHandleWrapper widgetHandleAxis={widgetHandleAxis}>
|
||||
<StyledVerticalHandle />
|
||||
</StyledVerticalHandleWrapper>
|
||||
)}
|
||||
{isHorizontalHandle(widgetHandleAxis) && (
|
||||
<StyledHorizontalHandleWrapper widgetHandleAxis={widgetHandleAxis}>
|
||||
<StyledHorizontalHandle />
|
||||
</StyledHorizontalHandleWrapper>
|
||||
)}
|
||||
{widgetHandleAxis === 'ne' && (
|
||||
<StyledTopRightIcon
|
||||
size={theme.icon.size.lg}
|
||||
stroke={theme.icon.stroke.lg}
|
||||
/>
|
||||
)}
|
||||
{widgetHandleAxis === 'nw' && (
|
||||
<StyledTopLeftIcon
|
||||
size={theme.icon.size.lg}
|
||||
stroke={theme.icon.stroke.lg}
|
||||
/>
|
||||
)}
|
||||
{widgetHandleAxis === 'se' && (
|
||||
<StyledBottomRightIcon
|
||||
size={theme.icon.size.lg}
|
||||
stroke={theme.icon.stroke.lg}
|
||||
/>
|
||||
)}
|
||||
{widgetHandleAxis === 'sw' && (
|
||||
<StyledBottomLeftIcon
|
||||
size={theme.icon.size.lg}
|
||||
stroke={theme.icon.stroke.lg}
|
||||
/>
|
||||
)}
|
||||
</StyledResizeHandleWrapper>
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
import { forwardRef } from 'react';
|
||||
|
||||
export const ReactGridLayoutCardWrapper = forwardRef<
|
||||
HTMLDivElement,
|
||||
{
|
||||
key: string;
|
||||
children: React.ReactNode;
|
||||
style?: React.CSSProperties;
|
||||
className?: string;
|
||||
onMouseDown?: React.MouseEventHandler<HTMLDivElement>;
|
||||
onMouseUp?: React.MouseEventHandler<HTMLDivElement>;
|
||||
onMouseMove?: React.MouseEventHandler<HTMLDivElement>;
|
||||
}
|
||||
>(
|
||||
(
|
||||
{ children, key, className, style, onMouseDown, onMouseUp, onMouseMove },
|
||||
ref,
|
||||
) => {
|
||||
return (
|
||||
<div
|
||||
ref={ref}
|
||||
key={key}
|
||||
data-select-disable="true"
|
||||
className={className}
|
||||
style={style}
|
||||
onMouseDown={onMouseDown}
|
||||
onMouseUp={onMouseUp}
|
||||
onMouseMove={onMouseMove}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
},
|
||||
);
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState';
|
||||
|
||||
import { PageLayoutComponentInstanceContext } from './contexts/PageLayoutComponentInstanceContext';
|
||||
|
||||
export const pageLayoutResizingWidgetIdComponentState = createComponentState<
|
||||
string | null
|
||||
>({
|
||||
key: 'pageLayoutResizingWidgetIdComponentState',
|
||||
defaultValue: null,
|
||||
componentInstanceContext: PageLayoutComponentInstanceContext,
|
||||
});
|
||||
@@ -60,6 +60,7 @@ export const WidgetPlaceholder = () => {
|
||||
<WidgetCardHeader
|
||||
isWidgetCardHovered={false}
|
||||
isInEditMode={isPageLayoutInEditMode}
|
||||
isResizing={false}
|
||||
title={t`Add Widget`}
|
||||
isEmpty
|
||||
/>
|
||||
|
||||
+10
-1
@@ -5,6 +5,7 @@ import { useEditPageLayoutWidget } from '@/page-layout/hooks/useEditPageLayoutWi
|
||||
import { isPageLayoutInEditModeComponentState } from '@/page-layout/states/isPageLayoutInEditModeComponentState';
|
||||
import { pageLayoutDraggingWidgetIdComponentState } from '@/page-layout/states/pageLayoutDraggingWidgetIdComponentState';
|
||||
import { pageLayoutEditingWidgetIdComponentState } from '@/page-layout/states/pageLayoutEditingWidgetIdComponentState';
|
||||
import { pageLayoutResizingWidgetIdComponentState } from '@/page-layout/states/pageLayoutResizingWidgetIdComponentState';
|
||||
import { PageLayoutWidgetForbiddenDisplay } from '@/page-layout/widgets/components/PageLayoutWidgetForbiddenDisplay';
|
||||
import { WidgetContentRenderer } from '@/page-layout/widgets/components/WidgetContentRenderer';
|
||||
import { useIsInPinnedTab } from '@/page-layout/widgets/hooks/useIsInPinnedTab';
|
||||
@@ -35,6 +36,10 @@ export const WidgetRenderer = ({ widget }: WidgetRendererProps) => {
|
||||
pageLayoutDraggingWidgetIdComponentState,
|
||||
);
|
||||
|
||||
const resizingWidgetId = useRecoilComponentValue(
|
||||
pageLayoutResizingWidgetIdComponentState,
|
||||
);
|
||||
|
||||
const currentlyEditingWidgetId = useRecoilComponentValue(
|
||||
pageLayoutEditingWidgetIdComponentState,
|
||||
);
|
||||
@@ -43,6 +48,8 @@ export const WidgetRenderer = ({ widget }: WidgetRendererProps) => {
|
||||
|
||||
const isDragging = draggingWidgetId === widget.id;
|
||||
|
||||
const isResizing = resizingWidgetId === widget.id;
|
||||
|
||||
const { hasAccess, restriction } = useWidgetPermissions(widget);
|
||||
|
||||
const { layoutMode } = usePageLayoutContentContext();
|
||||
@@ -76,9 +83,10 @@ export const WidgetRenderer = ({ widget }: WidgetRendererProps) => {
|
||||
|
||||
return (
|
||||
<WidgetCard
|
||||
isEditing={isEditing}
|
||||
isDragging={isDragging}
|
||||
isResizing={isResizing}
|
||||
layoutMode={layoutMode}
|
||||
isEditing={isEditing}
|
||||
pageLayoutType={currentPageLayout.type}
|
||||
isInPinnedTab={isInPinnedTab}
|
||||
onClick={isPageLayoutInEditMode ? handleClick : undefined}
|
||||
@@ -89,6 +97,7 @@ export const WidgetRenderer = ({ widget }: WidgetRendererProps) => {
|
||||
<WidgetCardHeader
|
||||
isWidgetCardHovered={isHovered}
|
||||
isInEditMode={isPageLayoutInEditMode}
|
||||
isResizing={isResizing}
|
||||
title={widget.title}
|
||||
onRemove={handleRemove}
|
||||
forbiddenDisplay={
|
||||
|
||||
+8
-1
@@ -15,6 +15,7 @@ export type WidgetCardProps = {
|
||||
isEditing: boolean;
|
||||
isDragging: boolean;
|
||||
isInPinnedTab: boolean;
|
||||
isResizing?: boolean;
|
||||
className?: string;
|
||||
onMouseEnter?: () => void;
|
||||
onMouseLeave?: () => void;
|
||||
@@ -28,13 +29,14 @@ const StyledWidgetCard = styled.div<{
|
||||
isPageLayoutInEditMode: boolean;
|
||||
isEditing: boolean;
|
||||
isDragging: boolean;
|
||||
isResizing: boolean;
|
||||
}>`
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
position: relative;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
position: relative;
|
||||
|
||||
${({
|
||||
theme,
|
||||
@@ -44,6 +46,7 @@ const StyledWidgetCard = styled.div<{
|
||||
isEditing,
|
||||
isDragging,
|
||||
isInPinnedTab,
|
||||
isResizing,
|
||||
onClick,
|
||||
}) => {
|
||||
if (layoutMode === 'canvas') {
|
||||
@@ -64,6 +67,7 @@ const StyledWidgetCard = styled.div<{
|
||||
${isPageLayoutInEditMode &&
|
||||
!isDragging &&
|
||||
!isEditing &&
|
||||
!isResizing &&
|
||||
css`
|
||||
&:hover {
|
||||
border: 1px solid ${theme.border.color.strong};
|
||||
@@ -101,6 +105,7 @@ const StyledWidgetCard = styled.div<{
|
||||
${isPageLayoutInEditMode &&
|
||||
!isDragging &&
|
||||
!isEditing &&
|
||||
!isResizing &&
|
||||
css`
|
||||
&:hover {
|
||||
border: 1px solid ${theme.border.color.strong};
|
||||
@@ -150,6 +155,7 @@ export const WidgetCard = ({
|
||||
isEditing,
|
||||
isDragging,
|
||||
isInPinnedTab,
|
||||
isResizing = false,
|
||||
className,
|
||||
onMouseEnter,
|
||||
onMouseLeave,
|
||||
@@ -167,6 +173,7 @@ export const WidgetCard = ({
|
||||
isEditing={isEditing}
|
||||
isDragging={isDragging}
|
||||
isInPinnedTab={isInPinnedTab}
|
||||
isResizing={isResizing}
|
||||
className={className}
|
||||
onMouseEnter={onMouseEnter}
|
||||
onMouseLeave={onMouseLeave}
|
||||
|
||||
+24
-18
@@ -17,6 +17,7 @@ export type WidgetCardHeaderProps = {
|
||||
onRemove?: (e?: React.MouseEvent) => void;
|
||||
forbiddenDisplay?: ReactNode;
|
||||
className?: string;
|
||||
isResizing?: boolean;
|
||||
};
|
||||
|
||||
const StyledWidgetCardHeader = styled.div`
|
||||
@@ -52,6 +53,7 @@ export const WidgetCardHeader = ({
|
||||
isWidgetCardHovered = false,
|
||||
isEmpty = false,
|
||||
isInEditMode = false,
|
||||
isResizing = false,
|
||||
title,
|
||||
onRemove,
|
||||
forbiddenDisplay,
|
||||
@@ -75,24 +77,28 @@ export const WidgetCardHeader = ({
|
||||
<StyledRightContainer>
|
||||
{isDefined(forbiddenDisplay) && forbiddenDisplay}
|
||||
<AnimatePresence>
|
||||
{!isEmpty && isInEditMode && onRemove && isWidgetCardHovered && (
|
||||
<StyledIconButtonContainer
|
||||
initial={{ width: 0, opacity: 0 }}
|
||||
animate={{ width: 'auto', opacity: 1 }}
|
||||
exit={{ width: 0, opacity: 0 }}
|
||||
transition={{
|
||||
duration: theme.animation.duration.fast,
|
||||
ease: 'easeInOut',
|
||||
}}
|
||||
>
|
||||
<IconButton
|
||||
onClick={onRemove}
|
||||
Icon={IconTrash}
|
||||
variant="tertiary"
|
||||
size="small"
|
||||
/>
|
||||
</StyledIconButtonContainer>
|
||||
)}
|
||||
{!isResizing &&
|
||||
!isEmpty &&
|
||||
isInEditMode &&
|
||||
onRemove &&
|
||||
isWidgetCardHovered && (
|
||||
<StyledIconButtonContainer
|
||||
initial={{ width: 0, opacity: 0 }}
|
||||
animate={{ width: 'auto', opacity: 1 }}
|
||||
exit={{ width: 0, opacity: 0 }}
|
||||
transition={{
|
||||
duration: theme.animation.duration.fast,
|
||||
ease: 'easeInOut',
|
||||
}}
|
||||
>
|
||||
<IconButton
|
||||
onClick={onRemove}
|
||||
Icon={IconTrash}
|
||||
variant="tertiary"
|
||||
size="small"
|
||||
/>
|
||||
</StyledIconButtonContainer>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
</StyledRightContainer>
|
||||
</StyledWidgetCardHeader>
|
||||
|
||||
@@ -278,7 +278,10 @@ export {
|
||||
IconPuzzle,
|
||||
IconPuzzle2,
|
||||
IconQuestionMark,
|
||||
IconRadiusBottomLeft,
|
||||
IconRadiusBottomRight,
|
||||
IconRadiusTopLeft,
|
||||
IconRadiusTopRight,
|
||||
IconRefresh,
|
||||
IconRefreshAlert,
|
||||
IconRefreshDot,
|
||||
|
||||
@@ -2839,7 +2839,6 @@ import {
|
||||
IconMilkshake,
|
||||
IconMinimize,
|
||||
IconMinus,
|
||||
IconMinusVertical,
|
||||
IconMist,
|
||||
IconMistOff,
|
||||
IconMobiledata,
|
||||
@@ -7023,7 +7022,6 @@ export const ALL_ICONS = {
|
||||
IconMilkshake,
|
||||
IconMinimize,
|
||||
IconMinus,
|
||||
IconMinusVertical,
|
||||
IconMist,
|
||||
IconMistOff,
|
||||
IconMobiledata,
|
||||
|
||||
@@ -343,7 +343,10 @@ export {
|
||||
IconPuzzle,
|
||||
IconPuzzle2,
|
||||
IconQuestionMark,
|
||||
IconRadiusBottomLeft,
|
||||
IconRadiusBottomRight,
|
||||
IconRadiusTopLeft,
|
||||
IconRadiusTopRight,
|
||||
IconRefresh,
|
||||
IconRefreshAlert,
|
||||
IconRefreshDot,
|
||||
|
||||
Reference in New Issue
Block a user