ToolJet/frontend/src/Editor/Components/Multiselect.jsx
Muhsin Shah C P f0ed2764fd
Feature: port multi select to react select lib (#2551)
* Ported multi-select to react-select lib

* Changed some values

* working on all option select / unselect feature

* All clear event

* Changed exposed values

* Resolved some ui issues
- Changed values height to a fixed size
- Fixed close btn alignment

* Removed 'All' option from selected values section

* Changed some paddings and sizes

* Resolved scroll and label width problem

* Adjusted some margin

* Removed scrolling from container
- scroll only values

* Hide scrollbar

* Resolved indicators alignment

* updated multiselect with searchable select

* Use only multiselect with checkboxes

* Alignment fix for multiselect dropdown

* Make multiselect dropdown adjust according to height

* Add custom rendered for multiselect options

Co-authored-by: stepinfwd <stepinfwd@gmail.com>
Co-authored-by: Sherfin Shamsudeen <sherfin94@gmail.com>
2022-03-30 14:51:22 +05:30

100 lines
3 KiB
JavaScript

import _ from 'lodash';
import React, { useState, useEffect } from 'react';
import { MultiSelect } from 'react-multi-select-component';
const ItemRenderer = ({ checked, option, onClick, disabled }) => (
<div className={`item-renderer ${disabled && 'disabled'}`}>
<input type="checkbox" onClick={onClick} checked={checked} tabIndex={-1} disabled={disabled} />
<span>{option.label}</span>
</div>
);
export const Multiselect = function Multiselect({
id,
component,
height,
properties,
styles,
exposedVariables,
setExposedVariable,
onComponentClick,
darkMode,
}) {
const { label, value, values, display_values, showAllOption } = properties;
const { borderRadius, visibility, disabledState } = styles;
const [selected, setSelected] = useState([]);
let selectOptions = [];
try {
selectOptions = [
...values.map((value, index) => {
return { label: display_values[index], value: value };
}),
];
} catch (err) {
console.log(err);
}
useEffect(() => {
let newValues = [];
if (_.intersection(values, value)?.length === value?.length) newValues = value;
setExposedVariable('values', newValues);
setSelected(selectOptions.filter((option) => newValues.includes(option.value)));
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [JSON.stringify(values)]);
useEffect(() => {
setExposedVariable('values', value);
setSelected(selectOptions.filter((option) => value.includes(option.value)));
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [JSON.stringify(value)]);
useEffect(() => {
if (value && !selected) {
setSelected(selectOptions.filter((option) => properties.value.includes(option.value)));
}
if (JSON.stringify(exposedVariables.values) === '{}') {
setSelected(selectOptions.filter((option) => properties.value.includes(option.value)));
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
useEffect(() => {
setExposedVariable(
'values',
selected.map((option) => option.value)
);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [selected]);
return (
<div
className="multiselect-widget row g-0"
style={{ height, display: visibility ? '' : 'none' }}
onFocus={() => {
onComponentClick(this, id, component);
}}
>
<div className="col-auto my-auto d-flex align-items-center">
<label style={{ marginRight: label ? '1rem' : '', marginBottom: 0 }} className="form-label py-1">
{label}
</label>
</div>
<div className="col px-0 h-100" style={{ borderRadius: parseInt(borderRadius) }}>
<MultiSelect
hasSelectAll={showAllOption ?? false}
options={selectOptions}
value={selected}
onChange={setSelected}
labelledBy={'Select'}
disabled={disabledState}
className={`multiselect-box${darkMode ? ' dark' : ''}`}
ItemRenderer={ItemRenderer}
/>
</div>
</div>
);
};