3 changed files with 44 additions and 172 deletions
@ -0,0 +1,3 @@ |
|||
{ |
|||
"recommendations": ["bradlc.vscode-tailwindcss"] |
|||
} |
|||
@ -1,133 +0,0 @@ |
|||
import React, { InputHTMLAttributes, useState } from "react"; |
|||
|
|||
import { ExclamationCircleIcon } from "@heroicons/react/24/outline"; |
|||
|
|||
export interface IPAddressProps extends InputHTMLAttributes<HTMLInputElement> { |
|||
label: string; |
|||
description?: string; |
|||
prefix?: string; |
|||
suffix?: string; |
|||
action?: { |
|||
icon: JSX.Element; |
|||
action: () => void; |
|||
}; |
|||
error?: string; |
|||
} |
|||
|
|||
export const IPAddress = ({ |
|||
label, |
|||
description, |
|||
action, |
|||
error, |
|||
disabled, |
|||
...rest |
|||
}: IPAddressProps): JSX.Element => { |
|||
const [value, setValue] = useState<[number, number, number, number]>([ |
|||
0, 0, 0, 0 |
|||
]); |
|||
|
|||
// const getRange = (el) => {
|
|||
// var cuRange, tbRange, headRange, range, dupRange, ret = {};
|
|||
// if (el.setSelectionRange) {
|
|||
// // standard
|
|||
// ret.begin = el.selectionStart;
|
|||
// ret.end = el.selectionEnd;
|
|||
// ret.result = el.value.substring(ret.begin, ret.end);
|
|||
// } else if (document.selection) {
|
|||
// // ie
|
|||
// if (el.tagName.toLowerCase() === 'input') {
|
|||
// cuRange = document.selection.createRange();
|
|||
// tbRange = el.createTextRange();
|
|||
// tbRange.collapse(true);
|
|||
// tbRange.select();
|
|||
// headRange = document.selection.createRange();
|
|||
// headRange.setEndPoint('EndToEnd', cuRange);
|
|||
// ret.begin = headRange.text.length - cuRange.text.length;
|
|||
// ret.end = headRange.text.length;
|
|||
// ret.result = cuRange.text;
|
|||
// cuRange.select();
|
|||
// } else if (el.tagName.toLowerCase() === 'textarea') {
|
|||
// range = document.selection.createRange();
|
|||
// dupRange = range.duplicate();
|
|||
// dupRange.moveToElementText(el);
|
|||
// dupRange.setEndPoint('EndToEnd', range);
|
|||
// ret.begin = dupRange.text.length - range.text.length;
|
|||
// ret.end = dupRange.text.length;
|
|||
// ret.result = range.text;
|
|||
// }
|
|||
// }
|
|||
// el.focus();
|
|||
// return ret;
|
|||
// }
|
|||
|
|||
// const isValidIPItemValue = (val) => {
|
|||
// val = parseInt(val);
|
|||
// return !isNaN(val) && val >= 0 && val <= 255;
|
|||
// }
|
|||
|
|||
// const handleKeyDown = (event: React.KeyboardEvent<HTMLInputElement>, index: number) => {
|
|||
// /* 37 = ←, 39 = →, 8 = backspace, 110 or 190 = . */
|
|||
// let domId = index;
|
|||
// if ((event.keyCode === 37 || event.keyCode === 8) && getRange(event.target).end === 0 && index > 0) { domId = index - 1; }
|
|||
// if (event.keyCode === 39 && getRange(event.target).end === event.target.value.length && index < 3) { domId = index + 1; }
|
|||
// if (event.keyCode === 110 || event.keyCode === 190) {
|
|||
// event.preventDefault();
|
|||
// if(i < 3) {
|
|||
// domId = i + 1;
|
|||
// }
|
|||
// }
|
|||
// this[`_input-${domId}`].focus();
|
|||
// }
|
|||
|
|||
// useEffect(() => {
|
|||
|
|||
// }, [])
|
|||
|
|||
// const ip = value.map(val => isNaN(val) ? '' : val).join('.');
|
|||
|
|||
return ( |
|||
<div> |
|||
{/* Label */} |
|||
<label className="block text-sm font-medium text-gray-700">{label}</label> |
|||
{/* */} |
|||
<div className="relative flex gap-1 rounded-md"> |
|||
{value.map((octet, index) => ( |
|||
<> |
|||
<input |
|||
key={index} |
|||
// ref={ref}
|
|||
className={`flex h-10 w-full rounded-md border-transparent bg-orange-100 px-3 text-sm shadow-sm focus:border-transparent focus:outline-none focus:ring-2 focus:ring-orange-500 ${ |
|||
action ? "rounded-r-none" : "" |
|||
} ${ |
|||
disabled |
|||
? "cursor-not-allowed bg-orange-50 text-orange-200" |
|||
: "" |
|||
}`}
|
|||
disabled={disabled} |
|||
{...rest} |
|||
/> |
|||
{index !== 3 && <i className="text-xl">.</i>} |
|||
</> |
|||
))} |
|||
{action && ( |
|||
<button |
|||
type="button" |
|||
onClick={action.action} |
|||
className="relative -ml-px inline-flex items-center space-x-2 rounded-r-md bg-orange-200 px-4 py-2 text-sm font-medium hover:bg-orange-300 focus:outline-none focus:ring-2 focus:ring-orange-500" |
|||
> |
|||
{action.icon} |
|||
</button> |
|||
)} |
|||
{error && ( |
|||
<div className="pointer-events-none absolute inset-y-0 right-0 flex items-center pr-3"> |
|||
<ExclamationCircleIcon className="h-5 w-5 text-red-500" /> |
|||
</div> |
|||
)} |
|||
</div> |
|||
{description && ( |
|||
<p className="mt-2 text-sm text-gray-500">{description}</p> |
|||
)} |
|||
{error && <p className="mt-2 text-sm text-red-600">{error}</p>} |
|||
</div> |
|||
); |
|||
}; |
|||
Loading…
Reference in new issue