Skip to content

Commit

Permalink
improvement: throw if no ref, allow single-item without ref
Browse files Browse the repository at this point in the history
closes #13, #12
  • Loading branch information
irudoy committed Apr 24, 2020
1 parent 59522c6 commit 6dd48e9
Show file tree
Hide file tree
Showing 5 changed files with 95 additions and 29 deletions.
44 changes: 44 additions & 0 deletions src/__tests__/index.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React, { useRef, useState } from 'react'
import PhotoSwipe from 'photoswipe'
import { mount, shallow } from 'enzyme'
import toJson from 'enzyme-to-json'
import { NoRefError } from '../no-ref-error'
import { shuffle } from '../helpers'
import { InternalItem } from '../types'
import { Gallery, GalleryProps, Item, DefaultLayout, LayoutProps } from '..'
Expand Down Expand Up @@ -208,4 +209,47 @@ describe('gallery', () => {
...photoswipeArgsMock(null, 0),
)
})

test('should throw when there is no ref and more than one item', () => {
/* eslint-disable no-console */
const consoleError = console.error
console.error = jest.fn()
const items = createItems(2)
expect(() => {
mount(
<Gallery>
{items.map((item) => (
<Item key={item.original} {...item}>
{({ open }) => <img onClick={open} src={item.thumbnail} />}
</Item>
))}
</Gallery>,
)
.find(Item)
.first()
.simulate('click')
}).toThrow(new NoRefError())
console.error = consoleError
/* eslint-enable no-console */
})

test('should not throw when there is no ref and only one item', () => {
const item: InternalItem = {
original: 'https://placekitten.com/1024/768',
thumbnail: 'https://placekitten.com/160/120',
width: 1024,
height: 768,
}
const wrapper = mount(
<Gallery>
<Item {...item}>
{({ open }) => <img onClick={open} src={item.thumbnail} />}
</Item>
</Gallery>,
)
wrapper.find(Item).first().simulate('click')
expect(PhotoSwipeMocked).toHaveBeenCalledWith(
...photoswipeArgsMock(null, 0),
)
})
})
55 changes: 30 additions & 25 deletions src/gallery.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
layoutDefaultProps,
LayoutProps,
} from '.'
import { getElBounds } from './helpers'
import { getElBounds, sortNodes } from './helpers'
import { Context } from './context'
import { ItemRef, InternalItem } from './types'

Expand Down Expand Up @@ -68,31 +68,36 @@ export const Gallery: FC<GalleryProps> = ({

const normalized: PhotoSwipeItem[] = []

Array.from(items.current)
.sort(([{ current: a }], [{ current: b }]) => {
if (a === b) return 0
// eslint-disable-next-line no-bitwise
if (a.compareDocumentPosition(b) & 2) {
return 1
}
return -1
const entries = Array.from(items.current)

const prepare = (entry: [ItemRef, InternalItem], i: number) => {
const [
ref,
{ width, height, title, original, thumbnail, ...rest },
] = entry

if (targetRef === ref) {
index = i
}

normalized.push({
...(title ? { title } : {}),
w: Number(width),
h: Number(height),
src: original,
msrc: thumbnail,
el: ref.current,
...rest,
})
.forEach(
([ref, { width, height, title, original, thumbnail, ...rest }], i) => {
if (targetRef === ref) {
index = i
}
normalized.push({
...(title ? { title } : {}),
w: Number(width),
h: Number(height),
src: original,
msrc: thumbnail,
el: ref.current,
...rest,
})
},
)
}

if (items.current.size > 1) {
entries
.sort(([{ current: a }], [{ current: b }]) => sortNodes(a, b))
.forEach(prepare)
} else {
entries.forEach(prepare)
}

const layoutEl = defaultLayoutRef.current || layoutRef?.current

Expand Down
14 changes: 14 additions & 0 deletions src/helpers.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { NoRefError } from './no-ref-error'

export const getElBounds = (el: HTMLImageElement) => {
const pageXScroll = window.pageXOffset || document.documentElement.scrollLeft
const pageYScroll = window.pageYOffset || document.documentElement.scrollTop
Expand All @@ -9,6 +11,18 @@ export const getElBounds = (el: HTMLImageElement) => {
}
}

export function sortNodes(a?: Element, b?: Element) {
if (!(a instanceof Element)) {
throw new NoRefError()
}
if (a === b) return 0
// eslint-disable-next-line no-bitwise
if (a.compareDocumentPosition(b) & 2) {
return 1
}
return -1
}

export function shuffle<T>(array: T[]) {
const result = [...array]
let currentIndex = result.length
Expand Down
5 changes: 1 addition & 4 deletions src/index.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -161,16 +161,13 @@ export const withHtml = () => {
return (
<Gallery options={{ showAnimationDuration: 0, hideAnimationDuration: 0 }}>
<Item html={html}>
{(
{ ref, open }, // TODO: only one item, remove ref
) => (
{({ open }) => (
<a
href="#"
onClick={(e) => {
e.preventDefault()
open()
}}
ref={ref as React.MutableRefObject<HTMLAnchorElement>}
>
Open
</a>
Expand Down
6 changes: 6 additions & 0 deletions src/no-ref-error.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export class NoRefError extends Error {
message = `No valid \`ref\` provided.
You shuld use \`ref\` from render prop of Item component.
Example:
<Item>{({ ref }) => <div ref={ref}></div>}</Item>\n`
}

0 comments on commit 6dd48e9

Please sign in to comment.