analytica-frontend-lib 1.0.34 → 1.0.36
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/DropdownMenu/index.d.mts +36 -5
- package/dist/DropdownMenu/index.d.ts +36 -5
- package/dist/DropdownMenu/index.js +178 -39
- package/dist/DropdownMenu/index.js.map +1 -1
- package/dist/DropdownMenu/index.mjs +175 -43
- package/dist/DropdownMenu/index.mjs.map +1 -1
- package/dist/ProgressBar/index.d.mts +60 -0
- package/dist/ProgressBar/index.d.ts +60 -0
- package/dist/ProgressBar/index.js +220 -0
- package/dist/ProgressBar/index.js.map +1 -0
- package/dist/ProgressBar/index.mjs +198 -0
- package/dist/ProgressBar/index.mjs.map +1 -0
- package/dist/Radio/index.d.mts +85 -0
- package/dist/Radio/index.d.ts +85 -0
- package/dist/Radio/index.js +299 -0
- package/dist/Radio/index.js.map +1 -0
- package/dist/Radio/index.mjs +283 -0
- package/dist/Radio/index.mjs.map +1 -0
- package/dist/index.css +150 -0
- package/dist/index.css.map +1 -1
- package/dist/index.d.mts +49 -61
- package/dist/index.d.ts +49 -61
- package/dist/index.js +618 -49
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +615 -50
- package/dist/index.mjs.map +1 -1
- package/dist/styles.css +150 -0
- package/dist/styles.css.map +1 -1
- package/package.json +3 -1
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
"use client";
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
+
};
|
|
11
|
+
var __copyProps = (to, from, except, desc) => {
|
|
12
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
+
for (let key of __getOwnPropNames(from))
|
|
14
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
20
|
+
|
|
21
|
+
// src/components/Radio/Radio.tsx
|
|
22
|
+
var Radio_exports = {};
|
|
23
|
+
__export(Radio_exports, {
|
|
24
|
+
default: () => Radio_default
|
|
25
|
+
});
|
|
26
|
+
module.exports = __toCommonJS(Radio_exports);
|
|
27
|
+
var import_react = require("react");
|
|
28
|
+
|
|
29
|
+
// src/components/Text/Text.tsx
|
|
30
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
31
|
+
var Text = ({
|
|
32
|
+
children,
|
|
33
|
+
size = "md",
|
|
34
|
+
weight = "normal",
|
|
35
|
+
color = "text-text-950",
|
|
36
|
+
as,
|
|
37
|
+
className = "",
|
|
38
|
+
...props
|
|
39
|
+
}) => {
|
|
40
|
+
let sizeClasses = "";
|
|
41
|
+
let weightClasses = "";
|
|
42
|
+
const sizeClassMap = {
|
|
43
|
+
"2xs": "text-2xs",
|
|
44
|
+
xs: "text-xs",
|
|
45
|
+
sm: "text-sm",
|
|
46
|
+
md: "text-md",
|
|
47
|
+
lg: "text-lg",
|
|
48
|
+
xl: "text-xl",
|
|
49
|
+
"2xl": "text-2xl",
|
|
50
|
+
"3xl": "text-3xl",
|
|
51
|
+
"4xl": "text-4xl",
|
|
52
|
+
"5xl": "text-5xl",
|
|
53
|
+
"6xl": "text-6xl"
|
|
54
|
+
};
|
|
55
|
+
sizeClasses = sizeClassMap[size] ?? sizeClassMap.md;
|
|
56
|
+
const weightClassMap = {
|
|
57
|
+
hairline: "font-hairline",
|
|
58
|
+
light: "font-light",
|
|
59
|
+
normal: "font-normal",
|
|
60
|
+
medium: "font-medium",
|
|
61
|
+
semibold: "font-semibold",
|
|
62
|
+
bold: "font-bold",
|
|
63
|
+
extrabold: "font-extrabold",
|
|
64
|
+
black: "font-black"
|
|
65
|
+
};
|
|
66
|
+
weightClasses = weightClassMap[weight] ?? weightClassMap.normal;
|
|
67
|
+
const baseClasses = "font-primary";
|
|
68
|
+
const Component = as ?? "p";
|
|
69
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
70
|
+
Component,
|
|
71
|
+
{
|
|
72
|
+
className: `${baseClasses} ${sizeClasses} ${weightClasses} ${color} ${className}`,
|
|
73
|
+
...props,
|
|
74
|
+
children
|
|
75
|
+
}
|
|
76
|
+
);
|
|
77
|
+
};
|
|
78
|
+
var Text_default = Text;
|
|
79
|
+
|
|
80
|
+
// src/components/Radio/Radio.tsx
|
|
81
|
+
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
82
|
+
var SIZE_CLASSES = {
|
|
83
|
+
small: {
|
|
84
|
+
radio: "w-5 h-5",
|
|
85
|
+
// 20px x 20px
|
|
86
|
+
textSize: "sm",
|
|
87
|
+
spacing: "gap-1.5",
|
|
88
|
+
// 6px
|
|
89
|
+
borderWidth: "border-2",
|
|
90
|
+
dotSize: "w-1.5 h-1.5",
|
|
91
|
+
// 6px inner dot
|
|
92
|
+
labelHeight: "h-5"
|
|
93
|
+
},
|
|
94
|
+
medium: {
|
|
95
|
+
radio: "w-6 h-6",
|
|
96
|
+
// 24px x 24px
|
|
97
|
+
textSize: "md",
|
|
98
|
+
spacing: "gap-2",
|
|
99
|
+
// 8px
|
|
100
|
+
borderWidth: "border-2",
|
|
101
|
+
dotSize: "w-2 h-2",
|
|
102
|
+
// 8px inner dot
|
|
103
|
+
labelHeight: "h-6"
|
|
104
|
+
},
|
|
105
|
+
large: {
|
|
106
|
+
radio: "w-7 h-7",
|
|
107
|
+
// 28px x 28px
|
|
108
|
+
textSize: "lg",
|
|
109
|
+
spacing: "gap-2",
|
|
110
|
+
// 8px
|
|
111
|
+
borderWidth: "border-2",
|
|
112
|
+
// 2px border (consistent with others)
|
|
113
|
+
dotSize: "w-2.5 h-2.5",
|
|
114
|
+
// 10px inner dot
|
|
115
|
+
labelHeight: "h-7"
|
|
116
|
+
},
|
|
117
|
+
extraLarge: {
|
|
118
|
+
radio: "w-8 h-8",
|
|
119
|
+
// 32px x 32px (larger than large)
|
|
120
|
+
textSize: "xl",
|
|
121
|
+
spacing: "gap-3",
|
|
122
|
+
// 12px
|
|
123
|
+
borderWidth: "border-2",
|
|
124
|
+
// 2px border (consistent with others)
|
|
125
|
+
dotSize: "w-3 h-3",
|
|
126
|
+
// 12px inner dot
|
|
127
|
+
labelHeight: "h-8"
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
var BASE_RADIO_CLASSES = "rounded-full border cursor-pointer transition-all duration-200 flex items-center justify-center focus:outline-none";
|
|
131
|
+
var STATE_CLASSES = {
|
|
132
|
+
default: {
|
|
133
|
+
unchecked: "border-border-400 bg-background hover:border-border-500",
|
|
134
|
+
checked: "border-primary-950 bg-background hover:border-primary-800"
|
|
135
|
+
},
|
|
136
|
+
hovered: {
|
|
137
|
+
unchecked: "border-border-500 bg-background",
|
|
138
|
+
// #8C8D8D hover state for unchecked
|
|
139
|
+
checked: "border-info-700 bg-background"
|
|
140
|
+
// Adjust checked border for hover
|
|
141
|
+
},
|
|
142
|
+
focused: {
|
|
143
|
+
unchecked: "border-border-400 bg-background",
|
|
144
|
+
// #A5A3A3 for unchecked radio
|
|
145
|
+
checked: "border-primary-950 bg-background"
|
|
146
|
+
// #124393 for checked radio
|
|
147
|
+
},
|
|
148
|
+
invalid: {
|
|
149
|
+
unchecked: "border-border-400 bg-background",
|
|
150
|
+
// #A5A3A3 for unchecked radio
|
|
151
|
+
checked: "border-primary-950 bg-background"
|
|
152
|
+
// #124393 for checked radio
|
|
153
|
+
},
|
|
154
|
+
disabled: {
|
|
155
|
+
unchecked: "border-border-400 bg-background cursor-not-allowed",
|
|
156
|
+
// #A5A3A3 for unchecked radio
|
|
157
|
+
checked: "border-primary-950 bg-background cursor-not-allowed"
|
|
158
|
+
// #124393 for checked radio
|
|
159
|
+
}
|
|
160
|
+
};
|
|
161
|
+
var DOT_CLASSES = {
|
|
162
|
+
default: "bg-primary-950",
|
|
163
|
+
hovered: "bg-info-700",
|
|
164
|
+
// #1C61B2 hover state for checked dot
|
|
165
|
+
focused: "bg-primary-950",
|
|
166
|
+
// #124393 for focused checked dot
|
|
167
|
+
invalid: "bg-primary-950",
|
|
168
|
+
// #124393 for invalid checked dot
|
|
169
|
+
disabled: "bg-primary-950"
|
|
170
|
+
// #124393 for disabled checked dot
|
|
171
|
+
};
|
|
172
|
+
var Radio = (0, import_react.forwardRef)(
|
|
173
|
+
({
|
|
174
|
+
label,
|
|
175
|
+
size = "medium",
|
|
176
|
+
state = "default",
|
|
177
|
+
errorMessage,
|
|
178
|
+
helperText,
|
|
179
|
+
className = "",
|
|
180
|
+
labelClassName = "",
|
|
181
|
+
checked: checkedProp,
|
|
182
|
+
defaultChecked = false,
|
|
183
|
+
disabled,
|
|
184
|
+
id,
|
|
185
|
+
name,
|
|
186
|
+
value,
|
|
187
|
+
onChange,
|
|
188
|
+
...props
|
|
189
|
+
}, ref) => {
|
|
190
|
+
const generatedId = (0, import_react.useId)();
|
|
191
|
+
const inputId = id ?? `radio-${generatedId}`;
|
|
192
|
+
const [internalChecked, setInternalChecked] = (0, import_react.useState)(defaultChecked);
|
|
193
|
+
const isControlled = checkedProp !== void 0;
|
|
194
|
+
const checked = isControlled ? checkedProp : internalChecked;
|
|
195
|
+
const handleChange = (event) => {
|
|
196
|
+
const newChecked = event.target.checked;
|
|
197
|
+
if (!isControlled) {
|
|
198
|
+
setInternalChecked(newChecked);
|
|
199
|
+
}
|
|
200
|
+
onChange?.(event);
|
|
201
|
+
};
|
|
202
|
+
const currentState = disabled ? "disabled" : state;
|
|
203
|
+
const sizeClasses = SIZE_CLASSES[size];
|
|
204
|
+
const actualRadioSize = sizeClasses.radio;
|
|
205
|
+
const actualDotSize = sizeClasses.dotSize;
|
|
206
|
+
const radioVariant = checked ? "checked" : "unchecked";
|
|
207
|
+
const stylingClasses = STATE_CLASSES[currentState][radioVariant];
|
|
208
|
+
const getBorderWidth = () => {
|
|
209
|
+
if (currentState === "focused") {
|
|
210
|
+
return "border-2";
|
|
211
|
+
}
|
|
212
|
+
return sizeClasses.borderWidth;
|
|
213
|
+
};
|
|
214
|
+
const borderWidthClass = getBorderWidth();
|
|
215
|
+
const radioClasses = `${BASE_RADIO_CLASSES} ${actualRadioSize} ${borderWidthClass} ${stylingClasses} ${className}`;
|
|
216
|
+
const dotClasses = `${actualDotSize} rounded-full ${DOT_CLASSES[currentState]} transition-all duration-200`;
|
|
217
|
+
const isWrapperNeeded = currentState === "focused" || currentState === "invalid";
|
|
218
|
+
const wrapperBorderColor = currentState === "focused" ? "border-indicator-info" : "border-indicator-error";
|
|
219
|
+
const getTextColor = () => {
|
|
220
|
+
if (currentState === "disabled") {
|
|
221
|
+
return checked ? "text-text-900" : "text-text-600";
|
|
222
|
+
}
|
|
223
|
+
if (currentState === "focused") {
|
|
224
|
+
return "text-text-900";
|
|
225
|
+
}
|
|
226
|
+
return checked ? "text-text-900" : "text-text-600";
|
|
227
|
+
};
|
|
228
|
+
const getCursorClass = () => {
|
|
229
|
+
return currentState === "disabled" ? "cursor-not-allowed" : "cursor-pointer";
|
|
230
|
+
};
|
|
231
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex flex-col", children: [
|
|
232
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
233
|
+
"div",
|
|
234
|
+
{
|
|
235
|
+
className: `flex flex-row items-center ${isWrapperNeeded ? `p-1 border-2 ${wrapperBorderColor} rounded-lg gap-1.5` : sizeClasses.spacing} ${disabled ? "opacity-40" : ""}`,
|
|
236
|
+
children: [
|
|
237
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
238
|
+
"input",
|
|
239
|
+
{
|
|
240
|
+
ref,
|
|
241
|
+
type: "radio",
|
|
242
|
+
id: inputId,
|
|
243
|
+
checked,
|
|
244
|
+
disabled,
|
|
245
|
+
name,
|
|
246
|
+
value,
|
|
247
|
+
onChange: handleChange,
|
|
248
|
+
className: "sr-only",
|
|
249
|
+
...props
|
|
250
|
+
}
|
|
251
|
+
),
|
|
252
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { htmlFor: inputId, className: radioClasses, children: checked && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: dotClasses }) }),
|
|
253
|
+
label && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
254
|
+
"div",
|
|
255
|
+
{
|
|
256
|
+
className: `flex flex-row items-center ${sizeClasses.labelHeight}`,
|
|
257
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
258
|
+
Text_default,
|
|
259
|
+
{
|
|
260
|
+
as: "label",
|
|
261
|
+
htmlFor: inputId,
|
|
262
|
+
size: sizeClasses.textSize,
|
|
263
|
+
weight: "normal",
|
|
264
|
+
className: `${getCursorClass()} select-none leading-normal flex items-center font-roboto ${labelClassName}`,
|
|
265
|
+
color: getTextColor(),
|
|
266
|
+
children: label
|
|
267
|
+
}
|
|
268
|
+
)
|
|
269
|
+
}
|
|
270
|
+
)
|
|
271
|
+
]
|
|
272
|
+
}
|
|
273
|
+
),
|
|
274
|
+
errorMessage && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
275
|
+
Text_default,
|
|
276
|
+
{
|
|
277
|
+
size: "sm",
|
|
278
|
+
weight: "normal",
|
|
279
|
+
className: "mt-1.5",
|
|
280
|
+
color: "text-error-600",
|
|
281
|
+
children: errorMessage
|
|
282
|
+
}
|
|
283
|
+
),
|
|
284
|
+
helperText && !errorMessage && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
285
|
+
Text_default,
|
|
286
|
+
{
|
|
287
|
+
size: "sm",
|
|
288
|
+
weight: "normal",
|
|
289
|
+
className: "mt-1.5",
|
|
290
|
+
color: "text-text-500",
|
|
291
|
+
children: helperText
|
|
292
|
+
}
|
|
293
|
+
)
|
|
294
|
+
] });
|
|
295
|
+
}
|
|
296
|
+
);
|
|
297
|
+
Radio.displayName = "Radio";
|
|
298
|
+
var Radio_default = Radio;
|
|
299
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/components/Radio/Radio.tsx","../../src/components/Text/Text.tsx"],"sourcesContent":["'use client';\n\nimport {\n InputHTMLAttributes,\n ReactNode,\n forwardRef,\n useState,\n useId,\n ChangeEvent,\n} from 'react';\nimport Text from '../Text/Text';\n\n/**\n * Radio size variants\n */\ntype RadioSize = 'small' | 'medium' | 'large' | 'extraLarge';\n\n/**\n * Radio visual state\n */\ntype RadioState = 'default' | 'hovered' | 'focused' | 'invalid' | 'disabled';\n\n/**\n * Size configurations using Tailwind classes\n */\nconst SIZE_CLASSES = {\n small: {\n radio: 'w-5 h-5', // 20px x 20px\n textSize: 'sm' as const,\n spacing: 'gap-1.5', // 6px\n borderWidth: 'border-2',\n dotSize: 'w-1.5 h-1.5', // 6px inner dot\n labelHeight: 'h-5',\n },\n medium: {\n radio: 'w-6 h-6', // 24px x 24px\n textSize: 'md' as const,\n spacing: 'gap-2', // 8px\n borderWidth: 'border-2',\n dotSize: 'w-2 h-2', // 8px inner dot\n labelHeight: 'h-6',\n },\n large: {\n radio: 'w-7 h-7', // 28px x 28px\n textSize: 'lg' as const,\n spacing: 'gap-2', // 8px\n borderWidth: 'border-2', // 2px border (consistent with others)\n dotSize: 'w-2.5 h-2.5', // 10px inner dot\n labelHeight: 'h-7',\n },\n extraLarge: {\n radio: 'w-8 h-8', // 32px x 32px (larger than large)\n textSize: 'xl' as const,\n spacing: 'gap-3', // 12px\n borderWidth: 'border-2', // 2px border (consistent with others)\n dotSize: 'w-3 h-3', // 12px inner dot\n labelHeight: 'h-8',\n },\n} as const;\n\n/**\n * Focused state maintains the same sizes as default state\n * Only adds wrapper styling, does not change radio/dot sizes\n */\n\n/**\n * Base radio styling classes using design system colors\n */\nconst BASE_RADIO_CLASSES =\n 'rounded-full border cursor-pointer transition-all duration-200 flex items-center justify-center focus:outline-none';\n\n/**\n * State-based styling classes using design system colors from styles.css\n */\nconst STATE_CLASSES = {\n default: {\n unchecked: 'border-border-400 bg-background hover:border-border-500',\n checked: 'border-primary-950 bg-background hover:border-primary-800',\n },\n hovered: {\n unchecked: 'border-border-500 bg-background', // #8C8D8D hover state for unchecked\n checked: 'border-info-700 bg-background', // Adjust checked border for hover\n },\n focused: {\n unchecked: 'border-border-400 bg-background', // #A5A3A3 for unchecked radio\n checked: 'border-primary-950 bg-background', // #124393 for checked radio\n },\n invalid: {\n unchecked: 'border-border-400 bg-background', // #A5A3A3 for unchecked radio\n checked: 'border-primary-950 bg-background', // #124393 for checked radio\n },\n disabled: {\n unchecked: 'border-border-400 bg-background cursor-not-allowed', // #A5A3A3 for unchecked radio\n checked: 'border-primary-950 bg-background cursor-not-allowed', // #124393 for checked radio\n },\n} as const;\n\n/**\n * Dot styling classes for the inner dot when checked\n */\nconst DOT_CLASSES = {\n default: 'bg-primary-950',\n hovered: 'bg-info-700', // #1C61B2 hover state for checked dot\n focused: 'bg-primary-950', // #124393 for focused checked dot\n invalid: 'bg-primary-950', // #124393 for invalid checked dot\n disabled: 'bg-primary-950', // #124393 for disabled checked dot\n} as const;\n\n/**\n * Radio component props interface\n */\nexport type RadioProps = {\n /** Label text to display next to the radio */\n label?: ReactNode;\n /** Size variant of the radio */\n size?: RadioSize;\n /** Visual state of the radio */\n state?: RadioState;\n /** Error message to display */\n errorMessage?: string;\n /** Helper text to display */\n helperText?: string;\n /** Additional CSS classes */\n className?: string;\n /** Label CSS classes */\n labelClassName?: string;\n /** Radio group name */\n name?: string;\n /** Radio value */\n value?: string;\n /** Default checked state for uncontrolled radios */\n defaultChecked?: boolean;\n} & Omit<\n InputHTMLAttributes<HTMLInputElement>,\n 'size' | 'type' | 'defaultChecked'\n>;\n\n/**\n * Radio component for Analytica Ensino platforms\n *\n * A radio button component with essential states, sizes and themes.\n * Uses the Analytica Ensino Design System colors from styles.css with automatic\n * light/dark mode support. Includes Text component integration for consistent typography.\n *\n * @example\n * ```tsx\n * // Basic radio\n * <Radio name=\"option\" value=\"1\" label=\"Option 1\" />\n *\n * // Small size\n * <Radio size=\"small\" name=\"option\" value=\"2\" label=\"Small option\" />\n *\n * // Invalid state\n * <Radio state=\"invalid\" name=\"option\" value=\"3\" label=\"Required field\" />\n *\n * // Disabled state\n * <Radio disabled name=\"option\" value=\"4\" label=\"Disabled option\" />\n *\n * // Default checked (uncontrolled)\n * <Radio defaultChecked name=\"option\" value=\"5\" label=\"Initially checked\" />\n * ```\n */\nconst Radio = forwardRef<HTMLInputElement, RadioProps>(\n (\n {\n label,\n size = 'medium',\n state = 'default',\n errorMessage,\n helperText,\n className = '',\n labelClassName = '',\n checked: checkedProp,\n defaultChecked = false,\n disabled,\n id,\n name,\n value,\n onChange,\n ...props\n },\n ref\n ) => {\n // Generate unique ID if not provided\n const generatedId = useId();\n const inputId = id ?? `radio-${generatedId}`;\n\n // Handle controlled vs uncontrolled behavior\n const [internalChecked, setInternalChecked] = useState(defaultChecked);\n const isControlled = checkedProp !== undefined;\n const checked = isControlled ? checkedProp : internalChecked;\n\n // Handle change events\n const handleChange = (event: ChangeEvent<HTMLInputElement>) => {\n const newChecked = event.target.checked;\n\n if (!isControlled) {\n setInternalChecked(newChecked);\n }\n\n onChange?.(event);\n };\n\n // Determine current state based on props\n const currentState = disabled ? 'disabled' : state;\n\n // Get size classes\n const sizeClasses = SIZE_CLASSES[size];\n\n // Focused state maintains original sizes, only adds wrapper\n const actualRadioSize = sizeClasses.radio;\n const actualDotSize = sizeClasses.dotSize;\n\n // Determine radio visual variant\n const radioVariant = checked ? 'checked' : 'unchecked';\n\n // Get styling classes\n const stylingClasses = STATE_CLASSES[currentState][radioVariant];\n\n // Border width logic - consistent across all states and sizes\n const getBorderWidth = () => {\n if (currentState === 'focused') {\n return 'border-2'; // Consistent border for all focused radios inside wrapper\n }\n return sizeClasses.borderWidth;\n };\n\n const borderWidthClass = getBorderWidth();\n\n // Get final radio classes\n const radioClasses = `${BASE_RADIO_CLASSES} ${actualRadioSize} ${borderWidthClass} ${stylingClasses} ${className}`;\n\n // Get dot classes\n const dotClasses = `${actualDotSize} rounded-full ${DOT_CLASSES[currentState]} transition-all duration-200`;\n\n // Determine if wrapper is needed only for focused or invalid states\n const isWrapperNeeded =\n currentState === 'focused' || currentState === 'invalid';\n const wrapperBorderColor =\n currentState === 'focused'\n ? 'border-indicator-info' // #5399EC for focused\n : 'border-indicator-error'; // #B91C1C for invalid\n\n // Determine text color based on state and checked status\n const getTextColor = () => {\n if (currentState === 'disabled') {\n return checked ? 'text-text-900' : 'text-text-600'; // #262627 for disabled checked, #737373 for disabled unchecked\n }\n\n if (currentState === 'focused') {\n return 'text-text-900'; // #262627 for focused (both checked and unchecked)\n }\n\n return checked ? 'text-text-900' : 'text-text-600'; // #262627 for checked, #737373 for unchecked\n };\n\n // Determine cursor class based on disabled state\n const getCursorClass = () => {\n return currentState === 'disabled'\n ? 'cursor-not-allowed'\n : 'cursor-pointer';\n };\n\n return (\n <div className=\"flex flex-col\">\n <div\n className={`flex flex-row items-center ${\n isWrapperNeeded\n ? `p-1 border-2 ${wrapperBorderColor} rounded-lg gap-1.5` // Wrapper apenas para focused/invalid\n : sizeClasses.spacing\n } ${disabled ? 'opacity-40' : ''}`}\n >\n {/* Hidden native input for accessibility and form submission */}\n <input\n ref={ref}\n type=\"radio\"\n id={inputId}\n checked={checked}\n disabled={disabled}\n name={name}\n value={value}\n onChange={handleChange}\n className=\"sr-only\"\n {...props}\n />\n\n {/* Custom styled radio */}\n <label htmlFor={inputId} className={radioClasses}>\n {/* Show dot when checked */}\n {checked && <div className={dotClasses} />}\n </label>\n\n {/* Label text */}\n {label && (\n <div\n className={`flex flex-row items-center ${sizeClasses.labelHeight}`}\n >\n <Text\n as=\"label\"\n htmlFor={inputId}\n size={sizeClasses.textSize}\n weight=\"normal\"\n className={`${getCursorClass()} select-none leading-normal flex items-center font-roboto ${labelClassName}`}\n color={getTextColor()}\n >\n {label}\n </Text>\n </div>\n )}\n </div>\n\n {/* Error message */}\n {errorMessage && (\n <Text\n size=\"sm\"\n weight=\"normal\"\n className=\"mt-1.5\"\n color=\"text-error-600\"\n >\n {errorMessage}\n </Text>\n )}\n\n {/* Helper text */}\n {helperText && !errorMessage && (\n <Text\n size=\"sm\"\n weight=\"normal\"\n className=\"mt-1.5\"\n color=\"text-text-500\"\n >\n {helperText}\n </Text>\n )}\n </div>\n );\n }\n);\n\nRadio.displayName = 'Radio';\n\nexport default Radio;\n","import { ComponentPropsWithoutRef, ElementType, ReactNode } from 'react';\n\n/**\n * Base text component props\n */\ntype BaseTextProps = {\n /** Content to be displayed */\n children?: ReactNode;\n /** Text size variant */\n size?:\n | '2xs'\n | 'xs'\n | 'sm'\n | 'md'\n | 'lg'\n | 'xl'\n | '2xl'\n | '3xl'\n | '4xl'\n | '5xl'\n | '6xl';\n /** Font weight variant */\n weight?:\n | 'hairline'\n | 'light'\n | 'normal'\n | 'medium'\n | 'semibold'\n | 'bold'\n | 'extrabold'\n | 'black';\n /** Color variant - white for light backgrounds, black for dark backgrounds */\n color?: string;\n /** Additional CSS classes to apply */\n className?: string;\n};\n\n/**\n * Polymorphic text component props that ensures type safety based on the 'as' prop\n */\ntype TextProps<T extends ElementType = 'p'> = BaseTextProps & {\n /** HTML tag to render */\n as?: T;\n} & Omit<ComponentPropsWithoutRef<T>, keyof BaseTextProps>;\n\n/**\n * Text component for Analytica Ensino platforms\n *\n * A flexible polymorphic text component with multiple sizes, weights, and colors.\n * Automatically adapts to dark and light themes with full type safety.\n * Fully compatible with Next.js 15 and React 19.\n *\n * @param children - The content to display\n * @param size - The text size variant (2xs, xs, sm, md, lg, xl, 2xl, 3xl, 4xl, 5xl, 6xl)\n * @param weight - The font weight variant (hairline, light, normal, medium, semibold, bold, extrabold, black)\n * @param color - The color variant - adapts to theme\n * @param as - The HTML tag to render - determines allowed attributes via TypeScript\n * @param className - Additional CSS classes\n * @param props - HTML attributes valid for the chosen tag only\n * @returns A styled text element with type-safe attributes\n *\n * @example\n * ```tsx\n * <Text size=\"lg\" weight=\"bold\" color=\"text-info-800\">\n * This is a large, bold text\n * </Text>\n *\n * <Text as=\"a\" href=\"/link\" target=\"_blank\">\n * Link with type-safe anchor attributes\n * </Text>\n *\n * <Text as=\"button\" onClick={handleClick} disabled>\n * Button with type-safe button attributes\n * </Text>\n * ```\n */\nconst Text = <T extends ElementType = 'p'>({\n children,\n size = 'md',\n weight = 'normal',\n color = 'text-text-950',\n as,\n className = '',\n ...props\n}: TextProps<T>) => {\n let sizeClasses = '';\n let weightClasses = '';\n\n // Text size classes mapping\n const sizeClassMap = {\n '2xs': 'text-2xs',\n xs: 'text-xs',\n sm: 'text-sm',\n md: 'text-md',\n lg: 'text-lg',\n xl: 'text-xl',\n '2xl': 'text-2xl',\n '3xl': 'text-3xl',\n '4xl': 'text-4xl',\n '5xl': 'text-5xl',\n '6xl': 'text-6xl',\n } as const;\n\n sizeClasses = sizeClassMap[size] ?? sizeClassMap.md;\n\n // Font weight classes mapping\n const weightClassMap = {\n hairline: 'font-hairline',\n light: 'font-light',\n normal: 'font-normal',\n medium: 'font-medium',\n semibold: 'font-semibold',\n bold: 'font-bold',\n extrabold: 'font-extrabold',\n black: 'font-black',\n } as const;\n\n weightClasses = weightClassMap[weight] ?? weightClassMap.normal;\n\n const baseClasses = 'font-primary';\n const Component = as ?? ('p' as ElementType);\n\n return (\n <Component\n className={`${baseClasses} ${sizeClasses} ${weightClasses} ${color} ${className}`}\n {...props}\n >\n {children}\n </Component>\n );\n};\n\nexport default Text;\n"],"mappings":"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","names":["import_jsx_runtime"]}
|
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// src/components/Radio/Radio.tsx
|
|
4
|
+
import {
|
|
5
|
+
forwardRef,
|
|
6
|
+
useState,
|
|
7
|
+
useId
|
|
8
|
+
} from "react";
|
|
9
|
+
|
|
10
|
+
// src/components/Text/Text.tsx
|
|
11
|
+
import { jsx } from "react/jsx-runtime";
|
|
12
|
+
var Text = ({
|
|
13
|
+
children,
|
|
14
|
+
size = "md",
|
|
15
|
+
weight = "normal",
|
|
16
|
+
color = "text-text-950",
|
|
17
|
+
as,
|
|
18
|
+
className = "",
|
|
19
|
+
...props
|
|
20
|
+
}) => {
|
|
21
|
+
let sizeClasses = "";
|
|
22
|
+
let weightClasses = "";
|
|
23
|
+
const sizeClassMap = {
|
|
24
|
+
"2xs": "text-2xs",
|
|
25
|
+
xs: "text-xs",
|
|
26
|
+
sm: "text-sm",
|
|
27
|
+
md: "text-md",
|
|
28
|
+
lg: "text-lg",
|
|
29
|
+
xl: "text-xl",
|
|
30
|
+
"2xl": "text-2xl",
|
|
31
|
+
"3xl": "text-3xl",
|
|
32
|
+
"4xl": "text-4xl",
|
|
33
|
+
"5xl": "text-5xl",
|
|
34
|
+
"6xl": "text-6xl"
|
|
35
|
+
};
|
|
36
|
+
sizeClasses = sizeClassMap[size] ?? sizeClassMap.md;
|
|
37
|
+
const weightClassMap = {
|
|
38
|
+
hairline: "font-hairline",
|
|
39
|
+
light: "font-light",
|
|
40
|
+
normal: "font-normal",
|
|
41
|
+
medium: "font-medium",
|
|
42
|
+
semibold: "font-semibold",
|
|
43
|
+
bold: "font-bold",
|
|
44
|
+
extrabold: "font-extrabold",
|
|
45
|
+
black: "font-black"
|
|
46
|
+
};
|
|
47
|
+
weightClasses = weightClassMap[weight] ?? weightClassMap.normal;
|
|
48
|
+
const baseClasses = "font-primary";
|
|
49
|
+
const Component = as ?? "p";
|
|
50
|
+
return /* @__PURE__ */ jsx(
|
|
51
|
+
Component,
|
|
52
|
+
{
|
|
53
|
+
className: `${baseClasses} ${sizeClasses} ${weightClasses} ${color} ${className}`,
|
|
54
|
+
...props,
|
|
55
|
+
children
|
|
56
|
+
}
|
|
57
|
+
);
|
|
58
|
+
};
|
|
59
|
+
var Text_default = Text;
|
|
60
|
+
|
|
61
|
+
// src/components/Radio/Radio.tsx
|
|
62
|
+
import { jsx as jsx2, jsxs } from "react/jsx-runtime";
|
|
63
|
+
var SIZE_CLASSES = {
|
|
64
|
+
small: {
|
|
65
|
+
radio: "w-5 h-5",
|
|
66
|
+
// 20px x 20px
|
|
67
|
+
textSize: "sm",
|
|
68
|
+
spacing: "gap-1.5",
|
|
69
|
+
// 6px
|
|
70
|
+
borderWidth: "border-2",
|
|
71
|
+
dotSize: "w-1.5 h-1.5",
|
|
72
|
+
// 6px inner dot
|
|
73
|
+
labelHeight: "h-5"
|
|
74
|
+
},
|
|
75
|
+
medium: {
|
|
76
|
+
radio: "w-6 h-6",
|
|
77
|
+
// 24px x 24px
|
|
78
|
+
textSize: "md",
|
|
79
|
+
spacing: "gap-2",
|
|
80
|
+
// 8px
|
|
81
|
+
borderWidth: "border-2",
|
|
82
|
+
dotSize: "w-2 h-2",
|
|
83
|
+
// 8px inner dot
|
|
84
|
+
labelHeight: "h-6"
|
|
85
|
+
},
|
|
86
|
+
large: {
|
|
87
|
+
radio: "w-7 h-7",
|
|
88
|
+
// 28px x 28px
|
|
89
|
+
textSize: "lg",
|
|
90
|
+
spacing: "gap-2",
|
|
91
|
+
// 8px
|
|
92
|
+
borderWidth: "border-2",
|
|
93
|
+
// 2px border (consistent with others)
|
|
94
|
+
dotSize: "w-2.5 h-2.5",
|
|
95
|
+
// 10px inner dot
|
|
96
|
+
labelHeight: "h-7"
|
|
97
|
+
},
|
|
98
|
+
extraLarge: {
|
|
99
|
+
radio: "w-8 h-8",
|
|
100
|
+
// 32px x 32px (larger than large)
|
|
101
|
+
textSize: "xl",
|
|
102
|
+
spacing: "gap-3",
|
|
103
|
+
// 12px
|
|
104
|
+
borderWidth: "border-2",
|
|
105
|
+
// 2px border (consistent with others)
|
|
106
|
+
dotSize: "w-3 h-3",
|
|
107
|
+
// 12px inner dot
|
|
108
|
+
labelHeight: "h-8"
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
var BASE_RADIO_CLASSES = "rounded-full border cursor-pointer transition-all duration-200 flex items-center justify-center focus:outline-none";
|
|
112
|
+
var STATE_CLASSES = {
|
|
113
|
+
default: {
|
|
114
|
+
unchecked: "border-border-400 bg-background hover:border-border-500",
|
|
115
|
+
checked: "border-primary-950 bg-background hover:border-primary-800"
|
|
116
|
+
},
|
|
117
|
+
hovered: {
|
|
118
|
+
unchecked: "border-border-500 bg-background",
|
|
119
|
+
// #8C8D8D hover state for unchecked
|
|
120
|
+
checked: "border-info-700 bg-background"
|
|
121
|
+
// Adjust checked border for hover
|
|
122
|
+
},
|
|
123
|
+
focused: {
|
|
124
|
+
unchecked: "border-border-400 bg-background",
|
|
125
|
+
// #A5A3A3 for unchecked radio
|
|
126
|
+
checked: "border-primary-950 bg-background"
|
|
127
|
+
// #124393 for checked radio
|
|
128
|
+
},
|
|
129
|
+
invalid: {
|
|
130
|
+
unchecked: "border-border-400 bg-background",
|
|
131
|
+
// #A5A3A3 for unchecked radio
|
|
132
|
+
checked: "border-primary-950 bg-background"
|
|
133
|
+
// #124393 for checked radio
|
|
134
|
+
},
|
|
135
|
+
disabled: {
|
|
136
|
+
unchecked: "border-border-400 bg-background cursor-not-allowed",
|
|
137
|
+
// #A5A3A3 for unchecked radio
|
|
138
|
+
checked: "border-primary-950 bg-background cursor-not-allowed"
|
|
139
|
+
// #124393 for checked radio
|
|
140
|
+
}
|
|
141
|
+
};
|
|
142
|
+
var DOT_CLASSES = {
|
|
143
|
+
default: "bg-primary-950",
|
|
144
|
+
hovered: "bg-info-700",
|
|
145
|
+
// #1C61B2 hover state for checked dot
|
|
146
|
+
focused: "bg-primary-950",
|
|
147
|
+
// #124393 for focused checked dot
|
|
148
|
+
invalid: "bg-primary-950",
|
|
149
|
+
// #124393 for invalid checked dot
|
|
150
|
+
disabled: "bg-primary-950"
|
|
151
|
+
// #124393 for disabled checked dot
|
|
152
|
+
};
|
|
153
|
+
var Radio = forwardRef(
|
|
154
|
+
({
|
|
155
|
+
label,
|
|
156
|
+
size = "medium",
|
|
157
|
+
state = "default",
|
|
158
|
+
errorMessage,
|
|
159
|
+
helperText,
|
|
160
|
+
className = "",
|
|
161
|
+
labelClassName = "",
|
|
162
|
+
checked: checkedProp,
|
|
163
|
+
defaultChecked = false,
|
|
164
|
+
disabled,
|
|
165
|
+
id,
|
|
166
|
+
name,
|
|
167
|
+
value,
|
|
168
|
+
onChange,
|
|
169
|
+
...props
|
|
170
|
+
}, ref) => {
|
|
171
|
+
const generatedId = useId();
|
|
172
|
+
const inputId = id ?? `radio-${generatedId}`;
|
|
173
|
+
const [internalChecked, setInternalChecked] = useState(defaultChecked);
|
|
174
|
+
const isControlled = checkedProp !== void 0;
|
|
175
|
+
const checked = isControlled ? checkedProp : internalChecked;
|
|
176
|
+
const handleChange = (event) => {
|
|
177
|
+
const newChecked = event.target.checked;
|
|
178
|
+
if (!isControlled) {
|
|
179
|
+
setInternalChecked(newChecked);
|
|
180
|
+
}
|
|
181
|
+
onChange?.(event);
|
|
182
|
+
};
|
|
183
|
+
const currentState = disabled ? "disabled" : state;
|
|
184
|
+
const sizeClasses = SIZE_CLASSES[size];
|
|
185
|
+
const actualRadioSize = sizeClasses.radio;
|
|
186
|
+
const actualDotSize = sizeClasses.dotSize;
|
|
187
|
+
const radioVariant = checked ? "checked" : "unchecked";
|
|
188
|
+
const stylingClasses = STATE_CLASSES[currentState][radioVariant];
|
|
189
|
+
const getBorderWidth = () => {
|
|
190
|
+
if (currentState === "focused") {
|
|
191
|
+
return "border-2";
|
|
192
|
+
}
|
|
193
|
+
return sizeClasses.borderWidth;
|
|
194
|
+
};
|
|
195
|
+
const borderWidthClass = getBorderWidth();
|
|
196
|
+
const radioClasses = `${BASE_RADIO_CLASSES} ${actualRadioSize} ${borderWidthClass} ${stylingClasses} ${className}`;
|
|
197
|
+
const dotClasses = `${actualDotSize} rounded-full ${DOT_CLASSES[currentState]} transition-all duration-200`;
|
|
198
|
+
const isWrapperNeeded = currentState === "focused" || currentState === "invalid";
|
|
199
|
+
const wrapperBorderColor = currentState === "focused" ? "border-indicator-info" : "border-indicator-error";
|
|
200
|
+
const getTextColor = () => {
|
|
201
|
+
if (currentState === "disabled") {
|
|
202
|
+
return checked ? "text-text-900" : "text-text-600";
|
|
203
|
+
}
|
|
204
|
+
if (currentState === "focused") {
|
|
205
|
+
return "text-text-900";
|
|
206
|
+
}
|
|
207
|
+
return checked ? "text-text-900" : "text-text-600";
|
|
208
|
+
};
|
|
209
|
+
const getCursorClass = () => {
|
|
210
|
+
return currentState === "disabled" ? "cursor-not-allowed" : "cursor-pointer";
|
|
211
|
+
};
|
|
212
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
|
|
213
|
+
/* @__PURE__ */ jsxs(
|
|
214
|
+
"div",
|
|
215
|
+
{
|
|
216
|
+
className: `flex flex-row items-center ${isWrapperNeeded ? `p-1 border-2 ${wrapperBorderColor} rounded-lg gap-1.5` : sizeClasses.spacing} ${disabled ? "opacity-40" : ""}`,
|
|
217
|
+
children: [
|
|
218
|
+
/* @__PURE__ */ jsx2(
|
|
219
|
+
"input",
|
|
220
|
+
{
|
|
221
|
+
ref,
|
|
222
|
+
type: "radio",
|
|
223
|
+
id: inputId,
|
|
224
|
+
checked,
|
|
225
|
+
disabled,
|
|
226
|
+
name,
|
|
227
|
+
value,
|
|
228
|
+
onChange: handleChange,
|
|
229
|
+
className: "sr-only",
|
|
230
|
+
...props
|
|
231
|
+
}
|
|
232
|
+
),
|
|
233
|
+
/* @__PURE__ */ jsx2("label", { htmlFor: inputId, className: radioClasses, children: checked && /* @__PURE__ */ jsx2("div", { className: dotClasses }) }),
|
|
234
|
+
label && /* @__PURE__ */ jsx2(
|
|
235
|
+
"div",
|
|
236
|
+
{
|
|
237
|
+
className: `flex flex-row items-center ${sizeClasses.labelHeight}`,
|
|
238
|
+
children: /* @__PURE__ */ jsx2(
|
|
239
|
+
Text_default,
|
|
240
|
+
{
|
|
241
|
+
as: "label",
|
|
242
|
+
htmlFor: inputId,
|
|
243
|
+
size: sizeClasses.textSize,
|
|
244
|
+
weight: "normal",
|
|
245
|
+
className: `${getCursorClass()} select-none leading-normal flex items-center font-roboto ${labelClassName}`,
|
|
246
|
+
color: getTextColor(),
|
|
247
|
+
children: label
|
|
248
|
+
}
|
|
249
|
+
)
|
|
250
|
+
}
|
|
251
|
+
)
|
|
252
|
+
]
|
|
253
|
+
}
|
|
254
|
+
),
|
|
255
|
+
errorMessage && /* @__PURE__ */ jsx2(
|
|
256
|
+
Text_default,
|
|
257
|
+
{
|
|
258
|
+
size: "sm",
|
|
259
|
+
weight: "normal",
|
|
260
|
+
className: "mt-1.5",
|
|
261
|
+
color: "text-error-600",
|
|
262
|
+
children: errorMessage
|
|
263
|
+
}
|
|
264
|
+
),
|
|
265
|
+
helperText && !errorMessage && /* @__PURE__ */ jsx2(
|
|
266
|
+
Text_default,
|
|
267
|
+
{
|
|
268
|
+
size: "sm",
|
|
269
|
+
weight: "normal",
|
|
270
|
+
className: "mt-1.5",
|
|
271
|
+
color: "text-text-500",
|
|
272
|
+
children: helperText
|
|
273
|
+
}
|
|
274
|
+
)
|
|
275
|
+
] });
|
|
276
|
+
}
|
|
277
|
+
);
|
|
278
|
+
Radio.displayName = "Radio";
|
|
279
|
+
var Radio_default = Radio;
|
|
280
|
+
export {
|
|
281
|
+
Radio_default as default
|
|
282
|
+
};
|
|
283
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/components/Radio/Radio.tsx","../../src/components/Text/Text.tsx"],"sourcesContent":["'use client';\n\nimport {\n InputHTMLAttributes,\n ReactNode,\n forwardRef,\n useState,\n useId,\n ChangeEvent,\n} from 'react';\nimport Text from '../Text/Text';\n\n/**\n * Radio size variants\n */\ntype RadioSize = 'small' | 'medium' | 'large' | 'extraLarge';\n\n/**\n * Radio visual state\n */\ntype RadioState = 'default' | 'hovered' | 'focused' | 'invalid' | 'disabled';\n\n/**\n * Size configurations using Tailwind classes\n */\nconst SIZE_CLASSES = {\n small: {\n radio: 'w-5 h-5', // 20px x 20px\n textSize: 'sm' as const,\n spacing: 'gap-1.5', // 6px\n borderWidth: 'border-2',\n dotSize: 'w-1.5 h-1.5', // 6px inner dot\n labelHeight: 'h-5',\n },\n medium: {\n radio: 'w-6 h-6', // 24px x 24px\n textSize: 'md' as const,\n spacing: 'gap-2', // 8px\n borderWidth: 'border-2',\n dotSize: 'w-2 h-2', // 8px inner dot\n labelHeight: 'h-6',\n },\n large: {\n radio: 'w-7 h-7', // 28px x 28px\n textSize: 'lg' as const,\n spacing: 'gap-2', // 8px\n borderWidth: 'border-2', // 2px border (consistent with others)\n dotSize: 'w-2.5 h-2.5', // 10px inner dot\n labelHeight: 'h-7',\n },\n extraLarge: {\n radio: 'w-8 h-8', // 32px x 32px (larger than large)\n textSize: 'xl' as const,\n spacing: 'gap-3', // 12px\n borderWidth: 'border-2', // 2px border (consistent with others)\n dotSize: 'w-3 h-3', // 12px inner dot\n labelHeight: 'h-8',\n },\n} as const;\n\n/**\n * Focused state maintains the same sizes as default state\n * Only adds wrapper styling, does not change radio/dot sizes\n */\n\n/**\n * Base radio styling classes using design system colors\n */\nconst BASE_RADIO_CLASSES =\n 'rounded-full border cursor-pointer transition-all duration-200 flex items-center justify-center focus:outline-none';\n\n/**\n * State-based styling classes using design system colors from styles.css\n */\nconst STATE_CLASSES = {\n default: {\n unchecked: 'border-border-400 bg-background hover:border-border-500',\n checked: 'border-primary-950 bg-background hover:border-primary-800',\n },\n hovered: {\n unchecked: 'border-border-500 bg-background', // #8C8D8D hover state for unchecked\n checked: 'border-info-700 bg-background', // Adjust checked border for hover\n },\n focused: {\n unchecked: 'border-border-400 bg-background', // #A5A3A3 for unchecked radio\n checked: 'border-primary-950 bg-background', // #124393 for checked radio\n },\n invalid: {\n unchecked: 'border-border-400 bg-background', // #A5A3A3 for unchecked radio\n checked: 'border-primary-950 bg-background', // #124393 for checked radio\n },\n disabled: {\n unchecked: 'border-border-400 bg-background cursor-not-allowed', // #A5A3A3 for unchecked radio\n checked: 'border-primary-950 bg-background cursor-not-allowed', // #124393 for checked radio\n },\n} as const;\n\n/**\n * Dot styling classes for the inner dot when checked\n */\nconst DOT_CLASSES = {\n default: 'bg-primary-950',\n hovered: 'bg-info-700', // #1C61B2 hover state for checked dot\n focused: 'bg-primary-950', // #124393 for focused checked dot\n invalid: 'bg-primary-950', // #124393 for invalid checked dot\n disabled: 'bg-primary-950', // #124393 for disabled checked dot\n} as const;\n\n/**\n * Radio component props interface\n */\nexport type RadioProps = {\n /** Label text to display next to the radio */\n label?: ReactNode;\n /** Size variant of the radio */\n size?: RadioSize;\n /** Visual state of the radio */\n state?: RadioState;\n /** Error message to display */\n errorMessage?: string;\n /** Helper text to display */\n helperText?: string;\n /** Additional CSS classes */\n className?: string;\n /** Label CSS classes */\n labelClassName?: string;\n /** Radio group name */\n name?: string;\n /** Radio value */\n value?: string;\n /** Default checked state for uncontrolled radios */\n defaultChecked?: boolean;\n} & Omit<\n InputHTMLAttributes<HTMLInputElement>,\n 'size' | 'type' | 'defaultChecked'\n>;\n\n/**\n * Radio component for Analytica Ensino platforms\n *\n * A radio button component with essential states, sizes and themes.\n * Uses the Analytica Ensino Design System colors from styles.css with automatic\n * light/dark mode support. Includes Text component integration for consistent typography.\n *\n * @example\n * ```tsx\n * // Basic radio\n * <Radio name=\"option\" value=\"1\" label=\"Option 1\" />\n *\n * // Small size\n * <Radio size=\"small\" name=\"option\" value=\"2\" label=\"Small option\" />\n *\n * // Invalid state\n * <Radio state=\"invalid\" name=\"option\" value=\"3\" label=\"Required field\" />\n *\n * // Disabled state\n * <Radio disabled name=\"option\" value=\"4\" label=\"Disabled option\" />\n *\n * // Default checked (uncontrolled)\n * <Radio defaultChecked name=\"option\" value=\"5\" label=\"Initially checked\" />\n * ```\n */\nconst Radio = forwardRef<HTMLInputElement, RadioProps>(\n (\n {\n label,\n size = 'medium',\n state = 'default',\n errorMessage,\n helperText,\n className = '',\n labelClassName = '',\n checked: checkedProp,\n defaultChecked = false,\n disabled,\n id,\n name,\n value,\n onChange,\n ...props\n },\n ref\n ) => {\n // Generate unique ID if not provided\n const generatedId = useId();\n const inputId = id ?? `radio-${generatedId}`;\n\n // Handle controlled vs uncontrolled behavior\n const [internalChecked, setInternalChecked] = useState(defaultChecked);\n const isControlled = checkedProp !== undefined;\n const checked = isControlled ? checkedProp : internalChecked;\n\n // Handle change events\n const handleChange = (event: ChangeEvent<HTMLInputElement>) => {\n const newChecked = event.target.checked;\n\n if (!isControlled) {\n setInternalChecked(newChecked);\n }\n\n onChange?.(event);\n };\n\n // Determine current state based on props\n const currentState = disabled ? 'disabled' : state;\n\n // Get size classes\n const sizeClasses = SIZE_CLASSES[size];\n\n // Focused state maintains original sizes, only adds wrapper\n const actualRadioSize = sizeClasses.radio;\n const actualDotSize = sizeClasses.dotSize;\n\n // Determine radio visual variant\n const radioVariant = checked ? 'checked' : 'unchecked';\n\n // Get styling classes\n const stylingClasses = STATE_CLASSES[currentState][radioVariant];\n\n // Border width logic - consistent across all states and sizes\n const getBorderWidth = () => {\n if (currentState === 'focused') {\n return 'border-2'; // Consistent border for all focused radios inside wrapper\n }\n return sizeClasses.borderWidth;\n };\n\n const borderWidthClass = getBorderWidth();\n\n // Get final radio classes\n const radioClasses = `${BASE_RADIO_CLASSES} ${actualRadioSize} ${borderWidthClass} ${stylingClasses} ${className}`;\n\n // Get dot classes\n const dotClasses = `${actualDotSize} rounded-full ${DOT_CLASSES[currentState]} transition-all duration-200`;\n\n // Determine if wrapper is needed only for focused or invalid states\n const isWrapperNeeded =\n currentState === 'focused' || currentState === 'invalid';\n const wrapperBorderColor =\n currentState === 'focused'\n ? 'border-indicator-info' // #5399EC for focused\n : 'border-indicator-error'; // #B91C1C for invalid\n\n // Determine text color based on state and checked status\n const getTextColor = () => {\n if (currentState === 'disabled') {\n return checked ? 'text-text-900' : 'text-text-600'; // #262627 for disabled checked, #737373 for disabled unchecked\n }\n\n if (currentState === 'focused') {\n return 'text-text-900'; // #262627 for focused (both checked and unchecked)\n }\n\n return checked ? 'text-text-900' : 'text-text-600'; // #262627 for checked, #737373 for unchecked\n };\n\n // Determine cursor class based on disabled state\n const getCursorClass = () => {\n return currentState === 'disabled'\n ? 'cursor-not-allowed'\n : 'cursor-pointer';\n };\n\n return (\n <div className=\"flex flex-col\">\n <div\n className={`flex flex-row items-center ${\n isWrapperNeeded\n ? `p-1 border-2 ${wrapperBorderColor} rounded-lg gap-1.5` // Wrapper apenas para focused/invalid\n : sizeClasses.spacing\n } ${disabled ? 'opacity-40' : ''}`}\n >\n {/* Hidden native input for accessibility and form submission */}\n <input\n ref={ref}\n type=\"radio\"\n id={inputId}\n checked={checked}\n disabled={disabled}\n name={name}\n value={value}\n onChange={handleChange}\n className=\"sr-only\"\n {...props}\n />\n\n {/* Custom styled radio */}\n <label htmlFor={inputId} className={radioClasses}>\n {/* Show dot when checked */}\n {checked && <div className={dotClasses} />}\n </label>\n\n {/* Label text */}\n {label && (\n <div\n className={`flex flex-row items-center ${sizeClasses.labelHeight}`}\n >\n <Text\n as=\"label\"\n htmlFor={inputId}\n size={sizeClasses.textSize}\n weight=\"normal\"\n className={`${getCursorClass()} select-none leading-normal flex items-center font-roboto ${labelClassName}`}\n color={getTextColor()}\n >\n {label}\n </Text>\n </div>\n )}\n </div>\n\n {/* Error message */}\n {errorMessage && (\n <Text\n size=\"sm\"\n weight=\"normal\"\n className=\"mt-1.5\"\n color=\"text-error-600\"\n >\n {errorMessage}\n </Text>\n )}\n\n {/* Helper text */}\n {helperText && !errorMessage && (\n <Text\n size=\"sm\"\n weight=\"normal\"\n className=\"mt-1.5\"\n color=\"text-text-500\"\n >\n {helperText}\n </Text>\n )}\n </div>\n );\n }\n);\n\nRadio.displayName = 'Radio';\n\nexport default Radio;\n","import { ComponentPropsWithoutRef, ElementType, ReactNode } from 'react';\n\n/**\n * Base text component props\n */\ntype BaseTextProps = {\n /** Content to be displayed */\n children?: ReactNode;\n /** Text size variant */\n size?:\n | '2xs'\n | 'xs'\n | 'sm'\n | 'md'\n | 'lg'\n | 'xl'\n | '2xl'\n | '3xl'\n | '4xl'\n | '5xl'\n | '6xl';\n /** Font weight variant */\n weight?:\n | 'hairline'\n | 'light'\n | 'normal'\n | 'medium'\n | 'semibold'\n | 'bold'\n | 'extrabold'\n | 'black';\n /** Color variant - white for light backgrounds, black for dark backgrounds */\n color?: string;\n /** Additional CSS classes to apply */\n className?: string;\n};\n\n/**\n * Polymorphic text component props that ensures type safety based on the 'as' prop\n */\ntype TextProps<T extends ElementType = 'p'> = BaseTextProps & {\n /** HTML tag to render */\n as?: T;\n} & Omit<ComponentPropsWithoutRef<T>, keyof BaseTextProps>;\n\n/**\n * Text component for Analytica Ensino platforms\n *\n * A flexible polymorphic text component with multiple sizes, weights, and colors.\n * Automatically adapts to dark and light themes with full type safety.\n * Fully compatible with Next.js 15 and React 19.\n *\n * @param children - The content to display\n * @param size - The text size variant (2xs, xs, sm, md, lg, xl, 2xl, 3xl, 4xl, 5xl, 6xl)\n * @param weight - The font weight variant (hairline, light, normal, medium, semibold, bold, extrabold, black)\n * @param color - The color variant - adapts to theme\n * @param as - The HTML tag to render - determines allowed attributes via TypeScript\n * @param className - Additional CSS classes\n * @param props - HTML attributes valid for the chosen tag only\n * @returns A styled text element with type-safe attributes\n *\n * @example\n * ```tsx\n * <Text size=\"lg\" weight=\"bold\" color=\"text-info-800\">\n * This is a large, bold text\n * </Text>\n *\n * <Text as=\"a\" href=\"/link\" target=\"_blank\">\n * Link with type-safe anchor attributes\n * </Text>\n *\n * <Text as=\"button\" onClick={handleClick} disabled>\n * Button with type-safe button attributes\n * </Text>\n * ```\n */\nconst Text = <T extends ElementType = 'p'>({\n children,\n size = 'md',\n weight = 'normal',\n color = 'text-text-950',\n as,\n className = '',\n ...props\n}: TextProps<T>) => {\n let sizeClasses = '';\n let weightClasses = '';\n\n // Text size classes mapping\n const sizeClassMap = {\n '2xs': 'text-2xs',\n xs: 'text-xs',\n sm: 'text-sm',\n md: 'text-md',\n lg: 'text-lg',\n xl: 'text-xl',\n '2xl': 'text-2xl',\n '3xl': 'text-3xl',\n '4xl': 'text-4xl',\n '5xl': 'text-5xl',\n '6xl': 'text-6xl',\n } as const;\n\n sizeClasses = sizeClassMap[size] ?? sizeClassMap.md;\n\n // Font weight classes mapping\n const weightClassMap = {\n hairline: 'font-hairline',\n light: 'font-light',\n normal: 'font-normal',\n medium: 'font-medium',\n semibold: 'font-semibold',\n bold: 'font-bold',\n extrabold: 'font-extrabold',\n black: 'font-black',\n } as const;\n\n weightClasses = weightClassMap[weight] ?? weightClassMap.normal;\n\n const baseClasses = 'font-primary';\n const Component = as ?? ('p' as ElementType);\n\n return (\n <Component\n className={`${baseClasses} ${sizeClasses} ${weightClasses} ${color} ${className}`}\n {...props}\n >\n {children}\n </Component>\n );\n};\n\nexport default Text;\n"],"mappings":"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","names":["jsx"]}
|