Skip to content

Commit

Permalink
Implement arrow down in chips autocomplete
Browse files Browse the repository at this point in the history
  • Loading branch information
driver-deploy-2 committed Jan 19, 2025
1 parent 4b82f74 commit 62b42b6
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 29 deletions.
2 changes: 1 addition & 1 deletion packages/lib/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,4 @@
"typedoc": "^0.27.6",
"typescript": "^5.7.3"
}
}
}
79 changes: 51 additions & 28 deletions packages/lib/src/chip.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,11 @@ import { HelperText, Label } from './label';
export interface ChipData {
tag: string;
image?: string;
alt?: string;
}

export interface AutocompleteOption {
text: string;
export interface AutocompleteOption extends ChipData {
value?: string;
image?: string;
}

export interface IChipsOptions {
Expand Down Expand Up @@ -66,13 +65,13 @@ export const Chips: m.FactoryComponent<IChipsOptions> = () => {
if (Array.isArray(data)) {
return data.map((item) => {
if (typeof item === 'string') {
return { text: item };
return { tag: item };
}
return item;
});
}
return Object.entries(data).map(([text, value]) => ({
text,
tag: text,
value: value || text,
}));
};
Expand All @@ -93,7 +92,7 @@ export const Chips: m.FactoryComponent<IChipsOptions> = () => {
}

const allOptions = processAutocompleteData(data);
const filtered = allOptions.filter((option) => option.text.toLowerCase().includes(input));
const filtered = allOptions.filter((option) => option.tag.toLowerCase().includes(input));

const limit = currentVnode.attrs.autocompleteOptions.limit || Infinity;
state.autocompleteItems = filtered.slice(0, limit);
Expand All @@ -103,8 +102,9 @@ export const Chips: m.FactoryComponent<IChipsOptions> = () => {

const selectAutocompleteItem = (item: AutocompleteOption) => {
addChip({
tag: item.text,
tag: item.tag,
image: item.image,
alt: item.alt, // Preserve alt text when converting to chip
});
state.inputValue = '';
state.showAutocomplete = false;
Expand Down Expand Up @@ -166,13 +166,21 @@ export const Chips: m.FactoryComponent<IChipsOptions> = () => {
state.selectedAutocompleteIndex + 1,
state.autocompleteItems.length - 1
);
const selectedItem = currentVnode?.dom.querySelector('.autocomplete-item.selected') as HTMLElement;
if (selectedItem) {
selectedItem.scrollIntoView({ block: 'nearest' });
}
m.redraw();
return;
}

if (e.key === 'ArrowUp') {
e.preventDefault();
state.selectedAutocompleteIndex = Math.max(state.selectedAutocompleteIndex - 1, -1);
const selectedItem = currentVnode?.dom.querySelector('.autocomplete-item.selected') as HTMLElement;
if (selectedItem) {
selectedItem.scrollIntoView({ block: 'nearest' });
}
m.redraw();
return;
}
Expand All @@ -187,7 +195,11 @@ export const Chips: m.FactoryComponent<IChipsOptions> = () => {
if (e.key === 'Enter' && target.value.trim()) {
e.preventDefault();
addChip({ tag: target.value.trim() });
} else if ((e.key === 'Backspace' || e.key === 'ArrowLeft') && !target.value && state.chipsData.length) {
} else if (e.key === 'Backspace' && !target.value && state.chipsData.length > 0) {
e.preventDefault();
// Delete the last chip immediately when backspace is pressed in an empty input
deleteChip(state.chipsData.length - 1);
} else if (e.key === 'ArrowLeft' && !target.value && state.chipsData.length) {
e.preventDefault();
selectChip(state.chipsData.length - 1);
}
Expand Down Expand Up @@ -220,20 +232,11 @@ export const Chips: m.FactoryComponent<IChipsOptions> = () => {
currentVnode = vnode;
},

// onupdate: (vnode) => {
// currentVnode = vnode;
// const { data } = vnode.attrs;
// if (data && JSON.stringify(data) !== JSON.stringify(state.chipsData)) {
// state.chipsData = data;
// }
// },

onremove: () => {
currentVnode = null;
},

view: ({ attrs }) => {
// console.log(state);
const {
id,
required,
Expand All @@ -255,7 +258,7 @@ export const Chips: m.FactoryComponent<IChipsOptions> = () => {
return '';
};

return m('div.input-field', { id, className }, [
return m('.input-field', { id, className }, [
m(
'.chips.chips-initial',
{
Expand All @@ -276,7 +279,7 @@ export const Chips: m.FactoryComponent<IChipsOptions> = () => {
chip.image &&
m('img', {
src: chip.image,
alt: chip.tag,
alt: chip.alt || chip.tag,
}),
chip.tag,
m(
Expand Down Expand Up @@ -311,9 +314,10 @@ export const Chips: m.FactoryComponent<IChipsOptions> = () => {
onblur: () => {
state.focused = false;
setTimeout(() => {
state.showAutocomplete = false;
state.selectedChip = null;
m.redraw();
}, 100);
}, 150);
},
onkeydown: handleKeydown,
}),
Expand All @@ -326,31 +330,50 @@ export const Chips: m.FactoryComponent<IChipsOptions> = () => {
display: 'block',
opacity: 1,
transform: 'scaleX(1) scaleY(1)',
width: '120px',
left: '0px',
top: '45px',
height: '50px',
transformOrigin: '0px 0px',
position: 'absolute',
width: '100%',
left: 0,
top: '100%',
maxHeight: '200px',
overflow: 'auto',
zIndex: 1000,
backgroundColor: '#fff',
boxShadow:
'0 2px 2px 0 rgba(0,0,0,0.14), 0 3px 1px -2px rgba(0,0,0,0.12), 0 1px 5px 0 rgba(0,0,0,0.2)',
},
},
state.autocompleteItems.map((item, index) =>
m(
'li.autocomplete-item',
{
key: item.text,
key: item.tag,
class: state.selectedAutocompleteIndex === index ? 'selected' : '',
style: {
padding: '12px 16px',
cursor: 'pointer',
backgroundColor: state.selectedAutocompleteIndex === index ? '#eee' : 'transparent',
},
onmousedown: (e: MouseEvent) => {
e.preventDefault();
selectAutocompleteItem(item);
},
onmouseover: () => {
state.selectedAutocompleteIndex = index;
},
},
[
item.image &&
m('img.autocomplete-item-image', {
src: item.image,
alt: item.text,
alt: item.alt || item.tag,
style: {
width: '24px',
height: '24px',
marginRight: '8px',
verticalAlign: 'middle',
},
}),
m('span.autocomplete-item-text', item.text),
m('span.autocomplete-item-text', item.tag),
]
)
)
Expand Down

0 comments on commit 62b42b6

Please sign in to comment.