From 2d34372eaffc812fa24f491b1134c2a4c5e72e1a Mon Sep 17 00:00:00 2001 From: Jonathan Neuteboom <--global> Date: Fri, 28 Nov 2025 09:26:45 +0100 Subject: [PATCH 1/2] Add canCrop function to Lightbox --- package.json | 2 +- src/components/Lightbox.tsx | 13 +- src/components/__tests__/Lightbox.test.tsx | 48 + .../__snapshots__/Lightbox.test.tsx.snap | 1425 +++++++++++++++-- 4 files changed, 1346 insertions(+), 142 deletions(-) diff --git a/package.json b/package.json index 9d11b94..fe8e568 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@observation.org/react-native-components", - "version": "1.60.0", + "version": "1.61.0", "main": "src/index.ts", "repository": "git@github.com:observation/react-native-components.git", "author": "Observation.org", diff --git a/src/components/Lightbox.tsx b/src/components/Lightbox.tsx index 0625daa..097ca50 100644 --- a/src/components/Lightbox.tsx +++ b/src/components/Lightbox.tsx @@ -89,6 +89,7 @@ type Props = { onClose: () => void onDelete?: (imageIndex: number) => void onCrop?: (imageIndex: number) => void + canCrop?: (imageIndex: number) => boolean photos: string[] title?: string description?: string @@ -96,12 +97,14 @@ type Props = { style?: LightboxStyle } -const Lightbox = ({ index, onClose, onDelete, onCrop, photos, title, description, content, style }: Props) => { +const Lightbox = ({ index, onClose, onDelete, onCrop, canCrop, photos, title, description, content, style }: Props) => { const initialImageIndex = index ?? 0 const [currentImageIndex, setCurrentImageIndex] = useState() - const onPressDelete = onDelete ? () => onDelete(currentImageIndex ?? initialImageIndex) : undefined - const onPressCrop = onCrop ? () => onCrop(currentImageIndex ?? initialImageIndex) : undefined + const imageIndex = currentImageIndex ?? initialImageIndex + const onPressDelete = onDelete ? () => onDelete(imageIndex) : undefined + const onPressCrop = onCrop ? () => onCrop(imageIndex) : undefined + const showCrop = canCrop ? canCrop(imageIndex) : true const ImageViewTypeErased = ImageView as unknown as any @@ -117,10 +120,10 @@ const Lightbox = ({ index, onClose, onDelete, onCrop, photos, title, description FooterComponent={getLightboxFooterComponent( title, description, - content?.(currentImageIndex), + content?.(imageIndex), style, onPressDelete, - onPressCrop, + showCrop ? onPressCrop : undefined, )} /> ) diff --git a/src/components/__tests__/Lightbox.test.tsx b/src/components/__tests__/Lightbox.test.tsx index 3587c82..9c408dc 100644 --- a/src/components/__tests__/Lightbox.test.tsx +++ b/src/components/__tests__/Lightbox.test.tsx @@ -103,6 +103,33 @@ describe('Lightbox', () => { expect(queryByTestId('crop-photo')).not.toBeNull() expect(toJSON()).toMatchSnapshot() }) + + test('Do not show crop button when canCrop returns false', () => { + const { toJSON, queryByTestId } = render( + {}} canCrop={() => false} />, + ) + + expect(queryByTestId('crop-photo')).toBeNull() + expect(toJSON()).toMatchSnapshot() + }) + + test('Show crop button when canCrop returns true', () => { + const { toJSON, queryByTestId } = render( + {}} canCrop={() => true} />, + ) + + expect(queryByTestId('crop-photo')).not.toBeNull() + expect(toJSON()).toMatchSnapshot() + }) + + test('When canCrop returns true, but no onCrop is provided, show no crop button', () => { + const { toJSON, queryByTestId } = render( + true} />, + ) + + expect(queryByTestId('crop-photo')).toBeNull() + expect(toJSON()).toMatchSnapshot() + }) }) describe('Interaction', () => { @@ -155,5 +182,26 @@ describe('Lightbox', () => { // THEN expect(onDelete).toHaveBeenCalledWith(1) }) + + test('When swiping to a photo that is not cropable, the crop button is not shown', async () => { + // GIVEN + jest.mock('@observation.org/react-native-image-viewing', () => 'ImageCarousel') + const { queryByTestId } = render( + {}} + canCrop={(imageIndex) => imageIndex === 0} + />, + ) + expect(queryByTestId('crop-photo')).not.toBeNull() + + // WHEN + act(() => mockOnImageIndexChange(1)) + + // THEN + expect(queryByTestId('crop-photo')).toBeNull() + }) }) }) diff --git a/src/components/__tests__/__snapshots__/Lightbox.test.tsx.snap b/src/components/__tests__/__snapshots__/Lightbox.test.tsx.snap index 037e433..a958d25 100644 --- a/src/components/__tests__/__snapshots__/Lightbox.test.tsx.snap +++ b/src/components/__tests__/__snapshots__/Lightbox.test.tsx.snap @@ -435,7 +435,7 @@ exports[`Lightbox Rendering Content that is dependent on the selected image 1`] `; -exports[`Lightbox Rendering First photo 1`] = ` +exports[`Lightbox Rendering Do not show crop button when canCrop returns false 1`] = ` - - - Grey Wagtail - - - - - 11/26/2020 2:37 PM - - - + /> `; -exports[`Lightbox Rendering Only a photo 1`] = ` +exports[`Lightbox Rendering First photo 1`] = ` + > + + + Grey Wagtail + + + + + 11/26/2020 2:37 PM + + + `; -exports[`Lightbox Rendering Photo with species name, date and user 1`] = ` +exports[`Lightbox Rendering Only a photo 1`] = ` - - - Grey Wagtail - - - - - 11/26/2020 2:37 PM - - - - - Jan de Vogelaar - - - + /> `; -exports[`Lightbox Rendering Second photo 1`] = ` +exports[`Lightbox Rendering Photo with species name, date and user 1`] = ` - + - + + + + Jan de Vogelaar + + @@ -2034,6 +1986,1207 @@ exports[`Lightbox Rendering Second photo 1`] = ` `; +exports[`Lightbox Rendering Second photo 1`] = ` + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Grey Wagtail + + + + + 11/26/2020 2:37 PM + + + + + + + +`; + +exports[`Lightbox Rendering Show crop button when canCrop returns true 1`] = ` + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +`; + +exports[`Lightbox Rendering When canCrop returns true, but no onCrop is provided, show no crop button 1`] = ` + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +`; + exports[`Lightbox Rendering With a crop button 1`] = ` Date: Mon, 1 Dec 2025 11:23:45 +0100 Subject: [PATCH 2/2] Rename canCrop to editable --- src/components/Lightbox.tsx | 17 ++++++++++++++--- src/components/__tests__/Lightbox.test.tsx | 14 +++++++------- .../__snapshots__/Lightbox.test.tsx.snap | 6 +++--- 3 files changed, 24 insertions(+), 13 deletions(-) diff --git a/src/components/Lightbox.tsx b/src/components/Lightbox.tsx index 097ca50..05cb275 100644 --- a/src/components/Lightbox.tsx +++ b/src/components/Lightbox.tsx @@ -89,7 +89,7 @@ type Props = { onClose: () => void onDelete?: (imageIndex: number) => void onCrop?: (imageIndex: number) => void - canCrop?: (imageIndex: number) => boolean + editable?: (imageIndex: number) => boolean photos: string[] title?: string description?: string @@ -97,14 +97,25 @@ type Props = { style?: LightboxStyle } -const Lightbox = ({ index, onClose, onDelete, onCrop, canCrop, photos, title, description, content, style }: Props) => { +const Lightbox = ({ + index, + onClose, + onDelete, + onCrop, + editable, + photos, + title, + description, + content, + style, +}: Props) => { const initialImageIndex = index ?? 0 const [currentImageIndex, setCurrentImageIndex] = useState() const imageIndex = currentImageIndex ?? initialImageIndex const onPressDelete = onDelete ? () => onDelete(imageIndex) : undefined const onPressCrop = onCrop ? () => onCrop(imageIndex) : undefined - const showCrop = canCrop ? canCrop(imageIndex) : true + const showCrop = editable ? editable(imageIndex) : true const ImageViewTypeErased = ImageView as unknown as any diff --git a/src/components/__tests__/Lightbox.test.tsx b/src/components/__tests__/Lightbox.test.tsx index 9c408dc..09dc1c2 100644 --- a/src/components/__tests__/Lightbox.test.tsx +++ b/src/components/__tests__/Lightbox.test.tsx @@ -104,27 +104,27 @@ describe('Lightbox', () => { expect(toJSON()).toMatchSnapshot() }) - test('Do not show crop button when canCrop returns false', () => { + test('Do not show crop button when editable returns false', () => { const { toJSON, queryByTestId } = render( - {}} canCrop={() => false} />, + {}} editable={() => false} />, ) expect(queryByTestId('crop-photo')).toBeNull() expect(toJSON()).toMatchSnapshot() }) - test('Show crop button when canCrop returns true', () => { + test('Show crop button when editable returns true', () => { const { toJSON, queryByTestId } = render( - {}} canCrop={() => true} />, + {}} editable={() => true} />, ) expect(queryByTestId('crop-photo')).not.toBeNull() expect(toJSON()).toMatchSnapshot() }) - test('When canCrop returns true, but no onCrop is provided, show no crop button', () => { + test('When editable returns true, but no onCrop is provided, show no crop button', () => { const { toJSON, queryByTestId } = render( - true} />, + true} />, ) expect(queryByTestId('crop-photo')).toBeNull() @@ -192,7 +192,7 @@ describe('Lightbox', () => { index={0} onClose={onClose} onCrop={() => {}} - canCrop={(imageIndex) => imageIndex === 0} + editable={(imageIndex) => imageIndex === 0} />, ) expect(queryByTestId('crop-photo')).not.toBeNull() diff --git a/src/components/__tests__/__snapshots__/Lightbox.test.tsx.snap b/src/components/__tests__/__snapshots__/Lightbox.test.tsx.snap index a958d25..d444eab 100644 --- a/src/components/__tests__/__snapshots__/Lightbox.test.tsx.snap +++ b/src/components/__tests__/__snapshots__/Lightbox.test.tsx.snap @@ -435,7 +435,7 @@ exports[`Lightbox Rendering Content that is dependent on the selected image 1`] `; -exports[`Lightbox Rendering Do not show crop button when canCrop returns false 1`] = ` +exports[`Lightbox Rendering Do not show crop button when editable returns false 1`] = ` `; -exports[`Lightbox Rendering Show crop button when canCrop returns true 1`] = ` +exports[`Lightbox Rendering Show crop button when editable returns true 1`] = ` `; -exports[`Lightbox Rendering When canCrop returns true, but no onCrop is provided, show no crop button 1`] = ` +exports[`Lightbox Rendering When editable returns true, but no onCrop is provided, show no crop button 1`] = `