From 5f95402d9965046435e24823ee5f709d8e8f5643 Mon Sep 17 00:00:00 2001 From: fancelin Date: Thu, 30 Mar 2023 10:03:42 -0400 Subject: [PATCH 1/5] Single Row Selection Plugin --- package-lock.json | 12 +- package.json | 8 +- plugins/selection/package-lock.json | 137 +++++++++--------- plugins/singleSelection/README.md | 14 ++ plugins/singleSelection/index.ts | 4 + plugins/singleSelection/package-lock.json | 119 +++++++++++++++ plugins/singleSelection/package.json | 21 +++ .../src/rowSelection/actions.ts | 31 ++++ .../src/rowSelection/rowSelection.tsx | 79 ++++++++++ .../tests/rowSelection/actions.test.ts | 88 +++++++++++ plugins/singleSelection/tsconfig.json | 12 ++ plugins/singleSelection/tsconfig.release.json | 14 ++ plugins/singleSelection/tsconfig.test.json | 7 + tests/dev-server/package-lock.json | 2 +- 14 files changed, 471 insertions(+), 77 deletions(-) create mode 100644 plugins/singleSelection/README.md create mode 100644 plugins/singleSelection/index.ts create mode 100644 plugins/singleSelection/package-lock.json create mode 100644 plugins/singleSelection/package.json create mode 100644 plugins/singleSelection/src/rowSelection/actions.ts create mode 100644 plugins/singleSelection/src/rowSelection/rowSelection.tsx create mode 100644 plugins/singleSelection/tests/rowSelection/actions.test.ts create mode 100644 plugins/singleSelection/tsconfig.json create mode 100644 plugins/singleSelection/tsconfig.release.json create mode 100644 plugins/singleSelection/tsconfig.test.json diff --git a/package-lock.json b/package-lock.json index 2f88b333..cd3c2532 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4303,9 +4303,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001441", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001441.tgz", - "integrity": "sha512-OyxRR4Vof59I3yGWXws6i908EtGbMzVUi3ganaZQHmydk1iwDhRnvaPG2WaR0KcqrDFKrxVZHULT396LEPhXfg==", + "version": "1.0.30001469", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001469.tgz", + "integrity": "sha512-Rcp7221ScNqQPP3W+lVOYDyjdR6dC+neEQCttoNr5bAyz54AboB4iwpnWgyi8P4YUsPybVzT4LgWiBbI3drL4g==", "dev": true, "funding": [ { @@ -16980,9 +16980,9 @@ } }, "caniuse-lite": { - "version": "1.0.30001441", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001441.tgz", - "integrity": "sha512-OyxRR4Vof59I3yGWXws6i908EtGbMzVUi3ganaZQHmydk1iwDhRnvaPG2WaR0KcqrDFKrxVZHULT396LEPhXfg==", + "version": "1.0.30001469", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001469.tgz", + "integrity": "sha512-Rcp7221ScNqQPP3W+lVOYDyjdR6dC+neEQCttoNr5bAyz54AboB4iwpnWgyi8P4YUsPybVzT4LgWiBbI3drL4g==", "dev": true }, "caseless": { diff --git a/package.json b/package.json index 2207908a..f9e46841 100644 --- a/package.json +++ b/package.json @@ -49,6 +49,12 @@ "import": "./plugins/selection/dist/selection.mjs", "require": "./plugins/selection/dist/selection.js" }, + "./plugins/single-selection": { + "browser": "./plugins/selection/dist/single.selection.module.js", + "umd": "./plugins/selection/dist/single.selection.umd.js", + "import": "./plugins/selection/dist/single.selection.mjs", + "require": "./plugins/selection/dist/single.selection.js" + }, "./package.json": "./package.json", "./": "./" }, @@ -107,7 +113,7 @@ "build:grid": "microbundle build --raw --external none --tsconfig tsconfig.release.json", "build:i18n": "microbundle build --raw --cwd l10n --tsconfig l10n/tsconfig.release.json", "build:watch": "npm run build:grid -- -w", - "build:plugins": "microbundle build --raw --cwd plugins/selection --tsconfig plugins/selection/tsconfig.release.json", + "build:plugins": "microbundle build --raw --cwd plugins/selection --tsconfig plugins/selection/tsconfig.release.json && microbundle build --raw --cwd plugins/singleSelection --tsconfig plugins/singleSelection/tsconfig.release.json", "postbuild": "node build/node-13-exports.js", "prebuild:themes": "sass src/theme/mermaid/index.scss dist/theme/mermaid.css", "build:themes-dev": "postcss dist/theme/mermaid.css --output dist/theme/mermaid.css --env development --verbose", diff --git a/plugins/selection/package-lock.json b/plugins/selection/package-lock.json index 26eb0ab8..08c8e0c9 100644 --- a/plugins/selection/package-lock.json +++ b/plugins/selection/package-lock.json @@ -5,6 +5,7 @@ "requires": true, "packages": { "": { + "name": "selection", "version": "4.0.0", "license": "MIT", "dependencies": { @@ -12,54 +13,53 @@ } }, "../..": { - "version": "5.0.2", + "version": "6.0.6", "license": "MIT", "dependencies": { - "preact": "^10.5.12", - "tslib": "^2.0.1" + "preact": "^10.11.3" }, "devDependencies": { - "@types/enzyme": "^3.10.5", - "@types/jest": "^26.0.0", - "@types/jest-axe": "^3.2.2", - "@types/node": "^15.3.0", - "@typescript-eslint/eslint-plugin": "~4.28.0", - "@typescript-eslint/parser": "~4.28.0", - "autoprefixer": "^9.8.0", - "axe-core": "^4.0.0", + "@types/enzyme": "^3.10.12", + "@types/jest": "^29.2.4", + "@types/jest-axe": "^3.5.5", + "@types/node": "^18.11.17", + "@typescript-eslint/eslint-plugin": "^5.47.0", + "@typescript-eslint/parser": "^5.47.0", + "autoprefixer": "^10.4.8", + "axe-core": "^4.4.2", "check-export-map": "^1.1.1", "cssnano": "^5.0.5", - "cypress": "^7.4.0", + "cypress": "^8.1.0", "cypress-visual-regression": "^1.5.7", "enzyme": "^3.11.0", - "enzyme-adapter-preact-pure": "^3.0.0", - "eslint": "~7.29.0", - "eslint-config-prettier": "^6.11.0", - "eslint-plugin-jest": "~24.3.2", + "enzyme-adapter-preact-pure": "^4.0.1", + "eslint": "^8.18.0", + "eslint-config-prettier": "^8.5.0", + "eslint-plugin-jest": "~26.8.7", "identity-obj-proxy": "^3.0.0", - "jest": "~27.0.6", - "jest-axe": "^5.0.1", - "jest-extended": "^0.11.5", - "jsdom": "^16.2.2", + "jest": "^29.3.1", + "jest-axe": "^6.0.0", + "jest-extended": "^3.2.0", + "jsdom": "^19.0.0", "jsdom-global": "^3.0.2", - "lerna-changelog": "^1.0.1", - "microbundle": "^0.13.0", - "node-sass": "^6.0.1", - "node-sass-chokidar": "^1.5.0", + "lerna-changelog": "^2.1.0", + "microbundle": "^0.15.1", "npm-run-all": "^4.1.5", - "postcss": "^8.3.0", - "postcss-cli": "^8.3.1", - "postcss-nested": "^5.0.5", - "postcss-scss": "^4.0.0", - "postcss-sort-media-queries": "^3.10.11", - "prettier": "~2.3.1", + "postcss": "^8.4.16", + "postcss-cli": "^9.1.0", + "postcss-nested": "^5.0.6", + "postcss-scss": "^4.0.4", + "postcss-sort-media-queries": "^4.1.0", + "prettier": "~2.7.1", "rimraf": "~3.0.2", - "source-map-loader": "^2.0.1", + "sass": "^1.54.5", + "source-map-loader": "^4.0.0", "start-server-and-test": "^1.12.3", - "ts-jest": "^27.0.3", - "ts-loader": "^9.1.1", - "tsutils": "~3.21.0", - "typescript": "^4.2.4" + "ts-jest": "^29.0.3", + "ts-loader": "^9.4.2", + "tslib": "^2.4.1", + "tsutils": "^3.21.0", + "typescript": "^4.9.4" } }, "node_modules/gridjs": { @@ -71,49 +71,48 @@ "gridjs": { "version": "file:../..", "requires": { - "@types/enzyme": "^3.10.5", - "@types/jest": "^26.0.0", - "@types/jest-axe": "^3.2.2", - "@types/node": "^15.3.0", - "@typescript-eslint/eslint-plugin": "~4.28.0", - "@typescript-eslint/parser": "~4.28.0", - "autoprefixer": "^9.8.0", - "axe-core": "^4.0.0", + "@types/enzyme": "^3.10.12", + "@types/jest": "^29.2.4", + "@types/jest-axe": "^3.5.5", + "@types/node": "^18.11.17", + "@typescript-eslint/eslint-plugin": "^5.47.0", + "@typescript-eslint/parser": "^5.47.0", + "autoprefixer": "^10.4.8", + "axe-core": "^4.4.2", "check-export-map": "^1.1.1", "cssnano": "^5.0.5", - "cypress": "^7.4.0", + "cypress": "^8.1.0", "cypress-visual-regression": "^1.5.7", "enzyme": "^3.11.0", - "enzyme-adapter-preact-pure": "^3.0.0", - "eslint": "~7.29.0", - "eslint-config-prettier": "^6.11.0", - "eslint-plugin-jest": "~24.3.2", + "enzyme-adapter-preact-pure": "^4.0.1", + "eslint": "^8.18.0", + "eslint-config-prettier": "^8.5.0", + "eslint-plugin-jest": "~26.8.7", "identity-obj-proxy": "^3.0.0", - "jest": "~27.0.6", - "jest-axe": "^5.0.1", - "jest-extended": "^0.11.5", - "jsdom": "^16.2.2", + "jest": "^29.3.1", + "jest-axe": "^6.0.0", + "jest-extended": "^3.2.0", + "jsdom": "^19.0.0", "jsdom-global": "^3.0.2", - "lerna-changelog": "^1.0.1", - "microbundle": "^0.13.0", - "node-sass": "^6.0.1", - "node-sass-chokidar": "^1.5.0", + "lerna-changelog": "^2.1.0", + "microbundle": "^0.15.1", "npm-run-all": "^4.1.5", - "postcss": "^8.3.0", - "postcss-cli": "^8.3.1", - "postcss-nested": "^5.0.5", - "postcss-scss": "^4.0.0", - "postcss-sort-media-queries": "^3.10.11", - "preact": "^10.5.12", - "prettier": "~2.3.1", + "postcss": "^8.4.16", + "postcss-cli": "^9.1.0", + "postcss-nested": "^5.0.6", + "postcss-scss": "^4.0.4", + "postcss-sort-media-queries": "^4.1.0", + "preact": "^10.11.3", + "prettier": "~2.7.1", "rimraf": "~3.0.2", - "source-map-loader": "^2.0.1", + "sass": "^1.54.5", + "source-map-loader": "^4.0.0", "start-server-and-test": "^1.12.3", - "ts-jest": "^27.0.3", - "ts-loader": "^9.1.1", - "tslib": "^2.0.1", - "tsutils": "~3.21.0", - "typescript": "^4.2.4" + "ts-jest": "^29.0.3", + "ts-loader": "^9.4.2", + "tslib": "^2.4.1", + "tsutils": "^3.21.0", + "typescript": "^4.9.4" } } } diff --git a/plugins/singleSelection/README.md b/plugins/singleSelection/README.md new file mode 100644 index 00000000..9690d5c1 --- /dev/null +++ b/plugins/singleSelection/README.md @@ -0,0 +1,14 @@ +# `gridjs-selection` + +> Row/cell selection plugin for Grid.js + +## Documentation :book: + +See [Selection plugin](https://gridjs.io/docs/examples/selection) docs on gridjs.io. + +Full documentation of Grid.js installation, config, API and examples are available +on Grid.js website [grid.js/docs](https://gridjs.io/docs/index). + +## License + +[MIT](https://github.com/grid-js/gridjs/blob/master/LICENSE) diff --git a/plugins/singleSelection/index.ts b/plugins/singleSelection/index.ts new file mode 100644 index 00000000..26a0d17c --- /dev/null +++ b/plugins/singleSelection/index.ts @@ -0,0 +1,4 @@ +import { RowSelection } from './src/rowSelection/rowSelection'; +import * as RowSelectionActions from './src/rowSelection/actions'; + +export { RowSelection, RowSelectionActions }; diff --git a/plugins/singleSelection/package-lock.json b/plugins/singleSelection/package-lock.json new file mode 100644 index 00000000..08c8e0c9 --- /dev/null +++ b/plugins/singleSelection/package-lock.json @@ -0,0 +1,119 @@ +{ + "name": "selection", + "version": "4.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "selection", + "version": "4.0.0", + "license": "MIT", + "dependencies": { + "gridjs": "../../" + } + }, + "../..": { + "version": "6.0.6", + "license": "MIT", + "dependencies": { + "preact": "^10.11.3" + }, + "devDependencies": { + "@types/enzyme": "^3.10.12", + "@types/jest": "^29.2.4", + "@types/jest-axe": "^3.5.5", + "@types/node": "^18.11.17", + "@typescript-eslint/eslint-plugin": "^5.47.0", + "@typescript-eslint/parser": "^5.47.0", + "autoprefixer": "^10.4.8", + "axe-core": "^4.4.2", + "check-export-map": "^1.1.1", + "cssnano": "^5.0.5", + "cypress": "^8.1.0", + "cypress-visual-regression": "^1.5.7", + "enzyme": "^3.11.0", + "enzyme-adapter-preact-pure": "^4.0.1", + "eslint": "^8.18.0", + "eslint-config-prettier": "^8.5.0", + "eslint-plugin-jest": "~26.8.7", + "identity-obj-proxy": "^3.0.0", + "jest": "^29.3.1", + "jest-axe": "^6.0.0", + "jest-extended": "^3.2.0", + "jsdom": "^19.0.0", + "jsdom-global": "^3.0.2", + "lerna-changelog": "^2.1.0", + "microbundle": "^0.15.1", + "npm-run-all": "^4.1.5", + "postcss": "^8.4.16", + "postcss-cli": "^9.1.0", + "postcss-nested": "^5.0.6", + "postcss-scss": "^4.0.4", + "postcss-sort-media-queries": "^4.1.0", + "prettier": "~2.7.1", + "rimraf": "~3.0.2", + "sass": "^1.54.5", + "source-map-loader": "^4.0.0", + "start-server-and-test": "^1.12.3", + "ts-jest": "^29.0.3", + "ts-loader": "^9.4.2", + "tslib": "^2.4.1", + "tsutils": "^3.21.0", + "typescript": "^4.9.4" + } + }, + "node_modules/gridjs": { + "resolved": "../..", + "link": true + } + }, + "dependencies": { + "gridjs": { + "version": "file:../..", + "requires": { + "@types/enzyme": "^3.10.12", + "@types/jest": "^29.2.4", + "@types/jest-axe": "^3.5.5", + "@types/node": "^18.11.17", + "@typescript-eslint/eslint-plugin": "^5.47.0", + "@typescript-eslint/parser": "^5.47.0", + "autoprefixer": "^10.4.8", + "axe-core": "^4.4.2", + "check-export-map": "^1.1.1", + "cssnano": "^5.0.5", + "cypress": "^8.1.0", + "cypress-visual-regression": "^1.5.7", + "enzyme": "^3.11.0", + "enzyme-adapter-preact-pure": "^4.0.1", + "eslint": "^8.18.0", + "eslint-config-prettier": "^8.5.0", + "eslint-plugin-jest": "~26.8.7", + "identity-obj-proxy": "^3.0.0", + "jest": "^29.3.1", + "jest-axe": "^6.0.0", + "jest-extended": "^3.2.0", + "jsdom": "^19.0.0", + "jsdom-global": "^3.0.2", + "lerna-changelog": "^2.1.0", + "microbundle": "^0.15.1", + "npm-run-all": "^4.1.5", + "postcss": "^8.4.16", + "postcss-cli": "^9.1.0", + "postcss-nested": "^5.0.6", + "postcss-scss": "^4.0.4", + "postcss-sort-media-queries": "^4.1.0", + "preact": "^10.11.3", + "prettier": "~2.7.1", + "rimraf": "~3.0.2", + "sass": "^1.54.5", + "source-map-loader": "^4.0.0", + "start-server-and-test": "^1.12.3", + "ts-jest": "^29.0.3", + "ts-loader": "^9.4.2", + "tslib": "^2.4.1", + "tsutils": "^3.21.0", + "typescript": "^4.9.4" + } + } + } +} diff --git a/plugins/singleSelection/package.json b/plugins/singleSelection/package.json new file mode 100644 index 00000000..cefbcd57 --- /dev/null +++ b/plugins/singleSelection/package.json @@ -0,0 +1,21 @@ +{ + "name": "singleelection", + "version": "4.0.0", + "private": true, + "description": "Adds row and cell selection to Grid.js", + "author": "Afshin Mehrabani ", + "homepage": "https://gridjs.io/docs/examples/selection", + "license": "MIT", + "source": "index.ts", + "main": "dist/singleselection.js", + "module": "dist/singleselection.module.js", + "umd:main": "dist/singleselection.umd.js", + "amdName": "gridjs.plugins.singleselection", + "types": "dist/singleselection.d.ts", + "files": [ + "dist/*" + ], + "dependencies": { + "gridjs": "../../" + } +} diff --git a/plugins/singleSelection/src/rowSelection/actions.ts b/plugins/singleSelection/src/rowSelection/actions.ts new file mode 100644 index 00000000..5b0ec588 --- /dev/null +++ b/plugins/singleSelection/src/rowSelection/actions.ts @@ -0,0 +1,31 @@ +export const CheckRow = (rowId: string) => (state) => { + const rowIds = state.rowSelection?.rowIds || []; + + // rowId already exists + if (rowIds.indexOf(rowId) > -1) return state; + + return { + ...state, + rowSelection: { + rowIds: [rowId], + }, + }; +}; + +export const UncheckRow = (rowId: string) => (state) => { + const rowIds = state.rowSelection?.rowIds || []; + const index = rowIds.indexOf(rowId); + + // rowId doesn't exist + if (index === -1) return state; + + const cloned = [...rowIds]; + cloned.splice(index, 1); + + return { + ...state, + rowSelection: { + rowIds: cloned, + }, + }; +}; diff --git a/plugins/singleSelection/src/rowSelection/rowSelection.tsx b/plugins/singleSelection/src/rowSelection/rowSelection.tsx new file mode 100644 index 00000000..85125748 --- /dev/null +++ b/plugins/singleSelection/src/rowSelection/rowSelection.tsx @@ -0,0 +1,79 @@ +import { h } from 'preact'; +import * as actions from './actions'; +import { useStore, className, useEffect, useState, useSelector } from 'gridjs'; +import { Row } from 'gridjs'; +import { Cell } from 'gridjs'; + +interface RowSelectionProps { + // it's optional because thead doesn't have a row + row?: Row; + cell?: Cell; +} + + + +export function RowSelection(props: RowSelectionProps) { + const { dispatch } = useStore(); + const state = useSelector((state) => state.rowSelection); + const [isChecked, setIsChecked] = useState(false); + const selectedClassName = className('tr', 'selected'); + const checkboxClassName = className('checkbox'); + const isDataCell = (props) => props.row !== undefined; + const getParentTR = () => + this.base && + this.base.parentElement && + (this.base.parentElement.parentElement as Element); + + useEffect(() => { + // store/dispatcher is required only if we are rendering a TD (not a TH) + if (props.cell?.data && isDataCell(props)) { + // mark this checkbox as checked if cell.data is true + check(); + } + }, []); + + useEffect(() => { + const parent = getParentTR(); + + if (!parent) return; + + const rowIds = state?.rowIds || []; + const isChecked = rowIds.indexOf(props.row.id) > -1; + setIsChecked(isChecked); + + if (isChecked) { + parent.classList.add(selectedClassName); + } else { + parent.classList.remove(selectedClassName); + } + }, [state]); + + const check = () => { + dispatch(actions.CheckRow(props.row.id)); + props.cell?.update(true); + }; + + const uncheck = () => { + dispatch(actions.UncheckRow(props.row.id)); + props.cell?.update(false); + }; + + const toggle = () => { + if (isChecked) { + uncheck(); + } else { + check(); + } + }; + + if (!isDataCell(props)) return null; + + return ( + toggle()} + className={checkboxClassName} + /> + ); +} diff --git a/plugins/singleSelection/tests/rowSelection/actions.test.ts b/plugins/singleSelection/tests/rowSelection/actions.test.ts new file mode 100644 index 00000000..9d3d7b85 --- /dev/null +++ b/plugins/singleSelection/tests/rowSelection/actions.test.ts @@ -0,0 +1,88 @@ +import * as Actions from '../../src/rowSelection/actions'; + +describe('Actions', () => { + it('should trigger CHECK', () => { + const state = Actions.CheckRow('42')({}); + + expect(state).toStrictEqual({ + rowSelection: { + rowIds: ['42'], + }, + }); + }); + + it('should trigger CHECK when rowIds already exists', () => { + const state = Actions.CheckRow('42')({ + rowSelection: { + rowIds: ['24'], + }, + }); + + expect(state).toStrictEqual({ + rowSelection: { + rowIds: ['42', '24'], + }, + }); + }); + + it('should trigger UNCHECK', () => { + const state = Actions.UncheckRow('42')({ + rowSelection: { + rowIds: ['42'], + }, + }); + + expect(state).toStrictEqual({ + rowSelection: { + rowIds: [], + }, + }); + }); + + it('should UNCHECK the correct item', () => { + const state = Actions.UncheckRow('42')({ + rowSelection: { + rowIds: ['22', '11'], + }, + }); + + expect(state).toStrictEqual({ + rowSelection: { + rowIds: ['22', '11'], + }, + }); + }); + + it('should UNCHECK when rowIds is null', () => { + const state = Actions.UncheckRow('42')({}); + + expect(state).toStrictEqual({}); + }); + + it('should trigger UNCHECK when rowIds is empty', () => { + const state = Actions.UncheckRow('42')({ + rowSelection: { + rowIds: [], + }, + }); + + expect(state).toStrictEqual({ + rowSelection: { + rowIds: [], + }, + }); + }); + + it('should CHECK and UNCHECK', () => { + let state = {}; + state = Actions.CheckRow('42')(state); + state = Actions.CheckRow('24')(state); + state = Actions.UncheckRow('42')(state); + + expect(state).toStrictEqual({ + rowSelection: { + rowIds: ['24'], + }, + }); + }); +}); diff --git a/plugins/singleSelection/tsconfig.json b/plugins/singleSelection/tsconfig.json new file mode 100644 index 00000000..a0cc8dcf --- /dev/null +++ b/plugins/singleSelection/tsconfig.json @@ -0,0 +1,12 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "rootDir": ".", + "removeComments": true + }, + "include": [ + "index.ts", + "src/**/*", + "tests/**/*" + ] +} diff --git a/plugins/singleSelection/tsconfig.release.json b/plugins/singleSelection/tsconfig.release.json new file mode 100644 index 00000000..f65dfe8d --- /dev/null +++ b/plugins/singleSelection/tsconfig.release.json @@ -0,0 +1,14 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "rootDir": ".", + "removeComments": true + }, + "include": [ + "index.ts", + "src/**/*" + ], + "exclude": [ + "tests/**/*" + ] +} diff --git a/plugins/singleSelection/tsconfig.test.json b/plugins/singleSelection/tsconfig.test.json new file mode 100644 index 00000000..f5515d65 --- /dev/null +++ b/plugins/singleSelection/tsconfig.test.json @@ -0,0 +1,7 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "types": ["jest"], + "esModuleInterop": true + } +} diff --git a/tests/dev-server/package-lock.json b/tests/dev-server/package-lock.json index e8d5365d..8aa7a5bc 100644 --- a/tests/dev-server/package-lock.json +++ b/tests/dev-server/package-lock.json @@ -19,7 +19,7 @@ } }, "../..": { - "version": "6.0.0", + "version": "6.0.6", "license": "MIT", "dependencies": { "preact": "^10.11.3" From fd84361db0f4d69875519848bc1b5ff312747a58 Mon Sep 17 00:00:00 2001 From: fancelin Date: Thu, 30 Mar 2023 15:13:11 -0400 Subject: [PATCH 2/5] Single Row Implementation --- plugins/singleSelection/index.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/singleSelection/index.ts b/plugins/singleSelection/index.ts index 26a0d17c..d350c87a 100644 --- a/plugins/singleSelection/index.ts +++ b/plugins/singleSelection/index.ts @@ -1,4 +1,4 @@ -import { RowSelection } from './src/rowSelection/rowSelection'; +import { RowSelection, RowSelectionSingle, RowSelectionMultiple } from './src/rowSelection/rowSelection'; import * as RowSelectionActions from './src/rowSelection/actions'; -export { RowSelection, RowSelectionActions }; +export { RowSelection, RowSelectionSingle, RowSelectionMultiple, RowSelectionActions }; From ffe7467122f4b2a3c243a572e62d7bf96cd97a1d Mon Sep 17 00:00:00 2001 From: fancelin Date: Thu, 30 Mar 2023 15:14:14 -0400 Subject: [PATCH 3/5] Single Row Selection Plugin --- .../src/rowSelection/actions.ts | 16 ++++++++++--- .../src/rowSelection/rowSelection.tsx | 23 +++++++++++++++---- 2 files changed, 31 insertions(+), 8 deletions(-) diff --git a/plugins/singleSelection/src/rowSelection/actions.ts b/plugins/singleSelection/src/rowSelection/actions.ts index 5b0ec588..d14337bf 100644 --- a/plugins/singleSelection/src/rowSelection/actions.ts +++ b/plugins/singleSelection/src/rowSelection/actions.ts @@ -1,15 +1,25 @@ -export const CheckRow = (rowId: string) => (state) => { +export const CheckRow = (rowId: string, singleSelection:boolean) => (state) => { const rowIds = state.rowSelection?.rowIds || []; // rowId already exists if (rowIds.indexOf(rowId) > -1) return state; + if (singleSelection){ + return { + ...state, + rowSelection: { + rowIds: [rowId], + }, + }; + } + return { ...state, rowSelection: { - rowIds: [rowId], + rowIds: [rowId, ...rowIds], }, }; + }; export const UncheckRow = (rowId: string) => (state) => { @@ -21,7 +31,7 @@ export const UncheckRow = (rowId: string) => (state) => { const cloned = [...rowIds]; cloned.splice(index, 1); - + return { ...state, rowSelection: { diff --git a/plugins/singleSelection/src/rowSelection/rowSelection.tsx b/plugins/singleSelection/src/rowSelection/rowSelection.tsx index 85125748..3d9b66fa 100644 --- a/plugins/singleSelection/src/rowSelection/rowSelection.tsx +++ b/plugins/singleSelection/src/rowSelection/rowSelection.tsx @@ -10,9 +10,15 @@ interface RowSelectionProps { cell?: Cell; } +export function RowSelectionSingle(props: RowSelectionProps){ + return RowSelection(props, true); +} +export function RowSelectionMultiple(props: RowSelectionProps){ + return RowSelection(props, false); +} -export function RowSelection(props: RowSelectionProps) { +export function RowSelection(props: RowSelectionProps, singleSelect:boolean=false) { const { dispatch } = useStore(); const state = useSelector((state) => state.rowSelection); const [isChecked, setIsChecked] = useState(false); @@ -24,23 +30,30 @@ export function RowSelection(props: RowSelectionProps) { this.base.parentElement && (this.base.parentElement.parentElement as Element); + + const isSingleSelect:boolean = singleSelect; + + useEffect(() => { // store/dispatcher is required only if we are rendering a TD (not a TH) if (props.cell?.data && isDataCell(props)) { // mark this checkbox as checked if cell.data is true check(); } + }, []); useEffect(() => { - const parent = getParentTR(); - - if (!parent) return; const rowIds = state?.rowIds || []; const isChecked = rowIds.indexOf(props.row.id) > -1; + setIsChecked(isChecked); + const parent = getParentTR(); + + if (!parent) return; + if (isChecked) { parent.classList.add(selectedClassName); } else { @@ -49,7 +62,7 @@ export function RowSelection(props: RowSelectionProps) { }, [state]); const check = () => { - dispatch(actions.CheckRow(props.row.id)); + dispatch(actions.CheckRow(props.row.id, isSingleSelect)); props.cell?.update(true); }; From bbc6c5fb9efc0d00287f2ff3bfc27c36093b2161 Mon Sep 17 00:00:00 2001 From: fancelin Date: Sat, 1 Apr 2023 20:17:55 -0400 Subject: [PATCH 4/5] Merge single select with main plugin --- package.json | 2 +- plugins/selection/index.ts | 4 +- plugins/selection/package.json | 2 +- plugins/selection/src/rowSelection/actions.ts | 14 ++- .../src/rowSelection/rowSelection.tsx | 25 +++- plugins/singleSelection/README.md | 14 --- plugins/singleSelection/index.ts | 4 - plugins/singleSelection/package-lock.json | 119 ------------------ plugins/singleSelection/package.json | 21 ---- .../src/rowSelection/actions.ts | 41 ------ .../src/rowSelection/rowSelection.tsx | 92 -------------- .../tests/rowSelection/actions.test.ts | 88 ------------- plugins/singleSelection/tsconfig.json | 12 -- plugins/singleSelection/tsconfig.release.json | 14 --- plugins/singleSelection/tsconfig.test.json | 7 -- 15 files changed, 36 insertions(+), 423 deletions(-) delete mode 100644 plugins/singleSelection/README.md delete mode 100644 plugins/singleSelection/index.ts delete mode 100644 plugins/singleSelection/package-lock.json delete mode 100644 plugins/singleSelection/package.json delete mode 100644 plugins/singleSelection/src/rowSelection/actions.ts delete mode 100644 plugins/singleSelection/src/rowSelection/rowSelection.tsx delete mode 100644 plugins/singleSelection/tests/rowSelection/actions.test.ts delete mode 100644 plugins/singleSelection/tsconfig.json delete mode 100644 plugins/singleSelection/tsconfig.release.json delete mode 100644 plugins/singleSelection/tsconfig.test.json diff --git a/package.json b/package.json index f9e46841..4514dcb5 100644 --- a/package.json +++ b/package.json @@ -113,7 +113,7 @@ "build:grid": "microbundle build --raw --external none --tsconfig tsconfig.release.json", "build:i18n": "microbundle build --raw --cwd l10n --tsconfig l10n/tsconfig.release.json", "build:watch": "npm run build:grid -- -w", - "build:plugins": "microbundle build --raw --cwd plugins/selection --tsconfig plugins/selection/tsconfig.release.json && microbundle build --raw --cwd plugins/singleSelection --tsconfig plugins/singleSelection/tsconfig.release.json", + "build:plugins": "microbundle build --raw --cwd plugins/selection --tsconfig plugins/selection/tsconfig.release.json", "postbuild": "node build/node-13-exports.js", "prebuild:themes": "sass src/theme/mermaid/index.scss dist/theme/mermaid.css", "build:themes-dev": "postcss dist/theme/mermaid.css --output dist/theme/mermaid.css --env development --verbose", diff --git a/plugins/selection/index.ts b/plugins/selection/index.ts index 26a0d17c..6f1a5769 100644 --- a/plugins/selection/index.ts +++ b/plugins/selection/index.ts @@ -1,4 +1,4 @@ -import { RowSelection } from './src/rowSelection/rowSelection'; +import { RowSelection, RowSelectionSingle } from './src/rowSelection/rowSelection'; import * as RowSelectionActions from './src/rowSelection/actions'; -export { RowSelection, RowSelectionActions }; +export { RowSelection, RowSelectionSingle, RowSelectionActions }; diff --git a/plugins/selection/package.json b/plugins/selection/package.json index b47072b7..5c75753a 100644 --- a/plugins/selection/package.json +++ b/plugins/selection/package.json @@ -1,6 +1,6 @@ { "name": "selection", - "version": "4.0.0", + "version": "5.0.0", "private": true, "description": "Adds row and cell selection to Grid.js", "author": "Afshin Mehrabani ", diff --git a/plugins/selection/src/rowSelection/actions.ts b/plugins/selection/src/rowSelection/actions.ts index de8b3944..d14337bf 100644 --- a/plugins/selection/src/rowSelection/actions.ts +++ b/plugins/selection/src/rowSelection/actions.ts @@ -1,15 +1,25 @@ -export const CheckRow = (rowId: string) => (state) => { +export const CheckRow = (rowId: string, singleSelection:boolean) => (state) => { const rowIds = state.rowSelection?.rowIds || []; // rowId already exists if (rowIds.indexOf(rowId) > -1) return state; + if (singleSelection){ + return { + ...state, + rowSelection: { + rowIds: [rowId], + }, + }; + } + return { ...state, rowSelection: { rowIds: [rowId, ...rowIds], }, }; + }; export const UncheckRow = (rowId: string) => (state) => { @@ -21,7 +31,7 @@ export const UncheckRow = (rowId: string) => (state) => { const cloned = [...rowIds]; cloned.splice(index, 1); - + return { ...state, rowSelection: { diff --git a/plugins/selection/src/rowSelection/rowSelection.tsx b/plugins/selection/src/rowSelection/rowSelection.tsx index 2fa67c9d..3d9b66fa 100644 --- a/plugins/selection/src/rowSelection/rowSelection.tsx +++ b/plugins/selection/src/rowSelection/rowSelection.tsx @@ -10,7 +10,15 @@ interface RowSelectionProps { cell?: Cell; } -export function RowSelection(props: RowSelectionProps) { +export function RowSelectionSingle(props: RowSelectionProps){ + return RowSelection(props, true); +} + +export function RowSelectionMultiple(props: RowSelectionProps){ + return RowSelection(props, false); +} + +export function RowSelection(props: RowSelectionProps, singleSelect:boolean=false) { const { dispatch } = useStore(); const state = useSelector((state) => state.rowSelection); const [isChecked, setIsChecked] = useState(false); @@ -22,23 +30,30 @@ export function RowSelection(props: RowSelectionProps) { this.base.parentElement && (this.base.parentElement.parentElement as Element); + + const isSingleSelect:boolean = singleSelect; + + useEffect(() => { // store/dispatcher is required only if we are rendering a TD (not a TH) if (props.cell?.data && isDataCell(props)) { // mark this checkbox as checked if cell.data is true check(); } + }, []); useEffect(() => { - const parent = getParentTR(); - - if (!parent) return; const rowIds = state?.rowIds || []; const isChecked = rowIds.indexOf(props.row.id) > -1; + setIsChecked(isChecked); + const parent = getParentTR(); + + if (!parent) return; + if (isChecked) { parent.classList.add(selectedClassName); } else { @@ -47,7 +62,7 @@ export function RowSelection(props: RowSelectionProps) { }, [state]); const check = () => { - dispatch(actions.CheckRow(props.row.id)); + dispatch(actions.CheckRow(props.row.id, isSingleSelect)); props.cell?.update(true); }; diff --git a/plugins/singleSelection/README.md b/plugins/singleSelection/README.md deleted file mode 100644 index 9690d5c1..00000000 --- a/plugins/singleSelection/README.md +++ /dev/null @@ -1,14 +0,0 @@ -# `gridjs-selection` - -> Row/cell selection plugin for Grid.js - -## Documentation :book: - -See [Selection plugin](https://gridjs.io/docs/examples/selection) docs on gridjs.io. - -Full documentation of Grid.js installation, config, API and examples are available -on Grid.js website [grid.js/docs](https://gridjs.io/docs/index). - -## License - -[MIT](https://github.com/grid-js/gridjs/blob/master/LICENSE) diff --git a/plugins/singleSelection/index.ts b/plugins/singleSelection/index.ts deleted file mode 100644 index d350c87a..00000000 --- a/plugins/singleSelection/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -import { RowSelection, RowSelectionSingle, RowSelectionMultiple } from './src/rowSelection/rowSelection'; -import * as RowSelectionActions from './src/rowSelection/actions'; - -export { RowSelection, RowSelectionSingle, RowSelectionMultiple, RowSelectionActions }; diff --git a/plugins/singleSelection/package-lock.json b/plugins/singleSelection/package-lock.json deleted file mode 100644 index 08c8e0c9..00000000 --- a/plugins/singleSelection/package-lock.json +++ /dev/null @@ -1,119 +0,0 @@ -{ - "name": "selection", - "version": "4.0.0", - "lockfileVersion": 2, - "requires": true, - "packages": { - "": { - "name": "selection", - "version": "4.0.0", - "license": "MIT", - "dependencies": { - "gridjs": "../../" - } - }, - "../..": { - "version": "6.0.6", - "license": "MIT", - "dependencies": { - "preact": "^10.11.3" - }, - "devDependencies": { - "@types/enzyme": "^3.10.12", - "@types/jest": "^29.2.4", - "@types/jest-axe": "^3.5.5", - "@types/node": "^18.11.17", - "@typescript-eslint/eslint-plugin": "^5.47.0", - "@typescript-eslint/parser": "^5.47.0", - "autoprefixer": "^10.4.8", - "axe-core": "^4.4.2", - "check-export-map": "^1.1.1", - "cssnano": "^5.0.5", - "cypress": "^8.1.0", - "cypress-visual-regression": "^1.5.7", - "enzyme": "^3.11.0", - "enzyme-adapter-preact-pure": "^4.0.1", - "eslint": "^8.18.0", - "eslint-config-prettier": "^8.5.0", - "eslint-plugin-jest": "~26.8.7", - "identity-obj-proxy": "^3.0.0", - "jest": "^29.3.1", - "jest-axe": "^6.0.0", - "jest-extended": "^3.2.0", - "jsdom": "^19.0.0", - "jsdom-global": "^3.0.2", - "lerna-changelog": "^2.1.0", - "microbundle": "^0.15.1", - "npm-run-all": "^4.1.5", - "postcss": "^8.4.16", - "postcss-cli": "^9.1.0", - "postcss-nested": "^5.0.6", - "postcss-scss": "^4.0.4", - "postcss-sort-media-queries": "^4.1.0", - "prettier": "~2.7.1", - "rimraf": "~3.0.2", - "sass": "^1.54.5", - "source-map-loader": "^4.0.0", - "start-server-and-test": "^1.12.3", - "ts-jest": "^29.0.3", - "ts-loader": "^9.4.2", - "tslib": "^2.4.1", - "tsutils": "^3.21.0", - "typescript": "^4.9.4" - } - }, - "node_modules/gridjs": { - "resolved": "../..", - "link": true - } - }, - "dependencies": { - "gridjs": { - "version": "file:../..", - "requires": { - "@types/enzyme": "^3.10.12", - "@types/jest": "^29.2.4", - "@types/jest-axe": "^3.5.5", - "@types/node": "^18.11.17", - "@typescript-eslint/eslint-plugin": "^5.47.0", - "@typescript-eslint/parser": "^5.47.0", - "autoprefixer": "^10.4.8", - "axe-core": "^4.4.2", - "check-export-map": "^1.1.1", - "cssnano": "^5.0.5", - "cypress": "^8.1.0", - "cypress-visual-regression": "^1.5.7", - "enzyme": "^3.11.0", - "enzyme-adapter-preact-pure": "^4.0.1", - "eslint": "^8.18.0", - "eslint-config-prettier": "^8.5.0", - "eslint-plugin-jest": "~26.8.7", - "identity-obj-proxy": "^3.0.0", - "jest": "^29.3.1", - "jest-axe": "^6.0.0", - "jest-extended": "^3.2.0", - "jsdom": "^19.0.0", - "jsdom-global": "^3.0.2", - "lerna-changelog": "^2.1.0", - "microbundle": "^0.15.1", - "npm-run-all": "^4.1.5", - "postcss": "^8.4.16", - "postcss-cli": "^9.1.0", - "postcss-nested": "^5.0.6", - "postcss-scss": "^4.0.4", - "postcss-sort-media-queries": "^4.1.0", - "preact": "^10.11.3", - "prettier": "~2.7.1", - "rimraf": "~3.0.2", - "sass": "^1.54.5", - "source-map-loader": "^4.0.0", - "start-server-and-test": "^1.12.3", - "ts-jest": "^29.0.3", - "ts-loader": "^9.4.2", - "tslib": "^2.4.1", - "tsutils": "^3.21.0", - "typescript": "^4.9.4" - } - } - } -} diff --git a/plugins/singleSelection/package.json b/plugins/singleSelection/package.json deleted file mode 100644 index cefbcd57..00000000 --- a/plugins/singleSelection/package.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "name": "singleelection", - "version": "4.0.0", - "private": true, - "description": "Adds row and cell selection to Grid.js", - "author": "Afshin Mehrabani ", - "homepage": "https://gridjs.io/docs/examples/selection", - "license": "MIT", - "source": "index.ts", - "main": "dist/singleselection.js", - "module": "dist/singleselection.module.js", - "umd:main": "dist/singleselection.umd.js", - "amdName": "gridjs.plugins.singleselection", - "types": "dist/singleselection.d.ts", - "files": [ - "dist/*" - ], - "dependencies": { - "gridjs": "../../" - } -} diff --git a/plugins/singleSelection/src/rowSelection/actions.ts b/plugins/singleSelection/src/rowSelection/actions.ts deleted file mode 100644 index d14337bf..00000000 --- a/plugins/singleSelection/src/rowSelection/actions.ts +++ /dev/null @@ -1,41 +0,0 @@ -export const CheckRow = (rowId: string, singleSelection:boolean) => (state) => { - const rowIds = state.rowSelection?.rowIds || []; - - // rowId already exists - if (rowIds.indexOf(rowId) > -1) return state; - - if (singleSelection){ - return { - ...state, - rowSelection: { - rowIds: [rowId], - }, - }; - } - - return { - ...state, - rowSelection: { - rowIds: [rowId, ...rowIds], - }, - }; - -}; - -export const UncheckRow = (rowId: string) => (state) => { - const rowIds = state.rowSelection?.rowIds || []; - const index = rowIds.indexOf(rowId); - - // rowId doesn't exist - if (index === -1) return state; - - const cloned = [...rowIds]; - cloned.splice(index, 1); - - return { - ...state, - rowSelection: { - rowIds: cloned, - }, - }; -}; diff --git a/plugins/singleSelection/src/rowSelection/rowSelection.tsx b/plugins/singleSelection/src/rowSelection/rowSelection.tsx deleted file mode 100644 index 3d9b66fa..00000000 --- a/plugins/singleSelection/src/rowSelection/rowSelection.tsx +++ /dev/null @@ -1,92 +0,0 @@ -import { h } from 'preact'; -import * as actions from './actions'; -import { useStore, className, useEffect, useState, useSelector } from 'gridjs'; -import { Row } from 'gridjs'; -import { Cell } from 'gridjs'; - -interface RowSelectionProps { - // it's optional because thead doesn't have a row - row?: Row; - cell?: Cell; -} - -export function RowSelectionSingle(props: RowSelectionProps){ - return RowSelection(props, true); -} - -export function RowSelectionMultiple(props: RowSelectionProps){ - return RowSelection(props, false); -} - -export function RowSelection(props: RowSelectionProps, singleSelect:boolean=false) { - const { dispatch } = useStore(); - const state = useSelector((state) => state.rowSelection); - const [isChecked, setIsChecked] = useState(false); - const selectedClassName = className('tr', 'selected'); - const checkboxClassName = className('checkbox'); - const isDataCell = (props) => props.row !== undefined; - const getParentTR = () => - this.base && - this.base.parentElement && - (this.base.parentElement.parentElement as Element); - - - const isSingleSelect:boolean = singleSelect; - - - useEffect(() => { - // store/dispatcher is required only if we are rendering a TD (not a TH) - if (props.cell?.data && isDataCell(props)) { - // mark this checkbox as checked if cell.data is true - check(); - } - - }, []); - - useEffect(() => { - - const rowIds = state?.rowIds || []; - const isChecked = rowIds.indexOf(props.row.id) > -1; - - setIsChecked(isChecked); - - const parent = getParentTR(); - - if (!parent) return; - - if (isChecked) { - parent.classList.add(selectedClassName); - } else { - parent.classList.remove(selectedClassName); - } - }, [state]); - - const check = () => { - dispatch(actions.CheckRow(props.row.id, isSingleSelect)); - props.cell?.update(true); - }; - - const uncheck = () => { - dispatch(actions.UncheckRow(props.row.id)); - props.cell?.update(false); - }; - - const toggle = () => { - if (isChecked) { - uncheck(); - } else { - check(); - } - }; - - if (!isDataCell(props)) return null; - - return ( - toggle()} - className={checkboxClassName} - /> - ); -} diff --git a/plugins/singleSelection/tests/rowSelection/actions.test.ts b/plugins/singleSelection/tests/rowSelection/actions.test.ts deleted file mode 100644 index 9d3d7b85..00000000 --- a/plugins/singleSelection/tests/rowSelection/actions.test.ts +++ /dev/null @@ -1,88 +0,0 @@ -import * as Actions from '../../src/rowSelection/actions'; - -describe('Actions', () => { - it('should trigger CHECK', () => { - const state = Actions.CheckRow('42')({}); - - expect(state).toStrictEqual({ - rowSelection: { - rowIds: ['42'], - }, - }); - }); - - it('should trigger CHECK when rowIds already exists', () => { - const state = Actions.CheckRow('42')({ - rowSelection: { - rowIds: ['24'], - }, - }); - - expect(state).toStrictEqual({ - rowSelection: { - rowIds: ['42', '24'], - }, - }); - }); - - it('should trigger UNCHECK', () => { - const state = Actions.UncheckRow('42')({ - rowSelection: { - rowIds: ['42'], - }, - }); - - expect(state).toStrictEqual({ - rowSelection: { - rowIds: [], - }, - }); - }); - - it('should UNCHECK the correct item', () => { - const state = Actions.UncheckRow('42')({ - rowSelection: { - rowIds: ['22', '11'], - }, - }); - - expect(state).toStrictEqual({ - rowSelection: { - rowIds: ['22', '11'], - }, - }); - }); - - it('should UNCHECK when rowIds is null', () => { - const state = Actions.UncheckRow('42')({}); - - expect(state).toStrictEqual({}); - }); - - it('should trigger UNCHECK when rowIds is empty', () => { - const state = Actions.UncheckRow('42')({ - rowSelection: { - rowIds: [], - }, - }); - - expect(state).toStrictEqual({ - rowSelection: { - rowIds: [], - }, - }); - }); - - it('should CHECK and UNCHECK', () => { - let state = {}; - state = Actions.CheckRow('42')(state); - state = Actions.CheckRow('24')(state); - state = Actions.UncheckRow('42')(state); - - expect(state).toStrictEqual({ - rowSelection: { - rowIds: ['24'], - }, - }); - }); -}); diff --git a/plugins/singleSelection/tsconfig.json b/plugins/singleSelection/tsconfig.json deleted file mode 100644 index a0cc8dcf..00000000 --- a/plugins/singleSelection/tsconfig.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "extends": "../../tsconfig.json", - "compilerOptions": { - "rootDir": ".", - "removeComments": true - }, - "include": [ - "index.ts", - "src/**/*", - "tests/**/*" - ] -} diff --git a/plugins/singleSelection/tsconfig.release.json b/plugins/singleSelection/tsconfig.release.json deleted file mode 100644 index f65dfe8d..00000000 --- a/plugins/singleSelection/tsconfig.release.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "extends": "./tsconfig.json", - "compilerOptions": { - "rootDir": ".", - "removeComments": true - }, - "include": [ - "index.ts", - "src/**/*" - ], - "exclude": [ - "tests/**/*" - ] -} diff --git a/plugins/singleSelection/tsconfig.test.json b/plugins/singleSelection/tsconfig.test.json deleted file mode 100644 index f5515d65..00000000 --- a/plugins/singleSelection/tsconfig.test.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "extends": "./tsconfig.json", - "compilerOptions": { - "types": ["jest"], - "esModuleInterop": true - } -} From 5e63b5398ff5905e0322fa16e97713f2e127b5bc Mon Sep 17 00:00:00 2001 From: fancelin Date: Sat, 1 Apr 2023 21:11:55 -0400 Subject: [PATCH 5/5] Updated unit tests and prettier --- package.json | 8 +---- plugins/selection/index.ts | 13 +++++-- plugins/selection/src/rowSelection/actions.ts | 34 +++++++++---------- .../src/rowSelection/rowSelection.tsx | 23 +++++++------ .../tests/rowSelection/actions.test.ts | 22 +++++++++--- 5 files changed, 60 insertions(+), 40 deletions(-) diff --git a/package.json b/package.json index 4514dcb5..9d8fe7bf 100644 --- a/package.json +++ b/package.json @@ -48,13 +48,7 @@ "umd": "./plugins/selection/dist/selection.umd.js", "import": "./plugins/selection/dist/selection.mjs", "require": "./plugins/selection/dist/selection.js" - }, - "./plugins/single-selection": { - "browser": "./plugins/selection/dist/single.selection.module.js", - "umd": "./plugins/selection/dist/single.selection.umd.js", - "import": "./plugins/selection/dist/single.selection.mjs", - "require": "./plugins/selection/dist/single.selection.js" - }, + }, "./package.json": "./package.json", "./": "./" }, diff --git a/plugins/selection/index.ts b/plugins/selection/index.ts index 6f1a5769..5100ac13 100644 --- a/plugins/selection/index.ts +++ b/plugins/selection/index.ts @@ -1,4 +1,13 @@ -import { RowSelection, RowSelectionSingle } from './src/rowSelection/rowSelection'; +import { + RowSelection, + RowSelectionSingle, + RowSelectionMultiple, +} from './src/rowSelection/rowSelection'; import * as RowSelectionActions from './src/rowSelection/actions'; -export { RowSelection, RowSelectionSingle, RowSelectionActions }; +export { + RowSelection, + RowSelectionSingle, + RowSelectionMultiple, + RowSelectionActions, +}; diff --git a/plugins/selection/src/rowSelection/actions.ts b/plugins/selection/src/rowSelection/actions.ts index d14337bf..13997c71 100644 --- a/plugins/selection/src/rowSelection/actions.ts +++ b/plugins/selection/src/rowSelection/actions.ts @@ -1,27 +1,27 @@ -export const CheckRow = (rowId: string, singleSelection:boolean) => (state) => { - const rowIds = state.rowSelection?.rowIds || []; +export const CheckRow = + (rowId: string, singleSelection: boolean) => (state) => { + const rowIds = state.rowSelection?.rowIds || []; + + // rowId already exists + if (rowIds.indexOf(rowId) > -1) return state; - // rowId already exists - if (rowIds.indexOf(rowId) > -1) return state; + if (singleSelection) { + return { + ...state, + rowSelection: { + rowIds: [rowId], + }, + }; + } - if (singleSelection){ return { ...state, rowSelection: { - rowIds: [rowId], + rowIds: [rowId, ...rowIds], }, - }; - } - - return { - ...state, - rowSelection: { - rowIds: [rowId, ...rowIds], - }, + }; }; -}; - export const UncheckRow = (rowId: string) => (state) => { const rowIds = state.rowSelection?.rowIds || []; const index = rowIds.indexOf(rowId); @@ -31,7 +31,7 @@ export const UncheckRow = (rowId: string) => (state) => { const cloned = [...rowIds]; cloned.splice(index, 1); - + return { ...state, rowSelection: { diff --git a/plugins/selection/src/rowSelection/rowSelection.tsx b/plugins/selection/src/rowSelection/rowSelection.tsx index 3d9b66fa..6cfe40cf 100644 --- a/plugins/selection/src/rowSelection/rowSelection.tsx +++ b/plugins/selection/src/rowSelection/rowSelection.tsx @@ -10,15 +10,22 @@ interface RowSelectionProps { cell?: Cell; } -export function RowSelectionSingle(props: RowSelectionProps){ - return RowSelection(props, true); +export function RowSelectionSingle(props: RowSelectionProps) { + return RowSelectionCore(props, true); } -export function RowSelectionMultiple(props: RowSelectionProps){ - return RowSelection(props, false); +export function RowSelectionMultiple(props: RowSelectionProps) { + return RowSelectionCore(props, false); } -export function RowSelection(props: RowSelectionProps, singleSelect:boolean=false) { +export function RowSelection(props: RowSelectionProps) { + return RowSelectionCore(props, false); +} + +export function RowSelectionCore( + props: RowSelectionProps, + singleSelect: boolean = false, +) { const { dispatch } = useStore(); const state = useSelector((state) => state.rowSelection); const [isChecked, setIsChecked] = useState(false); @@ -30,9 +37,7 @@ export function RowSelection(props: RowSelectionProps, singleSelect:boolean=fals this.base.parentElement && (this.base.parentElement.parentElement as Element); - - const isSingleSelect:boolean = singleSelect; - + const isSingleSelect: boolean = singleSelect; useEffect(() => { // store/dispatcher is required only if we are rendering a TD (not a TH) @@ -40,11 +45,9 @@ export function RowSelection(props: RowSelectionProps, singleSelect:boolean=fals // mark this checkbox as checked if cell.data is true check(); } - }, []); useEffect(() => { - const rowIds = state?.rowIds || []; const isChecked = rowIds.indexOf(props.row.id) > -1; diff --git a/plugins/selection/tests/rowSelection/actions.test.ts b/plugins/selection/tests/rowSelection/actions.test.ts index 9d3d7b85..a08f3474 100644 --- a/plugins/selection/tests/rowSelection/actions.test.ts +++ b/plugins/selection/tests/rowSelection/actions.test.ts @@ -2,7 +2,7 @@ import * as Actions from '../../src/rowSelection/actions'; describe('Actions', () => { it('should trigger CHECK', () => { - const state = Actions.CheckRow('42')({}); + const state = Actions.CheckRow('42', false)({}); expect(state).toStrictEqual({ rowSelection: { @@ -12,7 +12,10 @@ describe('Actions', () => { }); it('should trigger CHECK when rowIds already exists', () => { - const state = Actions.CheckRow('42')({ + const state = Actions.CheckRow( + '42', + false, + )({ rowSelection: { rowIds: ['24'], }, @@ -75,8 +78,8 @@ describe('Actions', () => { it('should CHECK and UNCHECK', () => { let state = {}; - state = Actions.CheckRow('42')(state); - state = Actions.CheckRow('24')(state); + state = Actions.CheckRow('42', false)(state); + state = Actions.CheckRow('24', false)(state); state = Actions.UncheckRow('42')(state); expect(state).toStrictEqual({ @@ -85,4 +88,15 @@ describe('Actions', () => { }, }); }); + + it('should CHECK (SINGLE SELECT)', () => { + let state = {}; + state = Actions.CheckRow('42', true)(state); + state = Actions.CheckRow('24', true)(state); + expect(state).toStrictEqual({ + rowSelection: { + rowIds: ['24'], + }, + }); + }); });