redesign the homepage
Build & Deploy / Build & Push Docker Image (push) Failing after 47s
Build & Deploy / Deploy to VPS (push) Has been skipped
Test / API Unit Tests (push) Failing after 5m4s
Test / Marketplace Unit Tests (push) Failing after 4m55s
Test / Admin Unit Tests (push) Successful in 9m37s
Test / Dashboard Unit Tests (push) Successful in 9m37s
Test / API Integration Tests (push) Successful in 9m54s

This commit is contained in:
root
2026-06-26 16:27:21 -04:00
parent 256ff0814e
commit d7fb7b7a7b
1030 changed files with 107374 additions and 2657 deletions
@@ -0,0 +1,93 @@
import { BidiText } from '@/components/foundation/BidiText';
import { classNames } from '@/lib/components/classNames';
import {
forwardRef,
type InputHTMLAttributes,
type SelectHTMLAttributes,
type TextareaHTMLAttributes,
} from 'react';
import styles from './TextInput.module.css';
export type TextInputType = 'text' | 'email' | 'tel' | 'url' | 'search';
interface TextInputProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'type'> {
type?: TextInputType;
invalid?: boolean;
describedBy?: string | undefined;
bidiValue?: boolean;
}
export const TextInput = forwardRef<HTMLInputElement, TextInputProps>(function TextInput(
{ type = 'text', invalid = false, describedBy, bidiValue = false, className, ...props },
ref,
) {
const dir = bidiValue || type === 'email' || type === 'tel' || type === 'url' ? 'ltr' : undefined;
return (
<input
ref={ref}
type={type}
dir={dir}
className={classNames(styles.control, className)}
aria-invalid={invalid || undefined}
aria-describedby={describedBy}
{...props}
/>
);
});
interface TextAreaProps extends TextareaHTMLAttributes<HTMLTextAreaElement> {
invalid?: boolean;
describedBy?: string | undefined;
characterCount?: { current: number; max: number; label: string };
}
export function TextArea({
invalid = false,
describedBy,
characterCount,
className,
...props
}: TextAreaProps) {
const countId = characterCount && props.id ? `${props.id}-count` : undefined;
const ids = [describedBy, countId].filter(Boolean).join(' ') || undefined;
return (
<div className={styles.textareaGroup}>
<textarea
className={classNames(styles.control, styles.textarea, className)}
aria-invalid={invalid || undefined}
aria-describedby={ids}
{...props}
/>
{characterCount ? (
<p id={countId} className={styles.count} aria-live="polite">
<BidiText>{`${characterCount.current}/${characterCount.max}`}</BidiText>{' '}
{characterCount.label}
</p>
) : null}
</div>
);
}
interface SelectProps extends SelectHTMLAttributes<HTMLSelectElement> {
invalid?: boolean;
describedBy?: string | undefined;
}
export function Select({
invalid = false,
describedBy,
className,
children,
...props
}: SelectProps) {
return (
<select
className={classNames(styles.control, styles.select, className)}
aria-invalid={invalid || undefined}
aria-describedby={describedBy}
{...props}
>
{children}
</select>
);
}