Skip to content

Commit 44ec503

Browse files
mhuang1234Michelle Huang
andauthored
Get initials using graphemes instead of chars (#3980)
* Handle characters requiring surrogate pairs in Avatar getInitials * Split graphemes * Replace graphemer with unicode-segmenter * Update yarn.lock * Run prettier * Fix lint error --------- Co-authored-by: Michelle Huang <[email protected]>
1 parent 63d6044 commit 44ec503

File tree

4 files changed

+41
-5
lines changed

4 files changed

+41
-5
lines changed
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"type": "patch",
3+
"comment": "Handle characters requiring surrogate pairs in Avatar getInitials",
4+
"packageName": "@fluentui-react-native/avatar",
5+
"email": "email not defined",
6+
"dependentChangeType": "patch"
7+
}

packages/components/Avatar/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@
4040
"@fluentui-react-native/theme-tokens": "workspace:*",
4141
"@fluentui-react-native/theming-utils": "workspace:*",
4242
"@fluentui-react-native/tokens": "workspace:*",
43-
"@fluentui-react-native/use-styling": "workspace:*"
43+
"@fluentui-react-native/use-styling": "workspace:*",
44+
"unicode-segmenter": "^0.14.4"
4445
},
4546
"devDependencies": {
4647
"@babel/core": "^7.20.0",

packages/components/Avatar/src/useAvatar.ts

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
import type { ImageProps, ImageSourcePropType } from 'react-native';
22
import { Platform } from 'react-native';
3-
43
import { createIconProps } from '@fluentui-react-native/icon';
54

65
import type { AvatarProps, AvatarInfo, AvatarState, AvatarSize, AvatarColor } from './Avatar.types';
76
import { AvatarColors } from './Avatar.types';
87
import { getHashCodeWeb } from './getHashCode';
98
import { titles, multiWordTitles } from './titles';
109

10+
const splitGraphemes = require('unicode-segmenter/grapheme').splitGraphemes as (str: string) => string[];
11+
1112
/**
1213
* Re-usable hook for FURN Avatar.
1314
* This hook configures Avatar props and state for FURN Avatar.
@@ -124,12 +125,31 @@ export const getInitials = (name: string): string => {
124125
}
125126

126127
const lastWordIdx = wordsLength - 1;
127-
const firstLetter = words[0].charAt(0).toUpperCase();
128-
const lastLetter = wordsLength > 1 ? words[lastWordIdx].charAt(0).toUpperCase() : '';
129-
const initials = `${firstLetter}${ARABIC_ASIAN_REGEXP.test(name) ? '' : lastLetter}`;
128+
const firstLetter = getFirstGrapheme(words[0]).toUpperCase();
129+
130+
let lastLetter = '';
131+
if (wordsLength > 1 && !ARABIC_ASIAN_REGEXP.test(name)) {
132+
lastLetter = getFirstGrapheme(words[lastWordIdx]).toUpperCase();
133+
}
134+
135+
const initials = `${firstLetter}${lastLetter}`;
130136
return initials;
131137
};
132138

139+
/**
140+
* Get the first grapheme cluster from a string
141+
*
142+
* @param str input string
143+
* @returns first grapheme cluster (handles composite emojis, skin tone modifiers, ZWJ sequences, etc.)
144+
*/
145+
const getFirstGrapheme = (str: string): string => {
146+
if (!str) {
147+
return '';
148+
}
149+
150+
return [...splitGraphemes(str)][0] ?? '';
151+
};
152+
133153
/**
134154
* A function which takes a name and returns array of valid words
135155
*

yarn.lock

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2521,6 +2521,7 @@ __metadata:
25212521
react-native-svg: "npm:>=15.4.0 <15.13.0"
25222522
react-native-windows: "npm:^0.74.0"
25232523
react-test-renderer: "npm:18.2.0"
2524+
unicode-segmenter: "npm:^0.14.4"
25242525
peerDependencies:
25252526
"@office-iss/react-native-win32": ^0.74.0
25262527
react: 18.2.0
@@ -21410,6 +21411,13 @@ __metadata:
2141021411
languageName: node
2141121412
linkType: hard
2141221413

21414+
"unicode-segmenter@npm:^0.14.4":
21415+
version: 0.14.4
21416+
resolution: "unicode-segmenter@npm:0.14.4"
21417+
checksum: 10c0/ec062a90518fd8cdba14ad2516b2a5d8240931f5e7668bb8dc8881d7b6962ba9739df0219b4a237118f17b2fbdaf7704df8803538517c51315c73d380dc75128
21418+
languageName: node
21419+
linkType: hard
21420+
2141321421
"unicorn-magic@npm:^0.3.0":
2141421422
version: 0.3.0
2141521423
resolution: "unicorn-magic@npm:0.3.0"

0 commit comments

Comments
 (0)