From 1eb9a72168eb5e8799815255c363fafcd90d942e Mon Sep 17 00:00:00 2001 From: chris <kokosias@yahoo.gr> Date: Tue, 7 Nov 2023 17:15:45 +0200 Subject: [PATCH] dropdown options --- .../components/EditorComponent.js | 3 +- .../NumericalAnswerContainerNodeView.js | 6 +- .../NumericalAnswerDropDownCompontent.js | 163 +++++++++++++++++- 3 files changed, 164 insertions(+), 8 deletions(-) diff --git a/wax-questions-service/src/MultipleChoiceQuestionService/components/EditorComponent.js b/wax-questions-service/src/MultipleChoiceQuestionService/components/EditorComponent.js index 828d5d686..0d1cc820a 100644 --- a/wax-questions-service/src/MultipleChoiceQuestionService/components/EditorComponent.js +++ b/wax-questions-service/src/MultipleChoiceQuestionService/components/EditorComponent.js @@ -191,7 +191,8 @@ const QuestionEditorComponent = ({ } }, }, - + scrollMargin: 200, + scrollThreshold: 200, attributes: { spellcheck: 'false', }, diff --git a/wax-questions-service/src/NumericalAnswerService/NumericalAnswerContainerNodeView.js b/wax-questions-service/src/NumericalAnswerService/NumericalAnswerContainerNodeView.js index 460e1f78e..9de069ea1 100644 --- a/wax-questions-service/src/NumericalAnswerService/NumericalAnswerContainerNodeView.js +++ b/wax-questions-service/src/NumericalAnswerService/NumericalAnswerContainerNodeView.js @@ -27,7 +27,11 @@ export default class NumericalAnswerContainerNodeView extends QuestionsNodeView } stopEvent(event) { - if (event.target.type === 'textarea' || !event.target.type) { + if ( + event.target.type === 'textarea' || + event.target.type === 'button' || + !event.target.type + ) { return true; } diff --git a/wax-questions-service/src/NumericalAnswerService/components/NumericalAnswerDropDownCompontent.js b/wax-questions-service/src/NumericalAnswerService/components/NumericalAnswerDropDownCompontent.js index b9901a6c8..24ae58d89 100644 --- a/wax-questions-service/src/NumericalAnswerService/components/NumericalAnswerDropDownCompontent.js +++ b/wax-questions-service/src/NumericalAnswerService/components/NumericalAnswerDropDownCompontent.js @@ -26,14 +26,49 @@ const DropDownButton = styled.button` cursor: ${props => (props.disabled ? 'not-allowed' : 'pointer')}; display: flex; position: relative; - width: 160px; + width: 215px; + height: 100%; span { position: relative; - top: 2px; + top: 12px; } `; +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: 2px auto auto; + position: absolute; + width: 220px; + max-height: 150px; + overflow-y: auto; + z-index: 2; + + span { + cursor: pointer; + font-size: 11px; + padding: 8px 10px; + } + + span:focus { + background: #f2f9fc; + outline: 2px solid #f2f9fc; + } +`; + +const StyledIcon = styled(Icon)` + height: 18px; + width: 18px; + margin-left: auto; + position: relative; +`; + const NumericalAnswerDropDownCompontent = ({ view = {}, item }) => { const dropDownOptions = [ { @@ -50,19 +85,135 @@ const NumericalAnswerDropDownCompontent = ({ view = {}, item }) => { }, ]; - const { activeView } = useContext(WaxContext); + const context = useContext(WaxContext); + const { + activeView, + activeViewId, + pmViews: { main }, + } = context; + const { state } = view; + const itemRefs = useRef([]); const wrapperRef = useRef(); const [isOpen, setIsOpen] = useState(false); - const isDisabled = false; - useOnClickOutside(wrapperRef, () => setIsOpen(false)); + const [label, setLabel] = useState('Select Type'); + const isEditable = main.props.editable(editable => { + return editable; + }); + + useEffect(() => { + setLabel('Select Type'); + dropDownOptions.forEach(option => { + // if (option.item.active(main.state)) { + // setLabel(option.label); + // } + }); + }, [activeViewId]); + + let isDisabled = false; + useEffect(() => { if (isDisabled) setIsOpen(false); }, [isDisabled]); - return <>dropDown</>; + 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) { + setIsOpen(false); + } + }; + + const onChange = option => { + tools[option.value].run(main, context); + openCloseMenu(); + }; + + const NumericalAnswerDropDown = useMemo( + () => ( + <Wrapper disabled={isDisabled} ref={wrapperRef}> + <DropDownButton + aria-controls="questions-list" + aria-expanded={isOpen} + aria-haspopup + disabled={isDisabled} + onKeyDown={e => { + if (e.keyCode === 40) { + itemRefs.current[0].current.focus(); + } + if (e.keyCode === 27) { + setIsOpen(false); + } + if (e.keyCode === 13 || e.keyCode === 32) { + setIsOpen(true); + } + }} + onMouseDown={openCloseMenu} + type="button" + > + <span>{label}</span> <StyledIcon name="expand" /> + </DropDownButton> + <DropDownMenu + aria-label="Choose an item type" + id="questions-list" + isOpen={isOpen} + role="menu" + > + {dropDownOptions.map((option, index) => { + itemRefs.current[index] = itemRefs.current[index] || createRef(); + return ( + <span + key={option.value} + onClick={() => onChange(option)} + onKeyDown={e => onKeyDown(e, index)} + ref={itemRefs.current[index]} + role="menuitem" + tabIndex="-1" + > + {option.label} + </span> + ); + })} + </DropDownMenu> + </Wrapper> + ), + [isDisabled, isOpen, label], + ); + + return NumericalAnswerDropDown; }; export default NumericalAnswerDropDownCompontent; -- GitLab