|
@@ -55,6 +55,7 @@ export interface TagInputProps extends Omit<React.HTMLProps<TagInputDerivedEleme |
|
|
* Separators for splitting the input value into multiple tags. |
|
|
* Separators for splitting the input value into multiple tags. |
|
|
*/ |
|
|
*/ |
|
|
separator?: TagInputSeparator[], |
|
|
separator?: TagInputSeparator[], |
|
|
|
|
|
editOnRemove?: boolean, |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
@@ -78,6 +79,10 @@ export const TagInput = React.forwardRef<TagInputDerivedElement, TagInputProps>( |
|
|
defaultValue, |
|
|
defaultValue, |
|
|
disabled, |
|
|
disabled, |
|
|
id: idProp, |
|
|
id: idProp, |
|
|
|
|
|
onFocus, |
|
|
|
|
|
onBlur, |
|
|
|
|
|
editOnRemove = false, |
|
|
|
|
|
placeholder, |
|
|
...etcProps |
|
|
...etcProps |
|
|
}, |
|
|
}, |
|
|
forwardedRef, |
|
|
forwardedRef, |
|
@@ -119,7 +124,19 @@ export const TagInput = React.forwardRef<TagInputDerivedElement, TagInputProps>( |
|
|
}); |
|
|
}); |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
const handleBlur = () => { |
|
|
|
|
|
|
|
|
const handleFocus: React.FocusEventHandler<HTMLTextAreaElement> = (e) => { |
|
|
|
|
|
if (!clientSide) { |
|
|
|
|
|
onFocus?.(e); |
|
|
|
|
|
} |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
const handleBlur: React.FocusEventHandler<HTMLTextAreaElement> = (e) => { |
|
|
|
|
|
if (!clientSide) { |
|
|
|
|
|
onBlur?.(e); |
|
|
|
|
|
} |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
const handleRemoveTag = () => { |
|
|
if (!(typeof ref === 'object' && ref)) { |
|
|
if (!(typeof ref === 'object' && ref)) { |
|
|
return; |
|
|
return; |
|
|
} |
|
|
} |
|
@@ -128,10 +145,59 @@ export const TagInput = React.forwardRef<TagInputDerivedElement, TagInputProps>( |
|
|
return; |
|
|
return; |
|
|
} |
|
|
} |
|
|
setTimeout(() => { |
|
|
setTimeout(() => { |
|
|
delegateTriggerEvent('blur', input); |
|
|
|
|
|
|
|
|
const sibling = input.nextElementSibling as HTMLDivElement; |
|
|
|
|
|
const tagsInput = sibling.children[sibling.children.length - 1] as HTMLInputElement; |
|
|
|
|
|
tagsInput.focus(); |
|
|
|
|
|
}); |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
const handleInputBlur: React.FocusEventHandler<HTMLInputElement> = (e) => { |
|
|
|
|
|
if (!(typeof ref === 'object' && ref)) { |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
const { current: input } = ref; |
|
|
|
|
|
if (!input) { |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
onBlur?.({ |
|
|
|
|
|
...e, |
|
|
|
|
|
target: input, |
|
|
|
|
|
currentTarget: input, |
|
|
}); |
|
|
}); |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
const handleFocusCapture: React.FocusEventHandler<HTMLDivElement> = (e) => { |
|
|
|
|
|
const { currentTarget } = e; |
|
|
|
|
|
if (!clientSide) { |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
const { activeElement } = window.document; |
|
|
|
|
|
if (!activeElement) { |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
const tagInputWrapper = currentTarget.children[1] as HTMLDivElement; |
|
|
|
|
|
const tagInput = ( |
|
|
|
|
|
tagInputWrapper.children[tagInputWrapper.children.length - 1] as HTMLInputElement |
|
|
|
|
|
); |
|
|
|
|
|
if (activeElement !== tagInput) { |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
if (!(typeof ref === 'object' && ref)) { |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
const { current: input } = ref; |
|
|
|
|
|
if (!input) { |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
if (activeElement.tagName === 'INPUT') { |
|
|
|
|
|
onFocus?.({ |
|
|
|
|
|
...e, |
|
|
|
|
|
target: input, |
|
|
|
|
|
currentTarget: input, |
|
|
|
|
|
}); |
|
|
|
|
|
} |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
return ( |
|
|
return ( |
|
|
<div |
|
|
<div |
|
|
className={clsx( |
|
|
className={clsx( |
|
@@ -155,18 +221,23 @@ export const TagInput = React.forwardRef<TagInputDerivedElement, TagInputProps>( |
|
|
variant === 'alternate' && 'tag-input-alternate', |
|
|
variant === 'alternate' && 'tag-input-alternate', |
|
|
className, |
|
|
className, |
|
|
)} |
|
|
)} |
|
|
|
|
|
onFocusCapture={handleFocusCapture} |
|
|
> |
|
|
> |
|
|
<textarea |
|
|
<textarea |
|
|
{...etcProps} |
|
|
{...etcProps} |
|
|
|
|
|
placeholder={placeholder} |
|
|
disabled={disabled} |
|
|
disabled={disabled} |
|
|
ref={ref} |
|
|
ref={ref} |
|
|
id={id} |
|
|
id={id} |
|
|
aria-labelledby={labelId} |
|
|
aria-labelledby={labelId} |
|
|
data-testid="input" |
|
|
data-testid="input" |
|
|
defaultValue={defaultValue} |
|
|
defaultValue={defaultValue} |
|
|
|
|
|
onFocus={handleFocus} |
|
|
|
|
|
onBlur={handleBlur} |
|
|
style={{ |
|
|
style={{ |
|
|
height: clientSide ? undefined : 0, |
|
|
height: clientSide ? undefined : 0, |
|
|
}} |
|
|
}} |
|
|
|
|
|
tabIndex={clientSide ? -1 : undefined} |
|
|
className={clsx( |
|
|
className={clsx( |
|
|
'bg-negative rounded-inherit peer block', |
|
|
'bg-negative rounded-inherit peer block', |
|
|
'focus:outline-0', |
|
|
'focus:outline-0', |
|
@@ -219,9 +290,12 @@ export const TagInput = React.forwardRef<TagInputDerivedElement, TagInputProps>( |
|
|
input: 'peer bg-transparent', |
|
|
input: 'peer bg-transparent', |
|
|
tag: 'text-xs p-2 select-none', |
|
|
tag: 'text-xs p-2 select-none', |
|
|
}} |
|
|
}} |
|
|
|
|
|
isEditOnRemove={editOnRemove} |
|
|
|
|
|
placeHolder={placeholder} |
|
|
disabled={disabled} |
|
|
disabled={disabled} |
|
|
|
|
|
onBlur={handleInputBlur} |
|
|
onChange={handleTagsInputChange} |
|
|
onChange={handleTagsInputChange} |
|
|
onBlur={handleBlur} |
|
|
|
|
|
|
|
|
onRemoved={handleRemoveTag} |
|
|
separators={separator.map((s) => TAG_INPUT_SEPARATOR_MAP[s])} |
|
|
separators={separator.map((s) => TAG_INPUT_SEPARATOR_MAP[s])} |
|
|
/> |
|
|
/> |
|
|
)} |
|
|
)} |
|
@@ -322,4 +396,5 @@ TagInput.defaultProps = { |
|
|
block: false, |
|
|
block: false, |
|
|
hiddenLabel: false, |
|
|
hiddenLabel: false, |
|
|
enhanced: false, |
|
|
enhanced: false, |
|
|
|
|
|
editOnRemove: false, |
|
|
}; |
|
|
}; |