Coder Social home page Coder Social logo

based-ghost / react-functional-select Goto Github PK

View Code? Open in Web Editor NEW
193.0 2.0 11.0 38.96 MB

Micro-sized & micro-optimized select component for React.js

Home Page: https://master--625676b6922472003af898b4.chromatic.com

License: MIT License

JavaScript 1.97% TypeScript 95.34% HTML 2.67% Shell 0.02%
react select dropdown multi-select functional styled-components performance windowing react-components virtualization

react-functional-select's Introduction

Howdy  👋🤠

  • ⚡  Technical background: Full-stack .NET developer (client-side: React, Vue, Angular, or Svelte)

  • 🔭  Current hobby: Data privacy & security, OSINT, ethical hacking

  • 📫  Reach me at: [email protected]

react-functional-select's People

Contributors

based-ghost avatar brettm12345 avatar brightpixels avatar dependabot[bot] avatar michal-wrzosek avatar stephenwf avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

react-functional-select's Issues

Feedback after first test

Just a raw feedback after 2 hours spent on testing component. Promising but fixes needed (imho).

  1. Options cannot be passed as readable meaning they are prone to mutation. A no no since we want functional coding style.
  2. No way to render icon in label (only allows string type).
  3. onOptionChange is documented as
onOptionChange(data: any) => void - executed after an option is selected or removed

is that really correct "or option removed" - the options list should not be mutable?
4. I found this lib when trying to find a minimalistic library with first class support for styled-components. A little disappointed, having to edit themeProvider as object and even then it is quite difficult to get to some styling properties, e.g. I want to reduce focused border width.
5. Cannot find a way to support cursor: pointer over control.
6. I see no possibility to hide "select options" text inside empy select
[edit: set placeholder=""] - hackish though

Just my quick tidbits. Good work, keep it up!

Separate render prop for control vs menu

Is there a plan to support a separate render prop for the selected option in the control vs the menu? Currently renderOptionLabel is applied to both.

I am rendering custom menu items with additional subtext and an icon, it doesn't make sense for me to display these extra things in the control, I just want the main piece of text. In the example below, I would like to be able to only render Denver in the control

Screen Shot 2021-04-26 at 8 44 19 AM

Something like renderControlLabel to go along with the current renderOptionLabel?

Cannot add styles for Single Value

Hello,

Unless I'm mistaken, there is no way to add styles for the Single Value component. Based on the source code:

const SINGLE_VALUE_BASE_STYLE = css`
  top: 50%;
  overflow: hidden;
  position: absolute;
  white-space: nowrap;
  box-sizing: border-box;
  text-overflow: ellipsis;
  transform: translateY(-50%);
`;

const SingleValue = styled.div`
  ${SINGLE_VALUE_BASE_STYLE}
  max-width: calc(100% - 0.5rem);
`;

There is no theme extension for Single Value. What I'm trying to achieve is to change to "top" property, basically.

Screenshot 2021-11-24 at 20 07 01

Notice the position of the Label and Input value vs. the Single Value position.

Thank you!

Missing types

In the published package the ./src/types folder doesn't appear to be included in the ./dist folder.

If you check Select.d.ts you can see it importing from ./types which doesn't exist in the published model.

Introduced in: 2.3.3 (source)
Working in: 2.3.2 (source)
Still missing in 3.3.3 (source)

A possible fix would be to rename the index.d.ts and styled.d.ts to index.ts and styled.ts respectively. The other would be to use something like copy-files to grab the *.d.ts into the dist folder.

Not rendered options

Hi. sometimes when the menu is opened, some options are not rendered
image

<SelectStyled lazyLoadMenu={true} themeConfig={themeConfig} ref={selectRef} isClearable options={options} isDisabled={isDisabled} onOptionChange={onChange} placeholder={placeholder} isInvalid={validation} openMenuOnClick={onClick} initialValue={value} isLoading={isLoading} />

AJAX/Fetch-powered dropdown?

I’m looking at the API, and I can’t figure out relevant options, but is it possible to build a dropdown that will fetch options via XHR/fetch as a user types input?

Of all the libraries I’ve explored, I love this one for a few reasons —

  1. It is super lightweight.
  2. It performs really well.
  3. The API and the examples are all well laid out and thoughtful.

I’d absolutely love to use this library to build my dropdowns, but currently I’m looking for a component that will let me build a search-as-you-type dropdown.

Controlled input value

I don't see an obvious way to control the value of the select input. This is necessary for at least me, since I am using controlled inputs in react-form-hooks.

Am I missing something?

Some bugs I spotted...

  1. If hideSelectedOptions is set to true, all other options disappear after an option is selected. (Might be related to search functionality)
  2. If hideSelectedOptions is set to false, rfs-option-selected css class is applied to all options after an option is selected.
  3. onOptionChange does not fire again after an option is selected. Note that this was the case when hideSelectedOptions was set to false, since there is currently no way to fire it twice while it is set to true afaik.

Code is pretty much like the following. If my code is wrong, feel free to let me know.

const getOptionLabel = useCallback((option: SomeObject): string => option.text, []);
const onOptionChange = useCallback((option: SomeObject | null): void => {
	console.log(option);
	if (!option) return;
	setSomeState(prevState => {
		return { ...prevState, id: option.id };
	});
}, []);

<Select
	options={someObjectArray}
	isDisabled={!!someValue}
	ref={selectRef}
	placeholder="some text"
	onOptionChange={onOptionChange}
	getOptionLabel={getOptionLabel}
	addClassNames={true}
	hideSelectedOptions={true}
	menuItemSize={30}
	blurInputOnSelect={true}
	noOptionsMsg="some text"
	themeConfig={...}
        onMenuClose={() => selectRef.current.blur()}
/>

Suggestion: open dropdown at top when don't have enough place

In some cases (ex: select language) we need to place the select at bottom of the page, would be great to open the dropdown at top when bottom don't have enough place.

For example if we removed the min-height of container in your storybook demo:
0

Support for VariableSizeList

I have a case where I render items which have optional subtext (see example below). In the case where the subtext is not available I'd like to show a smaller sized menu item.

Currently, FixedSizeList is used, which doesn't support this behaviour. Could VariableSizeList be used instead?

Screen Shot 2021-04-26 at 8 47 54 AM

Got an error: 'Cannot read properties of undefined (reading 'withConfig')' during the testing with RTL

Hi!

I updated from 3.3.3 to 5.0.0 v of the react-functional-select.

After this, I got an error:
image

This error occurred when the component with Select loaded before tests started. And I have no idea what happened and how to solve it.
I use CRA, RTL, and Typescript.

Environment

Node: 16.17.0
npm: 8.15.0

npmPackages:
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-scripts": "^5.0.1",
"react-functional-select": "^5.0.0",
"styled-components": "^5.3.5",
"typescript": "^4.7.4",
"@testing-library/jest-dom": "^5.16.4",
"@testing-library/react": "^13.3.0",
"@testing-library/user-event": "^14.2.1",
"jest-styled-components": "^7.0.8",

And using:

const CustomSelect = (props: SelectProps) => {  
   // ....
    
        const getCaretIcon = ({ menuOpen }: IconState) => (
            <StyledCaretIconSelect active={menuOpen}>
                <CaretIcon className="select-caret-icon" />
            </StyledCaretIconSelect>
        );
        
        const getCrossIcon = () => (
            <>
                <CrosstIcon className="select-cross-icon" />
                <StyledSelectIconsDevider className="select-devider" />
            </>
        );

    const handleOnChange = useCallback((option: OptionData) =>  onChange(option), []);

    const getOptionValue = useCallback(
        (option: OptionData): number | string =>
            handleOptionValue(option),
        [],
    );

    const getOptionLabel = useCallback(
        (option: OptionData): number | string =>
            handleOptionLabel(option),
        [],
    );


    return (
            <Select
                initialValue={value}
                options={options}
                isInvalid={isInvalid}
                isSearchable={isSearchable}
                isClearable={isClearable}
                isDisabled={isDisabled}
                onOptionChange={handleOnChange}
                getOptionValue={getOptionValue}
                getOptionLabel={getOptionLabel}
                caretIcon={getCaretIcon}
                clearIcon={getCrossIcon}
                themeConfig={ThemeSelectFilter}
                required={required}
                placeholder={placeholder}
                hideSelectedOptions={false}
                menuItemSize={selectMenuItemSize}
                menuWidth={menuWidth}
            />
    );
};

export default CustomSelect;

and theme:

const ThemeSelectFilter: Partial<DefaultTheme> = {
    color: {
        border: 'transparent',
        danger: `${COLORS.warning}`,
        dangerLight: 'rgb(213 66 54 / 25%)',
        disabled: `${COLORS.background.disabled}`,
        placeholder: `${COLORS.text.light}`,
        iconSeparator: 'transparent',
    },
    icon: {
        padding: 0,
        css: css`
            svg {
                fill: ${COLORS.text.light};
            }

            .select-caret-icon {
                margin-bottom: 2px;
                width: 12px;
                height: 6px;
            }

            .select-cross-icon {
                margin-right: 10px;
                width: 10px;
                height: 10px;
            }
        `,
    },
    control: {
        minHeight: '20px',
        borderWidth: '1px',
        boxShadow: '0 0 0 0.18rem',
        boxShadowColor: 'transparent',
        focusedBorderColor: 'transparent',
        padding: '0px 10px 0px 3px',
        css: css`
            font-weight: 600;
            cursor: pointer;
        `,
    },
    menu: {
        padding: '8px',
        borderRadius: `${SIZES.border.radius}`,
        boxShadow: '0 2px 10px #00000029',
        option: {
            selectedColor: `${COLORS.text.main}`,
            selectedBgColor: 'transparent',
            padding: '5px 7px',
            focusedBgColor: 'transparent',
        },
    },
    noOptions: {
        fontSize: `${SIZES.typography.body1}`,
        margin: '0',
        color: `${COLORS.text.light}`,
        padding: '5px 7px',
    },
};

But, I also got this error even without theming.

menu position when there is not enough space

First of all, congratulations on such a beautiful component. I am very attracted to the way you have implemented the search without delay in the DOM.

I have a doubt...
Will the option of automatic or manual positioning of the menu be implemented when there is not enough space?

An idea: react-select

Thank you!

Mount the dropdown menu outside the parent div

Hi,

I am rendering the select within another component - that requires overflow: hidden

This means that I cannot see the dropdown after opening it.

As such, do you think it is possible to add portaling / Overlay etc. to the dropdown to get around this issue?

I note that React select has a menuPortalTarget prop - so something similar would be amazing:

How to set selected option from outside?

Version: 2.9.4

I'm trying to set the selected option / value of the Select from outside of the component. It seems that when I do that, the Select component fires onOptionChange with the previous (still current?) value which (probably?) overrides the new value that was just passed in.

Code:

import React, { useState } from 'react'
import { Select } from 'react-functional-select'

const initialOptions = [
  { value: 0, label: 'Abc' },
  { value: 1, label: 'Bcd' },
  { value: 2, label: 'Cde' }
]

export default () => {
  const [options, setOptions] = useState(initialOptions)
  const [value, setValue] = useState(null)
  console.log('value', value)

  return <>
    <Select options={options}
            initialValue={value}
            onOptionChange={option => console.log('onOptionChange', option)}
    />
    <button onClick={() => {
      const newOption = { value: 3, label: 'New' }
      setOptions([newOption, ...options])
      setValue(newOption)
    }}>
      Set new value
    </button>
  </>
}

Expectations:

  • When I click on the "Set new value" button, I expect to have the option with label "New" selected.

Actual behavior:

  • The "New" option is not selected.

Console reveals that when I click on the button, the onOptionChange callback is fired with the previously selected option (or null if none was selected). One might guess that this is an indication that the newly set value is immediately afterwards overridden by the previous value.

Console output:

value null
... now click the button...
value {value: 3, label: "New"}
onOptionChange null

(All the code examples I found have the selected option assigned solely from the argument passed by the onOptionChange callback, including issue #5.)

Accessibility issue/question

Hi,
I've notice that the component is not tab selectable and so it will interfere with accessibility focused software. I've also noted that you've set the tabindex to -1 on the input used to filter.

  1. Do you have a plan to address accessibility issues (this one in particular)?
  2. Is there a reason for the "-1" as value for tabindex?
  3. Would you consider the reset/clear button to be part of the tab index flow too?

Custom cursor style on control and/or menu

Hello, I have reviewed the documentation and the code, but I have not found a way to change the cursor style.

Another possibility is something similar to renderOptionLabel, but for control as well.

Thanks!

To styling with different states

Hello, may I know how to styling for different states? For example if I use a custom component as caret icon, how to set something like rotate(180deg) for it when menu is opened?

Below is what react select do (state.isSelected / state.isDisabled):

const customStyles = {
  option: (provided, state) => ({
    ...provided,
    borderBottom: '1px dotted pink',
    color: state.isSelected ? 'red' : 'blue',
    padding: 20,
  }),
  control: () => ({
    // none of react-select's styles are passed to <Control />
    width: 200,
  }),
  singleValue: (provided, state) => {
    const opacity = state.isDisabled ? 0.5 : 1;
    const transition = 'opacity 300ms';

    return { ...provided, opacity, transition };
  }
}

Is sortable multi-select supported?

Hi,
For a huge number of options in the select list, I think a sortable feature would be useful. As I can see from the docs that the library doesn't support this feature itself; however, I wonder if it is possible to use this library with other library that supports sortable, for example react-sortable-hoc? Or if there is other possible implementation for sortable feature, I'd appreciate if you could show me.
Thanks in advance!

initialValue prop not working?

Hi, I have initialValue set and it's not using it.

        <Select
            initialValue={maxPlayers}
            options={[1, 2, 3, 4, 5, 6, 7, 8]}
            onOptionChange={setMaxPlayers}
            getOptionValue={opt => opt}
            getOptionLabel={opt => opt}
          />

I even hard-coded it to initialValue={2} without success. Am I doing something wrong?

Filter by startsWith instead of contains the typed value

Is it possible to add a prop to filter by startsWith instead of the current filter?

If I have these list of words:

  • strike
  • ancestor
  • indication
  • recognize
  • dilute
  • man
  • fog
  • rise
  • grudge
  • recognize

Currently, if I search ri the result is:

  • strike
  • rise

If we apply the new proposed filter the result is:

  • rise

Thanks

No tag / release for version 5.0.0

Version 5.0.0 has been released on NPM, but there is no tag for this version, and no Github Release or changelog.

Is this version legit? Could you add a release or a Changelog so we know what changed?

Capturing input value and using it as the selected option

Hello, I am trying to implement the react-functional-select component into an application that I am working on, I am wondering if there is a way to capture the input from the user and be able to use that value as the selected option. Is this part of the functionality that is built into this component?

I have a list of options that exist already, my goal is to be able to capture the input from the user in the case that what they typed in does not match any of the options that are available in the predefined set.

Order of multi-select tags not preserved.

There seems to be an issue with the order of tags when using multi-select.

If I choose c, b, a (in that order) from menuOptions which are by default in this order (a, b, c & d), if the data is preserved and the component is re-loaded, the tags are in the order of the menuOptions (a, b, c) and NOT (c, b, a).

The issue arises in this function:

(It's the final reduce function).

export function validateSetValueParam(

I am not confident in changing this function as I'm not sure about the repercussions that I'm unaware of.

I can't customize control container as much as I like

I've been having some issues with customization for the last couple of days. I tried and failed to do 2 things.

  1. Give a custom height to the select container which is lower than its default value. I can change its font size by applying css to control container but i just cannot decrease the select container's default height. Is there a configuration option like menuItemSize that applies to the selector that I am potentially missing?

  2. I need to apply custom style to the control box when the menu is toggled. The problem is clicking on the component focuses the select container instead of the control container so .rfs-control-container:focus doesn't get applied when the component is clicked. I tried the following scss rule but apparently it doesn't work either.

.rfs-select-container {
	&:focus {
		.rfs-control-container {
			background-color: #fff !important;
			box-shadow: 0 2.5px 5px 0 rgba(224, 228, 238, 0.75);
		}
	}
}

I'd appreciate some assistance.

Typescript error

Error:Error:line (9)TS7016: Could not find a declaration file for module 'react-functional-select'.
Try npm install @types/react-functional-select if it exists or add a new declaration (.d.ts) file containing declare module 'react-functional-select';

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.