@mikezimm/fps-library-v2
Version:
Library of reusable typescript/javascript functions, interfaces and constants
122 lines • 6.01 kB
JavaScript
/**
* 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