fix(ui): Apple Pencil requires onPointerUp instead of onClick

With `onClick`, elements w/ a tooltip require a double-tap.
This commit is contained in:
psychedelicious
2024-10-04 13:13:22 +10:00
committed by Kent Keirsey
parent af5f342347
commit 2a90f4f59e
208 changed files with 412 additions and 412 deletions

View File

@@ -65,10 +65,10 @@ const AppErrorBoundaryFallback = ({ error, resetErrorBoundary }: Props) => {
</Text>
</Flex>
<Flex gap={4}>
<Button leftIcon={<PiArrowCounterClockwiseBold />} onClick={resetErrorBoundary}>
<Button leftIcon={<PiArrowCounterClockwiseBold />} onPointerUp={resetErrorBoundary}>
{t('accessibility.resetUI')}
</Button>
<Button leftIcon={<PiCopyBold />} onClick={handleCopy}>
<Button leftIcon={<PiCopyBold />} onPointerUp={handleCopy}>
{t('common.copyError')}
</Button>
<Link href={url} isExternal>

View File

@@ -98,8 +98,8 @@ const RgbColorPicker = (props: Props) => {
export default memo(RgbColorPicker);
const ColorSwatch = ({ color, onChange }: { color: RgbColor; onChange: (color: RgbColor) => void }) => {
const onClick = useCallback(() => {
const onPointerUp = useCallback(() => {
onChange(color);
}, [color, onChange]);
return <Box role="button" onClick={onClick} h={8} w={8} bg={rgbColorToString(color)} borderRadius="base" />;
return <Box role="button" onPointerUp={onPointerUp} h={8} w={8} bg={rgbColorToString(color)} borderRadius="base" />;
};

View File

@@ -109,8 +109,8 @@ const RgbaColorPicker = (props: Props) => {
export default memo(RgbaColorPicker);
const ColorSwatch = ({ color, onChange }: { color: RgbaColor; onChange: (color: RgbaColor) => void }) => {
const onClick = useCallback(() => {
const onPointerUp = useCallback(() => {
onChange(color);
}, [color, onChange]);
return <Box role="button" onClick={onClick} h={8} w={8} bg={rgbaColorToString(color)} borderRadius="base" />;
return <Box role="button" onPointerUp={onPointerUp} h={8} w={8} bg={rgbaColorToString(color)} borderRadius="base" />;
};

View File

@@ -55,7 +55,7 @@ type IAIDndImageProps = FlexProps & {
imageDTO: ImageDTO | undefined;
onError?: (event: SyntheticEvent<HTMLImageElement>) => void;
onLoad?: (event: SyntheticEvent<HTMLImageElement>) => void;
onClick?: (event: MouseEvent<HTMLDivElement>) => void;
onPointerUp?: (event: MouseEvent<HTMLDivElement>) => void;
withMetadataOverlay?: boolean;
isDragDisabled?: boolean;
isDropDisabled?: boolean;
@@ -82,7 +82,7 @@ const IAIDndImage = (props: IAIDndImageProps) => {
const {
imageDTO,
onError,
onClick,
onPointerUp,
withMetadataOverlay = false,
isDropDisabled = false,
isDragDisabled = false,
@@ -228,7 +228,7 @@ const IAIDndImage = (props: IAIDndImageProps) => {
<IAIDraggable
data={draggableData}
disabled={isDragDisabled || !imageDTO}
onClick={onClick}
onPointerUp={onPointerUp}
onAuxClick={openInNewTab}
/>
)}

View File

@@ -16,17 +16,17 @@ const sx: SystemStyleObject = {
},
};
type Props = Omit<IconButtonProps, 'aria-label' | 'onClick' | 'tooltip'> & {
onClick: (event: MouseEvent<HTMLButtonElement>) => void;
type Props = Omit<IconButtonProps, 'aria-label' | 'onPointerUp' | 'tooltip'> & {
onPointerUp: (event: MouseEvent<HTMLButtonElement>) => void;
tooltip: string;
};
const IAIDndImageIcon = (props: Props) => {
const { onClick, tooltip, icon, ...rest } = props;
const { onPointerUp, tooltip, icon, ...rest } = props;
return (
<IconButton
onClick={onClick}
onPointerUp={onPointerUp}
aria-label={tooltip}
icon={icon}
variant="link"

View File

@@ -95,14 +95,14 @@ const Content = ({ data, feature, hideDisable }: ContentProps) => {
[feature, t]
);
const onClickLearnMore = useCallback(() => {
const onPointerUpLearnMore = useCallback(() => {
if (!data?.href) {
return;
}
window.open(data.href);
}, [data?.href]);
const onClickDontShowMeThese = useCallback(() => {
const onPointerUpDontShowMeThese = useCallback(() => {
dispatch(setShouldEnableInformationalPopovers(false));
toast({
title: t('settings.informationalPopoversDisabled'),
@@ -135,13 +135,13 @@ const Content = ({ data, feature, hideDisable }: ContentProps) => {
<Divider />
<Flex alignItems="center" justifyContent="space-between" w="full">
{!hideDisable && (
<Button onClick={onClickDontShowMeThese} variant="link" size="sm">
<Button onPointerUp={onPointerUpDontShowMeThese} variant="link" size="sm">
{t('common.dontShowMeThese')}
</Button>
)}
<Spacer />
{data?.href && (
<Button onClick={onClickLearnMore} leftIcon={<PiArrowSquareOutBold />} variant="link" size="sm">
<Button onPointerUp={onPointerUpLearnMore} leftIcon={<PiArrowSquareOutBold />} variant="link" size="sm">
{t('common.learnMore') ?? heading}
</Button>
)}

View File

@@ -33,7 +33,7 @@ export const CanvasAddEntityButtons = memo(() => {
variant="ghost"
justifyContent="flex-start"
leftIcon={<PiPlusBold />}
onClick={addGlobalReferenceImage}
onPointerUp={addGlobalReferenceImage}
isDisabled={isFLUX}
>
{t('controlLayers.globalReferenceImage')}
@@ -46,7 +46,7 @@ export const CanvasAddEntityButtons = memo(() => {
variant="ghost"
justifyContent="flex-start"
leftIcon={<PiPlusBold />}
onClick={addInpaintMask}
onPointerUp={addInpaintMask}
>
{t('controlLayers.inpaintMask')}
</Button>
@@ -55,7 +55,7 @@ export const CanvasAddEntityButtons = memo(() => {
variant="ghost"
justifyContent="flex-start"
leftIcon={<PiPlusBold />}
onClick={addRegionalGuidance}
onPointerUp={addRegionalGuidance}
isDisabled={isFLUX}
>
{t('controlLayers.regionalGuidance')}
@@ -65,7 +65,7 @@ export const CanvasAddEntityButtons = memo(() => {
variant="ghost"
justifyContent="flex-start"
leftIcon={<PiPlusBold />}
onClick={addRegionalReferenceImage}
onPointerUp={addRegionalReferenceImage}
isDisabled={isFLUX}
>
{t('controlLayers.regionalReferenceImage')}
@@ -79,7 +79,7 @@ export const CanvasAddEntityButtons = memo(() => {
variant="ghost"
justifyContent="flex-start"
leftIcon={<PiPlusBold />}
onClick={addControlLayer}
onPointerUp={addControlLayer}
isDisabled={isFLUX}
>
{t('controlLayers.controlLayer')}
@@ -89,7 +89,7 @@ export const CanvasAddEntityButtons = memo(() => {
variant="ghost"
justifyContent="flex-start"
leftIcon={<PiPlusBold />}
onClick={addRasterLayer}
onPointerUp={addRasterLayer}
>
{t('controlLayers.rasterLayer')}
</Button>

View File

@@ -17,12 +17,12 @@ import { Trans, useTranslation } from 'react-i18next';
const ActivateImageViewerButton = (props: PropsWithChildren) => {
const imageViewer = useImageViewer();
const onClick = useCallback(() => {
const onPointerUp = useCallback(() => {
imageViewer.open();
selectCanvasRightPanelGalleryTab();
}, [imageViewer]);
return (
<Button onClick={onClick} size="sm" variant="link" color="base.50">
<Button onPointerUp={onPointerUp} size="sm" variant="link" color="base.50">
{props.children}
</Button>
);
@@ -58,13 +58,13 @@ export const CanvasAlertsSendingToGallery = () => {
const ActivateCanvasButton = (props: PropsWithChildren) => {
const dispatch = useAppDispatch();
const imageViewer = useImageViewer();
const onClick = useCallback(() => {
const onPointerUp = useCallback(() => {
dispatch(setActiveTab('canvas'));
selectCanvasRightPanelLayersTab();
imageViewer.close();
}, [dispatch, imageViewer]);
return (
<Button onClick={onClick} size="sm" variant="link" color="base.50">
<Button onPointerUp={onPointerUp} size="sm" variant="link" color="base.50">
{props.children}
</Button>
);

View File

@@ -30,24 +30,24 @@ export const CanvasContextMenuGlobalMenuItems = memo(() => {
<CanvasContextMenuItemsCropCanvasToBbox />
</MenuGroup>
<MenuGroup title={t('controlLayers.canvasContextMenu.saveToGalleryGroup')}>
<MenuItem icon={<PiFloppyDiskBold />} isDisabled={isBusy} onClick={saveCanvasToGallery}>
<MenuItem icon={<PiFloppyDiskBold />} isDisabled={isBusy} onPointerUp={saveCanvasToGallery}>
{t('controlLayers.canvasContextMenu.saveCanvasToGallery')}
</MenuItem>
<MenuItem icon={<PiFloppyDiskBold />} isDisabled={isBusy} onClick={saveBboxToGallery}>
<MenuItem icon={<PiFloppyDiskBold />} isDisabled={isBusy} onPointerUp={saveBboxToGallery}>
{t('controlLayers.canvasContextMenu.saveBboxToGallery')}
</MenuItem>
</MenuGroup>
<MenuGroup title={t('controlLayers.canvasContextMenu.bboxGroup')}>
<MenuItem icon={<NewLayerIcon />} isDisabled={isBusy} onClick={newGlobalReferenceImageFromBbox}>
<MenuItem icon={<NewLayerIcon />} isDisabled={isBusy} onPointerUp={newGlobalReferenceImageFromBbox}>
{t('controlLayers.canvasContextMenu.newGlobalReferenceImage')}
</MenuItem>
<MenuItem icon={<NewLayerIcon />} isDisabled={isBusy} onClick={newRegionalReferenceImageFromBbox}>
<MenuItem icon={<NewLayerIcon />} isDisabled={isBusy} onPointerUp={newRegionalReferenceImageFromBbox}>
{t('controlLayers.canvasContextMenu.newRegionalReferenceImage')}
</MenuItem>
<MenuItem icon={<NewLayerIcon />} isDisabled={isBusy} onClick={newControlLayerFromBbox}>
<MenuItem icon={<NewLayerIcon />} isDisabled={isBusy} onPointerUp={newControlLayerFromBbox}>
{t('controlLayers.canvasContextMenu.newControlLayer')}
</MenuItem>
<MenuItem icon={<NewLayerIcon />} isDisabled={isBusy} onClick={newRasterLayerFromBbox}>
<MenuItem icon={<NewLayerIcon />} isDisabled={isBusy} onPointerUp={newRasterLayerFromBbox}>
{t('controlLayers.canvasContextMenu.newRasterLayer')}
</MenuItem>
</MenuGroup>

View File

@@ -17,7 +17,7 @@ export const CanvasContextMenuItemsCropCanvasToBbox = memo(() => {
}, [canvasManager]);
return (
<MenuItem icon={<PiCropBold />} isDisabled={isBusy} onClick={cropCanvasToBbox}>
<MenuItem icon={<PiCropBold />} isDisabled={isBusy} onPointerUp={cropCanvasToBbox}>
{t('controlLayers.canvasContextMenu.cropCanvasToBbox')}
</MenuItem>
);

View File

@@ -40,26 +40,26 @@ export const EntityListGlobalActionBarAddLayerMenu = memo(() => {
/>
<MenuList>
<MenuGroup title={t('controlLayers.global')}>
<MenuItem icon={<PiPlusBold />} onClick={addGlobalReferenceImage} isDisabled={isFLUX}>
<MenuItem icon={<PiPlusBold />} onPointerUp={addGlobalReferenceImage} isDisabled={isFLUX}>
{t('controlLayers.globalReferenceImage')}
</MenuItem>
</MenuGroup>
<MenuGroup title={t('controlLayers.regional')}>
<MenuItem icon={<PiPlusBold />} onClick={addInpaintMask}>
<MenuItem icon={<PiPlusBold />} onPointerUp={addInpaintMask}>
{t('controlLayers.inpaintMask')}
</MenuItem>
<MenuItem icon={<PiPlusBold />} onClick={addRegionalGuidance} isDisabled={isFLUX}>
<MenuItem icon={<PiPlusBold />} onPointerUp={addRegionalGuidance} isDisabled={isFLUX}>
{t('controlLayers.regionalGuidance')}
</MenuItem>
<MenuItem icon={<PiPlusBold />} onClick={addRegionalReferenceImage} isDisabled={isFLUX}>
<MenuItem icon={<PiPlusBold />} onPointerUp={addRegionalReferenceImage} isDisabled={isFLUX}>
{t('controlLayers.regionalReferenceImage')}
</MenuItem>
</MenuGroup>
<MenuGroup title={t('controlLayers.layer_other')}>
<MenuItem icon={<PiPlusBold />} onClick={addControlLayer} isDisabled={isFLUX}>
<MenuItem icon={<PiPlusBold />} onPointerUp={addControlLayer} isDisabled={isFLUX}>
{t('controlLayers.controlLayer')}
</MenuItem>
<MenuItem icon={<PiPlusBold />} onClick={addRasterLayer}>
<MenuItem icon={<PiPlusBold />} onPointerUp={addRasterLayer}>
{t('controlLayers.rasterLayer')}
</MenuItem>
</MenuGroup>

View File

@@ -12,7 +12,7 @@ export const EntityListSelectedEntityActionBarDuplicateButton = memo(() => {
const dispatch = useAppDispatch();
const isBusy = useCanvasIsBusy();
const selectedEntityIdentifier = useAppSelector(selectSelectedEntityIdentifier);
const onClick = useCallback(() => {
const onPointerUp = useCallback(() => {
if (!selectedEntityIdentifier) {
return;
}
@@ -21,7 +21,7 @@ export const EntityListSelectedEntityActionBarDuplicateButton = memo(() => {
return (
<IconButton
onClick={onClick}
onPointerUp={onPointerUp}
isDisabled={!selectedEntityIdentifier || isBusy}
size="sm"
variant="link"

View File

@@ -22,7 +22,7 @@ export const EntityListSelectedEntityActionBarFilterButton = memo(() => {
return (
<IconButton
onClick={filter.start}
onPointerUp={filter.start}
isDisabled={filter.isDisabled}
size="sm"
variant="link"

View File

@@ -15,7 +15,7 @@ export const EntityListSelectedEntityActionBarSaveToAssetsButton = memo(() => {
const selectedEntityIdentifier = useAppSelector(selectSelectedEntityIdentifier);
const adapter = useEntityAdapterSafe(selectedEntityIdentifier);
const saveLayerToAssets = useSaveLayerToAssets();
const onClick = useCallback(() => {
const onPointerUp = useCallback(() => {
saveLayerToAssets(adapter);
}, [saveLayerToAssets, adapter]);
@@ -29,7 +29,7 @@ export const EntityListSelectedEntityActionBarSaveToAssetsButton = memo(() => {
return (
<IconButton
onClick={onClick}
onPointerUp={onPointerUp}
isDisabled={!selectedEntityIdentifier || isBusy}
size="sm"
variant="link"

View File

@@ -22,7 +22,7 @@ export const EntityListSelectedEntityActionBarTransformButton = memo(() => {
return (
<IconButton
onClick={transform.start}
onPointerUp={transform.start}
isDisabled={transform.isDisabled}
size="sm"
variant="link"

View File

@@ -20,7 +20,7 @@ export const CanvasRightPanel = memo(() => {
const { t } = useTranslation();
const tabIndex = useStore($canvasRightPanelTabIndex);
const imageViewer = useImageViewer();
const onClickViewerToggleButton = useCallback(() => {
const onPointerUpViewerToggleButton = useCallback(() => {
if ($canvasRightPanelTabIndex.get() !== 1) {
$canvasRightPanelTabIndex.set(1);
}
@@ -38,7 +38,7 @@ export const CanvasRightPanel = memo(() => {
<TabList alignItems="center">
<PanelTabs />
<Spacer />
<Button size="sm" variant="ghost" onClick={onClickViewerToggleButton}>
<Button size="sm" variant="ghost" onPointerUp={onPointerUpViewerToggleButton}>
{imageViewer.isOpen ? t('gallery.closeViewer') : t('gallery.openViewer')}
</Button>
</TabList>

View File

@@ -84,7 +84,7 @@ export const ControlLayerControlAdapter = memo(() => {
<Flex w="full" gap={2}>
<ControlLayerControlAdapterModel modelKey={controlAdapter.model?.key ?? null} onChange={onChangeModel} />
<IconButton
onClick={filter.start}
onPointerUp={filter.start}
isDisabled={filter.isDisabled}
size="sm"
alignSelf="stretch"
@@ -94,7 +94,7 @@ export const ControlLayerControlAdapter = memo(() => {
icon={<PiShootingStarBold />}
/>
<IconButton
onClick={pullBboxIntoLayer}
onPointerUp={pullBboxIntoLayer}
isDisabled={isBusy}
size="sm"
alignSelf="stretch"

View File

@@ -18,7 +18,7 @@ export const ControlLayerMenuItemsConvertControlToRaster = memo(() => {
}, [dispatch, entityIdentifier]);
return (
<MenuItem onClick={convertControlLayerToRasterLayer} icon={<PiLightningBold />} isDisabled={!isInteractable}>
<MenuItem onPointerUp={convertControlLayerToRasterLayer} icon={<PiLightningBold />} isDisabled={!isInteractable}>
{t('controlLayers.convertToRasterLayer')}
</MenuItem>
);

View File

@@ -28,7 +28,7 @@ export const ControlLayerMenuItemsTransparencyEffect = memo(() => {
}, [dispatch, entityIdentifier]);
return (
<MenuItem onClick={onToggle} icon={<PiDropHalfBold />} isDisabled={!isInteractable}>
<MenuItem onPointerUp={onToggle} icon={<PiDropHalfBold />} isDisabled={!isInteractable}>
{withTransparencyEffect
? t('controlLayers.disableTransparencyEffect')
: t('controlLayers.enableTransparencyEffect')}

View File

@@ -109,7 +109,7 @@ const FilterContent = memo(
<Button
variant="ghost"
leftIcon={<PiShootingStarBold />}
onClick={adapter.filterer.processImmediate}
onPointerUp={adapter.filterer.processImmediate}
isLoading={isProcessing}
loadingText={t('controlLayers.filter.process')}
isDisabled={!isValid || autoProcessFilter}
@@ -119,7 +119,7 @@ const FilterContent = memo(
<Spacer />
<Button
leftIcon={<PiArrowsCounterClockwiseBold />}
onClick={adapter.filterer.reset}
onPointerUp={adapter.filterer.reset}
isLoading={isProcessing}
loadingText={t('controlLayers.filter.reset')}
variant="ghost"
@@ -129,7 +129,7 @@ const FilterContent = memo(
<Button
variant="ghost"
leftIcon={<PiCheckBold />}
onClick={adapter.filterer.apply}
onPointerUp={adapter.filterer.apply}
isLoading={isProcessing}
loadingText={t('controlLayers.filter.apply')}
isDisabled={!isValid || !hasProcessed}
@@ -139,7 +139,7 @@ const FilterContent = memo(
<Button
variant="ghost"
leftIcon={<PiXBold />}
onClick={adapter.filterer.cancel}
onPointerUp={adapter.filterer.cancel}
loadingText={t('controlLayers.filter.cancel')}
>
{t('controlLayers.filter.cancel')}

View File

@@ -60,7 +60,7 @@ export const IPAdapterImagePreview = memo(({ image, onChangeImage, droppableData
{controlImage && (
<Flex position="absolute" flexDir="column" top={2} insetInlineEnd={2} gap={1}>
<IAIDndImageIcon
onClick={handleResetControlImage}
onPointerUp={handleResetControlImage}
icon={<PiArrowCounterClockwiseBold size={16} />}
tooltip={t('common.reset')}
/>

View File

@@ -103,7 +103,7 @@ export const IPAdapterSettings = memo(() => {
/>
</Box>
<IconButton
onClick={pullBboxIntoIPAdapter}
onPointerUp={pullBboxIntoIPAdapter}
isDisabled={isBusy}
variant="ghost"
aria-label={t('controlLayers.pullBboxIntoReferenceImage')}

View File

@@ -15,7 +15,7 @@ export const RasterLayerMenuItemsConvertRasterToControl = memo(() => {
const defaultControlAdapter = useAppSelector(selectDefaultControlAdapter);
const isInteractable = useIsEntityInteractable(entityIdentifier);
const onClick = useCallback(() => {
const onPointerUp = useCallback(() => {
dispatch(
rasterLayerConvertedToControlLayer({
entityIdentifier,
@@ -27,7 +27,7 @@ export const RasterLayerMenuItemsConvertRasterToControl = memo(() => {
}, [defaultControlAdapter, dispatch, entityIdentifier]);
return (
<MenuItem onClick={onClick} icon={<PiLightningBold />} isDisabled={!isInteractable}>
<MenuItem onPointerUp={onPointerUp} icon={<PiLightningBold />} isDisabled={!isInteractable}>
{t('controlLayers.convertToControlLayer')}
</MenuItem>
);

View File

@@ -30,7 +30,7 @@ export const RegionalGuidanceAddPromptsIPAdapterButtons = () => {
size="sm"
variant="ghost"
leftIcon={<PiPlusBold />}
onClick={addRegionalGuidancePositivePrompt}
onPointerUp={addRegionalGuidancePositivePrompt}
isDisabled={!validActions.canAddPositivePrompt}
>
{t('controlLayers.prompt')}
@@ -39,12 +39,12 @@ export const RegionalGuidanceAddPromptsIPAdapterButtons = () => {
size="sm"
variant="ghost"
leftIcon={<PiPlusBold />}
onClick={addRegionalGuidanceNegativePrompt}
onPointerUp={addRegionalGuidanceNegativePrompt}
isDisabled={!validActions.canAddNegativePrompt}
>
{t('controlLayers.negativePrompt')}
</Button>
<Button size="sm" variant="ghost" leftIcon={<PiPlusBold />} onClick={addRegionalGuidanceIPAdapter}>
<Button size="sm" variant="ghost" leftIcon={<PiPlusBold />} onPointerUp={addRegionalGuidanceIPAdapter}>
{t('controlLayers.referenceImage')}
</Button>
</Flex>

View File

@@ -15,7 +15,7 @@ export const RegionalGuidanceDeletePromptButton = memo(({ onDelete }: Props) =>
variant="link"
aria-label={t('controlLayers.deletePrompt')}
icon={<PiTrashSimpleFill />}
onClick={onDelete}
onPointerUp={onDelete}
flexGrow={0}
size="sm"
p={0}

View File

@@ -120,7 +120,7 @@ export const RegionalGuidanceIPAdapterSettings = memo(({ referenceImageId }: Pro
icon={<PiTrashSimpleFill />}
tooltip={t('controlLayers.deleteReferenceImage')}
aria-label={t('controlLayers.deleteReferenceImage')}
onClick={onDeleteIPAdapter}
onPointerUp={onDeleteIPAdapter}
colorScheme="error"
/>
</Flex>
@@ -135,7 +135,7 @@ export const RegionalGuidanceIPAdapterSettings = memo(({ referenceImageId }: Pro
/>
</Box>
<IconButton
onClick={pullBboxIntoIPAdapter}
onPointerUp={pullBboxIntoIPAdapter}
isDisabled={isBusy}
variant="ghost"
aria-label={t('controlLayers.pullBboxIntoReferenceImage')}

View File

@@ -26,13 +26,13 @@ export const RegionalGuidanceMenuItemsAddPromptsAndIPAdapter = memo(() => {
return (
<>
<MenuItem onClick={addRegionalGuidancePositivePrompt} isDisabled={!validActions.canAddPositivePrompt || isBusy}>
<MenuItem onPointerUp={addRegionalGuidancePositivePrompt} isDisabled={!validActions.canAddPositivePrompt || isBusy}>
{t('controlLayers.addPositivePrompt')}
</MenuItem>
<MenuItem onClick={addRegionalGuidanceNegativePrompt} isDisabled={!validActions.canAddNegativePrompt || isBusy}>
<MenuItem onPointerUp={addRegionalGuidanceNegativePrompt} isDisabled={!validActions.canAddNegativePrompt || isBusy}>
{t('controlLayers.addNegativePrompt')}
</MenuItem>
<MenuItem onClick={addRegionalGuidanceIPAdapter} isDisabled={isBusy}>
<MenuItem onPointerUp={addRegionalGuidanceIPAdapter} isDisabled={isBusy}>
{t('controlLayers.addReferenceImage')}
</MenuItem>
</>

View File

@@ -17,12 +17,12 @@ export const RegionalGuidanceMenuItemsAutoNegative = memo(() => {
[entityIdentifier]
);
const autoNegative = useAppSelector(selectAutoNegative);
const onClick = useCallback(() => {
const onPointerUp = useCallback(() => {
dispatch(rgAutoNegativeToggled({ entityIdentifier }));
}, [dispatch, entityIdentifier]);
return (
<MenuItem icon={<PiSelectionInverseBold />} onClick={onClick}>
<MenuItem icon={<PiSelectionInverseBold />} onPointerUp={onPointerUp}>
{autoNegative ? t('controlLayers.disableAutoNegative') : t('controlLayers.enableAutoNegative')}
</MenuItem>
);

View File

@@ -10,7 +10,7 @@ export const CanvasSettingsClearCachesButton = memo(() => {
canvasManager.cache.clearAll();
}, [canvasManager]);
return (
<Button onClick={clearCaches} size="sm" colorScheme="warning">
<Button onPointerUp={clearCaches} size="sm" colorScheme="warning">
{t('controlLayers.clearCaches')}
</Button>
);

View File

@@ -7,11 +7,11 @@ import { useTranslation } from 'react-i18next';
export const CanvasSettingsClearHistoryButton = memo(() => {
const { t } = useTranslation();
const dispatch = useAppDispatch();
const onClick = useCallback(() => {
const onPointerUp = useCallback(() => {
dispatch(canvasClearHistory());
}, [dispatch]);
return (
<Button onClick={onClick} size="sm">
<Button onPointerUp={onPointerUp} size="sm">
{t('controlLayers.clearHistory')}
</Button>
);

View File

@@ -6,11 +6,11 @@ import { useTranslation } from 'react-i18next';
export const CanvasSettingsLogDebugInfoButton = memo(() => {
const { t } = useTranslation();
const canvasManager = useCanvasManager();
const onClick = useCallback(() => {
const onPointerUp = useCallback(() => {
canvasManager.logDebugInfo();
}, [canvasManager]);
return (
<Button onClick={onClick} size="sm">
<Button onPointerUp={onPointerUp} size="sm">
{t('controlLayers.logDebugInfo')}
</Button>
);

View File

@@ -6,14 +6,14 @@ import { useTranslation } from 'react-i18next';
export const CanvasSettingsRecalculateRectsButton = memo(() => {
const { t } = useTranslation();
const canvasManager = useCanvasManager();
const onClick = useCallback(() => {
const onPointerUp = useCallback(() => {
for (const adapter of canvasManager.getAllAdapters()) {
adapter.transformer.requestRectCalculation();
}
}, [canvasManager]);
return (
<Button onClick={onClick} size="sm" colorScheme="warning">
<Button onPointerUp={onPointerUp} size="sm" colorScheme="warning">
{t('controlLayers.recalculateRects')}
</Button>
);

View File

@@ -60,7 +60,7 @@ export const StagingAreaToolbarAcceptButton = memo(() => {
tooltip={`${t('common.accept')} (Enter)`}
aria-label={`${t('common.accept')} (Enter)`}
icon={<PiCheckBold />}
onClick={acceptSelected}
onPointerUp={acceptSelected}
colorScheme="invokeBlue"
isDisabled={!selectedImage}
/>

View File

@@ -18,7 +18,7 @@ export const StagingAreaToolbarDiscardAllButton = memo(() => {
tooltip={`${t('controlLayers.stagingArea.discardAll')} (Esc)`}
aria-label={t('controlLayers.stagingArea.discardAll')}
icon={<PiTrashSimpleBold />}
onClick={discardAll}
onPointerUp={discardAll}
colorScheme="error"
fontSize={16}
/>

View File

@@ -35,7 +35,7 @@ export const StagingAreaToolbarDiscardSelectedButton = memo(() => {
tooltip={t('controlLayers.stagingArea.discard')}
aria-label={t('controlLayers.stagingArea.discard')}
icon={<PiXBold />}
onClick={discardSelected}
onPointerUp={discardSelected}
colorScheme="invokeBlue"
fontSize={16}
isDisabled={!selectedImage}

View File

@@ -40,7 +40,7 @@ export const StagingAreaToolbarNextButton = memo(() => {
tooltip={`${t('controlLayers.stagingArea.next')} (Right)`}
aria-label={`${t('controlLayers.stagingArea.next')} (Right)`}
icon={<PiArrowRightBold />}
onClick={selectNext}
onPointerUp={selectNext}
colorScheme="invokeBlue"
isDisabled={imageCount <= 1 || !shouldShowStagedImage}
/>

View File

@@ -40,7 +40,7 @@ export const StagingAreaToolbarPrevButton = memo(() => {
tooltip={`${t('controlLayers.stagingArea.previous')} (Left)`}
aria-label={`${t('controlLayers.stagingArea.previous')} (Left)`}
icon={<PiArrowLeftBold />}
onClick={selectPrev}
onPointerUp={selectPrev}
colorScheme="invokeBlue"
isDisabled={imageCount <= 1 || !shouldShowStagedImage}
/>

View File

@@ -40,7 +40,7 @@ export const StagingAreaToolbarSaveSelectedToGalleryButton = memo(() => {
tooltip={t('controlLayers.stagingArea.saveToGallery')}
aria-label={t('controlLayers.stagingArea.saveToGallery')}
icon={<PiFloppyDiskBold />}
onClick={saveSelectedImageToGallery}
onPointerUp={saveSelectedImageToGallery}
colorScheme="invokeBlue"
isDisabled={!selectedImage || !selectedImage.imageDTO.is_intermediate}
/>

View File

@@ -29,7 +29,7 @@ export const StagingAreaToolbarToggleShowResultsButton = memo(() => {
}
data-alert={!shouldShowStagedImage}
icon={shouldShowStagedImage ? <PiEyeBold /> : <PiEyeSlashBold />}
onClick={toggleShowResults}
onPointerUp={toggleShowResults}
colorScheme="invokeBlue"
/>
);

View File

@@ -27,7 +27,7 @@ export const ToolBboxButton = memo(() => {
icon={<PiBoundingBoxBold />}
colorScheme={isSelected ? 'invokeBlue' : 'base'}
variant="solid"
onClick={selectBbox}
onPointerUp={selectBbox}
/>
</Tooltip>
);

View File

@@ -27,7 +27,7 @@ export const ToolBrushButton = memo(() => {
icon={<PiPaintBrushBold />}
colorScheme={isSelected ? 'invokeBlue' : 'base'}
variant="solid"
onClick={selectBrush}
onPointerUp={selectBrush}
/>
</Tooltip>
);

View File

@@ -27,7 +27,7 @@ export const ToolColorPickerButton = memo(() => {
icon={<PiEyedropperBold />}
colorScheme={isSelected ? 'invokeBlue' : 'base'}
variant="solid"
onClick={selectColorPicker}
onPointerUp={selectColorPicker}
/>
</Tooltip>
);

View File

@@ -27,7 +27,7 @@ export const ToolEraserButton = memo(() => {
icon={<PiEraserBold />}
colorScheme={isSelected ? 'invokeBlue' : 'base'}
variant="solid"
onClick={selectEraser}
onPointerUp={selectEraser}
/>
</Tooltip>
);

View File

@@ -27,7 +27,7 @@ export const ToolMoveButton = memo(() => {
icon={<PiCursorBold />}
colorScheme={isSelected ? 'invokeBlue' : 'base'}
variant="solid"
onClick={selectMove}
onPointerUp={selectMove}
/>
</Tooltip>
);

View File

@@ -27,7 +27,7 @@ export const ToolRectButton = memo(() => {
icon={<PiRectangleBold />}
colorScheme={isSelected ? 'invokeBlue' : 'base'}
variant="solid"
onClick={selectRect}
onPointerUp={selectRect}
/>
</Tooltip>
);

View File

@@ -27,7 +27,7 @@ export const ToolViewButton = memo(() => {
icon={<PiHandBold />}
colorScheme={isSelected ? 'invokeBlue' : 'base'}
variant="solid"
onClick={selectView}
onPointerUp={selectView}
/>
</Tooltip>
);

View File

@@ -9,13 +9,13 @@ export const CanvasToolbarFitBboxToLayersButton = memo(() => {
const { t } = useTranslation();
const canvasManager = useCanvasManager();
const isBusy = useCanvasIsBusy();
const onClick = useCallback(() => {
const onPointerUp = useCallback(() => {
canvasManager.bbox.fitToLayers();
}, [canvasManager.bbox]);
return (
<IconButton
onClick={onClick}
onPointerUp={onPointerUp}
variant="link"
alignSelf="stretch"
aria-label={t('controlLayers.fitBboxToLayers')}

View File

@@ -12,7 +12,7 @@ export const CanvasToolbarRedoButton = memo(() => {
const dispatch = useAppDispatch();
const isBusy = useCanvasIsBusy();
const mayRedo = useAppSelector(selectCanvasMayRedo);
const onClick = useCallback(() => {
const onPointerUp = useCallback(() => {
dispatch(canvasRedo());
}, [dispatch]);
@@ -20,7 +20,7 @@ export const CanvasToolbarRedoButton = memo(() => {
<IconButton
aria-label={t('hotkeys.canvas.redo.title')}
tooltip={t('hotkeys.canvas.redo.title')}
onClick={onClick}
onPointerUp={onPointerUp}
icon={<PiArrowClockwiseBold />}
variant="link"
alignSelf="stretch"

View File

@@ -10,7 +10,7 @@ export const CanvasToolbarResetCanvasButton = memo(() => {
const { t } = useTranslation();
const dispatch = useAppDispatch();
const canvasManager = useCanvasManager();
const onClick = useCallback(() => {
const onPointerUp = useCallback(() => {
dispatch(canvasReset());
canvasManager.stage.fitLayersToStage();
}, [canvasManager.stage, dispatch]);
@@ -18,7 +18,7 @@ export const CanvasToolbarResetCanvasButton = memo(() => {
<IconButton
aria-label={t('controlLayers.resetCanvas')}
tooltip={t('controlLayers.resetCanvas')}
onClick={onClick}
onPointerUp={onPointerUp}
colorScheme="error"
icon={<PiTrashBold />}
variant="link"

View File

@@ -60,7 +60,7 @@ export const CanvasToolbarResetViewButton = memo(() => {
<IconButton
tooltip={t('hotkeys.canvas.fitLayersToCanvas.title')}
aria-label={t('hotkeys.canvas.fitLayersToCanvas.title')}
onClick={canvasManager.stage.fitLayersToStage}
onPointerUp={canvasManager.stage.fitLayersToStage}
icon={<PiArrowsOutBold />}
variant="link"
alignSelf="stretch"

View File

@@ -16,7 +16,7 @@ export const CanvasToolbarSaveToGalleryButton = memo(() => {
<IconButton
variant="link"
alignSelf="stretch"
onClick={shift ? saveBboxToGallery : saveCanvasToGallery}
onPointerUp={shift ? saveBboxToGallery : saveCanvasToGallery}
icon={<PiFloppyDiskBold />}
aria-label={shift ? t('controlLayers.saveBboxToGallery') : t('controlLayers.saveCanvasToGallery')}
tooltip={shift ? t('controlLayers.saveBboxToGallery') : t('controlLayers.saveCanvasToGallery')}

View File

@@ -174,7 +174,7 @@ const SCALE_SNAPS = [0.1, 0.15, 0.2, 0.25, 0.5, 0.75, 1, 1.5, 2, 2.5, 5, 7.5, 10
const ZoomOutButton = () => {
const canvasManager = useCanvasManager();
const scale = useStore(computed(canvasManager.stage.$stageAttrs, (attrs) => attrs.scale));
const onClick = useCallback(() => {
const onPointerUp = useCallback(() => {
const nextScale =
SCALE_SNAPS.slice()
.reverse()
@@ -184,7 +184,7 @@ const ZoomOutButton = () => {
return (
<IconButton
onClick={onClick}
onPointerUp={onPointerUp}
icon={<PiMagnifyingGlassMinusBold />}
aria-label="Zoom out"
variant="link"
@@ -197,14 +197,14 @@ const ZoomOutButton = () => {
const ZoomInButton = () => {
const canvasManager = useCanvasManager();
const scale = useStore(computed(canvasManager.stage.$stageAttrs, (attrs) => attrs.scale));
const onClick = useCallback(() => {
const onPointerUp = useCallback(() => {
const nextScale = SCALE_SNAPS.find((snap) => snap > scale) ?? canvasManager.stage.config.MAX_SCALE;
canvasManager.stage.setScale(Math.min(nextScale, canvasManager.stage.config.MAX_SCALE));
}, [canvasManager.stage, scale]);
return (
<IconButton
onClick={onClick}
onPointerUp={onPointerUp}
icon={<PiMagnifyingGlassPlusBold />}
aria-label="Zoom out"
variant="link"

View File

@@ -12,7 +12,7 @@ export const CanvasToolbarUndoButton = memo(() => {
const dispatch = useAppDispatch();
const isBusy = useCanvasIsBusy();
const mayUndo = useAppSelector(selectCanvasMayUndo);
const onClick = useCallback(() => {
const onPointerUp = useCallback(() => {
dispatch(canvasUndo());
}, [dispatch]);
@@ -20,7 +20,7 @@ export const CanvasToolbarUndoButton = memo(() => {
<IconButton
aria-label={t('hotkeys.canvas.undo.title')}
tooltip={t('hotkeys.canvas.undo.title')}
onClick={onClick}
onPointerUp={onPointerUp}
icon={<PiArrowCounterClockwiseBold />}
variant="link"
alignSelf="stretch"

View File

@@ -68,7 +68,7 @@ const TransformContent = memo(({ adapter }: { adapter: CanvasEntityAdapter }) =>
<ButtonGroup isAttached={false} size="sm" w="full">
<Button
leftIcon={<PiArrowsOutBold />}
onClick={adapter.transformer.fitProxyRectToBbox}
onPointerUp={adapter.transformer.fitProxyRectToBbox}
isLoading={isProcessing}
loadingText={t('controlLayers.transform.fitToBbox')}
variant="ghost"
@@ -78,7 +78,7 @@ const TransformContent = memo(({ adapter }: { adapter: CanvasEntityAdapter }) =>
<Spacer />
<Button
leftIcon={<PiArrowsCounterClockwiseBold />}
onClick={adapter.transformer.resetTransform}
onPointerUp={adapter.transformer.resetTransform}
isLoading={isProcessing}
loadingText={t('controlLayers.transform.reset')}
variant="ghost"
@@ -87,7 +87,7 @@ const TransformContent = memo(({ adapter }: { adapter: CanvasEntityAdapter }) =>
</Button>
<Button
leftIcon={<PiCheckBold />}
onClick={adapter.transformer.applyTransform}
onPointerUp={adapter.transformer.applyTransform}
isLoading={isProcessing}
loadingText={t('controlLayers.transform.apply')}
variant="ghost"
@@ -96,7 +96,7 @@ const TransformContent = memo(({ adapter }: { adapter: CanvasEntityAdapter }) =>
</Button>
<Button
leftIcon={<PiXBold />}
onClick={adapter.transformer.stopTransform}
onPointerUp={adapter.transformer.stopTransform}
isLoading={isProcessing}
loadingText={t('common.cancel')}
variant="ghost"

View File

@@ -25,7 +25,7 @@ export const CanvasEntityAddOfTypeButton = memo(({ type }: Props) => {
const addControlLayer = useAddControlLayer();
const addGlobalReferenceImage = useAddGlobalReferenceImage();
const onClick = useCallback(() => {
const onPointerUp = useCallback(() => {
switch (type) {
case 'inpaint_mask':
addInpaintMask();
@@ -67,7 +67,7 @@ export const CanvasEntityAddOfTypeButton = memo(({ type }: Props) => {
tooltip={label}
variant="link"
icon={<NewLayerIcon />}
onClick={onClick}
onPointerUp={onPointerUp}
alignSelf="stretch"
isDisabled={isBusy}
/>

View File

@@ -12,7 +12,7 @@ export const CanvasEntityContainer = memo((props: PropsWithChildren) => {
const entityIdentifier = useEntityIdentifierContext();
const isSelected = useEntityIsSelected(entityIdentifier);
const selectionColor = useEntitySelectionColor(entityIdentifier);
const onClick = useCallback(() => {
const onPointerUp = useCallback(() => {
if (isSelected) {
return;
}
@@ -25,7 +25,7 @@ export const CanvasEntityContainer = memo((props: PropsWithChildren) => {
flexDir="column"
w="full"
bg={isSelected ? 'base.800' : 'base.850'}
onClick={onClick}
onPointerUp={onPointerUp}
borderInlineStartWidth={5}
borderColor={isSelected ? selectionColor : 'base.800'}
borderRadius="base"

View File

@@ -12,7 +12,7 @@ export const CanvasEntityDeleteButton = memo(() => {
const entityIdentifier = useEntityIdentifierContext();
const dispatch = useAppDispatch();
const isBusy = useCanvasIsBusy();
const onClick = useCallback(() => {
const onPointerUp = useCallback(() => {
dispatch(entityDeleted({ entityIdentifier }));
}, [dispatch, entityIdentifier]);
@@ -24,7 +24,7 @@ export const CanvasEntityDeleteButton = memo(() => {
variant="link"
alignSelf="stretch"
icon={<PiTrashSimpleFill />}
onPointerUp={onClick}
onPointerUp={onPointerUp}
colorScheme="error"
isDisabled={isBusy}
/>

View File

@@ -14,7 +14,7 @@ export const CanvasEntityEnabledToggle = memo(() => {
const isEnabled = useEntityIsEnabled(entityIdentifier);
const isBusy = useCanvasIsBusy();
const dispatch = useAppDispatch();
const onClick = useCallback(() => {
const onPointerUp = useCallback(() => {
dispatch(entityIsEnabledToggled({ entityIdentifier }));
}, [dispatch, entityIdentifier]);
@@ -26,7 +26,7 @@ export const CanvasEntityEnabledToggle = memo(() => {
variant="link"
alignSelf="stretch"
icon={isEnabled ? <PiCircleFill /> : <PiCircleBold />}
onClick={onClick}
onPointerUp={onPointerUp}
isDisabled={isBusy}
/>
);

View File

@@ -31,7 +31,7 @@ export const CanvasEntityGroupList = memo(({ isSelected, type, children }: Props
<Flex
flexGrow={1}
as={Button}
onClick={collapse.toggle}
onPointerUp={collapse.toggle}
justifyContent="space-between"
alignItems="center"
gap={3}

View File

@@ -12,7 +12,7 @@ export const CanvasEntityIsBookmarkedForQuickSwitchToggle = memo(() => {
const entityIdentifier = useEntityIdentifierContext();
const isBookmarked = useEntityIsBookmarkedForQuickSwitch(entityIdentifier);
const dispatch = useAppDispatch();
const onClick = useCallback(() => {
const onPointerUp = useCallback(() => {
if (isBookmarked) {
dispatch(bookmarkedEntityChanged({ entityIdentifier: null }));
} else {
@@ -28,7 +28,7 @@ export const CanvasEntityIsBookmarkedForQuickSwitchToggle = memo(() => {
variant="link"
alignSelf="stretch"
icon={isBookmarked ? <PiBookmarkSimpleFill /> : <PiBookmarkSimpleBold />}
onClick={onClick}
onPointerUp={onPointerUp}
/>
);
});

View File

@@ -14,7 +14,7 @@ export const CanvasEntityIsLockedToggle = memo(() => {
const isLocked = useEntityIsLocked(entityIdentifier);
const isBusy = useCanvasIsBusy();
const dispatch = useAppDispatch();
const onClick = useCallback(() => {
const onPointerUp = useCallback(() => {
dispatch(entityIsLockedToggled({ entityIdentifier }));
}, [dispatch, entityIdentifier]);
@@ -26,7 +26,7 @@ export const CanvasEntityIsLockedToggle = memo(() => {
variant="link"
alignSelf="stretch"
icon={isLocked ? <PiLockSimpleFill /> : <PiLockSimpleOpenBold />}
onClick={onClick}
onPointerUp={onPointerUp}
isDisabled={isBusy}
/>
);

View File

@@ -89,28 +89,28 @@ export const CanvasEntityMenuItemsArrange = memo(() => {
return (
<>
<MenuItem
onClick={moveToFront}
onPointerUp={moveToFront}
isDisabled={!validActions.canMoveToFront || !isInteractable}
icon={<PiArrowLineUpBold />}
>
{t('controlLayers.moveToFront')}
</MenuItem>
<MenuItem
onClick={moveForwardOne}
onPointerUp={moveForwardOne}
isDisabled={!validActions.canMoveForwardOne || !isInteractable}
icon={<PiArrowUpBold />}
>
{t('controlLayers.moveForward')}
</MenuItem>
<MenuItem
onClick={moveBackwardOne}
onPointerUp={moveBackwardOne}
isDisabled={!validActions.canMoveBackwardOne || !isInteractable}
icon={<PiArrowDownBold />}
>
{t('controlLayers.moveBackward')}
</MenuItem>
<MenuItem
onClick={moveToBack}
onPointerUp={moveToBack}
isDisabled={!validActions.canMoveToBack || !isInteractable}
icon={<PiArrowLineDownBold />}
>

View File

@@ -14,12 +14,12 @@ export const CanvasEntityMenuItemsCopyToClipboard = memo(() => {
const isInteractable = useIsEntityInteractable(entityIdentifier);
const copyLayerToClipboard = useCopyLayerToClipboard();
const onClick = useCallback(() => {
const onPointerUp = useCallback(() => {
copyLayerToClipboard(adapter);
}, [copyLayerToClipboard, adapter]);
return (
<MenuItem onClick={onClick} icon={<PiCopyBold />} isDisabled={!isInteractable}>
<MenuItem onPointerUp={onPointerUp} icon={<PiCopyBold />} isDisabled={!isInteractable}>
{t('controlLayers.copyToClipboard')}
</MenuItem>
);

View File

@@ -11,7 +11,7 @@ export const CanvasEntityMenuItemsCropToBbox = memo(() => {
const entityIdentifier = useEntityIdentifierContext();
const adapter = useEntityAdapterSafe(entityIdentifier);
const isInteractable = useIsEntityInteractable(entityIdentifier);
const onClick = useCallback(() => {
const onPointerUp = useCallback(() => {
if (!adapter) {
return;
}
@@ -19,7 +19,7 @@ export const CanvasEntityMenuItemsCropToBbox = memo(() => {
}, [adapter]);
return (
<MenuItem onClick={onClick} icon={<PiCropBold />} isDisabled={!isInteractable}>
<MenuItem onPointerUp={onPointerUp} icon={<PiCropBold />} isDisabled={!isInteractable}>
{t('controlLayers.cropLayerToBbox')}
</MenuItem>
);

View File

@@ -18,7 +18,7 @@ export const CanvasEntityMenuItemsDelete = memo(() => {
}, [dispatch, entityIdentifier]);
return (
<MenuItem onClick={deleteEntity} icon={<PiTrashSimpleBold />} isDestructive isDisabled={!isInteractable}>
<MenuItem onPointerUp={deleteEntity} icon={<PiTrashSimpleBold />} isDestructive isDisabled={!isInteractable}>
{t('common.delete')}
</MenuItem>
);

View File

@@ -13,12 +13,12 @@ export const CanvasEntityMenuItemsDuplicate = memo(() => {
const entityIdentifier = useEntityIdentifierContext();
const isInteractable = useIsEntityInteractable(entityIdentifier);
const onClick = useCallback(() => {
const onPointerUp = useCallback(() => {
dispatch(entityDuplicated({ entityIdentifier }));
}, [dispatch, entityIdentifier]);
return (
<MenuItem onClick={onClick} icon={<PiCopyFill />} isDisabled={!isInteractable}>
<MenuItem onPointerUp={onPointerUp} icon={<PiCopyFill />} isDisabled={!isInteractable}>
{t('controlLayers.duplicate')}
</MenuItem>
);

View File

@@ -11,7 +11,7 @@ export const CanvasEntityMenuItemsFilter = memo(() => {
const filter = useEntityFilter(entityIdentifier);
return (
<MenuItem onClick={filter.start} icon={<PiShootingStarBold />} isDisabled={filter.isDisabled}>
<MenuItem onPointerUp={filter.start} icon={<PiShootingStarBold />} isDisabled={filter.isDisabled}>
{t('controlLayers.filter.filter')}
</MenuItem>
);

View File

@@ -13,12 +13,12 @@ export const CanvasEntityMenuItemsSave = memo(() => {
const adapter = useEntityAdapterSafe(entityIdentifier);
const isInteractable = useIsEntityInteractable(entityIdentifier);
const saveLayerToAssets = useSaveLayerToAssets();
const onClick = useCallback(() => {
const onPointerUp = useCallback(() => {
saveLayerToAssets(adapter);
}, [saveLayerToAssets, adapter]);
return (
<MenuItem onClick={onClick} icon={<PiFloppyDiskBold />} isDisabled={!isInteractable}>
<MenuItem onPointerUp={onPointerUp} icon={<PiFloppyDiskBold />} isDisabled={!isInteractable}>
{t('controlLayers.saveLayerToAssets')}
</MenuItem>
);

View File

@@ -11,7 +11,7 @@ export const CanvasEntityMenuItemsTransform = memo(() => {
const transform = useEntityTransform(entityIdentifier);
return (
<MenuItem onClick={transform.start} icon={<PiFrameCornersBold />} isDisabled={transform.isDisabled}>
<MenuItem onPointerUp={transform.start} icon={<PiFrameCornersBold />} isDisabled={transform.isDisabled}>
{t('controlLayers.transform.transform')}
</MenuItem>
);

View File

@@ -26,7 +26,7 @@ export const CanvasEntityMergeVisibleButton = memo(({ type }: Props) => {
const canvasManager = useCanvasManager();
const isBusy = useCanvasIsBusy();
const entityCount = useEntityTypeCount(type);
const onClick = useCallback(async () => {
const onPointerUp = useCallback(async () => {
if (type === 'raster_layer') {
const rect = canvasManager.stage.getVisibleRect('raster_layer');
const result = await withResultAsync(() =>
@@ -83,7 +83,7 @@ export const CanvasEntityMergeVisibleButton = memo(({ type }: Props) => {
tooltip={t('controlLayers.mergeVisible')}
variant="link"
icon={<PiStackBold />}
onClick={onClick}
onPointerUp={onPointerUp}
alignSelf="stretch"
isDisabled={entityCount <= 1 || isBusy}
/>

View File

@@ -18,7 +18,7 @@ export const CanvasEntityTypeIsHiddenToggle = memo(({ type }: Props) => {
const dispatch = useAppDispatch();
const isHidden = useEntityTypeIsHidden(type);
const typeString = useEntityTypeString(type, true);
const onClick = useCallback<MouseEventHandler>(
const onPointerUp = useCallback<MouseEventHandler>(
(e) => {
e.stopPropagation();
dispatch(allEntitiesOfTypeIsHiddenToggled({ type }));
@@ -33,7 +33,7 @@ export const CanvasEntityTypeIsHiddenToggle = memo(({ type }: Props) => {
tooltip={t(isHidden ? 'controlLayers.hidingType' : 'controlLayers.showingType', { type: typeString })}
variant="link"
icon={isHidden ? <PiEyeClosedBold /> : <PiEyeBold />}
onClick={onClick}
onPointerUp={onPointerUp}
alignSelf="stretch"
/>
);

View File

@@ -9,11 +9,11 @@ import { PiTrashSimpleBold } from 'react-icons/pi';
import { $isConnected } from 'services/events/stores';
type DeleteImageButtonProps = Omit<IconButtonProps, 'aria-label'> & {
onClick: () => void;
onPointerUp: () => void;
};
export const DeleteImageButton = memo((props: DeleteImageButtonProps) => {
const { onClick, isDisabled } = props;
const { onPointerUp, isDisabled } = props;
const { t } = useTranslation();
const isConnected = useStore($isConnected);
const imageSelectionLength = useAppSelector(selectSelectionCount);
@@ -21,7 +21,7 @@ export const DeleteImageButton = memo((props: DeleteImageButtonProps) => {
return (
<IconButton
onClick={onClick}
onPointerUp={onPointerUp}
icon={<PiTrashSimpleBold />}
tooltip={labelMessage}
aria-label={labelMessage}

View File

@@ -28,7 +28,7 @@ export const ShowDynamicPromptsPreviewButton = memo(() => {
isDisabled={isOpen}
aria-label={t('dynamicPrompts.showDynamicPrompts')}
icon={<PiBracketsCurlyBold />}
onClick={onOpen}
onPointerUp={onOpen}
sx={isLoading ? loadingStyles : undefined}
colorScheme={isError && !isLoading ? 'error' : 'base'}
/>

View File

@@ -75,29 +75,29 @@ const BoardContextMenu = ({ board, children }: Props) => {
<MenuList visibility="visible">
<MenuGroup title={boardName}>
{!autoAssignBoardOnClick && (
<MenuItem icon={<PiPlusBold />} isDisabled={isSelectedForAutoAdd} onClick={handleSetAutoAdd}>
<MenuItem icon={<PiPlusBold />} isDisabled={isSelectedForAutoAdd} onPointerUp={handleSetAutoAdd}>
{isSelectedForAutoAdd ? t('boards.selectedForAutoAdd') : t('boards.menuItemAutoAdd')}
</MenuItem>
)}
{isBulkDownloadEnabled && (
<MenuItem icon={<PiDownloadBold />} onClickCapture={handleBulkDownload}>
<MenuItem icon={<PiDownloadBold />} onPointerUpCapture={handleBulkDownload}>
{t('boards.downloadBoard')}
</MenuItem>
)}
{board.archived && (
<MenuItem icon={<PiArchiveBold />} onClick={handleUnarchive}>
<MenuItem icon={<PiArchiveBold />} onPointerUp={handleUnarchive}>
{t('boards.unarchiveBoard')}
</MenuItem>
)}
{!board.archived && (
<MenuItem icon={<PiArchiveFill />} onClick={handleArchive}>
<MenuItem icon={<PiArchiveFill />} onPointerUp={handleArchive}>
{t('boards.archiveBoard')}
</MenuItem>
)}
<MenuItem color="error.300" icon={<PiTrashSimpleBold />} onClick={setAsBoardToDelete} isDestructive>
<MenuItem color="error.300" icon={<PiTrashSimpleBold />} onPointerUp={setAsBoardToDelete} isDestructive>
{t('boards.deleteBoard')}
</MenuItem>
</MenuGroup>

View File

@@ -42,7 +42,7 @@ const AddBoardButton = ({ isPrivateBoard }: Props) => {
isLoading={isLoading}
tooltip={label}
aria-label={label}
onClick={handleCreateBoard}
onPointerUp={handleCreateBoard}
size="md"
data-testid="add-board-button"
variant="link"

View File

@@ -84,7 +84,7 @@ export const BoardsList = ({ isPrivate }: Props) => {
bg="base.900"
>
{allowPrivateBoards ? (
<Button variant="unstyled" onClick={onToggle}>
<Button variant="unstyled" onPointerUp={onToggle}>
<Flex gap="2" alignItems="center">
<Icon
boxSize={4}

View File

@@ -52,7 +52,7 @@ const BoardsSearch = () => {
{boardSearchText && boardSearchText.length && (
<InputRightElement h="full" pe={2}>
<IconButton
onClick={clearBoardSearch}
onPointerUp={clearBoardSearch}
size="sm"
variant="link"
aria-label={t('boards.clearSearch')}

View File

@@ -60,7 +60,7 @@ const GalleryBoard = ({ board, isSelected }: GalleryBoardProps) => {
const [localBoardName, setLocalBoardName] = useState(board.board_name);
const onStartEditingRef = useRef<MouseEventHandler | undefined>(undefined);
const onClick = useCallback(() => {
const onPointerUp = useCallback(() => {
if (selectedBoardId !== board.board_id) {
dispatch(boardIdSelected({ boardId: board.board_id }));
}
@@ -123,7 +123,7 @@ const GalleryBoard = ({ board, isSelected }: GalleryBoardProps) => {
<Flex
position="relative"
ref={ref}
onClick={onClick}
onPointerUp={onPointerUp}
onDoubleClick={onDoubleClick}
w="full"
alignItems="center"
@@ -180,7 +180,7 @@ const GalleryBoard = ({ board, isSelected }: GalleryBoardProps) => {
const JankEditableHijack = memo((props: { onStartEditingRef: MutableRefObject<MouseEventHandler | undefined> }) => {
const editableControls = useEditableControls();
useEffect(() => {
props.onStartEditingRef.current = editableControls.getEditButtonProps().onClick;
props.onStartEditingRef.current = editableControls.getEditButtonProps().onPointerUp;
}, [props, editableControls]);
return null;
});

View File

@@ -64,7 +64,7 @@ const NoBoardBoard = memo(({ isSelected }: Props) => {
<Flex
position="relative"
ref={ref}
onClick={handleSelectBoard}
onPointerUp={handleSelectBoard}
w="full"
alignItems="center"
borderRadius="base"

View File

@@ -127,13 +127,13 @@ const DeleteBoardModal = () => {
</AlertDialogBody>
<AlertDialogFooter>
<Flex w="full" gap={2} justifyContent="end">
<Button ref={cancelRef} onClick={handleClose}>
<Button ref={cancelRef} onPointerUp={handleClose}>
{t('boards.cancel')}
</Button>
<Button colorScheme="warning" isLoading={isLoading} onClick={handleDeleteBoardOnly}>
<Button colorScheme="warning" isLoading={isLoading} onPointerUp={handleDeleteBoardOnly}>
{t('boards.deleteBoardOnly')}
</Button>
<Button colorScheme="error" isLoading={isLoading} onClick={handleDeleteBoardAndImages}>
<Button colorScheme="error" isLoading={isLoading} onPointerUp={handleDeleteBoardAndImages}>
{t('boards.deleteBoardAndImages')}
</Button>
</Flex>

View File

@@ -38,12 +38,12 @@ const NoBoardBoardContextMenu = ({ children }: Props) => {
<MenuList visibility="visible">
<MenuGroup title={t('boards.uncategorized')}>
{!autoAssignBoardOnClick && (
<MenuItem icon={<PiPlusBold />} isDisabled={isSelectedForAutoAdd} onClick={handleSetAutoAdd}>
<MenuItem icon={<PiPlusBold />} isDisabled={isSelectedForAutoAdd} onPointerUp={handleSetAutoAdd}>
{isSelectedForAutoAdd ? t('boards.selectedForAutoAdd') : t('boards.menuItemAutoAdd')}
</MenuItem>
)}
{isBulkDownloadEnabled && (
<MenuItem icon={<PiDownloadBold />} onClickCapture={handleBulkDownload}>
<MenuItem icon={<PiDownloadBold />} onPointerUpCapture={handleBulkDownload}>
{t('boards.downloadBoard')}
</MenuItem>
)}

View File

@@ -74,17 +74,17 @@ export const Gallery = () => {
{boardName}
</Text>
<Spacer />
<Tab sx={BASE_STYLES} _selected={SELECTED_STYLES} onClick={handleClickImages} data-testid="images-tab">
<Tab sx={BASE_STYLES} _selected={SELECTED_STYLES} onPointerUp={handleClickImages} data-testid="images-tab">
{t('parameters.images')}
</Tab>
<Tab sx={BASE_STYLES} _selected={SELECTED_STYLES} onClick={handleClickAssets} data-testid="assets-tab">
<Tab sx={BASE_STYLES} _selected={SELECTED_STYLES} onPointerUp={handleClickAssets} data-testid="assets-tab">
{t('gallery.assets')}
</Tab>
<IconButton
size="sm"
variant="link"
alignSelf="stretch"
onClick={handleClickSearch}
onPointerUp={handleClickSearch}
tooltip={searchDisclosure.isOpen ? `${t('gallery.exitSearch')}` : `${t('gallery.displaySearch')}`}
aria-label={t('gallery.displaySearch')}
icon={<PiMagnifyingGlassBold />}

View File

@@ -56,7 +56,7 @@ const GalleryPanelContent = () => {
<Button
size="sm"
variant="ghost"
onClick={boardsListPanel.toggle}
onPointerUp={boardsListPanel.toggle}
rightIcon={boardsListPanel.isCollapsed ? <PiCaretDownBold /> : <PiCaretUpBold />}
>
{boardsListPanel.isCollapsed ? t('boards.viewBoards') : t('boards.hideBoards')}
@@ -69,7 +69,7 @@ const GalleryPanelContent = () => {
size="sm"
variant="link"
alignSelf="stretch"
onClick={handleClickBoardSearch}
onPointerUp={handleClickBoardSearch}
tooltip={
boardSearchDisclosure.isOpen ? `${t('gallery.exitBoardSearch')}` : `${t('gallery.displayBoardSearch')}`
}

View File

@@ -11,13 +11,13 @@ export const ImageMenuItemChangeBoard = memo(() => {
const dispatch = useAppDispatch();
const imageDTO = useImageDTOContext();
const onClick = useCallback(() => {
const onPointerUp = useCallback(() => {
dispatch(imagesToChangeSelected([imageDTO]));
dispatch(isModalOpenChanged(true));
}, [dispatch, imageDTO]);
return (
<MenuItem icon={<PiFoldersBold />} onClickCapture={onClick}>
<MenuItem icon={<PiFoldersBold />} onPointerUpCapture={onPointerUp}>
{t('boards.changeBoard')}
</MenuItem>
);

View File

@@ -10,7 +10,7 @@ export const ImageMenuItemCopy = memo(() => {
const imageDTO = useImageDTOContext();
const { isClipboardAPIAvailable, copyImageToClipboard } = useCopyImageToClipboard();
const onClick = useCallback(() => {
const onPointerUp = useCallback(() => {
copyImageToClipboard(imageDTO.image_url);
}, [copyImageToClipboard, imageDTO.image_url]);
@@ -23,7 +23,7 @@ export const ImageMenuItemCopy = memo(() => {
icon={<PiCopyBold />}
aria-label={t('parameters.copyImage')}
tooltip={t('parameters.copyImage')}
onClickCapture={onClick}
onPointerUpCapture={onPointerUp}
variant="ghost"
colorScheme="base"
/>

View File

@@ -11,14 +11,14 @@ export const ImageMenuItemDelete = memo(() => {
const dispatch = useAppDispatch();
const imageDTO = useImageDTOContext();
const onClick = useCallback(() => {
const onPointerUp = useCallback(() => {
dispatch(imagesToDeleteSelected([imageDTO]));
}, [dispatch, imageDTO]);
return (
<IconButton
icon={<PiTrashSimpleBold />}
onClickCapture={onClick}
onPointerUpCapture={onPointerUp}
aria-label={t('gallery.deleteImage', { count: 1 })}
tooltip={t('gallery.deleteImage', { count: 1 })}
variant="ghost"

View File

@@ -10,7 +10,7 @@ export const ImageMenuItemDownload = memo(() => {
const imageDTO = useImageDTOContext();
const { downloadImage } = useDownloadImage();
const onClick = useCallback(() => {
const onPointerUp = useCallback(() => {
downloadImage(imageDTO.image_url, imageDTO.image_name);
}, [downloadImage, imageDTO.image_name, imageDTO.image_url]);
@@ -21,7 +21,7 @@ export const ImageMenuItemDownload = memo(() => {
tooltip={t('parameters.downloadImage')}
variant="ghost"
colorScheme="base"
onClick={onClick}
onPointerUp={onPointerUp}
/>
);
});

View File

@@ -14,14 +14,14 @@ export const ImageMenuItemLoadWorkflow = memo(() => {
const [getAndLoadEmbeddedWorkflow, { isLoading }] = useGetAndLoadEmbeddedWorkflow();
const hasTemplates = useStore($hasTemplates);
const onClick = useCallback(() => {
const onPointerUp = useCallback(() => {
getAndLoadEmbeddedWorkflow(imageDTO.image_name);
}, [getAndLoadEmbeddedWorkflow, imageDTO.image_name]);
return (
<MenuItem
icon={isLoading ? <SpinnerIcon /> : <PiFlowArrowBold />}
onClickCapture={onClick}
onPointerUpCapture={onPointerUp}
isDisabled={!imageDTO.has_workflow || !hasTemplates}
>
{t('nodes.loadWorkflow')}

View File

@@ -20,19 +20,19 @@ export const ImageMenuItemMetadataRecallActions = memo(() => {
return (
<>
<MenuItem icon={<PiArrowsCounterClockwiseBold />} onClickCapture={remix} isDisabled={!hasMetadata}>
<MenuItem icon={<PiArrowsCounterClockwiseBold />} onPointerUpCapture={remix} isDisabled={!hasMetadata}>
{t('parameters.remixImage')}
</MenuItem>
<MenuItem icon={<PiQuotesBold />} onClickCapture={recallPrompts} isDisabled={!hasPrompts}>
<MenuItem icon={<PiQuotesBold />} onPointerUpCapture={recallPrompts} isDisabled={!hasPrompts}>
{t('parameters.usePrompt')}
</MenuItem>
<MenuItem icon={<PiPlantBold />} onClickCapture={recallSeed} isDisabled={!hasSeed}>
<MenuItem icon={<PiPlantBold />} onPointerUpCapture={recallSeed} isDisabled={!hasSeed}>
{t('parameters.useSeed')}
</MenuItem>
<MenuItem icon={<PiAsteriskBold />} onClickCapture={recallAll} isDisabled={!hasMetadata}>
<MenuItem icon={<PiAsteriskBold />} onPointerUpCapture={recallAll} isDisabled={!hasMetadata}>
{t('parameters.useAll')}
</MenuItem>
<MenuItem icon={<PiPaintBrushBold />} onClickCapture={createAsPreset} isDisabled={!hasPrompts}>
<MenuItem icon={<PiPaintBrushBold />} onPointerUpCapture={createAsPreset} isDisabled={!hasPrompts}>
{t('stylePresets.useForTemplate')}
</MenuItem>
</>

View File

@@ -41,7 +41,7 @@ export const ImageMenuItemNewCanvasFromImage = memo(() => {
}, [bboxRect.x, bboxRect.y, dispatch, imageDTO, imageViewer, t]);
return (
<MenuItem icon={<PiFileBold />} onClickCapture={handleSendToCanvas}>
<MenuItem icon={<PiFileBold />} onPointerUpCapture={handleSendToCanvas}>
{t('controlLayers.newCanvasFromImage')}
</MenuItem>
);

View File

@@ -41,7 +41,7 @@ export const ImageMenuItemNewLayerFromImage = memo(() => {
}, [bboxRect.x, bboxRect.y, dispatch, imageDTO, imageViewer, t]);
return (
<MenuItem icon={<NewLayerIcon />} onClickCapture={handleSendToCanvas}>
<MenuItem icon={<NewLayerIcon />} onPointerUpCapture={handleSendToCanvas}>
{t('controlLayers.newLayerFromImage')}
</MenuItem>
);

View File

@@ -7,13 +7,13 @@ import { PiArrowSquareOutBold } from 'react-icons/pi';
export const ImageMenuItemOpenInNewTab = memo(() => {
const { t } = useTranslation();
const imageDTO = useImageDTOContext();
const onClick = useCallback(() => {
const onPointerUp = useCallback(() => {
window.open(imageDTO.image_url, '_blank');
}, [imageDTO.image_url]);
return (
<IconButton
onClickCapture={onClick}
onPointerUpCapture={onPointerUp}
aria-label={t('common.openInNewTab')}
tooltip={t('common.openInNewTab')}
icon={<PiArrowSquareOutBold />}

View File

@@ -9,14 +9,14 @@ export const ImageMenuItemOpenInViewer = memo(() => {
const { t } = useTranslation();
const imageDTO = useImageDTOContext();
const imageViewer = useImageViewer();
const onClick = useCallback(() => {
const onPointerUp = useCallback(() => {
imageViewer.openImageInViewer(imageDTO);
}, [imageDTO, imageViewer]);
return (
<IconButton
icon={<PiArrowsOutBold />}
onClick={onClick}
onPointerUp={onPointerUp}
aria-label={t('common.openInViewer')}
tooltip={t('common.openInViewer')}
variant="ghost"

View File

@@ -17,7 +17,7 @@ export const ImageMenuItemSelectForCompare = memo(() => {
);
const maySelectForCompare = useAppSelector(selectMaySelectForCompare);
const onClick = useCallback(() => {
const onPointerUp = useCallback(() => {
dispatch(imageToCompareChanged(imageDTO));
}, [dispatch, imageDTO]);
@@ -25,7 +25,7 @@ export const ImageMenuItemSelectForCompare = memo(() => {
<IconButton
icon={<PiImagesBold />}
isDisabled={!maySelectForCompare}
onClick={onClick}
onPointerUp={onPointerUp}
aria-label={t('gallery.selectForCompare')}
tooltip={t('gallery.selectForCompare')}
variant="ghost"

View File

@@ -24,7 +24,7 @@ export const ImageMenuItemSendToUpscale = memo(() => {
}, [dispatch, imageDTO, t]);
return (
<MenuItem icon={<PiShareFatBold />} onClickCapture={handleSendToCanvas} id="send-to-upscale">
<MenuItem icon={<PiShareFatBold />} onPointerUpCapture={handleSendToCanvas} id="send-to-upscale">
{t('parameters.sendToUpscale')}
</MenuItem>
);

View File

@@ -28,14 +28,14 @@ export const ImageMenuItemStarUnstar = memo(() => {
if (imageDTO.starred) {
return (
<MenuItem icon={customStarUi ? customStarUi.off.icon : <PiStarFill />} onClickCapture={unstarImage}>
<MenuItem icon={customStarUi ? customStarUi.off.icon : <PiStarFill />} onPointerUpCapture={unstarImage}>
{customStarUi ? customStarUi.off.text : t('gallery.unstarImage')}
</MenuItem>
);
}
return (
<MenuItem icon={customStarUi ? customStarUi.on.icon : <PiStarBold />} onClickCapture={starImage}>
<MenuItem icon={customStarUi ? customStarUi.on.icon : <PiStarBold />} onPointerUpCapture={starImage}>
{customStarUi ? customStarUi.on.text : t('gallery.starImage')}
</MenuItem>
);

View File

@@ -58,25 +58,25 @@ const MultipleSelectionMenuItems = () => {
return (
<>
{areAllStarred && (
<MenuItem icon={customStarUi ? customStarUi.on.icon : <PiStarBold />} onClickCapture={handleUnstarSelection}>
<MenuItem icon={customStarUi ? customStarUi.on.icon : <PiStarBold />} onPointerUpCapture={handleUnstarSelection}>
{customStarUi ? customStarUi.off.text : `Unstar All`}
</MenuItem>
)}
{(areAllUnstarred || (!areAllStarred && !areAllUnstarred)) && (
<MenuItem icon={customStarUi ? customStarUi.on.icon : <PiStarFill />} onClickCapture={handleStarSelection}>
<MenuItem icon={customStarUi ? customStarUi.on.icon : <PiStarFill />} onPointerUpCapture={handleStarSelection}>
{customStarUi ? customStarUi.on.text : `Star All`}
</MenuItem>
)}
{isBulkDownloadEnabled && (
<MenuItem icon={<PiDownloadSimpleBold />} onClickCapture={handleBulkDownload}>
<MenuItem icon={<PiDownloadSimpleBold />} onPointerUpCapture={handleBulkDownload}>
{t('gallery.downloadSelection')}
</MenuItem>
)}
<MenuItem icon={<PiFoldersBold />} onClickCapture={handleChangeBoard}>
<MenuItem icon={<PiFoldersBold />} onPointerUpCapture={handleChangeBoard}>
{t('boards.changeBoard')}
</MenuItem>
<MenuDivider />
<MenuItem color="error.300" icon={<PiTrashSimpleBold />} onClickCapture={handleDeleteSelection}>
<MenuItem color="error.300" icon={<PiTrashSimpleBold />} onPointerUpCapture={handleDeleteSelection}>
{t('gallery.deleteSelection')}
</MenuItem>
</>

View File

@@ -157,7 +157,7 @@ const GalleryImageContent = memo(({ index, imageDTO }: HoverableImageProps) => {
aspectRatio="1/1"
>
<IAIDndImage
onClick={handleClick}
onPointerUp={handleClick}
onDoubleClick={onDoubleClick}
imageDTO={imageDTO}
draggableData={draggableData}
@@ -191,7 +191,7 @@ const GalleryImageContent = memo(({ index, imageDTO }: HoverableImageProps) => {
>{`${imageDTO.width}x${imageDTO.height}`}</Text>
)}
<IAIDndImageIcon
onClick={toggleStarredState}
onPointerUp={toggleStarredState}
icon={starIcon}
tooltip={starTooltip}
position="absolute"
@@ -213,7 +213,7 @@ const DeleteIcon = ({ imageDTO }: { imageDTO: ImageDTO }) => {
const shift = useShiftModifier();
const { t } = useTranslation();
const dispatch = useAppDispatch();
const onClick = useCallback(
const onPointerUp = useCallback(
(e: MouseEvent<HTMLButtonElement>) => {
e.stopPropagation();
if (!imageDTO) {
@@ -230,7 +230,7 @@ const DeleteIcon = ({ imageDTO }: { imageDTO: ImageDTO }) => {
return (
<IAIDndImageIcon
onClick={onClick}
onPointerUp={onPointerUp}
icon={<PiTrashSimpleFill />}
tooltip={t('gallery.deleteImage_one')}
position="absolute"
@@ -244,13 +244,13 @@ const OpenInViewerIconButton = ({ imageDTO }: { imageDTO: ImageDTO }) => {
const imageViewer = useImageViewer();
const { t } = useTranslation();
const onClick = useCallback(() => {
const onPointerUp = useCallback(() => {
imageViewer.openImageInViewer(imageDTO);
}, [imageDTO, imageViewer]);
return (
<IAIDndImageIcon
onClick={onClick}
onPointerUp={onPointerUp}
icon={<PiArrowsOutBold />}
tooltip={t('gallery.openInViewer')}
position="absolute"

View File

@@ -9,11 +9,11 @@ export const GalleryPagination = () => {
const { goPrev, goNext, isPrevEnabled, isNextEnabled, pageButtons, goToPage, currentPage, total } =
useGalleryPagination();
const onClickPrev = useCallback(() => {
const onPointerUpPrev = useCallback(() => {
goPrev();
}, [goPrev]);
const onClickNext = useCallback(() => {
const onPointerUpNext = useCallback(() => {
goNext();
}, [goNext]);
@@ -27,7 +27,7 @@ export const GalleryPagination = () => {
size="sm"
aria-label="prev"
icon={<PiCaretLeftBold />}
onClick={onClickPrev}
onPointerUp={onPointerUpPrev}
isDisabled={!isPrevEnabled}
variant="ghost"
/>
@@ -40,7 +40,7 @@ export const GalleryPagination = () => {
size="sm"
aria-label="next"
icon={<PiCaretRightBold />}
onClick={onClickNext}
onPointerUp={onPointerUpNext}
isDisabled={!isNextEnabled}
variant="ghost"
/>
@@ -64,7 +64,7 @@ const PageButton = ({ page, currentPage, goToPage }: PageButtonProps) => {
);
}
return (
<Button size="sm" onClick={goToPage.bind(null, page - 1)} variant={currentPage === page - 1 ? 'solid' : 'outline'}>
<Button size="sm" onPointerUp={goToPage.bind(null, page - 1)} variant={currentPage === page - 1 ? 'solid' : 'outline'}>
{page}
</Button>
);

View File

@@ -54,7 +54,7 @@ export const GallerySearch = ({ searchTerm, onChangeSearchTerm, onResetSearchTer
{!isPending && searchTerm.length && (
<InputRightElement h="full" pe={2}>
<IconButton
onClick={onResetSearchTerm}
onPointerUp={onResetSearchTerm}
size="sm"
variant="link"
aria-label={t('boards.clearSearch')}

Some files were not shown because too many files have changed in this diff Show More