analytica-frontend-lib
Version:
Repositório público dos componentes utilizados nas plataformas da Analytica Ensino
1,484 lines (1,466 loc) • 81.4 kB
JavaScript
// src/components/Text/Text.tsx
import { jsx } from "react/jsx-runtime";
var Text = ({
children,
size = "md",
weight = "normal",
color = "text-text-950",
as,
className = "",
...props
}) => {
let sizeClasses = "";
let weightClasses = "";
const sizeClassMap = {
"2xs": "text-2xs",
xs: "text-xs",
sm: "text-sm",
md: "text-md",
lg: "text-lg",
xl: "text-xl",
"2xl": "text-2xl",
"3xl": "text-3xl",
"4xl": "text-4xl",
"5xl": "text-5xl",
"6xl": "text-6xl"
};
sizeClasses = sizeClassMap[size] ?? sizeClassMap.md;
const weightClassMap = {
hairline: "font-hairline",
light: "font-light",
normal: "font-normal",
medium: "font-medium",
semibold: "font-semibold",
bold: "font-bold",
extrabold: "font-extrabold",
black: "font-black"
};
weightClasses = weightClassMap[weight] ?? weightClassMap.normal;
const baseClasses = "font-primary";
const Component = as ?? "p";
return /* @__PURE__ */ jsx(
Component,
{
className: `${baseClasses} ${sizeClasses} ${weightClasses} ${color} ${className}`,
...props,
children
}
);
};
var Text_default = Text;
// src/components/Button/Button.tsx
import { jsx as jsx2, jsxs } from "react/jsx-runtime";
var VARIANT_ACTION_CLASSES = {
solid: {
primary: "bg-primary-950 text-text border border-primary-950 hover:bg-primary-800 hover:border-primary-800 focus-visible:outline-none focus-visible:bg-primary-950 focus-visible:ring-2 focus-visible:ring-offset-0 focus-visible:ring-indicator-info active:bg-primary-700 active:border-primary-700 disabled:bg-primary-500 disabled:border-primary-500 disabled:opacity-40 disabled:cursor-not-allowed",
positive: "bg-success-500 text-text border border-success-500 hover:bg-success-600 hover:border-success-600 focus-visible:outline-none focus-visible:bg-success-500 focus-visible:ring-2 focus-visible:ring-offset-0 focus-visible:ring-indicator-info active:bg-success-700 active:border-success-700 disabled:bg-success-500 disabled:border-success-500 disabled:opacity-40 disabled:cursor-not-allowed",
negative: "bg-error-500 text-text border border-error-500 hover:bg-error-600 hover:border-error-600 focus-visible:outline-none focus-visible:bg-error-500 focus-visible:ring-2 focus-visible:ring-offset-0 focus-visible:ring-indicator-info active:bg-error-700 active:border-error-700 disabled:bg-error-500 disabled:border-error-500 disabled:opacity-40 disabled:cursor-not-allowed"
},
outline: {
primary: "bg-transparent text-primary-950 border border-primary-950 hover:bg-background-50 hover:text-primary-400 hover:border-primary-400 focus-visible:border-0 focus-visible:outline-none focus-visible:text-primary-600 focus-visible:ring-2 focus-visible:ring-offset-0 focus-visible:ring-indicator-info active:text-primary-700 active:border-primary-700 disabled:opacity-40 disabled:cursor-not-allowed",
positive: "bg-transparent text-success-500 border border-success-300 hover:bg-background-50 hover:text-success-400 hover:border-success-400 focus-visible:border-0 focus-visible:outline-none focus-visible:text-success-600 focus-visible:ring-2 focus-visible:ring-offset-0 focus-visible:ring-indicator-info active:text-success-700 active:border-success-700 disabled:opacity-40 disabled:cursor-not-allowed",
negative: "bg-transparent text-error-500 border border-error-300 hover:bg-background-50 hover:text-error-400 hover:border-error-400 focus-visible:border-0 focus-visible:outline-none focus-visible:text-error-600 focus-visible:ring-2 focus-visible:ring-offset-0 focus-visible:ring-indicator-info active:text-error-700 active:border-error-700 disabled:opacity-40 disabled:cursor-not-allowed"
},
link: {
primary: "bg-transparent text-primary-950 hover:text-primary-400 focus-visible:outline-none focus-visible:text-primary-600 focus-visible:ring-2 focus-visible:ring-offset-0 focus-visible:ring-indicator-info active:text-primary-700 disabled:opacity-40 disabled:cursor-not-allowed",
positive: "bg-transparent text-success-500 hover:text-success-400 focus-visible:outline-none focus-visible:text-success-600 focus-visible:ring-2 focus-visible:ring-offset-0 focus-visible:ring-indicator-info active:text-success-700 disabled:opacity-40 disabled:cursor-not-allowed",
negative: "bg-transparent text-error-500 hover:text-error-400 focus-visible:outline-none focus-visible:text-error-600 focus-visible:ring-2 focus-visible:ring-offset-0 focus-visible:ring-indicator-info active:text-error-700 disabled:opacity-40 disabled:cursor-not-allowed"
}
};
var SIZE_CLASSES = {
"extra-small": "text-xs px-3.5 py-2",
small: "text-sm px-4 py-2.5",
medium: "text-md px-5 py-2.5",
large: "text-lg px-6 py-3",
"extra-large": "text-lg px-7 py-3.5"
};
var Button = ({
children,
iconLeft,
iconRight,
size = "medium",
variant = "solid",
action = "primary",
className = "",
disabled,
type = "button",
...props
}) => {
const sizeClasses = SIZE_CLASSES[size];
const variantClasses = VARIANT_ACTION_CLASSES[variant][action];
const baseClasses = "inline-flex items-center justify-center rounded-full cursor-pointer font-medium";
return /* @__PURE__ */ jsxs(
"button",
{
className: `${baseClasses} ${variantClasses} ${sizeClasses} ${className}`,
disabled,
type,
...props,
children: [
iconLeft && /* @__PURE__ */ jsx2("span", { className: "mr-2 flex items-center", children: iconLeft }),
children,
iconRight && /* @__PURE__ */ jsx2("span", { className: "ml-2 flex items-center", children: iconRight })
]
}
);
};
var Button_default = Button;
// src/components/Badge/Badge.tsx
import { Bell } from "phosphor-react";
import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
var VARIANT_ACTION_CLASSES2 = {
solid: {
error: "bg-error text-error-700 focus-visible:outline-none",
warning: "bg-warning text-warning-800 focus-visible:outline-none",
success: "bg-success text-success-800 focus-visible:outline-none",
info: "bg-info text-info-800 focus-visible:outline-none",
muted: "bg-background-muted text-background-800 focus-visible:outline-none"
},
outlined: {
error: "bg-error text-error-700 border border-error-300 focus-visible:outline-none",
warning: "bg-warning text-warning-800 border border-warning-300 focus-visible:outline-none",
success: "bg-success text-success-800 border border-success-300 focus-visible:outline-none",
info: "bg-info text-info-800 border border-info-300 focus-visible:outline-none",
muted: "bg-background-muted text-background-800 border border-border-300 focus-visible:outline-none"
},
exams: {
exam1: "bg-exam-1 text-info-700 focus-visible:outline-none",
exam2: "bg-exam-2 text-typography-1 focus-visible:outline-none",
exam3: "bg-exam-3 text-typography-2 focus-visible:outline-none",
exam4: "bg-exam-4 text-success-700 focus-visible:outline-none"
},
resultStatus: {
negative: "bg-error text-error-800 focus-visible:outline-none",
positive: "bg-success text-success-800 focus-visible:outline-none"
},
notification: "text-primary"
};
var SIZE_CLASSES2 = {
small: "text-2xs px-2 py-1",
medium: "text-xs px-2 py-1",
large: "text-sm px-2 py-1"
};
var SIZE_CLASSES_ICON = {
small: "size-3",
medium: "size-3.5",
large: "size-4"
};
var Badge = ({
children,
iconLeft,
iconRight,
size = "medium",
variant = "solid",
action = "error",
className = "",
notificationActive = false,
...props
}) => {
const sizeClasses = SIZE_CLASSES2[size];
const sizeClassesIcon = SIZE_CLASSES_ICON[size];
const variantActionMap = VARIANT_ACTION_CLASSES2[variant] || {};
const variantClasses = typeof variantActionMap === "string" ? variantActionMap : variantActionMap[action] ?? variantActionMap.muted ?? "";
const baseClasses = "inline-flex items-center justify-center rounded-xs font-normal gap-1 relative";
const baseClassesIcon = "flex items-center";
if (variant === "notification") {
return /* @__PURE__ */ jsxs2(
"div",
{
className: `${baseClasses} ${variantClasses} ${sizeClasses} ${className}`,
...props,
children: [
/* @__PURE__ */ jsx3(Bell, { size: 24, className: "text-primary-950" }),
notificationActive && /* @__PURE__ */ jsx3(
"span",
{
"data-testid": "notification-dot",
className: "absolute top-[5px] right-[10px] block h-2 w-2 rounded-full bg-indicator-error ring-2 ring-white"
}
)
]
}
);
}
return /* @__PURE__ */ jsxs2(
"div",
{
className: `${baseClasses} ${variantClasses} ${sizeClasses} ${className}`,
...props,
children: [
iconLeft && /* @__PURE__ */ jsx3("span", { className: `${baseClassesIcon} ${sizeClassesIcon}`, children: iconLeft }),
children,
iconRight && /* @__PURE__ */ jsx3("span", { className: `${baseClassesIcon} ${sizeClassesIcon}`, children: iconRight })
]
}
);
};
var Badge_default = Badge;
// src/components/Alert/Alert.tsx
import { CheckCircle, Info, WarningCircle, XCircle } from "phosphor-react";
import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
var VARIANT_ACTION_CLASSES3 = {
solid: {
default: "bg-background-50 border-transparent",
info: "bg-info border-transparent",
success: "bg-success border-transparent",
warning: "bg-warning border-transparent",
error: "bg-error border-transparent"
},
outline: {
default: "bg-background border border-border-100",
info: "bg-background border border-border-100",
success: "bg-background border border-border-100",
warning: "bg-background border border-border-100",
error: "bg-background border border-border-100"
}
};
var COLOR_CLASSES = {
default: "text-text-950",
info: "text-info-800",
success: "text-success-800",
warning: "text-warning-800",
error: "text-error-800"
};
var ICONS = {
default: /* @__PURE__ */ jsx4(CheckCircle, { size: 18 }),
info: /* @__PURE__ */ jsx4(Info, { size: 18 }),
success: /* @__PURE__ */ jsx4(CheckCircle, { size: 18 }),
warning: /* @__PURE__ */ jsx4(WarningCircle, { size: 18 }),
error: /* @__PURE__ */ jsx4(XCircle, { size: 18 })
};
var Alert = ({
variant = "solid",
title,
description,
action = "default",
className,
...props
}) => {
const baseClasses = "alert-wrapper flex items-start gap-2 w-[384px] py-3 px-4 font-inherit rounded-md";
const variantClasses = VARIANT_ACTION_CLASSES3[variant][action];
const variantColor = COLOR_CLASSES[action];
const variantIcon = ICONS[action];
const hasHeading = Boolean(title);
return /* @__PURE__ */ jsxs3(
"div",
{
className: `${baseClasses} ${variantClasses} ${className ?? ""}`,
...props,
children: [
/* @__PURE__ */ jsx4("span", { className: `mt-0.5 ${variantColor}`, children: variantIcon }),
/* @__PURE__ */ jsxs3("div", { children: [
hasHeading && /* @__PURE__ */ jsx4(
Text_default,
{
size: "md",
weight: "medium",
color: variantColor,
className: "mb-0.5",
children: title
}
),
/* @__PURE__ */ jsx4(
Text_default,
{
size: hasHeading ? "sm" : "md",
weight: "normal",
color: !hasHeading ? variantColor : "text-text-700",
children: description
}
)
] })
]
}
);
};
var Alert_default = Alert;
// src/components/IconButton/IconButton.tsx
import { forwardRef } from "react";
import { jsx as jsx5 } from "react/jsx-runtime";
var IconButton = forwardRef(
({ icon, size = "md", active = false, className = "", disabled, ...props }, ref) => {
const baseClasses = [
"inline-flex",
"items-center",
"justify-center",
"rounded-lg",
"font-medium",
"bg-transparent",
"text-text-950",
"cursor-pointer",
"hover:bg-primary-600",
"hover:text-text",
"focus-visible:outline-none",
"focus-visible:ring-2",
"focus-visible:ring-offset-0",
"focus-visible:ring-indicator-info",
"disabled:opacity-50",
"disabled:cursor-not-allowed",
"disabled:pointer-events-none"
];
const sizeClasses = {
sm: ["w-6", "h-6", "text-sm"],
md: ["w-10", "h-10", "text-base"]
};
const activeClasses = active ? ["!bg-primary-50", "!text-primary-950", "hover:!bg-primary-100"] : [];
const allClasses = [
...baseClasses,
...sizeClasses[size],
...activeClasses
].join(" ");
const ariaLabel = props["aria-label"] ?? "Bot\xE3o de a\xE7\xE3o";
return /* @__PURE__ */ jsx5(
"button",
{
ref,
type: "button",
className: `${allClasses} ${className}`,
disabled,
"aria-pressed": active,
"aria-label": ariaLabel,
...props,
children: /* @__PURE__ */ jsx5("span", { className: "flex items-center justify-center", children: icon })
}
);
}
);
IconButton.displayName = "IconButton";
var IconButton_default = IconButton;
// src/components/IconRoundedButton/IconRoundedButton.tsx
import { jsx as jsx6 } from "react/jsx-runtime";
var IconRoundedButton = ({
icon,
className = "",
disabled,
...props
}) => {
const baseClasses = [
"inline-flex",
"items-center",
"justify-center",
"w-8",
"h-8",
"rounded-full",
"cursor-pointer",
"border",
"border-background-200",
"bg-background",
"text-text-950",
"hover:shadow-hard-shadow-1",
"focus-visible:outline-none",
"focus-visible:shadow-hard-shadow-1",
"focus-visible:ring-2",
"focus-visible:ring-indicator-info",
"focus-visible:ring-offset-0",
"disabled:opacity-50",
"disabled:cursor-not-allowed"
].join(" ");
return /* @__PURE__ */ jsx6(
"button",
{
type: "button",
className: `${baseClasses} ${className}`,
disabled,
...props,
children: /* @__PURE__ */ jsx6("span", { className: "flex items-center justify-center w-5 h-5", children: icon })
}
);
};
var IconRoundedButton_default = IconRoundedButton;
// src/components/NavButton/NavButton.tsx
import { forwardRef as forwardRef2 } from "react";
import { jsx as jsx7, jsxs as jsxs4 } from "react/jsx-runtime";
var NavButton = forwardRef2(
({ icon, label, selected = false, className = "", disabled, ...props }, ref) => {
const baseClasses = [
"flex",
"flex-col",
"items-center",
"justify-center",
"gap-0.5",
"px-12",
"py-1",
"rounded-sm",
"cursor-pointer",
"text-text-950",
"text-xs",
"font-medium",
"hover:text-text",
"hover:bg-primary-600",
"focus-visible:outline-none",
"focus-visible:ring-2",
"focus-visible:ring-offset-0",
"focus-visible:ring-indicator-info",
"disabled:opacity-50",
"disabled:cursor-not-allowed",
"disabled:pointer-events-none"
];
const stateClasses = selected ? ["bg-primary-50", "text-primary-950"] : [];
const allClasses = [...baseClasses, ...stateClasses].join(" ");
return /* @__PURE__ */ jsxs4(
"button",
{
ref,
type: "button",
className: `${allClasses} ${className}`,
disabled,
"aria-pressed": selected,
...props,
children: [
/* @__PURE__ */ jsx7("span", { className: "flex items-center justify-center w-5 h-5", children: icon }),
/* @__PURE__ */ jsx7("span", { className: "whitespace-nowrap", children: label })
]
}
);
}
);
NavButton.displayName = "NavButton";
var NavButton_default = NavButton;
// src/components/SelectionButton/SelectionButton.tsx
import { forwardRef as forwardRef3 } from "react";
import { jsx as jsx8, jsxs as jsxs5 } from "react/jsx-runtime";
var SelectionButton = forwardRef3(
({ icon, label, selected = false, className = "", disabled, ...props }, ref) => {
const baseClasses = [
"inline-flex",
"items-center",
"justify-start",
"gap-2",
"p-4",
"rounded-xl",
"cursor-pointer",
"border",
"border-border-50",
"bg-background",
"text-sm",
"text-text-700",
"font-bold",
"shadow-soft-shadow-1",
"hover:bg-background-100",
"focus-visible:outline-none",
"focus-visible:ring-2",
"focus-visible:ring-indicator-info",
"focus-visible:ring-offset-0",
"focus-visible:shadow-none",
"active:ring-2",
"active:ring-primary-950",
"active:ring-offset-0",
"active:shadow-none",
"disabled:opacity-50",
"disabled:cursor-not-allowed"
];
const stateClasses = selected ? ["ring-primary-950", "ring-2", "ring-offset-0", "shadow-none"] : [];
const allClasses = [...baseClasses, ...stateClasses].join(" ");
return /* @__PURE__ */ jsxs5(
"button",
{
ref,
type: "button",
className: `${allClasses} ${className}`,
disabled,
"aria-pressed": selected,
...props,
children: [
/* @__PURE__ */ jsx8("span", { className: "flex items-center justify-center w-6 h-6", children: icon }),
/* @__PURE__ */ jsx8("span", { children: label })
]
}
);
}
);
SelectionButton.displayName = "SelectionButton";
var SelectionButton_default = SelectionButton;
// src/components/Table/Table.tsx
import { forwardRef as forwardRef4 } from "react";
import { jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
var Table = forwardRef4(
({ className, children, ...props }, ref) => /* @__PURE__ */ jsx9("div", { className: "border border-border-200 rounded-xl relative w-full overflow-hidden", children: /* @__PURE__ */ jsxs6(
"table",
{
ref,
className: `w-full caption-bottom text-sm ${className ?? ""}`,
...props,
children: [
/* @__PURE__ */ jsx9("caption", { className: "sr-only", children: "My Table" }),
children
]
}
) })
);
Table.displayName = "Table";
var TableHeader = forwardRef4(({ className, ...props }, ref) => /* @__PURE__ */ jsx9(
"thead",
{
ref,
className: `[&_tr:first-child]:border-0 ${className}`,
...props
}
));
TableHeader.displayName = "TableHeader";
var TableBody = forwardRef4(({ className, ...props }, ref) => /* @__PURE__ */ jsx9(
"tbody",
{
ref,
className: `[&_tr:last-child]:border-0 border-t border-border-200 ${className}`,
...props
}
));
TableBody.displayName = "TableBody";
var TableFooter = forwardRef4(({ className, ...props }, ref) => /* @__PURE__ */ jsx9(
"tfoot",
{
ref,
className: `border-t bg-background-50 border-border-200 font-medium [&>tr]:last:border-b-0 px-6 py-3.5 ${className}`,
...props
}
));
TableFooter.displayName = "TableFooter";
var VARIANT_STATES_ROW = {
default: "border-b border-border-200",
selected: "border-b-2 border-indicator-primary",
invalid: "border-b-2 border-indicator-error",
disabled: "border-b border-border-100 bg-background-50 opacity-50 cursor-not-allowed"
};
var TableRow = forwardRef4(
({ state = "default", className, ...props }, ref) => {
return /* @__PURE__ */ jsx9(
"tr",
{
ref,
className: `
transition-colors
${state !== "disabled" ? "hover:bg-muted/50" : ""}
${VARIANT_STATES_ROW[state]}
${className}
`,
"aria-disabled": state === "disabled",
...props
}
);
}
);
TableRow.displayName = "TableRow";
var TableHead = forwardRef4(({ className, ...props }, ref) => /* @__PURE__ */ jsx9(
"th",
{
ref,
className: `h-10 px-6 py-3.5 bg-bg-secondary bg-muted/50 text-left align-middle font-bold text-text-800 [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px] ${className}`,
...props
}
));
TableHead.displayName = "TableHead";
var TableCell = forwardRef4(({ className, ...props }, ref) => /* @__PURE__ */ jsx9(
"td",
{
ref,
className: `p-2 align-middle [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px] text-md text-text-800 px-6 py-3.5 ${className}`,
...props
}
));
TableCell.displayName = "TableCell";
var TableCaption = forwardRef4(({ className, ...props }, ref) => /* @__PURE__ */ jsx9(
"caption",
{
ref,
className: `border-t border-border-200 text-sm text-text-800 px-6 py-3.5 ${className}`,
...props
}
));
TableCaption.displayName = "TableCaption";
var Table_default = Table;
// src/components/CheckBox/CheckBox.tsx
import {
forwardRef as forwardRef5,
useState,
useId
} from "react";
import { Check, Minus } from "phosphor-react";
import { jsx as jsx10, jsxs as jsxs7 } from "react/jsx-runtime";
var SIZE_CLASSES3 = {
small: {
checkbox: "w-4 h-4",
// 16px x 16px
textSize: "sm",
spacing: "gap-1.5",
// 6px
borderWidth: "border-2",
iconSize: 14,
// pixels for Phosphor icons
labelHeight: "h-[21px]"
},
medium: {
checkbox: "w-5 h-5",
// 20px x 20px
textSize: "md",
spacing: "gap-2",
// 8px
borderWidth: "border-2",
iconSize: 16,
// pixels for Phosphor icons
labelHeight: "h-6"
},
large: {
checkbox: "w-6 h-6",
// 24px x 24px
textSize: "lg",
spacing: "gap-2",
// 8px
borderWidth: "border-[3px]",
// 3px border
iconSize: 20,
// pixels for Phosphor icons
labelHeight: "h-[27px]"
}
};
var BASE_CHECKBOX_CLASSES = "rounded border cursor-pointer transition-all duration-200 flex items-center justify-center focus:outline-none";
var STATE_CLASSES = {
default: {
unchecked: "border-border-400 bg-background hover:border-border-500",
checked: "border-primary-950 bg-primary-950 text-text hover:border-primary-800 hover:bg-primary-800"
},
hovered: {
unchecked: "border-border-500 bg-background",
checked: "border-primary-800 bg-primary-800 text-text"
},
focused: {
unchecked: "border-indicator-info bg-background ring-2 ring-indicator-info/20",
checked: "border-indicator-info bg-primary-950 text-text ring-2 ring-indicator-info/20"
},
invalid: {
unchecked: "border-error-700 bg-background hover:border-error-600",
checked: "border-error-700 bg-primary-950 text-text"
},
disabled: {
unchecked: "border-border-400 bg-background cursor-not-allowed opacity-40",
checked: "border-primary-600 bg-primary-600 text-text cursor-not-allowed opacity-40"
}
};
var CheckBox = forwardRef5(
({
label,
size = "medium",
state = "default",
indeterminate = false,
errorMessage,
helperText,
className = "",
labelClassName = "",
checked: checkedProp,
disabled,
id,
onChange,
...props
}, ref) => {
const generatedId = useId();
const inputId = id ?? `checkbox-${generatedId}`;
const [internalChecked, setInternalChecked] = useState(false);
const isControlled = checkedProp !== void 0;
const checked = isControlled ? checkedProp : internalChecked;
const handleChange = (event) => {
if (!isControlled) {
setInternalChecked(event.target.checked);
}
onChange?.(event);
};
const currentState = disabled ? "disabled" : state;
const sizeClasses = SIZE_CLASSES3[size];
const checkVariant = checked || indeterminate ? "checked" : "unchecked";
const stylingClasses = STATE_CLASSES[currentState][checkVariant];
const borderWidthClass = state === "focused" || state === "hovered" && size === "large" ? "border-[3px]" : sizeClasses.borderWidth;
const checkboxClasses = `${BASE_CHECKBOX_CLASSES} ${sizeClasses.checkbox} ${borderWidthClass} ${stylingClasses} ${className}`;
const renderIcon = () => {
if (indeterminate) {
return /* @__PURE__ */ jsx10(
Minus,
{
size: sizeClasses.iconSize,
weight: "bold",
color: "currentColor"
}
);
}
if (checked) {
return /* @__PURE__ */ jsx10(
Check,
{
size: sizeClasses.iconSize,
weight: "bold",
color: "currentColor"
}
);
}
return null;
};
return /* @__PURE__ */ jsxs7("div", { className: "flex flex-col", children: [
/* @__PURE__ */ jsxs7(
"div",
{
className: `flex flex-row items-center ${sizeClasses.spacing} ${disabled ? "opacity-40" : ""}`,
children: [
/* @__PURE__ */ jsx10(
"input",
{
ref,
type: "checkbox",
id: inputId,
checked,
disabled,
onChange: handleChange,
className: "sr-only",
...props
}
),
/* @__PURE__ */ jsx10("label", { htmlFor: inputId, className: checkboxClasses, children: renderIcon() }),
label && /* @__PURE__ */ jsx10(
"div",
{
className: `flex flex-row items-center ${sizeClasses.labelHeight}`,
children: /* @__PURE__ */ jsx10(
Text_default,
{
as: "label",
htmlFor: inputId,
size: sizeClasses.textSize,
weight: "normal",
className: `cursor-pointer select-none leading-[150%] flex items-center font-roboto ${labelClassName}`,
children: label
}
)
}
)
]
}
),
errorMessage && /* @__PURE__ */ jsx10(
Text_default,
{
size: "sm",
weight: "normal",
className: "mt-1.5",
color: "text-error-600",
children: errorMessage
}
),
helperText && !errorMessage && /* @__PURE__ */ jsx10(
Text_default,
{
size: "sm",
weight: "normal",
className: "mt-1.5",
color: "text-text-500",
children: helperText
}
)
] });
}
);
CheckBox.displayName = "CheckBox";
var CheckBox_default = CheckBox;
// src/components/Radio/Radio.tsx
import {
forwardRef as forwardRef6,
useState as useState2,
useId as useId2
} from "react";
import { jsx as jsx11, jsxs as jsxs8 } from "react/jsx-runtime";
var SIZE_CLASSES4 = {
small: {
radio: "w-5 h-5",
// 20px x 20px
textSize: "sm",
spacing: "gap-1.5",
// 6px
borderWidth: "border-2",
dotSize: "w-1.5 h-1.5",
// 6px inner dot
labelHeight: "h-5"
},
medium: {
radio: "w-6 h-6",
// 24px x 24px
textSize: "md",
spacing: "gap-2",
// 8px
borderWidth: "border-2",
dotSize: "w-2 h-2",
// 8px inner dot
labelHeight: "h-6"
},
large: {
radio: "w-7 h-7",
// 28px x 28px
textSize: "lg",
spacing: "gap-2",
// 8px
borderWidth: "border-2",
// 2px border (consistent with others)
dotSize: "w-2.5 h-2.5",
// 10px inner dot
labelHeight: "h-7"
},
extraLarge: {
radio: "w-8 h-8",
// 32px x 32px (larger than large)
textSize: "xl",
spacing: "gap-3",
// 12px
borderWidth: "border-2",
// 2px border (consistent with others)
dotSize: "w-3 h-3",
// 12px inner dot
labelHeight: "h-8"
}
};
var BASE_RADIO_CLASSES = "rounded-full border cursor-pointer transition-all duration-200 flex items-center justify-center focus:outline-none";
var STATE_CLASSES2 = {
default: {
unchecked: "border-border-400 bg-background hover:border-border-500",
checked: "border-primary-950 bg-background hover:border-primary-800"
},
hovered: {
unchecked: "border-border-500 bg-background",
// #8C8D8D hover state for unchecked
checked: "border-info-700 bg-background"
// Adjust checked border for hover
},
focused: {
unchecked: "border-border-400 bg-background",
// #A5A3A3 for unchecked radio
checked: "border-primary-950 bg-background"
// #124393 for checked radio
},
invalid: {
unchecked: "border-border-400 bg-background",
// #A5A3A3 for unchecked radio
checked: "border-primary-950 bg-background"
// #124393 for checked radio
},
disabled: {
unchecked: "border-border-400 bg-background cursor-not-allowed",
// #A5A3A3 for unchecked radio
checked: "border-primary-950 bg-background cursor-not-allowed"
// #124393 for checked radio
}
};
var DOT_CLASSES = {
default: "bg-primary-950",
hovered: "bg-info-700",
// #1C61B2 hover state for checked dot
focused: "bg-primary-950",
// #124393 for focused checked dot
invalid: "bg-primary-950",
// #124393 for invalid checked dot
disabled: "bg-primary-950"
// #124393 for disabled checked dot
};
var Radio = forwardRef6(
({
label,
size = "medium",
state = "default",
errorMessage,
helperText,
className = "",
labelClassName = "",
checked: checkedProp,
defaultChecked = false,
disabled,
id,
name,
value,
onChange,
...props
}, ref) => {
const generatedId = useId2();
const inputId = id ?? `radio-${generatedId}`;
const [internalChecked, setInternalChecked] = useState2(defaultChecked);
const isControlled = checkedProp !== void 0;
const checked = isControlled ? checkedProp : internalChecked;
const handleChange = (event) => {
const newChecked = event.target.checked;
if (!isControlled) {
setInternalChecked(newChecked);
}
onChange?.(event);
};
const currentState = disabled ? "disabled" : state;
const sizeClasses = SIZE_CLASSES4[size];
const actualRadioSize = sizeClasses.radio;
const actualDotSize = sizeClasses.dotSize;
const radioVariant = checked ? "checked" : "unchecked";
const stylingClasses = STATE_CLASSES2[currentState][radioVariant];
const getBorderWidth = () => {
if (currentState === "focused") {
return "border-2";
}
return sizeClasses.borderWidth;
};
const borderWidthClass = getBorderWidth();
const radioClasses = `${BASE_RADIO_CLASSES} ${actualRadioSize} ${borderWidthClass} ${stylingClasses} ${className}`;
const dotClasses = `${actualDotSize} rounded-full ${DOT_CLASSES[currentState]} transition-all duration-200`;
const isWrapperNeeded = currentState === "focused" || currentState === "invalid";
const wrapperBorderColor = currentState === "focused" ? "border-indicator-info" : "border-indicator-error";
const getTextColor = () => {
if (currentState === "disabled") {
return checked ? "text-text-900" : "text-text-600";
}
if (currentState === "focused") {
return "text-text-900";
}
return checked ? "text-text-900" : "text-text-600";
};
const getCursorClass = () => {
return currentState === "disabled" ? "cursor-not-allowed" : "cursor-pointer";
};
return /* @__PURE__ */ jsxs8("div", { className: "flex flex-col", children: [
/* @__PURE__ */ jsxs8(
"div",
{
className: `flex flex-row items-center ${isWrapperNeeded ? `p-1 border-2 ${wrapperBorderColor} rounded-lg gap-1.5` : sizeClasses.spacing} ${disabled ? "opacity-40" : ""}`,
children: [
/* @__PURE__ */ jsx11(
"input",
{
ref,
type: "radio",
id: inputId,
checked,
disabled,
name,
value,
onChange: handleChange,
className: "sr-only",
...props
}
),
/* @__PURE__ */ jsx11("label", { htmlFor: inputId, className: radioClasses, children: checked && /* @__PURE__ */ jsx11("div", { className: dotClasses }) }),
label && /* @__PURE__ */ jsx11(
"div",
{
className: `flex flex-row items-center ${sizeClasses.labelHeight}`,
children: /* @__PURE__ */ jsx11(
Text_default,
{
as: "label",
htmlFor: inputId,
size: sizeClasses.textSize,
weight: "normal",
className: `${getCursorClass()} select-none leading-normal flex items-center font-roboto ${labelClassName}`,
color: getTextColor(),
children: label
}
)
}
)
]
}
),
errorMessage && /* @__PURE__ */ jsx11(
Text_default,
{
size: "sm",
weight: "normal",
className: "mt-1.5",
color: "text-error-600",
children: errorMessage
}
),
helperText && !errorMessage && /* @__PURE__ */ jsx11(
Text_default,
{
size: "sm",
weight: "normal",
className: "mt-1.5",
color: "text-text-500",
children: helperText
}
)
] });
}
);
Radio.displayName = "Radio";
var Radio_default = Radio;
// src/components/TextArea/TextArea.tsx
import {
forwardRef as forwardRef7,
useState as useState3,
useId as useId3
} from "react";
import { jsx as jsx12, jsxs as jsxs9 } from "react/jsx-runtime";
var SIZE_CLASSES5 = {
small: {
container: "w-72",
// 288px width
textarea: "h-24 text-sm",
// 96px height, 14px font
textSize: "sm"
},
medium: {
container: "w-72",
// 288px width
textarea: "h-24 text-base",
// 96px height, 16px font
textSize: "md"
},
large: {
container: "w-72",
// 288px width
textarea: "h-24 text-lg",
// 96px height, 18px font
textSize: "lg"
},
extraLarge: {
container: "w-72",
// 288px width
textarea: "h-24 text-xl",
// 96px height, 20px font
textSize: "xl"
}
};
var BASE_TEXTAREA_CLASSES = "w-full box-border p-3 bg-background border border-solid rounded-[4px] resize-none focus:outline-none font-roboto font-normal leading-[150%] placeholder:text-text-600 transition-all duration-200";
var STATE_CLASSES3 = {
default: {
base: "border-border-300 bg-background text-text-600",
hover: "hover:border-border-400",
focus: "focus:border-border-500"
},
hovered: {
base: "border-border-400 bg-background text-text-600",
hover: "",
focus: "focus:border-border-500"
},
focused: {
base: "border-2 border-primary-950 bg-background text-text-900",
hover: "",
focus: ""
},
invalid: {
base: "border-2 border-red-700 bg-white text-gray-800",
hover: "hover:border-red-700",
focus: "focus:border-red-700"
},
disabled: {
base: "border-border-300 bg-background text-text-600 cursor-not-allowed opacity-40",
hover: "",
focus: ""
}
};
var TextArea = forwardRef7(
({
label,
size = "medium",
state = "default",
errorMessage,
helperMessage,
className = "",
labelClassName = "",
disabled,
id,
onChange,
placeholder,
...props
}, ref) => {
const generatedId = useId3();
const inputId = id ?? `textarea-${generatedId}`;
const [isFocused, setIsFocused] = useState3(false);
const handleChange = (event) => {
onChange?.(event);
};
const handleFocus = (event) => {
setIsFocused(true);
props.onFocus?.(event);
};
const handleBlur = (event) => {
setIsFocused(false);
props.onBlur?.(event);
};
let currentState = disabled ? "disabled" : state;
if (isFocused && currentState !== "invalid" && currentState !== "disabled") {
currentState = "focused";
}
const sizeClasses = SIZE_CLASSES5[size];
const stateClasses = STATE_CLASSES3[currentState];
const textareaClasses = `${BASE_TEXTAREA_CLASSES} ${sizeClasses.textarea} ${stateClasses.base} ${stateClasses.hover} ${stateClasses.focus} ${className}`;
return /* @__PURE__ */ jsxs9("div", { className: `flex flex-col ${sizeClasses.container}`, children: [
label && /* @__PURE__ */ jsx12(
Text_default,
{
as: "label",
htmlFor: inputId,
size: sizeClasses.textSize,
weight: "medium",
color: "text-text-950",
className: `mb-1.5 ${labelClassName}`,
children: label
}
),
/* @__PURE__ */ jsx12(
"textarea",
{
ref,
id: inputId,
disabled,
onChange: handleChange,
onFocus: handleFocus,
onBlur: handleBlur,
className: textareaClasses,
placeholder,
...props
}
),
errorMessage && /* @__PURE__ */ jsx12(Text_default, { size: "sm", weight: "normal", className: "mt-1.5 text-error-600", children: errorMessage }),
helperMessage && !errorMessage && /* @__PURE__ */ jsx12(Text_default, { size: "sm", weight: "normal", className: "mt-1.5 text-text-500", children: helperMessage })
] });
}
);
TextArea.displayName = "TextArea";
var TextArea_default = TextArea;
// src/components/Toast/Toast.tsx
import { CheckCircle as CheckCircle2, WarningCircle as WarningCircle2, Info as Info2, X } from "phosphor-react";
import { jsx as jsx13, jsxs as jsxs10 } from "react/jsx-runtime";
var VARIANT_ACTION_CLASSES4 = {
solid: {
warning: "bg-warning text-warning-600 border-none focus-visible:outline-none",
success: "bg-success text-success-800 border-none focus-visible:outline-none",
info: "bg-info text-info-600 border-none focus-visible:outline-none"
},
outlined: {
warning: "bg-warning text-warning-600 border border-warning-300 focus-visible:outline-none",
success: "bg-success text-success-800 border border-success-200 focus-visible:outline-none",
info: "bg-info text-info-600 border border-info-600 focus-visible:outline-none"
}
};
var iconMap = {
success: CheckCircle2,
info: Info2,
warning: WarningCircle2
};
var Toast = ({
variant = "outlined",
action = "success",
className = "",
onClose,
title,
description,
position = "default",
...props
}) => {
const variantClasses = VARIANT_ACTION_CLASSES4[variant][action];
const positionClasses = {
"top-left": "fixed top-4 left-4",
"top-center": "fixed top-4 left-1/2 transform -translate-x-1/2",
"top-right": "fixed top-4 right-4",
"bottom-left": "fixed bottom-4 left-4",
"bottom-center": "fixed bottom-4 left-1/2 transform -translate-x-1/2",
"bottom-right": "fixed bottom-4 right-4",
default: ""
};
const IconAction = iconMap[action] || iconMap["success"];
const baseClasses = "max-w-[390px] w-full flex flex-row items-start justify-between shadow-lg rounded-lg border p-4 gap-6 group";
return /* @__PURE__ */ jsxs10(
"div",
{
role: "alert",
"aria-live": "assertive",
"aria-atomic": "true",
className: `${baseClasses} ${positionClasses[position]} ${variantClasses} ${className}`,
...props,
children: [
/* @__PURE__ */ jsxs10("div", { className: "flex flex-row items-start gap-3", children: [
/* @__PURE__ */ jsx13("span", { className: "mt-1", "data-testid": `toast-icon-${action}`, children: /* @__PURE__ */ jsx13(IconAction, {}) }),
/* @__PURE__ */ jsxs10("div", { className: "flex flex-col items-start justify-start", children: [
/* @__PURE__ */ jsx13("p", { className: "font-semibold text-md", children: title }),
description && /* @__PURE__ */ jsx13("p", { className: "text-md text-text-900", children: description })
] })
] }),
/* @__PURE__ */ jsx13(
"button",
{
onClick: onClose,
"aria-label": "Dismiss notification",
className: "text-background-500 cursor-pointer opacity-0 group-hover:opacity-100 transition-opacity",
children: /* @__PURE__ */ jsx13(X, {})
}
)
]
}
);
};
var Toast_default = Toast;
// src/components/Toast/utils/ToastStore.ts
import { create } from "zustand";
var useToastStore = create((set) => ({
toasts: [],
addToast: (toast) => {
const id = crypto.randomUUID();
set((state) => ({
toasts: [...state.toasts, { id, ...toast }]
}));
},
removeToast: (id) => {
set((state) => ({
toasts: state.toasts.filter((t) => t.id !== id)
}));
}
}));
var ToastStore_default = useToastStore;
// src/components/Toast/utils/Toaster.tsx
import { Fragment, jsx as jsx14 } from "react/jsx-runtime";
var Toaster = () => {
const toasts = ToastStore_default((state) => state.toasts);
const removeToast = ToastStore_default((state) => state.removeToast);
return /* @__PURE__ */ jsx14(Fragment, { children: toasts.map((toast) => /* @__PURE__ */ jsx14(
Toast_default,
{
title: toast.title,
description: toast.description,
variant: toast.variant,
action: toast.action,
position: toast.position,
onClose: () => removeToast(toast.id)
},
toast.id
)) });
};
var Toaster_default = Toaster;
// src/components/Divider/Divider.tsx
import { jsx as jsx15 } from "react/jsx-runtime";
var Divider = ({
orientation = "horizontal",
className = "",
...props
}) => {
const baseClasses = "bg-border-200 border-0";
const orientationClasses = {
horizontal: "w-full h-px",
vertical: "h-full w-px"
};
return /* @__PURE__ */ jsx15(
"hr",
{
className: `${baseClasses} ${orientationClasses[orientation]} ${className}`,
"aria-orientation": orientation,
...props
}
);
};
var Divider_default = Divider;
// src/components/Input/Input.tsx
import { WarningCircle as WarningCircle3, Eye, EyeSlash } from "phosphor-react";
import {
forwardRef as forwardRef8,
useState as useState4,
useId as useId4,
useMemo
} from "react";
import { jsx as jsx16, jsxs as jsxs11 } from "react/jsx-runtime";
var SIZE_CLASSES6 = {
small: "text-sm",
medium: "text-md",
large: "text-lg",
"extra-large": "text-xl"
};
var STATE_CLASSES4 = {
default: "border-border-300 placeholder:text-text-600 hover:border-border-400",
error: "border-2 border-indicator-error placeholder:text-text-600",
disabled: "border-border-300 placeholder:text-text-600 cursor-not-allowed opacity-40",
"read-only": "border-border-300 !text-text-600 cursor-default focus:outline-none bg-background-50"
};
var VARIANT_CLASSES = {
outlined: "border rounded-lg",
underlined: "border-0 border-b rounded-none bg-transparent focus:outline-none focus:border-primary-950 focus:border-b-2",
rounded: "border rounded-full"
};
var getActualState = (disabled, readOnly, errorMessage, state) => {
if (disabled) return "disabled";
if (readOnly) return "read-only";
if (errorMessage) return "error";
return state || "default";
};
var getIconSize = (size) => {
const iconSizeClasses = {
small: "w-4 h-4",
medium: "w-5 h-5",
large: "w-6 h-6",
"extra-large": "w-7 h-7"
};
return iconSizeClasses[size] || iconSizeClasses.medium;
};
var getPasswordToggleConfig = (type, disabled, readOnly, showPassword, iconRight) => {
const isPasswordType = type === "password";
const shouldShowPasswordToggle = isPasswordType && !disabled && !readOnly;
let actualIconRight = iconRight;
let ariaLabel;
if (shouldShowPasswordToggle) {
actualIconRight = showPassword ? /* @__PURE__ */ jsx16(EyeSlash, {}) : /* @__PURE__ */ jsx16(Eye, {});
ariaLabel = showPassword ? "Ocultar senha" : "Mostrar senha";
}
return { shouldShowPasswordToggle, actualIconRight, ariaLabel };
};
var getCombinedClasses = (actualState, variant) => {
const stateClasses = STATE_CLASSES4[actualState];
const variantClasses = VARIANT_CLASSES[variant];
if (actualState === "error" && variant === "underlined") {
return "border-0 border-b-2 border-indicator-error rounded-none bg-transparent focus:outline-none focus:border-primary-950 placeholder:text-text-600";
}
return `${stateClasses} ${variantClasses}`;
};
var Input = forwardRef8(
({
label,
helperText,
errorMessage,
size = "medium",
variant = "outlined",
state = "default",
iconLeft,
iconRight,
className = "",
containerClassName = "",
disabled,
readOnly,
id,
type = "text",
...props
}, ref) => {
const [showPassword, setShowPassword] = useState4(false);
const isPasswordType = type === "password";
const actualType = isPasswordType && showPassword ? "text" : type;
const actualState = getActualState(disabled, readOnly, errorMessage, state);
const sizeClasses = SIZE_CLASSES6[size];
const combinedClasses = useMemo(
() => getCombinedClasses(actualState, variant),
[actualState, variant]
);
const iconSize = getIconSize(size);
const baseClasses = "bg-background w-full py-2 px-3 font-normal text-text-900 focus:outline-primary-950";
const generatedId = useId4();
const inputId = id ?? `input-${generatedId}`;
const togglePasswordVisibility = () => setShowPassword(!showPassword);
const { shouldShowPasswordToggle, actualIconRight, ariaLabel } = getPasswordToggleConfig(
type,
disabled,
readOnly,
showPassword,
iconRight
);
return /* @__PURE__ */ jsxs11("div", { className: `${containerClassName}`, children: [
label && /* @__PURE__ */ jsx16(
"label",
{
htmlFor: inputId,
className: `block font-bold text-text-900 mb-1.5 ${sizeClasses}`,
children: label
}
),
/* @__PURE__ */ jsxs11("div", { className: "relative", children: [
iconLeft && /* @__PURE__ */ jsx16("div", { className: "absolute left-3 top-1/2 transform -translate-y-1/2 pointer-events-none", children: /* @__PURE__ */ jsx16(
"span",
{
className: `${iconSize} text-text-400 flex items-center justify-center`,
children: iconLeft
}
) }),
/* @__PURE__ */ jsx16(
"input",
{
ref,
id: inputId,
type: actualType,
className: `${baseClasses} ${sizeClasses} ${combinedClasses} ${iconLeft ? "pl-10" : ""} ${actualIconRight ? "pr-10" : ""} ${className}`,
disabled,
readOnly,
"aria-invalid": actualState === "error" ? "true" : void 0,
...props
}
),
actualIconRight && (shouldShowPasswordToggle ? /* @__PURE__ */ jsx16(
"button",
{
type: "button",
className: "absolute right-3 top-1/2 transform -translate-y-1/2 cursor-pointer border-0 bg-transparent p-0",
onClick: togglePasswordVisibility,
"aria-label": ariaLabel,
children: /* @__PURE__ */ jsx16(
"span",
{
className: `${iconSize} text-text-400 flex items-center justify-center hover:text-text-600 transition-colors`,
children: actualIconRight
}
)
}
) : /* @__PURE__ */ jsx16("div", { className: "absolute right-3 top-1/2 transform -translate-y-1/2 pointer-events-none", children: /* @__PURE__ */ jsx16(
"span",
{
className: `${iconSize} text-text-400 flex items-center justify-center`,
children: actualIconRight
}
) }))
] }),
/* @__PURE__ */ jsxs11("div", { className: "mt-1.5 gap-1.5", children: [
helperText && /* @__PURE__ */ jsx16("p", { className: "text-sm text-text-500", children: helperText }),
errorMessage && /* @__PURE__ */ jsxs11("p", { className: "flex gap-1 items-center text-sm text-indicator-error", children: [
/* @__PURE__ */ jsx16(WarningCircle3, { size: 16 }),
" ",
errorMessage
] })
] })
] });
}
);
var Input_default = Input;
// src/components/Chips/Chips.tsx
import { Check as Check2 } from "phosphor-react";
import { jsx as jsx17, jsxs as jsxs12 } from "react/jsx-runtime";
var STATE_CLASSES5 = {
default: "bg-background text-text-950 border border-border-100 hover:bg-secondary-50 hover:border-border-300",
selected: "bg-info-background text-primary-950 border-2 border-primary-950 hover:bg-secondary-50 focus-visible:border-0"
};
var Chips = ({
children,
selected = false,
className = "",
disabled,
type = "button",
...props
}) => {
const stateClasses = selected ? STATE_CLASSES5.selected : STATE_CLASSES5.default;
const baseClasses = "inline-flex items-center justify-center rounded-full cursor-pointer font-normal text-sm px-4 py-2 gap-2 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-0 focus-visible:ring-primary-600 disabled:opacity-40 disabled:cursor-not-allowed";
return /* @__PURE__ */ jsxs12(
"button",
{
className: `${baseClasses} ${stateClasses} ${className}`,
disabled,
type,
...props,
children: [
selected && /* @__PURE__ */ jsx17("span", { className: `flex items-center`, children: /* @__PURE__ */ jsx17(Check2, { weight: "bold", size: 16 }) }),
/* @__PURE__ */ jsx17("span", { className: "flex-1", children })
]
}
);
};
var Chips_default = Chips;
// src/components/ProgressBar/ProgressBar.tsx
import { jsx as jsx18, jsxs as jsxs13 } from "react/jsx-runtime";
var SIZE_CLASSES7 = {
small: {
container: "h-1",
// 4px height (h-1 = 4px in Tailwind)
bar: "h-1",
// 4px height for the fill bar
labelSize: "xs",
spacing: "gap-2",
// 8px gap between label and progress bar
layout: "flex-col",
// vertical layout for small
borderRadius: "rounded-full"
// 9999px border radius
},
medium: {
container: "h-2",
// 8px height (h-2 = 8px in Tailwind)
bar: "h-2",
// 8px height for the fill bar
labelSize: "xs",
// 12px