@fabio.caffarello/react-design-system 4.5.0 → 4.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/granular/ui/components/Stat/StatGroup.js +51 -36
- package/dist/granular/ui/components/Stat/StatGroup.js.map +1 -1
- package/dist/granular/ui/primitives/Avatar/Avatar.js +39 -34
- package/dist/granular/ui/primitives/Avatar/Avatar.js.map +1 -1
- package/dist/index.cjs +10 -10
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +601 -582
- package/dist/index.js.map +1 -1
- package/dist/react-design-system.css +1 -1
- package/dist/server/index.cjs +13 -13
- package/dist/server/index.cjs.map +1 -1
- package/dist/server/index.js +331 -317
- package/dist/server/index.js.map +1 -1
- package/dist/ui/components/Stat/StatGroup.d.ts +59 -11
- package/dist/ui/primitives/Avatar/Avatar.d.ts +38 -6
- package/package.json +1 -1
|
@@ -1,61 +1,76 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
var
|
|
3
|
-
var
|
|
4
|
-
var
|
|
5
|
-
var
|
|
6
|
-
var
|
|
7
|
-
for (var
|
|
8
|
-
|
|
9
|
-
if (
|
|
10
|
-
for (var
|
|
11
|
-
|
|
2
|
+
var b = Object.defineProperty, v = Object.defineProperties;
|
|
3
|
+
var h = Object.getOwnPropertyDescriptors;
|
|
4
|
+
var l = Object.getOwnPropertySymbols;
|
|
5
|
+
var o = Object.prototype.hasOwnProperty, a = Object.prototype.propertyIsEnumerable;
|
|
6
|
+
var t = (r, e, s) => e in r ? b(r, e, { enumerable: !0, configurable: !0, writable: !0, value: s }) : r[e] = s, c = (r, e) => {
|
|
7
|
+
for (var s in e || (e = {}))
|
|
8
|
+
o.call(e, s) && t(r, s, e[s]);
|
|
9
|
+
if (l)
|
|
10
|
+
for (var s of l(e))
|
|
11
|
+
a.call(e, s) && t(r, s, e[s]);
|
|
12
12
|
return r;
|
|
13
|
-
}, m = (r,
|
|
14
|
-
var n = (r,
|
|
15
|
-
var
|
|
16
|
-
for (var
|
|
17
|
-
|
|
18
|
-
if (r != null &&
|
|
19
|
-
for (var
|
|
20
|
-
|
|
21
|
-
return
|
|
13
|
+
}, m = (r, e) => v(r, h(e));
|
|
14
|
+
var n = (r, e) => {
|
|
15
|
+
var s = {};
|
|
16
|
+
for (var i in r)
|
|
17
|
+
o.call(r, i) && e.indexOf(i) < 0 && (s[i] = r[i]);
|
|
18
|
+
if (r != null && l)
|
|
19
|
+
for (var i of l(r))
|
|
20
|
+
e.indexOf(i) < 0 && a.call(r, i) && (s[i] = r[i]);
|
|
21
|
+
return s;
|
|
22
22
|
};
|
|
23
|
-
import { jsx as
|
|
24
|
-
import { getRadiusClass as
|
|
25
|
-
import {
|
|
23
|
+
import { jsxs as C, jsx as p } from "react/jsx-runtime";
|
|
24
|
+
import { getRadiusClass as N } from "../../tokens/radius.js";
|
|
25
|
+
import { getSpacingClass as j } from "../../tokens/spacing.js";
|
|
26
|
+
import { cn as g } from "../../utils/cn.js";
|
|
26
27
|
const G = {
|
|
27
28
|
2: "md:grid-cols-2",
|
|
28
29
|
3: "md:grid-cols-3",
|
|
29
30
|
4: "md:grid-cols-4"
|
|
30
31
|
};
|
|
31
|
-
function
|
|
32
|
-
var
|
|
32
|
+
function $(S) {
|
|
33
|
+
var d = S, {
|
|
33
34
|
layout: r = "grid",
|
|
34
|
-
cols:
|
|
35
|
+
cols: e = 4,
|
|
36
|
+
floatingBadge: s,
|
|
35
37
|
className: i,
|
|
36
|
-
children:
|
|
37
|
-
} =
|
|
38
|
+
children: u
|
|
39
|
+
} = d, f = n(d, [
|
|
38
40
|
"layout",
|
|
39
41
|
"cols",
|
|
42
|
+
"floatingBadge",
|
|
40
43
|
"className",
|
|
41
44
|
"children"
|
|
42
45
|
]);
|
|
43
|
-
const
|
|
44
|
-
return /* @__PURE__ */
|
|
46
|
+
const x = r === "grid";
|
|
47
|
+
return /* @__PURE__ */ C(
|
|
45
48
|
"div",
|
|
46
49
|
m(c({
|
|
47
|
-
className:
|
|
48
|
-
"
|
|
49
|
-
|
|
50
|
-
f ? `grid grid-cols-2 ${G[d]}` : "flex",
|
|
50
|
+
className: g(
|
|
51
|
+
"relative",
|
|
52
|
+
s && j("base", "pt"),
|
|
51
53
|
i
|
|
52
54
|
)
|
|
53
|
-
},
|
|
54
|
-
children:
|
|
55
|
+
}, f), {
|
|
56
|
+
children: [
|
|
57
|
+
s ? /* @__PURE__ */ p("div", { className: "absolute top-4 left-1/2 -translate-x-1/2 -translate-y-1/2 z-10", children: s }) : null,
|
|
58
|
+
/* @__PURE__ */ p(
|
|
59
|
+
"div",
|
|
60
|
+
{
|
|
61
|
+
className: g(
|
|
62
|
+
"bg-line-default border border-line-default overflow-hidden gap-px",
|
|
63
|
+
N("lg"),
|
|
64
|
+
x ? `grid grid-cols-2 ${G[e]}` : "flex"
|
|
65
|
+
),
|
|
66
|
+
children: u
|
|
67
|
+
}
|
|
68
|
+
)
|
|
69
|
+
]
|
|
55
70
|
})
|
|
56
71
|
);
|
|
57
72
|
}
|
|
58
73
|
export {
|
|
59
|
-
|
|
74
|
+
$ as StatGroup
|
|
60
75
|
};
|
|
61
76
|
//# sourceMappingURL=StatGroup.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StatGroup.js","sources":["../../../../../src/ui/components/Stat/StatGroup.tsx"],"sourcesContent":["import { type HTMLAttributes, type ReactNode } from \"react\";\nimport { cn } from \"../../utils\";\nimport { getRadiusClass } from \"../../tokens/radius\";\n\nexport type StatGroupLayout = \"strip\" | \"grid\";\nexport type StatGroupCols = 2 | 3 | 4;\n\nexport interface StatGroupProps extends HTMLAttributes<HTMLDivElement> {\n /**\n * `strip` — single horizontal row, no wrap. Each `Stat` shares the row\n * width via `flex-1`. Use when you guarantee the horizontal space\n * (hero areas, wide dashboards). On narrow viewports the row does NOT\n * reflow — choose `grid` if you need responsive collapse.\n *\n * `grid` — multi-column grid that reflows. Always 2-up on mobile,\n * expands to `cols` columns at the `md` breakpoint (768 px) and up.\n * Five or more children spill to a second row with the divider lines\n * preserved.\n *\n * @default 'grid'\n */\n layout?: StatGroupLayout;\n /**\n * Desktop column count (≥ 768 px). Only effective in `layout=\"grid\"`;\n * ignored in `layout=\"strip\"`. Mobile is always 2 columns regardless.\n *\n * @default 4\n */\n cols?: StatGroupCols;\n children: ReactNode;\n}\n\n// Tailwind v4 generates `md:grid-cols-N` for N ∈ {2,3,4} statically from\n// the literal class string. The map below ensures the strings exist\n// verbatim in the source so JIT picks them up.\nconst gridColsMd: Record<StatGroupCols, string> = {\n 2: \"md:grid-cols-2\",\n 3: \"md:grid-cols-3\",\n 4: \"md:grid-cols-4\",\n};\n\n/**\n * `StatGroup` — container for one or more `Stat` blocks with 1-px\n * dividers between them.\n *\n * ### Divider technique\n *\n * The container has `bg-line-default` and `gap-px` (1 px); each
|
|
1
|
+
{"version":3,"file":"StatGroup.js","sources":["../../../../../src/ui/components/Stat/StatGroup.tsx"],"sourcesContent":["import { type HTMLAttributes, type ReactNode } from \"react\";\nimport { cn } from \"../../utils\";\nimport { getRadiusClass } from \"../../tokens/radius\";\nimport { getSpacingClass } from \"../../tokens/spacing\";\n\nexport type StatGroupLayout = \"strip\" | \"grid\";\nexport type StatGroupCols = 2 | 3 | 4;\n\nexport interface StatGroupProps extends HTMLAttributes<HTMLDivElement> {\n /**\n * `strip` — single horizontal row, no wrap. Each `Stat` shares the row\n * width via `flex-1`. Use when you guarantee the horizontal space\n * (hero areas, wide dashboards). On narrow viewports the row does NOT\n * reflow — choose `grid` if you need responsive collapse.\n *\n * `grid` — multi-column grid that reflows. Always 2-up on mobile,\n * expands to `cols` columns at the `md` breakpoint (768 px) and up.\n * Five or more children spill to a second row with the divider lines\n * preserved.\n *\n * @default 'grid'\n */\n layout?: StatGroupLayout;\n /**\n * Desktop column count (≥ 768 px). Only effective in `layout=\"grid\"`;\n * ignored in `layout=\"strip\"`. Mobile is always 2 columns regardless.\n *\n * @default 4\n */\n cols?: StatGroupCols;\n /**\n * Optional slot for a badge that floats centered over the top border of\n * the container. Use when all metrics in the group share a common\n * provenance mark (e.g. a trust badge, data-source seal, tier label).\n *\n * The slot is intentionally opaque — the consumer supplies any ReactNode\n * and owns the badge's styling and a11y. `StatGroup` provides only the\n * positioning, not the badge shape. This is the same convention as the\n * `kicker` slot in `HeroSection` or the `badge` slot in `PageHeader`.\n *\n * ### Layout\n *\n * When `floatingBadge` is supplied the outer container gains\n * `pt-4` (16 px) top padding, which creates a landing zone for the\n * badge's bottom half while keeping the first stat row clear. The badge\n * itself is absolutely centred at `top-4 left-1/2`, then shifted up by\n * `−50%` of its own height so its centre sits on the inner container's\n * top border. This calibration is accurate for badges up to ~32 px tall\n * (a standard `Badge` or small `Chip`). If a taller badge is needed,\n * pass a `className` that increases the top padding to match.\n *\n * ### Reading order\n *\n * The badge node appears in the DOM **before** the stat cells, so screen\n * readers encounter it first — \"Fonte oficial, followed by the metrics\" —\n * which is the correct contextual order.\n *\n * @example\n * ```tsx\n * import { CheckCircle2 } from \"lucide-react\";\n * import { Badge } from \"@fabio.caffarello/react-design-system\";\n *\n * <StatGroup\n * layout=\"strip\"\n * floatingBadge={\n * <Badge variant=\"success\" size=\"sm\">\n * <CheckCircle2 size={10} aria-hidden=\"true\" />\n * Fonte oficial\n * </Badge>\n * }\n * >\n * <Stat icon={<Users />} value=\"726\" label=\"Parlam.\" align=\"center\" />\n * <Stat icon={<FileText />} value=\"28,1 mil\" label=\"Proposições\" align=\"center\" />\n * </StatGroup>\n * ```\n */\n floatingBadge?: ReactNode;\n children: ReactNode;\n}\n\n// Tailwind v4 generates `md:grid-cols-N` for N ∈ {2,3,4} statically from\n// the literal class string. The map below ensures the strings exist\n// verbatim in the source so JIT picks them up.\nconst gridColsMd: Record<StatGroupCols, string> = {\n 2: \"md:grid-cols-2\",\n 3: \"md:grid-cols-3\",\n 4: \"md:grid-cols-4\",\n};\n\n/**\n * `StatGroup` — container for one or more `Stat` blocks with 1-px\n * dividers between them.\n *\n * ### Divider technique\n *\n * The inner container has `bg-line-default` and `gap-px` (1 px); each\n * child `Stat` carries its own `bg-surface-base`. The 1 px of gap exposes\n * the container's background as the divider line, while each cell masks\n * its own area with `bg-surface-base`. Works identically for the strip\n * layout (vertical dividers) and the grid layout (vertical AND horizontal\n * dividers, automatically, as the grid reflows). No separate `Divider`\n * component, no per-cell border logic.\n *\n * The inner ring is `border border-line-default` matching the gap color,\n * with `rounded-lg` and `overflow-hidden` clipping the inner cells to the\n * radius. The outer wrapper is `relative` so the optional `floatingBadge`\n * can be absolutely positioned over the inner container's top border.\n *\n * ### Server-safe\n *\n * Pure presentation — no hooks, no event handlers on the DOM. Ships in\n * `./server` alongside `Stat`.\n *\n * @example\n * ```tsx\n * <StatGroup layout=\"strip\">\n * <Stat icon={<Users />} value=\"9,4 mil\" label=\"Parlamentares\" align=\"center\" />\n * <Stat icon={<FileText />} value=\"3,2 mil\" label=\"Proposições\" align=\"center\" />\n * <Stat icon={<Vote />} value=\"1,1 mil\" label=\"Votações\" align=\"center\" />\n * <Stat icon={<Clock />} value=\"há 18 dias\" label=\"Última atualização\" align=\"center\" />\n * </StatGroup>\n *\n * <StatGroup layout=\"grid\" cols={4}>\n * <Stat value=\"87%\" label=\"Alinhamento\" hint=\"últimos 12 m\" tone=\"success\" />\n * <Stat value={null} label=\"Sem orientação\" hint=\"no período\" />\n * <Stat value=\"R$ 187.472,95\" label=\"Gastos\" hint=\"no mandato\" />\n * <Stat value=\"42\" label=\"Votações\" hint=\"no banco\" />\n * </StatGroup>\n * ```\n */\nexport function StatGroup({\n layout = \"grid\",\n cols = 4,\n floatingBadge,\n className,\n children,\n ...props\n}: StatGroupProps) {\n const isGrid = layout === \"grid\";\n\n return (\n <div\n className={cn(\n \"relative\",\n floatingBadge && getSpacingClass(\"base\", \"pt\"),\n className,\n )}\n {...props}\n >\n {floatingBadge ? (\n <div className=\"absolute top-4 left-1/2 -translate-x-1/2 -translate-y-1/2 z-10\">\n {floatingBadge}\n </div>\n ) : null}\n <div\n className={cn(\n \"bg-line-default border border-line-default overflow-hidden gap-px\",\n getRadiusClass(\"lg\"),\n isGrid ? `grid grid-cols-2 ${gridColsMd[cols]}` : \"flex\",\n )}\n >\n {children}\n </div>\n </div>\n );\n}\n\nexport default StatGroup;\n"],"names":["gridColsMd","StatGroup","_a","_b","layout","cols","floatingBadge","className","children","props","__objRest","isGrid","jsxs","__spreadProps","__spreadValues","cn","getSpacingClass","jsx","getRadiusClass"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAmFA,MAAMA,IAA4C;AAAA,EAChD,GAAG;AAAA,EACH,GAAG;AAAA,EACH,GAAG;AACL;AA2CO,SAASC,EAAUC,GAOP;AAPO,MAAAC,IAAAD,GACxB;AAAA,YAAAE,IAAS;AAAA,IACT,MAAAC,IAAO;AAAA,IACP,eAAAC;AAAA,IACA,WAAAC;AAAA,IACA,UAAAC;AAAA,MALwBL,GAMrBM,IAAAC,EANqBP,GAMrB;AAAA,IALH;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA;AAGA,QAAMQ,IAASP,MAAW;AAE1B,SACE,gBAAAQ;AAAA,IAAC;AAAA,IAAAC,EAAAC,EAAA;AAAA,MACC,WAAWC;AAAA,QACT;AAAA,QACAT,KAAiBU,EAAgB,QAAQ,IAAI;AAAA,QAC7CT;AAAA,MAAA;AAAA,OAEEE,IANL;AAAA,MAQE,UAAA;AAAA,QAAAH,IACC,gBAAAW,EAAC,OAAA,EAAI,WAAU,kEACZ,aACH,IACE;AAAA,QACJ,gBAAAA;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,WAAWF;AAAA,cACT;AAAA,cACAG,EAAe,IAAI;AAAA,cACnBP,IAAS,oBAAoBX,EAAWK,CAAI,CAAC,KAAK;AAAA,YAAA;AAAA,YAGnD,UAAAG;AAAA,UAAA;AAAA,QAAA;AAAA,MACH;AAAA,IAAA;AAAA,EAAA;AAGN;"}
|
|
@@ -1,62 +1,66 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
var
|
|
3
|
-
var
|
|
2
|
+
var k = Object.defineProperty, q = Object.defineProperties;
|
|
3
|
+
var z = Object.getOwnPropertyDescriptors;
|
|
4
4
|
var s = Object.getOwnPropertySymbols;
|
|
5
|
-
var u = Object.prototype.hasOwnProperty,
|
|
6
|
-
var f = (t, e, a) => e in t ?
|
|
5
|
+
var u = Object.prototype.hasOwnProperty, x = Object.prototype.propertyIsEnumerable;
|
|
6
|
+
var f = (t, e, a) => e in t ? k(t, e, { enumerable: !0, configurable: !0, writable: !0, value: a }) : t[e] = a, h = (t, e) => {
|
|
7
7
|
for (var a in e || (e = {}))
|
|
8
8
|
u.call(e, a) && f(t, a, e[a]);
|
|
9
9
|
if (s)
|
|
10
10
|
for (var a of s(e))
|
|
11
|
-
|
|
11
|
+
x.call(e, a) && f(t, a, e[a]);
|
|
12
12
|
return t;
|
|
13
|
-
},
|
|
13
|
+
}, p = (t, e) => q(t, z(e));
|
|
14
14
|
var g = (t, e) => {
|
|
15
15
|
var a = {};
|
|
16
16
|
for (var r in t)
|
|
17
17
|
u.call(t, r) && e.indexOf(r) < 0 && (a[r] = t[r]);
|
|
18
18
|
if (t != null && s)
|
|
19
19
|
for (var r of s(t))
|
|
20
|
-
e.indexOf(r) < 0 &&
|
|
20
|
+
e.indexOf(r) < 0 && x.call(t, r) && (a[r] = t[r]);
|
|
21
21
|
return a;
|
|
22
22
|
};
|
|
23
|
-
import { jsxs as
|
|
24
|
-
import { forwardRef as
|
|
23
|
+
import { jsxs as S, jsx as w } from "react/jsx-runtime";
|
|
24
|
+
import { forwardRef as B, useState as y } from "react";
|
|
25
25
|
import { getRadiusClass as o } from "../../tokens/radius.js";
|
|
26
26
|
import { cn as n } from "../../utils/cn.js";
|
|
27
|
-
const
|
|
28
|
-
var c =
|
|
27
|
+
const D = B(function(G, L) {
|
|
28
|
+
var c = G, {
|
|
29
29
|
src: e,
|
|
30
30
|
alt: a,
|
|
31
31
|
fallback: r,
|
|
32
32
|
size: v = "md",
|
|
33
|
-
variant:
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
33
|
+
variant: l = "circle",
|
|
34
|
+
loading: b = "eager",
|
|
35
|
+
"aria-label": j,
|
|
36
|
+
className: A = ""
|
|
37
|
+
} = c, C = g(c, [
|
|
37
38
|
"src",
|
|
38
39
|
"alt",
|
|
39
40
|
"fallback",
|
|
40
41
|
"size",
|
|
41
42
|
"variant",
|
|
43
|
+
"loading",
|
|
42
44
|
"aria-label",
|
|
43
45
|
"className"
|
|
44
46
|
]);
|
|
45
|
-
const [
|
|
47
|
+
const [N, E] = y(!1), [F, m] = y(!1), I = {
|
|
46
48
|
xs: "h-6 w-6 text-xs",
|
|
47
49
|
sm: "h-8 w-8 text-sm",
|
|
48
50
|
md: "h-10 w-10 text-base",
|
|
49
51
|
lg: "h-12 w-12 text-lg",
|
|
50
|
-
xl: "h-16 w-16 text-xl"
|
|
51
|
-
|
|
52
|
+
xl: "h-16 w-16 text-xl",
|
|
53
|
+
"2xl": "h-24 w-24 text-3xl",
|
|
54
|
+
"3xl": "h-28 w-28 text-4xl"
|
|
55
|
+
}, i = {
|
|
52
56
|
circle: o("full"),
|
|
53
57
|
square: o("none"),
|
|
54
58
|
rounded: o("md")
|
|
55
|
-
}, d = !e ||
|
|
56
|
-
return /* @__PURE__ */
|
|
59
|
+
}, d = !e || N, R = typeof r == "string" ? r.toUpperCase().slice(0, 2) : r, U = j || a || "User avatar";
|
|
60
|
+
return /* @__PURE__ */ S(
|
|
57
61
|
"div",
|
|
58
|
-
h(
|
|
59
|
-
ref:
|
|
62
|
+
p(h({
|
|
63
|
+
ref: L,
|
|
60
64
|
className: n(
|
|
61
65
|
"relative",
|
|
62
66
|
"inline-flex",
|
|
@@ -65,33 +69,34 @@ const B = S(function(D, C) {
|
|
|
65
69
|
"shrink-0",
|
|
66
70
|
"font-medium",
|
|
67
71
|
"overflow-hidden",
|
|
68
|
-
|
|
69
|
-
l
|
|
72
|
+
I[v],
|
|
73
|
+
i[l],
|
|
70
74
|
"bg-surface-muted",
|
|
71
75
|
"text-fg-primary",
|
|
72
|
-
|
|
76
|
+
A
|
|
73
77
|
),
|
|
74
78
|
role: "img",
|
|
75
|
-
"aria-label":
|
|
76
|
-
},
|
|
79
|
+
"aria-label": U
|
|
80
|
+
}, C), {
|
|
77
81
|
children: [
|
|
78
82
|
!d && e && /* @__PURE__ */ w(
|
|
79
83
|
"img",
|
|
80
84
|
{
|
|
81
85
|
src: e,
|
|
82
86
|
alt: a || "",
|
|
87
|
+
loading: b,
|
|
83
88
|
className: n(
|
|
84
89
|
"w-full",
|
|
85
90
|
"h-full",
|
|
86
91
|
"object-cover",
|
|
87
|
-
l
|
|
88
|
-
|
|
92
|
+
i[l],
|
|
93
|
+
F ? "opacity-100" : "opacity-0",
|
|
89
94
|
"transition-opacity",
|
|
90
95
|
"duration-200"
|
|
91
96
|
),
|
|
92
97
|
onLoad: () => m(!0),
|
|
93
98
|
onError: () => {
|
|
94
|
-
|
|
99
|
+
E(!0), m(!1);
|
|
95
100
|
},
|
|
96
101
|
"aria-hidden": "true"
|
|
97
102
|
}
|
|
@@ -105,18 +110,18 @@ const B = S(function(D, C) {
|
|
|
105
110
|
"justify-center",
|
|
106
111
|
"w-full",
|
|
107
112
|
"h-full",
|
|
108
|
-
l
|
|
113
|
+
i[l]
|
|
109
114
|
),
|
|
110
115
|
"aria-hidden": "true",
|
|
111
|
-
children:
|
|
116
|
+
children: R || "?"
|
|
112
117
|
}
|
|
113
118
|
)
|
|
114
119
|
]
|
|
115
120
|
})
|
|
116
121
|
);
|
|
117
122
|
});
|
|
118
|
-
|
|
123
|
+
D.displayName = "Avatar";
|
|
119
124
|
export {
|
|
120
|
-
|
|
125
|
+
D as default
|
|
121
126
|
};
|
|
122
127
|
//# sourceMappingURL=Avatar.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Avatar.js","sources":["../../../../../src/ui/primitives/Avatar/Avatar.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n useState,\n forwardRef,\n type HTMLAttributes,\n type ReactNode,\n} from \"react\";\nimport { getRadiusClass } from \"../../tokens/radius\";\nimport { cn } from \"../../utils\";\n\nexport type AvatarSize = \"xs\" | \"sm\" | \"md\" | \"lg\" | \"xl\";\n\nexport interface AvatarProps extends Omit<\n HTMLAttributes<HTMLDivElement>,\n \"children\"\n> {\n src?: string;\n alt?: string;\n fallback?: string | ReactNode;\n size?: AvatarSize;\n variant?: \"circle\" | \"square\" | \"rounded\";\n \"aria-label\"?: string;\n}\n\n/**\n * Avatar Component\n *\n * A versatile avatar component for displaying user profile images or
|
|
1
|
+
{"version":3,"file":"Avatar.js","sources":["../../../../../src/ui/primitives/Avatar/Avatar.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n useState,\n forwardRef,\n type HTMLAttributes,\n type ReactNode,\n} from \"react\";\nimport { getRadiusClass } from \"../../tokens/radius\";\nimport { cn } from \"../../utils\";\n\nexport type AvatarSize = \"xs\" | \"sm\" | \"md\" | \"lg\" | \"xl\" | \"2xl\" | \"3xl\";\n\nexport interface AvatarProps extends Omit<\n HTMLAttributes<HTMLDivElement>,\n \"children\"\n> {\n src?: string;\n alt?: string;\n fallback?: string | ReactNode;\n size?: AvatarSize;\n variant?: \"circle\" | \"square\" | \"rounded\";\n \"aria-label\"?: string;\n /**\n * Controls the browser's native lazy-loading behaviour for the avatar\n * `<img>`. Set to `\"lazy\"` to defer loading until the avatar is near the\n * viewport — strongly recommended for listings with many off-screen\n * profile images (e.g. a 24-card parliament listing).\n *\n * Maps directly to the native `<img loading>` attribute and has no effect\n * when `src` is absent (no `<img>` is rendered).\n *\n * @default 'eager'\n */\n loading?: \"lazy\" | \"eager\";\n}\n\n/**\n * Avatar Component\n *\n * A versatile avatar component for displaying user profile images or\n * initials. Supports fallback display when image fails to load or is not\n * provided. Fully accessible with ARIA attributes.\n *\n * ### Size scale\n *\n * | size | px | Use case |\n * |------|-----|---------------------------------|\n * | xs | 24 | Tight inline / notification dot |\n * | sm | 32 | Comment thread, compact row |\n * | md | 40 | Default — card header, form row |\n * | lg | 48 | Expanded card, sidebar profile |\n * | xl | 64 | Detail-page section header |\n * | 2xl | 96 | Hero profile (PerfilHeader) |\n * | 3xl | 112 | Full-bleed hero cover |\n *\n * ### Lazy loading\n *\n * Pass `loading=\"lazy\"` on listings to defer off-screen image loads. The\n * default is `\"eager\"` (matches browser default) for backward compatibility.\n *\n * @example\n * ```tsx\n * // With image\n * <Avatar src=\"/user.jpg\" alt=\"John Doe\" />\n *\n * // With fallback initials\n * <Avatar fallback=\"JD\" alt=\"John Doe\" />\n *\n * // Hero profile — larger size + lazy load\n * <Avatar src=\"/perfil.jpg\" alt=\"Dep. Silva\" size=\"2xl\" />\n *\n * // Listing — lazy-load all avatars below the fold\n * <Avatar src=\"/user.jpg\" alt=\"User Name\" loading=\"lazy\" />\n * ```\n */\nconst Avatar = forwardRef<HTMLDivElement, AvatarProps>(function Avatar(\n {\n src,\n alt,\n fallback,\n size = \"md\",\n variant = \"circle\",\n loading = \"eager\",\n \"aria-label\": ariaLabel,\n className = \"\",\n ...props\n },\n ref,\n) {\n const [imageError, setImageError] = useState(false);\n const [imageLoaded, setImageLoaded] = useState(false);\n\n const sizeClasses: Record<AvatarSize, string> = {\n xs: \"h-6 w-6 text-xs\",\n sm: \"h-8 w-8 text-sm\",\n md: \"h-10 w-10 text-base\",\n lg: \"h-12 w-12 text-lg\",\n xl: \"h-16 w-16 text-xl\",\n \"2xl\": \"h-24 w-24 text-3xl\",\n \"3xl\": \"h-28 w-28 text-4xl\",\n };\n\n const variantClasses = {\n circle: getRadiusClass(\"full\"),\n square: getRadiusClass(\"none\"),\n rounded: getRadiusClass(\"md\"),\n };\n\n const showFallback = !src || imageError;\n const displayFallback =\n typeof fallback === \"string\"\n ? fallback.toUpperCase().slice(0, 2)\n : fallback;\n\n const defaultAriaLabel = ariaLabel || alt || \"User avatar\";\n\n return (\n <div\n ref={ref}\n className={cn(\n \"relative\",\n \"inline-flex\",\n \"items-center\",\n \"justify-center\",\n \"shrink-0\",\n \"font-medium\",\n \"overflow-hidden\",\n sizeClasses[size],\n variantClasses[variant],\n \"bg-surface-muted\",\n \"text-fg-primary\",\n className,\n )}\n role=\"img\"\n aria-label={defaultAriaLabel}\n {...props}\n >\n {!showFallback && src && (\n <img\n src={src}\n alt={alt || \"\"}\n loading={loading}\n className={cn(\n \"w-full\",\n \"h-full\",\n \"object-cover\",\n variantClasses[variant],\n !imageLoaded ? \"opacity-0\" : \"opacity-100\",\n \"transition-opacity\",\n \"duration-200\",\n )}\n onLoad={() => setImageLoaded(true)}\n onError={() => {\n setImageError(true);\n setImageLoaded(false);\n }}\n aria-hidden=\"true\"\n />\n )}\n {showFallback && (\n <span\n className={cn(\n \"flex\",\n \"items-center\",\n \"justify-center\",\n \"w-full\",\n \"h-full\",\n variantClasses[variant],\n )}\n aria-hidden=\"true\"\n >\n {displayFallback || \"?\"}\n </span>\n )}\n </div>\n );\n});\n\nAvatar.displayName = \"Avatar\";\n\nexport default Avatar;\n"],"names":["Avatar","forwardRef","_a","ref","_b","src","alt","fallback","size","variant","loading","ariaLabel","className","props","__objRest","imageError","setImageError","useState","imageLoaded","setImageLoaded","sizeClasses","variantClasses","getRadiusClass","showFallback","displayFallback","defaultAriaLabel","jsxs","__spreadProps","__spreadValues","cn","jsx"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AA4EA,MAAMA,IAASC,EAAwC,SACrDC,GAWAC,GACA;AAZA,MAAAC,IAAAF,GACE;AAAA,SAAAG;AAAA,IACA,KAAAC;AAAA,IACA,UAAAC;AAAA,IACA,MAAAC,IAAO;AAAA,IACP,SAAAC,IAAU;AAAA,IACV,SAAAC,IAAU;AAAA,IACV,cAAcC;AAAA,IACd,WAAAC,IAAY;AAAA,MARdR,GASKS,IAAAC,EATLV,GASK;AAAA,IARH;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA;AAKF,QAAM,CAACW,GAAYC,CAAa,IAAIC,EAAS,EAAK,GAC5C,CAACC,GAAaC,CAAc,IAAIF,EAAS,EAAK,GAE9CG,IAA0C;AAAA,IAC9C,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,OAAO;AAAA,IACP,OAAO;AAAA,EAAA,GAGHC,IAAiB;AAAA,IACrB,QAAQC,EAAe,MAAM;AAAA,IAC7B,QAAQA,EAAe,MAAM;AAAA,IAC7B,SAASA,EAAe,IAAI;AAAA,EAAA,GAGxBC,IAAe,CAAClB,KAAOU,GACvBS,IACJ,OAAOjB,KAAa,WAChBA,EAAS,cAAc,MAAM,GAAG,CAAC,IACjCA,GAEAkB,IAAmBd,KAAaL,KAAO;AAE7C,SACE,gBAAAoB;AAAA,IAAC;AAAA,IAAAC,EAAAC,EAAA;AAAA,MACC,KAAAzB;AAAA,MACA,WAAW0B;AAAA,QACT;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACAT,EAAYZ,CAAI;AAAA,QAChBa,EAAeZ,CAAO;AAAA,QACtB;AAAA,QACA;AAAA,QACAG;AAAA,MAAA;AAAA,MAEF,MAAK;AAAA,MACL,cAAYa;AAAA,OACRZ,IAlBL;AAAA,MAoBE,UAAA;AAAA,QAAA,CAACU,KAAgBlB,KAChB,gBAAAyB;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,KAAAzB;AAAA,YACA,KAAKC,KAAO;AAAA,YACZ,SAAAI;AAAA,YACA,WAAWmB;AAAA,cACT;AAAA,cACA;AAAA,cACA;AAAA,cACAR,EAAeZ,CAAO;AAAA,cACrBS,IAA4B,gBAAd;AAAA,cACf;AAAA,cACA;AAAA,YAAA;AAAA,YAEF,QAAQ,MAAMC,EAAe,EAAI;AAAA,YACjC,SAAS,MAAM;AACb,cAAAH,EAAc,EAAI,GAClBG,EAAe,EAAK;AAAA,YACtB;AAAA,YACA,eAAY;AAAA,UAAA;AAAA,QAAA;AAAA,QAGfI,KACC,gBAAAO;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,WAAWD;AAAA,cACT;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACAR,EAAeZ,CAAO;AAAA,YAAA;AAAA,YAExB,eAAY;AAAA,YAEX,UAAAe,KAAmB;AAAA,UAAA;AAAA,QAAA;AAAA,MACtB;AAAA,IAAA;AAAA,EAAA;AAIR,CAAC;AAEDxB,EAAO,cAAc;"}
|