diff --git a/wax-prosemirror-services/src/MatchingService/components/DropDownComponent.js b/wax-prosemirror-services/src/MatchingService/components/DropDownComponent.js index 558ceb785b91efc11d2613ca336640235e3c0197..803f7c3596da4217a43627b3ff29d90ec3b02013 100644 --- a/wax-prosemirror-services/src/MatchingService/components/DropDownComponent.js +++ b/wax-prosemirror-services/src/MatchingService/components/DropDownComponent.js @@ -1,61 +1,93 @@ +/* eslint-disable no-unused-vars */ /* eslint-disable no-underscore-dangle */ -import React, { useContext, useMemo, useState } from 'react'; +import React, { + useMemo, + useContext, + useState, + useEffect, + useRef, + createRef, +} from 'react'; import styled from 'styled-components'; import { WaxContext, DocumentHelpers, - ReactDropDownStyles, + Icon, + useOnClickOutside, } from 'wax-prosemirror-core'; import Dropdown from 'react-dropdown'; import { v4 as uuidv4 } from 'uuid'; const Wrapper = styled.div` - ${ReactDropDownStyles}; + opacity: ${props => (props.disabled ? '0.4' : '1')}; + cursor: ${props => (props.disabled ? 'not-allowed' : 'pointer')}; `; -const DropdownStyled = styled(Dropdown)` - cursor: not-allowed; - display: inline-flex; - margin-left: auto; - opacity: ${props => (props.select ? 1 : 0.4)}; - pointer-events: ${props => (props.select ? 'default' : 'none')}; - - .Dropdown-control { - border: none; - padding: 8px 30px 8px 10px; - &:hover { - box-shadow: none; - } +const DropDownButton = styled.button` + background: #fff; + border: none; + color: #000; + cursor: pointer; + display: flex; + position: relative; + width: 160px; + + span { + position: relative; + top: 2px; } +`; - .Dropdown-arrow { - top: 17px; +const DropDownMenu = styled.div` + visibility: ${props => (props.isOpen ? 'visible' : 'hidden')}; + background: #fff; + display: flex; + flex-direction: column; + border: 1px solid #ddd; + border-radius: 0.25rem; + box-shadow: 0 0.2rem 0.4rem rgb(0 0 0 / 10%); + margin: 10px auto auto; + position: absolute; + width: 170px; + max-height: 150px; + overflow-y: scroll; + z-index: 2; + + span { + cursor: pointer; + padding: 8px 10px; } - .Dropdown-menu { - align-items: flex-start; - display: flex; - flex-direction: column; - width: 102%; - - .Dropdown-option { - width: 100%; - } + span:focus { + background: #f2f9fc; + outline: 2px solid #f2f9fc; } `; +const StyledIcon = styled(Icon)` + height: 18px; + width: 18px; + margin-left: auto; +`; + const DropComponent = ({ getPos, node, view }) => { const [selectedOption, setSelectedOption] = useState(node.attrs.correct); + const itemRefs = useRef([]); + const wrapperRef = useRef(); + const [isOpen, setIsOpen] = useState(false); const context = useContext(WaxContext); const { pmViews: { main }, + activeView, } = context; const isEditable = main.props.editable(editable => { return editable; }); + const isDisabled = false; + const onChange = option => { const allNodes = getNodes(main); allNodes.forEach(singleNode => { @@ -70,29 +102,89 @@ const DropComponent = ({ getPos, node, view }) => { ); } }); + openCloseMenu(); }; - // useEffect(() => { - // const found = find(node.attrs.options, { value: node.attrs.correct }); + useOnClickOutside(wrapperRef, () => setIsOpen(false)); + + useEffect(() => { + if (isDisabled) setIsOpen(false); + }, [isDisabled]); - // if (found) { - // setSelectedOption(found); - // } - // }, [node.attrs.options]); + const openCloseMenu = () => { + if (!isDisabled) setIsOpen(!isOpen); + if (isOpen) + setTimeout(() => { + activeView.focus(); + }); + }; + + const onKeyDown = (e, index) => { + e.preventDefault(); + // arrow down + if (e.keyCode === 40) { + if (index === itemRefs.current.length - 1) { + itemRefs.current[0].current.focus(); + } else { + itemRefs.current[index + 1].current.focus(); + } + } + + // arrow up + if (e.keyCode === 38) { + if (index === 0) { + itemRefs.current[itemRefs.current.length - 1].current.focus(); + } else { + itemRefs.current[index - 1].current.focus(); + } + } + + // enter + if (e.keyCode === 13) { + itemRefs.current[index].current.click(); + } + + // ESC + if (e.keyCode === 27) { + openCloseMenu(); + } + }; const MultipleDropDown = useMemo( () => ( - <Wrapper key={uuidv4()}> - <DropdownStyled - key={uuidv4()} - onChange={option => onChange(option)} - options={node.attrs.options} - placeholder="Select option" - select={isEditable} - value={ - selectedOption === 'undefined' ? 'Select Option' : selectedOption - } - /> + <Wrapper disabled={isDisabled} ref={wrapperRef}> + <DropDownButton + aria-expanded={isOpen} + aria-haspopup + onKeyDown={e => { + e.preventDefault(); + if (e.keyCode === 40) { + itemRefs.current[0].current.focus(); + } + }} + onMouseDown={openCloseMenu} + tabIndex="0" + type="button" + > + <span>Table Options</span> <StyledIcon name="expand" /> + </DropDownButton> + <DropDownMenu isOpen={isOpen} role="menu"> + {node.attrs.options.map((option, index) => { + itemRefs.current[index] = itemRefs.current[index] || createRef(); + return ( + <span + key={option.value} + onClick={onChange} + onKeyDown={e => onKeyDown(e, index)} + ref={itemRefs.current[index]} + role="menuitem" + tabIndex="-1" + > + {option.label} + </span> + ); + })} + </DropDownMenu> </Wrapper> ), [node.attrs.options, selectedOption],