@frame-kit/ui-ng 0.2.24 → 0.2.25
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.
|
@@ -31,7 +31,15 @@ class AvatarComponent {
|
|
|
31
31
|
if (!name) {
|
|
32
32
|
return '?';
|
|
33
33
|
}
|
|
34
|
-
|
|
34
|
+
// Only words that start with a letter count, so a suffix such as
|
|
35
|
+
// "(she/her)" or "(dev)" never lends a bracket to the initials.
|
|
36
|
+
const parts = name
|
|
37
|
+
.trim()
|
|
38
|
+
.split(/\s+/)
|
|
39
|
+
.filter((part) => /^\p{L}/u.test(part));
|
|
40
|
+
if (parts.length === 0) {
|
|
41
|
+
return '?';
|
|
42
|
+
}
|
|
35
43
|
if (parts.length >= 2) {
|
|
36
44
|
return (parts[0][0] + parts[parts.length - 1][0]).toUpperCase();
|
|
37
45
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"frame-kit-ui-ng-ui-avatar.mjs","sources":["../../../../packages/ui-ng/ui/avatar/avatar.component.ts","../../../../packages/ui-ng/ui/avatar/avatar.component.html","../../../../packages/ui-ng/ui/avatar/frame-kit-ui-ng-ui-avatar.ts"],"sourcesContent":["import {\n ChangeDetectionStrategy,\n Component,\n computed,\n HostBinding,\n input,\n} from '@angular/core';\n\nimport type { AvatarSize, AvatarStatus } from './avatar.types';\n\n@Component({\n selector: 'fk-avatar',\n standalone: true,\n imports: [],\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './avatar.component.html',\n styleUrl: './avatar.component.scss',\n})\nexport class AvatarComponent {\n // ===== IDENTITY =====\n /** Full display name used to derive initials when no explicit initials or image are provided. */\n readonly name = input.required<string>();\n /** URL of the avatar image; falls back to initials when the image fails to load. */\n readonly avatarUrl = input<string | null>(null);\n /** Explicit two-character initials that override the name-derived fallback. */\n readonly initials = input<string | null>(null);\n\n // ===== STATUS =====\n /** Online/offline/away status to reflect on the indicator dot. */\n readonly status = input<AvatarStatus | null>(null);\n /** When true, renders the status indicator dot over the avatar. */\n readonly showStatus = input<boolean>(false);\n\n // ===== DISPLAY =====\n /** Controls the avatar size. */\n readonly size = input<AvatarSize>('md');\n\n // ===== BASE PROPS =====\n readonly className = input<string>('');\n readonly id = input<string | null>(null);\n readonly ariaLabel = input<string | null>(null);\n\n // ===== COMPUTED =====\n\n readonly derivedInitials = computed(() => {\n const explicit = this.initials();\n\n if (explicit) {\n return explicit;\n }\n\n const name = this.name();\n\n if (!name) {\n return '?';\n }\n\n const parts = name.trim().split(/\\s+/);\n\n if (parts.length >= 2) {\n return (parts[0][0] + parts[parts.length - 1][0]).toUpperCase();\n }\n\n return parts[0].substring(0, 2).toUpperCase();\n });\n\n readonly showIndicator = computed(\n () => this.showStatus() && this.status() !== null,\n );\n\n readonly classes = computed(() => {\n return [\n 'fk-avatar',\n `fk-avatar--${this.size()}`,\n this.showIndicator() ? `fk-avatar--status-${this.status()}` : '',\n this.className(),\n ]\n .filter(Boolean)\n .join(' ');\n });\n\n @HostBinding('class')\n get hostClass() {\n return this.classes();\n }\n\n @HostBinding('attr.id')\n get hostId(): string | null {\n return this.id();\n }\n\n // Tracks whether the image failed to load\n readonly imgError = { value: false };\n\n onImgError(): void {\n this.imgError.value = true;\n }\n}\n","<!-- Avatar circle -->\n<span\n class=\"fk-avatar__circle\"\n [attr.aria-label]=\"ariaLabel() ?? 'Avatar for ' + name()\"\n role=\"img\"\n>\n @if (avatarUrl() && !imgError.value) {\n <img\n class=\"fk-avatar__image\"\n [src]=\"avatarUrl()\"\n [alt]=\"name()\"\n (error)=\"onImgError()\"\n />\n } @else {\n <span class=\"fk-avatar__initials\" aria-hidden=\"true\">\n {{ derivedInitials() }}\n </span>\n }\n</span>\n\n<!-- Status indicator -->\n@if (showIndicator()) {\n <span\n class=\"fk-avatar__status\"\n [attr.aria-label]=\"status() + ' status'\"\n role=\"status\"\n ></span>\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;MAkBa,eAAe,CAAA;;;AAGjB,IAAA,IAAI,GAAG,KAAK,CAAC,QAAQ,0EAAU;;AAE/B,IAAA,SAAS,GAAG,KAAK,CAAgB,IAAI,gFAAC;;AAEtC,IAAA,QAAQ,GAAG,KAAK,CAAgB,IAAI,+EAAC;;;AAIrC,IAAA,MAAM,GAAG,KAAK,CAAsB,IAAI,6EAAC;;AAEzC,IAAA,UAAU,GAAG,KAAK,CAAU,KAAK,iFAAC;;;AAIlC,IAAA,IAAI,GAAG,KAAK,CAAa,IAAI,2EAAC;;AAG9B,IAAA,SAAS,GAAG,KAAK,CAAS,EAAE,gFAAC;AAC7B,IAAA,EAAE,GAAG,KAAK,CAAgB,IAAI,yEAAC;AAC/B,IAAA,SAAS,GAAG,KAAK,CAAgB,IAAI,gFAAC;;AAItC,IAAA,eAAe,GAAG,QAAQ,CAAC,MAAK;AACvC,QAAA,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,EAAE;QAEhC,IAAI,QAAQ,EAAE;AACZ,YAAA,OAAO,QAAQ;QACjB;AAEA,QAAA,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,EAAE;QAExB,IAAI,CAAC,IAAI,EAAE;AACT,YAAA,OAAO,GAAG;QACZ
|
|
1
|
+
{"version":3,"file":"frame-kit-ui-ng-ui-avatar.mjs","sources":["../../../../packages/ui-ng/ui/avatar/avatar.component.ts","../../../../packages/ui-ng/ui/avatar/avatar.component.html","../../../../packages/ui-ng/ui/avatar/frame-kit-ui-ng-ui-avatar.ts"],"sourcesContent":["import {\n ChangeDetectionStrategy,\n Component,\n computed,\n HostBinding,\n input,\n} from '@angular/core';\n\nimport type { AvatarSize, AvatarStatus } from './avatar.types';\n\n@Component({\n selector: 'fk-avatar',\n standalone: true,\n imports: [],\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './avatar.component.html',\n styleUrl: './avatar.component.scss',\n})\nexport class AvatarComponent {\n // ===== IDENTITY =====\n /** Full display name used to derive initials when no explicit initials or image are provided. */\n readonly name = input.required<string>();\n /** URL of the avatar image; falls back to initials when the image fails to load. */\n readonly avatarUrl = input<string | null>(null);\n /** Explicit two-character initials that override the name-derived fallback. */\n readonly initials = input<string | null>(null);\n\n // ===== STATUS =====\n /** Online/offline/away status to reflect on the indicator dot. */\n readonly status = input<AvatarStatus | null>(null);\n /** When true, renders the status indicator dot over the avatar. */\n readonly showStatus = input<boolean>(false);\n\n // ===== DISPLAY =====\n /** Controls the avatar size. */\n readonly size = input<AvatarSize>('md');\n\n // ===== BASE PROPS =====\n readonly className = input<string>('');\n readonly id = input<string | null>(null);\n readonly ariaLabel = input<string | null>(null);\n\n // ===== COMPUTED =====\n\n readonly derivedInitials = computed(() => {\n const explicit = this.initials();\n\n if (explicit) {\n return explicit;\n }\n\n const name = this.name();\n\n if (!name) {\n return '?';\n }\n\n // Only words that start with a letter count, so a suffix such as\n // \"(she/her)\" or \"(dev)\" never lends a bracket to the initials.\n const parts = name\n .trim()\n .split(/\\s+/)\n .filter((part) => /^\\p{L}/u.test(part));\n\n if (parts.length === 0) {\n return '?';\n }\n\n if (parts.length >= 2) {\n return (parts[0][0] + parts[parts.length - 1][0]).toUpperCase();\n }\n\n return parts[0].substring(0, 2).toUpperCase();\n });\n\n readonly showIndicator = computed(\n () => this.showStatus() && this.status() !== null,\n );\n\n readonly classes = computed(() => {\n return [\n 'fk-avatar',\n `fk-avatar--${this.size()}`,\n this.showIndicator() ? `fk-avatar--status-${this.status()}` : '',\n this.className(),\n ]\n .filter(Boolean)\n .join(' ');\n });\n\n @HostBinding('class')\n get hostClass() {\n return this.classes();\n }\n\n @HostBinding('attr.id')\n get hostId(): string | null {\n return this.id();\n }\n\n // Tracks whether the image failed to load\n readonly imgError = { value: false };\n\n onImgError(): void {\n this.imgError.value = true;\n }\n}\n","<!-- Avatar circle -->\n<span\n class=\"fk-avatar__circle\"\n [attr.aria-label]=\"ariaLabel() ?? 'Avatar for ' + name()\"\n role=\"img\"\n>\n @if (avatarUrl() && !imgError.value) {\n <img\n class=\"fk-avatar__image\"\n [src]=\"avatarUrl()\"\n [alt]=\"name()\"\n (error)=\"onImgError()\"\n />\n } @else {\n <span class=\"fk-avatar__initials\" aria-hidden=\"true\">\n {{ derivedInitials() }}\n </span>\n }\n</span>\n\n<!-- Status indicator -->\n@if (showIndicator()) {\n <span\n class=\"fk-avatar__status\"\n [attr.aria-label]=\"status() + ' status'\"\n role=\"status\"\n ></span>\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@frame-kit/ui-ng",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.25",
|
|
4
4
|
"description": "Style-agnostic, token-driven Angular UI component library for FrameKit.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"@angular/forms": "^21.2.0",
|
|
18
18
|
"@angular/platform-browser": "^21.2.0",
|
|
19
19
|
"@angular/router": "^21.2.0",
|
|
20
|
-
"@frame-kit/utils": "0.2.
|
|
20
|
+
"@frame-kit/utils": "0.2.25",
|
|
21
21
|
"rxjs": "^7.0.0"
|
|
22
22
|
},
|
|
23
23
|
"sideEffects": false,
|
package/ui/avatar/README.md
CHANGED
|
@@ -25,7 +25,7 @@ A token-driven avatar atom that displays a user image with an initials fallback
|
|
|
25
25
|
## Features
|
|
26
26
|
|
|
27
27
|
- Displays an image when `avatarUrl` is provided, gracefully falling back to initials on load error
|
|
28
|
-
- Auto-derives initials from `name` (first + last initial for multi-word names, first two characters for single names)
|
|
28
|
+
- Auto-derives initials from `name` (first + last initial for multi-word names, first two characters for single names); words that do not start with a letter, such as a "(she/her)" suffix, are ignored
|
|
29
29
|
- Status indicator dot positioned at the bottom-right corner, color-coded by status
|
|
30
30
|
- Three size presets (`sm`, `md`, `lg`) controlled via tokens
|
|
31
31
|
- Fully token-driven — all colors, sizes, typography, and radii are overridable
|