Skip to content

Commit

Permalink
feat(transfer): use native single-/multi selects
Browse files Browse the repository at this point in the history
  • Loading branch information
Mohammer5 committed Jul 24, 2024
1 parent 457e04f commit ee209d0
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 70 deletions.
86 changes: 53 additions & 33 deletions components/transfer/src/options-container.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,12 @@ export const OptionsContainer = ({
getOptionClickHandlers,
highlightedOptions,
loading,
maxSelections,
renderOption,
options,
selected,
selectionHandler,
setHighlightedOptions,
toggleHighlightedOption,
}) => {
const optionsRef = useRef(null)
Expand All @@ -31,51 +33,62 @@ export const OptionsContainer = ({
)}

<div className="container" data-test={dataTest} ref={optionsRef}>
<div className="content-container" ref={wrapperRef}>
{!options.length && emptyComponent}
{options.map((option) => {
const highlighted = !!highlightedOptions.find(
(highlightedSourceOption) =>
highlightedSourceOption === option.value
)
{!options.length && emptyComponent}
{!!options.length && (
<select
multiple={maxSelections === Infinity}
size={maxSelections === 1 ? 2 : undefined}
className="content-container"
ref={wrapperRef}
onChange={(e) => {
const nextSelected = [...e.target.options].reduce(
(curNextSelected, option) => {
if (!option.selected) {
return curNextSelected
}

return (
<Fragment key={option.value}>
{renderOption({
...option,
...getOptionClickHandlers(
option,
selectionHandler,
toggleHighlightedOption
),
highlighted,
selected,
})}
</Fragment>
)
})}
return [...curNextSelected, option.value]
},
[]
)
setHighlightedOptions(nextSelected)
}}
>
{options.map((option, index) => {
const isLast = index === options.length - 1

Check failure on line 58 in components/transfer/src/options-container.js

View workflow job for this annotation

GitHub Actions / lint

'isLast' is assigned a value but never used
const highlighted = !!highlightedOptions.find(
(highlightedSourceOption) =>
highlightedSourceOption === option.value
)

{onEndReached && (
<EndIntersectionDetector
dataTest={`${dataTest}-endintersectiondetector`}
key={`key-${resizeCounter}`}
rootRef={optionsRef}
onEndReached={onEndReached}
/>
)}
</div>
return (
<Fragment key={option.value}>
{renderOption({
...option,
...getOptionClickHandlers(
option,
selectionHandler,
toggleHighlightedOption
),
highlighted,
selected,
})}
</Fragment>
)
})}
</select>
)}
</div>

<style jsx>{`
.optionsContainer {
flex-grow: 1;
padding: ${spacers.dp4} 0;
position: relative;
overflow: hidden;
}
.container {
overflow-y: auto;
overflow: hidden;
height: 100%;
}
Expand All @@ -94,6 +107,11 @@ export const OptionsContainer = ({
.content-container {
z-index: 1;
position: relative;
height: 100%;
width: 100%;
overflow: auto;
border: 0;
padding: ${spacers.dp4} 0;
}
.loading + .container .content-container {
Expand All @@ -111,6 +129,8 @@ OptionsContainer.defaultProps = {
OptionsContainer.propTypes = {
dataTest: PropTypes.string.isRequired,
getOptionClickHandlers: PropTypes.func.isRequired,
maxSelections: PropTypes.oneOf([1, Infinity]).isRequired,
setHighlightedOptions: PropTypes.func.isRequired,
emptyComponent: PropTypes.node,
highlightedOptions: PropTypes.arrayOf(PropTypes.string),
loading: PropTypes.bool,
Expand Down
53 changes: 16 additions & 37 deletions components/transfer/src/transfer-option.js
Original file line number Diff line number Diff line change
@@ -1,73 +1,53 @@
import { colors } from '@dhis2/ui-constants'
import cx from 'classnames'
import PropTypes from 'prop-types'
import React, { useRef } from 'react'

const DOUBLE_CLICK_MAX_DELAY = 500
import React from 'react'

export const TransferOption = ({
className,
disabled,
dataTest,
highlighted,
onClick,

Check failure on line 10 in components/transfer/src/transfer-option.js

View workflow job for this annotation

GitHub Actions / lint

'onClick' is defined but never used
onDoubleClick,
label,
value,
}) => {
const doubleClickTimeout = useRef(null)

return (
<div
data-test={dataTest}
onClick={(event) => {
if (disabled) {
return
}

if (doubleClickTimeout.current) {
clearTimeout(doubleClickTimeout.current)
doubleClickTimeout.current = null

onDoubleClick({ value }, event)
} else {
doubleClickTimeout.current = setTimeout(() => {
clearTimeout(doubleClickTimeout.current)
doubleClickTimeout.current = null
}, DOUBLE_CLICK_MAX_DELAY)

onClick({ value }, event)
}
}}
data-value={value}
className={cx(className, { highlighted, disabled })}
>
{label}
<>
<option
className={cx(className, { disabled })}
data-test={dataTest}
data-value={value}
value={value}
onDoubleClick={(e) => onDoubleClick({ value }, event)}

Check failure on line 22 in components/transfer/src/transfer-option.js

View workflow job for this annotation

GitHub Actions / lint

'e' is defined but never used
>
{label}
</option>

<style jsx>{`
div {
option {
font-size: 14px;
line-height: 16px;
padding: 4px 8px;
color: ${colors.grey900};
user-select: none;
}
div:hover {
option:hover {
background: ${colors.grey200};
}
div.highlighted {
option:checked {
background: ${colors.teal700};
color: ${colors.white};
}
div.disabled {
option.disabled {
color: ${colors.grey600};
cursor: not-allowed;
}
`}</style>
</div>
</>
)
}

Expand All @@ -81,7 +61,6 @@ TransferOption.propTypes = {
className: PropTypes.string,
dataTest: PropTypes.string,
disabled: PropTypes.bool,
highlighted: PropTypes.bool,
onClick: PropTypes.func,
onDoubleClick: PropTypes.func,
}
4 changes: 4 additions & 0 deletions components/transfer/src/transfer.js
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,8 @@ export const Transfer = ({
)}

<OptionsContainer
maxSelections={maxSelections}
setHighlightedOptions={setHighlightedSourceOptions}
dataTest={`${dataTest}-sourceoptions`}
emptyComponent={sourceEmptyPlaceholder}
getOptionClickHandlers={getOptionClickHandlers}
Expand Down Expand Up @@ -324,6 +326,8 @@ export const Transfer = ({
)}

<OptionsContainer
maxSelections={maxSelections}
setHighlightedOptions={setHighlightedPickedOptions}
selected
dataTest={`${dataTest}-pickedoptions`}
emptyComponent={selectedEmptyComponent}
Expand Down

0 comments on commit ee209d0

Please sign in to comment.