@plexui/ui 0.7.94 → 0.7.95
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -279,7 +279,7 @@ export const TagInput = (props) => {
|
|
|
279
279
|
};
|
|
280
280
|
// @ts-expect-error - Fix once usehooks-ts is updated https://github.com/juliencrn/usehooks-ts/pull/675
|
|
281
281
|
useOnClickOutside(containerRef, handleContainerBlur);
|
|
282
|
-
return (_jsxs(_Fragment, { children: [_jsx("div", { className: s.Container, ref: containerRef, onKeyDown: handleContainerKeyDown, onMouseDown: handleContainerMouseDown, onFocus: handleFocus, onBlur: handleBlur, "data-size": size, "data-focused": focused ? "" : undefined, "data-empty": tags.size === 0 ? "" : undefined, tabIndex: -1, style: toCssVariables({ "min-rows": String(rows) }), "data-disabled": disabled ? "" : undefined, children: _jsxs("div", { className: s.TagInput, children: [Array.from(tags.values()).map((tag) => (_jsxs("div", { className: s.Tag, tabIndex: -1, onClick: () => setSelectedTag(tag.value), "data-tag": tag.value, "data-invalid": !tag.valid ? "" : undefined, "data-duplicate": duplicateTags.has(tag.value) ? "" : undefined, children: [_jsx("span", { className: "overflow-hidden text-ellipsis", title: tag.value, children: _jsx("span", { className: s.TagValue, children: tag.value }) }), _jsx("div", { className: s.TagRemove, onClick: () => removeTag(tag.value), role: "button", "aria-label": "Remove item", children: _jsx(X, {
|
|
282
|
+
return (_jsxs(_Fragment, { children: [_jsx("div", { className: s.Container, ref: containerRef, onKeyDown: handleContainerKeyDown, onMouseDown: handleContainerMouseDown, onFocus: handleFocus, onBlur: handleBlur, "data-size": size, "data-focused": focused ? "" : undefined, "data-empty": tags.size === 0 ? "" : undefined, tabIndex: -1, style: toCssVariables({ "min-rows": String(rows) }), "data-disabled": disabled ? "" : undefined, children: _jsxs("div", { className: s.TagInput, children: [Array.from(tags.values()).map((tag) => (_jsxs("div", { className: s.Tag, tabIndex: -1, onClick: () => setSelectedTag(tag.value), "data-tag": tag.value, "data-invalid": !tag.valid ? "" : undefined, "data-duplicate": duplicateTags.has(tag.value) ? "" : undefined, children: [_jsx("span", { className: "overflow-hidden text-ellipsis", title: tag.value, children: _jsx("span", { className: s.TagValue, children: tag.value }) }), _jsx("div", { className: s.TagRemove, onClick: () => removeTag(tag.value), role: "button", "aria-label": "Remove item", children: _jsx(X, {}) })] }, tag.value))), showInput && (_jsxs("div", { className: s.InputContainer, children: [_jsx("span", { ref: measureRef, className: s.InputMeasure }), _jsx("div", { className: s.InputWrapper, children: _jsx("input", { id: id, className: s.Input, ref: inputRef, value: currentInput, onChange: (e) => {
|
|
283
283
|
setCurrentInput(e.target.value);
|
|
284
284
|
}, onPaste: handlePaste, onKeyDown: handleInputKeyDown, placeholder: placeholderText, style: { width: inputWidth }, disabled: disabled }) })] }))] }) }), maxTags && (_jsxs("div", { className: s.Limit, children: [tags.size, _jsx("span", { className: "mx-px", children: "/" }), maxTags] }))] }));
|
|
285
285
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TagInput.js","sourceRoot":"","sources":["../../../../src/components/TagInput/TagInput.tsx"],"names":[],"mappings":"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","sourcesContent":["\"use client\"\n\nimport React, { useEffect, useLayoutEffect, useMemo, useRef, useState } from \"react\"\nimport { useOnClickOutside } from \"usehooks-ts\"\nimport { useLatestValue } from \"../../hooks/useLatestValue\"\nimport { toCssVariables } from \"../../lib/helpers\"\nimport type { Sizes } from \"../../types\"\nimport { X } from \"../Icon\"\nimport s from \"./TagInput.module.css\"\n\nexport type Tag = {\n value: string\n valid: boolean\n}\n\nexport type TagInputProps = {\n /**\n * The state of the tag input when it is initially rendered, used when uncontrolled\n */\n defaultValue?: Tag[]\n /**\n * The value of the tag input, used to control the tag input\n */\n value?: Tag[]\n /**\n * Allows the tag input to be targeted with htmlFor\n */\n id?: string\n /**\n * Corresponds with Input height when rows=1\n * @default xl\n */\n size?: Sizes<\"md\" | \"lg\" | \"xl\" | \"2xl\" | \"3xl\">\n /**\n * Callback function invoked when the tag list changes\n */\n onChange?: (tags: Tag[]) => void\n /**\n * Placeholder text for the input\n */\n placeholder?: string\n /**\n * A function that returns whether a given value is a valid tag.\n * Invalid tags are highlighted in red.\n * Tags are evaluated for validity only on creation; changing the validator function later has no effect\n */\n validator?: (value: string) => boolean\n /**\n * The maximum number of tags allowed before the input is disabled; displays a counter below the input\n */\n maxTags?: number\n /**\n * Whether to focus this input on mount\n * @default false\n */\n autoFocus?: boolean\n /**\n * The minimum number of rows for the tag input\n * @default 1\n */\n rows?: number\n /**\n * Controls what characters will count towards creating a new tag\n * @default [\",\", \" \"]\n */\n delimiters?: string[]\n /**\n * Disables the tag input visually and from interactions\n */\n disabled?: boolean\n}\n\n// How many pixels to reserve on the right of the input as a buffer before wrapping to the next line\nconst INPUT_CURSOR_TOLERANCE_PX = 10\n// The total space reserved on either side of the input for padding\nconst CONTAINER_PADDING_PX = 24\nconst SHAKE_ANIMATION_DURATION_MS = 500\n\nexport const TagInput = (props: TagInputProps) => {\n const {\n defaultValue: defaultValueProp = [],\n value: controlledValue,\n size = \"xl\",\n onChange,\n validator,\n maxTags,\n placeholder = \"\",\n autoFocus = false,\n rows = 1,\n delimiters = [\",\", \" \"],\n disabled,\n id,\n } = props\n\n const [internalTags, setInternalTags] = useState(defaultValueProp)\n\n const value = controlledValue ?? internalTags\n const isControlled = controlledValue !== undefined\n\n const tags = useMemo(() => new Map(value.map((tag) => [tag.value, tag])), [value])\n\n const [currentInput, setCurrentInput] = useState(\"\")\n const [focused, setFocused] = useState(autoFocus)\n const [selectedTag, setSelectedTag] = useState<string | null>(null)\n const [duplicateTags, setDuplicateTags] = useState<Set<string>>(new Set())\n const [inputWidth, setInputWidth] = useState<number>(0)\n const validatorLatest = useLatestValue(validator)\n const onChangeLatest = useLatestValue(onChange)\n\n const inputRef = useRef<HTMLInputElement>(null)\n const containerRef = useRef<HTMLDivElement>(null)\n const measureRef = useRef<HTMLSpanElement>(null)\n\n const showInput = !maxTags || tags.size < maxTags\n\n // Handle focusing the correct part of the tag input\n useEffect(() => {\n if (!focused || !containerRef.current) {\n return\n }\n const defaultFocusEl = inputRef.current ?? containerRef.current\n if (selectedTag === null) {\n defaultFocusEl.focus()\n } else {\n const selectedTagElement = containerRef.current.querySelector(\n `[data-tag=\"${selectedTag}\"]`,\n ) as HTMLElement | null\n if (selectedTagElement) {\n selectedTagElement.focus()\n } else {\n defaultFocusEl.focus()\n }\n }\n }, [focused, selectedTag, showInput]) // Include showInput so we focus the container when we hide the input\n\n const placeholderText = tags.size === 0 ? placeholder : undefined\n\n // Handle positioning the real input inside of the container\n // Use useLayoutEffect to avoid flashing during width calculation\n useLayoutEffect(() => {\n if (containerRef.current && measureRef.current) {\n const containerRect = containerRef.current.getBoundingClientRect()\n const tagElements = Array.from(\n containerRef.current.querySelectorAll(\"[data-tag]\"),\n ) as HTMLDivElement[]\n\n // Grab the right edge of the last tag if it exists, otherwise the left edge of the container\n const leftBound =\n tagElements.length > 0\n ? tagElements[tagElements.length - 1].getBoundingClientRect().right\n : containerRect.left\n\n measureRef.current.textContent = currentInput || placeholderText || \"\"\n\n // By padding the text width, we ensure the input wraps to the next line\n // before we get to the point where we start to overflow\n const textWidth = measureRef.current.getBoundingClientRect().width + INPUT_CURSOR_TOLERANCE_PX\n\n // Calculate the remaining space based on the last tag's right edge (or container's left if no tags)\n const remainingSpace = containerRect.right - leftBound - CONTAINER_PADDING_PX\n\n if (textWidth <= remainingSpace) {\n setInputWidth(remainingSpace)\n } else {\n // We are going to flow to a new line, so recalculate remaining space based on the container size\n const width = containerRect.right - containerRect.left - CONTAINER_PADDING_PX\n setInputWidth(width)\n }\n }\n }, [currentInput, placeholderText, tags]) // Include tags so we reflow the container when we delete a tag\n\n // ============================================\n // Tag lifecycle functions\n // ============================================\n\n const addTag = (tagValue: string) => {\n const trimmed = tagValue.trim()\n if (!trimmed) {\n return\n }\n if (tags.has(trimmed)) {\n setDuplicateTags((prevTags) => new Set(prevTags).add(trimmed))\n setTimeout(\n () =>\n setDuplicateTags((prevTags) => {\n const newTags = new Set(prevTags)\n newTags.delete(trimmed)\n return newTags\n }),\n SHAKE_ANIMATION_DURATION_MS,\n )\n return\n }\n const validTag = validatorLatest.current?.(trimmed) ?? true\n const newSet = new Map(tags)\n newSet.set(trimmed, { value: trimmed, valid: validTag })\n const newTags = Array.from(newSet.values())\n onChangeLatest.current?.(newTags)\n\n if (!isControlled) {\n setInternalTags(newTags)\n }\n }\n\n const removeTag = (tag: string) => {\n const newSet = new Map(tags)\n newSet.delete(tag)\n const newTags = Array.from(newSet.values())\n onChangeLatest.current?.(newTags)\n if (!isControlled) {\n setInternalTags(newTags)\n }\n if (selectedTag === tag) {\n setSelectedTag(null)\n }\n }\n\n const selectPreviousTag = () => {\n if (tags.size === 0) {\n return\n }\n const tagList = Array.from(tags.keys())\n if (selectedTag === null) {\n setSelectedTag(tagList[tagList.length - 1])\n } else {\n const prevIndex = tagList.indexOf(selectedTag)\n const index = Math.max(0, prevIndex - 1)\n setSelectedTag(tagList[index])\n }\n }\n\n const selectNextTag = () => {\n if (selectedTag === null) {\n return\n }\n const tagList = Array.from(tags.keys())\n const prevIndex = tagList.indexOf(selectedTag)\n const index = prevIndex + 1\n if (index < tagList.length) {\n setSelectedTag(tagList[index])\n } else {\n setSelectedTag(null)\n }\n }\n\n // ============================================\n // Helper functions\n // ============================================\n\n const isEmptyStartingSelection = () => {\n const input = inputRef.current\n if (!input) {\n return true\n }\n return input.selectionStart === 0 && input.selectionEnd === 0\n }\n\n const handleContainerBlur = () => {\n setFocused(false)\n setSelectedTag(null)\n if (currentInput) {\n addTag(currentInput)\n setCurrentInput(\"\")\n }\n }\n\n // ============================================\n // Event handlers\n // ============================================\n\n const handleContainerKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {\n if (e.key === \"ArrowLeft\" || e.key === \"ArrowUp\") {\n if (isEmptyStartingSelection()) {\n e.preventDefault()\n selectPreviousTag()\n }\n } else if (e.key === \"ArrowRight\" || e.key === \"ArrowDown\") {\n if (selectedTag !== null) {\n e.preventDefault()\n selectNextTag()\n }\n } else if (e.key === \"Backspace\") {\n if (selectedTag !== null) {\n removeTag(selectedTag)\n } else if (isEmptyStartingSelection()) {\n selectPreviousTag()\n }\n }\n }\n\n const handleInputKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {\n if (e.key === \"Enter\" || delimiters.includes(e.key)) {\n e.preventDefault()\n if (currentInput) {\n addTag(currentInput)\n setCurrentInput(\"\")\n }\n } else if (e.key === \"Tab\") {\n if (currentInput) {\n e.preventDefault()\n addTag(currentInput)\n setCurrentInput(\"\")\n }\n }\n }\n\n const handlePaste = (e: React.ClipboardEvent<HTMLInputElement>) => {\n const text = e.clipboardData.getData(\"Text\")\n let parts = [text]\n\n // Split by all delimiters\n for (const delimiter of delimiters) {\n const newParts = []\n for (const segment of parts) {\n newParts.push(...segment.split(delimiter))\n }\n parts = newParts\n }\n\n // Remove empty parts\n parts = parts.filter(Boolean)\n\n if (parts.length > 1) {\n e.preventDefault()\n parts.forEach((part) => addTag(part))\n }\n }\n\n const handleContainerMouseDown = (e: React.MouseEvent) => {\n // All clicks in the container focus the container\n setFocused(true)\n\n // If the click is on a tag pill, we are done. The click handler\n // for the specific tag will handle focusing it\n if (e.target && e.target instanceof Element && e.target.closest(\"[data-tag]\")) {\n return\n }\n\n // Since we know we didn't click a tag, clear any selected tag\n setSelectedTag(null)\n\n // If this click is outside of the input, prevent it from \"stealing\" focus from the input\n if (\n e.target &&\n e.target instanceof Element &&\n inputRef.current &&\n !inputRef.current.contains(e.target)\n ) {\n e.preventDefault()\n\n const { left, right, top, bottom } = inputRef.current.getBoundingClientRect()\n const { clientX, clientY } = e\n\n // If this is the first click, clear the selection. Otherwise, select the input contents\n if (e.detail === 1) {\n if (clientY < top || clientX < left) {\n // \"Before\" the input: top/left\n inputRef.current.setSelectionRange(0, 0)\n } else if (clientY > bottom || clientX > right) {\n // \"After\" the input: bottom/right\n const length = inputRef.current.value.length\n inputRef.current.setSelectionRange(length, length)\n }\n } else {\n inputRef.current.select()\n }\n }\n }\n\n const handleFocus = (e: React.FocusEvent) => {\n // If the focus is on a tag pill, do not trigger input focus logic\n // The click handler for the specific tag will handle it instead\n if (e.target && e.target instanceof Element && e.target.closest(\"[data-tag]\")) {\n return\n }\n setFocused(true)\n }\n\n const handleBlur = (e: React.FocusEvent) => {\n // If there is no related target, don't remove focus.\n // This occurs on a click inside the container but not on any element.\n // The handleClickOutside handler handles other cases\n if (!e.relatedTarget || !(e.relatedTarget instanceof Node)) {\n return\n }\n // Don't clear focus if focus is only moved elsewhere within the container\n if (containerRef.current && containerRef.current.contains(e.relatedTarget)) {\n // If we just tabbed into the input, clear the selected tag\n if (inputRef.current && inputRef.current.contains(e.relatedTarget)) {\n setSelectedTag(null)\n }\n return\n }\n handleContainerBlur()\n }\n\n // @ts-expect-error - Fix once usehooks-ts is updated https://github.com/juliencrn/usehooks-ts/pull/675\n useOnClickOutside(containerRef, handleContainerBlur)\n\n return (\n <>\n <div\n className={s.Container}\n ref={containerRef}\n onKeyDown={handleContainerKeyDown}\n onMouseDown={handleContainerMouseDown}\n onFocus={handleFocus}\n onBlur={handleBlur}\n data-size={size}\n data-focused={focused ? \"\" : undefined}\n data-empty={tags.size === 0 ? \"\" : undefined}\n tabIndex={-1}\n style={toCssVariables({ \"min-rows\": String(rows) })}\n data-disabled={disabled ? \"\" : undefined}\n >\n <div className={s.TagInput}>\n {Array.from(tags.values()).map((tag) => (\n <div\n key={tag.value}\n className={s.Tag}\n tabIndex={-1}\n onClick={() => setSelectedTag(tag.value)}\n data-tag={tag.value}\n data-invalid={!tag.valid ? \"\" : undefined}\n data-duplicate={duplicateTags.has(tag.value) ? \"\" : undefined}\n >\n <span className=\"overflow-hidden text-ellipsis\" title={tag.value}>\n <span className={s.TagValue}>{tag.value}</span>\n </span>\n <div\n className={s.TagRemove}\n onClick={() => removeTag(tag.value)}\n role=\"button\"\n aria-label=\"Remove item\"\n >\n <X height={14} width={14} />\n </div>\n </div>\n ))}\n {showInput && (\n <div className={s.InputContainer}>\n {/* Hidden element to measure input width */}\n <span ref={measureRef} className={s.InputMeasure} />\n <div className={s.InputWrapper}>\n <input\n id={id}\n className={s.Input}\n ref={inputRef}\n value={currentInput}\n onChange={(e) => {\n setCurrentInput(e.target.value)\n }}\n onPaste={handlePaste}\n onKeyDown={handleInputKeyDown}\n placeholder={placeholderText}\n style={{ width: inputWidth }}\n disabled={disabled}\n />\n </div>\n </div>\n )}\n </div>\n </div>\n {maxTags && (\n <div className={s.Limit}>\n {tags.size}\n <span className=\"mx-px\">/</span>\n {maxTags}\n </div>\n )}\n </>\n )\n}\n"]}
|
|
1
|
+
{"version":3,"file":"TagInput.js","sourceRoot":"","sources":["../../../../src/components/TagInput/TagInput.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAA;;AAEZ,OAAO,KAAK,EAAE,EAAE,SAAS,EAAE,eAAe,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AACpF,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AAC/C,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAA;AAC3D,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA;AAElD,OAAO,EAAE,CAAC,EAAE,MAAM,SAAS,CAAA;AAC3B,OAAO,CAAC,MAAM,uBAAuB,CAAA;AAgErC,oGAAoG;AACpG,MAAM,yBAAyB,GAAG,EAAE,CAAA;AACpC,mEAAmE;AACnE,MAAM,oBAAoB,GAAG,EAAE,CAAA;AAC/B,MAAM,2BAA2B,GAAG,GAAG,CAAA;AAEvC,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,KAAoB,EAAE,EAAE;IAC/C,MAAM,EACJ,YAAY,EAAE,gBAAgB,GAAG,EAAE,EACnC,KAAK,EAAE,eAAe,EACtB,IAAI,GAAG,IAAI,EACX,QAAQ,EACR,SAAS,EACT,OAAO,EACP,WAAW,GAAG,EAAE,EAChB,SAAS,GAAG,KAAK,EACjB,IAAI,GAAG,CAAC,EACR,UAAU,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,EACvB,QAAQ,EACR,EAAE,GACH,GAAG,KAAK,CAAA;IAET,MAAM,CAAC,YAAY,EAAE,eAAe,CAAC,GAAG,QAAQ,CAAC,gBAAgB,CAAC,CAAA;IAElE,MAAM,KAAK,GAAG,eAAe,IAAI,YAAY,CAAA;IAC7C,MAAM,YAAY,GAAG,eAAe,KAAK,SAAS,CAAA;IAElD,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAA;IAElF,MAAM,CAAC,YAAY,EAAE,eAAe,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAA;IACpD,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAA;IACjD,MAAM,CAAC,WAAW,EAAE,cAAc,CAAC,GAAG,QAAQ,CAAgB,IAAI,CAAC,CAAA;IACnE,MAAM,CAAC,aAAa,EAAE,gBAAgB,CAAC,GAAG,QAAQ,CAAc,IAAI,GAAG,EAAE,CAAC,CAAA;IAC1E,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,QAAQ,CAAS,CAAC,CAAC,CAAA;IACvD,MAAM,eAAe,GAAG,cAAc,CAAC,SAAS,CAAC,CAAA;IACjD,MAAM,cAAc,GAAG,cAAc,CAAC,QAAQ,CAAC,CAAA;IAE/C,MAAM,QAAQ,GAAG,MAAM,CAAmB,IAAI,CAAC,CAAA;IAC/C,MAAM,YAAY,GAAG,MAAM,CAAiB,IAAI,CAAC,CAAA;IACjD,MAAM,UAAU,GAAG,MAAM,CAAkB,IAAI,CAAC,CAAA;IAEhD,MAAM,SAAS,GAAG,CAAC,OAAO,IAAI,IAAI,CAAC,IAAI,GAAG,OAAO,CAAA;IAEjD,oDAAoD;IACpD,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,OAAO,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,CAAC;YACtC,OAAM;QACR,CAAC;QACD,MAAM,cAAc,GAAG,QAAQ,CAAC,OAAO,IAAI,YAAY,CAAC,OAAO,CAAA;QAC/D,IAAI,WAAW,KAAK,IAAI,EAAE,CAAC;YACzB,cAAc,CAAC,KAAK,EAAE,CAAA;QACxB,CAAC;aAAM,CAAC;YACN,MAAM,kBAAkB,GAAG,YAAY,CAAC,OAAO,CAAC,aAAa,CAC3D,cAAc,WAAW,IAAI,CACR,CAAA;YACvB,IAAI,kBAAkB,EAAE,CAAC;gBACvB,kBAAkB,CAAC,KAAK,EAAE,CAAA;YAC5B,CAAC;iBAAM,CAAC;gBACN,cAAc,CAAC,KAAK,EAAE,CAAA;YACxB,CAAC;QACH,CAAC;IACH,CAAC,EAAE,CAAC,OAAO,EAAE,WAAW,EAAE,SAAS,CAAC,CAAC,CAAA,CAAC,qEAAqE;IAE3G,MAAM,eAAe,GAAG,IAAI,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,CAAA;IAEjE,4DAA4D;IAC5D,iEAAiE;IACjE,eAAe,CAAC,GAAG,EAAE;QACnB,IAAI,YAAY,CAAC,OAAO,IAAI,UAAU,CAAC,OAAO,EAAE,CAAC;YAC/C,MAAM,aAAa,GAAG,YAAY,CAAC,OAAO,CAAC,qBAAqB,EAAE,CAAA;YAClE,MAAM,WAAW,GAAG,KAAK,CAAC,IAAI,CAC5B,YAAY,CAAC,OAAO,CAAC,gBAAgB,CAAC,YAAY,CAAC,CAChC,CAAA;YAErB,6FAA6F;YAC7F,MAAM,SAAS,GACb,WAAW,CAAC,MAAM,GAAG,CAAC;gBACpB,CAAC,CAAC,WAAW,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,qBAAqB,EAAE,CAAC,KAAK;gBACnE,CAAC,CAAC,aAAa,CAAC,IAAI,CAAA;YAExB,UAAU,CAAC,OAAO,CAAC,WAAW,GAAG,YAAY,IAAI,eAAe,IAAI,EAAE,CAAA;YAEtE,wEAAwE;YACxE,wDAAwD;YACxD,MAAM,SAAS,GAAG,UAAU,CAAC,OAAO,CAAC,qBAAqB,EAAE,CAAC,KAAK,GAAG,yBAAyB,CAAA;YAE9F,oGAAoG;YACpG,MAAM,cAAc,GAAG,aAAa,CAAC,KAAK,GAAG,SAAS,GAAG,oBAAoB,CAAA;YAE7E,IAAI,SAAS,IAAI,cAAc,EAAE,CAAC;gBAChC,aAAa,CAAC,cAAc,CAAC,CAAA;YAC/B,CAAC;iBAAM,CAAC;gBACN,iGAAiG;gBACjG,MAAM,KAAK,GAAG,aAAa,CAAC,KAAK,GAAG,aAAa,CAAC,IAAI,GAAG,oBAAoB,CAAA;gBAC7E,aAAa,CAAC,KAAK,CAAC,CAAA;YACtB,CAAC;QACH,CAAC;IACH,CAAC,EAAE,CAAC,YAAY,EAAE,eAAe,EAAE,IAAI,CAAC,CAAC,CAAA,CAAC,+DAA+D;IAEzG,+CAA+C;IAC/C,0BAA0B;IAC1B,+CAA+C;IAE/C,MAAM,MAAM,GAAG,CAAC,QAAgB,EAAE,EAAE;QAClC,MAAM,OAAO,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAA;QAC/B,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAM;QACR,CAAC;QACD,IAAI,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;YACtB,gBAAgB,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,IAAI,GAAG,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAA;YAC9D,UAAU,CACR,GAAG,EAAE,CACH,gBAAgB,CAAC,CAAC,QAAQ,EAAE,EAAE;gBAC5B,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,CAAA;gBACjC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;gBACvB,OAAO,OAAO,CAAA;YAChB,CAAC,CAAC,EACJ,2BAA2B,CAC5B,CAAA;YACD,OAAM;QACR,CAAC;QACD,MAAM,QAAQ,GAAG,eAAe,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,IAAI,IAAI,CAAA;QAC3D,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,CAAA;QAC5B,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAA;QACxD,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAA;QAC3C,cAAc,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,CAAA;QAEjC,IAAI,CAAC,YAAY,EAAE,CAAC;YAClB,eAAe,CAAC,OAAO,CAAC,CAAA;QAC1B,CAAC;IACH,CAAC,CAAA;IAED,MAAM,SAAS,GAAG,CAAC,GAAW,EAAE,EAAE;QAChC,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,CAAA;QAC5B,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;QAClB,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAA;QAC3C,cAAc,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,CAAA;QACjC,IAAI,CAAC,YAAY,EAAE,CAAC;YAClB,eAAe,CAAC,OAAO,CAAC,CAAA;QAC1B,CAAC;QACD,IAAI,WAAW,KAAK,GAAG,EAAE,CAAC;YACxB,cAAc,CAAC,IAAI,CAAC,CAAA;QACtB,CAAC;IACH,CAAC,CAAA;IAED,MAAM,iBAAiB,GAAG,GAAG,EAAE;QAC7B,IAAI,IAAI,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;YACpB,OAAM;QACR,CAAC;QACD,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAA;QACvC,IAAI,WAAW,KAAK,IAAI,EAAE,CAAC;YACzB,cAAc,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAA;QAC7C,CAAC;aAAM,CAAC;YACN,MAAM,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC,CAAA;YAC9C,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,SAAS,GAAG,CAAC,CAAC,CAAA;YACxC,cAAc,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAA;QAChC,CAAC;IACH,CAAC,CAAA;IAED,MAAM,aAAa,GAAG,GAAG,EAAE;QACzB,IAAI,WAAW,KAAK,IAAI,EAAE,CAAC;YACzB,OAAM;QACR,CAAC;QACD,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAA;QACvC,MAAM,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC,CAAA;QAC9C,MAAM,KAAK,GAAG,SAAS,GAAG,CAAC,CAAA;QAC3B,IAAI,KAAK,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;YAC3B,cAAc,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAA;QAChC,CAAC;aAAM,CAAC;YACN,cAAc,CAAC,IAAI,CAAC,CAAA;QACtB,CAAC;IACH,CAAC,CAAA;IAED,+CAA+C;IAC/C,mBAAmB;IACnB,+CAA+C;IAE/C,MAAM,wBAAwB,GAAG,GAAG,EAAE;QACpC,MAAM,KAAK,GAAG,QAAQ,CAAC,OAAO,CAAA;QAC9B,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,IAAI,CAAA;QACb,CAAC;QACD,OAAO,KAAK,CAAC,cAAc,KAAK,CAAC,IAAI,KAAK,CAAC,YAAY,KAAK,CAAC,CAAA;IAC/D,CAAC,CAAA;IAED,MAAM,mBAAmB,GAAG,GAAG,EAAE;QAC/B,UAAU,CAAC,KAAK,CAAC,CAAA;QACjB,cAAc,CAAC,IAAI,CAAC,CAAA;QACpB,IAAI,YAAY,EAAE,CAAC;YACjB,MAAM,CAAC,YAAY,CAAC,CAAA;YACpB,eAAe,CAAC,EAAE,CAAC,CAAA;QACrB,CAAC;IACH,CAAC,CAAA;IAED,+CAA+C;IAC/C,iBAAiB;IACjB,+CAA+C;IAE/C,MAAM,sBAAsB,GAAG,CAAC,CAAwC,EAAE,EAAE;QAC1E,IAAI,CAAC,CAAC,GAAG,KAAK,WAAW,IAAI,CAAC,CAAC,GAAG,KAAK,SAAS,EAAE,CAAC;YACjD,IAAI,wBAAwB,EAAE,EAAE,CAAC;gBAC/B,CAAC,CAAC,cAAc,EAAE,CAAA;gBAClB,iBAAiB,EAAE,CAAA;YACrB,CAAC;QACH,CAAC;aAAM,IAAI,CAAC,CAAC,GAAG,KAAK,YAAY,IAAI,CAAC,CAAC,GAAG,KAAK,WAAW,EAAE,CAAC;YAC3D,IAAI,WAAW,KAAK,IAAI,EAAE,CAAC;gBACzB,CAAC,CAAC,cAAc,EAAE,CAAA;gBAClB,aAAa,EAAE,CAAA;YACjB,CAAC;QACH,CAAC;aAAM,IAAI,CAAC,CAAC,GAAG,KAAK,WAAW,EAAE,CAAC;YACjC,IAAI,WAAW,KAAK,IAAI,EAAE,CAAC;gBACzB,SAAS,CAAC,WAAW,CAAC,CAAA;YACxB,CAAC;iBAAM,IAAI,wBAAwB,EAAE,EAAE,CAAC;gBACtC,iBAAiB,EAAE,CAAA;YACrB,CAAC;QACH,CAAC;IACH,CAAC,CAAA;IAED,MAAM,kBAAkB,GAAG,CAAC,CAAwC,EAAE,EAAE;QACtE,IAAI,CAAC,CAAC,GAAG,KAAK,OAAO,IAAI,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC;YACpD,CAAC,CAAC,cAAc,EAAE,CAAA;YAClB,IAAI,YAAY,EAAE,CAAC;gBACjB,MAAM,CAAC,YAAY,CAAC,CAAA;gBACpB,eAAe,CAAC,EAAE,CAAC,CAAA;YACrB,CAAC;QACH,CAAC;aAAM,IAAI,CAAC,CAAC,GAAG,KAAK,KAAK,EAAE,CAAC;YAC3B,IAAI,YAAY,EAAE,CAAC;gBACjB,CAAC,CAAC,cAAc,EAAE,CAAA;gBAClB,MAAM,CAAC,YAAY,CAAC,CAAA;gBACpB,eAAe,CAAC,EAAE,CAAC,CAAA;YACrB,CAAC;QACH,CAAC;IACH,CAAC,CAAA;IAED,MAAM,WAAW,GAAG,CAAC,CAAyC,EAAE,EAAE;QAChE,MAAM,IAAI,GAAG,CAAC,CAAC,aAAa,CAAC,OAAO,CAAC,MAAM,CAAC,CAAA;QAC5C,IAAI,KAAK,GAAG,CAAC,IAAI,CAAC,CAAA;QAElB,0BAA0B;QAC1B,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;YACnC,MAAM,QAAQ,GAAG,EAAE,CAAA;YACnB,KAAK,MAAM,OAAO,IAAI,KAAK,EAAE,CAAC;gBAC5B,QAAQ,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAA;YAC5C,CAAC;YACD,KAAK,GAAG,QAAQ,CAAA;QAClB,CAAC;QAED,qBAAqB;QACrB,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;QAE7B,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACrB,CAAC,CAAC,cAAc,EAAE,CAAA;YAClB,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAA;QACvC,CAAC;IACH,CAAC,CAAA;IAED,MAAM,wBAAwB,GAAG,CAAC,CAAmB,EAAE,EAAE;QACvD,kDAAkD;QAClD,UAAU,CAAC,IAAI,CAAC,CAAA;QAEhB,gEAAgE;QAChE,+CAA+C;QAC/C,IAAI,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,MAAM,YAAY,OAAO,IAAI,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE,CAAC;YAC9E,OAAM;QACR,CAAC;QAED,8DAA8D;QAC9D,cAAc,CAAC,IAAI,CAAC,CAAA;QAEpB,yFAAyF;QACzF,IACE,CAAC,CAAC,MAAM;YACR,CAAC,CAAC,MAAM,YAAY,OAAO;YAC3B,QAAQ,CAAC,OAAO;YAChB,CAAC,QAAQ,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,EACpC,CAAC;YACD,CAAC,CAAC,cAAc,EAAE,CAAA;YAElB,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,QAAQ,CAAC,OAAO,CAAC,qBAAqB,EAAE,CAAA;YAC7E,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,CAAC,CAAA;YAE9B,wFAAwF;YACxF,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACnB,IAAI,OAAO,GAAG,GAAG,IAAI,OAAO,GAAG,IAAI,EAAE,CAAC;oBACpC,+BAA+B;oBAC/B,QAAQ,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;gBAC1C,CAAC;qBAAM,IAAI,OAAO,GAAG,MAAM,IAAI,OAAO,GAAG,KAAK,EAAE,CAAC;oBAC/C,kCAAkC;oBAClC,MAAM,MAAM,GAAG,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,CAAA;oBAC5C,QAAQ,CAAC,OAAO,CAAC,iBAAiB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;gBACpD,CAAC;YACH,CAAC;iBAAM,CAAC;gBACN,QAAQ,CAAC,OAAO,CAAC,MAAM,EAAE,CAAA;YAC3B,CAAC;QACH,CAAC;IACH,CAAC,CAAA;IAED,MAAM,WAAW,GAAG,CAAC,CAAmB,EAAE,EAAE;QAC1C,kEAAkE;QAClE,gEAAgE;QAChE,IAAI,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,MAAM,YAAY,OAAO,IAAI,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE,CAAC;YAC9E,OAAM;QACR,CAAC;QACD,UAAU,CAAC,IAAI,CAAC,CAAA;IAClB,CAAC,CAAA;IAED,MAAM,UAAU,GAAG,CAAC,CAAmB,EAAE,EAAE;QACzC,qDAAqD;QACrD,sEAAsE;QACtE,qDAAqD;QACrD,IAAI,CAAC,CAAC,CAAC,aAAa,IAAI,CAAC,CAAC,CAAC,CAAC,aAAa,YAAY,IAAI,CAAC,EAAE,CAAC;YAC3D,OAAM;QACR,CAAC;QACD,0EAA0E;QAC1E,IAAI,YAAY,CAAC,OAAO,IAAI,YAAY,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,aAAa,CAAC,EAAE,CAAC;YAC3E,2DAA2D;YAC3D,IAAI,QAAQ,CAAC,OAAO,IAAI,QAAQ,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,aAAa,CAAC,EAAE,CAAC;gBACnE,cAAc,CAAC,IAAI,CAAC,CAAA;YACtB,CAAC;YACD,OAAM;QACR,CAAC;QACD,mBAAmB,EAAE,CAAA;IACvB,CAAC,CAAA;IAED,uGAAuG;IACvG,iBAAiB,CAAC,YAAY,EAAE,mBAAmB,CAAC,CAAA;IAEpD,OAAO,CACL,8BACE,cACE,SAAS,EAAE,CAAC,CAAC,SAAS,EACtB,GAAG,EAAE,YAAY,EACjB,SAAS,EAAE,sBAAsB,EACjC,WAAW,EAAE,wBAAwB,EACrC,OAAO,EAAE,WAAW,EACpB,MAAM,EAAE,UAAU,eACP,IAAI,kBACD,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,gBAC1B,IAAI,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,EAC5C,QAAQ,EAAE,CAAC,CAAC,EACZ,KAAK,EAAE,cAAc,CAAC,EAAE,UAAU,EAAE,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,mBACpC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,YAExC,eAAK,SAAS,EAAE,CAAC,CAAC,QAAQ,aACvB,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CACtC,eAEE,SAAS,EAAE,CAAC,CAAC,GAAG,EAChB,QAAQ,EAAE,CAAC,CAAC,EACZ,OAAO,EAAE,GAAG,EAAE,CAAC,cAAc,CAAC,GAAG,CAAC,KAAK,CAAC,cAC9B,GAAG,CAAC,KAAK,kBACL,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,oBACzB,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,aAE7D,eAAM,SAAS,EAAC,+BAA+B,EAAC,KAAK,EAAE,GAAG,CAAC,KAAK,YAC9D,eAAM,SAAS,EAAE,CAAC,CAAC,QAAQ,YAAG,GAAG,CAAC,KAAK,GAAQ,GAC1C,EACP,cACE,SAAS,EAAE,CAAC,CAAC,SAAS,EACtB,OAAO,EAAE,GAAG,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,EACnC,IAAI,EAAC,QAAQ,gBACF,aAAa,YAExB,KAAC,CAAC,KAAG,GACD,KAlBD,GAAG,CAAC,KAAK,CAmBV,CACP,CAAC,EACD,SAAS,IAAI,CACZ,eAAK,SAAS,EAAE,CAAC,CAAC,cAAc,aAE9B,eAAM,GAAG,EAAE,UAAU,EAAE,SAAS,EAAE,CAAC,CAAC,YAAY,GAAI,EACpD,cAAK,SAAS,EAAE,CAAC,CAAC,YAAY,YAC5B,gBACE,EAAE,EAAE,EAAE,EACN,SAAS,EAAE,CAAC,CAAC,KAAK,EAClB,GAAG,EAAE,QAAQ,EACb,KAAK,EAAE,YAAY,EACnB,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE;4CACd,eAAe,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;wCACjC,CAAC,EACD,OAAO,EAAE,WAAW,EACpB,SAAS,EAAE,kBAAkB,EAC7B,WAAW,EAAE,eAAe,EAC5B,KAAK,EAAE,EAAE,KAAK,EAAE,UAAU,EAAE,EAC5B,QAAQ,EAAE,QAAQ,GAClB,GACE,IACF,CACP,IACG,GACF,EACL,OAAO,IAAI,CACV,eAAK,SAAS,EAAE,CAAC,CAAC,KAAK,aACpB,IAAI,CAAC,IAAI,EACV,eAAM,SAAS,EAAC,OAAO,kBAAS,EAC/B,OAAO,IACJ,CACP,IACA,CACJ,CAAA;AACH,CAAC,CAAA","sourcesContent":["\"use client\"\n\nimport React, { useEffect, useLayoutEffect, useMemo, useRef, useState } from \"react\"\nimport { useOnClickOutside } from \"usehooks-ts\"\nimport { useLatestValue } from \"../../hooks/useLatestValue\"\nimport { toCssVariables } from \"../../lib/helpers\"\nimport type { Sizes } from \"../../types\"\nimport { X } from \"../Icon\"\nimport s from \"./TagInput.module.css\"\n\nexport type Tag = {\n value: string\n valid: boolean\n}\n\nexport type TagInputProps = {\n /**\n * The state of the tag input when it is initially rendered, used when uncontrolled\n */\n defaultValue?: Tag[]\n /**\n * The value of the tag input, used to control the tag input\n */\n value?: Tag[]\n /**\n * Allows the tag input to be targeted with htmlFor\n */\n id?: string\n /**\n * Corresponds with Input height when rows=1\n * @default xl\n */\n size?: Sizes<\"md\" | \"lg\" | \"xl\" | \"2xl\" | \"3xl\">\n /**\n * Callback function invoked when the tag list changes\n */\n onChange?: (tags: Tag[]) => void\n /**\n * Placeholder text for the input\n */\n placeholder?: string\n /**\n * A function that returns whether a given value is a valid tag.\n * Invalid tags are highlighted in red.\n * Tags are evaluated for validity only on creation; changing the validator function later has no effect\n */\n validator?: (value: string) => boolean\n /**\n * The maximum number of tags allowed before the input is disabled; displays a counter below the input\n */\n maxTags?: number\n /**\n * Whether to focus this input on mount\n * @default false\n */\n autoFocus?: boolean\n /**\n * The minimum number of rows for the tag input\n * @default 1\n */\n rows?: number\n /**\n * Controls what characters will count towards creating a new tag\n * @default [\",\", \" \"]\n */\n delimiters?: string[]\n /**\n * Disables the tag input visually and from interactions\n */\n disabled?: boolean\n}\n\n// How many pixels to reserve on the right of the input as a buffer before wrapping to the next line\nconst INPUT_CURSOR_TOLERANCE_PX = 10\n// The total space reserved on either side of the input for padding\nconst CONTAINER_PADDING_PX = 24\nconst SHAKE_ANIMATION_DURATION_MS = 500\n\nexport const TagInput = (props: TagInputProps) => {\n const {\n defaultValue: defaultValueProp = [],\n value: controlledValue,\n size = \"xl\",\n onChange,\n validator,\n maxTags,\n placeholder = \"\",\n autoFocus = false,\n rows = 1,\n delimiters = [\",\", \" \"],\n disabled,\n id,\n } = props\n\n const [internalTags, setInternalTags] = useState(defaultValueProp)\n\n const value = controlledValue ?? internalTags\n const isControlled = controlledValue !== undefined\n\n const tags = useMemo(() => new Map(value.map((tag) => [tag.value, tag])), [value])\n\n const [currentInput, setCurrentInput] = useState(\"\")\n const [focused, setFocused] = useState(autoFocus)\n const [selectedTag, setSelectedTag] = useState<string | null>(null)\n const [duplicateTags, setDuplicateTags] = useState<Set<string>>(new Set())\n const [inputWidth, setInputWidth] = useState<number>(0)\n const validatorLatest = useLatestValue(validator)\n const onChangeLatest = useLatestValue(onChange)\n\n const inputRef = useRef<HTMLInputElement>(null)\n const containerRef = useRef<HTMLDivElement>(null)\n const measureRef = useRef<HTMLSpanElement>(null)\n\n const showInput = !maxTags || tags.size < maxTags\n\n // Handle focusing the correct part of the tag input\n useEffect(() => {\n if (!focused || !containerRef.current) {\n return\n }\n const defaultFocusEl = inputRef.current ?? containerRef.current\n if (selectedTag === null) {\n defaultFocusEl.focus()\n } else {\n const selectedTagElement = containerRef.current.querySelector(\n `[data-tag=\"${selectedTag}\"]`,\n ) as HTMLElement | null\n if (selectedTagElement) {\n selectedTagElement.focus()\n } else {\n defaultFocusEl.focus()\n }\n }\n }, [focused, selectedTag, showInput]) // Include showInput so we focus the container when we hide the input\n\n const placeholderText = tags.size === 0 ? placeholder : undefined\n\n // Handle positioning the real input inside of the container\n // Use useLayoutEffect to avoid flashing during width calculation\n useLayoutEffect(() => {\n if (containerRef.current && measureRef.current) {\n const containerRect = containerRef.current.getBoundingClientRect()\n const tagElements = Array.from(\n containerRef.current.querySelectorAll(\"[data-tag]\"),\n ) as HTMLDivElement[]\n\n // Grab the right edge of the last tag if it exists, otherwise the left edge of the container\n const leftBound =\n tagElements.length > 0\n ? tagElements[tagElements.length - 1].getBoundingClientRect().right\n : containerRect.left\n\n measureRef.current.textContent = currentInput || placeholderText || \"\"\n\n // By padding the text width, we ensure the input wraps to the next line\n // before we get to the point where we start to overflow\n const textWidth = measureRef.current.getBoundingClientRect().width + INPUT_CURSOR_TOLERANCE_PX\n\n // Calculate the remaining space based on the last tag's right edge (or container's left if no tags)\n const remainingSpace = containerRect.right - leftBound - CONTAINER_PADDING_PX\n\n if (textWidth <= remainingSpace) {\n setInputWidth(remainingSpace)\n } else {\n // We are going to flow to a new line, so recalculate remaining space based on the container size\n const width = containerRect.right - containerRect.left - CONTAINER_PADDING_PX\n setInputWidth(width)\n }\n }\n }, [currentInput, placeholderText, tags]) // Include tags so we reflow the container when we delete a tag\n\n // ============================================\n // Tag lifecycle functions\n // ============================================\n\n const addTag = (tagValue: string) => {\n const trimmed = tagValue.trim()\n if (!trimmed) {\n return\n }\n if (tags.has(trimmed)) {\n setDuplicateTags((prevTags) => new Set(prevTags).add(trimmed))\n setTimeout(\n () =>\n setDuplicateTags((prevTags) => {\n const newTags = new Set(prevTags)\n newTags.delete(trimmed)\n return newTags\n }),\n SHAKE_ANIMATION_DURATION_MS,\n )\n return\n }\n const validTag = validatorLatest.current?.(trimmed) ?? true\n const newSet = new Map(tags)\n newSet.set(trimmed, { value: trimmed, valid: validTag })\n const newTags = Array.from(newSet.values())\n onChangeLatest.current?.(newTags)\n\n if (!isControlled) {\n setInternalTags(newTags)\n }\n }\n\n const removeTag = (tag: string) => {\n const newSet = new Map(tags)\n newSet.delete(tag)\n const newTags = Array.from(newSet.values())\n onChangeLatest.current?.(newTags)\n if (!isControlled) {\n setInternalTags(newTags)\n }\n if (selectedTag === tag) {\n setSelectedTag(null)\n }\n }\n\n const selectPreviousTag = () => {\n if (tags.size === 0) {\n return\n }\n const tagList = Array.from(tags.keys())\n if (selectedTag === null) {\n setSelectedTag(tagList[tagList.length - 1])\n } else {\n const prevIndex = tagList.indexOf(selectedTag)\n const index = Math.max(0, prevIndex - 1)\n setSelectedTag(tagList[index])\n }\n }\n\n const selectNextTag = () => {\n if (selectedTag === null) {\n return\n }\n const tagList = Array.from(tags.keys())\n const prevIndex = tagList.indexOf(selectedTag)\n const index = prevIndex + 1\n if (index < tagList.length) {\n setSelectedTag(tagList[index])\n } else {\n setSelectedTag(null)\n }\n }\n\n // ============================================\n // Helper functions\n // ============================================\n\n const isEmptyStartingSelection = () => {\n const input = inputRef.current\n if (!input) {\n return true\n }\n return input.selectionStart === 0 && input.selectionEnd === 0\n }\n\n const handleContainerBlur = () => {\n setFocused(false)\n setSelectedTag(null)\n if (currentInput) {\n addTag(currentInput)\n setCurrentInput(\"\")\n }\n }\n\n // ============================================\n // Event handlers\n // ============================================\n\n const handleContainerKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {\n if (e.key === \"ArrowLeft\" || e.key === \"ArrowUp\") {\n if (isEmptyStartingSelection()) {\n e.preventDefault()\n selectPreviousTag()\n }\n } else if (e.key === \"ArrowRight\" || e.key === \"ArrowDown\") {\n if (selectedTag !== null) {\n e.preventDefault()\n selectNextTag()\n }\n } else if (e.key === \"Backspace\") {\n if (selectedTag !== null) {\n removeTag(selectedTag)\n } else if (isEmptyStartingSelection()) {\n selectPreviousTag()\n }\n }\n }\n\n const handleInputKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {\n if (e.key === \"Enter\" || delimiters.includes(e.key)) {\n e.preventDefault()\n if (currentInput) {\n addTag(currentInput)\n setCurrentInput(\"\")\n }\n } else if (e.key === \"Tab\") {\n if (currentInput) {\n e.preventDefault()\n addTag(currentInput)\n setCurrentInput(\"\")\n }\n }\n }\n\n const handlePaste = (e: React.ClipboardEvent<HTMLInputElement>) => {\n const text = e.clipboardData.getData(\"Text\")\n let parts = [text]\n\n // Split by all delimiters\n for (const delimiter of delimiters) {\n const newParts = []\n for (const segment of parts) {\n newParts.push(...segment.split(delimiter))\n }\n parts = newParts\n }\n\n // Remove empty parts\n parts = parts.filter(Boolean)\n\n if (parts.length > 1) {\n e.preventDefault()\n parts.forEach((part) => addTag(part))\n }\n }\n\n const handleContainerMouseDown = (e: React.MouseEvent) => {\n // All clicks in the container focus the container\n setFocused(true)\n\n // If the click is on a tag pill, we are done. The click handler\n // for the specific tag will handle focusing it\n if (e.target && e.target instanceof Element && e.target.closest(\"[data-tag]\")) {\n return\n }\n\n // Since we know we didn't click a tag, clear any selected tag\n setSelectedTag(null)\n\n // If this click is outside of the input, prevent it from \"stealing\" focus from the input\n if (\n e.target &&\n e.target instanceof Element &&\n inputRef.current &&\n !inputRef.current.contains(e.target)\n ) {\n e.preventDefault()\n\n const { left, right, top, bottom } = inputRef.current.getBoundingClientRect()\n const { clientX, clientY } = e\n\n // If this is the first click, clear the selection. Otherwise, select the input contents\n if (e.detail === 1) {\n if (clientY < top || clientX < left) {\n // \"Before\" the input: top/left\n inputRef.current.setSelectionRange(0, 0)\n } else if (clientY > bottom || clientX > right) {\n // \"After\" the input: bottom/right\n const length = inputRef.current.value.length\n inputRef.current.setSelectionRange(length, length)\n }\n } else {\n inputRef.current.select()\n }\n }\n }\n\n const handleFocus = (e: React.FocusEvent) => {\n // If the focus is on a tag pill, do not trigger input focus logic\n // The click handler for the specific tag will handle it instead\n if (e.target && e.target instanceof Element && e.target.closest(\"[data-tag]\")) {\n return\n }\n setFocused(true)\n }\n\n const handleBlur = (e: React.FocusEvent) => {\n // If there is no related target, don't remove focus.\n // This occurs on a click inside the container but not on any element.\n // The handleClickOutside handler handles other cases\n if (!e.relatedTarget || !(e.relatedTarget instanceof Node)) {\n return\n }\n // Don't clear focus if focus is only moved elsewhere within the container\n if (containerRef.current && containerRef.current.contains(e.relatedTarget)) {\n // If we just tabbed into the input, clear the selected tag\n if (inputRef.current && inputRef.current.contains(e.relatedTarget)) {\n setSelectedTag(null)\n }\n return\n }\n handleContainerBlur()\n }\n\n // @ts-expect-error - Fix once usehooks-ts is updated https://github.com/juliencrn/usehooks-ts/pull/675\n useOnClickOutside(containerRef, handleContainerBlur)\n\n return (\n <>\n <div\n className={s.Container}\n ref={containerRef}\n onKeyDown={handleContainerKeyDown}\n onMouseDown={handleContainerMouseDown}\n onFocus={handleFocus}\n onBlur={handleBlur}\n data-size={size}\n data-focused={focused ? \"\" : undefined}\n data-empty={tags.size === 0 ? \"\" : undefined}\n tabIndex={-1}\n style={toCssVariables({ \"min-rows\": String(rows) })}\n data-disabled={disabled ? \"\" : undefined}\n >\n <div className={s.TagInput}>\n {Array.from(tags.values()).map((tag) => (\n <div\n key={tag.value}\n className={s.Tag}\n tabIndex={-1}\n onClick={() => setSelectedTag(tag.value)}\n data-tag={tag.value}\n data-invalid={!tag.valid ? \"\" : undefined}\n data-duplicate={duplicateTags.has(tag.value) ? \"\" : undefined}\n >\n <span className=\"overflow-hidden text-ellipsis\" title={tag.value}>\n <span className={s.TagValue}>{tag.value}</span>\n </span>\n <div\n className={s.TagRemove}\n onClick={() => removeTag(tag.value)}\n role=\"button\"\n aria-label=\"Remove item\"\n >\n <X />\n </div>\n </div>\n ))}\n {showInput && (\n <div className={s.InputContainer}>\n {/* Hidden element to measure input width */}\n <span ref={measureRef} className={s.InputMeasure} />\n <div className={s.InputWrapper}>\n <input\n id={id}\n className={s.Input}\n ref={inputRef}\n value={currentInput}\n onChange={(e) => {\n setCurrentInput(e.target.value)\n }}\n onPaste={handlePaste}\n onKeyDown={handleInputKeyDown}\n placeholder={placeholderText}\n style={{ width: inputWidth }}\n disabled={disabled}\n />\n </div>\n </div>\n )}\n </div>\n </div>\n {maxTags && (\n <div className={s.Limit}>\n {tags.size}\n <span className=\"mx-px\">/</span>\n {maxTags}\n </div>\n )}\n </>\n )\n}\n"]}
|
|
@@ -77,75 +77,76 @@ box-shadow: 0 0 0 1px var(--gray-500) inset;
|
|
|
77
77
|
gap: var(--tag-input-tag-spacing);
|
|
78
78
|
}.Tag {
|
|
79
79
|
overflow: hidden;
|
|
80
|
-
display: flex;
|
|
80
|
+
display: inline-flex;
|
|
81
81
|
align-items: center;
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
82
|
+
gap: calc(var(--spacing) * 1);
|
|
83
|
+
height: var(--control-size-xs);
|
|
84
|
+
padding: 0 var(--control-gutter-xs);
|
|
85
|
+
border-radius: var(--control-radius-sm);
|
|
86
|
+
background-color: var(--color-background-secondary-soft-alpha);
|
|
87
|
+
color: var(--color-text-secondary-soft);
|
|
88
|
+
font-size: var(--control-font-size-md);
|
|
89
|
+
font-weight: var(--button-font-weight);
|
|
85
90
|
cursor: pointer;
|
|
86
|
-
|
|
91
|
+
white-space: nowrap;
|
|
87
92
|
outline: none;
|
|
88
93
|
transition: background-color 0.15s ease;
|
|
89
|
-
}.Tag, :where([data-theme="light"]) .Tag {
|
|
90
|
-
background-color: var(--color-background-secondary-soft);
|
|
91
|
-
color: var(--color-text-secondary-soft);
|
|
92
|
-
}:where([data-theme="dark"]) .Tag {
|
|
93
|
-
background-color: var(--color-background-secondary-solid);
|
|
94
|
-
color: var(--color-text-secondary-solid);
|
|
95
94
|
}
|
|
96
95
|
|
|
97
|
-
@media (hover: hover) and (pointer: fine) {.Tag:hover
|
|
98
|
-
background-color: var(--color-background-secondary-soft-hover);
|
|
99
|
-
}:where([data-theme="dark"]) .Tag:hover {
|
|
100
|
-
background-color: var(--color-background-secondary-solid-hover);
|
|
96
|
+
@media (hover: hover) and (pointer: fine) {.Tag:hover {
|
|
97
|
+
background-color: var(--color-background-secondary-soft-alpha-hover);
|
|
101
98
|
}
|
|
102
99
|
}
|
|
103
100
|
|
|
104
|
-
.Tag:focus
|
|
105
|
-
background-color: var(--color-background-secondary-soft-hover);
|
|
106
|
-
}
|
|
101
|
+
.Tag:focus {
|
|
102
|
+
background-color: var(--color-background-secondary-soft-alpha-hover);
|
|
103
|
+
}
|
|
107
104
|
|
|
108
|
-
|
|
109
|
-
background-color: var(--color-background-secondary-
|
|
110
|
-
}
|
|
105
|
+
.Tag:active {
|
|
106
|
+
background-color: var(--color-background-secondary-soft-alpha-active);
|
|
107
|
+
}
|
|
111
108
|
|
|
112
109
|
.Container[data-disabled] .Tag {
|
|
113
110
|
color: var(--color-text-tertiary);
|
|
114
111
|
}
|
|
115
112
|
|
|
116
113
|
.Tag[data-invalid] {
|
|
117
|
-
background-color: var(--color-background-danger-soft);
|
|
114
|
+
background-color: var(--color-background-danger-soft-alpha);
|
|
118
115
|
color: var(--color-text-danger-soft);
|
|
119
116
|
}
|
|
120
117
|
|
|
121
118
|
@media (hover: hover) and (pointer: fine) {.Tag[data-invalid]:hover {
|
|
122
|
-
background-color: var(--color-background-danger-soft-hover);
|
|
119
|
+
background-color: var(--color-background-danger-soft-alpha-hover);
|
|
123
120
|
}
|
|
124
121
|
}
|
|
125
122
|
|
|
126
123
|
.Tag[data-invalid]:focus {
|
|
127
|
-
background-color: var(--color-background-danger-soft-hover);
|
|
124
|
+
background-color: var(--color-background-danger-soft-alpha-hover);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
.Tag[data-invalid]:active {
|
|
128
|
+
background-color: var(--color-background-danger-soft-alpha-active);
|
|
128
129
|
}
|
|
129
130
|
|
|
130
131
|
.Tag[data-duplicate] {
|
|
131
132
|
animation: shake 0.5s ease;
|
|
132
133
|
}
|
|
133
134
|
|
|
134
|
-
.Tag
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
135
|
+
.Tag svg {
|
|
136
|
+
font-size: var(--control-icon-size-sm);
|
|
137
|
+
}.TagRemove {
|
|
138
|
+
display: flex;
|
|
139
|
+
align-items: center;
|
|
140
|
+
margin-right: -1px;
|
|
141
|
+
color: inherit;
|
|
142
|
+
opacity: 0.5;
|
|
143
|
+
transition: opacity 0.15s ease;
|
|
144
|
+
}
|
|
143
145
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
+
@media (hover: hover) and (pointer: fine) {.TagRemove:hover {
|
|
147
|
+
opacity: 1;
|
|
146
148
|
}
|
|
147
149
|
}.TagValue {
|
|
148
|
-
font-size: var(--tag-input-font-size);
|
|
149
150
|
white-space: nowrap;
|
|
150
151
|
}.InputContainer {
|
|
151
152
|
display: flex;
|