Respuestas y escaneo

This commit is contained in:
jalvarado
2025-04-03 15:37:35 -06:00
parent 236522a637
commit 5a3c1a5af7
23 changed files with 994 additions and 293 deletions
+65
View File
@@ -0,0 +1,65 @@
import React, { useState } from 'react';
export interface FloatingInputProps
extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'className'> {
label?: string;
className?: {
container?: string;
label?: string;
input?: string;
};
}
/**
* Componente `FloatingInput` reutilizable con soporte para estilo flotante de Bootstrap.
*
* Similar al componente `Input`, pero adaptado al sistema `form-floating` de Bootstrap.
* Soporta personalización de clases, tipo `password` con visibilidad opcional y accesibilidad.
*/
export default function FloatingInput(props: FloatingInputProps) {
const { className, label, type, name, id, ...rest } = props;
const [showPassword, setShowPassword] = useState(false);
const isPassword = type === 'password';
const inputType = isPassword && showPassword ? 'text' : type;
const inputId =
id ||
name ||
(label ? `floating-${label.replace(/\s+/g, '-')}` : undefined);
const togglePasswordVisibility = () => setShowPassword(!showPassword);
return (
<div className={`form-floating bg-white ${className?.container || 'mb-3'}`}>
<input
id={inputId}
name={name}
type={inputType}
className={`form-control ${className?.input || ''}`}
placeholder={label || ''}
{...rest}
/>
{label && (
<label htmlFor={inputId} className={className?.label || ''}>
{label}
</label>
)}
{/* Botón para mostrar/ocultar contraseña */}
{isPassword && (
<button
type='button'
className='btn btn-light border position-absolute top-50 end-0 translate-middle-y me-2'
style={{ zIndex: 5 }}
onClick={togglePasswordVisibility}
aria-label={
showPassword ? 'Ocultar contraseña' : 'Mostrar contraseña'
}
title={showPassword ? 'Ocultar contraseña' : 'Mostrar contraseña'}
>
<i className={`bi ${showPassword ? 'bi-eye-slash' : 'bi-eye'}`}></i>
</button>
)}
</div>
);
}
+14 -14
View File
@@ -1,7 +1,7 @@
import React, { useState } from "react";
import React, { useState } from 'react';
export interface InputProps
extends Omit<React.InputHTMLAttributes<HTMLInputElement>, "className"> {
extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'className'> {
label?: string;
className?: {
container?: string;
@@ -35,42 +35,42 @@ export default function Input(props: InputProps) {
const { className, label, type, name, id, ...rest } = props;
const [showPassword, setShowPassword] = useState(false);
const isPassword = type === "password";
const inputType = isPassword && showPassword ? "text" : type;
const isPassword = type === 'password';
const inputType = isPassword && showPassword ? 'text' : type;
const inputId =
id || name || (label ? `input-${label.replace(/\s+/g, "-")}` : undefined);
id || name || (label ? `input-${label.replace(/\s+/g, '-')}` : undefined);
const togglePasswordVisibility = () => setShowPassword(!showPassword);
return (
<div className={className?.container || "mb-3"}>
<div className={className?.container || 'mb-3'}>
{label && inputId && (
<label
htmlFor={inputId}
className={`form-label ${className?.label || ""}`}
className={`form-label ${className?.label || ''}`}
>
{label}
</label>
)}
<div className="input-group">
<div className='input-group'>
<input
id={inputId}
name={name}
type={inputType}
className={`form-control bg-white ${className?.input || ""}`}
className={`form-control bg-white ${className?.input || ''}`}
{...rest}
/>
{isPassword && (
<button
type="button"
className="btn btn-light border"
type='button'
className='btn btn-light border'
onClick={togglePasswordVisibility}
aria-label={
showPassword ? "Ocultar contraseña" : "Mostrar contraseña"
showPassword ? 'Ocultar contraseña' : 'Mostrar contraseña'
}
title={showPassword ? "Ocultar contraseña" : "Mostrar contraseña"}
title={showPassword ? 'Ocultar contraseña' : 'Mostrar contraseña'}
>
<i className={`bi ${showPassword ? "bi-eye-slash" : "bi-eye"}`}></i>
<i className={`bi ${showPassword ? 'bi-eye-slash' : 'bi-eye'}`}></i>
</button>
)}
</div>