UNPKG

@prosperitainova/dumbo-react-native

Version:
260 lines (256 loc) 7.86 kB
"use strict"; import React from 'react'; import { StyleSheet, View, Pressable, Modal as ReactModal, Dimensions } from 'react-native'; import { getColor, shadowStyle } from '../../styles/colors'; import { createIcon, pressableFeedbackStyle, styleReferenceBreaker } from '../../helpers'; import { Menu } from '../Menu'; import { getTextInputStyle } from '../BaseTextInputs'; import { Text } from '../Text'; import ChevronDownIcon from '@carbon/icons/es/chevron--down/20'; import ChevronUpIcon from '@carbon/icons/es/chevron--up/20'; import { modalPresentations } from '../../constants/constants'; import { zIndexes } from '../../styles/z-index'; import { defaultText } from '../../constants/defaultText'; /** An item to pass to the Dropdown component */ /** Props for Dropdown component */ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; /** * Dropdown component for rendering a dropdown * * {@link https://github.com/carbon-design-system/carbon-react-native/blob/main/example/src/Views/Dropdown.tsx | Example code} */ export class Dropdown extends React.Component { state = { open: false, renderLeft: 0, renderRight: 0, renderTop: 0, renderBottom: 0, inverseMenu: false }; get itemColor() { const { disabled } = this.props; return disabled ? getColor('textDisabled') : getColor('textPrimary'); } get styles() { const { renderLeft, renderRight, renderTop, renderBottom, inverseMenu } = this.state; const { maxMenuHeight } = this.props; return StyleSheet.create({ modal: { zIndex: zIndexes.dropdown }, wrapper: {}, innerWrapper: { position: 'relative' }, closeModal: { zIndex: zIndexes.behind, top: 0, right: 0, bottom: 0, left: 0, position: 'absolute' }, menuWrapper: { position: 'absolute', top: renderTop, bottom: renderBottom, right: renderRight, left: renderLeft, maxHeight: inverseMenu ? undefined : maxMenuHeight || 280, flexDirection: inverseMenu ? 'column-reverse' : undefined, ...shadowStyle }, iconStyle: { position: 'absolute', top: 13, right: 13 }, dropdownText: { color: this.itemColor, paddingRight: 32 } }); } get textInputStyles() { const { light } = this.props; return getTextInputStyle(light); } get dropdownIcon() { const { open } = this.state; return /*#__PURE__*/_jsx(View, { style: this.styles.iconStyle, children: createIcon(open ? ChevronUpIcon : ChevronDownIcon, 20, 20, this.itemColor) }); } toggleDropdown = () => { const { open } = this.state; this.setState({ open: !open }); }; closeDropdown = () => { this.setState({ open: false }); }; getStateStyle = state => { return state.pressed ? { backgroundColor: getColor('layerActive01'), borderColor: getColor('layerActive01') } : undefined; }; /** * Calculate where to render the overlayed dropdown menu * Sometimes didMount is not called before full render and results in all 0. setTimeout waits for load * * In event measure returns bad it will load to top of page with min width/height. * * @param item - View from reference */ setFormItemRef = item => { if (item && typeof item?.measure === 'function') { setTimeout(() => { const { renderLeft, renderRight, renderTop, renderBottom, inverseMenu } = this.state; const screenWidth = Dimensions.get('window').width || 320; const screenHeight = Dimensions.get('window').height || 320; const baseSafePadding = 44; item.measure((_fx, _fy, width, height, pageX, pageY) => { const newRenderLeft = pageX || 0; const newRenderRight = screenWidth - (newRenderLeft + (width || 200)); let newRenderTop = (pageY || 0) + (height || 200); let newRenderBottom = baseSafePadding; let newInverse = false; if (newRenderTop > screenHeight - 200) { newRenderBottom = screenHeight - (pageY || 0); newRenderTop = baseSafePadding; newInverse = true; } if (renderLeft !== newRenderLeft || renderRight !== newRenderRight || renderTop !== newRenderTop || renderBottom !== newRenderBottom || inverseMenu !== newInverse) { this.setState({ renderLeft: newRenderLeft, renderRight: newRenderRight, renderTop: newRenderTop, renderBottom: newRenderBottom, inverseMenu: newInverse }); } }); }); } }; render() { const { items, componentProps, style, label, helperText, value, onChange, disabled, closeText, valueToText, unsetText } = this.props; const { open } = this.state; const finalStyle = styleReferenceBreaker(disabled ? this.textInputStyles.textBoxDisabled : this.textInputStyles.textBox); finalStyle.paddingTop = 10; const currentText = typeof valueToText === 'function' ? valueToText(value) : value; if (open) { finalStyle.borderBottomColor = getColor('borderSubtle01'); } const itemList = items.map((item, index) => { const newItem = Object.assign({}, item); newItem.style = { borderBottomColor: getColor('borderSubtle01'), borderBottomWidth: items.length === index + 1 ? 0 : 1, paddingRight: 0, paddingLeft: 0, marginRight: 16, marginLeft: 16 }; newItem.onPress = () => { this.setState({ open: false }); if (typeof onChange === 'function') { onChange(item); } }; return newItem; }); return /*#__PURE__*/_jsxs(View, { style: styleReferenceBreaker(this.styles.wrapper, style), accessibilityRole: "menu", ...(componentProps || {}), children: [!!label && /*#__PURE__*/_jsx(Text, { style: this.textInputStyles.label, type: "label-02", text: label }), /*#__PURE__*/_jsxs(View, { style: this.styles.innerWrapper, children: [/*#__PURE__*/_jsxs(Pressable, { disabled: disabled, style: state => pressableFeedbackStyle(state, finalStyle, this.getStateStyle), accessibilityLabel: label, accessibilityHint: currentText, onPress: this.toggleDropdown, ref: this.setFormItemRef, children: [/*#__PURE__*/_jsx(Text, { text: currentText || unsetText, breakMode: "tail", style: this.styles.dropdownText }), this.dropdownIcon] }), open && /*#__PURE__*/_jsxs(ReactModal, { style: this.styles.modal, supportedOrientations: modalPresentations, transparent: true, onRequestClose: () => this.setState({ open: false }), children: [/*#__PURE__*/_jsx(Pressable, { style: this.styles.closeModal, accessibilityRole: "button", accessibilityLabel: closeText || defaultText.close, onPress: this.closeDropdown }), /*#__PURE__*/_jsx(View, { style: this.styles.menuWrapper, children: /*#__PURE__*/_jsx(Menu, { items: itemList }) })] })] }), !!helperText && /*#__PURE__*/_jsx(Text, { style: this.textInputStyles.helperText, type: "helper-text-02", text: helperText })] }); } } //# sourceMappingURL=index.js.map