Compare commits

...

1 Commits

Author SHA1 Message Date
7265eaad18 Add password input 2026-03-20 22:12:59 -04:00
6 changed files with 74 additions and 5 deletions

View File

@@ -47,6 +47,7 @@ export { default as DragAndDropFileInput } from "./file/DragAndDropFileInput";
export { default as FileInput } from "./file/FileInput"; export { default as FileInput } from "./file/FileInput";
export { default as NumberInput } from "./number/NumberInput"; export { default as NumberInput } from "./number/NumberInput";
export { default as OptionInput } from "./text/OptionInput"; export { default as OptionInput } from "./text/OptionInput";
export { default as PasswordInput } from "./text/PasswordInput";
export { default as PhoneInput } from "./text/PhoneInput"; export { default as PhoneInput } from "./text/PhoneInput";
export { default as SelectInput } from "./text/SelectInput"; export { default as SelectInput } from "./text/SelectInput";
export { default as TextArea } from "./text/TextArea"; export { default as TextArea } from "./text/TextArea";

View File

@@ -0,0 +1,66 @@
import type { TextInputProps } from "$/types/InputTypes";
import clsx from "clsx";
import { useId } from "react";
export default function PasswordInput({
id,
className,
inputClassName,
labelClassName,
name,
maxLength,
spellCheck,
placeholder,
value,
onChange,
onKeyDown,
disabled
}: Readonly<TextInputProps>){
const componentId = useId();
const activeId = id ?? componentId;
return (
<div
className={clsx(
"flex flex-row items-center justify-center rounded-lg border-2 w-full",
className
)}
>
<div
className="relative flex flex-row items-center justify-center px-2 py-1 w-full"
>
<input
type="password"
id={activeId}
className={clsx(
"peer bg-transparent outline-none placeholder-transparent w-full",
inputClassName
)}
name={name}
placeholder={placeholder}
maxLength={maxLength}
value={value}
onChange={(e) => onChange?.(e.target.value)}
disabled={disabled}
spellCheck={spellCheck}
onKeyDown={onKeyDown}
/>
<label
className={clsx(
"absolute ml-2 -top-3 left-0 text-sm rounded-md px-1 select-none cursor-default",
"peer-placeholder-shown:top-0 peer-placeholder-shown:-left-1 peer-placeholder-shown:text-inherit peer-placeholder-shown:text-base peer-placeholder-shown:h-full peer-placeholder-shown:cursor-text peer-placeholder-shown:w-[98%]",
"peer-focus:-top-3 peer-focus:left-0 peer-focus:text-sm peer-focus:w-auto peer-focus:h-auto",
"flex items-center",
labelClassName
)}
style={{ transitionProperty: "top, left, font-size, line-height", transitionTimingFunction: "cubic-bezier(0.4 0, 0.2, 1)", transitionDuration: "250ms" }}
htmlFor={activeId}
>
{placeholder}
</label>
</div>
</div>
);
}

View File

@@ -53,7 +53,7 @@ export default function TextArea({
<label <label
className={clsx( className={clsx(
"absolute ml-2 -top-3 left-0 text-sm rounded-md px-1 select-none cursor-default", "absolute ml-2 -top-3 left-0 text-sm rounded-md px-1 select-none cursor-default",
"peer-placeholder-shown:top-0 peer-placeholder-shown:-left-1 peer-placeholder-shown:text-inherit peer-placeholder-shown:text-base peer-placeholder-shown:cursor-text peer-placeholder-shown:w-[99%]", "peer-placeholder-shown:top-0 peer-placeholder-shown:-left-1 peer-placeholder-shown:text-inherit peer-placeholder-shown:text-base peer-placeholder-shown:cursor-text peer-placeholder-shown:w-[98%]",
"peer-focus:-top-3 peer-focus:left-0 peer-focus:text-sm peer-focus:w-auto peer-focus:h-auto", "peer-focus:-top-3 peer-focus:left-0 peer-focus:text-sm peer-focus:w-auto peer-focus:h-auto",
"flex items-center", "flex items-center",
labelClassName labelClassName

View File

@@ -50,7 +50,7 @@ export default function TextInput({
<label <label
className={clsx( className={clsx(
"absolute ml-2 -top-3 left-0 text-sm rounded-md px-1 select-none cursor-default", "absolute ml-2 -top-3 left-0 text-sm rounded-md px-1 select-none cursor-default",
"peer-placeholder-shown:top-0 peer-placeholder-shown:-left-1 peer-placeholder-shown:text-inherit peer-placeholder-shown:text-base peer-placeholder-shown:h-full peer-placeholder-shown:cursor-text peer-placeholder-shown:w-[99%]", "peer-placeholder-shown:top-0 peer-placeholder-shown:-left-1 peer-placeholder-shown:text-inherit peer-placeholder-shown:text-base peer-placeholder-shown:h-full peer-placeholder-shown:cursor-text peer-placeholder-shown:w-[98%]",
"peer-focus:-top-3 peer-focus:left-0 peer-focus:text-sm peer-focus:w-auto peer-focus:h-auto", "peer-focus:-top-3 peer-focus:left-0 peer-focus:text-sm peer-focus:w-auto peer-focus:h-auto",
"flex items-center", "flex items-center",
labelClassName labelClassName

View File

@@ -28,13 +28,15 @@ export default function AxiosProvider({
const publicApi = useMemo(() => { const publicApi = useMemo(() => {
const api = axios.create({ const api = axios.create({
baseURL: apiUrl baseURL: apiUrl,
withCredentials: true
}); });
return api; return api;
}, [apiUrl]); }, [apiUrl]);
const authorizedApi = useMemo(() => { const authorizedApi = useMemo(() => {
const api = axios.create({ const api = axios.create({
baseURL: apiUrl baseURL: apiUrl,
withCredentials: true
}); });
api.interceptors.request.use(async (config) => { api.interceptors.request.use(async (config) => {
try{ try{

View File

@@ -26,7 +26,7 @@ export const defaultTokenData: TokenData = {
} }
export async function fetchToken(apiUrl: string){ export async function fetchToken(apiUrl: string){
const res = await fetch(`${apiUrl}/refresh`); const res = await fetch(`${apiUrl}/auth/refresh`, { method: "POST", credentials: "include" });
return await res.json() as TokenResponse; return await res.json() as TokenResponse;
} }