From 049b21484b7b00dec2f91f9c775b6a18ef9ea264 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Vitor?= Date: Tue, 22 Jun 2021 08:50:38 -0300 Subject: [PATCH 01/25] feat: allow input masks functions on forminput2 --- demo/Form2Examples.jsx | 102 +++++++++++++++++++++++++- src/forms2/FormInput.jsx | 15 +++- src/forms2/helpers/useFormControl.jsx | 18 +++-- 3 files changed, 126 insertions(+), 9 deletions(-) diff --git a/demo/Form2Examples.jsx b/demo/Form2Examples.jsx index 5dc2b07..1e7f8af 100644 --- a/demo/Form2Examples.jsx +++ b/demo/Form2Examples.jsx @@ -7,7 +7,13 @@ export function Form2Examples() {
Alternative Form implementation console.log('onSubmit', data)} onChange={(data) => console.log('onChange', data)} transform={(formData) => { @@ -76,6 +82,8 @@ export function Form2Examples() {
+ +
@@ -122,3 +130,95 @@ function FormObserver() { return
{state}
; } + +function FormMasked() { + const percentageFormControl = useFormControl2('masks.percentageValue'); + + const decimalMask = function (v) { + let maskedValue = String(v); + + maskedValue = maskedValue.replace(/\D/g, ''); + maskedValue = maskedValue.replace(/(\d)(\d{3})$/, '$1.$2'); + + return maskedValue; + }; + + const dateMask = function (v) { + let maskedValue = v; + + maskedValue = maskedValue.replace(/\D/g, ''); + + maskedValue = maskedValue.replace(/(\d{2})(\d)/, '$1/$2'); + maskedValue = maskedValue.replace(/(\d{2})(\d)/, '$1/$2'); + + return maskedValue; + }; + + const hourMask = function (v) { + let maskedValue = v; + + maskedValue = maskedValue.replace(/\D/g, ''); + maskedValue = maskedValue.replace(/(\d{2})(\d)/, '$1:$2'); + + return maskedValue; + }; + + const currency = function (v) { + let maskedValue = v; + + maskedValue = maskedValue.replace(/\D/g, ''); + maskedValue = maskedValue.replace(/(\d)(\d{2})$/, '$1,$2'); + maskedValue = maskedValue.replace(/(?=(\d{3})+(\D))\B/g, '.'); + + return maskedValue; + }; + + const percentageMask = function (v) { + let maskedValue = v; + maskedValue = maskedValue.replace(/[^0-9\.]/g, ''); + + if (!maskedValue) { + return ''; + } + + return `${maskedValue}%`; + }; + + return ( +
+ Masked Inputs +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + { + const rawValue = value.replace(/\%/, ''); + percentageFormControl.setValue(Number(rawValue) / 100); + }} + /> + +
+ +
+ + +
+
+ ); +} diff --git a/src/forms2/FormInput.jsx b/src/forms2/FormInput.jsx index 5570426..5147053 100644 --- a/src/forms2/FormInput.jsx +++ b/src/forms2/FormInput.jsx @@ -5,7 +5,15 @@ import { booleanOrFunction } from '../forms/helpers/form-helpers'; import { useFormControl2 } from './helpers/useFormControl'; -export function FormInput2({ type, name, required: _required, disabled: _disabled, afterChange, ..._attrs }) { +export function FormInput2({ + type, + name, + required: _required, + disabled: _disabled, + afterChange, + maskFunction, + ..._attrs +}) { const { getValue, handleOnChangeFactory, getFormData } = useFormControl2(name); const disabled = booleanOrFunction(_disabled, getFormData()); @@ -25,7 +33,9 @@ export function FormInput2({ type, name, required: _required, disabled: _disable attrs.value = getValue(); } - return ; + return ( + + ); } FormInput2.defaultProps = { @@ -36,6 +46,7 @@ FormInput2.propTypes = { afterChange: PropTypes.func, disabled: PropTypes.oneOfType([PropTypes.bool, PropTypes.func]), id: PropTypes.string, + maskFunction: PropTypes.func, max: PropTypes.string, maxLength: PropTypes.string, min: PropTypes.string, diff --git a/src/forms2/helpers/useFormControl.jsx b/src/forms2/helpers/useFormControl.jsx index ce358d1..89b45d1 100644 --- a/src/forms2/helpers/useFormControl.jsx +++ b/src/forms2/helpers/useFormControl.jsx @@ -26,14 +26,20 @@ export function useFormControl2(name, type) { ); const handleOnChange = useCallback( - ({ target }, _type) => { + ({ target }, _type, maskFunction) => { const value = getTargetValue(target); - const decodedValue = decode(value, type || _type); + let maskedOrDecodedValue; - setValue(decodedValue); + if (isFunction(maskFunction)) { + maskedOrDecodedValue = maskFunction(value); + } else { + maskedOrDecodedValue = decode(value, type || _type); + } + + setValue(maskedOrDecodedValue); - return decodedValue; + return maskedOrDecodedValue; }, [setValue, type] ); @@ -54,8 +60,8 @@ export function useFormControl2(name, type) { isRegistered() { return isRegistered; }, - handleOnChangeFactory: (afterChange, type) => (e) => { - const newValue = handleOnChange(e, type); + handleOnChangeFactory: (afterChange, type, maskFunction) => (e) => { + const newValue = handleOnChange(e, type, maskFunction); if (isFunction(afterChange)) { afterChange(newValue); From 28eecc21577895b66cca7811113045c8138296b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Vitor?= Date: Tue, 22 Jun 2021 13:06:56 -0300 Subject: [PATCH 02/25] =?UTF-8?q?chore:=20corrige=20infos=20de=20publica?= =?UTF-8?q?=C3=A7ao?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index 1c57bed..f13808e 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "react-bootstrap-utils", + "name": "@geolaborapp/react-bootstrap-utils", "version": "0.26.3", "description": "React bootstrap library", "main": "dist/main.js", @@ -18,15 +18,14 @@ }, "repository": { "type": "git", - "url": "git+https://github.com/assisrafael/react-bootstrap-utils.git" + "url": "git+https://github.com/geolaborapp/react-bootstrap-utils.git" + }, + "publishConfig": { + "registry": "https://npm.pkg.github.com/geolaborapp" }, "keywords": [], - "author": "Igor Rafael ", + "author": "João Vitor ", "license": "MIT", - "bugs": { - "url": "https://github.com/assisrafael/react-bootstrap-utils/issues" - }, - "homepage": "https://github.com/assisrafael/react-bootstrap-utils#readme", "devDependencies": { "@babel/core": "^7.12.10", "@babel/plugin-transform-runtime": "^7.12.10", From a1eb85d56cbd0142673e2a35394821a5a4a19874 Mon Sep 17 00:00:00 2001 From: Camila Campos Date: Fri, 9 Jul 2021 10:27:22 -0300 Subject: [PATCH 03/25] fix: check if an element is descendant before remove --- src/dialog/ModalPortal.jsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/dialog/ModalPortal.jsx b/src/dialog/ModalPortal.jsx index 4ecbf26..0409a18 100644 --- a/src/dialog/ModalPortal.jsx +++ b/src/dialog/ModalPortal.jsx @@ -22,7 +22,11 @@ export function ModalPortal({ children, title, isOpen }) { return; } - modalPortalsElem.removeChild(container); + const isDescendant = modalPortalsElem.contains(container); + + if (isDescendant) { + modalPortalsElem.removeChild(container); + } }; }, [container, title]); From c919bcaf49fd966c4ca8c78a8de4c50465fe1ebc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Vitor?= Date: Fri, 9 Jul 2021 10:28:57 -0300 Subject: [PATCH 04/25] chore(release): 0.26.4 --- CHANGELOG.md | 13 +++++++++++++ package.json | 2 +- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d245e6c..68142ce 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,19 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +### [0.26.4](https://github.com/geolaborapp/react-bootstrap-utils/compare/v0.26.3...v0.26.4) (2021-07-09) + + +### Features + +* allow input masks functions on forminput2 ([afaa1ce](https://github.com/geolaborapp/react-bootstrap-utils/commit/afaa1cea773ea9abedd8ffaa4e827b0e14b22ea0)) +* allow input masks functions on forminput2 ([049b214](https://github.com/geolaborapp/react-bootstrap-utils/commit/049b21484b7b00dec2f91f9c775b6a18ef9ea264)) + + +### Bug Fixes + +* check if an element is descendant before remove ([a1eb85d](https://github.com/geolaborapp/react-bootstrap-utils/commit/a1eb85d56cbd0142673e2a35394821a5a4a19874)) + ### [0.26.3](https://github.com/assisrafael/react-bootstrap-utils/compare/v0.26.2...v0.26.3) (2021-04-21) diff --git a/package.json b/package.json index f13808e..61788a8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@geolaborapp/react-bootstrap-utils", - "version": "0.26.3", + "version": "0.26.4", "description": "React bootstrap library", "main": "dist/main.js", "scripts": { From 790b7b59e7475180b9d114af6bc586216f91d2b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Vitor?= Date: Fri, 9 Jul 2021 10:30:16 -0300 Subject: [PATCH 05/25] chore(release): 0.26.5 --- CHANGELOG.md | 13 +++++++++++++ package.json | 2 +- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 68142ce..dd6ba70 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,19 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +### [0.26.5](https://github.com/geolaborapp/react-bootstrap-utils/compare/v0.26.3...v0.26.5) (2021-07-09) + + +### Features + +* allow input masks functions on forminput2 ([afaa1ce](https://github.com/geolaborapp/react-bootstrap-utils/commit/afaa1cea773ea9abedd8ffaa4e827b0e14b22ea0)) +* allow input masks functions on forminput2 ([049b214](https://github.com/geolaborapp/react-bootstrap-utils/commit/049b21484b7b00dec2f91f9c775b6a18ef9ea264)) + + +### Bug Fixes + +* check if an element is descendant before remove ([a1eb85d](https://github.com/geolaborapp/react-bootstrap-utils/commit/a1eb85d56cbd0142673e2a35394821a5a4a19874)) + ### [0.26.4](https://github.com/geolaborapp/react-bootstrap-utils/compare/v0.26.3...v0.26.4) (2021-07-09) diff --git a/package.json b/package.json index 61788a8..0d51374 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@geolaborapp/react-bootstrap-utils", - "version": "0.26.4", + "version": "0.26.5", "description": "React bootstrap library", "main": "dist/main.js", "scripts": { From c9f5a98b1b460470eccc82b64a57f5ec2385e472 Mon Sep 17 00:00:00 2001 From: Nerissa Date: Mon, 12 Jul 2021 16:44:45 -0300 Subject: [PATCH 06/25] =?UTF-8?q?Flexibiliza=20defini=C3=A7=C3=A3o=20de=20?= =?UTF-8?q?role=20das=20linhas=20do=20corpo=20da=20tabela?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/table/Table.jsx | 1 - src/table/TableBody.jsx | 9 +++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/table/Table.jsx b/src/table/Table.jsx index 82eaad2..9063934 100644 --- a/src/table/Table.jsx +++ b/src/table/Table.jsx @@ -55,7 +55,6 @@ Table.defaultProps = { dark: false, actionLabel: 'Actions', rowClass: () => '', - onRowClick: () => {}, columnHeaderFormat: (label) => label, }; diff --git a/src/table/TableBody.jsx b/src/table/TableBody.jsx index 11ddd47..ae46402 100644 --- a/src/table/TableBody.jsx +++ b/src/table/TableBody.jsx @@ -1,5 +1,6 @@ import React from 'react'; import PropTypes from 'prop-types'; +import { isFunction } from 'js-var-type'; import { safeClick } from '../utils/event-handlers'; import { getValueByPath } from '../utils/getters-setters'; @@ -7,11 +8,14 @@ import { getValueByPath } from '../utils/getters-setters'; import { getColumnClass } from './table-helpers'; import { TableActions } from './TableActions'; -export function TableBody({ columns, docs, rowClass, actions, onRowClick }) { +export function TableBody({ columns, docs, rowRole, rowClass, actions, onRowClick }) { + const trRole = rowRole ?? isFunction(onRowClick) ? 'button' : 'row'; + const trOnClick = isFunction(onRowClick) ? onRowClick : () => {}; + return ( {docs.map((doc, docIndex) => ( - + {columns.map((column, columnIndex) => ( {getColumnValue(doc, column, docIndex)} @@ -29,6 +33,7 @@ TableBody.propTypes = { actions: PropTypes.oneOfType([PropTypes.func, PropTypes.arrayOf(PropTypes.object)]), columns: PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.string, PropTypes.object])), docs: PropTypes.arrayOf(PropTypes.object), + rowRole: PropTypes.string, rowClass: PropTypes.func, onRowClick: PropTypes.func, }; From b36e789ab4a347633a35939634d67b5adb38efa3 Mon Sep 17 00:00:00 2001 From: Nerissa Date: Thu, 15 Jul 2021 17:37:04 -0300 Subject: [PATCH 07/25] =?UTF-8?q?L=C3=B3gica=20do=20SortableTable?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- demo/TableExamples.jsx | 102 +++++++++++++++++++++++++++++++++- demo/index.html | 4 +- src/table/SortableTable.jsx | 106 ++++++++++++++++++++++++++++++++++++ src/table/TableBody.jsx | 4 +- src/table/TableHead.jsx | 4 +- src/table/index.js | 1 + src/utils/sort.js | 57 +++++++++++++++++++ 7 files changed, 272 insertions(+), 6 deletions(-) create mode 100644 src/table/SortableTable.jsx create mode 100644 src/utils/sort.js diff --git a/demo/TableExamples.jsx b/demo/TableExamples.jsx index 6ea33c2..414cb03 100644 --- a/demo/TableExamples.jsx +++ b/demo/TableExamples.jsx @@ -1,7 +1,7 @@ /* eslint-disable no-console */ import React, { useState } from 'react'; // eslint-disable-next-line import/no-unresolved -import { Table, Form, FormCheckbox } from '../dist/main'; +import { Table, SortableTable, Form, FormCheckbox } from '../dist/main'; import { stopPropagation } from '../src/utils/event-handlers'; export function TableExamples() { @@ -221,6 +221,106 @@ export function TableExamples() { ]} />
+
+

Sortable Table

+ + +
+ +
+
+

Sortable Table with Custom Header

+ + + column?.isSortable !== false ? ( + sortBy === attribute ? ( + sortOrder === 'ASC' ? ( + + ) : ( + + ) + ) : ( + + ) + ) : ( + label + ) + } + columns={[ + { + attribute: 'a', + label: 'A', + }, + { + attribute: 'b', + label: 'B', + isSortable: false, + }, + { + attribute: 'c', + label: 'C', + }, + ]} + docs={[ + { a: 'B', b: 'G', c: 'Y' }, + { a: 'C', b: 'I', c: 'Z' }, + { a: 'A', b: 'H', c: 'X' }, + { a: 'D', b: 'L', c: 'T' }, + ]} + /> +
+
+

Sortable Table with no default sorting

+ + +
); diff --git a/demo/index.html b/demo/index.html index 458f8af..72d0643 100644 --- a/demo/index.html +++ b/demo/index.html @@ -8,7 +8,9 @@ - + + +
diff --git a/src/table/SortableTable.jsx b/src/table/SortableTable.jsx new file mode 100644 index 0000000..5fcc664 --- /dev/null +++ b/src/table/SortableTable.jsx @@ -0,0 +1,106 @@ +import React, { useState, useCallback, useMemo } from 'react'; +import PropTypes from 'prop-types'; +import { isFunction } from 'js-var-type'; + +import { sortData } from '../utils/sort'; + +import { Table } from './Table'; + +export function SortableTable({ columnHeaderFormat, docs, defaultSortOption, ..._props }) { + const [sortOption, setSortOption] = useState(defaultSortOption); + + const sortedDocs = useMemo(() => { + if (sortOption?.sortBy) { + return sortData(docs, { + sortBy: sortOption.sortBy, + sortOrder: sortOption.sortOrder ?? 'ASC', // default case ASC + }); + } + + return docs; + }, [docs, sortOption]); + + const changeSort = useCallback((attribute) => { + setSortOption((prevState) => { + const attributeChanged = prevState?.sortBy !== attribute; + const order = !attributeChanged && prevState?.sortOrder === 'DESC' ? 'ASC' : 'DESC'; + + return { + sortBy: attribute, + sortOrder: order, + }; + }); + }, []); + + const defaultHeaderContent = useCallback( + (label, attribute, column) => { + /* By default, if isSortable is not set to false, + * it is assumed the column can be sorted */ + if (column?.isSortable === false) { + return label; + } + + const icon = + sortOption?.sortBy === attribute ? ( + sortOption.sortOrder === 'DESC' ? ( + + ) : ( + // default case ASC + ) + ) : ( + + ); + + return icon; + }, + [sortOption?.sortBy, sortOption?.sortOrder] + ); + + const renderHeaderContent = useCallback( + (label, attribute, column) => + isFunction(columnHeaderFormat) + ? columnHeaderFormat(label, attribute, column, sortOption) + : defaultHeaderContent(label, attribute, column), + [columnHeaderFormat, defaultHeaderContent, sortOption] + ); + + const buildSortingHeader = useCallback( + (label, attribute, column) => + /* By default, if isSortable is not set to false, + * it is assumed the column can be sorted */ + column?.isSortable === false ? ( + renderHeaderContent(label, attribute, column) + ) : ( + <> + { + e.preventDefault(); + e.stopPropagation(); + changeSort(attribute); + }} + > + {renderHeaderContent(label, attribute, column)} + + {label} + + ), + [changeSort, renderHeaderContent] + ); + + return ; +} + +SortableTable.defaultSortOption = { + defaultSortOption: {}, +}; + +SortableTable.propTypes = { + docs: PropTypes.arrayOf(PropTypes.object), + columnHeaderFormat: PropTypes.func, + defaultSortOption: PropTypes.shape({ + sortBy: PropTypes.string, + sortOrder: PropTypes.oneOf(['ASC', 'DESC']), + }), +}; diff --git a/src/table/TableBody.jsx b/src/table/TableBody.jsx index ae46402..d9183d8 100644 --- a/src/table/TableBody.jsx +++ b/src/table/TableBody.jsx @@ -14,9 +14,9 @@ export function TableBody({ columns, docs, rowRole, rowClass, actions, onRowClic return ( - {docs.map((doc, docIndex) => ( + {docs?.map((doc, docIndex) => ( - {columns.map((column, columnIndex) => ( + {columns?.map((column, columnIndex) => ( diff --git a/src/table/TableHead.jsx b/src/table/TableHead.jsx index 064aeec..0acc324 100644 --- a/src/table/TableHead.jsx +++ b/src/table/TableHead.jsx @@ -7,9 +7,9 @@ export function TableHead({ columns, hasActions, actionLabel, columnHeaderFormat return ( - {columns.map((column, columnIndex) => ( + {columns?.map((column, columnIndex) => ( ))} {hasActions && } diff --git a/src/table/index.js b/src/table/index.js index 75193ad..d0dfcca 100644 --- a/src/table/index.js +++ b/src/table/index.js @@ -1 +1,2 @@ +export * from './SortableTable'; export * from './Table'; diff --git a/src/utils/sort.js b/src/utils/sort.js new file mode 100644 index 0000000..29b8ea6 --- /dev/null +++ b/src/utils/sort.js @@ -0,0 +1,57 @@ +import { getValueByPath } from './getters-setters'; + +function compareASC(a, b) { + if (!a || !b) { + if (a) { + return 1; + } + + if (b) { + return -1; + } + + return 0; + } + + if (a > b) { + return 1; + } + + if (a < b) { + return -1; + } + + return 0; +} + +function compareDESC(a, b) { + if (!a || !b) { + if (a) { + return -1; + } + + if (b) { + return 1; + } + + return 0; + } + + if (a > b) { + return -1; + } + + if (a < b) { + return 1; + } + + return 0; +} + +export function sortData(docs, { sortBy, sortOrder }) { + return docs?.sort((a, b) => + sortOrder === 'ASC' + ? compareASC(getValueByPath(a, sortBy), getValueByPath(b, sortBy)) + : compareDESC(getValueByPath(a, sortBy), getValueByPath(b, sortBy)) + ); +} From ddf5cc3ab4292ac3c662bbc176818e85538880f1 Mon Sep 17 00:00:00 2001 From: Nerissa Date: Wed, 21 Jul 2021 11:06:45 -0300 Subject: [PATCH 08/25] chore(release): 0.26.6 --- CHANGELOG.md | 12 ++++++++++++ package.json | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dd6ba70..8d85427 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,18 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +### [0.26.6](https://github.com/geolaborapp/react-bootstrap-utils/compare/v0.26.5...v0.26.6) (2021-07-21) + + +### Features + +* adiciona componente SortableTable ([320feab](https://github.com/geolaborapp/react-bootstrap-utils/commit/320feab1af4e9a9339a6ac36e48551de17026ebe)) + + +### Bug Fixes + +* flexibiliza papel das linhas de uma tabela ([dd39fa7](https://github.com/geolaborapp/react-bootstrap-utils/commit/dd39fa7988f62fd43870ea78c34c4e3cd504aae2)) + ### [0.26.5](https://github.com/geolaborapp/react-bootstrap-utils/compare/v0.26.3...v0.26.5) (2021-07-09) diff --git a/package.json b/package.json index 0d51374..d85effb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@geolaborapp/react-bootstrap-utils", - "version": "0.26.5", + "version": "0.26.6", "description": "React bootstrap library", "main": "dist/main.js", "scripts": { From 3797215f21060d76541627deb67031b809f40667 Mon Sep 17 00:00:00 2001 From: Nerissa Date: Wed, 21 Jul 2021 11:13:31 -0300 Subject: [PATCH 09/25] Update readme --- README.md | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/README.md b/README.md index 5adf488..8f796de 100644 --- a/README.md +++ b/README.md @@ -46,3 +46,26 @@ Starting demo app ```bash npm run start ``` + +## How to Publish a New Version + +Make sure the master branch is updated (git pull) and make sure all new commits (or expected commits) are included. +Suggested log visualization: + +```bash +git log --graph --pretty=format:'%C(yellow)%h%C(cyan)%d%Creset %s - %C(blue)%an%Creset, %C(white)%ar%Creset' +``` + +On the terminal, run the command: + +```bash +npm run release +``` + +followed by: + +```bash +git push --follow-tags origin master && npm publish +``` + +Check the repository on Github, verifying the newly created tag \ No newline at end of file From bd3be741cba33fc0ad3583beaff63a57bed388ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Vitor?= Date: Wed, 28 Jul 2021 13:52:16 -0300 Subject: [PATCH 10/25] fix: set the selected value as initial search in autocomplete --- demo/FormExamples.jsx | 1 - src/forms/FormAutocomplete.jsx | 17 ++++++++++++++--- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/demo/FormExamples.jsx b/demo/FormExamples.jsx index 800411f..ff27413 100644 --- a/demo/FormExamples.jsx +++ b/demo/FormExamples.jsx @@ -137,7 +137,6 @@ export function FormExamples() { label="Autocomplete" options={['1234', '2345', '3456']} placeholder="Type some numbers" - disabled help="Autocomplete help" /> diff --git a/src/forms/FormAutocomplete.jsx b/src/forms/FormAutocomplete.jsx index c36cf0b..6495258 100644 --- a/src/forms/FormAutocomplete.jsx +++ b/src/forms/FormAutocomplete.jsx @@ -24,9 +24,14 @@ export function FormAutocomplete({ afterChange, allowUnlistedValue, }) { - const { getValue, setValue: _setValue, register, isValid, getFormSubmitedAttempted, getFormData } = useFormControl( - name - ); + const { + getValue, + setValue: _setValue, + register, + isValid, + getFormSubmitedAttempted, + getFormData, + } = useFormControl(name); const value = getValue(); const setValue = useCallback( @@ -149,6 +154,12 @@ export function FormAutocomplete({ useEffect(updateSearchInputValidation, [updateSearchInputValidation]); useEffect(clearSearchValue, [clearSearchValue]); + useEffect(() => { + if (selectedItem?.label) { + setSearchValue(selectedItem?.label); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); return ( <> From d978c05bae0a4101c68ea9d0da975716085a19f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Vitor?= Date: Wed, 28 Jul 2021 13:54:07 -0300 Subject: [PATCH 11/25] wip --- demo/FormExamples.jsx | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/demo/FormExamples.jsx b/demo/FormExamples.jsx index ff27413..5aa5e57 100644 --- a/demo/FormExamples.jsx +++ b/demo/FormExamples.jsx @@ -131,6 +131,16 @@ export function FormExamples() {
+
+ +
Date: Wed, 28 Jul 2021 13:58:46 -0300 Subject: [PATCH 12/25] chore(release): 0.26.7 --- CHANGELOG.md | 8 ++++++++ package.json | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8d85427..c5dce29 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,14 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +### [0.26.7](https://github.com/geolaborapp/react-bootstrap-utils/compare/v0.26.6...v0.26.7) (2021-07-28) + + +### Bug Fixes + +* set the selected value as initial search in autocomplete ([07c4369](https://github.com/geolaborapp/react-bootstrap-utils/commit/07c4369ec0585b426500824e65bb0599f9befee1)) +* set the selected value as initial search in autocomplete ([bd3be74](https://github.com/geolaborapp/react-bootstrap-utils/commit/bd3be741cba33fc0ad3583beaff63a57bed388ee)) + ### [0.26.6](https://github.com/geolaborapp/react-bootstrap-utils/compare/v0.26.5...v0.26.6) (2021-07-21) diff --git a/package.json b/package.json index d85effb..de42af1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@geolaborapp/react-bootstrap-utils", - "version": "0.26.6", + "version": "0.26.7", "description": "React bootstrap library", "main": "dist/main.js", "scripts": { From 82a00d638671990edff1bcca602950364943cb00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Vitor?= Date: Fri, 13 Aug 2021 17:28:05 -0300 Subject: [PATCH 13/25] feat: include prop to hide closed modals content --- src/dialog/Dialog.jsx | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/src/dialog/Dialog.jsx b/src/dialog/Dialog.jsx index 50616ad..dad5ecd 100644 --- a/src/dialog/Dialog.jsx +++ b/src/dialog/Dialog.jsx @@ -1,3 +1,4 @@ +/* eslint-disable react/prop-types */ import React, { useState } from 'react'; import PropTypes from 'prop-types'; @@ -8,7 +9,7 @@ import { safeClick } from '../utils/event-handlers'; import { ModalPortal } from './ModalPortal'; import { Modal } from './Modal'; -export function useDialog(props) { +export function useDialog({ onlyRenderContentIfIsOpen = true, ...props }) { const { isOpen, open, close } = useOpenState(); const [dialogBodyProps, setDialogBodyProps] = useState({}); @@ -18,29 +19,39 @@ export function useDialog(props) { open(); }, DialogPortal() { - return ( + return onlyRenderContentIfIsOpen && !isOpen() ? ( + <> + ) : ( - + ); }, }; } -export function Dialog({ children, ...props }) { +export function Dialog({ children, onlyRenderContentIfIsOpen, ...props }) { const { isOpen, open, close } = useOpenState(); return ( {children} - - - + {onlyRenderContentIfIsOpen && !isOpen() ? ( + <> + ) : ( + + + + )} ); } +Dialog.defaultProps = { + onlyRenderContentIfIsOpen: true, +}; + Dialog.propTypes = { afterOpen: PropTypes.func, children: PropTypes.node, @@ -48,6 +59,7 @@ Dialog.propTypes = { centered: PropTypes.bool, footer: PropTypes.oneOfType([PropTypes.node, PropTypes.func]), keyboard: PropTypes.bool, + onlyRenderContentIfIsOpen: PropTypes.bool, scrollable: PropTypes.bool, size: PropTypes.oneOf(['sm', 'lg', 'xl', '']), staticBackdrop: PropTypes.bool, From 64f71514afb52903481853990752b0e5775b527c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Vitor?= Date: Fri, 13 Aug 2021 17:59:22 -0300 Subject: [PATCH 14/25] wip --- src/dialog/Dialog.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dialog/Dialog.jsx b/src/dialog/Dialog.jsx index dad5ecd..59dad41 100644 --- a/src/dialog/Dialog.jsx +++ b/src/dialog/Dialog.jsx @@ -23,7 +23,7 @@ export function useDialog({ onlyRenderContentIfIsOpen = true, ...props }) { <> ) : ( - + ); }, From 8a25f1a3b70362449c6e3ef44dc0e8adcc699e3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Vitor?= Date: Fri, 13 Aug 2021 18:04:36 -0300 Subject: [PATCH 15/25] chore(release): 0.26.8 --- CHANGELOG.md | 8 ++++++++ package.json | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c5dce29..295910c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,14 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +### [0.26.8](https://github.com/geolaborapp/react-bootstrap-utils/compare/v0.26.7...v0.26.8) (2021-08-13) + + +### Features + +* include prop to hide closed modals content ([4099fdc](https://github.com/geolaborapp/react-bootstrap-utils/commit/4099fdcd86e9e1caafa539a7659d7edc82200dd7)) +* include prop to hide closed modals content ([82a00d6](https://github.com/geolaborapp/react-bootstrap-utils/commit/82a00d638671990edff1bcca602950364943cb00)) + ### [0.26.7](https://github.com/geolaborapp/react-bootstrap-utils/compare/v0.26.6...v0.26.7) (2021-07-28) diff --git a/package.json b/package.json index de42af1..e438cac 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@geolaborapp/react-bootstrap-utils", - "version": "0.26.7", + "version": "0.26.8", "description": "React bootstrap library", "main": "dist/main.js", "scripts": { From 60fae42059ece24817b61f293aeaa12842e85742 Mon Sep 17 00:00:00 2001 From: Camila Silva Campos <50001507+CamsCampos@users.noreply.github.com> Date: Wed, 25 Aug 2021 17:09:50 -0300 Subject: [PATCH 16/25] feat: new dropdown selection component (#6) * wip * wip * wip * wip * wip * wip * wip * wip * wip * Update src/forms/FormDropdown.jsx Co-authored-by: nerissa-aguirre <79877143+nerissa-aguirre@users.noreply.github.com> * wip * wip * wip Co-authored-by: Camila Campos Co-authored-by: nerissa-aguirre <79877143+nerissa-aguirre@users.noreply.github.com> --- demo/FormExamples.jsx | 77 +++++++++++++++ src/forms/FormDropdown.jsx | 159 ++++++++++++++++++++++++++++++ src/forms/FormSelect.jsx | 4 +- src/forms/helpers/form-helpers.js | 12 ++- src/forms/index.js | 2 + src/forms2/FormSelect.jsx | 4 +- src/mixed/Dropdown.jsx | 8 +- 7 files changed, 257 insertions(+), 9 deletions(-) create mode 100644 src/forms/FormDropdown.jsx diff --git a/demo/FormExamples.jsx b/demo/FormExamples.jsx index 5aa5e57..334de0c 100644 --- a/demo/FormExamples.jsx +++ b/demo/FormExamples.jsx @@ -9,6 +9,7 @@ import { FormGroupRadio, FormGroupTextarea, FormGroupAutocomplete, + FormGroupDropdown, // eslint-disable-next-line import/no-unresolved } from '../dist/main'; @@ -24,6 +25,10 @@ export function FormExamples() { radioField2: 'b', numberField: null, dateField: new Date().toISOString(), + dropdownField1: { + title: 'Title two', + }, + dropdownField2: '03', }} onChange={console.info} onSubmit={(formData) => { @@ -357,6 +362,78 @@ export function FormExamples() {
))} + + +
Title one
+

Subtitle one

+ + ), + }, + { + value: { + title: 'Title two', + subtitle: 'subtitle two', + }, + label: ( +
+
Title two
+

Subtitle two

+
+ ), + }, + { + value: { + title: 'Title three', + subtitle: 'subtitle three', + }, + label: ( +
+
Title three
+

Subtitle three

+
+ ), + }, + ]} + help="dropdown help" + placeholder="Select one value" + afterChange={() => console.log('afterChange dropdown')} + template={(label) =>
{label}
} + itemClassName="border-bottom" + childClassName="text-muted" + trackBy="title" + /> + + Value one

, + }, + { + value: '02', + label:

Value two

, + }, + { + value: '03', + label:

Value three

, + }, + ]} + placeholder="Select one value" + includeEmptyItem={false} + menuClassName="p-4 w-100" + /> ); } diff --git a/src/forms/FormDropdown.jsx b/src/forms/FormDropdown.jsx new file mode 100644 index 0000000..59cb631 --- /dev/null +++ b/src/forms/FormDropdown.jsx @@ -0,0 +1,159 @@ +import React, { useRef, useCallback, useEffect, useMemo } from 'react'; +import PropTypes from 'prop-types'; +import { isFunction } from 'js-var-type'; + +import { Dropdown } from '../mixed/Dropdown'; +import { useOpenState } from '../utils/useOpenState'; +import { formatClasses } from '../utils/attributes'; + +import { getSelectedOption, normalizeOptions } from './helpers/form-helpers'; +import { useFormControl } from './helpers/useFormControl'; +import { FormGroup } from './FormGroup'; + +export const FormDropdown = ({ + afterChange, + childClassName, + dropdownClassName, + includeEmptyItem, + itemClassName, + menuClassName, + name, + options, + placeholder, + template, + toggleIcon, + trackBy, +}) => { + const dropdownRef = useRef(null); + + const { getFormData, getValue, setValue: _setValue } = useFormControl(name); + + const value = getValue(); + const items = normalizeOptions(options, getFormData()); + const selectedItem = useMemo(() => getSelectedOption(value, items, trackBy), [items, trackBy, value]); + + const { isOpen: _isOpen, open, close } = useOpenState(); + const isOpen = _isOpen(); + + const setValue = useCallback( + (v) => { + _setValue(v); + + if (isFunction(afterChange)) { + afterChange(v); + } + }, + [_setValue, afterChange] + ); + + const onSelectItem = useCallback( + ({ value }) => { + setValue(value); + close(); + }, + [close, setValue] + ); + + const toggleDropdown = useCallback(() => (isOpen ? close() : open()), [close, isOpen, open]); + + useEffect(() => { + /* The logic in this effect allows the user to close the dropdown menu when they click outside of the component. */ + const pageClickEvent = (e) => { + if (dropdownRef.current !== null && !dropdownRef.current.contains(e.target)) { + if (isOpen) { + close(); + } else { + open(); + } + } + }; + + if (isOpen) { + window.addEventListener('click', pageClickEvent); + } + + return () => { + window.removeEventListener('click', pageClickEvent); + }; + }, [close, isOpen, open]); + + return ( +
+
}, ...items] : items} + onSelect={onSelectItem} + template={template} + itemClassName={itemClassName} + className={dropdownClassName} + menuClassName={menuClassName} + > +
+ {selectedItem ? template(selectedItem.label) :
{placeholder}
} + {toggleIcon(isOpen)} +
+ + + ); +}; + +FormDropdown.defaultProps = { + includeEmptyItem: true, + menuClassName: 'p-0 w-100', + template: (x) => x, + toggleIcon: function toggleIcon(isOpen) { + return ( +
+ +
+ ); + }, +}; + +FormDropdown.propTypes = { + afterChange: PropTypes.func, + childClassName: PropTypes.string, + dropdownClassName: PropTypes.string, + includeEmptyItem: PropTypes.bool, + itemClassName: PropTypes.string, + menuClassName: PropTypes.string, + name: PropTypes.string.isRequired, + options: PropTypes.oneOfType([ + PropTypes.func, + PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.string, PropTypes.object])), + ]), + placeholder: PropTypes.string, + template: PropTypes.func, + toggleIcon: PropTypes.func, + trackBy: PropTypes.string, +}; + +export function FormGroupDropdown(props) { + return ( + + + + ); +} + +FormGroupDropdown.propTypes = { + afterChange: PropTypes.func, + childClassName: PropTypes.string, + dropdownClassName: PropTypes.string, + help: PropTypes.node, + includeEmptyItem: PropTypes.bool, + itemClassName: PropTypes.string, + menuClassName: PropTypes.string, + name: PropTypes.string.isRequired, + options: PropTypes.oneOfType([ + PropTypes.func, + PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.string, PropTypes.object])), + ]), + placeholder: PropTypes.string, + template: PropTypes.func, + toggleIcon: PropTypes.func, + trackBy: PropTypes.string, +}; diff --git a/src/forms/FormSelect.jsx b/src/forms/FormSelect.jsx index 757c720..073f6c6 100644 --- a/src/forms/FormSelect.jsx +++ b/src/forms/FormSelect.jsx @@ -5,7 +5,7 @@ import { normalizeOptions, booleanOrFunction, serializeValue, - getSelectedOption, + getSelectedValue, getOptionsType, } from './helpers/form-helpers'; import { useFormControl } from './helpers/useFormControl'; @@ -40,7 +40,7 @@ export function FormSelect({ {...attrs} className="custom-select" onChange={handleOnChangeFactory(afterChange, getOptionsType(normalizedOptions))} - value={getSelectedOption(value, normalizedOptions, trackBy)} + value={getSelectedValue(value, normalizedOptions, trackBy)} ref={registerRef} > diff --git a/src/forms/helpers/form-helpers.js b/src/forms/helpers/form-helpers.js index a84500b..c9a2fcd 100644 --- a/src/forms/helpers/form-helpers.js +++ b/src/forms/helpers/form-helpers.js @@ -97,12 +97,18 @@ export function serializeValue(value) { } export function getSelectedOption(value, options, trackBy) { + if (!trackBy) { + return options.find((option) => option.value === value); + } + + return options.find((option) => getValueByPath(option.value, trackBy) === getValueByPath(value, trackBy)); +} + +export function getSelectedValue(value, options, trackBy) { let selectedValue = value; if (trackBy) { - const selectedOption = options.find( - (option) => getValueByPath(option.value, trackBy) === getValueByPath(value, trackBy) - ); + const selectedOption = getSelectedOption(value, options, trackBy); if (selectedOption) { selectedValue = selectedOption.value; diff --git a/src/forms/index.js b/src/forms/index.js index 94b662a..beb78f6 100644 --- a/src/forms/index.js +++ b/src/forms/index.js @@ -1,6 +1,8 @@ +/* eslint-disable import/max-dependencies */ export * from './Form'; export * from './FormAutocomplete'; export * from './FormCheckbox'; +export * from './FormDropdown'; export * from './FormGroup'; export * from './FormInput'; export * from './FormRadio'; diff --git a/src/forms2/FormSelect.jsx b/src/forms2/FormSelect.jsx index be41ece..763b43f 100644 --- a/src/forms2/FormSelect.jsx +++ b/src/forms2/FormSelect.jsx @@ -4,7 +4,7 @@ import PropTypes from 'prop-types'; import { booleanOrFunction, getOptionsType, - getSelectedOption, + getSelectedValue, normalizeOptions, serializeValue, } from '../forms/helpers/form-helpers'; @@ -40,7 +40,7 @@ export function FormSelect2({ {...attrs} className="custom-select" onChange={handleOnChangeFactory(afterChange, getOptionsType(normalizedOptions))} - value={getSelectedOption(value, normalizedOptions, trackBy)} + value={getSelectedValue(value, normalizedOptions, trackBy)} > {renderOptions(normalizedOptions, trackBy)} diff --git a/src/mixed/Dropdown.jsx b/src/mixed/Dropdown.jsx index d0568bb..27cc182 100644 --- a/src/mixed/Dropdown.jsx +++ b/src/mixed/Dropdown.jsx @@ -14,6 +14,8 @@ export function Dropdown({ onMouseLeave, template, className, + itemClassName, + menuClassName, }) { return (
0 && (
@@ -32,7 +34,7 @@ export function Dropdown({ {template(label)} @@ -59,4 +61,6 @@ Dropdown.propTypes = { onTouchStart: PropTypes.func, template: PropTypes.func, className: PropTypes.string, + itemClassName: PropTypes.string, + menuClassName: PropTypes.string, }; From a5298393262701f42114eb66cc9ab4120b84fc3e Mon Sep 17 00:00:00 2001 From: Nerissa Date: Wed, 25 Aug 2021 17:14:24 -0300 Subject: [PATCH 17/25] chore(release): 0.26.9 --- CHANGELOG.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 295910c..72c3572 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,13 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +### [0.26.9](https://github.com/geolaborapp/react-bootstrap-utils/compare/v0.26.8...v0.26.9) (2021-08-25) + + +### Features + +* new dropdown selection component ([#6](https://github.com/geolaborapp/react-bootstrap-utils/issues/6)) ([60fae42](https://github.com/geolaborapp/react-bootstrap-utils/commit/60fae42059ece24817b61f293aeaa12842e85742)) + ### [0.26.8](https://github.com/geolaborapp/react-bootstrap-utils/compare/v0.26.7...v0.26.8) (2021-08-13) diff --git a/package.json b/package.json index e438cac..c31b6e4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@geolaborapp/react-bootstrap-utils", - "version": "0.26.8", + "version": "0.26.9", "description": "React bootstrap library", "main": "dist/main.js", "scripts": { From 24a2d865811edadd94e82c3835da46f6bded4edc Mon Sep 17 00:00:00 2001 From: Camila Silva Campos <50001507+CamsCampos@users.noreply.github.com> Date: Fri, 3 Sep 2021 16:15:18 -0300 Subject: [PATCH 18/25] feat: makes the use of "template" more flexible for Dropdown and FormDropdown (#9) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: fix use of form dropdown template * wip * Padronizações Co-authored-by: Camila Campos Co-authored-by: Nerissa --- demo/FormExamples.jsx | 43 ++++++++++++++++++++------------------ src/forms/FormDropdown.jsx | 4 ++-- src/mixed/Dropdown.jsx | 2 +- 3 files changed, 26 insertions(+), 23 deletions(-) diff --git a/demo/FormExamples.jsx b/demo/FormExamples.jsx index 334de0c..6e6c3ae 100644 --- a/demo/FormExamples.jsx +++ b/demo/FormExamples.jsx @@ -369,48 +369,51 @@ export function FormExamples() { options={[ { value: { + firstValue: 'Title one', + secondValue: 1, + }, + label: { title: 'Title one', subtitle: 'subtitle one', }, - label: ( -
-
Title one
-

Subtitle one

-
- ), }, { value: { + firstValue: 'Title two', + secondValue: 2, + }, + label: { title: 'Title two', subtitle: 'subtitle two', }, - label: ( -
-
Title two
-

Subtitle two

-
- ), }, { value: { + firstValue: 'Title three', + secondValue: 3, + }, + label: { title: 'Title three', subtitle: 'subtitle three', }, - label: ( -
-
Title three
-

Subtitle three

-
- ), }, ]} help="dropdown help" placeholder="Select one value" afterChange={() => console.log('afterChange dropdown')} - template={(label) =>
{label}
} + template={(label, value) => { + return value ? ( +
+ {label.title ?? '-'} +

{label.subtitle ?? '-'}

+
+ ) : ( + label + ); + }} itemClassName="border-bottom" childClassName="text-muted" - trackBy="title" + trackBy="secondValue" /> (isOpen ? close() : open()), [close, isOpen, open]); useEffect(() => { - /* The logic in this effect allows the user to close the dropdown menu when they click outside of the component. */ + /* The logic in this effect allows the user to close the dropdown menu when they click outside of the component. */ const pageClickEvent = (e) => { if (dropdownRef.current !== null && !dropdownRef.current.contains(e.target)) { if (isOpen) { @@ -92,7 +92,7 @@ export const FormDropdown = ({ className={formatClasses(['input-group justify-content-between form-control h-auto', childClassName])} onClick={toggleDropdown} > - {selectedItem ? template(selectedItem.label) :
{placeholder}
} + {selectedItem ? template(selectedItem.label, selectedItem.value) :
{placeholder}
} {toggleIcon(isOpen)}
diff --git a/src/mixed/Dropdown.jsx b/src/mixed/Dropdown.jsx index 27cc182..320f1ea 100644 --- a/src/mixed/Dropdown.jsx +++ b/src/mixed/Dropdown.jsx @@ -37,7 +37,7 @@ export function Dropdown({ className={formatClasses(['dropdown-item', isDisabled && 'disabled', itemClassName])} onClick={safeClick(onSelect, { value, index, label })} > - {template(label)} + {template(label, value, index)} ))}
From 71e0004af27ab6f7de82548a1596614a35dc277a Mon Sep 17 00:00:00 2001 From: Nerissa Date: Fri, 3 Sep 2021 16:16:49 -0300 Subject: [PATCH 19/25] chore(release): 0.26.10 --- CHANGELOG.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 72c3572..3c7bc5a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,13 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +### [0.26.10](https://github.com/geolaborapp/react-bootstrap-utils/compare/v0.26.9...v0.26.10) (2021-09-03) + + +### Features + +* makes the use of "template" more flexible for Dropdown and FormDropdown ([#9](https://github.com/geolaborapp/react-bootstrap-utils/issues/9)) ([24a2d86](https://github.com/geolaborapp/react-bootstrap-utils/commit/24a2d865811edadd94e82c3835da46f6bded4edc)) + ### [0.26.9](https://github.com/geolaborapp/react-bootstrap-utils/compare/v0.26.8...v0.26.9) (2021-08-25) diff --git a/package.json b/package.json index c31b6e4..28744f0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@geolaborapp/react-bootstrap-utils", - "version": "0.26.9", + "version": "0.26.10", "description": "React bootstrap library", "main": "dist/main.js", "scripts": { From c0c84d175c2ed8143d87b2087fa76da2136faa50 Mon Sep 17 00:00:00 2001 From: Nerissa Date: Thu, 14 Oct 2021 18:16:03 -0300 Subject: [PATCH 20/25] fix: load of an unlisted value in the form autocomplete --- src/forms/FormAutocomplete.jsx | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/forms/FormAutocomplete.jsx b/src/forms/FormAutocomplete.jsx index 6495258..56b62d3 100644 --- a/src/forms/FormAutocomplete.jsx +++ b/src/forms/FormAutocomplete.jsx @@ -10,6 +10,14 @@ import { handleInputChange, normalizeOptions, booleanOrFunction } from './helper import { useFormControl } from './helpers/useFormControl'; import { FormGroup } from './FormGroup'; +function getSelectedItem(selectedItem, value, allowUnlistedValue) { + if (isEmptyLike(selectedItem) && !isEmptyLike(value) && allowUnlistedValue) { + return { value: value, label: value }; + } + + return selectedItem; +} + export function FormAutocomplete({ onSearch, options, @@ -48,7 +56,7 @@ export function FormAutocomplete({ const items = normalizeOptions(options, getFormData(), searchValue); const _selectedItem = items.find((item) => item.value === value); - const [selectedItem, setSelectedItem] = useState(_selectedItem); + const [selectedItem, setSelectedItem] = useState(getSelectedItem(_selectedItem, value, allowUnlistedValue)); const { isOpen, open, close } = useOpenState(); const [ignoreBlur, setIgnoreBlur] = useState(false); const [isFocused, setFocus] = useState(false); @@ -105,7 +113,7 @@ export function FormAutocomplete({ setValue(''); setSelectedItem(null); updateSearchInputValidation(); - } else if (isEmptyLike(selectedItem) && !isEmptyLike(searchValue) && allowUnlistedValue) { + } else if (selectedItem?.value !== searchValue && !isEmptyLike(searchValue) && allowUnlistedValue) { onSelectItem({ value: searchValue, label: searchValue }); } From 58b60389fdea4ba55825470d9e568a1506aee239 Mon Sep 17 00:00:00 2001 From: Nerissa Date: Thu, 14 Oct 2021 18:23:07 -0300 Subject: [PATCH 21/25] ajusta exemplo --- demo/FormExamples.jsx | 1 + 1 file changed, 1 insertion(+) diff --git a/demo/FormExamples.jsx b/demo/FormExamples.jsx index 6e6c3ae..0b1f282 100644 --- a/demo/FormExamples.jsx +++ b/demo/FormExamples.jsx @@ -19,6 +19,7 @@ export function FormExamples() { initialValues={{ textField: 'abc', autocompleteField1: '2345', + autocompleteField4: 'unlisted item', selectField4: { e: 2, c: 'b' }, switchField2: true, checkboxField2: true, From ddecccd715e52461be5139087b1a9b33b6fcccbe Mon Sep 17 00:00:00 2001 From: Nerissa Date: Fri, 15 Oct 2021 09:10:17 -0300 Subject: [PATCH 22/25] chore(release): 0.26.11 --- CHANGELOG.md | 8 ++++++++ package.json | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3c7bc5a..4818032 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,14 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +### [0.26.11](https://github.com/geolaborapp/react-bootstrap-utils/compare/v0.26.10...v0.26.11) (2021-10-15) + + +### Bug Fixes + +* load of an unlisted value in the form autocomplete ([85b5a80](https://github.com/geolaborapp/react-bootstrap-utils/commit/85b5a80efa7865d32dd25f6740b45328f5c7af0f)) +* load of an unlisted value in the form autocomplete ([c0c84d1](https://github.com/geolaborapp/react-bootstrap-utils/commit/c0c84d175c2ed8143d87b2087fa76da2136faa50)) + ### [0.26.10](https://github.com/geolaborapp/react-bootstrap-utils/compare/v0.26.9...v0.26.10) (2021-09-03) diff --git a/package.json b/package.json index 28744f0..c676073 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@geolaborapp/react-bootstrap-utils", - "version": "0.26.10", + "version": "0.26.11", "description": "React bootstrap library", "main": "dist/main.js", "scripts": { From 2f216a4a308fc95332285692c75b84d7fedaecbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Vitor?= Date: Wed, 20 Oct 2021 14:52:44 -0300 Subject: [PATCH 23/25] fix: define default value in align helper function --- src/table/table-helpers.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/table/table-helpers.js b/src/table/table-helpers.js index 2591eb1..9dce8a3 100644 --- a/src/table/table-helpers.js +++ b/src/table/table-helpers.js @@ -15,6 +15,6 @@ export function normalizeColumns(columns) { }); } -export function getColumnClass({ align }) { +export function getColumnClass({ align } = {}) { return formatClasses([align === 'center' ? 'text-center' : align === 'right' ? 'text-right' : '']); } From ae29ccec8c8415206562d340b8aa9a0b53daabf3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Vitor?= Date: Wed, 20 Oct 2021 14:53:01 -0300 Subject: [PATCH 24/25] chore(release): 0.26.12 --- CHANGELOG.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4818032..1bdbdf5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,13 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +### [0.26.12](https://github.com/geolaborapp/react-bootstrap-utils/compare/v0.26.11...v0.26.12) (2021-10-20) + + +### Bug Fixes + +* define default value in align helper function ([2f216a4](https://github.com/geolaborapp/react-bootstrap-utils/commit/2f216a4a308fc95332285692c75b84d7fedaecbd)) + ### [0.26.11](https://github.com/geolaborapp/react-bootstrap-utils/compare/v0.26.10...v0.26.11) (2021-10-15) diff --git a/package.json b/package.json index c676073..a142171 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@geolaborapp/react-bootstrap-utils", - "version": "0.26.11", + "version": "0.26.12", "description": "React bootstrap library", "main": "dist/main.js", "scripts": { From 6fe2abedfc92440764acac938e78e9b90616f72f Mon Sep 17 00:00:00 2001 From: Juliana Marinho Date: Fri, 22 Oct 2021 13:35:57 -0300 Subject: [PATCH 25/25] wip --- demo/TableExamples.jsx | 27 +++++++++++++++++++++++++++ src/table/TableBody.jsx | 3 ++- src/table/TableHead.jsx | 4 +++- 3 files changed, 32 insertions(+), 2 deletions(-) diff --git a/demo/TableExamples.jsx b/demo/TableExamples.jsx index 414cb03..7bae878 100644 --- a/demo/TableExamples.jsx +++ b/demo/TableExamples.jsx @@ -321,6 +321,33 @@ export function TableExamples() { ]} /> +
+

Table with column hideIf

+ +
{getColumnValue(doc, column, docIndex)}
- {columnHeaderFormat(column.label, column.attribute)} + {columnHeaderFormat(column.label, column.attribute, column)} {actionLabel}
true, + }, + { + attribute: 'b', + label: 'B', + }, + { + attribute: 'c', + label: 'C', + }, + ]} + docs={[ + { a: 'B', b: 'G', c: 'Y' }, + { a: 'C', b: 'I', c: 'Z' }, + { a: 'A', b: 'H', c: 'X' }, + { a: 'D', b: 'L', c: 'T' }, + ]} + /> + ); diff --git a/src/table/TableBody.jsx b/src/table/TableBody.jsx index d9183d8..c038b47 100644 --- a/src/table/TableBody.jsx +++ b/src/table/TableBody.jsx @@ -11,12 +11,13 @@ import { TableActions } from './TableActions'; export function TableBody({ columns, docs, rowRole, rowClass, actions, onRowClick }) { const trRole = rowRole ?? isFunction(onRowClick) ? 'button' : 'row'; const trOnClick = isFunction(onRowClick) ? onRowClick : () => {}; + const filteredColumns = columns.filter((column) => !column.hideIf?.()); return ( {docs?.map((doc, docIndex) => ( - {columns?.map((column, columnIndex) => ( + {filteredColumns?.map((column, columnIndex) => ( diff --git a/src/table/TableHead.jsx b/src/table/TableHead.jsx index 0acc324..d26a1d2 100644 --- a/src/table/TableHead.jsx +++ b/src/table/TableHead.jsx @@ -4,10 +4,12 @@ import PropTypes from 'prop-types'; import { getColumnClass } from './table-helpers'; export function TableHead({ columns, hasActions, actionLabel, columnHeaderFormat }) { + const filteredColumns = columns.filter((column) => !column.hideIf?.()); + return ( - {columns?.map((column, columnIndex) => ( + {filteredColumns?.map((column, columnIndex) => (
{getColumnValue(doc, column, docIndex)}
{columnHeaderFormat(column.label, column.attribute, column)}