Coder Social home page Coder Social logo

anubra266 / choc-autocomplete Goto Github PK

View Code? Open in Web Editor NEW
387.0 2.0 45.0 3.32 MB

πŸ‡ Autocomplete Component Package for Chakra UI

Home Page: https://githubbox.com/anubra266/choc-autocomplete/tree/main/demo

License: MIT License

HTML 0.80% TypeScript 95.55% CSS 2.12% JavaScript 1.52%
autocomplete combobox chakra-ui choc-ui anubra266 hacktoberfest react select dropdown

choc-autocomplete's Introduction

gitartwork

choc-autocomplete's People

Contributors

allcontributors[bot] avatar anubra266 avatar chrisregner avatar daliudzius avatar dependabot[bot] avatar eric-hc avatar fabien0102 avatar jcdogo avatar kysluss avatar mathisfederico avatar naorpeled avatar richi2293 avatar sakerhetspolisen avatar spencerkaiser 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

choc-autocomplete's Issues

Default value not working in v.4.3.0

I'm having problems to get the default value in v4.3.0, the problem is I'm not able to replicate it in the codeSandbox but when I switch to v4.2.0 it's working, I have looked the changes in the lastest version and I saw you added a defaultValue prop

const defaultValue = useParseDefaultValue(

I put console.log(autoCompleteProps.defaultValue) and it's undefined so the return of useParseDefaultValue is undefined as well, as I'm using the input in controlled mode I think it should get value as default value, I think that is the way how this was working before

Do not need to release the src directory?

image

➜ ls -al node_modules/@choc-ui/chakra-autocomplete
total 80
drwxr-xr-x   8 chenquan  staff    256  8 13 16:25 .
drwxr-xr-x   3 chenquan  staff     96  8 13 11:41 ..
-rw-r--r--   1 chenquan  staff   1228  8 13 16:25 Changelog.md
-rw-r--r--   1 chenquan  staff   1063  8 13 16:25 LICENSE
-rw-r--r--   1 chenquan  staff  25036  8 13 16:25 README.md
drwxr-xr-x  22 chenquan  staff    704  8 13 16:25 dist
-rw-r--r--   1 chenquan  staff   1691  8 13 16:25 package.json
drwxr-xr-x  15 chenquan  staff    480  8 13 16:25 src

Props Request: Show menu when input field is focused

Because the select options aren't displayed when the user clicks the input field, they have to type random letters just to see what options are available. It would be helpful to have the option to see all available options before typing anything.

AutoCompleteTag resizes the AutoCompleteInput component

When using multiple prop in AutoComplete, if I choose multiple tags then it resizes the entire AutoCompleteInput component and makes it wider/longer. Can there be a way to solve this?

Alternatively, can we use tags outside AutoCompleteInput and above that component so that it does not resize the parent.

Fix Emphasis prop

Highlighting with emphasis prop, does not work well with text transformation.

Using Autocomplete with react-instantsearch-dom HOCs

I'm currently trying to implement a search field using react-instantsearch-dom and chakra-autocomplete. I seem to be hitting a wall when rendering the AutoCompleteList. I believe the issue is that the reference or context of AutoComplete is getting lost but I'm not sure how to solve it.

The search box part looks like this

  <AutoComplete rollNavigation id="autoTop" itemRef="auto">
    <AutoCompleteInput
        value={currentRefinement}
        variant="filled"
        placeholder="Search..."
        minW="500px"
        autoFocus
        onChange={(e) => handleQuery(e)}
        id="auto-input"
      />
      <SearchResults />
    </AutoComplete>

With the SearchResults component looking like this and then being wrapped in the instantsearch HOC with connectHits()

const HitBase = ({ hits, handleClick }: HitProps) => {
  console.log(hits)

  return (
    <AutoCompleteList >
      {hits.map((hit) => (
        <AutoCompleteItem key={hit.title} value={hit.title}>
          <Poster id={hit.id} slug={hit.poster_path} title={hit.title} />
          <Text>{hit.title}</Text>
        </AutoCompleteItem>
      ))}
    </AutoCompleteList>
  )
}
const SearchResults = connectHits(HitBase)

Is there a way to maintain the reference between the two components? My assumption is that the hits HOC is what actually breaks it but I am not sure how to get around it.

<AutoCompleteInput> should be able to access the value but render the label instead


  let cats = [
    { value: 'CAT_1', label: 'Kitty 1' },
    { value: 'CAT_2', label: 'Kitty 2'},
  ];

  return
  <AutoComplete openOnFocus suggestWhenEmpty rollNavigation>
    <AutoCompleteInput variant="ghost" bgColor="transparent" />

    <AutoCompleteList fontStyle="normal">
      {cats.map((cat) => (
        <AutoCompleteItem
          key={cat.value}
          value={cat.value}
          textTransform="capitalize"
        >
          {cat.label}
        </AutoCompleteItem>
      ))}
    </AutoCompleteList>
  </AutoComplete>
}

Package version "@choc-ui/chakra-autocomplete": "^4.3.4",

In the above example, I want the AutoCompleteList items to show up options like "Kitty 1", "Kitty 2" and so on. Now when I select any option, the value that gets set in the <AutoCompleteInput> is CAT_1 whereas I wanted "Kitty 1" to get set because that is what I chose.
The only way to get around this is to make sure the value and label (child of <AutoCompleteItem>) is set as the same thing i.e. cat.label in this case, but this breaks the point of having the ability to pass a different value and child to <AutoCompleteItem>

The behaviour that is expected is similar to how any <Menu> component would work.

tldr: the value maintained internally and the value displayed/rendered should be different for the input box.

Bug using AutoCompleteFixedItem and AutoCompleteGroup

I have this list:

<AutoCompleteList>
  <AutoCompleteGroup title="Title" showDivider>
    <AutoCompleteItem value="1">Apple</AutoCompleteItem>
    <AutoCompleteItem value="2">Appoint</AutoCompleteItem>
  </AutoCompleteGroup>
  <AutoCompleteFixedItem value="F1">Fixed Item 1</AutoCompleteFixedItem>
  <AutoCompleteFixedItem value="F2">Fixed Item 2</AutoCompleteFixedItem>
</AutoCompleteList>

And this is what I see, as you can see The Fixed item 1 is duplicated

image

If I put the FixedItem Inside of the AutoCompleteGroup I can't see none of those items

Allow users to change the filter method

Should change this line for allowing a user to provide a custom function that filters the list.
Use case: I want a fuzzy search, so the function will receive the Input value, all options and the option value; perform the operation and return true to validate the option.

opt.value.toLowerCase().indexOf(inputValue.toLowerCase()) > -1 ||

Allow passing an entire object to AutoCompleteItem as the value

Overview

It's very common to use a component like this with a list of objects. While the input value is always a string, it would be nice to also pass the entire object to AutoComplete and invoke the onSelectOption with that value.

Example

<AutoComplete
  // This is a hack to reset the internal state of the component
  key={instanceCount}
  ...
  onSelectOption={(selection) => {
    // selection is { email: '[email protected]', id: 's3e8d' }
  }}
>
  ...
  <AutoCompleteItem
    key={item.email}
    value={{ email: '[email protected]', id: 's3e8d' }}
  />

Long option values getting cut

image

Values that are longer than the <AutoCompleteInput> component width should have an ellipses at the end of the text instead of getting cut abruptly.

I updated to the latest version, input and select an option will appear the following error

I updated to the latest version, input and select an option will appear the following error

Warning: A component is changing a controlled input to be uncontrolled. This is likely caused by the value changing from a defined to undefined, which should not happen. Decide between using a controlled or uncontrolled input element for the lifetime of the component. More info: https://reactjs.org/link/controlled-components
     at input

Demo: https://codesandbox.io/s/choc-ui-packages-codesandbox-forked-0ziuu?file=/src/App.js

Can you tell me why this error is?
thank you.

Originally posted by @StringKe in #45 (comment)

feature request: non-filterable item

I'll like to have an option to avoid filter a item from the list

I'm using the creatable option, but I want to add an aditional option that will be always available in the list

- Option 1
- Option 2
---
- Add "Text"
- Create and Edit

I need to always show the Create and Edit option, so I was thinking in something like this:

<AutoCompleteItem
  value="createAndEdit"
  textTransform="capitalize"
  alwaysShow
>
create and edit
</AutoCompleteItem>

[Question] The carriage return event will trigger an error (Cannot read property'disabled' of undefined)

demo: https://codesandbox.io/s/choc-ui-packages-codesandbox-forked-0ziuu?file=/src/App.js

Uncaught TypeError: Cannot read property 'disabled' of undefined

Open the demo link and enter some content at random, and press Enter, Don't use the mouse to select content

I don’t know why this is caused. I’m trying to implement a search box with autocomplete, and then some keywords will be loaded from the backend to the user.

bug(creatable): cannot render AutoCompleteCreatable

Following these docs:

First add the `creatable` prop to the AutoComplete component. Then add the `AutoCompleteCreatable` component to the bottom of the list. Refer to the references for more info on this component.

I was not able to render the <AutoCompleteCreatable> component within the AutoCompleteList

Clicking enter throws an error

I use the autocomplete with list of google suggestions

say I type 'laptop' then click enter

image

Edit: This was on 3.5.4 btw, just updated

Edit: still happening on latest update

feat (multiselect): API methods for removing one item or all items

When using multi-select, it would be nice to have an API to remove a single selected item or to clear all items (reset) from outside the component.

I think the most idiomatic React way to do this in the current architecture of AutoComplete would be to expose an onReady or init callback which provides these methods.

<AutoComplete
  onReady={({ getItems, removeItem, reset }) => {
    // Store reference to API methods for later use
  }}

AutoComplete input does not obbey width props

Seems like the autocompleteinput has a Wrap element with hardcoded props including wdith.

<Wrap {...inputProps.wrapper}>

I couldn't not figure out how to override those. No matter what width i set in autocompleteinput it stays fixed at '80'. They are coming from here i think https://github.com/anubra266/choc-autocomplete/blob/main/src/helpers/input.ts

Is there a way expand the input width?

Thanks very much for your work

style props on <AutoCompleteInput> seem janky

Hi, so everything seems great with this library now except for styling inputs

					<AutoCompleteInput
						autoFocus
						width='50rem'
						display='inline-flex'
						flexGrow={1}
						variant='filled'
						size='md'
						bg='white'
						value={query}
						onFocus={onFocused}
						onBlur={onBlur}
						onChange={onChangeSearch}
						zIndex={searchBarZIndex}
						bg='gray.50'
						color='gray.700'
					/>

I have the input in a grid like think airbnb or amazon, so I want it to flexgrow but using flex in any way on it doesnt seem to work because I have a left and right element attached to it, using width works but then it isn't responsive.

My entire searchbar component is

import React, { useEffect, useState, useRef } from 'react';
import { useRouter } from 'next/router';
import {
	Box,
	Flex,
	InputGroup,
	InputLeftElement,
	InputRightElement,
	Select,
	IconButton,
} from '@chakra-ui/react';
import {
	AutoComplete,
	AutoCompleteInput,
	AutoCompleteItem,
	AutoCompleteList,
  } from '@choc-ui/chakra-autocomplete';
import { SearchIcon } from '@chakra-ui/icons';
import { useQuery } from '@apollo/client';

import { GQL_GET_ALL_CATEGORIES } from '@/gql';

const getSuggestions = async text => {
	const
		res = await fetch('/api/suggestions?' + new URLSearchParams({
			text,
		}))
	;
	//console.log('res', await res.json());
	return await res.json();
};

const SearchBar = props => {
	const router = useRouter();

	const [category, setCategory] = useState(null);
	const [categories, setCategories] = useState([]);

	useQuery(GQL_GET_ALL_CATEGORIES, {
		notifyOnNetworkStatusChange: true,
		onCompleted: data => {
			setCategories(data?.categories);
			//console.log(data?.categories);
		},
		onError: data => {
			console.log(data);
		},
	});

	const renderCategories = () => categories?.map(e => (<option key={e?.name} value={e?.name}>{e?.title}</option>)) ?? null;

	const [searchBarZIndex, setSearchBarZIndex] = useState(2);

	const onFocused = () => setSearchBarZIndex(999);
	const onBlur = () => setSearchBarZIndex(2);

	const [query, setQuery] = useState('');
	const [suggestions, setSuggestions] = useState([]);

	const onChangeSearch = async event => {
		const
			query = event?.target?.value
		;
		setQuery(query);
	};

	useEffect(() => {
		const handle = async () => {
			if(query.length) {
				const
					results = await getSuggestions(query)
				;
				if(Array.isArray(results)) {
					if(results?.[0] !== query) {
						results.unshift(query);
					}
					setSuggestions(results);
					//console.log(results);
				}
			}
			else if(suggestions.length) {
				setSuggestions([]);
			}
		};
		handle();
	}, [query]);

	const handleSearchClick = event => {
		if(query.length) {
			console.log('handleSearchClick', query);
			router?.push('/s?' + new URLSearchParams({
				query,
			}));
		}
	};

	const renderSuggestions = () => {
		if(suggestions?.length) {
			const handleSuggestionClick = event => {
				const
					query = event?.target?.innerText
				;
				console.log('handleSuggestionClick', query);
				router?.push('/s?' + new URLSearchParams({
					query,
				}));
			};
			return (
				<AutoCompleteList>
					{suggestions.map((option, oid) => (
						<AutoCompleteItem
							key={`optio-${oid}`}
							value={option}
							textTransform='capitalize'
							align='center'
							color='black'
							onClick={handleSuggestionClick}
						>
							{option}
						</AutoCompleteItem>
					))}
				</AutoCompleteList>
			);
		}
	};

	const handleSearchKeyPress = event => {
		if(event.key === 'Enter') {
			handleSearchClick();
		}
	};

	const handleCategory = event => {
		//console.log('handleCategory:', event?.target?.value?.length ? event?.target?.value : null);
		setCategory(event?.target?.value?.length ? event?.target?.value : null);
	};

	return (
		<Flex
			justify='center'
			align='center'
			w='full'
		>
			<AutoComplete
				rollNavigation
				maxSuggestions={10}
				emphasize
				selectOnFocus={false}
				onKeyPress={handleSearchKeyPress} 
				suggestWhenEmpty={false}
			>
				<InputGroup
					maxWidth='60vw'
					width='auto'
					display='flex'
				>
					<InputLeftElement
						children={(
							<Select
								placeholder="All"
								borderColor="darkGray"
								color="#111111"
								size='md'
								bg='#eee'
								borderEndRadius={0}
								borderStartRadius={6}
								//overflow='ellipsis'
								onClick={handleCategory}
							>
								{ renderCategories() }
							</Select>
						)}
						display='inline-flex'
						flexGrow={0.5}
						width='auto'
						zIndex={searchBarZIndex + 1}
					/>
					<AutoCompleteInput
						autoFocus
						width='50rem'
						display='inline-flex'
						flexGrow={1}
						variant='filled'
						size='md'
						bg='white'
						value={query}
						onFocus={onFocused}
						onBlur={onBlur}
						onChange={onChangeSearch}
						zIndex={searchBarZIndex}
					/>
					<InputRightElement
						children={(
							<IconButton
								aria-label='Search'
								icon={(
									<SearchIcon
										color='black'
									/>
								)}
								borderEndRadius={6}
							/>)
						}
						display='inline-flex'
						zIndex={searchBarZIndex + 1}
						onClick={handleSearchClick}
					/>
					{ renderSuggestions() }
				</InputGroup>
			</AutoComplete>
		</Flex>
	);
};

export default SearchBar;

Not able to change borderRadius on AutoCompleteList

I have the following implementation:

<AutoComplete openOnFocus>
  <AutoCompleteInput variant="filled" />
  <AutoCompleteList borderRadius="none">

However, border radius is not registering. I can confirm, other style props (e.g. fontSize) work.

AutoCompleteCreatable is shown on empty input

When AutoCompleteCreatable is set with openOnFocus or suggestWhenEmpty the AutoCompleteCreatable is shown "empty"

{({ value }) => <span>Add {value} to List</span>}

It's not really empty but value is, so I will end with an item called Add to List

Also I noticed that if the list have an option called Apple for example, it won't be filtered when the input is Apple as well

image

I think this stop to working recently

Reproduction https://codesandbox.io/s/react-hook-form-v7-controller-forked-rb4sk?file=/src/Chakra.js

Bug using useState and onOptionHighlight

Hi, I'm trying to set a flag when there not options to show, but if I use the useState hook in onOptionHighlight the component stops working; it doesn't show any option.

if I use console.log it works as expected, I'm missing something?

const [extraOptions, setExtraOptions] = useState(false);

  return (
    <AutoComplete
      onOptionHighlight={(value) => setExtraOptions(!value)} <!---
    >
    ...
    </AutoComplete>

EDIT:

using the onChange prop with useState have the same behavior

EDIT2:

I think the problem is I'm using the component as uncontrolled, I tried to use it with react-hook-form but I couldn't. AutoComplete or AutoCompleteInput does not exposes the value prop

Filtering not good

The Package filters using the Items' value, so the text in the item is ignored

Feature Request: Prop to Show unfiltered items with input defaultValue

As per @TaylorFacen 's request in #14

I see that if I provide a default value, the menu is already filtered. Is there a way to show all options even when there's a default value and only filter once the input has changed? The use case is, the user is able to manage financial transactions and assign a category to each transaction. I want them to be able to edit a transaction's category. So when they go to edit the transaction, there's already a pre-filled category that they have the option to change. I want them to be able to see all options even if there's already a category value.

Possible to list all options when user focuses for the first time?

I am looking for a behaviour that material-ui autocomplete takes care off - Ability to view all the menu items when the user focuses on the input box. But when the user starts typing, it starts showing just the filtered options.

This is useful in order for the user to view all the options as there is no way to view them at the moment without having to erase the entire text in the input box.

Unable to set default value to the AutoCompleteInput


  let cats = [
    { id: 'CAT_1', label: 'Kitty 1' },
    { id: 'CAT_2', label: 'Kitty 2'},
  ];

  return
  <AutoComplete openOnFocus suggestWhenEmpty rollNavigation>
    <AutoCompleteInput variant="ghost" bgColor="transparent" />

    <AutoCompleteList fontStyle="normal">
      {cats.map((cat) => (
        <AutoCompleteItem
          key={cat.id}
          value={cat.label}
          textTransform="capitalize"
        >
          {cat.label}
        </AutoCompleteItem>
      ))}
    </AutoCompleteList>
  </AutoComplete>
}

Package version "@choc-ui/chakra-autocomplete": "^4.3.3",

I want the default value in the input box to be set to "Kitty 1" whenever the page loads.
With the above code, the input box is empty on page load which seems like the expected behaviour.

  • I tried setting defaultValue to the <AutoCompleteInput> component but it doesn't do anything.
  • I tried setting value to the component. It worked but whenever I focus on the input box first time and click outside the <AutoCompleteList>, the value disappears.

What is the right way to go about it?

AutoComplete.InputGroup does not respect InputLeftElement

import {
	InputGroup,
	InputLeftElement,
	InputRightElement,
	Icon,
} from '@chakra-ui/react';
import {
	AutoComplete,
	AutoCompleteInput,
	AutoCompleteItem,
	AutoCompleteList,
	AutoCompleteGroup,
	AutoCompleteFixedItem,
  } from '@choc-ui/chakra-autocomplete';
  import { SearchIcon, ChevronRightIcon, ChevronDownIcon } from '@chakra-ui/icons';

const SearchBar = props => {
	const options = ['apple', 'appoint', 'zap', 'cap', 'japan'];
  
	return (
		<AutoComplete rollNavigation>
			{({ isOpen }) => (
				<>
					<InputGroup>
						<InputLeftElement
							pointerEvents="none"
							children={<SearchIcon />}
						/>
						<AutoCompleteInput
							variant="filled"
							placeholder="    Search..."
						/>
						<InputRightElement
							pointerEvents="none"
							children={
								<Icon as={isOpen ? ChevronRightIcon : ChevronDownIcon} />
							}
						/>
					</InputGroup>
					<AutoCompleteList>
						{options.map((option, oid) => (
							<AutoCompleteItem
								key={`optio-${oid}`}
								value={option}
								textTransform="capitalize"
								align="center"
							>
								{option}
							</AutoCompleteItem>
						))}
					</AutoCompleteList>
				</>
			)}
		</AutoComplete>
	);
};

export default SearchBar;

Result is
image

image

isNewInput always false

Seems like there is a bug isNewInput is always false, as I understand, using the creatable option should return true if I select the creatable option but that is not working

use autocomplete with RHF

This is more a question than a issue. I'm trying to use this component with RHF

In my first try I did this:

     <Controller
        name={name}
        control={control}
        render={({ field: { onChange, onBlur, value } }) => (
            <AutoComplete freeSolo rollNavigation>
              <AutoCompleteInput onChange={onChange} onBlur={onBlur} value={value} />
            </AutoComplete>
        )}

I see the defaultValue in the input in the first render of the component, but if I select any item from the list, this is not updated in the input. Reading the docs, I think this is because is onChange in the AutoComplete component who handles that, so I have updated the code

     <Controller
        name={name}
        control={control}
        render={({ field: { onChange, onBlur, value } }) => (
            <AutoComplete onChange={onChange} freeSolo rollNavigation>
              <AutoCompleteInput onBlur={onBlur} value={value} />
            </AutoComplete>
        )}

In this case, I don't see the defaultValue on the first render and I can't select a new value from the list.

So do you know what would be the way to use the component in controlled mode with RHF?

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.