@fanvue/ui 3.7.1 → 3.8.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.
Files changed (59) hide show
  1. package/dist/cjs/components/Accordion/AccordionContent.cjs +6 -2
  2. package/dist/cjs/components/Accordion/AccordionContent.cjs.map +1 -1
  3. package/dist/cjs/components/Breadcrumb/Breadcrumb.cjs +46 -23
  4. package/dist/cjs/components/Breadcrumb/Breadcrumb.cjs.map +1 -1
  5. package/dist/cjs/components/Icons/GifIcon.cjs +101 -0
  6. package/dist/cjs/components/Icons/GifIcon.cjs.map +1 -0
  7. package/dist/cjs/components/Icons/VerifiedIcon.cjs +82 -0
  8. package/dist/cjs/components/Icons/VerifiedIcon.cjs.map +1 -0
  9. package/dist/cjs/components/Pagination/Pagination.cjs +7 -7
  10. package/dist/cjs/components/Pagination/Pagination.cjs.map +1 -1
  11. package/dist/cjs/components/ProfileOnlineStatus/ProfileOnlineStatus.cjs +44 -0
  12. package/dist/cjs/components/ProfileOnlineStatus/ProfileOnlineStatus.cjs.map +1 -0
  13. package/dist/cjs/components/RatingSummary/RatingSummary.cjs +103 -0
  14. package/dist/cjs/components/RatingSummary/RatingSummary.cjs.map +1 -0
  15. package/dist/cjs/components/ReviewCard/ReviewCard.cjs +51 -0
  16. package/dist/cjs/components/ReviewCard/ReviewCard.cjs.map +1 -0
  17. package/dist/cjs/components/Toast/Toast.cjs +18 -32
  18. package/dist/cjs/components/Toast/Toast.cjs.map +1 -1
  19. package/dist/cjs/components/UserDisplayName/UserDisplayName.cjs +67 -0
  20. package/dist/cjs/components/UserDisplayName/UserDisplayName.cjs.map +1 -0
  21. package/dist/cjs/components/UserHandle/UserHandle.cjs +46 -0
  22. package/dist/cjs/components/UserHandle/UserHandle.cjs.map +1 -0
  23. package/dist/cjs/components/UserItem/UserItem.cjs +74 -0
  24. package/dist/cjs/components/UserItem/UserItem.cjs.map +1 -0
  25. package/dist/cjs/index.cjs +18 -0
  26. package/dist/cjs/index.cjs.map +1 -1
  27. package/dist/cjs/utils/getInitials.cjs +10 -0
  28. package/dist/cjs/utils/getInitials.cjs.map +1 -0
  29. package/dist/components/Accordion/AccordionContent.mjs +6 -2
  30. package/dist/components/Accordion/AccordionContent.mjs.map +1 -1
  31. package/dist/components/Breadcrumb/Breadcrumb.mjs +46 -23
  32. package/dist/components/Breadcrumb/Breadcrumb.mjs.map +1 -1
  33. package/dist/components/Icons/GifIcon.mjs +84 -0
  34. package/dist/components/Icons/GifIcon.mjs.map +1 -0
  35. package/dist/components/Icons/VerifiedIcon.mjs +65 -0
  36. package/dist/components/Icons/VerifiedIcon.mjs.map +1 -0
  37. package/dist/components/Pagination/Pagination.mjs +7 -7
  38. package/dist/components/Pagination/Pagination.mjs.map +1 -1
  39. package/dist/components/ProfileOnlineStatus/ProfileOnlineStatus.mjs +27 -0
  40. package/dist/components/ProfileOnlineStatus/ProfileOnlineStatus.mjs.map +1 -0
  41. package/dist/components/RatingSummary/RatingSummary.mjs +86 -0
  42. package/dist/components/RatingSummary/RatingSummary.mjs.map +1 -0
  43. package/dist/components/ReviewCard/ReviewCard.mjs +34 -0
  44. package/dist/components/ReviewCard/ReviewCard.mjs.map +1 -0
  45. package/dist/components/Toast/Toast.mjs +18 -32
  46. package/dist/components/Toast/Toast.mjs.map +1 -1
  47. package/dist/components/UserDisplayName/UserDisplayName.mjs +50 -0
  48. package/dist/components/UserDisplayName/UserDisplayName.mjs.map +1 -0
  49. package/dist/components/UserHandle/UserHandle.mjs +29 -0
  50. package/dist/components/UserHandle/UserHandle.mjs.map +1 -0
  51. package/dist/components/UserItem/UserItem.mjs +57 -0
  52. package/dist/components/UserItem/UserItem.mjs.map +1 -0
  53. package/dist/index.d.ts +246 -4
  54. package/dist/index.mjs +18 -0
  55. package/dist/index.mjs.map +1 -1
  56. package/dist/styles/base.css +16 -0
  57. package/dist/utils/getInitials.mjs +10 -0
  58. package/dist/utils/getInitials.mjs.map +1 -0
  59. package/package.json +2 -2
@@ -0,0 +1,103 @@
1
+ "use client";
2
+ "use strict";
3
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
4
+ const jsxRuntime = require("react/jsx-runtime");
5
+ const React = require("react");
6
+ const cn = require("../../utils/cn.cjs");
7
+ const StarIcon = require("../Icons/StarIcon.cjs");
8
+ function _interopNamespaceDefault(e) {
9
+ const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
10
+ if (e) {
11
+ for (const k in e) {
12
+ if (k !== "default") {
13
+ const d = Object.getOwnPropertyDescriptor(e, k);
14
+ Object.defineProperty(n, k, d.get ? d : {
15
+ enumerable: true,
16
+ get: () => e[k]
17
+ });
18
+ }
19
+ }
20
+ }
21
+ n.default = e;
22
+ return Object.freeze(n);
23
+ }
24
+ const React__namespace = /* @__PURE__ */ _interopNamespaceDefault(React);
25
+ function defaultFormatCount(count) {
26
+ return `${count.toLocaleString()} ${count === 1 ? "review" : "reviews"}`;
27
+ }
28
+ function getWeightedAverage(distribution) {
29
+ let total = 0;
30
+ let weighted = 0;
31
+ for (const { rating, count } of distribution) {
32
+ total += count;
33
+ weighted += rating * count;
34
+ }
35
+ return total === 0 ? 0 : weighted / total;
36
+ }
37
+ const RatingSummary = React__namespace.forwardRef(
38
+ ({
39
+ distribution,
40
+ averageRating,
41
+ maxRating = 5,
42
+ formatCount = defaultFormatCount,
43
+ formatAverageLabel,
44
+ formatRatingLabel,
45
+ className,
46
+ ...props
47
+ }, ref) => {
48
+ const countByRating = /* @__PURE__ */ new Map();
49
+ for (const { rating, count } of distribution) {
50
+ countByRating.set(rating, (countByRating.get(rating) ?? 0) + count);
51
+ }
52
+ const rows = Array.from({ length: maxRating }, (_, index) => {
53
+ const rating = maxRating - index;
54
+ return { rating, count: countByRating.get(rating) ?? 0 };
55
+ });
56
+ const totalCount = rows.reduce((sum, row) => sum + row.count, 0);
57
+ const maxCount = rows.reduce((max, row) => Math.max(max, row.count), 0);
58
+ const average = averageRating ?? getWeightedAverage(rows);
59
+ const averageLabel = average.toFixed(1);
60
+ const headerLabel = formatAverageLabel ? formatAverageLabel(averageLabel, maxRating, totalCount) : `Average rating ${averageLabel} out of ${maxRating}, ${formatCount(totalCount)}`;
61
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref, className: cn.cn("flex flex-col gap-4", className), ...props, children: [
62
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1", role: "img", "aria-label": headerLabel, children: [
63
+ /* @__PURE__ */ jsxRuntime.jsx(StarIcon.StarIcon, { size: 24, filled: true, className: "shrink-0 text-brand-primary-default" }),
64
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-center gap-1.5", children: [
65
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "typography-body-small-14px-semibold text-content-primary", children: averageLabel }),
66
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "typography-body-small-14px-regular text-content-tertiary", children: [
67
+ "(",
68
+ formatCount(totalCount),
69
+ ")"
70
+ ] })
71
+ ] })
72
+ ] }),
73
+ /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "m-0 flex list-none flex-col gap-4 p-0", "aria-label": "Rating breakdown", children: rows.map(({ rating, count }) => /* @__PURE__ */ jsxRuntime.jsx("li", { children: /* @__PURE__ */ jsxRuntime.jsxs(
74
+ "div",
75
+ {
76
+ className: "flex items-center gap-4",
77
+ role: "img",
78
+ "aria-label": formatRatingLabel ? formatRatingLabel(rating, count) : `${rating} ${rating === 1 ? "star" : "stars"}, ${formatCount(count)}`,
79
+ children: [
80
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative h-4 flex-1 overflow-hidden rounded-full bg-neutral-alphas-50", children: /* @__PURE__ */ jsxRuntime.jsx(
81
+ "div",
82
+ {
83
+ className: "absolute inset-y-0 left-0 rounded-full bg-brand-primary-default transition-[width] duration-300 ease-in-out",
84
+ style: { width: maxCount === 0 ? "0%" : `${count / maxCount * 100}%` }
85
+ }
86
+ ) }),
87
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex shrink-0 items-center gap-1.5", children: [
88
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "typography-body-small-14px-semibold text-content-primary", children: rating }),
89
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "typography-body-small-14px-regular text-content-tertiary", children: [
90
+ "(",
91
+ formatCount(count),
92
+ ")"
93
+ ] })
94
+ ] })
95
+ ]
96
+ }
97
+ ) }, rating)) })
98
+ ] });
99
+ }
100
+ );
101
+ RatingSummary.displayName = "RatingSummary";
102
+ exports.RatingSummary = RatingSummary;
103
+ //# sourceMappingURL=RatingSummary.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RatingSummary.cjs","sources":["../../../../src/components/RatingSummary/RatingSummary.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { cn } from \"@/utils/cn\";\nimport { StarIcon } from \"../Icons/StarIcon\";\n\n/** A single rating value paired with the number of reviews that gave it. */\nexport interface RatingCount {\n /** The rating value this entry represents (e.g. `5`). */\n rating: number;\n /** Number of reviews that gave this rating. */\n count: number;\n}\n\nexport interface RatingSummaryProps extends Omit<React.HTMLAttributes<HTMLDivElement>, \"title\"> {\n /**\n * Per-rating review counts. Order is not significant — rows always render from\n * `maxRating` down to `1`, and any rating without an entry renders as zero.\n * Entries are expected to use whole-number ratings within `1`–`maxRating`;\n * any outside that range are ignored, including in the derived total and average.\n */\n distribution: RatingCount[];\n /**\n * Average rating shown in the header. Defaults to the count-weighted mean of\n * `distribution`; provide it to display a server-computed average instead.\n */\n averageRating?: number;\n /** Highest possible rating. Sets how many histogram rows render. @default 5 */\n maxRating?: number;\n /**\n * Formats a review count into its label, without surrounding parentheses.\n * Used for the visible text and as the count portion of the default\n * accessible labels.\n * @default ``(count) => `${count.toLocaleString()} review(s)` ``\n */\n formatCount?: (count: number) => string;\n /**\n * Builds the accessible label for the header. Override to localise the\n * screen-reader text. `average` is the already-formatted average string.\n * @default ``(average, max, total) => `Average rating ${average} out of ${max}, ${formatCount(total)}` ``\n */\n formatAverageLabel?: (average: string, maxRating: number, total: number) => string;\n /**\n * Builds the accessible label for each histogram row. Override to localise the\n * screen-reader text.\n * @default ``(rating, count) => `${rating} star(s), ${formatCount(count)}` ``\n */\n formatRatingLabel?: (rating: number, count: number) => string;\n}\n\nfunction defaultFormatCount(count: number): string {\n return `${count.toLocaleString()} ${count === 1 ? \"review\" : \"reviews\"}`;\n}\n\nfunction getWeightedAverage(distribution: RatingCount[]): number {\n let total = 0;\n let weighted = 0;\n for (const { rating, count } of distribution) {\n total += count;\n weighted += rating * count;\n }\n return total === 0 ? 0 : weighted / total;\n}\n\n/**\n * An aggregated rating overview: a headline average with the total review count,\n * followed by a per-rating histogram. Bar lengths are scaled relative to the\n * most-reviewed rating, so the busiest rating always fills the track.\n *\n * The brand star is decorative; the header and each histogram row expose\n * `role=\"img\"` with an accessible label (override via `formatAverageLabel` /\n * `formatRatingLabel`) so the single-star-plus-number reads clearly.\n *\n * @example\n * ```tsx\n * <RatingSummary\n * distribution={[\n * { rating: 5, count: 300 },\n * { rating: 4, count: 20 },\n * { rating: 3, count: 20 },\n * { rating: 2, count: 10 },\n * { rating: 1, count: 0 },\n * ]}\n * />\n * ```\n */\nexport const RatingSummary = React.forwardRef<HTMLDivElement, RatingSummaryProps>(\n (\n {\n distribution,\n averageRating,\n maxRating = 5,\n formatCount = defaultFormatCount,\n formatAverageLabel,\n formatRatingLabel,\n className,\n ...props\n },\n ref,\n ) => {\n const countByRating = new Map<number, number>();\n for (const { rating, count } of distribution) {\n countByRating.set(rating, (countByRating.get(rating) ?? 0) + count);\n }\n\n const rows = Array.from({ length: maxRating }, (_, index) => {\n const rating = maxRating - index;\n return { rating, count: countByRating.get(rating) ?? 0 };\n });\n\n const totalCount = rows.reduce((sum, row) => sum + row.count, 0);\n const maxCount = rows.reduce((max, row) => Math.max(max, row.count), 0);\n const average = averageRating ?? getWeightedAverage(rows);\n const averageLabel = average.toFixed(1);\n\n const headerLabel = formatAverageLabel\n ? formatAverageLabel(averageLabel, maxRating, totalCount)\n : `Average rating ${averageLabel} out of ${maxRating}, ${formatCount(totalCount)}`;\n\n return (\n <div ref={ref} className={cn(\"flex flex-col gap-4\", className)} {...props}>\n <div className=\"flex items-center gap-1\" role=\"img\" aria-label={headerLabel}>\n <StarIcon size={24} filled className=\"shrink-0 text-brand-primary-default\" />\n <span className=\"flex items-center gap-1.5\">\n <span className=\"typography-body-small-14px-semibold text-content-primary\">\n {averageLabel}\n </span>\n <span className=\"typography-body-small-14px-regular text-content-tertiary\">\n ({formatCount(totalCount)})\n </span>\n </span>\n </div>\n\n <ul className=\"m-0 flex list-none flex-col gap-4 p-0\" aria-label=\"Rating breakdown\">\n {rows.map(({ rating, count }) => (\n <li key={rating}>\n <div\n className=\"flex items-center gap-4\"\n role=\"img\"\n aria-label={\n formatRatingLabel\n ? formatRatingLabel(rating, count)\n : `${rating} ${rating === 1 ? \"star\" : \"stars\"}, ${formatCount(count)}`\n }\n >\n <div className=\"relative h-4 flex-1 overflow-hidden rounded-full bg-neutral-alphas-50\">\n <div\n className=\"absolute inset-y-0 left-0 rounded-full bg-brand-primary-default transition-[width] duration-300 ease-in-out\"\n style={{ width: maxCount === 0 ? \"0%\" : `${(count / maxCount) * 100}%` }}\n />\n </div>\n <span className=\"flex shrink-0 items-center gap-1.5\">\n <span className=\"typography-body-small-14px-semibold text-content-primary\">\n {rating}\n </span>\n <span className=\"typography-body-small-14px-regular text-content-tertiary\">\n ({formatCount(count)})\n </span>\n </span>\n </div>\n </li>\n ))}\n </ul>\n </div>\n );\n },\n);\n\nRatingSummary.displayName = \"RatingSummary\";\n"],"names":["React","jsxs","cn","jsx","StarIcon"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAgDA,SAAS,mBAAmB,OAAuB;AACjD,SAAO,GAAG,MAAM,gBAAgB,IAAI,UAAU,IAAI,WAAW,SAAS;AACxE;AAEA,SAAS,mBAAmB,cAAqC;AAC/D,MAAI,QAAQ;AACZ,MAAI,WAAW;AACf,aAAW,EAAE,QAAQ,MAAA,KAAW,cAAc;AAC5C,aAAS;AACT,gBAAY,SAAS;AAAA,EACvB;AACA,SAAO,UAAU,IAAI,IAAI,WAAW;AACtC;AAwBO,MAAM,gBAAgBA,iBAAM;AAAA,EACjC,CACE;AAAA,IACE;AAAA,IACA;AAAA,IACA,YAAY;AAAA,IACZ,cAAc;AAAA,IACd;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAG;AAAA,EAAA,GAEL,QACG;AACH,UAAM,oCAAoB,IAAA;AAC1B,eAAW,EAAE,QAAQ,MAAA,KAAW,cAAc;AAC5C,oBAAc,IAAI,SAAS,cAAc,IAAI,MAAM,KAAK,KAAK,KAAK;AAAA,IACpE;AAEA,UAAM,OAAO,MAAM,KAAK,EAAE,QAAQ,UAAA,GAAa,CAAC,GAAG,UAAU;AAC3D,YAAM,SAAS,YAAY;AAC3B,aAAO,EAAE,QAAQ,OAAO,cAAc,IAAI,MAAM,KAAK,EAAA;AAAA,IACvD,CAAC;AAED,UAAM,aAAa,KAAK,OAAO,CAAC,KAAK,QAAQ,MAAM,IAAI,OAAO,CAAC;AAC/D,UAAM,WAAW,KAAK,OAAO,CAAC,KAAK,QAAQ,KAAK,IAAI,KAAK,IAAI,KAAK,GAAG,CAAC;AACtE,UAAM,UAAU,iBAAiB,mBAAmB,IAAI;AACxD,UAAM,eAAe,QAAQ,QAAQ,CAAC;AAEtC,UAAM,cAAc,qBAChB,mBAAmB,cAAc,WAAW,UAAU,IACtD,kBAAkB,YAAY,WAAW,SAAS,KAAK,YAAY,UAAU,CAAC;AAElF,WACEC,gCAAC,SAAI,KAAU,WAAWC,MAAG,uBAAuB,SAAS,GAAI,GAAG,OAClE,UAAA;AAAA,MAAAD,gCAAC,SAAI,WAAU,2BAA0B,MAAK,OAAM,cAAY,aAC9D,UAAA;AAAA,QAAAE,+BAACC,SAAAA,YAAS,MAAM,IAAI,QAAM,MAAC,WAAU,uCAAsC;AAAA,QAC3EH,2BAAAA,KAAC,QAAA,EAAK,WAAU,6BACd,UAAA;AAAA,UAAAE,2BAAAA,IAAC,QAAA,EAAK,WAAU,4DACb,UAAA,cACH;AAAA,UACAF,2BAAAA,KAAC,QAAA,EAAK,WAAU,4DAA2D,UAAA;AAAA,YAAA;AAAA,YACvE,YAAY,UAAU;AAAA,YAAE;AAAA,UAAA,EAAA,CAC5B;AAAA,QAAA,EAAA,CACF;AAAA,MAAA,GACF;AAAA,MAEAE,2BAAAA,IAAC,MAAA,EAAG,WAAU,yCAAwC,cAAW,oBAC9D,UAAA,KAAK,IAAI,CAAC,EAAE,QAAQ,MAAA,qCAClB,MAAA,EACC,UAAAF,2BAAAA;AAAAA,QAAC;AAAA,QAAA;AAAA,UACC,WAAU;AAAA,UACV,MAAK;AAAA,UACL,cACE,oBACI,kBAAkB,QAAQ,KAAK,IAC/B,GAAG,MAAM,IAAI,WAAW,IAAI,SAAS,OAAO,KAAK,YAAY,KAAK,CAAC;AAAA,UAGzE,UAAA;AAAA,YAAAE,2BAAAA,IAAC,OAAA,EAAI,WAAU,yEACb,UAAAA,2BAAAA;AAAAA,cAAC;AAAA,cAAA;AAAA,gBACC,WAAU;AAAA,gBACV,OAAO,EAAE,OAAO,aAAa,IAAI,OAAO,GAAI,QAAQ,WAAY,GAAG,IAAA;AAAA,cAAI;AAAA,YAAA,GAE3E;AAAA,YACAF,2BAAAA,KAAC,QAAA,EAAK,WAAU,sCACd,UAAA;AAAA,cAAAE,2BAAAA,IAAC,QAAA,EAAK,WAAU,4DACb,UAAA,QACH;AAAA,cACAF,2BAAAA,KAAC,QAAA,EAAK,WAAU,4DAA2D,UAAA;AAAA,gBAAA;AAAA,gBACvE,YAAY,KAAK;AAAA,gBAAE;AAAA,cAAA,EAAA,CACvB;AAAA,YAAA,EAAA,CACF;AAAA,UAAA;AAAA,QAAA;AAAA,MAAA,EACF,GAxBO,MAyBT,CACD,EAAA,CACH;AAAA,IAAA,GACF;AAAA,EAEJ;AACF;AAEA,cAAc,cAAc;;"}
@@ -0,0 +1,51 @@
1
+ "use client";
2
+ "use strict";
3
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
4
+ const jsxRuntime = require("react/jsx-runtime");
5
+ const React = require("react");
6
+ const cn = require("../../utils/cn.cjs");
7
+ const StarIcon = require("../Icons/StarIcon.cjs");
8
+ function _interopNamespaceDefault(e) {
9
+ const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
10
+ if (e) {
11
+ for (const k in e) {
12
+ if (k !== "default") {
13
+ const d = Object.getOwnPropertyDescriptor(e, k);
14
+ Object.defineProperty(n, k, d.get ? d : {
15
+ enumerable: true,
16
+ get: () => e[k]
17
+ });
18
+ }
19
+ }
20
+ }
21
+ n.default = e;
22
+ return Object.freeze(n);
23
+ }
24
+ const React__namespace = /* @__PURE__ */ _interopNamespaceDefault(React);
25
+ const ReviewCard = React__namespace.forwardRef(
26
+ ({ rating, maxRating = 5, author, title, children, className, ...props }, ref) => {
27
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref, className: cn.cn("flex flex-col gap-2", className), ...props, children: [
28
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [
29
+ /* @__PURE__ */ jsxRuntime.jsx(StarIcon.StarIcon, { size: 24, filled: true, className: "shrink-0 text-brand-primary-default" }),
30
+ /* @__PURE__ */ jsxRuntime.jsx(
31
+ "span",
32
+ {
33
+ className: "typography-body-small-14px-semibold text-content-primary",
34
+ role: "img",
35
+ "aria-label": `Rated ${rating} out of ${maxRating}`,
36
+ children: rating
37
+ }
38
+ ),
39
+ author != null && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "typography-body-small-14px-regular text-content-tertiary", children: [
40
+ "by ",
41
+ author
42
+ ] })
43
+ ] }),
44
+ title != null && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "typography-body-default-16px-semibold text-content-primary", children: title }),
45
+ children != null && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "typography-body-small-14px-regular text-content-secondary", children })
46
+ ] });
47
+ }
48
+ );
49
+ ReviewCard.displayName = "ReviewCard";
50
+ exports.ReviewCard = ReviewCard;
51
+ //# sourceMappingURL=ReviewCard.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ReviewCard.cjs","sources":["../../../../src/components/ReviewCard/ReviewCard.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { cn } from \"@/utils/cn\";\nimport { StarIcon } from \"../Icons/StarIcon\";\n\nexport interface ReviewCardProps extends Omit<React.HTMLAttributes<HTMLDivElement>, \"title\"> {\n /** Star rating the reviewer gave, shown beside the star icon. */\n rating: number;\n /** Highest possible rating, used only in the accessible label (e.g. \"4 out of 5\"). @default 5 */\n maxRating?: number;\n /** Reviewer name or handle, rendered after \"by\". Omitted when not provided. */\n author?: React.ReactNode;\n /** Short headline for the review. */\n title?: React.ReactNode;\n /** Review body text. */\n children?: React.ReactNode;\n}\n\n/**\n * A single written review: a star rating with an optional author byline, a\n * title, and the review body. Stack several with a {@link Divider} between them\n * to build a review list.\n *\n * @example\n * ```tsx\n * <ReviewCard rating={4} author=\"@jane_doe\" title=\"A great app to start!\">\n * Easily plan and organize your content. Streamline your scheduling so you can\n * focus on what you do best.\n * </ReviewCard>\n * ```\n */\nexport const ReviewCard = React.forwardRef<HTMLDivElement, ReviewCardProps>(\n ({ rating, maxRating = 5, author, title, children, className, ...props }, ref) => {\n return (\n <div ref={ref} className={cn(\"flex flex-col gap-2\", className)} {...props}>\n <div className=\"flex items-center gap-1\">\n <StarIcon size={24} filled className=\"shrink-0 text-brand-primary-default\" />\n <span\n className=\"typography-body-small-14px-semibold text-content-primary\"\n role=\"img\"\n aria-label={`Rated ${rating} out of ${maxRating}`}\n >\n {rating}\n </span>\n {author != null && (\n <span className=\"typography-body-small-14px-regular text-content-tertiary\">\n by {author}\n </span>\n )}\n </div>\n {title != null && (\n <p className=\"typography-body-default-16px-semibold text-content-primary\">{title}</p>\n )}\n {children != null && (\n <p className=\"typography-body-small-14px-regular text-content-secondary\">{children}</p>\n )}\n </div>\n );\n },\n);\n\nReviewCard.displayName = \"ReviewCard\";\n"],"names":["React","jsxs","cn","jsx","StarIcon"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AA8BO,MAAM,aAAaA,iBAAM;AAAA,EAC9B,CAAC,EAAE,QAAQ,YAAY,GAAG,QAAQ,OAAO,UAAU,WAAW,GAAG,MAAA,GAAS,QAAQ;AAChF,WACEC,gCAAC,SAAI,KAAU,WAAWC,MAAG,uBAAuB,SAAS,GAAI,GAAG,OAClE,UAAA;AAAA,MAAAD,2BAAAA,KAAC,OAAA,EAAI,WAAU,2BACb,UAAA;AAAA,QAAAE,+BAACC,SAAAA,YAAS,MAAM,IAAI,QAAM,MAAC,WAAU,uCAAsC;AAAA,QAC3ED,2BAAAA;AAAAA,UAAC;AAAA,UAAA;AAAA,YACC,WAAU;AAAA,YACV,MAAK;AAAA,YACL,cAAY,SAAS,MAAM,WAAW,SAAS;AAAA,YAE9C,UAAA;AAAA,UAAA;AAAA,QAAA;AAAA,QAEF,UAAU,QACTF,gCAAC,QAAA,EAAK,WAAU,4DAA2D,UAAA;AAAA,UAAA;AAAA,UACrE;AAAA,QAAA,EAAA,CACN;AAAA,MAAA,GAEJ;AAAA,MACC,SAAS,QACRE,2BAAAA,IAAC,KAAA,EAAE,WAAU,8DAA8D,UAAA,OAAM;AAAA,MAElF,YAAY,QACXA,+BAAC,KAAA,EAAE,WAAU,6DAA6D,SAAA,CAAS;AAAA,IAAA,GAEvF;AAAA,EAEJ;AACF;AAEA,WAAW,cAAc;;"}
@@ -7,7 +7,6 @@ const React = require("react");
7
7
  const cn = require("../../utils/cn.cjs");
8
8
  const Avatar = require("../Avatar/Avatar.cjs");
9
9
  const Button = require("../Button/Button.cjs");
10
- const IconButton = require("../IconButton/IconButton.cjs");
11
10
  const CloseIcon = require("../Icons/CloseIcon.cjs");
12
11
  const ErrorIcon = require("../Icons/ErrorIcon.cjs");
13
12
  const InfoIcon = require("../Icons/InfoIcon.cjs");
@@ -47,13 +46,13 @@ ToastViewport.displayName = "ToastViewport";
47
46
  const VariantIcon = ({ variant }) => {
48
47
  switch (variant) {
49
48
  case "info":
50
- return /* @__PURE__ */ jsxRuntime.jsx(InfoIcon.InfoIcon, { className: "size-5 text-info-content" });
49
+ return /* @__PURE__ */ jsxRuntime.jsx(InfoIcon.InfoIcon, { size: 16, filled: true, className: "text-alerts-toast-icon-info" });
51
50
  case "warning":
52
- return /* @__PURE__ */ jsxRuntime.jsx(WarningIcon.WarningIcon, { className: "size-5 text-warning-content" });
51
+ return /* @__PURE__ */ jsxRuntime.jsx(WarningIcon.WarningIcon, { size: 16, filled: true, className: "text-alerts-toast-icon-warning" });
53
52
  case "success":
54
- return /* @__PURE__ */ jsxRuntime.jsx(SuccessIcon.SuccessIcon, { className: "size-5 text-success-content" });
53
+ return /* @__PURE__ */ jsxRuntime.jsx(SuccessIcon.SuccessIcon, { className: "size-4 text-alerts-toast-icon-success" });
55
54
  case "error":
56
- return /* @__PURE__ */ jsxRuntime.jsx(ErrorIcon.ErrorIcon, { className: "size-5 text-error-content" });
55
+ return /* @__PURE__ */ jsxRuntime.jsx(ErrorIcon.ErrorIcon, { className: "size-4 text-alerts-toast-icon-error" });
57
56
  }
58
57
  };
59
58
  const Toast = React__namespace.forwardRef(
@@ -78,43 +77,30 @@ const Toast = React__namespace.forwardRef(
78
77
  ref,
79
78
  "data-testid": "toast",
80
79
  className: cn.cn(
81
- // Base styles
82
- "group pointer-events-auto relative flex w-full flex-col items-start gap-3 overflow-hidden rounded-xs border-none bg-surface-primary-inverted p-4 text-content-primary-inverted shadow-lg transition-all",
83
- // Dark mode
84
- "dark:border-opacity-100",
85
- // Animation
80
+ "group pointer-events-auto relative flex w-full items-start gap-6 overflow-hidden rounded-md border-none bg-surface-primary-inverted py-3 pr-3 pl-4 text-content-primary-inverted shadow-md transition-all",
86
81
  "data-[state=closed]:fade-out-80 data-[state=closed]:slide-out-to-right-full data-[state=open]:slide-in-from-bottom-full data-[swipe=cancel]:translate-x-0 data-[swipe=end]:translate-x-(--radix-toast-swipe-end-x) data-[swipe=move]:translate-x-(--radix-toast-swipe-move-x) data-[state=closed]:animate-out data-[state=open]:animate-in data-[swipe=end]:animate-out data-[swipe=move]:transition-none",
87
- // Manual CSS overrides
88
82
  className
89
83
  ),
90
84
  ...props,
91
85
  children: [
92
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex w-full items-center gap-3", children: [
93
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "self-start", children: variant === "messageToast" ? avatarSrc && /* @__PURE__ */ jsxRuntime.jsx(Avatar.Avatar, { src: avatarSrc, alt: avatarAlt, fallback: avatarFallback }) : /* @__PURE__ */ jsxRuntime.jsx(VariantIcon, { variant }) }),
94
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-1 flex-col items-start", children: [
95
- title && /* @__PURE__ */ jsxRuntime.jsx(ToastPrimitive__namespace.Title, { className: "typography-body-small-14px-semibold", children: title }),
96
- description && /* @__PURE__ */ jsxRuntime.jsx(ToastPrimitive__namespace.Description, { className: "typography-body-small-14px-regular mt-1 opacity-90", children: description }),
97
- children,
98
- onActionClick && /* @__PURE__ */ jsxRuntime.jsx(
99
- Button.Button,
100
- {
101
- variant: "secondary",
102
- className: "mt-4 border-content-primary-inverted text-content-primary-inverted",
103
- size: "32",
104
- onClick: onActionClick,
105
- children: actionLabel ?? "Action"
106
- }
107
- )
86
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 flex-1 items-start gap-3 py-1 pr-1", children: [
87
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex shrink-0 items-center pt-px", children: variant === "messageToast" ? avatarSrc && /* @__PURE__ */ jsxRuntime.jsx(Avatar.Avatar, { src: avatarSrc, alt: avatarAlt, fallback: avatarFallback }) : /* @__PURE__ */ jsxRuntime.jsx(VariantIcon, { variant }) }),
88
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 flex-1 flex-col items-start gap-4", children: [
89
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex w-full flex-col items-start gap-1", children: [
90
+ title && /* @__PURE__ */ jsxRuntime.jsx(ToastPrimitive__namespace.Title, { className: "typography-body-small-14px-semibold", children: title }),
91
+ description && /* @__PURE__ */ jsxRuntime.jsx(ToastPrimitive__namespace.Description, { className: "typography-body-small-14px-regular", children: description }),
92
+ children
93
+ ] }),
94
+ onActionClick && /* @__PURE__ */ jsxRuntime.jsx(Button.Button, { variant: "outline", negative: true, size: "32", onClick: onActionClick, children: actionLabel ?? "Action" })
108
95
  ] })
109
96
  ] }),
110
97
  showClose && /* @__PURE__ */ jsxRuntime.jsx(ToastPrimitive__namespace.Close, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
111
- IconButton.IconButton,
98
+ "button",
112
99
  {
113
- icon: /* @__PURE__ */ jsxRuntime.jsx(CloseIcon.CloseIcon, {}),
100
+ type: "button",
114
101
  "aria-label": closeLabel,
115
- className: "absolute top-2 right-2 text-content-primary-inverted",
116
- variant: "tertiary",
117
- size: "24"
102
+ className: "flex size-6 shrink-0 cursor-pointer items-center justify-center rounded-xs bg-buttons-secondary-negative-default text-content-primary-inverted transition-colors hover:bg-buttons-secondary-negative-hover focus-visible:shadow-focus-ring focus-visible:outline-none",
103
+ children: /* @__PURE__ */ jsxRuntime.jsx(CloseIcon.CloseIcon, { size: 16, "aria-hidden": "true" })
118
104
  }
119
105
  ) })
120
106
  ]
@@ -1 +1 @@
1
- {"version":3,"file":"Toast.cjs","sources":["../../../../src/components/Toast/Toast.tsx"],"sourcesContent":["import * as ToastPrimitive from \"@radix-ui/react-toast\";\nimport * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { Avatar } from \"../Avatar/Avatar\";\nimport { Button } from \"../Button/Button\";\nimport { IconButton } from \"../IconButton/IconButton\";\nimport { CloseIcon } from \"../Icons/CloseIcon\";\nimport { ErrorIcon } from \"../Icons/ErrorIcon\";\nimport { InfoIcon } from \"../Icons/InfoIcon\";\nimport { SuccessIcon } from \"../Icons/SuccessIcon\";\nimport { WarningIcon } from \"../Icons/WarningIcon\";\n\n/** Visual/semantic variant of the toast notification. */\nexport type ToastVariant = \"info\" | \"warning\" | \"success\" | \"error\" | \"messageToast\";\n\nexport interface ToastProps\n extends Omit<Omit<React.ComponentPropsWithoutRef<typeof ToastPrimitive.Root>, \"type\">, \"title\"> {\n /** Visual/semantic variant of the toast. @default \"info\" */\n variant?: ToastVariant;\n /** Title text displayed in bold at the top of the toast. */\n title?: string;\n /** Description or body content displayed below the title. */\n description?: React.ReactNode;\n /** Label for the optional action button. @default \"Action\" */\n actionLabel?: string;\n /** Click handler for the action button. When provided, the action button is rendered. */\n onActionClick?: () => void;\n /** Whether to show the close button. @default true */\n showClose?: boolean;\n /** Accessible label for the close button. @default \"Close notification\" */\n closeLabel?: string;\n /** Avatar image URL (used by the `messageToast` variant). */\n avatarSrc?: string;\n /** Alt text for the avatar image. */\n avatarAlt?: string;\n /** Fallback content for the avatar (e.g. initials). */\n avatarFallback?: string;\n}\n\n/** Props for the {@link ToastProvider}. Wraps Radix `Toast.Provider`. */\nexport interface ToastProviderProps extends ToastPrimitive.ToastProviderProps {}\n/** Props for the {@link ToastViewport}. Controls where toasts are rendered on screen. */\nexport interface ToastViewportProps\n extends React.ComponentPropsWithoutRef<typeof ToastPrimitive.Viewport> {}\n\n/** Provides toast context. Wrap your application (or a subtree) with this provider. */\nexport const ToastProvider: React.FC<ToastProviderProps> = ToastPrimitive.Provider;\n\n/** Fixed-position container that renders active toasts. Place once at the root of your app. */\nexport const ToastViewport = React.forwardRef<\n React.ElementRef<typeof ToastPrimitive.Viewport>,\n ToastViewportProps\n>(({ className, ...props }, ref) => (\n <ToastPrimitive.Viewport\n ref={ref}\n className={cn(\n \"pointer-events-none fixed right-0 bottom-0 z-100 flex max-h-screen w-full flex-col-reverse gap-3 p-4 md:max-w-[420px]\",\n className,\n )}\n {...props}\n />\n));\n\nToastViewport.displayName = \"ToastViewport\";\n\nconst VariantIcon = ({ variant }: { variant: ToastVariant }) => {\n switch (variant) {\n case \"info\":\n return <InfoIcon className=\"size-5 text-info-content\" />;\n case \"warning\":\n return <WarningIcon className=\"size-5 text-warning-content\" />;\n case \"success\":\n return <SuccessIcon className=\"size-5 text-success-content\" />;\n case \"error\":\n return <ErrorIcon className=\"size-5 text-error-content\" />;\n }\n};\n\n/**\n * A dismissible notification that appears temporarily. Supports `info`,\n * `warning`, `success`, `error`, and `messageToast` variants with optional\n * action button, close control, and avatar.\n *\n * Use inside a {@link ToastProvider} with a {@link ToastViewport}.\n *\n * @example\n * ```tsx\n * <Toast variant=\"success\" title=\"Saved\" description=\"Your changes are live.\" />\n * ```\n */\nexport const Toast = React.forwardRef<React.ComponentRef<typeof ToastPrimitive.Root>, ToastProps>(\n (\n {\n className,\n variant = \"info\",\n title,\n description,\n actionLabel,\n onActionClick,\n showClose = true,\n closeLabel = \"Close notification\",\n avatarSrc,\n avatarAlt,\n avatarFallback,\n children,\n ...props\n },\n ref,\n ) => {\n return (\n <ToastPrimitive.Root\n ref={ref}\n data-testid=\"toast\"\n className={cn(\n // Base styles\n \"group pointer-events-auto relative flex w-full flex-col items-start gap-3 overflow-hidden rounded-xs border-none bg-surface-primary-inverted p-4 text-content-primary-inverted shadow-lg transition-all\",\n // Dark mode\n \"dark:border-opacity-100\",\n // Animation\n \"data-[state=closed]:fade-out-80 data-[state=closed]:slide-out-to-right-full data-[state=open]:slide-in-from-bottom-full data-[swipe=cancel]:translate-x-0 data-[swipe=end]:translate-x-(--radix-toast-swipe-end-x) data-[swipe=move]:translate-x-(--radix-toast-swipe-move-x) data-[state=closed]:animate-out data-[state=open]:animate-in data-[swipe=end]:animate-out data-[swipe=move]:transition-none\",\n // Manual CSS overrides\n className,\n )}\n {...props}\n >\n <div className=\"flex w-full items-center gap-3\">\n <div className=\"self-start\">\n {variant === \"messageToast\" ? (\n avatarSrc && <Avatar src={avatarSrc} alt={avatarAlt} fallback={avatarFallback} />\n ) : (\n <VariantIcon variant={variant} />\n )}\n </div>\n <div className=\"flex flex-1 flex-col items-start\">\n {title && (\n <ToastPrimitive.Title className=\"typography-body-small-14px-semibold\">\n {title}\n </ToastPrimitive.Title>\n )}\n {description && (\n <ToastPrimitive.Description className=\"typography-body-small-14px-regular mt-1 opacity-90\">\n {description}\n </ToastPrimitive.Description>\n )}\n {children}\n {onActionClick && (\n <Button\n variant=\"secondary\"\n // These styles are basically inverted from the selected theme\n className=\"mt-4 border-content-primary-inverted text-content-primary-inverted\"\n size=\"32\"\n onClick={onActionClick}\n >\n {actionLabel ?? \"Action\"}\n </Button>\n )}\n </div>\n </div>\n {showClose && (\n <ToastPrimitive.Close asChild>\n <IconButton\n icon={<CloseIcon />}\n aria-label={closeLabel}\n // same as the button above\n className=\"absolute top-2 right-2 text-content-primary-inverted\"\n variant=\"tertiary\"\n size=\"24\"\n />\n </ToastPrimitive.Close>\n )}\n </ToastPrimitive.Root>\n );\n },\n);\n\nToast.displayName = \"Toast\";\n"],"names":["ToastPrimitive","React","jsx","cn","InfoIcon","WarningIcon","SuccessIcon","ErrorIcon","jsxs","Avatar","Button","IconButton","CloseIcon"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8CO,MAAM,gBAA8CA,0BAAe;AAGnE,MAAM,gBAAgBC,iBAAM,WAGjC,CAAC,EAAE,WAAW,GAAG,MAAA,GAAS,QAC1BC,2BAAAA;AAAAA,EAACF,0BAAe;AAAA,EAAf;AAAA,IACC;AAAA,IACA,WAAWG,GAAAA;AAAAA,MACT;AAAA,MACA;AAAA,IAAA;AAAA,IAED,GAAG;AAAA,EAAA;AACN,CACD;AAED,cAAc,cAAc;AAE5B,MAAM,cAAc,CAAC,EAAE,cAAyC;AAC9D,UAAQ,SAAA;AAAA,IACN,KAAK;AACH,aAAOD,2BAAAA,IAACE,SAAAA,UAAA,EAAS,WAAU,2BAAA,CAA2B;AAAA,IACxD,KAAK;AACH,aAAOF,2BAAAA,IAACG,YAAAA,aAAA,EAAY,WAAU,8BAAA,CAA8B;AAAA,IAC9D,KAAK;AACH,aAAOH,2BAAAA,IAACI,YAAAA,aAAA,EAAY,WAAU,8BAAA,CAA8B;AAAA,IAC9D,KAAK;AACH,aAAOJ,2BAAAA,IAACK,UAAAA,WAAA,EAAU,WAAU,4BAAA,CAA4B;AAAA,EAAA;AAE9D;AAcO,MAAM,QAAQN,iBAAM;AAAA,EACzB,CACE;AAAA,IACE;AAAA,IACA,UAAU;AAAA,IACV;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,YAAY;AAAA,IACZ,aAAa;AAAA,IACb;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAG;AAAA,EAAA,GAEL,QACG;AACH,WACEO,2BAAAA;AAAAA,MAACR,0BAAe;AAAA,MAAf;AAAA,QACC;AAAA,QACA,eAAY;AAAA,QACZ,WAAWG,GAAAA;AAAAA;AAAAA,UAET;AAAA;AAAA,UAEA;AAAA;AAAA,UAEA;AAAA;AAAA,UAEA;AAAA,QAAA;AAAA,QAED,GAAG;AAAA,QAEJ,UAAA;AAAA,UAAAK,2BAAAA,KAAC,OAAA,EAAI,WAAU,kCACb,UAAA;AAAA,YAAAN,2BAAAA,IAAC,SAAI,WAAU,cACZ,sBAAY,iBACX,4CAAcO,eAAA,EAAO,KAAK,WAAW,KAAK,WAAW,UAAU,eAAA,CAAgB,IAE/EP,2BAAAA,IAAC,aAAA,EAAY,SAAkB,EAAA,CAEnC;AAAA,YACAM,2BAAAA,KAAC,OAAA,EAAI,WAAU,oCACZ,UAAA;AAAA,cAAA,wCACER,0BAAe,OAAf,EAAqB,WAAU,uCAC7B,UAAA,OACH;AAAA,cAED,eACCE,2BAAAA,IAACF,0BAAe,aAAf,EAA2B,WAAU,sDACnC,UAAA,aACH;AAAA,cAED;AAAA,cACA,iBACCE,2BAAAA;AAAAA,gBAACQ,OAAAA;AAAAA,gBAAA;AAAA,kBACC,SAAQ;AAAA,kBAER,WAAU;AAAA,kBACV,MAAK;AAAA,kBACL,SAAS;AAAA,kBAER,UAAA,eAAe;AAAA,gBAAA;AAAA,cAAA;AAAA,YAClB,EAAA,CAEJ;AAAA,UAAA,GACF;AAAA,UACC,aACCR,2BAAAA,IAACF,0BAAe,OAAf,EAAqB,SAAO,MAC3B,UAAAE,2BAAAA;AAAAA,YAACS,WAAAA;AAAAA,YAAA;AAAA,cACC,qCAAOC,UAAAA,WAAA,EAAU;AAAA,cACjB,cAAY;AAAA,cAEZ,WAAU;AAAA,cACV,SAAQ;AAAA,cACR,MAAK;AAAA,YAAA;AAAA,UAAA,EACP,CACF;AAAA,QAAA;AAAA,MAAA;AAAA,IAAA;AAAA,EAIR;AACF;AAEA,MAAM,cAAc;;;;"}
1
+ {"version":3,"file":"Toast.cjs","sources":["../../../../src/components/Toast/Toast.tsx"],"sourcesContent":["import * as ToastPrimitive from \"@radix-ui/react-toast\";\nimport * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { Avatar } from \"../Avatar/Avatar\";\nimport { Button } from \"../Button/Button\";\nimport { CloseIcon } from \"../Icons/CloseIcon\";\nimport { ErrorIcon } from \"../Icons/ErrorIcon\";\nimport { InfoIcon } from \"../Icons/InfoIcon\";\nimport { SuccessIcon } from \"../Icons/SuccessIcon\";\nimport { WarningIcon } from \"../Icons/WarningIcon\";\n\n/** Visual/semantic variant of the toast notification. */\nexport type ToastVariant = \"info\" | \"warning\" | \"success\" | \"error\" | \"messageToast\";\n\nexport interface ToastProps\n extends Omit<Omit<React.ComponentPropsWithoutRef<typeof ToastPrimitive.Root>, \"type\">, \"title\"> {\n /** Visual/semantic variant of the toast. @default \"info\" */\n variant?: ToastVariant;\n /** Title text displayed in bold at the top of the toast. */\n title?: string;\n /** Description or body content displayed below the title. */\n description?: React.ReactNode;\n /** Label for the optional action button. @default \"Action\" */\n actionLabel?: string;\n /** Click handler for the action button. When provided, the action button is rendered. */\n onActionClick?: () => void;\n /** Whether to show the close button. @default true */\n showClose?: boolean;\n /** Accessible label for the close button. @default \"Close notification\" */\n closeLabel?: string;\n /** Avatar image URL (used by the `messageToast` variant). */\n avatarSrc?: string;\n /** Alt text for the avatar image. */\n avatarAlt?: string;\n /** Fallback content for the avatar (e.g. initials). */\n avatarFallback?: string;\n}\n\n/** Props for the {@link ToastProvider}. Wraps Radix `Toast.Provider`. */\nexport interface ToastProviderProps extends ToastPrimitive.ToastProviderProps {}\n/** Props for the {@link ToastViewport}. Controls where toasts are rendered on screen. */\nexport interface ToastViewportProps\n extends React.ComponentPropsWithoutRef<typeof ToastPrimitive.Viewport> {}\n\n/** Provides toast context. Wrap your application (or a subtree) with this provider. */\nexport const ToastProvider: React.FC<ToastProviderProps> = ToastPrimitive.Provider;\n\n/** Fixed-position container that renders active toasts. Place once at the root of your app. */\nexport const ToastViewport = React.forwardRef<\n React.ElementRef<typeof ToastPrimitive.Viewport>,\n ToastViewportProps\n>(({ className, ...props }, ref) => (\n <ToastPrimitive.Viewport\n ref={ref}\n className={cn(\n \"pointer-events-none fixed right-0 bottom-0 z-100 flex max-h-screen w-full flex-col-reverse gap-3 p-4 md:max-w-[420px]\",\n className,\n )}\n {...props}\n />\n));\n\nToastViewport.displayName = \"ToastViewport\";\n\nconst VariantIcon = ({ variant }: { variant: ToastVariant }) => {\n switch (variant) {\n case \"info\":\n return <InfoIcon size={16} filled className=\"text-alerts-toast-icon-info\" />;\n case \"warning\":\n return <WarningIcon size={16} filled className=\"text-alerts-toast-icon-warning\" />;\n case \"success\":\n return <SuccessIcon className=\"size-4 text-alerts-toast-icon-success\" />;\n case \"error\":\n return <ErrorIcon className=\"size-4 text-alerts-toast-icon-error\" />;\n }\n};\n\n/**\n * A dismissible notification that appears temporarily. Supports `info`,\n * `warning`, `success`, `error`, and `messageToast` variants with optional\n * action button, close control, and avatar.\n *\n * Use inside a {@link ToastProvider} with a {@link ToastViewport}.\n *\n * @example\n * ```tsx\n * <Toast variant=\"success\" title=\"Saved\" description=\"Your changes are live.\" />\n * ```\n */\nexport const Toast = React.forwardRef<React.ComponentRef<typeof ToastPrimitive.Root>, ToastProps>(\n (\n {\n className,\n variant = \"info\",\n title,\n description,\n actionLabel,\n onActionClick,\n showClose = true,\n closeLabel = \"Close notification\",\n avatarSrc,\n avatarAlt,\n avatarFallback,\n children,\n ...props\n },\n ref,\n ) => {\n return (\n <ToastPrimitive.Root\n ref={ref}\n data-testid=\"toast\"\n className={cn(\n \"group pointer-events-auto relative flex w-full items-start gap-6 overflow-hidden rounded-md border-none bg-surface-primary-inverted py-3 pr-3 pl-4 text-content-primary-inverted shadow-md transition-all\",\n \"data-[state=closed]:fade-out-80 data-[state=closed]:slide-out-to-right-full data-[state=open]:slide-in-from-bottom-full data-[swipe=cancel]:translate-x-0 data-[swipe=end]:translate-x-(--radix-toast-swipe-end-x) data-[swipe=move]:translate-x-(--radix-toast-swipe-move-x) data-[state=closed]:animate-out data-[state=open]:animate-in data-[swipe=end]:animate-out data-[swipe=move]:transition-none\",\n className,\n )}\n {...props}\n >\n <div className=\"flex min-w-0 flex-1 items-start gap-3 py-1 pr-1\">\n <div className=\"flex shrink-0 items-center pt-px\">\n {variant === \"messageToast\" ? (\n avatarSrc && <Avatar src={avatarSrc} alt={avatarAlt} fallback={avatarFallback} />\n ) : (\n <VariantIcon variant={variant} />\n )}\n </div>\n <div className=\"flex min-w-0 flex-1 flex-col items-start gap-4\">\n <div className=\"flex w-full flex-col items-start gap-1\">\n {title && (\n <ToastPrimitive.Title className=\"typography-body-small-14px-semibold\">\n {title}\n </ToastPrimitive.Title>\n )}\n {description && (\n <ToastPrimitive.Description className=\"typography-body-small-14px-regular\">\n {description}\n </ToastPrimitive.Description>\n )}\n {children}\n </div>\n {onActionClick && (\n <Button variant=\"outline\" negative size=\"32\" onClick={onActionClick}>\n {actionLabel ?? \"Action\"}\n </Button>\n )}\n </div>\n </div>\n {showClose && (\n <ToastPrimitive.Close asChild>\n <button\n type=\"button\"\n aria-label={closeLabel}\n className=\"flex size-6 shrink-0 cursor-pointer items-center justify-center rounded-xs bg-buttons-secondary-negative-default text-content-primary-inverted transition-colors hover:bg-buttons-secondary-negative-hover focus-visible:shadow-focus-ring focus-visible:outline-none\"\n >\n <CloseIcon size={16} aria-hidden=\"true\" />\n </button>\n </ToastPrimitive.Close>\n )}\n </ToastPrimitive.Root>\n );\n },\n);\n\nToast.displayName = \"Toast\";\n"],"names":["ToastPrimitive","React","jsx","cn","InfoIcon","WarningIcon","SuccessIcon","ErrorIcon","jsxs","Avatar","Button","CloseIcon"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6CO,MAAM,gBAA8CA,0BAAe;AAGnE,MAAM,gBAAgBC,iBAAM,WAGjC,CAAC,EAAE,WAAW,GAAG,MAAA,GAAS,QAC1BC,2BAAAA;AAAAA,EAACF,0BAAe;AAAA,EAAf;AAAA,IACC;AAAA,IACA,WAAWG,GAAAA;AAAAA,MACT;AAAA,MACA;AAAA,IAAA;AAAA,IAED,GAAG;AAAA,EAAA;AACN,CACD;AAED,cAAc,cAAc;AAE5B,MAAM,cAAc,CAAC,EAAE,cAAyC;AAC9D,UAAQ,SAAA;AAAA,IACN,KAAK;AACH,4CAAQC,mBAAA,EAAS,MAAM,IAAI,QAAM,MAAC,WAAU,+BAA8B;AAAA,IAC5E,KAAK;AACH,4CAAQC,yBAAA,EAAY,MAAM,IAAI,QAAM,MAAC,WAAU,kCAAiC;AAAA,IAClF,KAAK;AACH,aAAOH,2BAAAA,IAACI,YAAAA,aAAA,EAAY,WAAU,wCAAA,CAAwC;AAAA,IACxE,KAAK;AACH,aAAOJ,2BAAAA,IAACK,UAAAA,WAAA,EAAU,WAAU,sCAAA,CAAsC;AAAA,EAAA;AAExE;AAcO,MAAM,QAAQN,iBAAM;AAAA,EACzB,CACE;AAAA,IACE;AAAA,IACA,UAAU;AAAA,IACV;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,YAAY;AAAA,IACZ,aAAa;AAAA,IACb;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAG;AAAA,EAAA,GAEL,QACG;AACH,WACEO,2BAAAA;AAAAA,MAACR,0BAAe;AAAA,MAAf;AAAA,QACC;AAAA,QACA,eAAY;AAAA,QACZ,WAAWG,GAAAA;AAAAA,UACT;AAAA,UACA;AAAA,UACA;AAAA,QAAA;AAAA,QAED,GAAG;AAAA,QAEJ,UAAA;AAAA,UAAAK,2BAAAA,KAAC,OAAA,EAAI,WAAU,mDACb,UAAA;AAAA,YAAAN,2BAAAA,IAAC,SAAI,WAAU,oCACZ,sBAAY,iBACX,4CAAcO,eAAA,EAAO,KAAK,WAAW,KAAK,WAAW,UAAU,eAAA,CAAgB,IAE/EP,2BAAAA,IAAC,aAAA,EAAY,SAAkB,EAAA,CAEnC;AAAA,YACAM,2BAAAA,KAAC,OAAA,EAAI,WAAU,kDACb,UAAA;AAAA,cAAAA,2BAAAA,KAAC,OAAA,EAAI,WAAU,0CACZ,UAAA;AAAA,gBAAA,wCACER,0BAAe,OAAf,EAAqB,WAAU,uCAC7B,UAAA,OACH;AAAA,gBAED,eACCE,2BAAAA,IAACF,0BAAe,aAAf,EAA2B,WAAU,sCACnC,UAAA,aACH;AAAA,gBAED;AAAA,cAAA,GACH;AAAA,cACC,iBACCE,2BAAAA,IAACQ,OAAAA,QAAA,EAAO,SAAQ,WAAU,UAAQ,MAAC,MAAK,MAAK,SAAS,eACnD,UAAA,eAAe,SAAA,CAClB;AAAA,YAAA,EAAA,CAEJ;AAAA,UAAA,GACF;AAAA,UACC,aACCR,2BAAAA,IAACF,0BAAe,OAAf,EAAqB,SAAO,MAC3B,UAAAE,2BAAAA;AAAAA,YAAC;AAAA,YAAA;AAAA,cACC,MAAK;AAAA,cACL,cAAY;AAAA,cACZ,WAAU;AAAA,cAEV,UAAAA,2BAAAA,IAACS,qBAAA,EAAU,MAAM,IAAI,eAAY,OAAA,CAAO;AAAA,YAAA;AAAA,UAAA,EAC1C,CACF;AAAA,QAAA;AAAA,MAAA;AAAA,IAAA;AAAA,EAIR;AACF;AAEA,MAAM,cAAc;;;;"}
@@ -0,0 +1,67 @@
1
+ "use client";
2
+ "use strict";
3
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
4
+ const jsxRuntime = require("react/jsx-runtime");
5
+ const React = require("react");
6
+ const cn = require("../../utils/cn.cjs");
7
+ const VerifiedIcon = require("../Icons/VerifiedIcon.cjs");
8
+ const ProfileOnlineStatus = require("../ProfileOnlineStatus/ProfileOnlineStatus.cjs");
9
+ function _interopNamespaceDefault(e) {
10
+ const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
11
+ if (e) {
12
+ for (const k in e) {
13
+ if (k !== "default") {
14
+ const d = Object.getOwnPropertyDescriptor(e, k);
15
+ Object.defineProperty(n, k, d.get ? d : {
16
+ enumerable: true,
17
+ get: () => e[k]
18
+ });
19
+ }
20
+ }
21
+ }
22
+ n.default = e;
23
+ return Object.freeze(n);
24
+ }
25
+ const React__namespace = /* @__PURE__ */ _interopNamespaceDefault(React);
26
+ const UserDisplayName = React__namespace.forwardRef(
27
+ ({
28
+ ambassador,
29
+ ambassadorLabel = "Ambassador",
30
+ children,
31
+ className,
32
+ component = "span",
33
+ noWrap = true,
34
+ onlineLabel = "Online",
35
+ showOnlineStatus,
36
+ verified,
37
+ verifiedLabel = "Verified",
38
+ ...props
39
+ }, ref) => {
40
+ const Component = component;
41
+ const badge = ambassador ? { label: ambassadorLabel, tint: "text-success-content" } : verified ? { label: verifiedLabel, tint: "text-content-primary" } : null;
42
+ return /* @__PURE__ */ jsxRuntime.jsxs(
43
+ Component,
44
+ {
45
+ ref,
46
+ className: cn.cn("inline-flex max-w-full items-center", className),
47
+ ...props,
48
+ children: [
49
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn.cn("min-w-0", noWrap && "truncate"), children }),
50
+ badge && /* @__PURE__ */ jsxRuntime.jsx(
51
+ "span",
52
+ {
53
+ role: "img",
54
+ "aria-label": badge.label,
55
+ className: cn.cn("ml-2 inline-flex shrink-0 items-center", badge.tint),
56
+ children: /* @__PURE__ */ jsxRuntime.jsx(VerifiedIcon.VerifiedIcon, { size: 16 })
57
+ }
58
+ ),
59
+ showOnlineStatus && /* @__PURE__ */ jsxRuntime.jsx(ProfileOnlineStatus.ProfileOnlineStatus, { label: onlineLabel, className: "shrink-0 ml-2" })
60
+ ]
61
+ }
62
+ );
63
+ }
64
+ );
65
+ UserDisplayName.displayName = "UserDisplayName";
66
+ exports.UserDisplayName = UserDisplayName;
67
+ //# sourceMappingURL=UserDisplayName.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"UserDisplayName.cjs","sources":["../../../../src/components/UserDisplayName/UserDisplayName.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { VerifiedIcon } from \"../Icons/VerifiedIcon\";\nimport { ProfileOnlineStatus } from \"../ProfileOnlineStatus/ProfileOnlineStatus\";\n\nexport interface UserDisplayNameProps extends React.HTMLAttributes<HTMLElement> {\n /** Render an ambassador badge after the name. */\n ambassador?: boolean;\n /** Accessible label for the ambassador badge. @default \"Ambassador\" */\n ambassadorLabel?: string;\n /** HTML element used for the root wrapper. @default \"span\" */\n component?: \"span\" | \"h1\" | \"h2\" | \"h3\" | \"p\" | \"div\";\n /** Truncate the display name on a single line. @default true */\n noWrap?: boolean;\n /** Accessible label for the online-status indicator. @default \"Online\" */\n onlineLabel?: string;\n /** Render the inline online-status indicator after the name. @default false */\n showOnlineStatus?: boolean;\n /** Render a verified badge after the name (ignored when `ambassador` is set). */\n verified?: boolean;\n /** Accessible label for the verified badge. @default \"Verified\" */\n verifiedLabel?: string;\n}\n\n/**\n * Renders a user's display name with optional ambassador/verified badges and an\n * online-status indicator. Only the name shrinks and truncates; trailing badges\n * and the online-status indicator stay visible on the same line.\n *\n * Typography is not baked in: pass a `typography-*` utility via `className` on\n * the root and the name inherits it. Use `typography-body-small-14px-semibold`\n * for the standard display-name scale.\n *\n * When both `ambassador` and `verified` are set, the ambassador badge takes\n * precedence. Its tint uses `text-success-content` (not `text-icons-brand-green`)\n * so the green darkens in light mode and lightens in dark mode, matching\n * {@link ProfileOnlineStatus}; `text-icons-brand-green` is fixed across modes.\n *\n * @example\n * ```tsx\n * <UserDisplayName className=\"typography-body-small-14px-semibold\">Jane Doe</UserDisplayName>\n * ```\n */\nexport const UserDisplayName = React.forwardRef<HTMLElement, UserDisplayNameProps>(\n (\n {\n ambassador,\n ambassadorLabel = \"Ambassador\",\n children,\n className,\n component = \"span\",\n noWrap = true,\n onlineLabel = \"Online\",\n showOnlineStatus,\n verified,\n verifiedLabel = \"Verified\",\n ...props\n },\n ref,\n ) => {\n const Component = component as React.ElementType;\n\n const badge = ambassador\n ? { label: ambassadorLabel, tint: \"text-success-content\" }\n : verified\n ? { label: verifiedLabel, tint: \"text-content-primary\" }\n : null;\n\n return (\n <Component\n ref={ref}\n className={cn(\"inline-flex max-w-full items-center\", className)}\n {...props}\n >\n <span className={cn(\"min-w-0\", noWrap && \"truncate\")}>{children}</span>\n {badge && (\n <span\n role=\"img\"\n aria-label={badge.label}\n className={cn(\"ml-2 inline-flex shrink-0 items-center\", badge.tint)}\n >\n <VerifiedIcon size={16} />\n </span>\n )}\n {showOnlineStatus && <ProfileOnlineStatus label={onlineLabel} className=\"shrink-0 ml-2\" />}\n </Component>\n );\n },\n);\n\nUserDisplayName.displayName = \"UserDisplayName\";\n"],"names":["React","jsxs","cn","jsx","VerifiedIcon","ProfileOnlineStatus"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AA2CO,MAAM,kBAAkBA,iBAAM;AAAA,EACnC,CACE;AAAA,IACE;AAAA,IACA,kBAAkB;AAAA,IAClB;AAAA,IACA;AAAA,IACA,YAAY;AAAA,IACZ,SAAS;AAAA,IACT,cAAc;AAAA,IACd;AAAA,IACA;AAAA,IACA,gBAAgB;AAAA,IAChB,GAAG;AAAA,EAAA,GAEL,QACG;AACH,UAAM,YAAY;AAElB,UAAM,QAAQ,aACV,EAAE,OAAO,iBAAiB,MAAM,uBAAA,IAChC,WACE,EAAE,OAAO,eAAe,MAAM,2BAC9B;AAEN,WACEC,2BAAAA;AAAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACA,WAAWC,GAAAA,GAAG,uCAAuC,SAAS;AAAA,QAC7D,GAAG;AAAA,QAEJ,UAAA;AAAA,UAAAC,+BAAC,UAAK,WAAWD,GAAAA,GAAG,WAAW,UAAU,UAAU,GAAI,UAAS;AAAA,UAC/D,SACCC,2BAAAA;AAAAA,YAAC;AAAA,YAAA;AAAA,cACC,MAAK;AAAA,cACL,cAAY,MAAM;AAAA,cAClB,WAAWD,GAAAA,GAAG,0CAA0C,MAAM,IAAI;AAAA,cAElE,UAAAC,2BAAAA,IAACC,aAAAA,cAAA,EAAa,MAAM,GAAA,CAAI;AAAA,YAAA;AAAA,UAAA;AAAA,UAG3B,oBAAoBD,2BAAAA,IAACE,yCAAA,EAAoB,OAAO,aAAa,WAAU,gBAAA,CAAgB;AAAA,QAAA;AAAA,MAAA;AAAA,IAAA;AAAA,EAG9F;AACF;AAEA,gBAAgB,cAAc;;"}
@@ -0,0 +1,46 @@
1
+ "use client";
2
+ "use strict";
3
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
4
+ const jsxRuntime = require("react/jsx-runtime");
5
+ const React = require("react");
6
+ const cn = require("../../utils/cn.cjs");
7
+ function _interopNamespaceDefault(e) {
8
+ const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
9
+ if (e) {
10
+ for (const k in e) {
11
+ if (k !== "default") {
12
+ const d = Object.getOwnPropertyDescriptor(e, k);
13
+ Object.defineProperty(n, k, d.get ? d : {
14
+ enumerable: true,
15
+ get: () => e[k]
16
+ });
17
+ }
18
+ }
19
+ }
20
+ n.default = e;
21
+ return Object.freeze(n);
22
+ }
23
+ const React__namespace = /* @__PURE__ */ _interopNamespaceDefault(React);
24
+ const HANDLE_SYMBOL = "@";
25
+ const UserHandle = React__namespace.forwardRef(
26
+ ({ children, className, ...props }, ref) => {
27
+ return /* @__PURE__ */ jsxRuntime.jsxs(
28
+ "span",
29
+ {
30
+ ref,
31
+ className: cn.cn(
32
+ "typography-body-small-14px-regular block max-w-full truncate text-content-secondary",
33
+ className
34
+ ),
35
+ ...props,
36
+ children: [
37
+ HANDLE_SYMBOL,
38
+ children
39
+ ]
40
+ }
41
+ );
42
+ }
43
+ );
44
+ UserHandle.displayName = "UserHandle";
45
+ exports.UserHandle = UserHandle;
46
+ //# sourceMappingURL=UserHandle.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"UserHandle.cjs","sources":["../../../../src/components/UserHandle/UserHandle.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\n\nconst HANDLE_SYMBOL = \"@\";\n\nexport interface UserHandleProps extends React.HTMLAttributes<HTMLSpanElement> {}\n\n/**\n * Renders a user handle prefixed with the `@` symbol as muted, truncated\n * secondary text.\n *\n * @example\n * ```tsx\n * <UserHandle>jane_doe</UserHandle>\n * ```\n */\nexport const UserHandle = React.forwardRef<HTMLSpanElement, UserHandleProps>(\n ({ children, className, ...props }, ref) => {\n return (\n <span\n ref={ref}\n className={cn(\n \"typography-body-small-14px-regular block max-w-full truncate text-content-secondary\",\n className,\n )}\n {...props}\n >\n {HANDLE_SYMBOL}\n {children}\n </span>\n );\n },\n);\n\nUserHandle.displayName = \"UserHandle\";\n"],"names":["React","jsxs","cn"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAGA,MAAM,gBAAgB;AAaf,MAAM,aAAaA,iBAAM;AAAA,EAC9B,CAAC,EAAE,UAAU,WAAW,GAAG,MAAA,GAAS,QAAQ;AAC1C,WACEC,2BAAAA;AAAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACA,WAAWC,GAAAA;AAAAA,UACT;AAAA,UACA;AAAA,QAAA;AAAA,QAED,GAAG;AAAA,QAEH,UAAA;AAAA,UAAA;AAAA,UACA;AAAA,QAAA;AAAA,MAAA;AAAA,IAAA;AAAA,EAGP;AACF;AAEA,WAAW,cAAc;;"}
@@ -0,0 +1,74 @@
1
+ "use client";
2
+ "use strict";
3
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
4
+ const jsxRuntime = require("react/jsx-runtime");
5
+ const React = require("react");
6
+ const cn = require("../../utils/cn.cjs");
7
+ const getInitials = require("../../utils/getInitials.cjs");
8
+ const Avatar = require("../Avatar/Avatar.cjs");
9
+ const BellOffIcon = require("../Icons/BellOffIcon.cjs");
10
+ const UserDisplayName = require("../UserDisplayName/UserDisplayName.cjs");
11
+ const UserHandle = require("../UserHandle/UserHandle.cjs");
12
+ function _interopNamespaceDefault(e) {
13
+ const n = Object.create(null, { [Symbol.toStringTag]: { value: "Module" } });
14
+ if (e) {
15
+ for (const k in e) {
16
+ if (k !== "default") {
17
+ const d = Object.getOwnPropertyDescriptor(e, k);
18
+ Object.defineProperty(n, k, d.get ? d : {
19
+ enumerable: true,
20
+ get: () => e[k]
21
+ });
22
+ }
23
+ }
24
+ }
25
+ n.default = e;
26
+ return Object.freeze(n);
27
+ }
28
+ const React__namespace = /* @__PURE__ */ _interopNamespaceDefault(React);
29
+ const AVATAR_SIZES = [16, 24, 32, 40, 48, 64, 88, 148];
30
+ const getNearestAvatarSize = (size) => AVATAR_SIZES.reduce(
31
+ (prev, curr) => Math.abs(curr - size) < Math.abs(prev - size) ? curr : prev
32
+ );
33
+ const UserItem = React__namespace.forwardRef(
34
+ ({
35
+ user,
36
+ avatarSize,
37
+ isOnline = false,
38
+ isMuted = false,
39
+ showOnlineStatus,
40
+ showHandle = true,
41
+ showAvatar = true,
42
+ className,
43
+ ...props
44
+ }, ref) => {
45
+ return /* @__PURE__ */ jsxRuntime.jsxs(
46
+ "div",
47
+ {
48
+ ref,
49
+ className: cn.cn("relative flex w-full items-center justify-start px-2 py-1", className),
50
+ ...props,
51
+ children: [
52
+ isMuted && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute bottom-0 left-0 z-1 flex rounded-xs bg-surface-primary p-1", children: /* @__PURE__ */ jsxRuntime.jsx(BellOffIcon.BellOffIcon, { size: 16 }) }),
53
+ showAvatar && /* @__PURE__ */ jsxRuntime.jsx(
54
+ Avatar.Avatar,
55
+ {
56
+ size: getNearestAvatarSize(avatarSize || 48),
57
+ src: user.avatarUri?.url,
58
+ alt: user.displayName,
59
+ fallback: getInitials.getInitials(user.displayName),
60
+ onlineIndicator: Boolean(showOnlineStatus && isOnline)
61
+ }
62
+ ),
63
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 overflow-hidden pl-2", children: [
64
+ /* @__PURE__ */ jsxRuntime.jsx(UserDisplayName.UserDisplayName, { className: "typography-body-small-14px-semibold", children: user.nickname || user.displayName }),
65
+ showHandle && /* @__PURE__ */ jsxRuntime.jsx(UserHandle.UserHandle, { children: user.handle })
66
+ ] })
67
+ ]
68
+ }
69
+ );
70
+ }
71
+ );
72
+ UserItem.displayName = "UserItem";
73
+ exports.UserItem = UserItem;
74
+ //# sourceMappingURL=UserItem.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"UserItem.cjs","sources":["../../../../src/components/UserItem/UserItem.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { getInitials } from \"../../utils/getInitials\";\nimport { Avatar } from \"../Avatar/Avatar\";\nimport { BellOffIcon } from \"../Icons/BellOffIcon\";\nimport { UserDisplayName } from \"../UserDisplayName/UserDisplayName\";\nimport { UserHandle } from \"../UserHandle/UserHandle\";\n\nconst AVATAR_SIZES = [16, 24, 32, 40, 48, 64, 88, 148] as const;\ntype AvatarSizeToken = (typeof AVATAR_SIZES)[number];\n\n/** Snap an arbitrary pixel size to the nearest supported {@link Avatar} size token. */\nconst getNearestAvatarSize = (size: number): AvatarSizeToken =>\n AVATAR_SIZES.reduce((prev, curr) =>\n Math.abs(curr - size) < Math.abs(prev - size) ? curr : prev,\n );\n\n/** Minimal user shape consumed by {@link UserItem}. */\nexport type UserItemUser = {\n avatarUri?: { url: string; url2x?: string };\n displayName: string;\n handle: string;\n nickname?: string;\n};\n\nexport interface UserItemProps extends React.HTMLAttributes<HTMLDivElement> {\n /** The user to display. */\n user: UserItemUser;\n /** Desired avatar size in px; snapped to the nearest supported token. @default 48 */\n avatarSize?: number;\n /** Show the muted indicator in the bottom-left corner. @default false */\n isMuted?: boolean;\n /** Whether the user is online (only shown when `showOnlineStatus` is also set). @default false */\n isOnline?: boolean;\n /** Render the avatar. @default true */\n showAvatar?: boolean;\n /** Render the handle line under the display name. @default true */\n showHandle?: boolean;\n /** Enable the avatar online indicator (combined with `isOnline`). */\n showOnlineStatus?: boolean;\n}\n\n/**\n * A compact user row showing an avatar, display name (or nickname) and handle,\n * with optional online and muted indicators.\n *\n * @example\n * ```tsx\n * <UserItem user={{ displayName: \"Jane Doe\", handle: \"jane_doe\" }} />\n * ```\n */\nexport const UserItem = React.forwardRef<HTMLDivElement, UserItemProps>(\n (\n {\n user,\n avatarSize,\n isOnline = false,\n isMuted = false,\n showOnlineStatus,\n showHandle = true,\n showAvatar = true,\n className,\n ...props\n },\n ref,\n ) => {\n return (\n <div\n ref={ref}\n className={cn(\"relative flex w-full items-center justify-start px-2 py-1\", className)}\n {...props}\n >\n {isMuted && (\n <div className=\"absolute bottom-0 left-0 z-1 flex rounded-xs bg-surface-primary p-1\">\n <BellOffIcon size={16} />\n </div>\n )}\n {showAvatar && (\n <Avatar\n size={getNearestAvatarSize(avatarSize || 48)}\n src={user.avatarUri?.url}\n alt={user.displayName}\n fallback={getInitials(user.displayName)}\n onlineIndicator={Boolean(showOnlineStatus && isOnline)}\n />\n )}\n <div className=\"flex-1 overflow-hidden pl-2\">\n <UserDisplayName className=\"typography-body-small-14px-semibold\">\n {user.nickname || user.displayName}\n </UserDisplayName>\n {showHandle && <UserHandle>{user.handle}</UserHandle>}\n </div>\n </div>\n );\n },\n);\n\nUserItem.displayName = \"UserItem\";\n"],"names":["React","jsxs","cn","jsx","BellOffIcon","Avatar","getInitials","UserDisplayName","UserHandle"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAQA,MAAM,eAAe,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,GAAG;AAIrD,MAAM,uBAAuB,CAAC,SAC5B,aAAa;AAAA,EAAO,CAAC,MAAM,SACzB,KAAK,IAAI,OAAO,IAAI,IAAI,KAAK,IAAI,OAAO,IAAI,IAAI,OAAO;AACzD;AAoCK,MAAM,WAAWA,iBAAM;AAAA,EAC5B,CACE;AAAA,IACE;AAAA,IACA;AAAA,IACA,WAAW;AAAA,IACX,UAAU;AAAA,IACV;AAAA,IACA,aAAa;AAAA,IACb,aAAa;AAAA,IACb;AAAA,IACA,GAAG;AAAA,EAAA,GAEL,QACG;AACH,WACEC,2BAAAA;AAAAA,MAAC;AAAA,MAAA;AAAA,QACC;AAAA,QACA,WAAWC,GAAAA,GAAG,6DAA6D,SAAS;AAAA,QACnF,GAAG;AAAA,QAEH,UAAA;AAAA,UAAA,WACCC,2BAAAA,IAAC,SAAI,WAAU,uEACb,yCAACC,YAAAA,aAAA,EAAY,MAAM,IAAI,EAAA,CACzB;AAAA,UAED,cACCD,2BAAAA;AAAAA,YAACE,OAAAA;AAAAA,YAAA;AAAA,cACC,MAAM,qBAAqB,cAAc,EAAE;AAAA,cAC3C,KAAK,KAAK,WAAW;AAAA,cACrB,KAAK,KAAK;AAAA,cACV,UAAUC,YAAAA,YAAY,KAAK,WAAW;AAAA,cACtC,iBAAiB,QAAQ,oBAAoB,QAAQ;AAAA,YAAA;AAAA,UAAA;AAAA,UAGzDL,2BAAAA,KAAC,OAAA,EAAI,WAAU,+BACb,UAAA;AAAA,YAAAE,+BAACI,gBAAAA,mBAAgB,WAAU,uCACxB,UAAA,KAAK,YAAY,KAAK,aACzB;AAAA,YACC,cAAcJ,2BAAAA,IAACK,WAAAA,YAAA,EAAY,UAAA,KAAK,OAAA,CAAO;AAAA,UAAA,EAAA,CAC1C;AAAA,QAAA;AAAA,MAAA;AAAA,IAAA;AAAA,EAGN;AACF;AAEA,SAAS,cAAc;;"}
@@ -100,6 +100,7 @@ const ForwardIcon = require("./components/Icons/ForwardIcon.cjs");
100
100
  const GalleryIcon = require("./components/Icons/GalleryIcon.cjs");
101
101
  const GameIcon = require("./components/Icons/GameIcon.cjs");
102
102
  const GenderIcon = require("./components/Icons/GenderIcon.cjs");
103
+ const GifIcon = require("./components/Icons/GifIcon.cjs");
103
104
  const GiftIcon = require("./components/Icons/GiftIcon.cjs");
104
105
  const GoogleIcon = require("./components/Icons/GoogleIcon.cjs");
105
106
  const HealthIcon = require("./components/Icons/HealthIcon.cjs");
@@ -184,6 +185,7 @@ const UserIcon = require("./components/Icons/UserIcon.cjs");
184
185
  const UserMenuIcon = require("./components/Icons/UserMenuIcon.cjs");
185
186
  const UsersIcon = require("./components/Icons/UsersIcon.cjs");
186
187
  const VaultIcon = require("./components/Icons/VaultIcon.cjs");
188
+ const VerifiedIcon = require("./components/Icons/VerifiedIcon.cjs");
187
189
  const VideoIcon = require("./components/Icons/VideoIcon.cjs");
188
190
  const VipBadgeIcon = require("./components/Icons/VipBadgeIcon.cjs");
189
191
  const WalletIcon = require("./components/Icons/WalletIcon.cjs");
@@ -202,9 +204,12 @@ const OnlineBlinkingIcon = require("./components/OnlineBlinkingIcon/OnlineBlinki
202
204
  const Pagination = require("./components/Pagination/Pagination.cjs");
203
205
  const PasswordField = require("./components/PasswordField/PasswordField.cjs");
204
206
  const Pill = require("./components/Pill/Pill.cjs");
207
+ const ProfileOnlineStatus = require("./components/ProfileOnlineStatus/ProfileOnlineStatus.cjs");
205
208
  const ProgressBar = require("./components/ProgressBar/ProgressBar.cjs");
206
209
  const Radio = require("./components/Radio/Radio.cjs");
207
210
  const RadioGroup = require("./components/RadioGroup/RadioGroup.cjs");
211
+ const RatingSummary = require("./components/RatingSummary/RatingSummary.cjs");
212
+ const ReviewCard = require("./components/ReviewCard/ReviewCard.cjs");
208
213
  const SearchField = require("./components/SearchField/SearchField.cjs");
209
214
  const Select = require("./components/Select/Select.cjs");
210
215
  const Skeleton = require("./components/Skeleton/Skeleton.cjs");
@@ -225,7 +230,11 @@ const TextArea = require("./components/TextArea/TextArea.cjs");
225
230
  const TextField = require("./components/TextField/TextField.cjs");
226
231
  const Toast = require("./components/Toast/Toast.cjs");
227
232
  const Tooltip = require("./components/Tooltip/Tooltip.cjs");
233
+ const UserDisplayName = require("./components/UserDisplayName/UserDisplayName.cjs");
234
+ const UserHandle = require("./components/UserHandle/UserHandle.cjs");
235
+ const UserItem = require("./components/UserItem/UserItem.cjs");
228
236
  const cn = require("./utils/cn.cjs");
237
+ const getInitials = require("./utils/getInitials.cjs");
229
238
  const useSuppressClickAfterDrag = require("./utils/useSuppressClickAfterDrag.cjs");
230
239
  Object.defineProperty(exports, "Slot", {
231
240
  enumerable: true,
@@ -372,6 +381,7 @@ exports.ForwardIcon = ForwardIcon.ForwardIcon;
372
381
  exports.GalleryIcon = GalleryIcon.GalleryIcon;
373
382
  exports.GameIcon = GameIcon.GameIcon;
374
383
  exports.GenderIcon = GenderIcon.GenderIcon;
384
+ exports.GifIcon = GifIcon.GifIcon;
375
385
  exports.GiftIcon = GiftIcon.GiftIcon;
376
386
  exports.GoogleIcon = GoogleIcon.GoogleIcon;
377
387
  exports.HealthIcon = HealthIcon.HealthIcon;
@@ -456,6 +466,7 @@ exports.UserIcon = UserIcon.UserIcon;
456
466
  exports.UserMenuIcon = UserMenuIcon.UserMenuIcon;
457
467
  exports.UsersIcon = UsersIcon.UsersIcon;
458
468
  exports.VaultIcon = VaultIcon.VaultIcon;
469
+ exports.VerifiedIcon = VerifiedIcon.VerifiedIcon;
459
470
  exports.VideoIcon = VideoIcon.VideoIcon;
460
471
  exports.VipBadgeIcon = VipBadgeIcon.VipBadgeIcon;
461
472
  exports.WalletIcon = WalletIcon.WalletIcon;
@@ -476,9 +487,12 @@ exports.OnlineBlinkingIcon = OnlineBlinkingIcon.OnlineBlinkingIcon;
476
487
  exports.Pagination = Pagination.Pagination;
477
488
  exports.PasswordField = PasswordField.PasswordField;
478
489
  exports.Pill = Pill.Pill;
490
+ exports.ProfileOnlineStatus = ProfileOnlineStatus.ProfileOnlineStatus;
479
491
  exports.ProgressBar = ProgressBar.ProgressBar;
480
492
  exports.Radio = Radio.Radio;
481
493
  exports.RadioGroup = RadioGroup.RadioGroup;
494
+ exports.RatingSummary = RatingSummary.RatingSummary;
495
+ exports.ReviewCard = ReviewCard.ReviewCard;
482
496
  exports.SearchField = SearchField.SearchField;
483
497
  exports.Select = Select.Select;
484
498
  exports.SelectContent = Select.SelectContent;
@@ -528,6 +542,10 @@ exports.Tooltip = Tooltip.Tooltip;
528
542
  exports.TooltipContent = Tooltip.TooltipContent;
529
543
  exports.TooltipProvider = Tooltip.TooltipProvider;
530
544
  exports.TooltipTrigger = Tooltip.TooltipTrigger;
545
+ exports.UserDisplayName = UserDisplayName.UserDisplayName;
546
+ exports.UserHandle = UserHandle.UserHandle;
547
+ exports.UserItem = UserItem.UserItem;
531
548
  exports.cn = cn.cn;
549
+ exports.getInitials = getInitials.getInitials;
532
550
  exports.useSuppressClickAfterDrag = useSuppressClickAfterDrag.useSuppressClickAfterDrag;
533
551
  //# sourceMappingURL=index.cjs.map