UNPKG

@mikezimm/fps-library-v2

Version:

Library of reusable typescript/javascript functions, interfaces and constants

122 lines 6.01 kB
/** * Credit where credit is due... * I created this component with the VERY helpful Bing Chat and some iterations. * Great Help and shout out to Bing Chat! */ import { Icon } from '@fluentui/react'; import * as React from 'react'; import { useState, useEffect } from 'react'; import { isXML } from './isXML'; import { countLineFeeds } from './countLineFeeds'; import { formatStringLike } from './formatStringLike'; import { CurrentOrigin } from '@mikezimm/fps-core-v7/lib/components/molecules/source-props/WindowLocationConstants'; function determineBGColor(text, format) { let bgColor = 'transparent'; if (typeof text !== 'string') return 'red'; if (text === null || text === undefined) bgColor = 'transparent'; if (format === 'text') { if (!text.trim()) bgColor = 'yellow'; } else if (format === 'number') { const regex = /^[0-9]+$/; if (regex.test(text) !== true) bgColor = 'yellow'; } else if (format === 'json') { if (isValidJSON(text) === false) { bgColor = 'yellow'; } } else if (format === 'html' || format === 'xml') { if (isXML(text) === false) { bgColor = 'yellow'; } } else if (format === 'spo' || format === 'spo-page') { const textLC = text.toLocaleLowerCase(); if (textLC.indexOf('/sites/') !== 0 && textLC.indexOf(CurrentOrigin) !== 0) bgColor = 'yellow'; if (format === 'spo-page' && bgColor === 'transparent' && textLC.indexOf('.aspx') < 0) bgColor = 'yellow'; } return bgColor; } function getCodeIconName(format) { let iconName = ''; if (format === 'json') { iconName = 'Code'; } else if (format === 'xml') { iconName = 'Embed'; } else if (format === 'html') { iconName = 'FileCode'; } return iconName; } // Eventually replace this with isValidJSON2? function isValidJSON(str) { try { JSON.parse(str); return true; } catch (e) { return false; } } const FPSTextInput = (props) => { const { title, subTitle, description, placeholder, onTextChange, defaultValue, validationType, multiLine, inputStyles = {}, errorElement, maxLines = 25, disabled = false } = props; const [text, setText] = useState(typeof defaultValue === 'string' ? formatStringLike(defaultValue, validationType) : ''); // Use the defaultValue prop as the initial state // 🔹 Use useEffect to update state when defaultValue changes useEffect(() => { setText(typeof defaultValue === 'string' ? formatStringLike(defaultValue, validationType) : ''); }, [defaultValue, validationType]); // Dependencies ensure updates when defaultValue or format type changes useEffect(() => { // https://ultimatecourses.com/blog/using-async-await-inside-react-use-effect-hook setText(defaultValue); }, [defaultValue]); const handleTextChange = (event) => { const newValue = event.target.value; setText(newValue); if (onTextChange) { onTextChange(newValue); } }; // const background = validationType === 'json' && isValidJSON( text ) === false ? 'yellow' : 'transparent' ; const background = determineBGColor(text, validationType); const totalLines = !text ? 7 : countLineFeeds(text) + 7; // https://github.com/fps-solutions/Entra-Spectives/issues/92 - standardized height to 2.5em - matches FPSDropdown and fluentui Text const height = multiLine === true ? `${totalLines > maxLines ? maxLines : totalLines}em` : '2.5em'; const titleStyles = { fontSize: 'larger', fontWeight: '600', ...props.titleStyles }; // 2024-06-21: https://github.com/fps-solutions/Network-Builder/issues/43 const subTitleStyles = { fontSize: 'small', ...props.subTitleStyles }; // 2024-06-21: Adjusted this up to 'small' because 'smaller' seemed pretty small. const descStyles = { fontSize: 'small', }; const iconName = getCodeIconName(validationType); const ReFormatIcon = !iconName ? undefined : React.createElement("span", { style: { fontSize: 'larger', fontWeight: 600, padding: '5px', marginLeft: '3em', cursor: 'pointer' }, onClick: () => setText(formatStringLike(text, validationType)), title: `Reformat string as ${validationType}` }, React.createElement(Icon, { iconName: iconName })); // https://github.com/fps-solutions/Network-Builder/issues/52 // 2024-06-21: Need to add this to the textarea box as well. const CommonInputStyles = { width: '100%', boxSizing: 'border-box', padding: '5px 10px', borderWidth: '1px', transition: 'all 0.4s ease' }; return (React.createElement("div", { style: { width: '100%', boxSizing: 'border-box', ...props.reactCSS }, className: props.className }, title && React.createElement("div", { style: titleStyles }, title, " ", ReFormatIcon, " ", props.actionElement), subTitle && React.createElement("div", { style: subTitleStyles }, subTitle), errorElement, multiLine === true ? // 2024-06-21: Also added disabled={ disabled } after I noticed it was missing. React.createElement("textarea", { disabled: disabled, style: { ...CommonInputStyles, height: height, background: background, ...inputStyles }, value: text, onChange: handleTextChange, placeholder: placeholder }) : React.createElement("input", { disabled: disabled, type: 'text', style: { ...CommonInputStyles, height: height, background: background, ...inputStyles }, value: text, onChange: handleTextChange, placeholder: placeholder }), description && React.createElement("div", { style: descStyles }, description))); }; export default FPSTextInput; //# sourceMappingURL=FPSTextInput.js.map