UNPKG

@sap-ux/ui-components

Version:

SAP UI Components Library

163 lines 6.56 kB
import React, { useCallback } from 'react'; import { UITextInput } from '../UIInput/index.js'; import { UiIcons } from '../Icons.js'; import { UITranslationButton } from './UITranslationButton.js'; import { TranslationKeyGenerator, SuggestValueType } from './UITranslationButton.types.js'; import { extractI18nKey, generateI18nKey, applyI18nPattern, getTranslationByKey, getTranslationByText } from './UITranslationUtils.js'; import { defaultTranslationInputStrings } from './defaults.js'; import { UIFormattedText, formatText } from './UIFormattedText.js'; /** * Method returns suggestion object with message and tooltip based on passed translation button props. * * @param props Properties of translation input component. * @returns Translation suggestion object. */ const getTranslationSuggestion = (props) => { const { value = '', allowedPatterns, entries, strings = defaultTranslationInputStrings, namingConvention = TranslationKeyGenerator.CamelCase, defaultPattern, i18nPrefix, allowedI18nPrefixes } = props; const i18nKey = extractI18nKey(value, allowedPatterns, allowedI18nPrefixes || [i18nPrefix]); let message = ''; let tooltip = ''; let suggest; if (i18nKey) { // There is already i18n binding as value const entry = getTranslationByKey(entries, i18nKey); if (entry) { tooltip = strings.i18nEntryExistsTooltip; suggest = { entry, type: SuggestValueType.Existing, icon: UiIcons.WorldArrow }; } else { message = strings.i18nKeyMissingDescription; tooltip = strings.i18nKeyMissingTooltip; suggest = { entry: { key: { value: i18nKey }, value: { value: i18nKey } }, type: SuggestValueType.New, icon: UiIcons.WorldWarning }; } } else { // Use generation format passed from outside or use default as 'Standard'; const existingEntry = getTranslationByText(entries, value); if (existingEntry) { message = strings.i18nReplaceWithExistingDescription; tooltip = strings.i18nReplaceWithExistingTooltip; suggest = { entry: existingEntry, type: SuggestValueType.Update }; } else { message = strings.i18nValueMissingDescription; tooltip = strings.i18nValueMissingTooltip; const key = generateI18nKey(value, namingConvention, entries); suggest = { entry: { key: { value: key }, value: { value } }, type: SuggestValueType.New }; } } // I18n string to apply for input value suggest.i18n = applyI18nPattern(suggest.entry.key.value, defaultPattern, i18nPrefix); // Format message to show in callout const messageValues = { key: suggest.entry.key.value, value: suggest.entry.value.value, i18n: suggest.i18n }; tooltip = formatText(tooltip, messageValues); return { message: (React.createElement(UIFormattedText, { values: messageValues, className: "ui-translatable__message__text" }, message)), tooltip, suggest }; }; /** * Generates the CSS class names for the translation input component. * * @param props - Component props containing styling options. * @returns A string containing the computed class names. */ const getClassNames = (props) => { const { className, invertedCalloutTheme } = props; let classNames = ' ui-translatable__input'; // Custom external classes if (className) { classNames += ` ${className}`; } if (invertedCalloutTheme) { classNames += ` ui-translatable--inverted`; } return classNames; }; /** * Component to render translation input with button to provide helper callout with i18n generation option. * * @param props Component properties. * @returns Component to render translation input. */ export const UITranslationInput = (props) => { const { id, onChange, value, allowedPatterns, defaultPattern, entries, busy, i18nPrefix, allowedI18nPrefixes, namingConvention, onCreateNewEntry, onShowExistingEntry, disabled, strings, invertedCalloutTheme } = props; const suggestion = getTranslationSuggestion(props); const classNames = getClassNames(props); const onUpdateValue = useCallback((newValue) => { onChange?.({}, newValue); }, [onChange]); // Generate DOM id for i18n button let buttonId = `${id}-i18n`; let title = props.title; if (suggestion.suggest?.type === SuggestValueType.Existing && strings?.i18nEntryExistsInputTooltip) { // Change DOM id with additional suffix buttonId += '-navigate'; if (!title) { title = formatText(strings.i18nEntryExistsInputTooltip, { value: value || '', translation: suggestion.suggest.entry.value.value }); } } const onRenderSuffix = useCallback(() => { return (React.createElement(UITranslationButton, { id: buttonId, value: value, busy: busy, onCreateNewEntry: onCreateNewEntry, onShowExistingEntry: onShowExistingEntry, onUpdateValue: onUpdateValue, disabled: disabled, strings: strings, suggestion: suggestion, invertedCalloutTheme: invertedCalloutTheme })); }, [ value, allowedPatterns, defaultPattern, entries, busy, disabled, i18nPrefix, allowedI18nPrefixes, namingConvention, onCreateNewEntry, onShowExistingEntry, onUpdateValue ]); const onRenderInput = useCallback((props, defaultRender) => { if (defaultRender) { return (React.createElement("div", { className: "ui-translatable__field", title: title }, defaultRender({ ...props, title: undefined }))); } return null; }, [title]); return (React.createElement(UITextInput, { ...props, onRenderSuffix: value?.trim() ? onRenderSuffix : undefined, className: classNames, onRenderInput: onRenderInput })); }; UITranslationInput.defaultProps = { strings: defaultTranslationInputStrings }; //# sourceMappingURL=UITranslationInput.js.map