diff --git a/docs/components_page/components/input/__init__.py b/docs/components_page/components/input/__init__.py index 6c48e24a3..f8820263f 100644 --- a/docs/components_page/components/input/__init__.py +++ b/docs/components_page/components/input/__init__.py @@ -12,6 +12,7 @@ from ...metadata import get_component_metadata from .number_input import number_input as input_numeric from .radio_check_inline import inline_inputs +from .select import select as input_select from .selected_styles import checklist as input_selected_styles from .size import inputs as input_size from .text_label import text_input as input_text_label @@ -25,6 +26,7 @@ input_text_label_source = (HERE / "text_label.py").read_text() input_size_source = (HERE / "size.py").read_text() input_validation_source = (HERE / "validation.py").read_text() +input_select_source = (HERE / "select.py").read_text() input_radio_check_source = (HERE / "radio_check.py").read_text() input_textarea_source = (HERE / "textarea.py").read_text() input_radio_check_inline_source = (HERE / "radio_check_inline.py").read_text() @@ -143,6 +145,20 @@ def get_content(app): ), ExampleContainer(input_textarea), HighlightedSource(input_textarea_source), + html.H4("Select"), + html.P( + dcc.Markdown( + "The `Select` component can be used to render a Bootstrap " + "themed select input. The options are specified with a list " + "of dictionaries much like the `Dropdown` component in " + "_dash-core-components_, i.e. with keys `'label'`, `'value'` " + "and optional key `'disabled'`. Like `Input` it also accepts " + "keyword arguments such as `bs_size`, `valid`, `invalid`, all " + "of which can be targeted with callbacks." + ) + ), + ExampleContainer(input_select), + HighlightedSource(input_select_source), html.H4("RadioItems and Checklist"), html.P( dcc.Markdown( diff --git a/docs/components_page/components/input/select.py b/docs/components_page/components/input/select.py new file mode 100644 index 000000000..9b8ef94f8 --- /dev/null +++ b/docs/components_page/components/input/select.py @@ -0,0 +1,10 @@ +import dash_bootstrap_components as dbc + +select = dbc.Select( + id="select", + options=[ + {"label": "Option 1", "value": "1"}, + {"label": "Option 2", "value": "2"}, + {"label": "Disabled option", "value": "3", "disabled": True}, + ], +) diff --git a/package.json b/package.json index 38eae47e0..e53b12112 100644 --- a/package.json +++ b/package.json @@ -66,9 +66,9 @@ "moment": "^2.22.2", "prop-types": "^15.6.2", "ramda": "^0.25.0", - "react": "^16.5.2", + "react": "^16.9.0", "react-addons-shallow-compare": "^15.6.0", - "react-dom": "^16.5.2", + "react-dom": "^16.9.0", "reactstrap": "^8.0.0" }, "jest": { diff --git a/src/components/input/Select.js b/src/components/input/Select.js new file mode 100644 index 000000000..a3e1dac07 --- /dev/null +++ b/src/components/input/Select.js @@ -0,0 +1,115 @@ +import React, {useState} from 'react'; +import PropTypes from 'prop-types'; +import {omit} from 'ramda'; +import {CustomInput} from 'reactstrap'; + +const Select = props => { + const [value, setValue] = useState(props.value); + + const handleChange = e => { + if (props.setProps) { + props.setProps({value: e.target.value}); + } + setValue(e.target.value); + }; + + return ( + + {props.options.map(option => ( + + ))} + + ); +}; + +Select.propTypes = { + /** + * The ID of this component, used to identify dash components + * in callbacks. The ID needs to be unique across all of the + * components in an app. + */ + id: PropTypes.string, + + /** + * Defines CSS styles which will override styles previously set. + */ + style: PropTypes.object, + + /** + * Often used with CSS to style elements with common properties. + */ + className: PropTypes.string, + + /** + * A unique identifier for the component, used to improve + * performance by React.js while rendering components + * See https://reactjs.org/docs/lists-and-keys.html for more info + */ + key: PropTypes.string, + + /** + * The value of the currently selected option. + */ + value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), + + /** + * An array of options for the select + */ + options: PropTypes.arrayOf( + PropTypes.exact({ + /** + * The options's label + */ + label: PropTypes.oneOfType([PropTypes.string, PropTypes.number]) + .isRequired, + + /** + * The value of the option. This value corresponds to the items + * specified in the `value` property. + */ + value: PropTypes.string.isRequired, + + /** + * If true, this checkbox is disabled and can't be clicked on. + */ + disabled: PropTypes.bool + }) + ), + + /** + * Set to True to disable the Select. + */ + disabled: PropTypes.bool, + + /** + * Apply valid style to the Input for feedback purposes. This will cause + * any FormFeedback in the enclosing FormGroup with valid=True to display. + */ + valid: PropTypes.bool, + + /** + * Apply invalid style to the Input for feedback purposes. This will cause + * any FormFeedback in the enclosing FormGroup with valid=False to display. + */ + invalid: PropTypes.bool, + + /** + * Set the size of the Input. Options: 'sm' (small), 'md' (medium) + * or 'lg' (large). Default is 'md'. + */ + bs_size: PropTypes.string +}; + +export default Select; diff --git a/src/index.js b/src/index.js index 07de0643c..ec8fd8091 100644 --- a/src/index.js +++ b/src/index.js @@ -56,6 +56,7 @@ export {default as Progress} from './components/Progress'; export {default as RadioItems} from './components/input/RadioItems'; export {default as RadioButton} from './components/input/RadioButton'; export {default as Row} from './components/layout/Row'; +export {default as Select} from './components/input/Select'; export {default as Spinner} from './components/Spinner'; export {default as Tab} from './components/tabs/Tab'; export {default as Tabs} from './components/tabs/Tabs';