From de5a52810cea280e10a87902eedc172567d17742 Mon Sep 17 00:00:00 2001 From: Federico Zivolo Date: Tue, 2 Apr 2019 18:49:51 +0200 Subject: [PATCH] feat: add `renderDropdown` prop to react-dropdown This property allows to define a custom rendering logic for the dropdown component. --- .../src/__mocks__/DropdownWrapper.js | 4 +- packages/react-dropdown/src/index.js | 39 +++++++++++-------- packages/react-dropdown/src/index.md | 36 +++++++++++++++++ packages/react-dropdown/src/index.test.js | 15 +++++++ 4 files changed, 76 insertions(+), 18 deletions(-) diff --git a/packages/react-dropdown/src/__mocks__/DropdownWrapper.js b/packages/react-dropdown/src/__mocks__/DropdownWrapper.js index 7e92d5df..9f4a11ac 100644 --- a/packages/react-dropdown/src/__mocks__/DropdownWrapper.js +++ b/packages/react-dropdown/src/__mocks__/DropdownWrapper.js @@ -6,7 +6,7 @@ */ // @flow -import React from 'react'; +import * as React from 'react'; import Dropdown from '../index'; type State = { @@ -33,10 +33,10 @@ class DropdownWrapper extends React.Component { render() { return ( {({ getInputProps }) => } diff --git a/packages/react-dropdown/src/index.js b/packages/react-dropdown/src/index.js index f6f187f3..84b309ab 100644 --- a/packages/react-dropdown/src/index.js +++ b/packages/react-dropdown/src/index.js @@ -59,12 +59,15 @@ type Props = { Array, MultiControllerStateAndHelpers ) => void, + renderDropdown?: ({ dropdown: React.Node }) => React.Node, }; const DropdownContainer = styled.div` display: inline-block; `; +const defaultRenderDropdown = ({ dropdown }) => dropdown; + /** @visibleName Usage example */ const Dropdown = ({ filterFn = filterItems, @@ -84,6 +87,7 @@ const Dropdown = ({ onChange, onSelect, highlight = false, + renderDropdown = defaultRenderDropdown, ...props }: Props) => { if (defaultSelectedItems != null && selectedItems != null) { @@ -156,22 +160,25 @@ const Dropdown = ({ }) } - {isOpen && ( - - )} + {isOpen && + renderDropdown({ + dropdown: ( + + ), + })} )} diff --git a/packages/react-dropdown/src/index.md b/packages/react-dropdown/src/index.md index a3aba4c5..38bc967a 100644 --- a/packages/react-dropdown/src/index.md +++ b/packages/react-dropdown/src/index.md @@ -156,3 +156,39 @@ const items = [ )} ; ``` + +#### Dropdown with custom render function: + +```js +const ReactDOM = require('react-dom'); + +const items = [ + { id: 1, label: 'Alaska airlines' }, + { id: 2, label: 'Allegiant Air' }, + { id: 3, label: 'American Airlines' }, + { id: 4, label: 'Delta Air Lines' }, + { id: 5, label: 'Frontier Airlines' }, + { id: 6, label: 'Hawaiian Airlines' }, + { id: 7, label: 'JetBlue Airways' }, + { id: 8, label: 'Southwest Airlines' }, + { id: 9, label: 'Spirit Airlines' }, + { id: 10, label: 'Sun Country Airlines' }, + { id: 11, label: 'United Airlines' }, +]; + + ReactDOM.createPortal(dropdown, document.querySelector('#rsg-root')) + } +> + {({ getInputProps }) => ( + + )} +; +``` diff --git a/packages/react-dropdown/src/index.test.js b/packages/react-dropdown/src/index.test.js index 64b3064f..314519c4 100644 --- a/packages/react-dropdown/src/index.test.js +++ b/packages/react-dropdown/src/index.test.js @@ -750,3 +750,18 @@ it('empty selected items should result in empty string input value ', () => { .props().value ).toBe(11); }); + +it('custom renderDropdown function should render', () => { + const wrapper = mount( +
{dropdown}
} + /> + ); + + expect(wrapper.find('#foobar')).toHaveLength(1); + + expect(wrapper.find('ul li').hostNodes().length > 0).toBe(true); +});