analytica-frontend-lib 1.0.38 → 1.0.40
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/README.md +1 -2
- package/dist/Alert/index.js.map +1 -1
- package/dist/Alert/index.mjs.map +1 -1
- package/dist/Badge/index.d.mts +0 -1
- package/dist/Badge/index.d.ts +0 -1
- package/dist/Badge/index.js.map +1 -1
- package/dist/Badge/index.mjs.map +1 -1
- package/dist/Button/index.d.mts +0 -1
- package/dist/Button/index.d.ts +0 -1
- package/dist/Button/index.js.map +1 -1
- package/dist/Button/index.mjs.map +1 -1
- package/dist/CheckBox/index.js +0 -1
- package/dist/CheckBox/index.js.map +1 -1
- package/dist/CheckBox/index.mjs +0 -2
- package/dist/CheckBox/index.mjs.map +1 -1
- package/dist/Chips/index.d.mts +41 -0
- package/dist/Chips/index.d.ts +41 -0
- package/dist/Chips/index.js +57 -0
- package/dist/Chips/index.js.map +1 -0
- package/dist/Chips/index.mjs +36 -0
- package/dist/Chips/index.mjs.map +1 -0
- package/dist/Divider/index.d.mts +32 -0
- package/dist/Divider/index.d.ts +32 -0
- package/dist/Divider/index.js +47 -0
- package/dist/Divider/index.js.map +1 -0
- package/dist/Divider/index.mjs +26 -0
- package/dist/Divider/index.mjs.map +1 -0
- package/dist/DropdownMenu/index.d.mts +3 -3
- package/dist/DropdownMenu/index.d.ts +3 -3
- package/dist/DropdownMenu/index.js +8 -9
- package/dist/DropdownMenu/index.js.map +1 -1
- package/dist/DropdownMenu/index.mjs +6 -8
- package/dist/DropdownMenu/index.mjs.map +1 -1
- package/dist/IconButton/index.d.mts +0 -1
- package/dist/IconButton/index.d.ts +0 -1
- package/dist/IconButton/index.js.map +1 -1
- package/dist/IconButton/index.mjs.map +1 -1
- package/dist/IconRoundedButton/index.d.mts +0 -1
- package/dist/IconRoundedButton/index.d.ts +0 -1
- package/dist/IconRoundedButton/index.js.map +1 -1
- package/dist/IconRoundedButton/index.mjs.map +1 -1
- package/dist/Input/index.d.mts +27 -0
- package/dist/Input/index.d.ts +27 -0
- package/dist/Input/index.js +184 -0
- package/dist/Input/index.js.map +1 -0
- package/dist/Input/index.mjs +168 -0
- package/dist/Input/index.mjs.map +1 -0
- package/dist/Menu/index.d.mts +41 -0
- package/dist/Menu/index.d.ts +41 -0
- package/dist/Menu/index.js +307 -0
- package/dist/Menu/index.js.map +1 -0
- package/dist/Menu/index.mjs +283 -0
- package/dist/Menu/index.mjs.map +1 -0
- package/dist/NavButton/index.d.mts +0 -1
- package/dist/NavButton/index.d.ts +0 -1
- package/dist/NavButton/index.js.map +1 -1
- package/dist/NavButton/index.mjs.map +1 -1
- package/dist/ProgressBar/index.js +0 -1
- package/dist/ProgressBar/index.js.map +1 -1
- package/dist/ProgressBar/index.mjs +0 -2
- package/dist/ProgressBar/index.mjs.map +1 -1
- package/dist/ProgressCircle/index.js +0 -1
- package/dist/ProgressCircle/index.js.map +1 -1
- package/dist/ProgressCircle/index.mjs +0 -2
- package/dist/ProgressCircle/index.mjs.map +1 -1
- package/dist/Radio/index.js +0 -1
- package/dist/Radio/index.js.map +1 -1
- package/dist/Radio/index.mjs +0 -2
- package/dist/Radio/index.mjs.map +1 -1
- package/dist/Select/index.js +0 -1
- package/dist/Select/index.js.map +1 -1
- package/dist/Select/index.mjs +0 -2
- package/dist/Select/index.mjs.map +1 -1
- package/dist/SelectionButton/index.d.mts +0 -1
- package/dist/SelectionButton/index.d.ts +0 -1
- package/dist/SelectionButton/index.js.map +1 -1
- package/dist/SelectionButton/index.mjs.map +1 -1
- package/dist/Text/index.d.mts +0 -1
- package/dist/Text/index.d.ts +0 -1
- package/dist/Text/index.js.map +1 -1
- package/dist/Text/index.mjs.map +1 -1
- package/dist/TextArea/index.js +0 -1
- package/dist/TextArea/index.js.map +1 -1
- package/dist/TextArea/index.mjs +0 -2
- package/dist/TextArea/index.mjs.map +1 -1
- package/dist/Toast/Toaster/index.js +0 -1
- package/dist/Toast/Toaster/index.js.map +1 -1
- package/dist/Toast/Toaster/index.mjs +0 -2
- package/dist/Toast/Toaster/index.mjs.map +1 -1
- package/dist/Toast/index.js +0 -1
- package/dist/Toast/index.js.map +1 -1
- package/dist/Toast/index.mjs +0 -2
- package/dist/Toast/index.mjs.map +1 -1
- package/dist/index.css +84 -0
- package/dist/index.css.map +1 -1
- package/dist/index.d.mts +7 -94
- package/dist/index.d.ts +7 -94
- package/dist/index.js +174 -4
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +179 -4
- package/dist/index.mjs.map +1 -1
- package/dist/styles.css +84 -0
- package/dist/styles.css.map +1 -1
- package/package.json +2 -5
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
// src/components/Menu/Menu.tsx
|
|
2
|
+
import { create, useStore } from "zustand";
|
|
3
|
+
import {
|
|
4
|
+
useEffect,
|
|
5
|
+
useRef,
|
|
6
|
+
forwardRef,
|
|
7
|
+
isValidElement,
|
|
8
|
+
Children,
|
|
9
|
+
cloneElement,
|
|
10
|
+
useState
|
|
11
|
+
} from "react";
|
|
12
|
+
import { CaretLeft, CaretRight } from "phosphor-react";
|
|
13
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
14
|
+
var createMenuStore = () => create((set) => ({
|
|
15
|
+
value: "",
|
|
16
|
+
setValue: (value) => set({ value })
|
|
17
|
+
}));
|
|
18
|
+
var useMenuStore = (externalStore) => {
|
|
19
|
+
if (!externalStore) throw new Error("MenuItem must be inside Menu");
|
|
20
|
+
return externalStore;
|
|
21
|
+
};
|
|
22
|
+
var VARIANT_CLASSES = {
|
|
23
|
+
menu: "bg-background shadow-soft-shadow-1",
|
|
24
|
+
menu2: "overflow-x-auto scroll-smooth",
|
|
25
|
+
breadcrumb: ""
|
|
26
|
+
};
|
|
27
|
+
var Menu = forwardRef(
|
|
28
|
+
({
|
|
29
|
+
className,
|
|
30
|
+
children,
|
|
31
|
+
defaultValue,
|
|
32
|
+
value: propValue,
|
|
33
|
+
variant = "menu",
|
|
34
|
+
onValueChange,
|
|
35
|
+
...props
|
|
36
|
+
}, ref) => {
|
|
37
|
+
const storeRef = useRef(null);
|
|
38
|
+
storeRef.current ??= createMenuStore();
|
|
39
|
+
const store = storeRef.current;
|
|
40
|
+
const { setValue, value } = useStore(store, (s) => s);
|
|
41
|
+
useEffect(() => {
|
|
42
|
+
setValue(propValue ?? defaultValue);
|
|
43
|
+
}, [defaultValue, propValue, setValue]);
|
|
44
|
+
useEffect(() => {
|
|
45
|
+
onValueChange?.(value);
|
|
46
|
+
}, [value, onValueChange]);
|
|
47
|
+
const baseClasses = "w-full flex flex-row items-center gap-2 py-2 px-6";
|
|
48
|
+
const variantClasses = VARIANT_CLASSES[variant];
|
|
49
|
+
return /* @__PURE__ */ jsx(
|
|
50
|
+
"ul",
|
|
51
|
+
{
|
|
52
|
+
ref,
|
|
53
|
+
className: `
|
|
54
|
+
${baseClasses}
|
|
55
|
+
${variantClasses}
|
|
56
|
+
${className ?? ""}
|
|
57
|
+
`,
|
|
58
|
+
style: variant === "menu2" ? { scrollbarWidth: "none", msOverflowStyle: "none" } : void 0,
|
|
59
|
+
...props,
|
|
60
|
+
children: injectStore(children, store)
|
|
61
|
+
}
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
);
|
|
65
|
+
Menu.displayName = "Menu";
|
|
66
|
+
var MenuItem = forwardRef(
|
|
67
|
+
({
|
|
68
|
+
className,
|
|
69
|
+
children,
|
|
70
|
+
value,
|
|
71
|
+
disabled = false,
|
|
72
|
+
store: externalStore,
|
|
73
|
+
variant = "menu",
|
|
74
|
+
...props
|
|
75
|
+
}, ref) => {
|
|
76
|
+
const store = useMenuStore(externalStore);
|
|
77
|
+
const { value: selectedValue, setValue } = useStore(store, (s) => s);
|
|
78
|
+
const handleClick = (e) => {
|
|
79
|
+
if (!disabled) setValue(value);
|
|
80
|
+
props.onClick?.(e);
|
|
81
|
+
};
|
|
82
|
+
const commonProps = {
|
|
83
|
+
role: "menuitem",
|
|
84
|
+
"aria-disabled": disabled,
|
|
85
|
+
ref,
|
|
86
|
+
onClick: handleClick,
|
|
87
|
+
onKeyDown: (e) => {
|
|
88
|
+
if (["Enter", " "].includes(e.key)) handleClick(e);
|
|
89
|
+
},
|
|
90
|
+
tabIndex: disabled ? -1 : 0,
|
|
91
|
+
...props
|
|
92
|
+
};
|
|
93
|
+
const variants = {
|
|
94
|
+
menu: /* @__PURE__ */ jsx(
|
|
95
|
+
"li",
|
|
96
|
+
{
|
|
97
|
+
"data-variant": "menu",
|
|
98
|
+
className: `
|
|
99
|
+
w-full flex flex-col gap-0.5 items-center py-1 px-2 rounded-sm font-medium text-xs
|
|
100
|
+
[&>svg]:size-6 cursor-pointer hover:bg-primary-600 hover:text-text
|
|
101
|
+
focus:outline-none focus:border-2-indicator-info focus:border-2
|
|
102
|
+
${selectedValue === value ? "bg-primary-50 text-primary-950" : "text-text-950"}
|
|
103
|
+
${className ?? ""}
|
|
104
|
+
`,
|
|
105
|
+
...commonProps,
|
|
106
|
+
children
|
|
107
|
+
}
|
|
108
|
+
),
|
|
109
|
+
menu2: /* @__PURE__ */ jsx(
|
|
110
|
+
"li",
|
|
111
|
+
{
|
|
112
|
+
"data-variant": "menu2",
|
|
113
|
+
className: `
|
|
114
|
+
flex flex-row items-center p-4 gap-2 border-b-2 border-transparent text-text-950 text-sx font-bold cursor-pointer
|
|
115
|
+
${selectedValue === value ? "border-b-primary-950" : ""}
|
|
116
|
+
`,
|
|
117
|
+
...commonProps,
|
|
118
|
+
children
|
|
119
|
+
}
|
|
120
|
+
),
|
|
121
|
+
breadcrumb: /* @__PURE__ */ jsx(
|
|
122
|
+
"li",
|
|
123
|
+
{
|
|
124
|
+
"data-variant": "breadcrumb",
|
|
125
|
+
className: `
|
|
126
|
+
p-2 rounded-lg hover:text-primary-600 cursor-pointer font-bold text-xs
|
|
127
|
+
focus:outline-none focus:border-indicator-info focus:border-2
|
|
128
|
+
${selectedValue === value ? "text-primary-950" : "text-text-600"}
|
|
129
|
+
${className ?? ""}
|
|
130
|
+
`,
|
|
131
|
+
...commonProps,
|
|
132
|
+
children: /* @__PURE__ */ jsx(
|
|
133
|
+
"span",
|
|
134
|
+
{
|
|
135
|
+
className: `
|
|
136
|
+
border-b border-text-600 hover:border-primary-600 text-inherit
|
|
137
|
+
${selectedValue === value ? "border-b-primary-950" : "border-b-primary-600"}
|
|
138
|
+
`,
|
|
139
|
+
children
|
|
140
|
+
}
|
|
141
|
+
)
|
|
142
|
+
}
|
|
143
|
+
)
|
|
144
|
+
};
|
|
145
|
+
return variants[variant] ?? variants["menu"];
|
|
146
|
+
}
|
|
147
|
+
);
|
|
148
|
+
MenuItem.displayName = "MenuItem";
|
|
149
|
+
var MenuItemIcon = ({
|
|
150
|
+
className,
|
|
151
|
+
icon,
|
|
152
|
+
...props
|
|
153
|
+
}) => /* @__PURE__ */ jsx(
|
|
154
|
+
"span",
|
|
155
|
+
{
|
|
156
|
+
className: `
|
|
157
|
+
bg-background-500 w-[21px] h-[21px] flex items-center justify-center
|
|
158
|
+
[&>svg]:w-[17px] [&>svg]:h-[17px] rounded-sm ${className ?? ""}
|
|
159
|
+
`,
|
|
160
|
+
...props,
|
|
161
|
+
children: icon
|
|
162
|
+
}
|
|
163
|
+
);
|
|
164
|
+
var MenuSeparator = forwardRef(
|
|
165
|
+
({ className, children, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
166
|
+
"li",
|
|
167
|
+
{
|
|
168
|
+
ref,
|
|
169
|
+
"aria-hidden": "true",
|
|
170
|
+
className: `[&>svg]:w-4 [&>svg]:h-4 text-text-600 ${className ?? ""}`,
|
|
171
|
+
...props,
|
|
172
|
+
children: children ?? /* @__PURE__ */ jsx(CaretRight, {})
|
|
173
|
+
}
|
|
174
|
+
)
|
|
175
|
+
);
|
|
176
|
+
MenuSeparator.displayName = "MenuSeparator";
|
|
177
|
+
var internalScroll = (container, direction) => {
|
|
178
|
+
if (!container) return;
|
|
179
|
+
container.scrollBy({
|
|
180
|
+
left: direction === "left" ? -150 : 150,
|
|
181
|
+
behavior: "smooth"
|
|
182
|
+
});
|
|
183
|
+
};
|
|
184
|
+
var internalCheckScroll = (container, setShowLeftArrow, setShowRightArrow) => {
|
|
185
|
+
if (!container) return;
|
|
186
|
+
const { scrollLeft, scrollWidth, clientWidth } = container;
|
|
187
|
+
setShowLeftArrow(scrollLeft > 0);
|
|
188
|
+
setShowRightArrow(scrollLeft + clientWidth < scrollWidth);
|
|
189
|
+
};
|
|
190
|
+
var MenuOverflow = ({
|
|
191
|
+
children,
|
|
192
|
+
className,
|
|
193
|
+
defaultValue,
|
|
194
|
+
value,
|
|
195
|
+
onValueChange,
|
|
196
|
+
...props
|
|
197
|
+
}) => {
|
|
198
|
+
const containerRef = useRef(null);
|
|
199
|
+
const [showLeftArrow, setShowLeftArrow] = useState(false);
|
|
200
|
+
const [showRightArrow, setShowRightArrow] = useState(false);
|
|
201
|
+
useEffect(() => {
|
|
202
|
+
const checkScroll = () => internalCheckScroll(
|
|
203
|
+
containerRef.current,
|
|
204
|
+
setShowLeftArrow,
|
|
205
|
+
setShowRightArrow
|
|
206
|
+
);
|
|
207
|
+
checkScroll();
|
|
208
|
+
const container = containerRef.current;
|
|
209
|
+
container?.addEventListener("scroll", checkScroll);
|
|
210
|
+
window.addEventListener("resize", checkScroll);
|
|
211
|
+
return () => {
|
|
212
|
+
container?.removeEventListener("scroll", checkScroll);
|
|
213
|
+
window.removeEventListener("resize", checkScroll);
|
|
214
|
+
};
|
|
215
|
+
}, []);
|
|
216
|
+
return /* @__PURE__ */ jsxs(
|
|
217
|
+
"div",
|
|
218
|
+
{
|
|
219
|
+
"data-testid": "menu-overflow-wrapper",
|
|
220
|
+
className: `relative w-full overflow-hidden ${className ?? ""}`,
|
|
221
|
+
children: [
|
|
222
|
+
showLeftArrow && /* @__PURE__ */ jsxs(
|
|
223
|
+
"button",
|
|
224
|
+
{
|
|
225
|
+
onClick: () => internalScroll(containerRef.current, "left"),
|
|
226
|
+
className: "absolute left-0 top-1/2 -translate-y-1/2 z-10 flex h-8 w-8 items-center justify-center rounded-full bg-white shadow-md",
|
|
227
|
+
"data-testid": "scroll-left-button",
|
|
228
|
+
children: [
|
|
229
|
+
/* @__PURE__ */ jsx(CaretLeft, { size: 16 }),
|
|
230
|
+
/* @__PURE__ */ jsx("span", { className: "sr-only", children: "Scroll left" })
|
|
231
|
+
]
|
|
232
|
+
}
|
|
233
|
+
),
|
|
234
|
+
/* @__PURE__ */ jsx(
|
|
235
|
+
Menu,
|
|
236
|
+
{
|
|
237
|
+
ref: containerRef,
|
|
238
|
+
variant: "menu2",
|
|
239
|
+
defaultValue,
|
|
240
|
+
onValueChange,
|
|
241
|
+
value,
|
|
242
|
+
...props,
|
|
243
|
+
children
|
|
244
|
+
}
|
|
245
|
+
),
|
|
246
|
+
showRightArrow && /* @__PURE__ */ jsxs(
|
|
247
|
+
"button",
|
|
248
|
+
{
|
|
249
|
+
onClick: () => internalScroll(containerRef.current, "right"),
|
|
250
|
+
className: "absolute right-0 top-1/2 -translate-y-1/2 z-10 flex h-8 w-8 items-center justify-center rounded-full bg-white shadow-md",
|
|
251
|
+
"data-testid": "scroll-right-button",
|
|
252
|
+
children: [
|
|
253
|
+
/* @__PURE__ */ jsx(CaretRight, { size: 16 }),
|
|
254
|
+
/* @__PURE__ */ jsx("span", { className: "sr-only", children: "Scroll right" })
|
|
255
|
+
]
|
|
256
|
+
}
|
|
257
|
+
)
|
|
258
|
+
]
|
|
259
|
+
}
|
|
260
|
+
);
|
|
261
|
+
};
|
|
262
|
+
var injectStore = (children, store) => Children.map(children, (child) => {
|
|
263
|
+
if (!isValidElement(child)) return child;
|
|
264
|
+
const typedChild = child;
|
|
265
|
+
const shouldInject = typedChild.type === MenuItem;
|
|
266
|
+
return cloneElement(typedChild, {
|
|
267
|
+
...shouldInject ? { store } : {},
|
|
268
|
+
...typedChild.props.children ? { children: injectStore(typedChild.props.children, store) } : {}
|
|
269
|
+
});
|
|
270
|
+
});
|
|
271
|
+
var Menu_default = Menu;
|
|
272
|
+
export {
|
|
273
|
+
Menu,
|
|
274
|
+
MenuItem,
|
|
275
|
+
MenuItemIcon,
|
|
276
|
+
MenuOverflow,
|
|
277
|
+
MenuSeparator,
|
|
278
|
+
Menu_default as default,
|
|
279
|
+
internalCheckScroll,
|
|
280
|
+
internalScroll,
|
|
281
|
+
useMenuStore
|
|
282
|
+
};
|
|
283
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/components/Menu/Menu.tsx"],"sourcesContent":["import { create, StoreApi, useStore } from 'zustand';\nimport {\n ReactNode,\n useEffect,\n useRef,\n forwardRef,\n HTMLAttributes,\n KeyboardEvent,\n MouseEvent,\n ReactElement,\n isValidElement,\n Children,\n cloneElement,\n useState,\n} from 'react';\nimport { CaretLeft, CaretRight } from 'phosphor-react';\n\ninterface MenuStore {\n value: string;\n setValue: (value: string) => void;\n}\n\ntype MenuStoreApi = StoreApi<MenuStore>;\n\nconst createMenuStore = (): MenuStoreApi =>\n create<MenuStore>((set) => ({\n value: '',\n setValue: (value) => set({ value }),\n }));\n\nexport const useMenuStore = (externalStore?: MenuStoreApi) => {\n if (!externalStore) throw new Error('MenuItem must be inside Menu');\n return externalStore;\n};\n\ninterface MenuProps extends HTMLAttributes<HTMLUListElement> {\n children: ReactNode;\n defaultValue: string;\n value?: string;\n variant?: 'menu' | 'menu2' | 'breadcrumb';\n onValueChange?: (value: string) => void;\n}\n\nconst VARIANT_CLASSES = {\n menu: 'bg-background shadow-soft-shadow-1',\n menu2: 'overflow-x-auto scroll-smooth',\n breadcrumb: '',\n};\n\nconst Menu = forwardRef<HTMLUListElement, MenuProps>(\n (\n {\n className,\n children,\n defaultValue,\n value: propValue,\n variant = 'menu',\n onValueChange,\n ...props\n },\n ref\n ) => {\n const storeRef = useRef<MenuStoreApi>(null);\n storeRef.current ??= createMenuStore();\n const store = storeRef.current;\n const { setValue, value } = useStore(store, (s) => s);\n\n useEffect(() => {\n setValue(propValue ?? defaultValue);\n }, [defaultValue, propValue, setValue]);\n\n useEffect(() => {\n onValueChange?.(value);\n }, [value, onValueChange]);\n\n const baseClasses = 'w-full flex flex-row items-center gap-2 py-2 px-6';\n\n const variantClasses = VARIANT_CLASSES[variant];\n\n return (\n <ul\n ref={ref}\n className={`\n ${baseClasses}\n ${variantClasses}\n ${className ?? ''}\n `}\n style={\n variant === 'menu2'\n ? { scrollbarWidth: 'none', msOverflowStyle: 'none' }\n : undefined\n }\n {...props}\n >\n {injectStore(children, store)}\n </ul>\n );\n }\n);\nMenu.displayName = 'Menu';\n\ninterface MenuItemProps extends HTMLAttributes<HTMLLIElement> {\n value: string;\n disabled?: boolean;\n store?: MenuStoreApi;\n variant?: 'menu' | 'menu2' | 'breadcrumb';\n}\n\nconst MenuItem = forwardRef<HTMLLIElement, MenuItemProps>(\n (\n {\n className,\n children,\n value,\n disabled = false,\n store: externalStore,\n variant = 'menu',\n ...props\n },\n ref\n ) => {\n const store = useMenuStore(externalStore);\n const { value: selectedValue, setValue } = useStore(store, (s) => s);\n\n const handleClick = (\n e: MouseEvent<HTMLLIElement> | KeyboardEvent<HTMLLIElement>\n ) => {\n if (!disabled) setValue(value);\n props.onClick?.(e as MouseEvent<HTMLLIElement>);\n };\n\n const commonProps = {\n role: 'menuitem',\n 'aria-disabled': disabled,\n ref,\n onClick: handleClick,\n onKeyDown: (e: KeyboardEvent<HTMLLIElement>) => {\n if (['Enter', ' '].includes(e.key)) handleClick(e);\n },\n tabIndex: disabled ? -1 : 0,\n ...props,\n };\n\n const variants: Record<string, ReactNode> = {\n menu: (\n <li\n data-variant=\"menu\"\n className={`\n w-full flex flex-col gap-0.5 items-center py-1 px-2 rounded-sm font-medium text-xs\n [&>svg]:size-6 cursor-pointer hover:bg-primary-600 hover:text-text\n focus:outline-none focus:border-2-indicator-info focus:border-2\n ${selectedValue === value ? 'bg-primary-50 text-primary-950' : 'text-text-950'}\n ${className ?? ''}\n `}\n {...commonProps}\n >\n {children}\n </li>\n ),\n menu2: (\n <li\n data-variant=\"menu2\"\n className={`\n flex flex-row items-center p-4 gap-2 border-b-2 border-transparent text-text-950 text-sx font-bold cursor-pointer\n ${selectedValue === value ? 'border-b-primary-950' : ''}\n `}\n {...commonProps}\n >\n {children}\n </li>\n ),\n breadcrumb: (\n <li\n data-variant=\"breadcrumb\"\n className={`\n p-2 rounded-lg hover:text-primary-600 cursor-pointer font-bold text-xs\n focus:outline-none focus:border-indicator-info focus:border-2\n ${selectedValue === value ? 'text-primary-950' : 'text-text-600'}\n ${className ?? ''}\n `}\n {...commonProps}\n >\n <span\n className={`\n border-b border-text-600 hover:border-primary-600 text-inherit\n ${selectedValue === value ? 'border-b-primary-950' : 'border-b-primary-600'}\n `}\n >\n {children}\n </span>\n </li>\n ),\n };\n\n return variants[variant] ?? variants['menu'];\n }\n);\nMenuItem.displayName = 'MenuItem';\n\nconst MenuItemIcon = ({\n className,\n icon,\n ...props\n}: HTMLAttributes<HTMLSpanElement> & { icon: ReactNode }) => (\n <span\n className={`\n bg-background-500 w-[21px] h-[21px] flex items-center justify-center\n [&>svg]:w-[17px] [&>svg]:h-[17px] rounded-sm ${className ?? ''}\n `}\n {...props}\n >\n {icon}\n </span>\n);\n\nconst MenuSeparator = forwardRef<HTMLLIElement, HTMLAttributes<HTMLLIElement>>(\n ({ className, children, ...props }, ref) => (\n <li\n ref={ref}\n aria-hidden=\"true\"\n className={`[&>svg]:w-4 [&>svg]:h-4 text-text-600 ${className ?? ''}`}\n {...props}\n >\n {children ?? <CaretRight />}\n </li>\n )\n);\nMenuSeparator.displayName = 'MenuSeparator';\n\nexport const internalScroll = (\n container: HTMLUListElement | null,\n direction: 'left' | 'right'\n) => {\n if (!container) return;\n container.scrollBy({\n left: direction === 'left' ? -150 : 150,\n behavior: 'smooth',\n });\n};\n\nexport const internalCheckScroll = (\n container: HTMLUListElement | null,\n setShowLeftArrow: (v: boolean) => void,\n setShowRightArrow: (v: boolean) => void\n) => {\n if (!container) return;\n const { scrollLeft, scrollWidth, clientWidth } = container;\n setShowLeftArrow(scrollLeft > 0);\n setShowRightArrow(scrollLeft + clientWidth < scrollWidth);\n};\n\ninterface MenuOverflowProps extends HTMLAttributes<HTMLUListElement> {\n children: ReactNode;\n defaultValue: string;\n value?: string;\n onValueChange?: (value: string) => void;\n}\n\nconst MenuOverflow = ({\n children,\n className,\n defaultValue,\n value,\n onValueChange,\n ...props\n}: MenuOverflowProps) => {\n const containerRef = useRef<HTMLUListElement>(null);\n const [showLeftArrow, setShowLeftArrow] = useState(false);\n const [showRightArrow, setShowRightArrow] = useState(false);\n\n useEffect(() => {\n const checkScroll = () =>\n internalCheckScroll(\n containerRef.current,\n setShowLeftArrow,\n setShowRightArrow\n );\n checkScroll();\n const container = containerRef.current;\n container?.addEventListener('scroll', checkScroll);\n window.addEventListener('resize', checkScroll);\n return () => {\n container?.removeEventListener('scroll', checkScroll);\n window.removeEventListener('resize', checkScroll);\n };\n }, []);\n\n return (\n <div\n data-testid=\"menu-overflow-wrapper\"\n className={`relative w-full overflow-hidden ${className ?? ''}`}\n >\n {showLeftArrow && (\n <button\n onClick={() => internalScroll(containerRef.current, 'left')}\n className=\"absolute left-0 top-1/2 -translate-y-1/2 z-10 flex h-8 w-8 items-center justify-center rounded-full bg-white shadow-md\"\n data-testid=\"scroll-left-button\"\n >\n <CaretLeft size={16} />\n <span className=\"sr-only\">Scroll left</span>\n </button>\n )}\n\n <Menu\n ref={containerRef}\n variant=\"menu2\"\n defaultValue={defaultValue}\n onValueChange={onValueChange}\n value={value}\n {...props}\n >\n {children}\n </Menu>\n\n {showRightArrow && (\n <button\n onClick={() => internalScroll(containerRef.current, 'right')}\n className=\"absolute right-0 top-1/2 -translate-y-1/2 z-10 flex h-8 w-8 items-center justify-center rounded-full bg-white shadow-md\"\n data-testid=\"scroll-right-button\"\n >\n <CaretRight size={16} />\n <span className=\"sr-only\">Scroll right</span>\n </button>\n )}\n </div>\n );\n};\n\nconst injectStore = (children: ReactNode, store: MenuStoreApi): ReactNode =>\n Children.map(children, (child) => {\n if (!isValidElement(child)) return child;\n /* eslint-disable-next-line @typescript-eslint/no-explicit-any */\n const typedChild = child as ReactElement<any>;\n const shouldInject = typedChild.type === MenuItem;\n return cloneElement(typedChild, {\n ...(shouldInject ? { store } : {}),\n ...(typedChild.props.children\n ? { children: injectStore(typedChild.props.children, store) }\n : {}),\n });\n });\n\nexport default Menu;\nexport { Menu, MenuItem, MenuSeparator, MenuOverflow, MenuItemIcon };\n"],"mappings":";AAAA,SAAS,QAAkB,gBAAgB;AAC3C;AAAA,EAEE;AAAA,EACA;AAAA,EACA;AAAA,EAKA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,WAAW,kBAAkB;AAiEhC,cAqNE,YArNF;AAxDN,IAAM,kBAAkB,MACtB,OAAkB,CAAC,SAAS;AAAA,EAC1B,OAAO;AAAA,EACP,UAAU,CAAC,UAAU,IAAI,EAAE,MAAM,CAAC;AACpC,EAAE;AAEG,IAAM,eAAe,CAAC,kBAAiC;AAC5D,MAAI,CAAC,cAAe,OAAM,IAAI,MAAM,8BAA8B;AAClE,SAAO;AACT;AAUA,IAAM,kBAAkB;AAAA,EACtB,MAAM;AAAA,EACN,OAAO;AAAA,EACP,YAAY;AACd;AAEA,IAAM,OAAO;AAAA,EACX,CACE;AAAA,IACE;AAAA,IACA;AAAA,IACA;AAAA,IACA,OAAO;AAAA,IACP,UAAU;AAAA,IACV;AAAA,IACA,GAAG;AAAA,EACL,GACA,QACG;AACH,UAAM,WAAW,OAAqB,IAAI;AAC1C,aAAS,YAAY,gBAAgB;AACrC,UAAM,QAAQ,SAAS;AACvB,UAAM,EAAE,UAAU,MAAM,IAAI,SAAS,OAAO,CAAC,MAAM,CAAC;AAEpD,cAAU,MAAM;AACd,eAAS,aAAa,YAAY;AAAA,IACpC,GAAG,CAAC,cAAc,WAAW,QAAQ,CAAC;AAEtC,cAAU,MAAM;AACd,sBAAgB,KAAK;AAAA,IACvB,GAAG,CAAC,OAAO,aAAa,CAAC;AAEzB,UAAM,cAAc;AAEpB,UAAM,iBAAiB,gBAAgB,OAAO;AAE9C,WACE;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA,WAAW;AAAA,YACP,WAAW;AAAA,YACX,cAAc;AAAA,YACd,aAAa,EAAE;AAAA;AAAA,QAEnB,OACE,YAAY,UACR,EAAE,gBAAgB,QAAQ,iBAAiB,OAAO,IAClD;AAAA,QAEL,GAAG;AAAA,QAEH,sBAAY,UAAU,KAAK;AAAA;AAAA,IAC9B;AAAA,EAEJ;AACF;AACA,KAAK,cAAc;AASnB,IAAM,WAAW;AAAA,EACf,CACE;AAAA,IACE;AAAA,IACA;AAAA,IACA;AAAA,IACA,WAAW;AAAA,IACX,OAAO;AAAA,IACP,UAAU;AAAA,IACV,GAAG;AAAA,EACL,GACA,QACG;AACH,UAAM,QAAQ,aAAa,aAAa;AACxC,UAAM,EAAE,OAAO,eAAe,SAAS,IAAI,SAAS,OAAO,CAAC,MAAM,CAAC;AAEnE,UAAM,cAAc,CAClB,MACG;AACH,UAAI,CAAC,SAAU,UAAS,KAAK;AAC7B,YAAM,UAAU,CAA8B;AAAA,IAChD;AAEA,UAAM,cAAc;AAAA,MAClB,MAAM;AAAA,MACN,iBAAiB;AAAA,MACjB;AAAA,MACA,SAAS;AAAA,MACT,WAAW,CAAC,MAAoC;AAC9C,YAAI,CAAC,SAAS,GAAG,EAAE,SAAS,EAAE,GAAG,EAAG,aAAY,CAAC;AAAA,MACnD;AAAA,MACA,UAAU,WAAW,KAAK;AAAA,MAC1B,GAAG;AAAA,IACL;AAEA,UAAM,WAAsC;AAAA,MAC1C,MACE;AAAA,QAAC;AAAA;AAAA,UACC,gBAAa;AAAA,UACb,WAAW;AAAA;AAAA;AAAA;AAAA,cAIP,kBAAkB,QAAQ,mCAAmC,eAAe;AAAA,cAC5E,aAAa,EAAE;AAAA;AAAA,UAElB,GAAG;AAAA,UAEH;AAAA;AAAA,MACH;AAAA,MAEF,OACE;AAAA,QAAC;AAAA;AAAA,UACC,gBAAa;AAAA,UACb,WAAW;AAAA;AAAA,cAEP,kBAAkB,QAAQ,yBAAyB,EAAE;AAAA;AAAA,UAExD,GAAG;AAAA,UAEH;AAAA;AAAA,MACH;AAAA,MAEF,YACE;AAAA,QAAC;AAAA;AAAA,UACC,gBAAa;AAAA,UACb,WAAW;AAAA;AAAA;AAAA,cAGP,kBAAkB,QAAQ,qBAAqB,eAAe;AAAA,cAC9D,aAAa,EAAE;AAAA;AAAA,UAElB,GAAG;AAAA,UAEJ;AAAA,YAAC;AAAA;AAAA,cACC,WAAW;AAAA;AAAA,gBAEP,kBAAkB,QAAQ,yBAAyB,sBAAsB;AAAA;AAAA,cAG5E;AAAA;AAAA,UACH;AAAA;AAAA,MACF;AAAA,IAEJ;AAEA,WAAO,SAAS,OAAO,KAAK,SAAS,MAAM;AAAA,EAC7C;AACF;AACA,SAAS,cAAc;AAEvB,IAAM,eAAe,CAAC;AAAA,EACpB;AAAA,EACA;AAAA,EACA,GAAG;AACL,MACE;AAAA,EAAC;AAAA;AAAA,IACC,WAAW;AAAA;AAAA,qDAEsC,aAAa,EAAE;AAAA;AAAA,IAE/D,GAAG;AAAA,IAEH;AAAA;AACH;AAGF,IAAM,gBAAgB;AAAA,EACpB,CAAC,EAAE,WAAW,UAAU,GAAG,MAAM,GAAG,QAClC;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,eAAY;AAAA,MACZ,WAAW,yCAAyC,aAAa,EAAE;AAAA,MAClE,GAAG;AAAA,MAEH,sBAAY,oBAAC,cAAW;AAAA;AAAA,EAC3B;AAEJ;AACA,cAAc,cAAc;AAErB,IAAM,iBAAiB,CAC5B,WACA,cACG;AACH,MAAI,CAAC,UAAW;AAChB,YAAU,SAAS;AAAA,IACjB,MAAM,cAAc,SAAS,OAAO;AAAA,IACpC,UAAU;AAAA,EACZ,CAAC;AACH;AAEO,IAAM,sBAAsB,CACjC,WACA,kBACA,sBACG;AACH,MAAI,CAAC,UAAW;AAChB,QAAM,EAAE,YAAY,aAAa,YAAY,IAAI;AACjD,mBAAiB,aAAa,CAAC;AAC/B,oBAAkB,aAAa,cAAc,WAAW;AAC1D;AASA,IAAM,eAAe,CAAC;AAAA,EACpB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACL,MAAyB;AACvB,QAAM,eAAe,OAAyB,IAAI;AAClD,QAAM,CAAC,eAAe,gBAAgB,IAAI,SAAS,KAAK;AACxD,QAAM,CAAC,gBAAgB,iBAAiB,IAAI,SAAS,KAAK;AAE1D,YAAU,MAAM;AACd,UAAM,cAAc,MAClB;AAAA,MACE,aAAa;AAAA,MACb;AAAA,MACA;AAAA,IACF;AACF,gBAAY;AACZ,UAAM,YAAY,aAAa;AAC/B,eAAW,iBAAiB,UAAU,WAAW;AACjD,WAAO,iBAAiB,UAAU,WAAW;AAC7C,WAAO,MAAM;AACX,iBAAW,oBAAoB,UAAU,WAAW;AACpD,aAAO,oBAAoB,UAAU,WAAW;AAAA,IAClD;AAAA,EACF,GAAG,CAAC,CAAC;AAEL,SACE;AAAA,IAAC;AAAA;AAAA,MACC,eAAY;AAAA,MACZ,WAAW,mCAAmC,aAAa,EAAE;AAAA,MAE5D;AAAA,yBACC;AAAA,UAAC;AAAA;AAAA,YACC,SAAS,MAAM,eAAe,aAAa,SAAS,MAAM;AAAA,YAC1D,WAAU;AAAA,YACV,eAAY;AAAA,YAEZ;AAAA,kCAAC,aAAU,MAAM,IAAI;AAAA,cACrB,oBAAC,UAAK,WAAU,WAAU,yBAAW;AAAA;AAAA;AAAA,QACvC;AAAA,QAGF;AAAA,UAAC;AAAA;AAAA,YACC,KAAK;AAAA,YACL,SAAQ;AAAA,YACR;AAAA,YACA;AAAA,YACA;AAAA,YACC,GAAG;AAAA,YAEH;AAAA;AAAA,QACH;AAAA,QAEC,kBACC;AAAA,UAAC;AAAA;AAAA,YACC,SAAS,MAAM,eAAe,aAAa,SAAS,OAAO;AAAA,YAC3D,WAAU;AAAA,YACV,eAAY;AAAA,YAEZ;AAAA,kCAAC,cAAW,MAAM,IAAI;AAAA,cACtB,oBAAC,UAAK,WAAU,WAAU,0BAAY;AAAA;AAAA;AAAA,QACxC;AAAA;AAAA;AAAA,EAEJ;AAEJ;AAEA,IAAM,cAAc,CAAC,UAAqB,UACxC,SAAS,IAAI,UAAU,CAAC,UAAU;AAChC,MAAI,CAAC,eAAe,KAAK,EAAG,QAAO;AAEnC,QAAM,aAAa;AACnB,QAAM,eAAe,WAAW,SAAS;AACzC,SAAO,aAAa,YAAY;AAAA,IAC9B,GAAI,eAAe,EAAE,MAAM,IAAI,CAAC;AAAA,IAChC,GAAI,WAAW,MAAM,WACjB,EAAE,UAAU,YAAY,WAAW,MAAM,UAAU,KAAK,EAAE,IAC1D,CAAC;AAAA,EACP,CAAC;AACH,CAAC;AAEH,IAAO,eAAQ;","names":[]}
|
|
@@ -6,7 +6,6 @@ import { ReactNode, ButtonHTMLAttributes } from 'react';
|
|
|
6
6
|
*
|
|
7
7
|
* Um botão de navegação com ícone e texto para navegação principal.
|
|
8
8
|
* Ideal para menus de navegação, sidebar, tabs de navegação, etc.
|
|
9
|
-
* Compatível com Next.js 15 e React 19.
|
|
10
9
|
* Suporta forwardRef para acesso programático ao elemento DOM.
|
|
11
10
|
*
|
|
12
11
|
* @param icon - O ícone a ser exibido no botão
|
|
@@ -6,7 +6,6 @@ import { ReactNode, ButtonHTMLAttributes } from 'react';
|
|
|
6
6
|
*
|
|
7
7
|
* Um botão de navegação com ícone e texto para navegação principal.
|
|
8
8
|
* Ideal para menus de navegação, sidebar, tabs de navegação, etc.
|
|
9
|
-
* Compatível com Next.js 15 e React 19.
|
|
10
9
|
* Suporta forwardRef para acesso programático ao elemento DOM.
|
|
11
10
|
*
|
|
12
11
|
* @param icon - O ícone a ser exibido no botão
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/components/NavButton/NavButton.tsx"],"sourcesContent":["import { ButtonHTMLAttributes, ReactNode, forwardRef } from 'react';\n\n/**\n * NavButton component props interface\n */\ntype NavButtonProps = {\n /** Ícone a ser exibido no botão */\n icon: ReactNode;\n /** Texto/label a ser exibido ao lado do ícone */\n label: string;\n /** Estado de seleção do botão */\n selected?: boolean;\n /** Additional CSS classes to apply */\n className?: string;\n} & ButtonHTMLAttributes<HTMLButtonElement>;\n\n/**\n * NavButton component for Analytica Ensino platforms\n *\n * Um botão de navegação com ícone e texto para navegação principal.\n * Ideal para menus de navegação, sidebar, tabs de navegação, etc.\n *
|
|
1
|
+
{"version":3,"sources":["../../src/components/NavButton/NavButton.tsx"],"sourcesContent":["import { ButtonHTMLAttributes, ReactNode, forwardRef } from 'react';\n\n/**\n * NavButton component props interface\n */\ntype NavButtonProps = {\n /** Ícone a ser exibido no botão */\n icon: ReactNode;\n /** Texto/label a ser exibido ao lado do ícone */\n label: string;\n /** Estado de seleção do botão */\n selected?: boolean;\n /** Additional CSS classes to apply */\n className?: string;\n} & ButtonHTMLAttributes<HTMLButtonElement>;\n\n/**\n * NavButton component for Analytica Ensino platforms\n *\n * Um botão de navegação com ícone e texto para navegação principal.\n * Ideal para menus de navegação, sidebar, tabs de navegação, etc.\n * Suporta forwardRef para acesso programático ao elemento DOM.\n *\n * @param icon - O ícone a ser exibido no botão\n * @param label - O texto/label a ser exibido\n * @param selected - Estado de seleção do botão\n * @param className - Classes CSS adicionais\n * @param props - Todos os outros atributos HTML padrão de button\n * @returns Um elemento button estilizado para navegação\n *\n * @example\n * ```tsx\n * <NavButton\n * icon={<HomeIcon />}\n * label=\"Início\"\n * selected={false}\n * onClick={() => navigate('/')}\n * />\n * ```\n *\n * @example\n * ```tsx\n * // Usando ref para foco programático\n * const buttonRef = useRef<HTMLButtonElement>(null);\n *\n * const handleFocus = () => {\n * buttonRef.current?.focus();\n * };\n *\n * <NavButton\n * ref={buttonRef}\n * icon={<HomeIcon />}\n * label=\"Dashboard\"\n * selected={isActive}\n * onClick={() => setActiveTab('dashboard')}\n * />\n * ```\n */\nconst NavButton = forwardRef<HTMLButtonElement, NavButtonProps>(\n (\n { icon, label, selected = false, className = '', disabled, ...props },\n ref\n ) => {\n // Classes base para todos os estados\n const baseClasses = [\n 'flex',\n 'flex-col',\n 'items-center',\n 'justify-center',\n 'gap-0.5',\n 'px-12',\n 'py-1',\n 'rounded-sm',\n 'cursor-pointer',\n 'text-text-950',\n 'text-xs',\n 'font-medium',\n 'hover:text-text',\n 'hover:bg-primary-600',\n 'focus-visible:outline-none',\n 'focus-visible:ring-2',\n 'focus-visible:ring-offset-0',\n 'focus-visible:ring-indicator-info',\n 'disabled:opacity-50',\n 'disabled:cursor-not-allowed',\n 'disabled:pointer-events-none',\n ];\n\n const stateClasses = selected ? ['bg-primary-50', 'text-primary-950'] : [];\n\n const allClasses = [...baseClasses, ...stateClasses].join(' ');\n\n return (\n <button\n ref={ref}\n type=\"button\"\n className={`${allClasses} ${className}`}\n disabled={disabled}\n aria-pressed={selected}\n {...props}\n >\n <span className=\"flex items-center justify-center w-5 h-5\">{icon}</span>\n <span className=\"whitespace-nowrap\">{label}</span>\n </button>\n );\n }\n);\n\nNavButton.displayName = 'NavButton';\n\nexport default NavButton;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAA4D;AA6FtD;AAnCN,IAAM,gBAAY;AAAA,EAChB,CACE,EAAE,MAAM,OAAO,WAAW,OAAO,YAAY,IAAI,UAAU,GAAG,MAAM,GACpE,QACG;AAEH,UAAM,cAAc;AAAA,MAClB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAEA,UAAM,eAAe,WAAW,CAAC,iBAAiB,kBAAkB,IAAI,CAAC;AAEzE,UAAM,aAAa,CAAC,GAAG,aAAa,GAAG,YAAY,EAAE,KAAK,GAAG;AAE7D,WACE;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA,MAAK;AAAA,QACL,WAAW,GAAG,UAAU,IAAI,SAAS;AAAA,QACrC;AAAA,QACA,gBAAc;AAAA,QACb,GAAG;AAAA,QAEJ;AAAA,sDAAC,UAAK,WAAU,4CAA4C,gBAAK;AAAA,UACjE,4CAAC,UAAK,WAAU,qBAAqB,iBAAM;AAAA;AAAA;AAAA,IAC7C;AAAA,EAEJ;AACF;AAEA,UAAU,cAAc;AAExB,IAAO,oBAAQ;","names":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/components/NavButton/NavButton.tsx"],"sourcesContent":["import { ButtonHTMLAttributes, ReactNode, forwardRef } from 'react';\n\n/**\n * NavButton component props interface\n */\ntype NavButtonProps = {\n /** Ícone a ser exibido no botão */\n icon: ReactNode;\n /** Texto/label a ser exibido ao lado do ícone */\n label: string;\n /** Estado de seleção do botão */\n selected?: boolean;\n /** Additional CSS classes to apply */\n className?: string;\n} & ButtonHTMLAttributes<HTMLButtonElement>;\n\n/**\n * NavButton component for Analytica Ensino platforms\n *\n * Um botão de navegação com ícone e texto para navegação principal.\n * Ideal para menus de navegação, sidebar, tabs de navegação, etc.\n *
|
|
1
|
+
{"version":3,"sources":["../../src/components/NavButton/NavButton.tsx"],"sourcesContent":["import { ButtonHTMLAttributes, ReactNode, forwardRef } from 'react';\n\n/**\n * NavButton component props interface\n */\ntype NavButtonProps = {\n /** Ícone a ser exibido no botão */\n icon: ReactNode;\n /** Texto/label a ser exibido ao lado do ícone */\n label: string;\n /** Estado de seleção do botão */\n selected?: boolean;\n /** Additional CSS classes to apply */\n className?: string;\n} & ButtonHTMLAttributes<HTMLButtonElement>;\n\n/**\n * NavButton component for Analytica Ensino platforms\n *\n * Um botão de navegação com ícone e texto para navegação principal.\n * Ideal para menus de navegação, sidebar, tabs de navegação, etc.\n * Suporta forwardRef para acesso programático ao elemento DOM.\n *\n * @param icon - O ícone a ser exibido no botão\n * @param label - O texto/label a ser exibido\n * @param selected - Estado de seleção do botão\n * @param className - Classes CSS adicionais\n * @param props - Todos os outros atributos HTML padrão de button\n * @returns Um elemento button estilizado para navegação\n *\n * @example\n * ```tsx\n * <NavButton\n * icon={<HomeIcon />}\n * label=\"Início\"\n * selected={false}\n * onClick={() => navigate('/')}\n * />\n * ```\n *\n * @example\n * ```tsx\n * // Usando ref para foco programático\n * const buttonRef = useRef<HTMLButtonElement>(null);\n *\n * const handleFocus = () => {\n * buttonRef.current?.focus();\n * };\n *\n * <NavButton\n * ref={buttonRef}\n * icon={<HomeIcon />}\n * label=\"Dashboard\"\n * selected={isActive}\n * onClick={() => setActiveTab('dashboard')}\n * />\n * ```\n */\nconst NavButton = forwardRef<HTMLButtonElement, NavButtonProps>(\n (\n { icon, label, selected = false, className = '', disabled, ...props },\n ref\n ) => {\n // Classes base para todos os estados\n const baseClasses = [\n 'flex',\n 'flex-col',\n 'items-center',\n 'justify-center',\n 'gap-0.5',\n 'px-12',\n 'py-1',\n 'rounded-sm',\n 'cursor-pointer',\n 'text-text-950',\n 'text-xs',\n 'font-medium',\n 'hover:text-text',\n 'hover:bg-primary-600',\n 'focus-visible:outline-none',\n 'focus-visible:ring-2',\n 'focus-visible:ring-offset-0',\n 'focus-visible:ring-indicator-info',\n 'disabled:opacity-50',\n 'disabled:cursor-not-allowed',\n 'disabled:pointer-events-none',\n ];\n\n const stateClasses = selected ? ['bg-primary-50', 'text-primary-950'] : [];\n\n const allClasses = [...baseClasses, ...stateClasses].join(' ');\n\n return (\n <button\n ref={ref}\n type=\"button\"\n className={`${allClasses} ${className}`}\n disabled={disabled}\n aria-pressed={selected}\n {...props}\n >\n <span className=\"flex items-center justify-center w-5 h-5\">{icon}</span>\n <span className=\"whitespace-nowrap\">{label}</span>\n </button>\n );\n }\n);\n\nNavButton.displayName = 'NavButton';\n\nexport default NavButton;\n"],"mappings":";AAAA,SAA0C,kBAAkB;AA6FtD,SAQE,KARF;AAnCN,IAAM,YAAY;AAAA,EAChB,CACE,EAAE,MAAM,OAAO,WAAW,OAAO,YAAY,IAAI,UAAU,GAAG,MAAM,GACpE,QACG;AAEH,UAAM,cAAc;AAAA,MAClB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAEA,UAAM,eAAe,WAAW,CAAC,iBAAiB,kBAAkB,IAAI,CAAC;AAEzE,UAAM,aAAa,CAAC,GAAG,aAAa,GAAG,YAAY,EAAE,KAAK,GAAG;AAE7D,WACE;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA,MAAK;AAAA,QACL,WAAW,GAAG,UAAU,IAAI,SAAS;AAAA,QACrC;AAAA,QACA,gBAAc;AAAA,QACb,GAAG;AAAA,QAEJ;AAAA,8BAAC,UAAK,WAAU,4CAA4C,gBAAK;AAAA,UACjE,oBAAC,UAAK,WAAU,qBAAqB,iBAAM;AAAA;AAAA;AAAA,IAC7C;AAAA,EAEJ;AACF;AAEA,UAAU,cAAc;AAExB,IAAO,oBAAQ;","names":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/components/ProgressBar/ProgressBar.tsx","../../src/components/Text/Text.tsx"],"sourcesContent":["'use client';\n\nimport { ReactNode } from 'react';\nimport Text from '../Text/Text';\n\n/**\n * Progress bar size variants\n */\ntype ProgressBarSize = 'small' | 'medium';\n\n/**\n * Progress bar color variants\n */\ntype ProgressBarVariant = 'blue' | 'green';\n\n/**\n * Size configurations using Tailwind classes\n */\nconst SIZE_CLASSES = {\n small: {\n container: 'h-1', // 4px height (h-1 = 4px in Tailwind)\n bar: 'h-1', // 4px height for the fill bar\n labelSize: 'xs' as const,\n spacing: 'gap-2', // 8px gap between label and progress bar\n layout: 'flex-col', // vertical layout for small\n borderRadius: 'rounded-full', // 9999px border radius\n },\n medium: {\n container: 'h-2', // 8px height (h-2 = 8px in Tailwind)\n bar: 'h-2', // 8px height for the fill bar\n labelSize: 'xs' as const, // 12px font size (xs in Tailwind)\n spacing: 'gap-2', // 8px gap between progress bar and label\n layout: 'flex-row items-center', // horizontal layout for medium\n borderRadius: 'rounded-lg', // 8px border radius\n },\n} as const;\n\n/**\n * Color configurations using design system colors\n */\nconst VARIANT_CLASSES = {\n blue: {\n background: 'bg-background-300', // Background track color (#D5D4D4)\n fill: 'bg-primary-700', // Blue for activity progress (#2271C4)\n },\n green: {\n background: 'bg-background-300', // Background track color (#D5D4D4)\n fill: 'bg-success-200', // Green for performance (#84D3A2)\n },\n} as const;\n\n/**\n * ProgressBar component props interface\n */\nexport type ProgressBarProps = {\n /** Progress value between 0 and 100 */\n value: number;\n /** Maximum value (defaults to 100) */\n max?: number;\n /** Size variant of the progress bar */\n size?: ProgressBarSize;\n /** Color variant of the progress bar */\n variant?: ProgressBarVariant;\n /** Optional label to display */\n label?: ReactNode;\n /** Show percentage text */\n showPercentage?: boolean;\n /** Additional CSS classes */\n className?: string;\n /** Label CSS classes */\n labelClassName?: string;\n /** Percentage text CSS classes */\n percentageClassName?: string;\n};\n\n/**\n * ProgressBar component for Analytica Ensino platforms\n *\n * A progress bar component with size and color variants designed for tracking\n * activity progress (blue) and performance metrics (green).\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 progress bar\n * <ProgressBar value={65} />\n *\n * // Activity progress (blue)\n * <ProgressBar variant=\"blue\" value={45} label=\"Progress\" showPercentage />\n *\n * // Performance metrics (green)\n * <ProgressBar variant=\"green\" size=\"medium\" value={85} label=\"Performance\" />\n *\n * // Small size with custom max value\n * <ProgressBar size=\"small\" value={3} max={5} showPercentage />\n * ```\n */\nconst ProgressBar = ({\n value,\n max = 100,\n size = 'medium',\n variant = 'blue',\n label,\n showPercentage = false,\n className = '',\n labelClassName = '',\n percentageClassName = '',\n}: ProgressBarProps) => {\n // Ensure value is within bounds and handle NaN/Infinity\n const safeValue = isNaN(value) ? 0 : value;\n const clampedValue = Math.max(0, Math.min(safeValue, max));\n const percentage = max === 0 ? 0 : (clampedValue / max) * 100;\n\n // Get size and variant classes\n const sizeClasses = SIZE_CLASSES[size];\n const variantClasses = VARIANT_CLASSES[variant];\n\n return (\n <div\n className={`flex ${sizeClasses.layout} ${sizeClasses.spacing} ${className}`}\n >\n {/* For small size: vertical layout with label/percentage on top */}\n {size === 'small' && (label || showPercentage) && (\n <div className=\"flex flex-row items-center justify-between w-full\">\n {/* Label */}\n {label && (\n <Text\n as=\"div\"\n size={sizeClasses.labelSize}\n weight=\"medium\"\n className={`text-text-950 ${labelClassName}`}\n >\n {label}\n </Text>\n )}\n\n {/* Percentage */}\n {showPercentage && (\n <Text\n size={sizeClasses.labelSize}\n weight=\"medium\"\n className={`text-text-700 text-center ${percentageClassName}`}\n >\n {Math.round(percentage)}%\n </Text>\n )}\n </div>\n )}\n\n {/* Progress bar container */}\n <div\n className={`${size === 'medium' ? 'flex-grow' : 'w-full'} ${sizeClasses.container} ${variantClasses.background} ${sizeClasses.borderRadius} overflow-hidden relative`}\n >\n {/* Native progress element for accessibility */}\n <progress\n value={clampedValue}\n max={max}\n aria-label={typeof label === 'string' ? label : 'Progress'}\n className=\"absolute inset-0 w-full h-full opacity-0\"\n />\n\n {/* Progress bar fill */}\n <div\n className={`${sizeClasses.bar} ${variantClasses.fill} ${sizeClasses.borderRadius} transition-all duration-300 ease-out shadow-hard-shadow-3`}\n style={{ width: `${percentage}%` }}\n />\n </div>\n\n {/* For medium size: horizontal layout with percentage on the right */}\n {size === 'medium' && showPercentage && (\n <Text\n size={sizeClasses.labelSize}\n weight=\"medium\"\n className={`text-text-950 text-center flex-none w-[70px] ${percentageClassName}`}\n >\n {Math.round(percentage)}%\n </Text>\n )}\n\n {/* For medium size: label below if provided */}\n {size === 'medium' && label && !showPercentage && (\n <Text\n as=\"div\"\n size={sizeClasses.labelSize}\n weight=\"medium\"\n className={`text-text-950 flex-none ${labelClassName}`}\n >\n {label}\n </Text>\n )}\n </div>\n );\n};\n\nexport default ProgressBar;\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"]}
|
|
1
|
+
{"version":3,"sources":["../../src/components/ProgressBar/ProgressBar.tsx","../../src/components/Text/Text.tsx"],"sourcesContent":["import { ReactNode } from 'react';\nimport Text from '../Text/Text';\n\n/**\n * Progress bar size variants\n */\ntype ProgressBarSize = 'small' | 'medium';\n\n/**\n * Progress bar color variants\n */\ntype ProgressBarVariant = 'blue' | 'green';\n\n/**\n * Size configurations using Tailwind classes\n */\nconst SIZE_CLASSES = {\n small: {\n container: 'h-1', // 4px height (h-1 = 4px in Tailwind)\n bar: 'h-1', // 4px height for the fill bar\n labelSize: 'xs' as const,\n spacing: 'gap-2', // 8px gap between label and progress bar\n layout: 'flex-col', // vertical layout for small\n borderRadius: 'rounded-full', // 9999px border radius\n },\n medium: {\n container: 'h-2', // 8px height (h-2 = 8px in Tailwind)\n bar: 'h-2', // 8px height for the fill bar\n labelSize: 'xs' as const, // 12px font size (xs in Tailwind)\n spacing: 'gap-2', // 8px gap between progress bar and label\n layout: 'flex-row items-center', // horizontal layout for medium\n borderRadius: 'rounded-lg', // 8px border radius\n },\n} as const;\n\n/**\n * Color configurations using design system colors\n */\nconst VARIANT_CLASSES = {\n blue: {\n background: 'bg-background-300', // Background track color (#D5D4D4)\n fill: 'bg-primary-700', // Blue for activity progress (#2271C4)\n },\n green: {\n background: 'bg-background-300', // Background track color (#D5D4D4)\n fill: 'bg-success-200', // Green for performance (#84D3A2)\n },\n} as const;\n\n/**\n * ProgressBar component props interface\n */\nexport type ProgressBarProps = {\n /** Progress value between 0 and 100 */\n value: number;\n /** Maximum value (defaults to 100) */\n max?: number;\n /** Size variant of the progress bar */\n size?: ProgressBarSize;\n /** Color variant of the progress bar */\n variant?: ProgressBarVariant;\n /** Optional label to display */\n label?: ReactNode;\n /** Show percentage text */\n showPercentage?: boolean;\n /** Additional CSS classes */\n className?: string;\n /** Label CSS classes */\n labelClassName?: string;\n /** Percentage text CSS classes */\n percentageClassName?: string;\n};\n\n/**\n * ProgressBar component for Analytica Ensino platforms\n *\n * A progress bar component with size and color variants designed for tracking\n * activity progress (blue) and performance metrics (green).\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 progress bar\n * <ProgressBar value={65} />\n *\n * // Activity progress (blue)\n * <ProgressBar variant=\"blue\" value={45} label=\"Progress\" showPercentage />\n *\n * // Performance metrics (green)\n * <ProgressBar variant=\"green\" size=\"medium\" value={85} label=\"Performance\" />\n *\n * // Small size with custom max value\n * <ProgressBar size=\"small\" value={3} max={5} showPercentage />\n * ```\n */\nconst ProgressBar = ({\n value,\n max = 100,\n size = 'medium',\n variant = 'blue',\n label,\n showPercentage = false,\n className = '',\n labelClassName = '',\n percentageClassName = '',\n}: ProgressBarProps) => {\n // Ensure value is within bounds and handle NaN/Infinity\n const safeValue = isNaN(value) ? 0 : value;\n const clampedValue = Math.max(0, Math.min(safeValue, max));\n const percentage = max === 0 ? 0 : (clampedValue / max) * 100;\n\n // Get size and variant classes\n const sizeClasses = SIZE_CLASSES[size];\n const variantClasses = VARIANT_CLASSES[variant];\n\n return (\n <div\n className={`flex ${sizeClasses.layout} ${sizeClasses.spacing} ${className}`}\n >\n {/* For small size: vertical layout with label/percentage on top */}\n {size === 'small' && (label || showPercentage) && (\n <div className=\"flex flex-row items-center justify-between w-full\">\n {/* Label */}\n {label && (\n <Text\n as=\"div\"\n size={sizeClasses.labelSize}\n weight=\"medium\"\n className={`text-text-950 ${labelClassName}`}\n >\n {label}\n </Text>\n )}\n\n {/* Percentage */}\n {showPercentage && (\n <Text\n size={sizeClasses.labelSize}\n weight=\"medium\"\n className={`text-text-700 text-center ${percentageClassName}`}\n >\n {Math.round(percentage)}%\n </Text>\n )}\n </div>\n )}\n\n {/* Progress bar container */}\n <div\n className={`${size === 'medium' ? 'flex-grow' : 'w-full'} ${sizeClasses.container} ${variantClasses.background} ${sizeClasses.borderRadius} overflow-hidden relative`}\n >\n {/* Native progress element for accessibility */}\n <progress\n value={clampedValue}\n max={max}\n aria-label={typeof label === 'string' ? label : 'Progress'}\n className=\"absolute inset-0 w-full h-full opacity-0\"\n />\n\n {/* Progress bar fill */}\n <div\n className={`${sizeClasses.bar} ${variantClasses.fill} ${sizeClasses.borderRadius} transition-all duration-300 ease-out shadow-hard-shadow-3`}\n style={{ width: `${percentage}%` }}\n />\n </div>\n\n {/* For medium size: horizontal layout with percentage on the right */}\n {size === 'medium' && showPercentage && (\n <Text\n size={sizeClasses.labelSize}\n weight=\"medium\"\n className={`text-text-950 text-center flex-none w-[70px] ${percentageClassName}`}\n >\n {Math.round(percentage)}%\n </Text>\n )}\n\n {/* For medium size: label below if provided */}\n {size === 'medium' && label && !showPercentage && (\n <Text\n as=\"div\"\n size={sizeClasses.labelSize}\n weight=\"medium\"\n className={`text-text-950 flex-none ${labelClassName}`}\n >\n {label}\n </Text>\n )}\n </div>\n );\n};\n\nexport default ProgressBar;\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 *\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"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/components/Text/Text.tsx","../../src/components/ProgressBar/ProgressBar.tsx"],"sourcesContent":["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","'use client';\n\nimport { ReactNode } from 'react';\nimport Text from '../Text/Text';\n\n/**\n * Progress bar size variants\n */\ntype ProgressBarSize = 'small' | 'medium';\n\n/**\n * Progress bar color variants\n */\ntype ProgressBarVariant = 'blue' | 'green';\n\n/**\n * Size configurations using Tailwind classes\n */\nconst SIZE_CLASSES = {\n small: {\n container: 'h-1', // 4px height (h-1 = 4px in Tailwind)\n bar: 'h-1', // 4px height for the fill bar\n labelSize: 'xs' as const,\n spacing: 'gap-2', // 8px gap between label and progress bar\n layout: 'flex-col', // vertical layout for small\n borderRadius: 'rounded-full', // 9999px border radius\n },\n medium: {\n container: 'h-2', // 8px height (h-2 = 8px in Tailwind)\n bar: 'h-2', // 8px height for the fill bar\n labelSize: 'xs' as const, // 12px font size (xs in Tailwind)\n spacing: 'gap-2', // 8px gap between progress bar and label\n layout: 'flex-row items-center', // horizontal layout for medium\n borderRadius: 'rounded-lg', // 8px border radius\n },\n} as const;\n\n/**\n * Color configurations using design system colors\n */\nconst VARIANT_CLASSES = {\n blue: {\n background: 'bg-background-300', // Background track color (#D5D4D4)\n fill: 'bg-primary-700', // Blue for activity progress (#2271C4)\n },\n green: {\n background: 'bg-background-300', // Background track color (#D5D4D4)\n fill: 'bg-success-200', // Green for performance (#84D3A2)\n },\n} as const;\n\n/**\n * ProgressBar component props interface\n */\nexport type ProgressBarProps = {\n /** Progress value between 0 and 100 */\n value: number;\n /** Maximum value (defaults to 100) */\n max?: number;\n /** Size variant of the progress bar */\n size?: ProgressBarSize;\n /** Color variant of the progress bar */\n variant?: ProgressBarVariant;\n /** Optional label to display */\n label?: ReactNode;\n /** Show percentage text */\n showPercentage?: boolean;\n /** Additional CSS classes */\n className?: string;\n /** Label CSS classes */\n labelClassName?: string;\n /** Percentage text CSS classes */\n percentageClassName?: string;\n};\n\n/**\n * ProgressBar component for Analytica Ensino platforms\n *\n * A progress bar component with size and color variants designed for tracking\n * activity progress (blue) and performance metrics (green).\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 progress bar\n * <ProgressBar value={65} />\n *\n * // Activity progress (blue)\n * <ProgressBar variant=\"blue\" value={45} label=\"Progress\" showPercentage />\n *\n * // Performance metrics (green)\n * <ProgressBar variant=\"green\" size=\"medium\" value={85} label=\"Performance\" />\n *\n * // Small size with custom max value\n * <ProgressBar size=\"small\" value={3} max={5} showPercentage />\n * ```\n */\nconst ProgressBar = ({\n value,\n max = 100,\n size = 'medium',\n variant = 'blue',\n label,\n showPercentage = false,\n className = '',\n labelClassName = '',\n percentageClassName = '',\n}: ProgressBarProps) => {\n // Ensure value is within bounds and handle NaN/Infinity\n const safeValue = isNaN(value) ? 0 : value;\n const clampedValue = Math.max(0, Math.min(safeValue, max));\n const percentage = max === 0 ? 0 : (clampedValue / max) * 100;\n\n // Get size and variant classes\n const sizeClasses = SIZE_CLASSES[size];\n const variantClasses = VARIANT_CLASSES[variant];\n\n return (\n <div\n className={`flex ${sizeClasses.layout} ${sizeClasses.spacing} ${className}`}\n >\n {/* For small size: vertical layout with label/percentage on top */}\n {size === 'small' && (label || showPercentage) && (\n <div className=\"flex flex-row items-center justify-between w-full\">\n {/* Label */}\n {label && (\n <Text\n as=\"div\"\n size={sizeClasses.labelSize}\n weight=\"medium\"\n className={`text-text-950 ${labelClassName}`}\n >\n {label}\n </Text>\n )}\n\n {/* Percentage */}\n {showPercentage && (\n <Text\n size={sizeClasses.labelSize}\n weight=\"medium\"\n className={`text-text-700 text-center ${percentageClassName}`}\n >\n {Math.round(percentage)}%\n </Text>\n )}\n </div>\n )}\n\n {/* Progress bar container */}\n <div\n className={`${size === 'medium' ? 'flex-grow' : 'w-full'} ${sizeClasses.container} ${variantClasses.background} ${sizeClasses.borderRadius} overflow-hidden relative`}\n >\n {/* Native progress element for accessibility */}\n <progress\n value={clampedValue}\n max={max}\n aria-label={typeof label === 'string' ? label : 'Progress'}\n className=\"absolute inset-0 w-full h-full opacity-0\"\n />\n\n {/* Progress bar fill */}\n <div\n className={`${sizeClasses.bar} ${variantClasses.fill} ${sizeClasses.borderRadius} transition-all duration-300 ease-out shadow-hard-shadow-3`}\n style={{ width: `${percentage}%` }}\n />\n </div>\n\n {/* For medium size: horizontal layout with percentage on the right */}\n {size === 'medium' && showPercentage && (\n <Text\n size={sizeClasses.labelSize}\n weight=\"medium\"\n className={`text-text-950 text-center flex-none w-[70px] ${percentageClassName}`}\n >\n {Math.round(percentage)}%\n </Text>\n )}\n\n {/* For medium size: label below if provided */}\n {size === 'medium' && label && !showPercentage && (\n <Text\n as=\"div\"\n size={sizeClasses.labelSize}\n weight=\"medium\"\n className={`text-text-950 flex-none ${labelClassName}`}\n >\n {label}\n </Text>\n )}\n </div>\n );\n};\n\nexport default ProgressBar;\n"],"mappings":"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","names":["jsx"]}
|
|
1
|
+
{"version":3,"sources":["../../src/components/Text/Text.tsx","../../src/components/ProgressBar/ProgressBar.tsx"],"sourcesContent":["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 *\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","import { ReactNode } from 'react';\nimport Text from '../Text/Text';\n\n/**\n * Progress bar size variants\n */\ntype ProgressBarSize = 'small' | 'medium';\n\n/**\n * Progress bar color variants\n */\ntype ProgressBarVariant = 'blue' | 'green';\n\n/**\n * Size configurations using Tailwind classes\n */\nconst SIZE_CLASSES = {\n small: {\n container: 'h-1', // 4px height (h-1 = 4px in Tailwind)\n bar: 'h-1', // 4px height for the fill bar\n labelSize: 'xs' as const,\n spacing: 'gap-2', // 8px gap between label and progress bar\n layout: 'flex-col', // vertical layout for small\n borderRadius: 'rounded-full', // 9999px border radius\n },\n medium: {\n container: 'h-2', // 8px height (h-2 = 8px in Tailwind)\n bar: 'h-2', // 8px height for the fill bar\n labelSize: 'xs' as const, // 12px font size (xs in Tailwind)\n spacing: 'gap-2', // 8px gap between progress bar and label\n layout: 'flex-row items-center', // horizontal layout for medium\n borderRadius: 'rounded-lg', // 8px border radius\n },\n} as const;\n\n/**\n * Color configurations using design system colors\n */\nconst VARIANT_CLASSES = {\n blue: {\n background: 'bg-background-300', // Background track color (#D5D4D4)\n fill: 'bg-primary-700', // Blue for activity progress (#2271C4)\n },\n green: {\n background: 'bg-background-300', // Background track color (#D5D4D4)\n fill: 'bg-success-200', // Green for performance (#84D3A2)\n },\n} as const;\n\n/**\n * ProgressBar component props interface\n */\nexport type ProgressBarProps = {\n /** Progress value between 0 and 100 */\n value: number;\n /** Maximum value (defaults to 100) */\n max?: number;\n /** Size variant of the progress bar */\n size?: ProgressBarSize;\n /** Color variant of the progress bar */\n variant?: ProgressBarVariant;\n /** Optional label to display */\n label?: ReactNode;\n /** Show percentage text */\n showPercentage?: boolean;\n /** Additional CSS classes */\n className?: string;\n /** Label CSS classes */\n labelClassName?: string;\n /** Percentage text CSS classes */\n percentageClassName?: string;\n};\n\n/**\n * ProgressBar component for Analytica Ensino platforms\n *\n * A progress bar component with size and color variants designed for tracking\n * activity progress (blue) and performance metrics (green).\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 progress bar\n * <ProgressBar value={65} />\n *\n * // Activity progress (blue)\n * <ProgressBar variant=\"blue\" value={45} label=\"Progress\" showPercentage />\n *\n * // Performance metrics (green)\n * <ProgressBar variant=\"green\" size=\"medium\" value={85} label=\"Performance\" />\n *\n * // Small size with custom max value\n * <ProgressBar size=\"small\" value={3} max={5} showPercentage />\n * ```\n */\nconst ProgressBar = ({\n value,\n max = 100,\n size = 'medium',\n variant = 'blue',\n label,\n showPercentage = false,\n className = '',\n labelClassName = '',\n percentageClassName = '',\n}: ProgressBarProps) => {\n // Ensure value is within bounds and handle NaN/Infinity\n const safeValue = isNaN(value) ? 0 : value;\n const clampedValue = Math.max(0, Math.min(safeValue, max));\n const percentage = max === 0 ? 0 : (clampedValue / max) * 100;\n\n // Get size and variant classes\n const sizeClasses = SIZE_CLASSES[size];\n const variantClasses = VARIANT_CLASSES[variant];\n\n return (\n <div\n className={`flex ${sizeClasses.layout} ${sizeClasses.spacing} ${className}`}\n >\n {/* For small size: vertical layout with label/percentage on top */}\n {size === 'small' && (label || showPercentage) && (\n <div className=\"flex flex-row items-center justify-between w-full\">\n {/* Label */}\n {label && (\n <Text\n as=\"div\"\n size={sizeClasses.labelSize}\n weight=\"medium\"\n className={`text-text-950 ${labelClassName}`}\n >\n {label}\n </Text>\n )}\n\n {/* Percentage */}\n {showPercentage && (\n <Text\n size={sizeClasses.labelSize}\n weight=\"medium\"\n className={`text-text-700 text-center ${percentageClassName}`}\n >\n {Math.round(percentage)}%\n </Text>\n )}\n </div>\n )}\n\n {/* Progress bar container */}\n <div\n className={`${size === 'medium' ? 'flex-grow' : 'w-full'} ${sizeClasses.container} ${variantClasses.background} ${sizeClasses.borderRadius} overflow-hidden relative`}\n >\n {/* Native progress element for accessibility */}\n <progress\n value={clampedValue}\n max={max}\n aria-label={typeof label === 'string' ? label : 'Progress'}\n className=\"absolute inset-0 w-full h-full opacity-0\"\n />\n\n {/* Progress bar fill */}\n <div\n className={`${sizeClasses.bar} ${variantClasses.fill} ${sizeClasses.borderRadius} transition-all duration-300 ease-out shadow-hard-shadow-3`}\n style={{ width: `${percentage}%` }}\n />\n </div>\n\n {/* For medium size: horizontal layout with percentage on the right */}\n {size === 'medium' && showPercentage && (\n <Text\n size={sizeClasses.labelSize}\n weight=\"medium\"\n className={`text-text-950 text-center flex-none w-[70px] ${percentageClassName}`}\n >\n {Math.round(percentage)}%\n </Text>\n )}\n\n {/* For medium size: label below if provided */}\n {size === 'medium' && label && !showPercentage && (\n <Text\n as=\"div\"\n size={sizeClasses.labelSize}\n weight=\"medium\"\n className={`text-text-950 flex-none ${labelClassName}`}\n >\n {label}\n </Text>\n )}\n </div>\n );\n};\n\nexport default ProgressBar;\n"],"mappings":"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","names":["jsx"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/components/ProgressCircle/ProgressCircle.tsx","../../src/components/Text/Text.tsx"],"sourcesContent":["'use client';\n\nimport { ReactNode } from 'react';\nimport Text from '../Text/Text';\n\n/**\n * Progress circle size variants\n */\ntype ProgressCircleSize = 'small' | 'medium';\n\n/**\n * Progress circle color variants\n */\ntype ProgressCircleVariant = 'blue' | 'green';\n\n/**\n * Size configurations using Tailwind classes\n */\nconst SIZE_CLASSES = {\n small: {\n container: 'w-[90px] h-[90px]', // 90px circle from design specs\n strokeWidth: 4, // 4px stroke width - matches ProgressBar small (h-1)\n textSize: '2xl', // 24px for percentage (font-size: 24px)\n textWeight: 'medium', // font-weight: 500\n labelSize: '2xs' as const, // 10px for status label (closest to 8px design spec)\n labelWeight: 'bold', // font-weight: 700\n spacing: 'gap-1', // 4px gap between percentage and label\n },\n medium: {\n container: 'w-[152px] h-[152px]', // 151.67px ≈ 152px circle from design specs\n strokeWidth: 8, // 8px stroke width - matches ProgressBar medium (h-2)\n textSize: '2xl', // 24px for percentage (font-size: 24px)\n textWeight: 'medium', // font-weight: 500\n labelSize: 'xs' as const, // 12px for status label (font-size: 12px)\n labelWeight: 'medium', // font-weight: 500 (changed from bold)\n spacing: 'gap-1', // 4px gap between percentage and label\n },\n} as const;\n\n/**\n * Color configurations using design system colors\n */\nconst VARIANT_CLASSES = {\n blue: {\n background: 'stroke-primary-100', // Light blue background (#BBDCF7)\n fill: 'stroke-primary-700', // Blue for activity progress (#2271C4)\n textColor: 'text-primary-700', // Blue text color (#2271C4)\n labelColor: 'text-text-700', // Gray text for label (#525252)\n },\n green: {\n background: 'stroke-background-300', // Gray background (#D5D4D4 - matches design)\n fill: 'stroke-success-200', // Green for performance (#84D3A2 - matches design)\n textColor: 'text-text-800', // Dark gray text (#404040 - matches design)\n labelColor: 'text-text-600', // Medium gray text for label (#737373 - matches design)\n },\n} as const;\n\n/**\n * ProgressCircle component props interface\n */\nexport type ProgressCircleProps = {\n /** Progress value between 0 and 100 */\n value: number;\n /** Maximum value (defaults to 100) */\n max?: number;\n /** Size variant of the progress circle */\n size?: ProgressCircleSize;\n /** Color variant of the progress circle */\n variant?: ProgressCircleVariant;\n /** Optional label to display below percentage */\n label?: ReactNode;\n /** Show percentage text */\n showPercentage?: boolean;\n /** Additional CSS classes */\n className?: string;\n /** Label CSS classes */\n labelClassName?: string;\n /** Percentage text CSS classes */\n percentageClassName?: string;\n};\n\n/**\n * ProgressCircle component for Analytica Ensino platforms\n *\n * A circular progress indicator with size and color variants designed for tracking\n * activity progress (blue) and performance metrics (green).\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 progress circle\n * <ProgressCircle value={65} />\n *\n * // Activity progress (blue)\n * <ProgressCircle variant=\"blue\" value={45} label=\"CONCLUÍDO\" showPercentage />\n *\n * // Performance metrics (green)\n * <ProgressCircle variant=\"green\" size=\"medium\" value={85} label=\"MÉDIA\" />\n *\n * // Small size with custom max value\n * <ProgressCircle size=\"small\" value={3} max={5} showPercentage />\n * ```\n */\nconst ProgressCircle = ({\n value,\n max = 100,\n size = 'small',\n variant = 'blue',\n label,\n showPercentage = true,\n className = '',\n labelClassName = '',\n percentageClassName = '',\n}: ProgressCircleProps) => {\n // Ensure value is within bounds and handle NaN/Infinity\n const safeValue = isNaN(value) ? 0 : value;\n const clampedValue = Math.max(0, Math.min(safeValue, max));\n const percentage = max === 0 ? 0 : (clampedValue / max) * 100;\n\n // Get size and variant classes\n const sizeClasses = SIZE_CLASSES[size];\n const variantClasses = VARIANT_CLASSES[variant];\n\n // Calculate SVG dimensions and stroke properties\n const radius = size === 'small' ? 37 : 64; // Radius calculation based on container size\n const circumference = 2 * Math.PI * radius;\n const strokeDashoffset = circumference - (percentage / 100) * circumference;\n const center = size === 'small' ? 45 : 76; // Center point of SVG\n const svgSize = size === 'small' ? 90 : 152; // SVG viewBox size\n\n return (\n <div\n className={`relative flex flex-col items-center justify-center ${sizeClasses.container} rounded-lg ${className}`}\n >\n {/* Progress circle SVG */}\n <svg\n className=\"absolute inset-0 transform -rotate-90\"\n width={svgSize}\n height={svgSize}\n viewBox={`0 0 ${svgSize} ${svgSize}`}\n aria-hidden=\"true\"\n >\n {/* Background circle */}\n <circle\n cx={center}\n cy={center}\n r={radius}\n fill=\"none\"\n strokeWidth={sizeClasses.strokeWidth}\n className={`${variantClasses.background} rounded-lg`}\n />\n {/* Progress circle - SVG stroke properties require style for animation */}\n <circle\n cx={center}\n cy={center}\n r={radius}\n fill=\"none\"\n strokeWidth={sizeClasses.strokeWidth}\n strokeLinecap=\"round\"\n strokeDasharray={circumference}\n strokeDashoffset={strokeDashoffset}\n className={`${variantClasses.fill} transition-all duration-500 ease-out shadow-soft-shadow-3 rounded-lg`}\n />\n </svg>\n\n {/* Native progress element for accessibility */}\n <progress\n value={clampedValue}\n max={max}\n aria-label={typeof label === 'string' ? label : 'Progress'}\n className=\"absolute opacity-0 w-0 h-0\"\n />\n\n {/* Content overlay - centered content */}\n <div\n className={`relative z-10 flex flex-col items-center justify-center ${sizeClasses.spacing}`}\n >\n {/* Percentage text */}\n {showPercentage && (\n <Text\n size={sizeClasses.textSize}\n weight={sizeClasses.textWeight}\n className={`text-center ${variantClasses.textColor} ${percentageClassName}`}\n >\n {Math.round(percentage)}%\n </Text>\n )}\n\n {/* Label text */}\n {label && (\n <Text\n as=\"span\"\n size={sizeClasses.labelSize}\n weight={sizeClasses.labelWeight}\n className={`${variantClasses.labelColor} text-center uppercase tracking-wide ${labelClassName}`}\n >\n {label}\n </Text>\n )}\n </div>\n </div>\n );\n};\n\nexport default ProgressCircle;\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"]}
|
|
1
|
+
{"version":3,"sources":["../../src/components/ProgressCircle/ProgressCircle.tsx","../../src/components/Text/Text.tsx"],"sourcesContent":["import { ReactNode } from 'react';\nimport Text from '../Text/Text';\n\n/**\n * Progress circle size variants\n */\ntype ProgressCircleSize = 'small' | 'medium';\n\n/**\n * Progress circle color variants\n */\ntype ProgressCircleVariant = 'blue' | 'green';\n\n/**\n * Size configurations using Tailwind classes\n */\nconst SIZE_CLASSES = {\n small: {\n container: 'w-[90px] h-[90px]', // 90px circle from design specs\n strokeWidth: 4, // 4px stroke width - matches ProgressBar small (h-1)\n textSize: '2xl', // 24px for percentage (font-size: 24px)\n textWeight: 'medium', // font-weight: 500\n labelSize: '2xs' as const, // 10px for status label (closest to 8px design spec)\n labelWeight: 'bold', // font-weight: 700\n spacing: 'gap-1', // 4px gap between percentage and label\n },\n medium: {\n container: 'w-[152px] h-[152px]', // 151.67px ≈ 152px circle from design specs\n strokeWidth: 8, // 8px stroke width - matches ProgressBar medium (h-2)\n textSize: '2xl', // 24px for percentage (font-size: 24px)\n textWeight: 'medium', // font-weight: 500\n labelSize: 'xs' as const, // 12px for status label (font-size: 12px)\n labelWeight: 'medium', // font-weight: 500 (changed from bold)\n spacing: 'gap-1', // 4px gap between percentage and label\n },\n} as const;\n\n/**\n * Color configurations using design system colors\n */\nconst VARIANT_CLASSES = {\n blue: {\n background: 'stroke-primary-100', // Light blue background (#BBDCF7)\n fill: 'stroke-primary-700', // Blue for activity progress (#2271C4)\n textColor: 'text-primary-700', // Blue text color (#2271C4)\n labelColor: 'text-text-700', // Gray text for label (#525252)\n },\n green: {\n background: 'stroke-background-300', // Gray background (#D5D4D4 - matches design)\n fill: 'stroke-success-200', // Green for performance (#84D3A2 - matches design)\n textColor: 'text-text-800', // Dark gray text (#404040 - matches design)\n labelColor: 'text-text-600', // Medium gray text for label (#737373 - matches design)\n },\n} as const;\n\n/**\n * ProgressCircle component props interface\n */\nexport type ProgressCircleProps = {\n /** Progress value between 0 and 100 */\n value: number;\n /** Maximum value (defaults to 100) */\n max?: number;\n /** Size variant of the progress circle */\n size?: ProgressCircleSize;\n /** Color variant of the progress circle */\n variant?: ProgressCircleVariant;\n /** Optional label to display below percentage */\n label?: ReactNode;\n /** Show percentage text */\n showPercentage?: boolean;\n /** Additional CSS classes */\n className?: string;\n /** Label CSS classes */\n labelClassName?: string;\n /** Percentage text CSS classes */\n percentageClassName?: string;\n};\n\n/**\n * ProgressCircle component for Analytica Ensino platforms\n *\n * A circular progress indicator with size and color variants designed for tracking\n * activity progress (blue) and performance metrics (green).\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 progress circle\n * <ProgressCircle value={65} />\n *\n * // Activity progress (blue)\n * <ProgressCircle variant=\"blue\" value={45} label=\"CONCLUÍDO\" showPercentage />\n *\n * // Performance metrics (green)\n * <ProgressCircle variant=\"green\" size=\"medium\" value={85} label=\"MÉDIA\" />\n *\n * // Small size with custom max value\n * <ProgressCircle size=\"small\" value={3} max={5} showPercentage />\n * ```\n */\nconst ProgressCircle = ({\n value,\n max = 100,\n size = 'small',\n variant = 'blue',\n label,\n showPercentage = true,\n className = '',\n labelClassName = '',\n percentageClassName = '',\n}: ProgressCircleProps) => {\n // Ensure value is within bounds and handle NaN/Infinity\n const safeValue = isNaN(value) ? 0 : value;\n const clampedValue = Math.max(0, Math.min(safeValue, max));\n const percentage = max === 0 ? 0 : (clampedValue / max) * 100;\n\n // Get size and variant classes\n const sizeClasses = SIZE_CLASSES[size];\n const variantClasses = VARIANT_CLASSES[variant];\n\n // Calculate SVG dimensions and stroke properties\n const radius = size === 'small' ? 37 : 64; // Radius calculation based on container size\n const circumference = 2 * Math.PI * radius;\n const strokeDashoffset = circumference - (percentage / 100) * circumference;\n const center = size === 'small' ? 45 : 76; // Center point of SVG\n const svgSize = size === 'small' ? 90 : 152; // SVG viewBox size\n\n return (\n <div\n className={`relative flex flex-col items-center justify-center ${sizeClasses.container} rounded-lg ${className}`}\n >\n {/* Progress circle SVG */}\n <svg\n className=\"absolute inset-0 transform -rotate-90\"\n width={svgSize}\n height={svgSize}\n viewBox={`0 0 ${svgSize} ${svgSize}`}\n aria-hidden=\"true\"\n >\n {/* Background circle */}\n <circle\n cx={center}\n cy={center}\n r={radius}\n fill=\"none\"\n strokeWidth={sizeClasses.strokeWidth}\n className={`${variantClasses.background} rounded-lg`}\n />\n {/* Progress circle - SVG stroke properties require style for animation */}\n <circle\n cx={center}\n cy={center}\n r={radius}\n fill=\"none\"\n strokeWidth={sizeClasses.strokeWidth}\n strokeLinecap=\"round\"\n strokeDasharray={circumference}\n strokeDashoffset={strokeDashoffset}\n className={`${variantClasses.fill} transition-all duration-500 ease-out shadow-soft-shadow-3 rounded-lg`}\n />\n </svg>\n\n {/* Native progress element for accessibility */}\n <progress\n value={clampedValue}\n max={max}\n aria-label={typeof label === 'string' ? label : 'Progress'}\n className=\"absolute opacity-0 w-0 h-0\"\n />\n\n {/* Content overlay - centered content */}\n <div\n className={`relative z-10 flex flex-col items-center justify-center ${sizeClasses.spacing}`}\n >\n {/* Percentage text */}\n {showPercentage && (\n <Text\n size={sizeClasses.textSize}\n weight={sizeClasses.textWeight}\n className={`text-center ${variantClasses.textColor} ${percentageClassName}`}\n >\n {Math.round(percentage)}%\n </Text>\n )}\n\n {/* Label text */}\n {label && (\n <Text\n as=\"span\"\n size={sizeClasses.labelSize}\n weight={sizeClasses.labelWeight}\n className={`${variantClasses.labelColor} text-center uppercase tracking-wide ${labelClassName}`}\n >\n {label}\n </Text>\n )}\n </div>\n </div>\n );\n};\n\nexport default ProgressCircle;\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 *\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"]}
|