@sesionario/blocks 1.4.0 → 1.4.1
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 +8 -0
- package/dist/avatar.cjs +89 -0
- package/dist/avatar.cjs.map +1 -0
- package/dist/avatar.d.cts +18 -0
- package/dist/avatar.d.ts +18 -0
- package/dist/avatar.js +85 -0
- package/dist/avatar.js.map +1 -0
- package/dist/index.d.cts +2 -18
- package/dist/index.d.ts +2 -18
- package/package.json +11 -1
package/README.md
CHANGED
|
@@ -12,6 +12,14 @@ Shared feedback patterns include `ConfirmDestructiveDialog` (confirm before dele
|
|
|
12
12
|
pnpm add @sesionario/blocks
|
|
13
13
|
```
|
|
14
14
|
|
|
15
|
+
The main entry is a Client Component boundary. Pure helpers that must run in
|
|
16
|
+
React Server Components (e.g. avatar initials/colors) should be imported from
|
|
17
|
+
the server-safe subpath:
|
|
18
|
+
|
|
19
|
+
```ts
|
|
20
|
+
import { avatarFallbackStyle, getInitials } from "@sesionario/blocks/avatar";
|
|
21
|
+
```
|
|
22
|
+
|
|
15
23
|
Peer dependencies (install in the consuming app as needed):
|
|
16
24
|
|
|
17
25
|
- `react`, `react-dom`
|
package/dist/avatar.cjs
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// src/lib/avatar.ts
|
|
4
|
+
var EMPTY_COLORS = {
|
|
5
|
+
backgroundColor: "#9ca3af",
|
|
6
|
+
color: "#111111"
|
|
7
|
+
};
|
|
8
|
+
var AVATAR_PALETTE = [
|
|
9
|
+
"#4f6d8c",
|
|
10
|
+
// slate blue
|
|
11
|
+
"#3d7a6a",
|
|
12
|
+
// teal
|
|
13
|
+
"#6b5b8a",
|
|
14
|
+
// muted purple
|
|
15
|
+
"#8a5a4a",
|
|
16
|
+
// warm brown
|
|
17
|
+
"#4a7a8a",
|
|
18
|
+
// steel cyan
|
|
19
|
+
"#7a6b4a",
|
|
20
|
+
// olive
|
|
21
|
+
"#5a6b8a",
|
|
22
|
+
// periwinkle
|
|
23
|
+
"#8a4a5a",
|
|
24
|
+
// rose
|
|
25
|
+
"#4a8a6b",
|
|
26
|
+
// green
|
|
27
|
+
"#6b4a7a",
|
|
28
|
+
// plum
|
|
29
|
+
"#8a6b4a",
|
|
30
|
+
// amber brown
|
|
31
|
+
"#4a5a8a",
|
|
32
|
+
// indigo
|
|
33
|
+
"#7a4a6b",
|
|
34
|
+
// mauve
|
|
35
|
+
"#5a8a4a",
|
|
36
|
+
// leaf
|
|
37
|
+
"#8a5a7a",
|
|
38
|
+
// dusty pink
|
|
39
|
+
"#3d6b7a"
|
|
40
|
+
// deep teal
|
|
41
|
+
];
|
|
42
|
+
function hashString(input) {
|
|
43
|
+
let hash = 2166136261;
|
|
44
|
+
for (let i = 0; i < input.length; i++) {
|
|
45
|
+
hash ^= input.charCodeAt(i);
|
|
46
|
+
hash = Math.imul(hash, 16777619);
|
|
47
|
+
}
|
|
48
|
+
return hash >>> 0;
|
|
49
|
+
}
|
|
50
|
+
function srgbToLinear(channel) {
|
|
51
|
+
const c = channel / 255;
|
|
52
|
+
return c <= 0.04045 ? c / 12.92 : ((c + 0.055) / 1.055) ** 2.4;
|
|
53
|
+
}
|
|
54
|
+
function relativeLuminance(hex) {
|
|
55
|
+
const normalized = hex.replace("#", "");
|
|
56
|
+
const r = Number.parseInt(normalized.slice(0, 2), 16);
|
|
57
|
+
const g = Number.parseInt(normalized.slice(2, 4), 16);
|
|
58
|
+
const b = Number.parseInt(normalized.slice(4, 6), 16);
|
|
59
|
+
return 0.2126 * srgbToLinear(r) + 0.7152 * srgbToLinear(g) + 0.0722 * srgbToLinear(b);
|
|
60
|
+
}
|
|
61
|
+
function contrastingTextColor(backgroundHex) {
|
|
62
|
+
return relativeLuminance(backgroundHex) > 0.179 ? "#111111" : "#ffffff";
|
|
63
|
+
}
|
|
64
|
+
function getInitials(name, max = 2) {
|
|
65
|
+
const parts = name.trim().split(/\s+/).filter(Boolean);
|
|
66
|
+
if (parts.length === 0) return "?";
|
|
67
|
+
const letters = parts.slice(0, Math.max(1, max)).map((part) => part.charAt(0)).join("");
|
|
68
|
+
return letters.toUpperCase() || "?";
|
|
69
|
+
}
|
|
70
|
+
function getAvatarColors(name) {
|
|
71
|
+
const normalized = name.trim().toLowerCase();
|
|
72
|
+
if (!normalized) {
|
|
73
|
+
return { ...EMPTY_COLORS };
|
|
74
|
+
}
|
|
75
|
+
const backgroundColor = AVATAR_PALETTE[hashString(normalized) % AVATAR_PALETTE.length];
|
|
76
|
+
return {
|
|
77
|
+
backgroundColor,
|
|
78
|
+
color: contrastingTextColor(backgroundColor)
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
function avatarFallbackStyle(name) {
|
|
82
|
+
return getAvatarColors(name);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
exports.avatarFallbackStyle = avatarFallbackStyle;
|
|
86
|
+
exports.getAvatarColors = getAvatarColors;
|
|
87
|
+
exports.getInitials = getInitials;
|
|
88
|
+
//# sourceMappingURL=avatar.cjs.map
|
|
89
|
+
//# sourceMappingURL=avatar.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/lib/avatar.ts"],"names":[],"mappings":"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","file":"avatar.cjs","sourcesContent":["/** Neutral fallback when the name is empty. */\nconst EMPTY_COLORS = {\n\tbackgroundColor: \"#9ca3af\",\n\tcolor: \"#111111\",\n} as const;\n\n/**\n * Curated mid-lightness palette — professional, calm hues that stay\n * distinct when hashed by name and contrast well with black or white text.\n */\nconst AVATAR_PALETTE = [\n\t\"#4f6d8c\", // slate blue\n\t\"#3d7a6a\", // teal\n\t\"#6b5b8a\", // muted purple\n\t\"#8a5a4a\", // warm brown\n\t\"#4a7a8a\", // steel cyan\n\t\"#7a6b4a\", // olive\n\t\"#5a6b8a\", // periwinkle\n\t\"#8a4a5a\", // rose\n\t\"#4a8a6b\", // green\n\t\"#6b4a7a\", // plum\n\t\"#8a6b4a\", // amber brown\n\t\"#4a5a8a\", // indigo\n\t\"#7a4a6b\", // mauve\n\t\"#5a8a4a\", // leaf\n\t\"#8a5a7a\", // dusty pink\n\t\"#3d6b7a\", // deep teal\n] as const;\n\nexport type AvatarColors = {\n\tbackgroundColor: string;\n\tcolor: string;\n};\n\n/** FNV-1a 32-bit hash — stable across runtimes for the same string. */\nfunction hashString(input: string): number {\n\tlet hash = 0x811c9dc5;\n\tfor (let i = 0; i < input.length; i++) {\n\t\thash ^= input.charCodeAt(i);\n\t\thash = Math.imul(hash, 0x01000193);\n\t}\n\treturn hash >>> 0;\n}\n\nfunction srgbToLinear(channel: number): number {\n\tconst c = channel / 255;\n\treturn c <= 0.04045 ? c / 12.92 : ((c + 0.055) / 1.055) ** 2.4;\n}\n\n/** Relative luminance (WCAG) for a hex color like `#rrggbb`. */\nfunction relativeLuminance(hex: string): number {\n\tconst normalized = hex.replace(\"#\", \"\");\n\tconst r = Number.parseInt(normalized.slice(0, 2), 16);\n\tconst g = Number.parseInt(normalized.slice(2, 4), 16);\n\tconst b = Number.parseInt(normalized.slice(4, 6), 16);\n\treturn (\n\t\t0.2126 * srgbToLinear(r) +\n\t\t0.7152 * srgbToLinear(g) +\n\t\t0.0722 * srgbToLinear(b)\n\t);\n}\n\nfunction contrastingTextColor(backgroundHex: string): \"#ffffff\" | \"#111111\" {\n\t// Threshold ~0.179 ≈ contrast preference for mid tones (WCAG-inspired).\n\treturn relativeLuminance(backgroundHex) > 0.179 ? \"#111111\" : \"#ffffff\";\n}\n\n/**\n * Word-based initials from a display name (max letters, default 2).\n * Empty / whitespace-only names yield `\"?\"`.\n */\nexport function getInitials(name: string, max = 2): string {\n\tconst parts = name.trim().split(/\\s+/).filter(Boolean);\n\tif (parts.length === 0) return \"?\";\n\tconst letters = parts\n\t\t.slice(0, Math.max(1, max))\n\t\t.map((part) => part.charAt(0))\n\t\t.join(\"\");\n\treturn letters.toUpperCase() || \"?\";\n}\n\n/**\n * Deterministic background + contrasting foreground from a full name.\n * Same name (case-insensitive) always maps to the same colors.\n */\nexport function getAvatarColors(name: string): AvatarColors {\n\tconst normalized = name.trim().toLowerCase();\n\tif (!normalized) {\n\t\treturn { ...EMPTY_COLORS };\n\t}\n\tconst backgroundColor =\n\t\tAVATAR_PALETTE[hashString(normalized) % AVATAR_PALETTE.length]!;\n\treturn {\n\t\tbackgroundColor,\n\t\tcolor: contrastingTextColor(backgroundColor),\n\t};\n}\n\n/** CSS style object for `AvatarFallback` (or any letter-avatar container). */\nexport function avatarFallbackStyle(\n\tname: string,\n): Pick<AvatarColors, \"backgroundColor\" | \"color\"> {\n\treturn getAvatarColors(name);\n}\n"]}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
type AvatarColors = {
|
|
2
|
+
backgroundColor: string;
|
|
3
|
+
color: string;
|
|
4
|
+
};
|
|
5
|
+
/**
|
|
6
|
+
* Word-based initials from a display name (max letters, default 2).
|
|
7
|
+
* Empty / whitespace-only names yield `"?"`.
|
|
8
|
+
*/
|
|
9
|
+
declare function getInitials(name: string, max?: number): string;
|
|
10
|
+
/**
|
|
11
|
+
* Deterministic background + contrasting foreground from a full name.
|
|
12
|
+
* Same name (case-insensitive) always maps to the same colors.
|
|
13
|
+
*/
|
|
14
|
+
declare function getAvatarColors(name: string): AvatarColors;
|
|
15
|
+
/** CSS style object for `AvatarFallback` (or any letter-avatar container). */
|
|
16
|
+
declare function avatarFallbackStyle(name: string): Pick<AvatarColors, "backgroundColor" | "color">;
|
|
17
|
+
|
|
18
|
+
export { type AvatarColors, avatarFallbackStyle, getAvatarColors, getInitials };
|
package/dist/avatar.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
type AvatarColors = {
|
|
2
|
+
backgroundColor: string;
|
|
3
|
+
color: string;
|
|
4
|
+
};
|
|
5
|
+
/**
|
|
6
|
+
* Word-based initials from a display name (max letters, default 2).
|
|
7
|
+
* Empty / whitespace-only names yield `"?"`.
|
|
8
|
+
*/
|
|
9
|
+
declare function getInitials(name: string, max?: number): string;
|
|
10
|
+
/**
|
|
11
|
+
* Deterministic background + contrasting foreground from a full name.
|
|
12
|
+
* Same name (case-insensitive) always maps to the same colors.
|
|
13
|
+
*/
|
|
14
|
+
declare function getAvatarColors(name: string): AvatarColors;
|
|
15
|
+
/** CSS style object for `AvatarFallback` (or any letter-avatar container). */
|
|
16
|
+
declare function avatarFallbackStyle(name: string): Pick<AvatarColors, "backgroundColor" | "color">;
|
|
17
|
+
|
|
18
|
+
export { type AvatarColors, avatarFallbackStyle, getAvatarColors, getInitials };
|
package/dist/avatar.js
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
// src/lib/avatar.ts
|
|
2
|
+
var EMPTY_COLORS = {
|
|
3
|
+
backgroundColor: "#9ca3af",
|
|
4
|
+
color: "#111111"
|
|
5
|
+
};
|
|
6
|
+
var AVATAR_PALETTE = [
|
|
7
|
+
"#4f6d8c",
|
|
8
|
+
// slate blue
|
|
9
|
+
"#3d7a6a",
|
|
10
|
+
// teal
|
|
11
|
+
"#6b5b8a",
|
|
12
|
+
// muted purple
|
|
13
|
+
"#8a5a4a",
|
|
14
|
+
// warm brown
|
|
15
|
+
"#4a7a8a",
|
|
16
|
+
// steel cyan
|
|
17
|
+
"#7a6b4a",
|
|
18
|
+
// olive
|
|
19
|
+
"#5a6b8a",
|
|
20
|
+
// periwinkle
|
|
21
|
+
"#8a4a5a",
|
|
22
|
+
// rose
|
|
23
|
+
"#4a8a6b",
|
|
24
|
+
// green
|
|
25
|
+
"#6b4a7a",
|
|
26
|
+
// plum
|
|
27
|
+
"#8a6b4a",
|
|
28
|
+
// amber brown
|
|
29
|
+
"#4a5a8a",
|
|
30
|
+
// indigo
|
|
31
|
+
"#7a4a6b",
|
|
32
|
+
// mauve
|
|
33
|
+
"#5a8a4a",
|
|
34
|
+
// leaf
|
|
35
|
+
"#8a5a7a",
|
|
36
|
+
// dusty pink
|
|
37
|
+
"#3d6b7a"
|
|
38
|
+
// deep teal
|
|
39
|
+
];
|
|
40
|
+
function hashString(input) {
|
|
41
|
+
let hash = 2166136261;
|
|
42
|
+
for (let i = 0; i < input.length; i++) {
|
|
43
|
+
hash ^= input.charCodeAt(i);
|
|
44
|
+
hash = Math.imul(hash, 16777619);
|
|
45
|
+
}
|
|
46
|
+
return hash >>> 0;
|
|
47
|
+
}
|
|
48
|
+
function srgbToLinear(channel) {
|
|
49
|
+
const c = channel / 255;
|
|
50
|
+
return c <= 0.04045 ? c / 12.92 : ((c + 0.055) / 1.055) ** 2.4;
|
|
51
|
+
}
|
|
52
|
+
function relativeLuminance(hex) {
|
|
53
|
+
const normalized = hex.replace("#", "");
|
|
54
|
+
const r = Number.parseInt(normalized.slice(0, 2), 16);
|
|
55
|
+
const g = Number.parseInt(normalized.slice(2, 4), 16);
|
|
56
|
+
const b = Number.parseInt(normalized.slice(4, 6), 16);
|
|
57
|
+
return 0.2126 * srgbToLinear(r) + 0.7152 * srgbToLinear(g) + 0.0722 * srgbToLinear(b);
|
|
58
|
+
}
|
|
59
|
+
function contrastingTextColor(backgroundHex) {
|
|
60
|
+
return relativeLuminance(backgroundHex) > 0.179 ? "#111111" : "#ffffff";
|
|
61
|
+
}
|
|
62
|
+
function getInitials(name, max = 2) {
|
|
63
|
+
const parts = name.trim().split(/\s+/).filter(Boolean);
|
|
64
|
+
if (parts.length === 0) return "?";
|
|
65
|
+
const letters = parts.slice(0, Math.max(1, max)).map((part) => part.charAt(0)).join("");
|
|
66
|
+
return letters.toUpperCase() || "?";
|
|
67
|
+
}
|
|
68
|
+
function getAvatarColors(name) {
|
|
69
|
+
const normalized = name.trim().toLowerCase();
|
|
70
|
+
if (!normalized) {
|
|
71
|
+
return { ...EMPTY_COLORS };
|
|
72
|
+
}
|
|
73
|
+
const backgroundColor = AVATAR_PALETTE[hashString(normalized) % AVATAR_PALETTE.length];
|
|
74
|
+
return {
|
|
75
|
+
backgroundColor,
|
|
76
|
+
color: contrastingTextColor(backgroundColor)
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
function avatarFallbackStyle(name) {
|
|
80
|
+
return getAvatarColors(name);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export { avatarFallbackStyle, getAvatarColors, getInitials };
|
|
84
|
+
//# sourceMappingURL=avatar.js.map
|
|
85
|
+
//# sourceMappingURL=avatar.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/lib/avatar.ts"],"names":[],"mappings":"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","file":"avatar.js","sourcesContent":["/** Neutral fallback when the name is empty. */\nconst EMPTY_COLORS = {\n\tbackgroundColor: \"#9ca3af\",\n\tcolor: \"#111111\",\n} as const;\n\n/**\n * Curated mid-lightness palette — professional, calm hues that stay\n * distinct when hashed by name and contrast well with black or white text.\n */\nconst AVATAR_PALETTE = [\n\t\"#4f6d8c\", // slate blue\n\t\"#3d7a6a\", // teal\n\t\"#6b5b8a\", // muted purple\n\t\"#8a5a4a\", // warm brown\n\t\"#4a7a8a\", // steel cyan\n\t\"#7a6b4a\", // olive\n\t\"#5a6b8a\", // periwinkle\n\t\"#8a4a5a\", // rose\n\t\"#4a8a6b\", // green\n\t\"#6b4a7a\", // plum\n\t\"#8a6b4a\", // amber brown\n\t\"#4a5a8a\", // indigo\n\t\"#7a4a6b\", // mauve\n\t\"#5a8a4a\", // leaf\n\t\"#8a5a7a\", // dusty pink\n\t\"#3d6b7a\", // deep teal\n] as const;\n\nexport type AvatarColors = {\n\tbackgroundColor: string;\n\tcolor: string;\n};\n\n/** FNV-1a 32-bit hash — stable across runtimes for the same string. */\nfunction hashString(input: string): number {\n\tlet hash = 0x811c9dc5;\n\tfor (let i = 0; i < input.length; i++) {\n\t\thash ^= input.charCodeAt(i);\n\t\thash = Math.imul(hash, 0x01000193);\n\t}\n\treturn hash >>> 0;\n}\n\nfunction srgbToLinear(channel: number): number {\n\tconst c = channel / 255;\n\treturn c <= 0.04045 ? c / 12.92 : ((c + 0.055) / 1.055) ** 2.4;\n}\n\n/** Relative luminance (WCAG) for a hex color like `#rrggbb`. */\nfunction relativeLuminance(hex: string): number {\n\tconst normalized = hex.replace(\"#\", \"\");\n\tconst r = Number.parseInt(normalized.slice(0, 2), 16);\n\tconst g = Number.parseInt(normalized.slice(2, 4), 16);\n\tconst b = Number.parseInt(normalized.slice(4, 6), 16);\n\treturn (\n\t\t0.2126 * srgbToLinear(r) +\n\t\t0.7152 * srgbToLinear(g) +\n\t\t0.0722 * srgbToLinear(b)\n\t);\n}\n\nfunction contrastingTextColor(backgroundHex: string): \"#ffffff\" | \"#111111\" {\n\t// Threshold ~0.179 ≈ contrast preference for mid tones (WCAG-inspired).\n\treturn relativeLuminance(backgroundHex) > 0.179 ? \"#111111\" : \"#ffffff\";\n}\n\n/**\n * Word-based initials from a display name (max letters, default 2).\n * Empty / whitespace-only names yield `\"?\"`.\n */\nexport function getInitials(name: string, max = 2): string {\n\tconst parts = name.trim().split(/\\s+/).filter(Boolean);\n\tif (parts.length === 0) return \"?\";\n\tconst letters = parts\n\t\t.slice(0, Math.max(1, max))\n\t\t.map((part) => part.charAt(0))\n\t\t.join(\"\");\n\treturn letters.toUpperCase() || \"?\";\n}\n\n/**\n * Deterministic background + contrasting foreground from a full name.\n * Same name (case-insensitive) always maps to the same colors.\n */\nexport function getAvatarColors(name: string): AvatarColors {\n\tconst normalized = name.trim().toLowerCase();\n\tif (!normalized) {\n\t\treturn { ...EMPTY_COLORS };\n\t}\n\tconst backgroundColor =\n\t\tAVATAR_PALETTE[hashString(normalized) % AVATAR_PALETTE.length]!;\n\treturn {\n\t\tbackgroundColor,\n\t\tcolor: contrastingTextColor(backgroundColor),\n\t};\n}\n\n/** CSS style object for `AvatarFallback` (or any letter-avatar container). */\nexport function avatarFallbackStyle(\n\tname: string,\n): Pick<AvatarColors, \"backgroundColor\" | \"color\"> {\n\treturn getAvatarColors(name);\n}\n"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -9,6 +9,7 @@ import * as RPNInput from 'react-phone-number-input';
|
|
|
9
9
|
import { MessageScroller as MessageScroller$1 } from '@shadcn/react/message-scroller';
|
|
10
10
|
export { useMessageScroller, useMessageScrollerScrollable, useMessageScrollerVisibility } from '@shadcn/react/message-scroller';
|
|
11
11
|
import { ClassValue } from 'clsx';
|
|
12
|
+
export { AvatarColors, avatarFallbackStyle, getAvatarColors, getInitials } from './avatar.cjs';
|
|
12
13
|
|
|
13
14
|
/**
|
|
14
15
|
* Blocks Context Interfaces
|
|
@@ -808,21 +809,4 @@ declare function ChatMessageList({ messages, currentUserId, emptyTitle, emptyDes
|
|
|
808
809
|
|
|
809
810
|
declare function cn(...inputs: ClassValue[]): string;
|
|
810
811
|
|
|
811
|
-
type
|
|
812
|
-
backgroundColor: string;
|
|
813
|
-
color: string;
|
|
814
|
-
};
|
|
815
|
-
/**
|
|
816
|
-
* Word-based initials from a display name (max letters, default 2).
|
|
817
|
-
* Empty / whitespace-only names yield `"?"`.
|
|
818
|
-
*/
|
|
819
|
-
declare function getInitials(name: string, max?: number): string;
|
|
820
|
-
/**
|
|
821
|
-
* Deterministic background + contrasting foreground from a full name.
|
|
822
|
-
* Same name (case-insensitive) always maps to the same colors.
|
|
823
|
-
*/
|
|
824
|
-
declare function getAvatarColors(name: string): AvatarColors;
|
|
825
|
-
/** CSS style object for `AvatarFallback` (or any letter-avatar container). */
|
|
826
|
-
declare function avatarFallbackStyle(name: string): Pick<AvatarColors, "backgroundColor" | "color">;
|
|
827
|
-
|
|
828
|
-
export { type AutoplayState, type AvatarColors, AvatarEditor, AvatarEditorDialog, type AvatarEditorDialogProps, type AvatarEditorProps, type BlocksLanguage, Bubble, BubbleContent, BubbleGroup, BubbleReactions, type ChatListMessage, ChatMessageList, type ChatMessageListProps, ConfirmDestructiveDialog, type ConfirmDestructiveDialogProps, type DescribedPlaybackError, type EmojiCategoryData, type EmojiCategoryKey, type EmojiDatum, EmojiInput, type EmojiInputProps, EmojiPicker, type EmojiPickerLabels, type EmojiPickerLocale, EmojiPickerPopover, type EmojiPickerPopoverProps, type EmojiPickerProps, type EmojiSkinTone, EmojiTextarea, type EmojiTextareaProps, Empty, EmptyContent, EmptyDescription, EmptyHeader, EmptyMedia, EmptyState, type EmptyStateProps, EmptyTitle, ErrorState, type FeatureEntry, type HlsPlayerMode, type Language, LanguageContext, type LanguageContextValue, LanguageSwitcher, type LanguageSwitcherLabels, type LanguageSwitcherProps, LoadingState, MEXICO_STATES, MEXICO_STATE_PATHS, Marker, MarkerContent, MarkerIcon, Message, MessageAvatar, MessageContent, MessageFooter, MessageGroup, MessageHeader, MessageScroller, MessageScrollerButton, MessageScrollerContent, MessageScrollerItem, MessageScrollerProvider, MessageScrollerViewport, MexicoMap, type MexicoMapProps, type MexicoState, type MexicoStateId, OrgSwitcher, type OrgSwitcherLabels, type OrgSwitcherProps, type OrgSwitcherTenant, PhoneInput, type PhoneInputProps, type PlaybackErrorContext, type PlaybackErrorDetail, type PlaybackErrorKind, type PlaybackState, type PlaybackStats, type ProfessionalVerificationStatus, type QualityLevel, SearchCommand, type SearchCommandLabels, type SearchCommandProps, type SearchCommandSelection, type SearchHit, ThemeSwitcher, type ThemeSwitcherLabels, type ThemeSwitcherProps, type UseHlsPlaybackOptions, type UseHlsPlaybackResult, type UsePlaybackStatsOptions, type UseSearchHotkeyOptions, type UseSearchHotkeyResult, VerifiedProfessionalBadge, type VerifiedProfessionalBadgeProps, VideoPlayer, type VideoPlayerLabels, type VideoPlayerProps, avatarFallbackStyle, bubbleVariants, cn, createLiveHlsConfig, createVodHlsConfig, defaultLanguages, describePlaybackError, fuzzyMatch, getAvatarColors, getInitials, insertAtCaret, markerVariants, normalizeEmojiQuery, shouldRetryLiveEdge404, useDebouncedValue, useDebouncedValueStrict, useHlsPlayback, useLanguageContext, usePlaybackStats, useSearchHotkey };
|
|
812
|
+
export { type AutoplayState, AvatarEditor, AvatarEditorDialog, type AvatarEditorDialogProps, type AvatarEditorProps, type BlocksLanguage, Bubble, BubbleContent, BubbleGroup, BubbleReactions, type ChatListMessage, ChatMessageList, type ChatMessageListProps, ConfirmDestructiveDialog, type ConfirmDestructiveDialogProps, type DescribedPlaybackError, type EmojiCategoryData, type EmojiCategoryKey, type EmojiDatum, EmojiInput, type EmojiInputProps, EmojiPicker, type EmojiPickerLabels, type EmojiPickerLocale, EmojiPickerPopover, type EmojiPickerPopoverProps, type EmojiPickerProps, type EmojiSkinTone, EmojiTextarea, type EmojiTextareaProps, Empty, EmptyContent, EmptyDescription, EmptyHeader, EmptyMedia, EmptyState, type EmptyStateProps, EmptyTitle, ErrorState, type FeatureEntry, type HlsPlayerMode, type Language, LanguageContext, type LanguageContextValue, LanguageSwitcher, type LanguageSwitcherLabels, type LanguageSwitcherProps, LoadingState, MEXICO_STATES, MEXICO_STATE_PATHS, Marker, MarkerContent, MarkerIcon, Message, MessageAvatar, MessageContent, MessageFooter, MessageGroup, MessageHeader, MessageScroller, MessageScrollerButton, MessageScrollerContent, MessageScrollerItem, MessageScrollerProvider, MessageScrollerViewport, MexicoMap, type MexicoMapProps, type MexicoState, type MexicoStateId, OrgSwitcher, type OrgSwitcherLabels, type OrgSwitcherProps, type OrgSwitcherTenant, PhoneInput, type PhoneInputProps, type PlaybackErrorContext, type PlaybackErrorDetail, type PlaybackErrorKind, type PlaybackState, type PlaybackStats, type ProfessionalVerificationStatus, type QualityLevel, SearchCommand, type SearchCommandLabels, type SearchCommandProps, type SearchCommandSelection, type SearchHit, ThemeSwitcher, type ThemeSwitcherLabels, type ThemeSwitcherProps, type UseHlsPlaybackOptions, type UseHlsPlaybackResult, type UsePlaybackStatsOptions, type UseSearchHotkeyOptions, type UseSearchHotkeyResult, VerifiedProfessionalBadge, type VerifiedProfessionalBadgeProps, VideoPlayer, type VideoPlayerLabels, type VideoPlayerProps, bubbleVariants, cn, createLiveHlsConfig, createVodHlsConfig, defaultLanguages, describePlaybackError, fuzzyMatch, insertAtCaret, markerVariants, normalizeEmojiQuery, shouldRetryLiveEdge404, useDebouncedValue, useDebouncedValueStrict, useHlsPlayback, useLanguageContext, usePlaybackStats, useSearchHotkey };
|
package/dist/index.d.ts
CHANGED
|
@@ -9,6 +9,7 @@ import * as RPNInput from 'react-phone-number-input';
|
|
|
9
9
|
import { MessageScroller as MessageScroller$1 } from '@shadcn/react/message-scroller';
|
|
10
10
|
export { useMessageScroller, useMessageScrollerScrollable, useMessageScrollerVisibility } from '@shadcn/react/message-scroller';
|
|
11
11
|
import { ClassValue } from 'clsx';
|
|
12
|
+
export { AvatarColors, avatarFallbackStyle, getAvatarColors, getInitials } from './avatar.js';
|
|
12
13
|
|
|
13
14
|
/**
|
|
14
15
|
* Blocks Context Interfaces
|
|
@@ -808,21 +809,4 @@ declare function ChatMessageList({ messages, currentUserId, emptyTitle, emptyDes
|
|
|
808
809
|
|
|
809
810
|
declare function cn(...inputs: ClassValue[]): string;
|
|
810
811
|
|
|
811
|
-
type
|
|
812
|
-
backgroundColor: string;
|
|
813
|
-
color: string;
|
|
814
|
-
};
|
|
815
|
-
/**
|
|
816
|
-
* Word-based initials from a display name (max letters, default 2).
|
|
817
|
-
* Empty / whitespace-only names yield `"?"`.
|
|
818
|
-
*/
|
|
819
|
-
declare function getInitials(name: string, max?: number): string;
|
|
820
|
-
/**
|
|
821
|
-
* Deterministic background + contrasting foreground from a full name.
|
|
822
|
-
* Same name (case-insensitive) always maps to the same colors.
|
|
823
|
-
*/
|
|
824
|
-
declare function getAvatarColors(name: string): AvatarColors;
|
|
825
|
-
/** CSS style object for `AvatarFallback` (or any letter-avatar container). */
|
|
826
|
-
declare function avatarFallbackStyle(name: string): Pick<AvatarColors, "backgroundColor" | "color">;
|
|
827
|
-
|
|
828
|
-
export { type AutoplayState, type AvatarColors, AvatarEditor, AvatarEditorDialog, type AvatarEditorDialogProps, type AvatarEditorProps, type BlocksLanguage, Bubble, BubbleContent, BubbleGroup, BubbleReactions, type ChatListMessage, ChatMessageList, type ChatMessageListProps, ConfirmDestructiveDialog, type ConfirmDestructiveDialogProps, type DescribedPlaybackError, type EmojiCategoryData, type EmojiCategoryKey, type EmojiDatum, EmojiInput, type EmojiInputProps, EmojiPicker, type EmojiPickerLabels, type EmojiPickerLocale, EmojiPickerPopover, type EmojiPickerPopoverProps, type EmojiPickerProps, type EmojiSkinTone, EmojiTextarea, type EmojiTextareaProps, Empty, EmptyContent, EmptyDescription, EmptyHeader, EmptyMedia, EmptyState, type EmptyStateProps, EmptyTitle, ErrorState, type FeatureEntry, type HlsPlayerMode, type Language, LanguageContext, type LanguageContextValue, LanguageSwitcher, type LanguageSwitcherLabels, type LanguageSwitcherProps, LoadingState, MEXICO_STATES, MEXICO_STATE_PATHS, Marker, MarkerContent, MarkerIcon, Message, MessageAvatar, MessageContent, MessageFooter, MessageGroup, MessageHeader, MessageScroller, MessageScrollerButton, MessageScrollerContent, MessageScrollerItem, MessageScrollerProvider, MessageScrollerViewport, MexicoMap, type MexicoMapProps, type MexicoState, type MexicoStateId, OrgSwitcher, type OrgSwitcherLabels, type OrgSwitcherProps, type OrgSwitcherTenant, PhoneInput, type PhoneInputProps, type PlaybackErrorContext, type PlaybackErrorDetail, type PlaybackErrorKind, type PlaybackState, type PlaybackStats, type ProfessionalVerificationStatus, type QualityLevel, SearchCommand, type SearchCommandLabels, type SearchCommandProps, type SearchCommandSelection, type SearchHit, ThemeSwitcher, type ThemeSwitcherLabels, type ThemeSwitcherProps, type UseHlsPlaybackOptions, type UseHlsPlaybackResult, type UsePlaybackStatsOptions, type UseSearchHotkeyOptions, type UseSearchHotkeyResult, VerifiedProfessionalBadge, type VerifiedProfessionalBadgeProps, VideoPlayer, type VideoPlayerLabels, type VideoPlayerProps, avatarFallbackStyle, bubbleVariants, cn, createLiveHlsConfig, createVodHlsConfig, defaultLanguages, describePlaybackError, fuzzyMatch, getAvatarColors, getInitials, insertAtCaret, markerVariants, normalizeEmojiQuery, shouldRetryLiveEdge404, useDebouncedValue, useDebouncedValueStrict, useHlsPlayback, useLanguageContext, usePlaybackStats, useSearchHotkey };
|
|
812
|
+
export { type AutoplayState, AvatarEditor, AvatarEditorDialog, type AvatarEditorDialogProps, type AvatarEditorProps, type BlocksLanguage, Bubble, BubbleContent, BubbleGroup, BubbleReactions, type ChatListMessage, ChatMessageList, type ChatMessageListProps, ConfirmDestructiveDialog, type ConfirmDestructiveDialogProps, type DescribedPlaybackError, type EmojiCategoryData, type EmojiCategoryKey, type EmojiDatum, EmojiInput, type EmojiInputProps, EmojiPicker, type EmojiPickerLabels, type EmojiPickerLocale, EmojiPickerPopover, type EmojiPickerPopoverProps, type EmojiPickerProps, type EmojiSkinTone, EmojiTextarea, type EmojiTextareaProps, Empty, EmptyContent, EmptyDescription, EmptyHeader, EmptyMedia, EmptyState, type EmptyStateProps, EmptyTitle, ErrorState, type FeatureEntry, type HlsPlayerMode, type Language, LanguageContext, type LanguageContextValue, LanguageSwitcher, type LanguageSwitcherLabels, type LanguageSwitcherProps, LoadingState, MEXICO_STATES, MEXICO_STATE_PATHS, Marker, MarkerContent, MarkerIcon, Message, MessageAvatar, MessageContent, MessageFooter, MessageGroup, MessageHeader, MessageScroller, MessageScrollerButton, MessageScrollerContent, MessageScrollerItem, MessageScrollerProvider, MessageScrollerViewport, MexicoMap, type MexicoMapProps, type MexicoState, type MexicoStateId, OrgSwitcher, type OrgSwitcherLabels, type OrgSwitcherProps, type OrgSwitcherTenant, PhoneInput, type PhoneInputProps, type PlaybackErrorContext, type PlaybackErrorDetail, type PlaybackErrorKind, type PlaybackState, type PlaybackStats, type ProfessionalVerificationStatus, type QualityLevel, SearchCommand, type SearchCommandLabels, type SearchCommandProps, type SearchCommandSelection, type SearchHit, ThemeSwitcher, type ThemeSwitcherLabels, type ThemeSwitcherProps, type UseHlsPlaybackOptions, type UseHlsPlaybackResult, type UsePlaybackStatsOptions, type UseSearchHotkeyOptions, type UseSearchHotkeyResult, VerifiedProfessionalBadge, type VerifiedProfessionalBadgeProps, VideoPlayer, type VideoPlayerLabels, type VideoPlayerProps, bubbleVariants, cn, createLiveHlsConfig, createVodHlsConfig, defaultLanguages, describePlaybackError, fuzzyMatch, insertAtCaret, markerVariants, normalizeEmojiQuery, shouldRetryLiveEdge404, useDebouncedValue, useDebouncedValueStrict, useHlsPlayback, useLanguageContext, usePlaybackStats, useSearchHotkey };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sesionario/blocks",
|
|
3
|
-
"version": "1.4.
|
|
3
|
+
"version": "1.4.1",
|
|
4
4
|
"description": "Shared UI components for Sesionario applications",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -16,6 +16,16 @@
|
|
|
16
16
|
"types": "./dist/index.d.cts",
|
|
17
17
|
"default": "./dist/index.cjs"
|
|
18
18
|
}
|
|
19
|
+
},
|
|
20
|
+
"./avatar": {
|
|
21
|
+
"import": {
|
|
22
|
+
"types": "./dist/avatar.d.ts",
|
|
23
|
+
"default": "./dist/avatar.js"
|
|
24
|
+
},
|
|
25
|
+
"require": {
|
|
26
|
+
"types": "./dist/avatar.d.cts",
|
|
27
|
+
"default": "./dist/avatar.cjs"
|
|
28
|
+
}
|
|
19
29
|
}
|
|
20
30
|
},
|
|
21
31
|
"files": [
|