From 2b97adcea547ff8625e720ce96f7ae4f51e79792 Mon Sep 17 00:00:00 2001 From: Zishan Ahmad Date: Mon, 26 Feb 2024 22:58:25 +0530 Subject: [PATCH] added a multiselect box --- .../src/components/MultiSelect/MultiSelect.js | 102 ++++++++++++++++++ .../react/src/components/MultiSelect/index.js | 1 + .../elements/MultiStaticSelectElement.js | 40 +++++++ .../uiKit/surfaces/FuselageSurfaceRenderer.js | 22 ++-- 4 files changed, 153 insertions(+), 12 deletions(-) create mode 100644 packages/react/src/components/MultiSelect/MultiSelect.js create mode 100644 packages/react/src/components/MultiSelect/index.js diff --git a/packages/react/src/components/MultiSelect/MultiSelect.js b/packages/react/src/components/MultiSelect/MultiSelect.js new file mode 100644 index 000000000..bb1b9e070 --- /dev/null +++ b/packages/react/src/components/MultiSelect/MultiSelect.js @@ -0,0 +1,102 @@ +import React, { useState } from 'react'; +import { css, useTheme } from '@emotion/react'; +import PropTypes from 'prop-types'; +import useComponentOverrides from '../../theme/useComponentOverrides'; +import { Box } from '../Box'; + +const MultiSelect = ({ + className = '', + style = {}, + color = 'primary', + options = [], + onChange, + ...props +}) => { + const { classNames, styleOverrides } = useComponentOverrides('MultiSelect'); + const theme = useTheme(); + const [selectedOptions, setSelectedOptions] = useState([]); + + const handleOptionToggle = (value) => { + const isSelected = selectedOptions.includes(value); + if (isSelected) { + setSelectedOptions(selectedOptions.filter((item) => item !== value)); + } else { + setSelectedOptions([...selectedOptions, value]); + } + }; + + const MultiSelectCss = css` + position: relative; + display: inline-flex; + flex: 1 0 auto; + min-width: 8rem; + padding: 0.5rem 0.9375rem; + vertical-align: baseline; + outline: 0; + background-color: transparent; + letter-spacing: 0rem; + font-size: 0.875rem; + font-weight: 400; + line-height: 1.25rem; + overflow: hidden; + color: #2f343d; + border-right: 0.9375rem transparent; + border-width: 1px; + border-color: #cbced1; + border-style: solid; + border-radius: 0.25rem; + background-color: white; + box-shadow: none; + -webkit-appearance: none; + appearance: none; + transition: all 230ms; + &:focus { + border-color: ${theme.palette[color].main || 'currentColor'}; + box-shadow: 0px 0px 2.5px ${theme.palette[color].light || 'currentColor'}; + } + `; + + const CheckboxCss = css` + margin-right: 8px; + cursor: pointer; + `; + + return ( + + + {options.map((option) => ( + // eslint-disable-next-line jsx-a11y/label-has-associated-control + + ))} + + + ); +}; + +MultiSelect.propTypes = { + className: PropTypes.string, + style: PropTypes.object, + color: PropTypes.string, + options: PropTypes.arrayOf( + PropTypes.shape({ + value: PropTypes.string, + label: PropTypes.string, + }) + ), + onChange: PropTypes.func, +}; + +export default MultiSelect; diff --git a/packages/react/src/components/MultiSelect/index.js b/packages/react/src/components/MultiSelect/index.js new file mode 100644 index 000000000..7860a30ca --- /dev/null +++ b/packages/react/src/components/MultiSelect/index.js @@ -0,0 +1 @@ +export { default as MultiSelect } from './MultiSelect'; diff --git a/packages/react/src/components/uiKit/elements/MultiStaticSelectElement.js b/packages/react/src/components/uiKit/elements/MultiStaticSelectElement.js index 7d389c847..b2d02806a 100644 --- a/packages/react/src/components/uiKit/elements/MultiStaticSelectElement.js +++ b/packages/react/src/components/uiKit/elements/MultiStaticSelectElement.js @@ -1,3 +1,43 @@ +import React, { memo, useMemo, useCallback } from 'react'; + +import { useUiKitState } from '../hooks/useUiKitState'; +import { fromTextObjectToString } from '../utils/fromTextObjectToString'; +import { MultiSelect } from '../../MultiSelect'; + +const MultiStaticSelectElement = ({ block, context, surfaceRenderer }) => { + const [{ loading }, action] = useUiKitState(block, context); + + const options = useMemo( + () => + block.options.map((option, i) => ({ + value: option.value, + label: fromTextObjectToString(surfaceRenderer, option.text, i) ?? '', + })), + [block.options, surfaceRenderer] + ); + + const handleChange = useCallback( + (val) => { + action({ target: { val } }); + }, + [action] + ); + + return ( + + ); +}; + +export default memo(MultiStaticSelectElement); + // import { MultiSelectFiltered } from '@rocket.chat/fuselage'; // import React, { memo, useCallback, useMemo } from 'react'; diff --git a/packages/react/src/components/uiKit/surfaces/FuselageSurfaceRenderer.js b/packages/react/src/components/uiKit/surfaces/FuselageSurfaceRenderer.js index c9141e886..bb08b0f88 100644 --- a/packages/react/src/components/uiKit/surfaces/FuselageSurfaceRenderer.js +++ b/packages/react/src/components/uiKit/surfaces/FuselageSurfaceRenderer.js @@ -12,7 +12,7 @@ import ButtonElement from '../elements/ButtonElement'; import DatePickerElement from '../elements/DatePickerElement'; import ImageElement from '../elements/ImageElement'; import LinearScaleElement from '../elements/LinearScaleElement'; -// import MultiStaticSelectElement from '../elements/MultiStaticSelectElement'; +import MultiStaticSelectElement from '../elements/MultiStaticSelectElement'; import OverflowElement from '../elements/OverflowElement'; import PlainTextInputElement from '../elements/PlainTextInputElement'; import StaticSelectElement from '../elements/StaticSelectElement'; @@ -234,17 +234,15 @@ export class FuselageSurfaceRenderer extends UiKit.SurfaceRenderer { return null; } - return null; - // implement this without fuselage - // return ( - // - // ); + return ( + + ); } overflow(block, context, index) {