UNPKG

@primer/react

Version:

An implementation of GitHub's Primer Design System using React

690 lines (686 loc) • 21 kB
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 };