UNPKG

@render-props/choices

Version:

A state container which provides an interface for making selections from a group of choices. The `Choices` component itself is a context provider which can be used with the `Choice` and `ChoicesConsumer` components for deep-tree selections. It does not ha

274 lines (238 loc) 7.57 kB
'use strict' var _interopRequireDefault = require('@babel/runtime/helpers/interopRequireDefault') exports.__esModule = true exports.default = Choices var _objectSpread2 = _interopRequireDefault( require('@babel/runtime/helpers/objectSpread') ) var _react = _interopRequireDefault(require('react')) var _propTypes = _interopRequireDefault(require('prop-types')) var _utils = require('@render-props/utils') var _items = _interopRequireDefault(require('@render-props/items')) var _ChoicesContext = _interopRequireDefault(require('./ChoicesContext')) var _invariants = require('./invariants') var _utils2 = require('./utils') /** import Choices, {Choice} from '@render-props/choices' const FavoritePets = props => ( <Choices initialChoices={new Set(['cat', 'dog', 'turtle'])} initialSelections={new Set(['cat'])} minChoices={1} minSelections={1} maxSelections={2} onBoundMaxSelections={ function ({selections, select, deselect}) { selections = Array.from(selections) deselect(selections.shift()) select(selections.pop()) } } > {PetsControl} </Choices> ) const PetsControl = ({ addChoice, deleteChoice, setChoices, clearChoices, isChoice, select, deselect, setSelections, clearSelections, isSelected, selections, choices }) => ( <div style={{borderWidth: 1}}> <span> Number of favorites: {selections.size} </span> { Array.from(choices).map(pet => ( <Choice key={pet} value={pet}> { function ({select, deselect, toggle, isSelected}) { return ( <button onClick={toggle} style={ isSelected ? {backgroundColor: 'green'} : {backgroundColor: 'grey'} } > {pet} </button> ) } } </Choice> )) } </div> ) */ function Choices(props) { const nextProps = { children: props.children, } function _ref(selectionsContext) { nextProps.select = selectionsContext.addItem nextProps.deselect = selectionsContext.deleteItem nextProps.setSelections = selectionsContext.setItems nextProps.isSelected = selectionsContext.includes nextProps.clearSelections = selectionsContext.clearItems nextProps.selections = selectionsContext.items return _react.default.createElement(Choices_, nextProps) } return _react.default.createElement( _items.default, { initialItems: props.initialChoices, minItems: props.minChoices, maxItems: props.maxChoices, onAdd: props.onAddChoice, onDelete: props.onDeleteChoice, onChange: props.onChoicesChange, onBoundMax: (0, _utils2.boundChoices)(props.onBoundMinChoices), onBoundMin: (0, _utils2.boundChoices)(props.onBoundMaxChoices), }, function(choicesContext) { nextProps.addChoice = choicesContext.addItem nextProps.deleteChoice = choicesContext.deleteItem nextProps.clearChoices = choicesContext.clearItems nextProps.setChoices = choicesContext.setItems nextProps.isChoice = choicesContext.includes nextProps.choices = choicesContext.items return _react.default.createElement( _items.default, { initialItems: props.initialSelections, minItems: props.minSelections, maxItems: props.maxSelections, onAdd: props.onSelect, onDelete: props.onDeselect, onChange: props.onChange, onBoundMin: (0, _utils2.boundSelections)(props.onBoundMinSelections), onBoundMax: (0, _utils2.boundSelections)(props.onBoundMaxSelections), }, _ref ) } ) } Choices.propTypes = { children: _propTypes.default.func.isRequired, // choices initialChoices: _propTypes.default.oneOfType([ _propTypes.default.array, _propTypes.default.instanceOf(Set), ]), minChoices: _propTypes.default.number, maxChoices: _propTypes.default.number, onAddChoice: _propTypes.default.func, onDeleteChoice: _propTypes.default.func, onChoicesChange: _propTypes.default.func, onBoundMinChoices: _propTypes.default.func, onBoundMaxChoices: _propTypes.default.func, // selections initialSelections: _propTypes.default.oneOfType([ _propTypes.default.array, _propTypes.default.instanceOf(Set), ]), minSelections: _propTypes.default.number, maxSelections: _propTypes.default.number, onSelect: _propTypes.default.func, onDeselect: _propTypes.default.func, onChange: _propTypes.default.func, onBoundMinSelections: _propTypes.default.func, onBoundMaxSelections: _propTypes.default.func, } class Choices_ extends _react.default.Component { constructor(props) { super(props) this.select = (...items) => { this.ifChoicesInclude(items) return this.props.select(...items) } this.deselect = (...items) => { this.ifChoicesInclude(items) return this.props.deselect(...items) } this.toggle = item => this.props.isSelected(item) ? this.deselect(item) : this.select(item) this.setSelections = items => { this.ifChoicesInclude(items) return this.props.setSelections(items) } this.deleteChoice = (...items) => { const {isSelected, minSelections, deleteChoice} = this.props const whichSize = this.props.selections.size === void 0 ? 'length' : 'size' // removes all selections referencing this choice for (let x = 0; x < items.length; x++) { const item = items[x] if (isSelected(item)) { this.deselect(item) if (minSelections > this.props.selections[whichSize] - 1) { return } } } // deletes the choice return deleteChoice(...items) } this.setChoices = items => { const diff = Array.from(items).filter(item => this.props.isChoice(item)) if (diff.length) { this.props.deleteChoice(...diff) } return this.props.setChoices(items) } this.clearChoices = () => { this.props.clearSelections() this.props.clearChoices() } this.choicesContext = { select: this.select, deselect: this.deselect, toggle: this.toggle, setSelections: this.setSelections, clearSelections: this.props.clearSelections, isSelected: this.props.isSelected, addChoice: this.props.addChoice, deleteChoice: this.deleteChoice, setChoices: this.setChoices, clearChoices: this.clearChoices, isChoice: this.props.isChoice, selections: null, choices: null, } } ifChoicesInclude(items) { if (typeof process !== void 0 && process.env.NODE_ENV !== 'production') { for (let x = 0; x < items.length; x++) { ;(0, _invariants.includesInvariant)(this.props.choices, items[x]) } } } render() { if ( this.choicesContext.selections !== this.props.selections || this.choicesContext.choices !== this.props.choices ) { this.choicesContext = (0, _objectSpread2.default)({}, this.choicesContext) } this.choicesContext.selections = this.props.selections this.choicesContext.choices = this.props.choices return _react.default.createElement( _ChoicesContext.default.Provider, { value: this.choicesContext, }, this.props.children(this.choicesContext) ) } } Choices_.displayName = 'Choices'