mirror of
https://github.com/estruyf/vscode-front-matter.git
synced 2026-07-06 18:01:24 +02:00
#26 - Fixes for arrow selection
This commit is contained in:
+5
-1
@@ -1,8 +1,12 @@
|
||||
# Change Log
|
||||
|
||||
## [1.11.1] - 2020-12-10
|
||||
|
||||
- [#26](https://github.com/estruyf/vscode-front-matter/issues/26): Fix for arrow selection in the dropdown.
|
||||
|
||||
## [1.11.0] - 2020-12-10
|
||||
|
||||
- Moved from Material UI Autocomplete to Downshift. This gives more flexibility, and allows to focus the inputs from a VSCode command.
|
||||
- [#25](https://github.com/estruyf/vscode-front-matter/issues/25): Moved from Material UI Autocomplete to Downshift. This gives more flexibility, and allows to focus the inputs from a VSCode command.
|
||||
- Changed the `Front Matter: Insert <tags | categories>` functionality to open in the panel, instead of using the VSCode dialogs.
|
||||
|
||||
## [1.10.0] - 2020-12-03
|
||||
|
||||
@@ -38,7 +38,7 @@ export const ViewPanel: React.FunctionComponent<IViewPanelProps> = (props: React
|
||||
(settings && settings.tags && settings.tags.length > 0) && (
|
||||
<TagPicker type={TagType.tags}
|
||||
crntSelected={metadata.tags || []}
|
||||
options={settings.tags}
|
||||
options={settings.tags.map(c => ({ key: c.toLowerCase(), value: c }))}
|
||||
freeform={settings.freeform}
|
||||
focussed={focusElm === TagType.tags}
|
||||
unsetFocus={unsetFocus} />
|
||||
@@ -48,7 +48,7 @@ export const ViewPanel: React.FunctionComponent<IViewPanelProps> = (props: React
|
||||
(settings && settings.categories && settings.categories.length > 0) && (
|
||||
<TagPicker type={TagType.categories}
|
||||
crntSelected={metadata.categories || []}
|
||||
options={settings.categories}
|
||||
options={settings.categories.map(c => ({ key: c.toLowerCase(), value: c }))}
|
||||
freeform={settings.freeform}
|
||||
focussed={focusElm === TagType.categories}
|
||||
unsetFocus={unsetFocus} />
|
||||
|
||||
@@ -6,10 +6,12 @@ import { TagType } from '../TagType';
|
||||
import { MessageHelper } from '../helper/MessageHelper';
|
||||
import Downshift from 'downshift';
|
||||
|
||||
export interface KeyValue { key: string, value: string };
|
||||
|
||||
export interface ITagPickerProps {
|
||||
type: string;
|
||||
crntSelected: string[];
|
||||
options: string[];
|
||||
options: KeyValue[];
|
||||
freeform: boolean;
|
||||
focussed: boolean;
|
||||
unsetFocus: () => void;
|
||||
@@ -21,7 +23,7 @@ export const TagPicker: React.FunctionComponent<ITagPickerProps> = (props: React
|
||||
const [ inputValue, setInputValue ] = React.useState<string>("");
|
||||
const prevSelected = usePrevious(crntSelected);
|
||||
const inputRef = React.useRef<HTMLInputElement | null>(null);
|
||||
const dsRef = React.useRef<Downshift<string> | null>(null);
|
||||
const dsRef = React.useRef<Downshift<KeyValue> | null>(null);
|
||||
|
||||
/**
|
||||
* Removes an option
|
||||
@@ -66,8 +68,16 @@ export const TagPicker: React.FunctionComponent<ITagPickerProps> = (props: React
|
||||
* @param compState
|
||||
*/
|
||||
const onSelect = (selectedItem: string | null) => {
|
||||
console.log(selectedItem)
|
||||
if (selectedItem) {
|
||||
const uniqValues = Array.from(new Set([...selected, selectedItem]));
|
||||
let value = selectedItem || "";
|
||||
|
||||
const item = options.find(o => o.key === selectedItem.toLowerCase());
|
||||
if (item && item.value) {
|
||||
value = item.value;
|
||||
}
|
||||
|
||||
const uniqValues = Array.from(new Set([...selected, value]));
|
||||
setSelected(uniqValues);
|
||||
sendUpdate(uniqValues);
|
||||
setInputValue("");
|
||||
@@ -80,15 +90,15 @@ export const TagPicker: React.FunctionComponent<ITagPickerProps> = (props: React
|
||||
*/
|
||||
const onEnterSelection = (event: React.KeyboardEvent<HTMLInputElement>, closeCb: () => void) => {
|
||||
if (freeform && event.key === "Enter" && inputValue) {
|
||||
onSelect(inputValue);
|
||||
|
||||
if (closeCb) {
|
||||
closeCb();
|
||||
}
|
||||
setTimeout(() => {
|
||||
onSelect(inputValue);
|
||||
}, 100);
|
||||
} else if (event.key === "Escape") {
|
||||
if (closeCb) {
|
||||
closeCb();
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,8 +107,20 @@ export const TagPicker: React.FunctionComponent<ITagPickerProps> = (props: React
|
||||
* @param option
|
||||
* @param inputValue
|
||||
*/
|
||||
const filterList = (option: string, inputValue: string | null) => {
|
||||
return !selected.includes(option) && option.toLowerCase().includes((inputValue || "").toLowerCase());
|
||||
const filterList = (option: KeyValue, inputValue: string | null) => {
|
||||
return !selected.includes(option.value) && option.key.includes((inputValue || "").toLowerCase());
|
||||
}
|
||||
|
||||
function stateReducer(state: any, changes: any) {
|
||||
// this prevents the menu from being closed when the user
|
||||
// selects an item with a keyboard or mouse
|
||||
switch (changes.type) {
|
||||
case Downshift.stateChangeTypes.keyDownEnter:
|
||||
console.log(`Enter`, JSON.stringify(changes));
|
||||
return changes;
|
||||
default:
|
||||
return changes
|
||||
}
|
||||
}
|
||||
|
||||
React.useEffect(() => {
|
||||
@@ -118,25 +140,30 @@ export const TagPicker: React.FunctionComponent<ITagPickerProps> = (props: React
|
||||
<h3>{type}</h3>
|
||||
|
||||
<Downshift ref={dsRef}
|
||||
onChange={onSelect}
|
||||
itemToString={item => (item ? item : '')}
|
||||
onChange={(selected) => onSelect(selected?.key || "")}
|
||||
itemToString={item => (item ? item.value : '')}
|
||||
inputValue={inputValue}
|
||||
onInputValueChange={(value) => setInputValue(value)}>
|
||||
onInputValueChange={(value) => setInputValue(value)}
|
||||
stateReducer={stateReducer}>
|
||||
{
|
||||
({ getInputProps, getItemProps, getMenuProps, isOpen, inputValue, getRootProps, openMenu, closeMenu }) => (
|
||||
<>
|
||||
<div {...getRootProps(undefined, {suppressRefError: true})}>
|
||||
<input {...getInputProps({ ref: inputRef, onFocus: openMenu })}
|
||||
onBlur={() => { closeMenu(); unsetFocus(); } }
|
||||
placeholder={`Pick your ${type.toLowerCase()}`}
|
||||
onKeyDown={(e) => onEnterSelection(e, closeMenu)} />
|
||||
<input {...getInputProps({
|
||||
ref: inputRef,
|
||||
onFocus: openMenu as any,
|
||||
onClick: openMenu as any,
|
||||
onBlur: () => { closeMenu(); unsetFocus(); },
|
||||
onKeyDown: (e) => onEnterSelection(e, closeMenu)
|
||||
})}
|
||||
placeholder={`Pick your ${type.toLowerCase()}`} />
|
||||
</div>
|
||||
|
||||
<ul className={`article__tags__dropbox ${isOpen ? "open" : "closed" }`} {...getMenuProps()}>
|
||||
{
|
||||
isOpen ? options.filter((option) => filterList(option, inputValue)).map((item, index) => (
|
||||
<li {...getItemProps({ key: item, index, item })} >
|
||||
{ item }
|
||||
<li {...getItemProps({ key: item.value, index, item })} >
|
||||
{ item.value }
|
||||
</li>
|
||||
)) : null
|
||||
}
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import * as React from 'react';
|
||||
import { Tag } from './Tag';
|
||||
import { KeyValue } from './TagPicker';
|
||||
|
||||
export interface ITagsProps {
|
||||
values: string[];
|
||||
options: string[];
|
||||
options: KeyValue[];
|
||||
|
||||
onCreate: (tags: string) => void;
|
||||
onRemove: (tags: string) => void;
|
||||
@@ -12,8 +13,8 @@ export interface ITagsProps {
|
||||
export const Tags: React.FunctionComponent<ITagsProps> = (props: React.PropsWithChildren<ITagsProps>) => {
|
||||
const { values, options, onCreate, onRemove } = props;
|
||||
|
||||
const knownTags = values.filter(v => options.includes(v));
|
||||
const unknownTags = values.filter(v => !options.includes(v));
|
||||
const knownTags = values.filter(v => options.map(o => o.value).includes(v));
|
||||
const unknownTags = values.filter(v => !options.map(o => o.value).includes(v));
|
||||
|
||||
return (
|
||||
<div className={`article__tags__items`}>
|
||||
|
||||
Reference in New Issue
Block a user