@primer/react
Version:
An implementation of GitHub's Primer Design System using React
690 lines (686 loc) • 21 kB
JavaScript
import { c } from 'react-compiler-runtime';
import { FocusKeys } from '@primer/behaviors';
import { isFocusable } from '@primer/behaviors/utils';
import React, { useRef, useState } from 'react';
import { isValidElementType } from 'react-is';
import { useMergedRefs } from '../hooks/useMergedRefs.js';
import { useFocusZone } from '../hooks/useFocusZone.js';
import { useId } from '../hooks/useId.js';
import Token from '../Token/Token.js';
import VisuallyHidden from '../_VisuallyHidden.js';
import { TextInputWrapper } from '../internal/components/TextInputWrapper.js';
import UnstyledTextInput from '../internal/components/UnstyledTextInput.js';
import TextInputInnerVisualSlot from '../internal/components/TextInputInnerVisualSlot.js';
import styles from './TextInputWithTokens.module.css.js';
import { clsx } from 'clsx';
import { jsx, jsxs } from 'react/jsx-runtime';
import Text from '../Text/Text.js';
const overflowCountClassMap = {
small: styles.OverflowCountSmall,
medium: styles.OverflowCountMedium,
large: styles.OverflowCountLarge,
xlarge: styles.OverflowCountXLarge
};
// using forwardRef is important so that other components (ex. Autocomplete) can use the ref
function TextInputWithTokensInnerComponent(t0, forwardedRef) {
const $ = c(152);
let IconComponent;
let LeadingVisual;
let TrailingVisual;
let block;
let className;
let contrast;
let disabled;
let loading;
let maxHeight;
let maxWidthProp;
let minWidthProp;
let onTokenRemove;
let rest;
let style;
let t1;
let t2;
let t3;
let t4;
let t5;
let tokens;
let validationStatus;
let variantProp;
let visibleTokenCount;
let widthProp;
if ($[0] !== t0) {
({
icon: IconComponent,
leadingVisual: LeadingVisual,
trailingVisual: TrailingVisual,
loading,
loaderPosition: t1,
contrast,
className,
block,
disabled,
tokens,
onTokenRemove,
tokenComponent: t2,
preventTokenWrapping: t3,
size: t4,
hideTokenRemoveButtons: t5,
maxHeight,
width: widthProp,
minWidth: minWidthProp,
maxWidth: maxWidthProp,
validationStatus,
variant: variantProp,
visibleTokenCount,
style,
...rest
} = t0);
$[0] = t0;
$[1] = IconComponent;
$[2] = LeadingVisual;
$[3] = TrailingVisual;
$[4] = block;
$[5] = className;
$[6] = contrast;
$[7] = disabled;
$[8] = loading;
$[9] = maxHeight;
$[10] = maxWidthProp;
$[11] = minWidthProp;
$[12] = onTokenRemove;
$[13] = rest;
$[14] = style;
$[15] = t1;
$[16] = t2;
$[17] = t3;
$[18] = t4;
$[19] = t5;
$[20] = tokens;
$[21] = validationStatus;
$[22] = variantProp;
$[23] = visibleTokenCount;
$[24] = widthProp;
} else {
IconComponent = $[1];
LeadingVisual = $[2];
TrailingVisual = $[3];
block = $[4];
className = $[5];
contrast = $[6];
disabled = $[7];
loading = $[8];
maxHeight = $[9];
maxWidthProp = $[10];
minWidthProp = $[11];
onTokenRemove = $[12];
rest = $[13];
style = $[14];
t1 = $[15];
t2 = $[16];
t3 = $[17];
t4 = $[18];
t5 = $[19];
tokens = $[20];
validationStatus = $[21];
variantProp = $[22];
visibleTokenCount = $[23];
widthProp = $[24];
}
const loaderPosition = t1 === undefined ? "auto" : t1;
const TokenComponent = t2 === undefined ? Token : t2;
const preventTokenWrapping = t3 === undefined ? false : t3;
const size = t4 === undefined ? "xlarge" : t4;
const hideTokenRemoveButtons = t5 === undefined ? false : t5;
let ariaDescribedByProp;
let inputPropsRest;
let onBlur;
let onFocus;
let onKeyDown;
let role;
if ($[25] !== rest) {
({
onBlur,
onFocus,
onKeyDown,
"aria-describedby": ariaDescribedByProp,
role,
...inputPropsRest
} = rest);
$[25] = rest;
$[26] = ariaDescribedByProp;
$[27] = inputPropsRest;
$[28] = onBlur;
$[29] = onFocus;
$[30] = onKeyDown;
$[31] = role;
} else {
ariaDescribedByProp = $[26];
inputPropsRest = $[27];
onBlur = $[28];
onFocus = $[29];
onKeyDown = $[30];
role = $[31];
}
const ref = useRef(null);
const mergedRef = useMergedRefs(forwardedRef, ref);
const selectedValuesDescriptionId = useId();
const [selectedTokenIndex, setSelectedTokenIndex] = useState();
const [tokensAreTruncated, setTokensAreTruncated] = useState(Boolean(visibleTokenCount));
let t6;
if ($[32] !== tokens) {
const selectedTokenTexts = tokens.map(_temp).filter(_temp2);
t6 = selectedTokenTexts.length ? `Selected: ${selectedTokenTexts.join(", ")}` : "";
$[32] = tokens;
$[33] = t6;
} else {
t6 = $[33];
}
const selectedValuesDescription = t6;
const shouldExposeSelectedValuesDescription = role === "combobox" && Boolean(selectedValuesDescription);
const t7 = shouldExposeSelectedValuesDescription ? selectedValuesDescriptionId : undefined;
let t8;
if ($[34] !== ariaDescribedByProp || $[35] !== t7) {
t8 = [ariaDescribedByProp, t7].filter(Boolean);
$[34] = ariaDescribedByProp;
$[35] = t7;
$[36] = t8;
} else {
t8 = $[36];
}
const ariaDescribedBy = t8.join(" ");
let t9;
if ($[37] !== selectedTokenIndex) {
t9 = [selectedTokenIndex];
$[37] = selectedTokenIndex;
$[38] = t9;
} else {
t9 = $[38];
}
const {
containerRef: t10
} = useFocusZone({
focusOutBehavior: "wrap",
bindKeys: FocusKeys.ArrowHorizontal | FocusKeys.HomeAndEnd,
focusableElementFilter: _temp3,
getNextFocusable: direction => {
var _containerRef$current;
if (!selectedTokenIndex && selectedTokenIndex !== 0) {
return;
}
let nextIndex = selectedTokenIndex + 1;
if (direction === "next") {
nextIndex = nextIndex + 1;
}
if (direction === "previous") {
nextIndex = nextIndex - 1;
}
if (nextIndex > tokens.length || nextIndex < 1) {
return ref.current || undefined;
}
return (_containerRef$current = containerRef.current) === null || _containerRef$current === void 0 ? void 0 : _containerRef$current.children[nextIndex];
}
}, t9);
const containerRef = t10;
let t11;
if ($[39] !== containerRef || $[40] !== onTokenRemove || $[41] !== selectedTokenIndex) {
t11 = tokenId => {
onTokenRemove(tokenId);
setTimeout(() => {
var _containerRef$current2, _containerRef$current3;
const nextElementToFocus = (_containerRef$current2 = containerRef.current) === null || _containerRef$current2 === void 0 ? void 0 : _containerRef$current2.children[selectedTokenIndex || 0];
const firstFocusable = nextElementToFocus && isFocusable(nextElementToFocus) ? nextElementToFocus : Array.from(((_containerRef$current3 = containerRef.current) === null || _containerRef$current3 === void 0 ? void 0 : _containerRef$current3.children) || []).find(_temp4);
if (firstFocusable) {
firstFocusable.focus();
} else {
var _ref$current;
(_ref$current = ref.current) === null || _ref$current === void 0 ? void 0 : _ref$current.focus();
}
}, 0);
};
$[39] = containerRef;
$[40] = onTokenRemove;
$[41] = selectedTokenIndex;
$[42] = t11;
} else {
t11 = $[42];
}
const handleTokenRemove = t11;
let t12;
if ($[43] !== disabled) {
t12 = tokenIndex => () => {
if (!disabled) {
setSelectedTokenIndex(tokenIndex);
}
};
$[43] = disabled;
$[44] = t12;
} else {
t12 = $[44];
}
const handleTokenFocus = t12;
let t13;
if ($[45] !== containerRef || $[46] !== visibleTokenCount) {
t13 = () => {
setSelectedTokenIndex(undefined);
setTimeout(() => {
var _containerRef$current4;
if (!((_containerRef$current4 = containerRef.current) !== null && _containerRef$current4 !== void 0 && _containerRef$current4.contains(document.activeElement)) && visibleTokenCount) {
setTokensAreTruncated(true);
}
}, 0);
};
$[45] = containerRef;
$[46] = visibleTokenCount;
$[47] = t13;
} else {
t13 = $[47];
}
const handleTokenBlur = t13;
let t14;
if ($[48] === Symbol.for("react.memo_cache_sentinel")) {
t14 = event => {
if (event.key === "Escape") {
var _ref$current2;
(_ref$current2 = ref.current) === null || _ref$current2 === void 0 ? void 0 : _ref$current2.focus();
}
};
$[48] = t14;
} else {
t14 = $[48];
}
const handleTokenKeyUp = t14;
let t15;
if ($[49] !== onFocus || $[50] !== visibleTokenCount) {
t15 = event_0 => {
onFocus && onFocus(event_0);
setSelectedTokenIndex(undefined);
visibleTokenCount && setTokensAreTruncated(false);
};
$[49] = onFocus;
$[50] = visibleTokenCount;
$[51] = t15;
} else {
t15 = $[51];
}
const handleInputFocus = t15;
let t16;
if ($[52] !== containerRef || $[53] !== onBlur || $[54] !== visibleTokenCount) {
t16 = event_1 => {
onBlur && onBlur(event_1);
setTimeout(() => {
var _containerRef$current5;
if (!((_containerRef$current5 = containerRef.current) !== null && _containerRef$current5 !== void 0 && _containerRef$current5.contains(document.activeElement)) && visibleTokenCount) {
setTokensAreTruncated(true);
}
}, 0);
};
$[52] = containerRef;
$[53] = onBlur;
$[54] = visibleTokenCount;
$[55] = t16;
} else {
t16 = $[55];
}
const handleInputBlur = t16;
let t17;
if ($[56] !== handleTokenRemove || $[57] !== onKeyDown || $[58] !== tokens) {
t17 = e => {
var _ref$current3;
if (onKeyDown) {
onKeyDown(e);
}
if ((_ref$current3 = ref.current) !== null && _ref$current3 !== void 0 && _ref$current3.value) {
return;
}
const lastToken = tokens[tokens.length - 1];
if (e.key === "Backspace" && lastToken) {
handleTokenRemove(lastToken.id);
if (ref.current) {
ref.current.value = `${lastToken.text} `;
}
setTimeout(() => {
var _ref$current4;
(_ref$current4 = ref.current) === null || _ref$current4 === void 0 ? void 0 : _ref$current4.select();
}, 0);
}
};
$[56] = handleTokenRemove;
$[57] = onKeyDown;
$[58] = tokens;
$[59] = t17;
} else {
t17 = $[59];
}
const handleInputKeyDown = t17;
let t18;
if ($[60] === Symbol.for("react.memo_cache_sentinel")) {
t18 = () => {
var _ref$current5;
(_ref$current5 = ref.current) === null || _ref$current5 === void 0 ? void 0 : _ref$current5.focus();
};
$[60] = t18;
} else {
t18 = $[60];
}
const focusInput = t18;
const preventTokenClickPropagation = _temp5;
let t19;
if ($[61] !== tokens || $[62] !== tokensAreTruncated || $[63] !== visibleTokenCount) {
t19 = tokensAreTruncated ? tokens.slice(0, visibleTokenCount) : tokens;
$[61] = tokens;
$[62] = tokensAreTruncated;
$[63] = visibleTokenCount;
$[64] = t19;
} else {
t19 = $[64];
}
const visibleTokens = t19;
let t20;
if ($[65] === Symbol.for("react.memo_cache_sentinel")) {
t20 = {
small: "small",
medium: "small",
large: "medium",
xlarge: "medium"
};
$[65] = t20;
} else {
t20 = $[65];
}
const inputSizeMap = t20;
const showLeadingLoadingIndicator = loading && (loaderPosition === "leading" || Boolean(LeadingVisual && loaderPosition !== "trailing"));
const showTrailingLoadingIndicator = loading && (loaderPosition === "trailing" || loaderPosition === "auto" && !LeadingVisual);
const t21 = Boolean(LeadingVisual || showLeadingLoadingIndicator);
const t22 = Boolean(TrailingVisual || showTrailingLoadingIndicator);
const t23 = inputSizeMap[size];
const t24 = Boolean(preventTokenWrapping || maxHeight) || undefined;
let t25;
if ($[66] !== className) {
t25 = clsx(className, styles.TextInputWrapper);
$[66] = className;
$[67] = t25;
} else {
t25 = $[67];
}
let t26;
if ($[68] !== maxHeight || $[69] !== style) {
t26 = maxHeight ? {
maxHeight,
...style
} : style;
$[68] = maxHeight;
$[69] = style;
$[70] = t26;
} else {
t26 = $[70];
}
let t27;
if ($[71] !== IconComponent || $[72] !== LeadingVisual) {
t27 = IconComponent && !LeadingVisual && /*#__PURE__*/jsx(IconComponent, {
className: "TextInput-icon",
"data-component": "TextInputWithTokens.Icon"
});
$[71] = IconComponent;
$[72] = LeadingVisual;
$[73] = t27;
} else {
t27 = $[73];
}
const t28 = typeof loading === "boolean";
let t29;
if ($[74] !== LeadingVisual) {
t29 = typeof LeadingVisual !== "string" && isValidElementType(LeadingVisual) ? /*#__PURE__*/jsx(LeadingVisual, {}) : LeadingVisual;
$[74] = LeadingVisual;
$[75] = t29;
} else {
t29 = $[75];
}
let t30;
if ($[76] !== showLeadingLoadingIndicator || $[77] !== t28 || $[78] !== t29) {
t30 = /*#__PURE__*/jsx(TextInputInnerVisualSlot, {
hasLoadingIndicator: t28,
visualPosition: "leading",
showLoadingIndicator: showLeadingLoadingIndicator,
componentPrefix: "TextInputWithTokens",
children: t29
});
$[76] = showLeadingLoadingIndicator;
$[77] = t28;
$[78] = t29;
$[79] = t30;
} else {
t30 = $[79];
}
const t31 = containerRef;
const t32 = validationStatus === "error" ? "true" : "false";
const t33 = ariaDescribedBy || undefined;
let t34;
if ($[80] !== disabled || $[81] !== handleInputBlur || $[82] !== handleInputFocus || $[83] !== handleInputKeyDown || $[84] !== inputPropsRest || $[85] !== mergedRef || $[86] !== role || $[87] !== t32 || $[88] !== t33) {
t34 = /*#__PURE__*/jsx(UnstyledTextInput, {
ref: mergedRef,
disabled: disabled,
onFocus: handleInputFocus,
onBlur: handleInputBlur,
onKeyDown: handleInputKeyDown,
type: "text",
className: styles.UnstyledTextInput,
"aria-invalid": t32,
role: role,
"aria-describedby": t33,
"data-component": "TextInputWithTokens.Input",
...inputPropsRest
});
$[80] = disabled;
$[81] = handleInputBlur;
$[82] = handleInputFocus;
$[83] = handleInputKeyDown;
$[84] = inputPropsRest;
$[85] = mergedRef;
$[86] = role;
$[87] = t32;
$[88] = t33;
$[89] = t34;
} else {
t34 = $[89];
}
let t35;
if ($[90] !== selectedValuesDescription || $[91] !== selectedValuesDescriptionId || $[92] !== shouldExposeSelectedValuesDescription) {
t35 = shouldExposeSelectedValuesDescription ? /*#__PURE__*/jsx(VisuallyHidden, {
id: selectedValuesDescriptionId,
children: selectedValuesDescription
}) : null;
$[90] = selectedValuesDescription;
$[91] = selectedValuesDescriptionId;
$[92] = shouldExposeSelectedValuesDescription;
$[93] = t35;
} else {
t35 = $[93];
}
let t36;
if ($[94] !== t34 || $[95] !== t35) {
t36 = /*#__PURE__*/jsxs("div", {
className: styles.InputWrapper,
children: [t34, t35]
});
$[94] = t34;
$[95] = t35;
$[96] = t36;
} else {
t36 = $[96];
}
let t37;
if ($[97] !== TokenComponent || $[98] !== disabled || $[99] !== handleTokenBlur || $[100] !== handleTokenFocus || $[101] !== handleTokenRemove || $[102] !== hideTokenRemoveButtons || $[103] !== selectedTokenIndex || $[104] !== size || $[105] !== visibleTokens) {
let t38;
if ($[107] !== TokenComponent || $[108] !== disabled || $[109] !== handleTokenBlur || $[110] !== handleTokenFocus || $[111] !== handleTokenRemove || $[112] !== hideTokenRemoveButtons || $[113] !== selectedTokenIndex || $[114] !== size) {
t38 = (t39, i) => {
const {
id,
...tokenRest
} = t39;
return /*#__PURE__*/jsx(TokenComponent, {
disabled: disabled,
onFocus: handleTokenFocus(i),
onBlur: handleTokenBlur,
onKeyUp: handleTokenKeyUp,
onClick: preventTokenClickPropagation,
isSelected: selectedTokenIndex === i,
onRemove: () => {
handleTokenRemove(id);
},
hideRemoveButton: disabled || hideTokenRemoveButtons,
size: size,
tabIndex: 0,
"data-component": "TextInputWithTokens.Token",
...tokenRest
}, id);
};
$[107] = TokenComponent;
$[108] = disabled;
$[109] = handleTokenBlur;
$[110] = handleTokenFocus;
$[111] = handleTokenRemove;
$[112] = hideTokenRemoveButtons;
$[113] = selectedTokenIndex;
$[114] = size;
$[115] = t38;
} else {
t38 = $[115];
}
t37 = visibleTokens.map(t38);
$[97] = TokenComponent;
$[98] = disabled;
$[99] = handleTokenBlur;
$[100] = handleTokenFocus;
$[101] = handleTokenRemove;
$[102] = hideTokenRemoveButtons;
$[103] = selectedTokenIndex;
$[104] = size;
$[105] = visibleTokens;
$[106] = t37;
} else {
t37 = $[106];
}
let t38;
if ($[116] !== size || $[117] !== tokens.length || $[118] !== tokensAreTruncated || $[119] !== visibleTokens.length) {
t38 = tokensAreTruncated && tokens.length - visibleTokens.length ? /*#__PURE__*/jsxs(Text, {
className: overflowCountClassMap[size],
"data-component": "TextInputWithTokens.OverflowCount",
children: ["+", tokens.length - visibleTokens.length]
}) : null;
$[116] = size;
$[117] = tokens.length;
$[118] = tokensAreTruncated;
$[119] = visibleTokens.length;
$[120] = t38;
} else {
t38 = $[120];
}
let t39;
if ($[121] !== preventTokenWrapping || $[122] !== t31 || $[123] !== t36 || $[124] !== t37 || $[125] !== t38) {
t39 = /*#__PURE__*/jsxs("div", {
ref: t31,
className: styles.Container,
"data-prevent-token-wrapping": preventTokenWrapping,
children: [t36, t37, t38]
});
$[121] = preventTokenWrapping;
$[122] = t31;
$[123] = t36;
$[124] = t37;
$[125] = t38;
$[126] = t39;
} else {
t39 = $[126];
}
const t40 = typeof loading === "boolean";
let t41;
if ($[127] !== TrailingVisual) {
t41 = typeof TrailingVisual !== "string" && isValidElementType(TrailingVisual) ? /*#__PURE__*/jsx(TrailingVisual, {}) : TrailingVisual;
$[127] = TrailingVisual;
$[128] = t41;
} else {
t41 = $[128];
}
let t42;
if ($[129] !== showTrailingLoadingIndicator || $[130] !== t40 || $[131] !== t41) {
t42 = /*#__PURE__*/jsx(TextInputInnerVisualSlot, {
hasLoadingIndicator: t40,
visualPosition: "trailing",
showLoadingIndicator: showTrailingLoadingIndicator,
componentPrefix: "TextInputWithTokens",
children: t41
});
$[129] = showTrailingLoadingIndicator;
$[130] = t40;
$[131] = t41;
$[132] = t42;
} else {
t42 = $[132];
}
let t43;
if ($[133] !== block || $[134] !== contrast || $[135] !== disabled || $[136] !== maxWidthProp || $[137] !== minWidthProp || $[138] !== t21 || $[139] !== t22 || $[140] !== t23 || $[141] !== t24 || $[142] !== t25 || $[143] !== t26 || $[144] !== t27 || $[145] !== t30 || $[146] !== t39 || $[147] !== t42 || $[148] !== validationStatus || $[149] !== variantProp || $[150] !== widthProp) {
t43 = /*#__PURE__*/jsxs(TextInputWrapper, {
block: block,
contrast: contrast,
disabled: disabled,
hasLeadingVisual: t21,
hasTrailingVisual: t22,
width: widthProp,
minWidth: minWidthProp,
maxWidth: maxWidthProp,
size: t23,
validationStatus: validationStatus,
variant: variantProp,
onClick: focusInput,
"data-token-wrapping": t24,
className: t25,
style: t26,
"data-component": "TextInputWithTokens",
children: [t27, t30, t39, t42]
});
$[133] = block;
$[134] = contrast;
$[135] = disabled;
$[136] = maxWidthProp;
$[137] = minWidthProp;
$[138] = t21;
$[139] = t22;
$[140] = t23;
$[141] = t24;
$[142] = t25;
$[143] = t26;
$[144] = t27;
$[145] = t30;
$[146] = t39;
$[147] = t42;
$[148] = validationStatus;
$[149] = variantProp;
$[150] = widthProp;
$[151] = t43;
} else {
t43 = $[151];
}
return t43;
}
function _temp5(event_2) {
event_2.stopPropagation();
}
function _temp4(el) {
return isFocusable(el);
}
function _temp3(element) {
return !element.getAttributeNames().includes("aria-hidden");
}
function _temp2(tokenText) {
return tokenText !== null;
}
function _temp(token) {
if ("text" in token && typeof token.text === "string" && token.text.trim().length) {
return token.text;
}
return null;
}
const TextInputWithTokens = /*#__PURE__*/React.forwardRef(TextInputWithTokensInnerComponent);
TextInputWithTokens.displayName = 'TextInputWithTokens';
TextInputWithTokens.__SLOT__ = Symbol('TextInputWithTokens');
export { TextInputWithTokens as default };