diff --git a/README.md b/README.md index 0001992..c679f4e 100644 --- a/README.md +++ b/README.md @@ -78,7 +78,7 @@ If you're new to hooks, the example might seem verbose; however, we can easily a > **Note:** React 16.8 is a peer dependency of react-accessible-shuttle which means we can use hooks! However, if, for some reason, you find yourself stubbing 16.8 APIs so you can use newer stuff without upgrading, then you could possibly make things work :astonished: -Not on the hooks train yet? No worries. `react-accessible-shuttle` depends in React 16.8.0+ so if you have that, then you can use without hooks (i.e. in a `class` component) with a some extra effort :smiley: (although we should really use hooks because they make our live much easier). +Not on the hooks train yet? No worries. `react-accessible-shuttle` depends in React 16.8.0+ so if you have that, then you can use without hooks (i.e. in a `class` component) with a some extra effort :smiley: (although we should really use hooks because they make our lives much easier). Here are the things that need to be done: @@ -208,7 +208,7 @@ function App() { if (action.type === 'SELECT_FIRST_ITEM') { // this is bad, since we use action.container to perform a lookup // in the state object, it becomes critical that it's present - if (action.container !== 'source' || action.container !== 'target') { + if (action.container !== 'source' && action.container !== 'target') { throw new Error('Missing container from SELECT_FIRST_ITEM reducer'); } @@ -236,7 +236,7 @@ function App() { return ( { - shuttle.setShuttleState(shuttle.state, { + shuttle.setShuttleState({ type: 'SELECT_FIRST_ITEM', container: 'source', }); diff --git a/package-lock.json b/package-lock.json index e64d3bc..691c30c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "react-accessible-shuttle", - "version": "1.0.0", + "version": "0.0.1", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -1476,9 +1476,9 @@ } }, "@types/jest": { - "version": "24.0.15", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-24.0.15.tgz", - "integrity": "sha512-MU1HIvWUme74stAoc3mgAi+aMlgKOudgEvQDIm1v4RkrDudBh1T+NFp5sftpBAdXdx1J0PbdpJ+M2EsSOi1djA==", + "version": "24.0.16", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-24.0.16.tgz", + "integrity": "sha512-JrAiyV+PPGKZzw6uxbI761cHZ0G7QMOHXPhtSpcl08rZH6CswXaaejckn3goFKmF7M3nzEoJ0lwYCbqLMmjziQ==", "dev": true, "requires": { "@types/jest-diff": "*" @@ -1515,9 +1515,9 @@ "dev": true }, "@types/react": { - "version": "16.8.23", - "resolved": "https://registry.npmjs.org/@types/react/-/react-16.8.23.tgz", - "integrity": "sha512-abkEOIeljniUN9qB5onp++g0EY38h7atnDHxwKUFz1r3VH1+yG1OKi2sNPTyObL40goBmfKFpdii2lEzwLX1cA==", + "version": "16.8.24", + "resolved": "https://registry.npmjs.org/@types/react/-/react-16.8.24.tgz", + "integrity": "sha512-VpFHUoD37YNY2+lr/+c7qL/tZsIU/bKuskUF3tmGUArbxIcQdb5j3zvo4cuuzu2A6UaVmVn7sJ4PgWYNFEBGzg==", "dev": true, "requires": { "@types/prop-types": "*", @@ -8224,9 +8224,9 @@ } }, "sass": { - "version": "1.22.7", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.22.7.tgz", - "integrity": "sha512-ahREi0AdG7RTovSv14+yd1prQSfIvFcrDpOsth5EQf1+RM7SvOxsSttzNQaFmK1aa/k/3vyYwlYF5l0Xl+6c+g==", + "version": "1.22.9", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.22.9.tgz", + "integrity": "sha512-FzU1X2V8DlnqabrL4u7OBwD2vcOzNMongEJEx3xMEhWY/v26FFR3aG0hyeu2T965sfR0E9ufJwmG+Qjz78vFPQ==", "dev": true, "requires": { "chokidar": ">=2.0.0 <4.0.0" diff --git a/package.json b/package.json index 2aa67e2..26471f4 100644 --- a/package.json +++ b/package.json @@ -1,14 +1,15 @@ { "name": "react-accessible-shuttle", - "version": "1.0.0", + "version": "0.0.1", "description": "", "main": "index.js", "scripts": { "test": "jest --silent", - "build": "npm run clean && pack build && npm run build:css", - "build:css": "mkdirp pkg/styles && sass -s compressed --embed-source-map src/styles/** pkg/css/shuttle.css", + "build": "npm run clean && npm run build:css && pack build && npm run clean:css", + "build:css": "sass -s compressed --embed-source-map src/styles/** ./css/shuttle.css", "build:test": "npm run clean && tsc src/index.ts --pretty --jsx react --esModuleInterop --outDir pkg", - "clean": "rimraf pkg/**" + "clean": "rimraf pkg/**", + "clean:css": "rimraf ./css" }, "@pika/pack": { "pipeline": [ @@ -33,6 +34,14 @@ }, "sourcemap": true } + ], + [ + "@pika/plugin-copy-assets", + { + "files": [ + "css/" + ] + } ] ] }, @@ -63,8 +72,8 @@ "@testing-library/jest-dom": "^4.0.0", "@testing-library/react": "^8.0.7", "@types/classnames": "^2.2.9", - "@types/jest": "^24.0.15", - "@types/react": "^16.8.23", + "@types/jest": "^24.0.16", + "@types/react": "^16.8.24", "@types/react-dom": "^16.8.5", "concurrently": "^4.1.1", "core-js": "^3.1.4", @@ -78,7 +87,7 @@ "react-dom": "^16.8.6", "react-window": "^1.8.5", "rimraf": "^2.6.3", - "sass": "^1.22.7", + "sass": "^1.22.9", "ts-jest": "^24.0.2", "typescript": "^3.5.3" }, diff --git a/src/components/Shuttle/ShuttleContainer.tsx b/src/components/Shuttle/ShuttleContainer.tsx index 500a966..67aa7f1 100644 --- a/src/components/Shuttle/ShuttleContainer.tsx +++ b/src/components/Shuttle/ShuttleContainer.tsx @@ -29,6 +29,8 @@ type ShuttleContainerProps = { * for CSS styles. */ className?: string; + + [key: string]: any; }; /** diff --git a/src/components/Shuttle/__tests__/Shuttle.test.tsx b/src/components/Shuttle/__tests__/Shuttle.test.tsx index 9042bf9..a94150e 100644 --- a/src/components/Shuttle/__tests__/Shuttle.test.tsx +++ b/src/components/Shuttle/__tests__/Shuttle.test.tsx @@ -1,5 +1,6 @@ import * as React from 'react'; import { render, cleanup, fireEvent, act, getByTestId } from '@testing-library/react'; +import '@testing-library/jest-dom/extend-expect'; import { Shuttle, ShuttleState } from '../Shuttle'; import { useShuttleState } from '../hooks/useShuttleState'; @@ -183,7 +184,11 @@ describe('Shuttle tests', () => { {() => ( <> - + )} @@ -217,4 +222,92 @@ describe('Shuttle tests', () => { expect(getByTestId('target_container').children.length).toEqual(10); }); }); + + describe('should expose a reducer API', () => { + it('should execute custom reducers', () => { + function App() { + const shuttle = useShuttleState( + { + source: ['a', 'b', 'c'], + target: ['d', 'e', 'f'], + }, + undefined, + undefined, + { + selectFirstItem: (state: any, action: { [key: string]: any } = {}) => { + if (action.type === 'SELECT_FIRST_ITEM') { + if ( + action.container !== 'source' && + action.container !== 'target' + ) { + throw new Error( + 'Missing container from SELECT_FIRST_ITEM reducer' + ); + } + + if (!state[action.container].length) { + console.warn( + `Cannot apply selectFirstItem when ${action.container} is empty` + ); + + return { ...state }; + } + + if (!state.selected[action.container].size) { + state.selected[action.container].add(0); + } + + return { ...state }; + } + + return { ...state }; + }, + } + ); + + return ( + + { + shuttle.setShuttleState({ + type: 'SELECT_FIRST_ITEM', + container: 'source', + }); + }}> + {({ source, selected }, getItemProps) => + source.map((item, index) => ( + + {item} + + )) + } + + + + {({ target, selected }, getItemProps) => + target.map((item, index) => ( + + {item} + + )) + } + + + ); + } + + const { container } = render(); + getByTestId(container, 'source__container').click(); + expect(getByTestId(container, "source__container").children[0]).toHaveClass("shuttle__item--selected"); + }); + }); });