@lifecorner/angular-ui-kit 3.11.1 → 3.11.3
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/fesm2022/lifecorner-angular-ui-kit-avatar-group.mjs +1 -0
- package/fesm2022/lifecorner-angular-ui-kit-avatar-group.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-avatar.mjs +26 -2
- package/fesm2022/lifecorner-angular-ui-kit-avatar.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-button.mjs +4 -4
- package/fesm2022/lifecorner-angular-ui-kit-button.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-character-svg.mjs +2 -2
- package/fesm2022/lifecorner-angular-ui-kit-character-svg.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-character.mjs +18 -2
- package/fesm2022/lifecorner-angular-ui-kit-character.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-header.mjs +6 -1
- package/fesm2022/lifecorner-angular-ui-kit-header.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-logo.mjs +115 -2
- package/fesm2022/lifecorner-angular-ui-kit-logo.mjs.map +1 -1
- package/fesm2022/lifecorner-angular-ui-kit-sidenav.mjs +5 -1
- package/fesm2022/lifecorner-angular-ui-kit-sidenav.mjs.map +1 -1
- package/package.json +1 -1
- package/src/assets/character/comforts-dark.svg +1 -1
- package/src/assets/character/comforts-light.svg +1 -1
- package/types/lifecorner-angular-ui-kit-avatar.d.ts +27 -1
- package/types/lifecorner-angular-ui-kit-character.d.ts +19 -0
- package/types/lifecorner-angular-ui-kit-logo.d.ts +69 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lifecorner-angular-ui-kit-avatar-group.mjs","names":[],"sources":["../../../../libs/angular-ui-kit/src/lib/avatar-group/avatar-group.component.ts","../../../../libs/angular-ui-kit/src/lib/avatar-group/avatar-group.component.html"],"sourcesContent":["import {\n ChangeDetectionStrategy,\n Component,\n input,\n computed,\n} from '@angular/core';\nimport { AvatarColor, AvatarComponent, AvatarSize } from '@lifecorner/angular-ui-kit/avatar';\n\nexport interface AvatarGroupItem {\n /** Image source URL */\n src?: string;\n /** Alt text */\n alt?: string;\n /** Full name for initials fallback */\n name?: string;\n /** Background of the initials: `default` or a member colour `member-1` … `member-6` (see `lc-avatar`). */\n color?: AvatarColor;\n}\n\n@Component({\n selector: 'lc-avatar-group',\n standalone: true,\n imports: [AvatarComponent],\n templateUrl: './avatar-group.component.html',\n styleUrls: ['./avatar-group.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\n/**\n * Avatar group component for displaying multiple user avatars.\n *\n * Features:\n * - Overlapping avatar display with configurable max visible count\n * - Overflow indicator showing remaining count\n * - Shared size variant across all avatars (xs, sm, md, lg)\n * - Automatic truncation based on max property\n * - Member colours per item (`color`), later avatars on top\n * - `ring`: each avatar gets a ring in the page colour instead of the surface\n * border; with `overlap=\"4px\"` this is the \"Weite\" member row\n *\n * @example\n * ```html\n * <lc-avatar-group [avatars]=\"users\" [max]=\"5\" size=\"md\" />\n * <lc-avatar-group\n * [avatars]=\"[{ name: 'Johanna Apfelbaum', color: 'member-1' }, { name: 'Tom Ek', color: 'member-2' }]\"\n * [ring]=\"true\"\n * overlap=\"4px\"\n * />\n * ```\n */\nexport class AvatarGroupComponent {\n /** List of avatars to show */\n avatars = input.required<AvatarGroupItem[]>();\n\n /** Avatar size */\n size = input<AvatarSize>('md');\n\n /** Maximum visible avatars before showing overflow count */\n max = input<number>(5);\n\n /**\n * Separate the avatars with a ring in the page colour\n * (`--lc-avatar-ring-color`, default `--color-background`) instead of the\n * 2 px surface border. Later avatars sit on top.\n */\n ring = input<boolean>(false);\n\n /**\n * How far each avatar overlaps the previous one, as a CSS length (e.g.\n * `4px`). Empty keeps the size's default (6–12 px).\n */\n overlap = input<string>('');\n\n protected visibleAvatars = computed(() => {\n const all = this.avatars();\n const limit = this.max();\n return all.slice(0, limit);\n });\n\n protected overflowCount = computed(() => {\n const all = this.avatars();\n const limit = this.max();\n return Math.max(0, all.length - limit);\n });\n\n protected groupClasses = computed(() => {\n const classes = ['avatar-group', `avatar-group--${this.size()}`];\n if (this.ring()) classes.push('avatar-group--ring');\n return classes.join(' ');\n });\n}\n","<div [class]=\"groupClasses()\" [style.--lc-avatar-group-overlap]=\"overlap() || null\">\n @for (avatar of visibleAvatars(); track avatar.name ?? $index) {\n <lc-avatar\n class=\"avatar-group__item\"\n [src]=\"avatar.src\"\n [alt]=\"avatar.alt\"\n [name]=\"avatar.name\"\n [size]=\"size()\"\n [color]=\"avatar.color ?? 'default'\"\n [ring]=\"ring()\"\n />\n }\n @if (overflowCount() > 0) {\n <span class=\"avatar-group__overflow avatar-group__overflow--{{ size() }}\">\n +{{ overflowCount() }}\n </span>\n }\n</div>\n"],"mappings":";;;AAiDA,IAAa,uBAAb,MAAa,qBAAoB;CAE/B,UAAU,MAAM,SAA6B,GAAA,YAAA,CAAA,EAAA,WAAA,UAAA,CAAA,+BAAA,CAAA,CAAA;CAG7C,OAAO,MAAkB,MAAK,GAAA,YAAA,CAAA,EAAA,WAAA,OAAA,CAAA,+BAAA,CAAA,CAAA;CAG9B,MAAM,MAAc,GAAE,GAAA,YAAA,CAAA,EAAA,WAAA,MAAA,CAAA,+BAAA,CAAA,CAAA;CAOtB,OAAO,MAAe,OAAM,GAAA,YAAA,CAAA,EAAA,WAAA,OAAA,CAAA,+BAAA,CAAA,CAAA;CAM5B,UAAU,MAAc,IAAG,GAAA,YAAA,CAAA,EAAA,WAAA,UAAA,CAAA,+BAAA,CAAA,CAAA;CAEjB,iBAAiB,eAAc;EACvC,MAAM,MAAM,KAAK,QAAO;EACxB,MAAM,QAAQ,KAAK,IAAG;EACtB,OAAO,IAAI,MAAM,GAAG,KAAK;CAC3B,GAAE,GAAA,YAAA,CAAA,EAAA,WAAA,iBAAA,CAAA,+BAAA,CAAA,CAAA;CAEQ,gBAAgB,eAAc;EACtC,MAAM,MAAM,KAAK,QAAO;EACxB,MAAM,QAAQ,KAAK,IAAG;EACtB,OAAO,KAAK,IAAI,GAAG,IAAI,SAAS,KAAK;CACvC,GAAE,GAAA,YAAA,CAAA,EAAA,WAAA,gBAAA,CAAA,+BAAA,CAAA,CAAA;CAEQ,eAAe,eAAc;EACrC,MAAM,UAAU,CAAC,gBAAgB,iBAAiB,KAAK,KAAI,GAAI;EAC/D,IAAI,KAAK,KAAI,GAAI,QAAQ,KAAK,oBAAoB;EAClD,OAAO,QAAQ,KAAK,GAAG;CACzB,GAAE,GAAA,YAAA,CAAA,EAAA,WAAA,eAAA,CAAA,+BAAA,CAAA,CAAA;CAvCS,OAAA,OAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;EAAoB,MAAA,CAAA;EAAA,QAAA,GAAA,gBAAA;CAAA,CAAA;CAApB,OAAA,OAAA,GAAA,qBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,MAAA;EAAoB,cAAA;EAAA,UAAA;EAAA,QAAA;GAAA,SAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,MAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,KAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,MAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,SAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;EAAA;EAAA,UAAA;EAAA,UCjDjC;EAkBA,QAAA,CAAA,6xDAAA;EAAA,cAAA,CAAA;GAAA,MAAA;GAAA,MDIY;GAAe,UAAA;GAAA,QAAA;IAAA;IAAA;IAAA;IAAA;IAAA;IAAA;IAAA;IAAA;GAAA;EAAA,CAAA;EAAA,iBAAA,GAAA,wBAAA;CAAA,CAAA;;AA2Bd,GAAA,yBAAA;CAAA,YAAA;CAAA,SAAA;CAAA,UAAA;CAAA,MAAA;CAAoB,YAAA,CAAA;EA9BhC,MAAA;EACW,MAAA,CAAA;GAAA,UAAA;GAAiB,YACf;GAAI,SACP,CAAC,eAAe;GAAC,iBAGT,wBAAwB;GAAM,UAAA;GAAA,QAAA,CAAA,6xDAAA;EAAA,CAAA"}
|
|
1
|
+
{"version":3,"file":"lifecorner-angular-ui-kit-avatar-group.mjs","names":[],"sources":["../../../../libs/angular-ui-kit/src/lib/avatar-group/avatar-group.component.ts","../../../../libs/angular-ui-kit/src/lib/avatar-group/avatar-group.component.html"],"sourcesContent":["import {\n ChangeDetectionStrategy,\n Component,\n input,\n computed,\n} from '@angular/core';\nimport { AvatarColor, AvatarComponent, AvatarSize } from '@lifecorner/angular-ui-kit/avatar';\n\nexport interface AvatarGroupItem {\n /** Image source URL */\n src?: string;\n /** Alt text */\n alt?: string;\n /** Full name for initials fallback */\n name?: string;\n /** Background of the initials: `default` or a member colour `member-1` … `member-6` (see `lc-avatar`). */\n color?: AvatarColor;\n}\n\n@Component({\n selector: 'lc-avatar-group',\n standalone: true,\n imports: [AvatarComponent],\n templateUrl: './avatar-group.component.html',\n styleUrls: ['./avatar-group.component.scss'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\n/**\n * Avatar group component for displaying multiple user avatars.\n *\n * Features:\n * - Overlapping avatar display with configurable max visible count\n * - Overflow indicator showing remaining count\n * - Shared size variant across all avatars (xs, sm, md, lg)\n * - Automatic truncation based on max property\n * - Member colours per item (`color`), later avatars on top\n * - `ring`: each avatar gets a ring in the page colour instead of the surface\n * border; with `overlap=\"4px\"` this is the \"Weite\" member row\n *\n * @example\n * ```html\n * <lc-avatar-group [avatars]=\"users\" [max]=\"5\" size=\"md\" />\n * <lc-avatar-group\n * [avatars]=\"[{ name: 'Johanna Apfelbaum', color: 'member-1' }, { name: 'Tom Ek', color: 'member-2' }]\"\n * [ring]=\"true\"\n * overlap=\"4px\"\n * />\n * ```\n */\nexport class AvatarGroupComponent {\n /** List of avatars to show */\n avatars = input.required<AvatarGroupItem[]>();\n\n /** Avatar size */\n size = input<AvatarSize>('md');\n\n /** Maximum visible avatars before showing overflow count */\n max = input<number>(5);\n\n /**\n * Separate the avatars with a ring in the page colour\n * (`--lc-avatar-ring-color`, default `--color-background`) instead of the\n * 2 px surface border. Later avatars sit on top.\n */\n ring = input<boolean>(false);\n\n /**\n * How far each avatar overlaps the previous one, as a CSS length (e.g.\n * `4px`). Empty keeps the size's default (6–12 px).\n */\n overlap = input<string>('');\n\n protected visibleAvatars = computed(() => {\n const all = this.avatars();\n const limit = this.max();\n return all.slice(0, limit);\n });\n\n protected overflowCount = computed(() => {\n const all = this.avatars();\n const limit = this.max();\n return Math.max(0, all.length - limit);\n });\n\n protected groupClasses = computed(() => {\n const classes = ['avatar-group', `avatar-group--${this.size()}`];\n if (this.ring()) classes.push('avatar-group--ring');\n return classes.join(' ');\n });\n}\n","<div [class]=\"groupClasses()\" [style.--lc-avatar-group-overlap]=\"overlap() || null\">\n @for (avatar of visibleAvatars(); track avatar.name ?? $index) {\n <lc-avatar\n class=\"avatar-group__item\"\n [src]=\"avatar.src\"\n [alt]=\"avatar.alt\"\n [name]=\"avatar.name\"\n [size]=\"size()\"\n [color]=\"avatar.color ?? 'default'\"\n [ring]=\"ring()\"\n />\n }\n @if (overflowCount() > 0) {\n <span class=\"avatar-group__overflow avatar-group__overflow--{{ size() }}\">\n +{{ overflowCount() }}\n </span>\n }\n</div>\n"],"mappings":";;;AAiDA,IAAa,uBAAb,MAAa,qBAAoB;CAE/B,UAAU,MAAM,SAA6B,GAAA,YAAA,CAAA,EAAA,WAAA,UAAA,CAAA,+BAAA,CAAA,CAAA;CAG7C,OAAO,MAAkB,MAAK,GAAA,YAAA,CAAA,EAAA,WAAA,OAAA,CAAA,+BAAA,CAAA,CAAA;CAG9B,MAAM,MAAc,GAAE,GAAA,YAAA,CAAA,EAAA,WAAA,MAAA,CAAA,+BAAA,CAAA,CAAA;CAOtB,OAAO,MAAe,OAAM,GAAA,YAAA,CAAA,EAAA,WAAA,OAAA,CAAA,+BAAA,CAAA,CAAA;CAM5B,UAAU,MAAc,IAAG,GAAA,YAAA,CAAA,EAAA,WAAA,UAAA,CAAA,+BAAA,CAAA,CAAA;CAEjB,iBAAiB,eAAc;EACvC,MAAM,MAAM,KAAK,QAAO;EACxB,MAAM,QAAQ,KAAK,IAAG;EACtB,OAAO,IAAI,MAAM,GAAG,KAAK;CAC3B,GAAE,GAAA,YAAA,CAAA,EAAA,WAAA,iBAAA,CAAA,+BAAA,CAAA,CAAA;CAEQ,gBAAgB,eAAc;EACtC,MAAM,MAAM,KAAK,QAAO;EACxB,MAAM,QAAQ,KAAK,IAAG;EACtB,OAAO,KAAK,IAAI,GAAG,IAAI,SAAS,KAAK;CACvC,GAAE,GAAA,YAAA,CAAA,EAAA,WAAA,gBAAA,CAAA,+BAAA,CAAA,CAAA;CAEQ,eAAe,eAAc;EACrC,MAAM,UAAU,CAAC,gBAAgB,iBAAiB,KAAK,KAAI,GAAI;EAC/D,IAAI,KAAK,KAAI,GAAI,QAAQ,KAAK,oBAAoB;EAClD,OAAO,QAAQ,KAAK,GAAG;CACzB,GAAE,GAAA,YAAA,CAAA,EAAA,WAAA,eAAA,CAAA,+BAAA,CAAA,CAAA;CAvCS,OAAA,OAAA,GAAA,mBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,UAAA;EAAA,MAAA;EAAoB,MAAA,CAAA;EAAA,QAAA,GAAA,gBAAA;CAAA,CAAA;CAApB,OAAA,OAAA,GAAA,qBAAA;EAAA,YAAA;EAAA,SAAA;EAAA,MAAA;EAAoB,cAAA;EAAA,UAAA;EAAA,QAAA;GAAA,SAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,MAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,KAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,MAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;GAAA,SAAA;IAAA,mBAAA;IAAA,YAAA;IAAA,UAAA;IAAA,YAAA;IAAA,mBAAA;GAAA;EAAA;EAAA,UAAA;EAAA,UCjDjC;EAkBA,QAAA,CAAA,6xDAAA;EAAA,cAAA,CAAA;GAAA,MAAA;GAAA,MDIY;GAAe,UAAA;GAAA,QAAA;IAAA;IAAA;IAAA;IAAA;IAAA;IAAA;IAAA;IAAA;IAAA;GAAA;EAAA,CAAA;EAAA,iBAAA,GAAA,wBAAA;CAAA,CAAA;;AA2Bd,GAAA,yBAAA;CAAA,YAAA;CAAA,SAAA;CAAA,UAAA;CAAA,MAAA;CAAoB,YAAA,CAAA;EA9BhC,MAAA;EACW,MAAA,CAAA;GAAA,UAAA;GAAiB,YACf;GAAI,SACP,CAAC,eAAe;GAAC,iBAGT,wBAAwB;GAAM,UAAA;GAAA,QAAA,CAAA,6xDAAA;EAAA,CAAA"}
|
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
import * as i0 from "@angular/core";
|
|
2
2
|
import { ChangeDetectionStrategy, Component, computed, input, linkedSignal } from "@angular/core";
|
|
3
|
+
const AVATAR_PX = {
|
|
4
|
+
xs: 24,
|
|
5
|
+
sm: 32,
|
|
6
|
+
md: 40,
|
|
7
|
+
lg: 48,
|
|
8
|
+
xl: 64
|
|
9
|
+
};
|
|
3
10
|
const AVATAR_MEMBER_COLORS = [
|
|
4
11
|
"member-1",
|
|
5
12
|
"member-2",
|
|
@@ -13,6 +20,7 @@ var AvatarComponent = class AvatarComponent {
|
|
|
13
20
|
alt = input(...ngDevMode ? [void 0, { debugName: "alt" }] : /* istanbul ignore next */ []);
|
|
14
21
|
name = input(...ngDevMode ? [void 0, { debugName: "name" }] : /* istanbul ignore next */ []);
|
|
15
22
|
size = input("md", ...ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []);
|
|
23
|
+
loading = input("eager", ...ngDevMode ? [{ debugName: "loading" }] : /* istanbul ignore next */ []);
|
|
16
24
|
status = input(...ngDevMode ? [void 0, { debugName: "status" }] : /* istanbul ignore next */ []);
|
|
17
25
|
color = input("default", ...ngDevMode ? [{ debugName: "color" }] : /* istanbul ignore next */ []);
|
|
18
26
|
ring = input(false, ...ngDevMode ? [{ debugName: "ring" }] : /* istanbul ignore next */ []);
|
|
@@ -39,6 +47,7 @@ var AvatarComponent = class AvatarComponent {
|
|
|
39
47
|
ariaLabel = computed(() => {
|
|
40
48
|
return this.alt() || this.name() || "Avatar";
|
|
41
49
|
}, ...ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []);
|
|
50
|
+
imagePx = computed(() => AVATAR_PX[this.size()], ...ngDevMode ? [{ debugName: "imagePx" }] : /* istanbul ignore next */ []);
|
|
42
51
|
showImage = computed(() => {
|
|
43
52
|
return this.src() && !this.imageError();
|
|
44
53
|
}, ...ngDevMode ? [{ debugName: "showImage" }] : /* istanbul ignore next */ []);
|
|
@@ -93,6 +102,13 @@ var AvatarComponent = class AvatarComponent {
|
|
|
93
102
|
isRequired: false,
|
|
94
103
|
transformFunction: null
|
|
95
104
|
},
|
|
105
|
+
loading: {
|
|
106
|
+
classPropertyName: "loading",
|
|
107
|
+
publicName: "loading",
|
|
108
|
+
isSignal: true,
|
|
109
|
+
isRequired: false,
|
|
110
|
+
transformFunction: null
|
|
111
|
+
},
|
|
96
112
|
status: {
|
|
97
113
|
classPropertyName: "status",
|
|
98
114
|
publicName: "status",
|
|
@@ -123,7 +139,7 @@ var AvatarComponent = class AvatarComponent {
|
|
|
123
139
|
}
|
|
124
140
|
},
|
|
125
141
|
ngImport: i0,
|
|
126
|
-
template: "<div \n [class]=\"avatarClasses()\"\n [attr.role]=\"decorative() ? null : 'img'\"\n [attr.aria-label]=\"decorative() ? null : ariaLabel()\"\n [attr.aria-hidden]=\"decorative() ? 'true' : null\"\n>\n @if (showImage()) {\n
|
|
142
|
+
template: "<div \n [class]=\"avatarClasses()\"\n [attr.role]=\"decorative() ? null : 'img'\"\n [attr.aria-label]=\"decorative() ? null : ariaLabel()\"\n [attr.aria-hidden]=\"decorative() ? 'true' : null\"\n>\n @if (showImage()) {\n <!-- `loading` before `src`: attribute bindings run in template order, after\n every property binding, so `[attr.src]` keeps the source behind\n `loading` (G-40; an engine may start the request when src is set). -->\n <img\n [alt]=\"alt() || name() || 'Avatar'\"\n class=\"lc-avatar__image\"\n [attr.width]=\"imagePx()\"\n [attr.height]=\"imagePx()\"\n [attr.loading]=\"loading() === 'lazy' ? 'lazy' : null\"\n [attr.src]=\"src()!\"\n (error)=\"onImageError()\"\n />\n } @else {\n <span class=\"lc-avatar__initials\">{{ initials() }}</span>\n }\n\n @if (status()) {\n <span \n class=\"lc-avatar__status lc-avatar__status--{{ status() }}\"\n [attr.aria-label]=\"status() + ' status'\"\n ></span>\n }\n</div>\n",
|
|
127
143
|
styles: [".lc-avatar{position:relative;display:inline-flex;align-items:center;justify-content:center;border-radius:50%;background-color:var(--color-surface-hover);color:var(--color-text-secondary);font-weight:var(--typography-font-weight-medium, 500);line-height:1;overflow:hidden;flex-shrink:0;-webkit-user-select:none;user-select:none}.lc-avatar__image{width:100%;height:100%;object-fit:cover;border-radius:50%}.lc-avatar__initials{display:flex;align-items:center;justify-content:center;width:100%;height:100%;font-size:inherit;text-transform:uppercase}.lc-avatar__status{position:absolute;bottom:0;right:0;width:25%;height:25%;border-radius:50%;border:2px solid var(--color-surface)}.lc-avatar__status--online{background-color:var(--color-success)}.lc-avatar__status--offline{background-color:var(--color-text-tertiary)}.lc-avatar__status--away{background-color:var(--color-warning-500)}.lc-avatar__status--busy{background-color:var(--color-error-500)}.lc-avatar--xs{width:1.5rem;height:1.5rem;font-size:var(--typography-font-size-xs, .75rem)}.lc-avatar--xs .lc-avatar__status{width:.375rem;height:.375rem;border-width:1px}.lc-avatar--sm{width:2rem;height:2rem;font-size:var(--typography-font-size-sm, .875rem)}.lc-avatar--sm .lc-avatar__status{width:.5rem;height:.5rem;border-width:1.5px}.lc-avatar--md{width:2.5rem;height:2.5rem;font-size:var(--typography-font-size-base, 1rem)}.lc-avatar--md .lc-avatar__status{width:.625rem;height:.625rem;border-width:2px}.lc-avatar--lg{width:3rem;height:3rem;font-size:var(--typography-font-size-lg, 1.125rem)}.lc-avatar--lg .lc-avatar__status{width:.75rem;height:.75rem;border-width:2px}.lc-avatar--xl{width:4rem;height:4rem;font-size:var(--typography-font-size-xl, 1.25rem)}.lc-avatar--xl .lc-avatar__status{width:1rem;height:1rem;border-width:2px}.lc-avatar--member{color:var(--color-on-member, #ffffff);font-weight:var(--typography-font-weight-bold, 700);letter-spacing:.02em}.lc-avatar--member.lc-avatar--xs{font-size:.625rem}.lc-avatar--member.lc-avatar--sm{font-size:.75rem}.lc-avatar--member.lc-avatar--md{font-size:.875rem}.lc-avatar--member.lc-avatar--lg{font-size:1rem}.lc-avatar--member.lc-avatar--xl{font-size:1.25rem}.lc-avatar--member-1{background-color:var(--color-member-1, #1a6a79)}.lc-avatar--member-2{background-color:var(--color-member-2, #b04a22)}.lc-avatar--member-3{background-color:var(--color-member-3, #4e3f84)}.lc-avatar--member-4{background-color:var(--color-member-4, #5f7150)}.lc-avatar--member-5{background-color:var(--color-member-5, #9e3846)}.lc-avatar--member-6{background-color:var(--color-member-6, #5a798c)}.lc-avatar--ring{box-shadow:0 0 0 var(--lc-avatar-ring-width, 3px) var(--lc-avatar-ring-color, var(--color-background))}.lc-avatar--ring.lc-avatar--xs,.lc-avatar--ring.lc-avatar--sm{box-shadow:0 0 0 var(--lc-avatar-ring-width, 2px) var(--lc-avatar-ring-color, var(--color-background))}\n"],
|
|
128
144
|
changeDetection: i0.ChangeDetectionStrategy.OnPush
|
|
129
145
|
});
|
|
@@ -140,7 +156,7 @@ i0.ɵɵngDeclareClassMetadata({
|
|
|
140
156
|
standalone: true,
|
|
141
157
|
imports: [],
|
|
142
158
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
143
|
-
template: "<div \n [class]=\"avatarClasses()\"\n [attr.role]=\"decorative() ? null : 'img'\"\n [attr.aria-label]=\"decorative() ? null : ariaLabel()\"\n [attr.aria-hidden]=\"decorative() ? 'true' : null\"\n>\n @if (showImage()) {\n
|
|
159
|
+
template: "<div \n [class]=\"avatarClasses()\"\n [attr.role]=\"decorative() ? null : 'img'\"\n [attr.aria-label]=\"decorative() ? null : ariaLabel()\"\n [attr.aria-hidden]=\"decorative() ? 'true' : null\"\n>\n @if (showImage()) {\n <!-- `loading` before `src`: attribute bindings run in template order, after\n every property binding, so `[attr.src]` keeps the source behind\n `loading` (G-40; an engine may start the request when src is set). -->\n <img\n [alt]=\"alt() || name() || 'Avatar'\"\n class=\"lc-avatar__image\"\n [attr.width]=\"imagePx()\"\n [attr.height]=\"imagePx()\"\n [attr.loading]=\"loading() === 'lazy' ? 'lazy' : null\"\n [attr.src]=\"src()!\"\n (error)=\"onImageError()\"\n />\n } @else {\n <span class=\"lc-avatar__initials\">{{ initials() }}</span>\n }\n\n @if (status()) {\n <span \n class=\"lc-avatar__status lc-avatar__status--{{ status() }}\"\n [attr.aria-label]=\"status() + ' status'\"\n ></span>\n }\n</div>\n",
|
|
144
160
|
styles: [".lc-avatar{position:relative;display:inline-flex;align-items:center;justify-content:center;border-radius:50%;background-color:var(--color-surface-hover);color:var(--color-text-secondary);font-weight:var(--typography-font-weight-medium, 500);line-height:1;overflow:hidden;flex-shrink:0;-webkit-user-select:none;user-select:none}.lc-avatar__image{width:100%;height:100%;object-fit:cover;border-radius:50%}.lc-avatar__initials{display:flex;align-items:center;justify-content:center;width:100%;height:100%;font-size:inherit;text-transform:uppercase}.lc-avatar__status{position:absolute;bottom:0;right:0;width:25%;height:25%;border-radius:50%;border:2px solid var(--color-surface)}.lc-avatar__status--online{background-color:var(--color-success)}.lc-avatar__status--offline{background-color:var(--color-text-tertiary)}.lc-avatar__status--away{background-color:var(--color-warning-500)}.lc-avatar__status--busy{background-color:var(--color-error-500)}.lc-avatar--xs{width:1.5rem;height:1.5rem;font-size:var(--typography-font-size-xs, .75rem)}.lc-avatar--xs .lc-avatar__status{width:.375rem;height:.375rem;border-width:1px}.lc-avatar--sm{width:2rem;height:2rem;font-size:var(--typography-font-size-sm, .875rem)}.lc-avatar--sm .lc-avatar__status{width:.5rem;height:.5rem;border-width:1.5px}.lc-avatar--md{width:2.5rem;height:2.5rem;font-size:var(--typography-font-size-base, 1rem)}.lc-avatar--md .lc-avatar__status{width:.625rem;height:.625rem;border-width:2px}.lc-avatar--lg{width:3rem;height:3rem;font-size:var(--typography-font-size-lg, 1.125rem)}.lc-avatar--lg .lc-avatar__status{width:.75rem;height:.75rem;border-width:2px}.lc-avatar--xl{width:4rem;height:4rem;font-size:var(--typography-font-size-xl, 1.25rem)}.lc-avatar--xl .lc-avatar__status{width:1rem;height:1rem;border-width:2px}.lc-avatar--member{color:var(--color-on-member, #ffffff);font-weight:var(--typography-font-weight-bold, 700);letter-spacing:.02em}.lc-avatar--member.lc-avatar--xs{font-size:.625rem}.lc-avatar--member.lc-avatar--sm{font-size:.75rem}.lc-avatar--member.lc-avatar--md{font-size:.875rem}.lc-avatar--member.lc-avatar--lg{font-size:1rem}.lc-avatar--member.lc-avatar--xl{font-size:1.25rem}.lc-avatar--member-1{background-color:var(--color-member-1, #1a6a79)}.lc-avatar--member-2{background-color:var(--color-member-2, #b04a22)}.lc-avatar--member-3{background-color:var(--color-member-3, #4e3f84)}.lc-avatar--member-4{background-color:var(--color-member-4, #5f7150)}.lc-avatar--member-5{background-color:var(--color-member-5, #9e3846)}.lc-avatar--member-6{background-color:var(--color-member-6, #5a798c)}.lc-avatar--ring{box-shadow:0 0 0 var(--lc-avatar-ring-width, 3px) var(--lc-avatar-ring-color, var(--color-background))}.lc-avatar--ring.lc-avatar--xs,.lc-avatar--ring.lc-avatar--sm{box-shadow:0 0 0 var(--lc-avatar-ring-width, 2px) var(--lc-avatar-ring-color, var(--color-background))}\n"]
|
|
145
161
|
}]
|
|
146
162
|
}],
|
|
@@ -177,6 +193,14 @@ i0.ɵɵngDeclareClassMetadata({
|
|
|
177
193
|
required: false
|
|
178
194
|
}]
|
|
179
195
|
}],
|
|
196
|
+
loading: [{
|
|
197
|
+
type: i0.Input,
|
|
198
|
+
args: [{
|
|
199
|
+
isSignal: true,
|
|
200
|
+
alias: "loading",
|
|
201
|
+
required: false
|
|
202
|
+
}]
|
|
203
|
+
}],
|
|
180
204
|
status: [{
|
|
181
205
|
type: i0.Input,
|
|
182
206
|
args: [{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lifecorner-angular-ui-kit-avatar.mjs","names":[],"sources":["../../../../libs/angular-ui-kit/src/lib/avatar/avatar.component.ts","../../../../libs/angular-ui-kit/src/lib/avatar/avatar.component.html"],"sourcesContent":["import { Component, ChangeDetectionStrategy, input, computed, linkedSignal } from '@angular/core';\n\nexport type AvatarSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl';\nexport type AvatarStatus = 'online' | 'offline' | 'away' | 'busy';\n\n/**\n * Background of the initials. `default` is the neutral kit avatar; `member-1`\n * … `member-6` are the member colours (`--color-member-1` … `-6`: teal, rust,\n * violet, sage, berry, slate) with white initials, each at least 4.5:1.\n * Assign them per person in a stable order (e.g. join order) and always show\n * the name or initials beside the colour — colour is never the only cue.\n */\nexport type AvatarColor =\n | 'default'\n | 'member-1'\n | 'member-2'\n | 'member-3'\n | 'member-4'\n | 'member-5'\n | 'member-6';\n\n/** The six member colours in their order (`AvatarColor` without `default`). */\nexport const AVATAR_MEMBER_COLORS: readonly AvatarColor[] = [\n 'member-1',\n 'member-2',\n 'member-3',\n 'member-4',\n 'member-5',\n 'member-6',\n];\n\n/**\n * Avatar component for circular user representation.\n *\n * Features:\n * - Image display with fallback to initials\n * - Auto-generated initials from user name\n * - Status indicator (online, offline, busy, away)\n * - Multiple size variants (xs, sm, md, lg, xl)\n * - Member colours (`color`: `member-1` … `member-6`) with white initials\n * - `ring`: a gap in the page colour around the avatar, for stacks and for\n * avatars on images or tints\n * - Accessible with alt text support\n *\n * @example\n * ```html\n * <lc-avatar src=\"https://example.com/avatar.jpg\" alt=\"John Doe\" />\n * <lc-avatar name=\"John Doe\" status=\"online\" size=\"lg\" />\n * <lc-avatar name=\"Tom Ek\" color=\"member-2\" [ring]=\"true\" />\n * ```\n */\n@Component({\n selector: 'lc-avatar',\n standalone: true,\n imports: [],\n templateUrl: './avatar.component.html',\n styleUrl: './avatar.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class AvatarComponent {\n /** Image source URL */\n src = input<string>();\n\n /** Alt text for the image */\n alt = input<string>();\n\n /** Full name for generating initials */\n name = input<string>();\n\n /** Size of the avatar */\n size = input<AvatarSize>('md');\n\n /** Status indicator */\n status = input<AvatarStatus>();\n\n /**\n * Background of the initials: `default` (neutral) or a member colour\n * `member-1` … `member-6` with white initials (LK-7).\n */\n color = input<AvatarColor>('default');\n\n /**\n * Draw a ring in the page colour around the avatar (3 px; 2 px for `xs` and\n * `sm`), so stacked or overlapping avatars stay apart. The ring colour is\n * `--lc-avatar-ring-color` (default `--color-background`); set it to the\n * surface the avatar sits on.\n */\n ring = input<boolean>(false);\n\n /**\n * Hide the avatar from assistive technology (no `img` role, no label), for\n * avatars inside a control that has its own accessible name — e.g. a menu\n * button labelled \"Menu for Tom Ek\".\n */\n decorative = input<boolean>(false);\n\n /**\n * Computed initials from name\n */\n initials = computed(() => {\n const fullName = this.name();\n if (!fullName || fullName.trim() === '') {\n return '?';\n }\n\n const parts = fullName\n .trim()\n .split(/\\s+/)\n .filter((p) => p.length > 0);\n\n if (parts.length === 0) {\n return '?';\n }\n\n if (parts.length === 1) {\n return parts[0]?.[0]?.toUpperCase() ?? '?';\n }\n\n // First and last name initials\n const firstInitial = parts[0]?.[0];\n const lastInitial = parts[parts.length - 1]?.[0];\n\n if (firstInitial && lastInitial) {\n return (firstInitial + lastInitial).toUpperCase();\n }\n return '?';\n });\n\n /**\n * Computed CSS classes for the avatar\n */\n avatarClasses = computed(() => {\n const classes = ['lc-avatar'];\n\n classes.push(`lc-avatar--${this.size()}`);\n\n if (this.status()) {\n classes.push('lc-avatar--with-status');\n }\n\n if (this.color() !== 'default') {\n classes.push('lc-avatar--member', `lc-avatar--${this.color()}`);\n }\n\n if (this.ring()) {\n classes.push('lc-avatar--ring');\n }\n\n return classes.join(' ');\n });\n\n /**\n * Get aria-label for accessibility\n */\n ariaLabel = computed(() => {\n return this.alt() || this.name() || 'Avatar';\n });\n\n /**\n * Check if image should be displayed\n */\n showImage = computed(() => {\n return this.src() && !this.imageError();\n });\n\n /**\n * Track if image failed to load. Resets whenever `src` changes so a new\n * image gets a fresh attempt instead of staying stuck on the initials.\n */\n protected imageError = linkedSignal<string | undefined, boolean>({\n source: this.src,\n computation: () => false,\n });\n\n /**\n * Handle image load error\n */\n onImageError(): void {\n this.imageError.set(true);\n }\n}\n","<div \n [class]=\"avatarClasses()\"\n [attr.role]=\"decorative() ? null : 'img'\"\n [attr.aria-label]=\"decorative() ? null : ariaLabel()\"\n [attr.aria-hidden]=\"decorative() ? 'true' : null\"\n>\n @if (showImage()) {\n <img \n [src]=\"src()!\" \n [alt]=\"alt() || name() || 'Avatar'\" \n class=\"lc-avatar__image\"\n (error)=\"onImageError()\"\n />\n } @else {\n <span class=\"lc-avatar__initials\">{{ initials() }}</span>\n }\n\n @if (status()) {\n <span \n class=\"lc-avatar__status lc-avatar__status--{{ status() }}\"\n [attr.aria-label]=\"status() + ' status'\"\n ></span>\n }\n</div>\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"lifecorner-angular-ui-kit-avatar.mjs","names":[],"sources":["../../../../libs/angular-ui-kit/src/lib/avatar/avatar.component.ts","../../../../libs/angular-ui-kit/src/lib/avatar/avatar.component.html"],"sourcesContent":["import { Component, ChangeDetectionStrategy, input, computed, linkedSignal } from '@angular/core';\n\nexport type AvatarSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl';\nexport type AvatarStatus = 'online' | 'offline' | 'away' | 'busy';\n\n/**\n * How the browser loads the image (3.11.2, G-40). The same union as\n * `CharacterLoading`, kept separate because entries don't import each other.\n * - `eager`: no attribute, the browser default.\n * - `lazy`: `loading=\"lazy\"`, for an avatar below the fold.\n */\nexport type AvatarLoading = 'eager' | 'lazy';\n\n/** The box of each size in px at 100 % text, written as the `<img>` `width`/`height` (G-40). */\nconst AVATAR_PX: Readonly<Record<AvatarSize, number>> = { xs: 24, sm: 32, md: 40, lg: 48, xl: 64 };\n\n/**\n * Background of the initials. `default` is the neutral kit avatar; `member-1`\n * … `member-6` are the member colours (`--color-member-1` … `-6`: teal, rust,\n * violet, sage, berry, slate) with white initials, each at least 4.5:1.\n * Assign them per person in a stable order (e.g. join order) and always show\n * the name or initials beside the colour — colour is never the only cue.\n */\nexport type AvatarColor =\n | 'default'\n | 'member-1'\n | 'member-2'\n | 'member-3'\n | 'member-4'\n | 'member-5'\n | 'member-6';\n\n/** The six member colours in their order (`AvatarColor` without `default`). */\nexport const AVATAR_MEMBER_COLORS: readonly AvatarColor[] = [\n 'member-1',\n 'member-2',\n 'member-3',\n 'member-4',\n 'member-5',\n 'member-6',\n];\n\n/**\n * Avatar component for circular user representation.\n *\n * Features:\n * - Image display with fallback to initials\n * - Auto-generated initials from user name\n * - Status indicator (online, offline, busy, away)\n * - Multiple size variants (xs, sm, md, lg, xl)\n * - Member colours (`color`: `member-1` … `member-6`) with white initials\n * - `ring`: a gap in the page colour around the avatar, for stacks and for\n * avatars on images or tints\n * - Accessible with alt text support\n *\n * @example\n * ```html\n * <lc-avatar src=\"https://example.com/avatar.jpg\" alt=\"John Doe\" />\n * <lc-avatar name=\"John Doe\" status=\"online\" size=\"lg\" />\n * <lc-avatar name=\"Tom Ek\" color=\"member-2\" [ring]=\"true\" />\n * ```\n */\n@Component({\n selector: 'lc-avatar',\n standalone: true,\n imports: [],\n templateUrl: './avatar.component.html',\n styleUrl: './avatar.component.scss',\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class AvatarComponent {\n /** Image source URL */\n src = input<string>();\n\n /** Alt text for the image */\n alt = input<string>();\n\n /** Full name for generating initials */\n name = input<string>();\n\n /**\n * Size of the avatar: xs 24, sm 32, md 40, lg 48, xl 64 px (1.5 … 4 rem).\n * The `<img>` carries the size's px as `width`/`height`; CSS sizes the box,\n * so at 200 % text the box grows and the attributes only give the 1:1 ratio.\n * @default 'md'\n */\n size = input<AvatarSize>('md');\n\n /**\n * How the browser loads the image. `lazy`: for an avatar below the fold;\n * writes `loading=\"lazy\"`. `eager` writes no attribute. The initials still\n * replace an image that fails.\n * @default 'eager'\n */\n loading = input<AvatarLoading>('eager');\n\n /** Status indicator */\n status = input<AvatarStatus>();\n\n /**\n * Background of the initials: `default` (neutral) or a member colour\n * `member-1` … `member-6` with white initials (LK-7).\n */\n color = input<AvatarColor>('default');\n\n /**\n * Draw a ring in the page colour around the avatar (3 px; 2 px for `xs` and\n * `sm`), so stacked or overlapping avatars stay apart. The ring colour is\n * `--lc-avatar-ring-color` (default `--color-background`); set it to the\n * surface the avatar sits on.\n */\n ring = input<boolean>(false);\n\n /**\n * Hide the avatar from assistive technology (no `img` role, no label), for\n * avatars inside a control that has its own accessible name — e.g. a menu\n * button labelled \"Menu for Tom Ek\".\n */\n decorative = input<boolean>(false);\n\n /**\n * Computed initials from name\n */\n initials = computed(() => {\n const fullName = this.name();\n if (!fullName || fullName.trim() === '') {\n return '?';\n }\n\n const parts = fullName\n .trim()\n .split(/\\s+/)\n .filter((p) => p.length > 0);\n\n if (parts.length === 0) {\n return '?';\n }\n\n if (parts.length === 1) {\n return parts[0]?.[0]?.toUpperCase() ?? '?';\n }\n\n // First and last name initials\n const firstInitial = parts[0]?.[0];\n const lastInitial = parts[parts.length - 1]?.[0];\n\n if (firstInitial && lastInitial) {\n return (firstInitial + lastInitial).toUpperCase();\n }\n return '?';\n });\n\n /**\n * Computed CSS classes for the avatar\n */\n avatarClasses = computed(() => {\n const classes = ['lc-avatar'];\n\n classes.push(`lc-avatar--${this.size()}`);\n\n if (this.status()) {\n classes.push('lc-avatar--with-status');\n }\n\n if (this.color() !== 'default') {\n classes.push('lc-avatar--member', `lc-avatar--${this.color()}`);\n }\n\n if (this.ring()) {\n classes.push('lc-avatar--ring');\n }\n\n return classes.join(' ');\n });\n\n /**\n * Get aria-label for accessibility\n */\n ariaLabel = computed(() => {\n return this.alt() || this.name() || 'Avatar';\n });\n\n /** The size's px, written as the `<img>` `width` and `height` (G-40). */\n protected readonly imagePx = computed(() => AVATAR_PX[this.size()]);\n\n /**\n * Check if image should be displayed\n */\n showImage = computed(() => {\n return this.src() && !this.imageError();\n });\n\n /**\n * Track if image failed to load. Resets whenever `src` changes so a new\n * image gets a fresh attempt instead of staying stuck on the initials.\n */\n protected imageError = linkedSignal<string | undefined, boolean>({\n source: this.src,\n computation: () => false,\n });\n\n /**\n * Handle image load error\n */\n onImageError(): void {\n this.imageError.set(true);\n }\n}\n","<div \n [class]=\"avatarClasses()\"\n [attr.role]=\"decorative() ? null : 'img'\"\n [attr.aria-label]=\"decorative() ? null : ariaLabel()\"\n [attr.aria-hidden]=\"decorative() ? 'true' : null\"\n>\n @if (showImage()) {\n <!-- `loading` before `src`: attribute bindings run in template order, after\n every property binding, so `[attr.src]` keeps the source behind\n `loading` (G-40; an engine may start the request when src is set). -->\n <img\n [alt]=\"alt() || name() || 'Avatar'\"\n class=\"lc-avatar__image\"\n [attr.width]=\"imagePx()\"\n [attr.height]=\"imagePx()\"\n [attr.loading]=\"loading() === 'lazy' ? 'lazy' : null\"\n [attr.src]=\"src()!\"\n (error)=\"onImageError()\"\n />\n } @else {\n <span class=\"lc-avatar__initials\">{{ initials() }}</span>\n }\n\n @if (status()) {\n <span \n class=\"lc-avatar__status lc-avatar__status--{{ status() }}\"\n [attr.aria-label]=\"status() + ' status'\"\n ></span>\n }\n</div>\n"],"mappings":"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"}
|
|
@@ -151,7 +151,7 @@ var ButtonComponent = class ButtonComponent {
|
|
|
151
151
|
}],
|
|
152
152
|
ngImport: i0,
|
|
153
153
|
template: "<button\n #buttonElement\n [type]=\"type()\"\n [disabled]=\"isDisabled()\"\n [attr.title]=\"effectiveTitle()\"\n [attr.aria-label]=\"ariaLabel() || null\"\n [attr.aria-disabled]=\"isDisabled() ? 'true' : 'false'\"\n [attr.aria-busy]=\"loading() ? 'true' : 'false'\"\n [ngClass]=\"{\n 'btn': true,\n 'btn-primary': variant() === 'primary',\n 'btn-secondary': variant() === 'secondary',\n 'btn-outline': variant() === 'outline',\n 'btn-ghost': variant() === 'ghost',\n 'btn-link': variant() === 'link',\n 'btn-danger': variant() === 'danger',\n 'btn-warning': variant() === 'warning',\n 'btn-info': variant() === 'info',\n 'btn-xs': size() === 'xs',\n 'btn-sm': size() === 'sm',\n 'btn-md': size() === 'md',\n 'btn-lg': size() === 'lg',\n 'btn-icon-only': iconOnly(),\n 'btn-full-width': fullWidth(),\n 'btn-inline': inline(),\n 'btn-flush': flush()\n }\"\n (click)=\"handleClick()\"\n (focus)=\"handleFocus()\"\n (blur)=\"handleBlur()\"\n>\n @if (loading()) {\n <span class=\"loading-spinner\"></span>\n }\n @if (!loading()) {\n <ng-content select=\"[slot='icon-before']\" />\n }\n <ng-content></ng-content>\n @if (!loading()) {\n <ng-content select=\"[slot='icon-after']\" />\n }\n</button>\n",
|
|
154
|
-
styles: [".btn{display:inline-flex;align-items:center;justify-content:center;gap:var(--spacing-2);font-family:var(--font-family-sans);font-weight:var(--font-weight-semibold);line-height:var(--line-height-tight);border:1px solid transparent;border-radius:var(--border-radius-full);cursor:pointer;transition:
|
|
154
|
+
styles: [".btn{display:inline-flex;align-items:center;justify-content:center;gap:var(--spacing-2);font-family:var(--font-family-sans);font-weight:var(--font-weight-semibold);line-height:var(--line-height-tight);border:1px solid transparent;border-radius:var(--border-radius-full);cursor:pointer;transition-property:color,background-color,border-color,box-shadow;transition-duration:var(--animation-duration-base);transition-timing-function:var(--animation-timing-ease);white-space:normal;text-align:center;overflow-wrap:var(--lc-btn-overflow-wrap, break-word);-webkit-user-select:none;user-select:none}.btn:focus-visible{outline:2px solid var(--color-primary-500);outline-offset:2px}.btn:disabled{opacity:.5;cursor:not-allowed;pointer-events:auto}a.btn{text-decoration:none}.btn-primary{background-color:var(--color-primary-fill);color:var(--color-on-primary)}.btn-primary:hover:not(:disabled){background-color:var(--color-primary-fill-hover)}.btn-primary:active:not(:disabled){background-color:var(--color-primary-fill-active)}.btn-secondary{background-color:var(--color-secondary-fill);color:var(--color-on-secondary)}.btn-secondary:hover:not(:disabled){background-color:var(--color-secondary-fill-hover)}.btn-secondary:active:not(:disabled){background-color:var(--color-secondary-fill-active)}.btn-outline{background-color:#84c7d40f;border-color:var(--color-border-strong);color:var(--color-text-primary)}.btn-outline:hover:not(:disabled){background-color:var(--color-primary-600);border-color:var(--color-primary-500);color:var(--color-neutral-white)}.btn-outline:active:not(:disabled){filter:brightness(.92)}.btn-ghost{background-color:var(--lc-button-ghost-bg, transparent);color:var(--lc-button-ghost-fg, var(--color-text-secondary))}.btn-ghost:hover:not(:disabled){background-color:var(--lc-button-ghost-hover-bg, var(--color-surface-hover));color:var(--lc-button-ghost-hover-fg, var(--lc-button-ghost-fg, var(--color-text-primary)))}.btn-ghost:active:not(:disabled){background-color:var(--lc-button-ghost-active-bg, var(--color-surface-selected))}.btn-link{background-color:transparent;color:var(--lc-button-link-fg, var(--color-primary-600));padding:0;border:none}.btn-link:hover:not(:disabled){color:var(--lc-button-link-hover-fg, var(--color-primary-700));text-decoration:underline}.btn-link:active:not(:disabled){color:var(--lc-button-link-active-fg, var(--color-primary-800))}.btn-danger{background-color:var(--color-error-fill);color:var(--color-on-error)}.btn-danger:hover:not(:disabled){background-color:var(--color-error-fill-hover)}.btn-danger:active:not(:disabled){background-color:var(--color-error-fill-active)}.btn-warning{background-color:#e1a040;color:var(--color-on-warning)}.btn-warning:hover:not(:disabled){filter:brightness(1.05)}.btn-warning:active:not(:disabled){filter:brightness(.94)}.btn-info{background-color:#3b6588;color:var(--color-neutral-white)}.btn-info:hover:not(:disabled){background-color:#27445c}.btn-info:active:not(:disabled){background-color:#27445c;filter:brightness(.85)}.btn-xs{padding:var(--spacing-1) var(--spacing-2);font-size:var(--font-size-xs)}.btn-sm{padding:var(--spacing-2) var(--spacing-3);font-size:var(--font-size-sm)}.btn-md{padding:var(--spacing-2-5) var(--spacing-4);font-size:var(--font-size-base)}.btn-lg{padding:var(--spacing-3) var(--spacing-6);font-size:var(--font-size-lg)}.btn-icon-only.btn-xs{padding:var(--spacing-1);width:calc(var(--spacing-1) * 2 + 1em);height:calc(var(--spacing-1) * 2 + 1em)}.btn-icon-only.btn-sm{padding:var(--spacing-2);width:calc(var(--spacing-2) * 2 + 1em);height:calc(var(--spacing-2) * 2 + 1em)}.btn-icon-only.btn-md{padding:var(--spacing-2-5);width:calc(var(--spacing-2-5) * 2 + 1em);height:calc(var(--spacing-2-5) * 2 + 1em)}.btn-icon-only.btn-lg{padding:var(--spacing-3);width:calc(var(--spacing-3) * 2 + 1.2em);height:calc(var(--spacing-3) * 2 + 1.2em)}.btn-full-width{width:100%}.btn-inline{display:inline;padding:0;font-size:inherit;font-weight:inherit;line-height:inherit;vertical-align:baseline;white-space:normal;text-align:inherit;border-radius:var(--border-radius-sm)}.btn.btn-inline{text-decoration:var(--lc-btn-inline-text-decoration, underline);text-decoration-thickness:max(1px,.0625em);text-underline-offset:.15em;transition-property:color,background-color,border-color,box-shadow}.btn.btn-inline:hover:not(:disabled){text-decoration-thickness:max(2px,.125em)}.btn-link.btn-flush:not(.btn-icon-only,.btn-inline){padding-inline:0;min-width:var(--size-min-touch-width, 2.75rem);min-height:var(--size-min-touch-height, 2.75rem);justify-content:var(--lc-btn-flush-align, start);text-align:var(--lc-btn-flush-align, start);border-radius:var(--border-radius-sm)}.loading-spinner{display:inline-block;width:1em;height:1em;border:2px solid currentColor;border-right-color:transparent;border-radius:50%;animation:spin 1s linear infinite}@keyframes spin{to{transform:rotate(360deg)}}.icon-before,.icon-after{display:inline-flex;align-items:center}\n"],
|
|
155
155
|
dependencies: [{
|
|
156
156
|
kind: "directive",
|
|
157
157
|
type: NgClass,
|
|
@@ -176,7 +176,7 @@ i0.ɵɵngDeclareClassMetadata({
|
|
|
176
176
|
encapsulation: ViewEncapsulation.None,
|
|
177
177
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
178
178
|
template: "<button\n #buttonElement\n [type]=\"type()\"\n [disabled]=\"isDisabled()\"\n [attr.title]=\"effectiveTitle()\"\n [attr.aria-label]=\"ariaLabel() || null\"\n [attr.aria-disabled]=\"isDisabled() ? 'true' : 'false'\"\n [attr.aria-busy]=\"loading() ? 'true' : 'false'\"\n [ngClass]=\"{\n 'btn': true,\n 'btn-primary': variant() === 'primary',\n 'btn-secondary': variant() === 'secondary',\n 'btn-outline': variant() === 'outline',\n 'btn-ghost': variant() === 'ghost',\n 'btn-link': variant() === 'link',\n 'btn-danger': variant() === 'danger',\n 'btn-warning': variant() === 'warning',\n 'btn-info': variant() === 'info',\n 'btn-xs': size() === 'xs',\n 'btn-sm': size() === 'sm',\n 'btn-md': size() === 'md',\n 'btn-lg': size() === 'lg',\n 'btn-icon-only': iconOnly(),\n 'btn-full-width': fullWidth(),\n 'btn-inline': inline(),\n 'btn-flush': flush()\n }\"\n (click)=\"handleClick()\"\n (focus)=\"handleFocus()\"\n (blur)=\"handleBlur()\"\n>\n @if (loading()) {\n <span class=\"loading-spinner\"></span>\n }\n @if (!loading()) {\n <ng-content select=\"[slot='icon-before']\" />\n }\n <ng-content></ng-content>\n @if (!loading()) {\n <ng-content select=\"[slot='icon-after']\" />\n }\n</button>\n",
|
|
179
|
-
styles: [".btn{display:inline-flex;align-items:center;justify-content:center;gap:var(--spacing-2);font-family:var(--font-family-sans);font-weight:var(--font-weight-semibold);line-height:var(--line-height-tight);border:1px solid transparent;border-radius:var(--border-radius-full);cursor:pointer;transition:
|
|
179
|
+
styles: [".btn{display:inline-flex;align-items:center;justify-content:center;gap:var(--spacing-2);font-family:var(--font-family-sans);font-weight:var(--font-weight-semibold);line-height:var(--line-height-tight);border:1px solid transparent;border-radius:var(--border-radius-full);cursor:pointer;transition-property:color,background-color,border-color,box-shadow;transition-duration:var(--animation-duration-base);transition-timing-function:var(--animation-timing-ease);white-space:normal;text-align:center;overflow-wrap:var(--lc-btn-overflow-wrap, break-word);-webkit-user-select:none;user-select:none}.btn:focus-visible{outline:2px solid var(--color-primary-500);outline-offset:2px}.btn:disabled{opacity:.5;cursor:not-allowed;pointer-events:auto}a.btn{text-decoration:none}.btn-primary{background-color:var(--color-primary-fill);color:var(--color-on-primary)}.btn-primary:hover:not(:disabled){background-color:var(--color-primary-fill-hover)}.btn-primary:active:not(:disabled){background-color:var(--color-primary-fill-active)}.btn-secondary{background-color:var(--color-secondary-fill);color:var(--color-on-secondary)}.btn-secondary:hover:not(:disabled){background-color:var(--color-secondary-fill-hover)}.btn-secondary:active:not(:disabled){background-color:var(--color-secondary-fill-active)}.btn-outline{background-color:#84c7d40f;border-color:var(--color-border-strong);color:var(--color-text-primary)}.btn-outline:hover:not(:disabled){background-color:var(--color-primary-600);border-color:var(--color-primary-500);color:var(--color-neutral-white)}.btn-outline:active:not(:disabled){filter:brightness(.92)}.btn-ghost{background-color:var(--lc-button-ghost-bg, transparent);color:var(--lc-button-ghost-fg, var(--color-text-secondary))}.btn-ghost:hover:not(:disabled){background-color:var(--lc-button-ghost-hover-bg, var(--color-surface-hover));color:var(--lc-button-ghost-hover-fg, var(--lc-button-ghost-fg, var(--color-text-primary)))}.btn-ghost:active:not(:disabled){background-color:var(--lc-button-ghost-active-bg, var(--color-surface-selected))}.btn-link{background-color:transparent;color:var(--lc-button-link-fg, var(--color-primary-600));padding:0;border:none}.btn-link:hover:not(:disabled){color:var(--lc-button-link-hover-fg, var(--color-primary-700));text-decoration:underline}.btn-link:active:not(:disabled){color:var(--lc-button-link-active-fg, var(--color-primary-800))}.btn-danger{background-color:var(--color-error-fill);color:var(--color-on-error)}.btn-danger:hover:not(:disabled){background-color:var(--color-error-fill-hover)}.btn-danger:active:not(:disabled){background-color:var(--color-error-fill-active)}.btn-warning{background-color:#e1a040;color:var(--color-on-warning)}.btn-warning:hover:not(:disabled){filter:brightness(1.05)}.btn-warning:active:not(:disabled){filter:brightness(.94)}.btn-info{background-color:#3b6588;color:var(--color-neutral-white)}.btn-info:hover:not(:disabled){background-color:#27445c}.btn-info:active:not(:disabled){background-color:#27445c;filter:brightness(.85)}.btn-xs{padding:var(--spacing-1) var(--spacing-2);font-size:var(--font-size-xs)}.btn-sm{padding:var(--spacing-2) var(--spacing-3);font-size:var(--font-size-sm)}.btn-md{padding:var(--spacing-2-5) var(--spacing-4);font-size:var(--font-size-base)}.btn-lg{padding:var(--spacing-3) var(--spacing-6);font-size:var(--font-size-lg)}.btn-icon-only.btn-xs{padding:var(--spacing-1);width:calc(var(--spacing-1) * 2 + 1em);height:calc(var(--spacing-1) * 2 + 1em)}.btn-icon-only.btn-sm{padding:var(--spacing-2);width:calc(var(--spacing-2) * 2 + 1em);height:calc(var(--spacing-2) * 2 + 1em)}.btn-icon-only.btn-md{padding:var(--spacing-2-5);width:calc(var(--spacing-2-5) * 2 + 1em);height:calc(var(--spacing-2-5) * 2 + 1em)}.btn-icon-only.btn-lg{padding:var(--spacing-3);width:calc(var(--spacing-3) * 2 + 1.2em);height:calc(var(--spacing-3) * 2 + 1.2em)}.btn-full-width{width:100%}.btn-inline{display:inline;padding:0;font-size:inherit;font-weight:inherit;line-height:inherit;vertical-align:baseline;white-space:normal;text-align:inherit;border-radius:var(--border-radius-sm)}.btn.btn-inline{text-decoration:var(--lc-btn-inline-text-decoration, underline);text-decoration-thickness:max(1px,.0625em);text-underline-offset:.15em;transition-property:color,background-color,border-color,box-shadow}.btn.btn-inline:hover:not(:disabled){text-decoration-thickness:max(2px,.125em)}.btn-link.btn-flush:not(.btn-icon-only,.btn-inline){padding-inline:0;min-width:var(--size-min-touch-width, 2.75rem);min-height:var(--size-min-touch-height, 2.75rem);justify-content:var(--lc-btn-flush-align, start);text-align:var(--lc-btn-flush-align, start);border-radius:var(--border-radius-sm)}.loading-spinner{display:inline-block;width:1em;height:1em;border:2px solid currentColor;border-right-color:transparent;border-radius:50%;animation:spin 1s linear infinite}@keyframes spin{to{transform:rotate(360deg)}}.icon-before,.icon-after{display:inline-flex;align-items:center}\n"]
|
|
180
180
|
}]
|
|
181
181
|
}],
|
|
182
182
|
propDecorators: {
|
|
@@ -377,7 +377,7 @@ var ButtonLinkComponent = class ButtonLinkComponent {
|
|
|
377
377
|
select="[slot='icon-after']"
|
|
378
378
|
/>`,
|
|
379
379
|
isInline: true,
|
|
380
|
-
styles: [".btn{display:inline-flex;align-items:center;justify-content:center;gap:var(--spacing-2);font-family:var(--font-family-sans);font-weight:var(--font-weight-semibold);line-height:var(--line-height-tight);border:1px solid transparent;border-radius:var(--border-radius-full);cursor:pointer;transition:
|
|
380
|
+
styles: [".btn{display:inline-flex;align-items:center;justify-content:center;gap:var(--spacing-2);font-family:var(--font-family-sans);font-weight:var(--font-weight-semibold);line-height:var(--line-height-tight);border:1px solid transparent;border-radius:var(--border-radius-full);cursor:pointer;transition-property:color,background-color,border-color,box-shadow;transition-duration:var(--animation-duration-base);transition-timing-function:var(--animation-timing-ease);white-space:normal;text-align:center;overflow-wrap:var(--lc-btn-overflow-wrap, break-word);-webkit-user-select:none;user-select:none}.btn:focus-visible{outline:2px solid var(--color-primary-500);outline-offset:2px}.btn:disabled{opacity:.5;cursor:not-allowed;pointer-events:auto}a.btn{text-decoration:none}.btn-primary{background-color:var(--color-primary-fill);color:var(--color-on-primary)}.btn-primary:hover:not(:disabled){background-color:var(--color-primary-fill-hover)}.btn-primary:active:not(:disabled){background-color:var(--color-primary-fill-active)}.btn-secondary{background-color:var(--color-secondary-fill);color:var(--color-on-secondary)}.btn-secondary:hover:not(:disabled){background-color:var(--color-secondary-fill-hover)}.btn-secondary:active:not(:disabled){background-color:var(--color-secondary-fill-active)}.btn-outline{background-color:#84c7d40f;border-color:var(--color-border-strong);color:var(--color-text-primary)}.btn-outline:hover:not(:disabled){background-color:var(--color-primary-600);border-color:var(--color-primary-500);color:var(--color-neutral-white)}.btn-outline:active:not(:disabled){filter:brightness(.92)}.btn-ghost{background-color:var(--lc-button-ghost-bg, transparent);color:var(--lc-button-ghost-fg, var(--color-text-secondary))}.btn-ghost:hover:not(:disabled){background-color:var(--lc-button-ghost-hover-bg, var(--color-surface-hover));color:var(--lc-button-ghost-hover-fg, var(--lc-button-ghost-fg, var(--color-text-primary)))}.btn-ghost:active:not(:disabled){background-color:var(--lc-button-ghost-active-bg, var(--color-surface-selected))}.btn-link{background-color:transparent;color:var(--lc-button-link-fg, var(--color-primary-600));padding:0;border:none}.btn-link:hover:not(:disabled){color:var(--lc-button-link-hover-fg, var(--color-primary-700));text-decoration:underline}.btn-link:active:not(:disabled){color:var(--lc-button-link-active-fg, var(--color-primary-800))}.btn-danger{background-color:var(--color-error-fill);color:var(--color-on-error)}.btn-danger:hover:not(:disabled){background-color:var(--color-error-fill-hover)}.btn-danger:active:not(:disabled){background-color:var(--color-error-fill-active)}.btn-warning{background-color:#e1a040;color:var(--color-on-warning)}.btn-warning:hover:not(:disabled){filter:brightness(1.05)}.btn-warning:active:not(:disabled){filter:brightness(.94)}.btn-info{background-color:#3b6588;color:var(--color-neutral-white)}.btn-info:hover:not(:disabled){background-color:#27445c}.btn-info:active:not(:disabled){background-color:#27445c;filter:brightness(.85)}.btn-xs{padding:var(--spacing-1) var(--spacing-2);font-size:var(--font-size-xs)}.btn-sm{padding:var(--spacing-2) var(--spacing-3);font-size:var(--font-size-sm)}.btn-md{padding:var(--spacing-2-5) var(--spacing-4);font-size:var(--font-size-base)}.btn-lg{padding:var(--spacing-3) var(--spacing-6);font-size:var(--font-size-lg)}.btn-icon-only.btn-xs{padding:var(--spacing-1);width:calc(var(--spacing-1) * 2 + 1em);height:calc(var(--spacing-1) * 2 + 1em)}.btn-icon-only.btn-sm{padding:var(--spacing-2);width:calc(var(--spacing-2) * 2 + 1em);height:calc(var(--spacing-2) * 2 + 1em)}.btn-icon-only.btn-md{padding:var(--spacing-2-5);width:calc(var(--spacing-2-5) * 2 + 1em);height:calc(var(--spacing-2-5) * 2 + 1em)}.btn-icon-only.btn-lg{padding:var(--spacing-3);width:calc(var(--spacing-3) * 2 + 1.2em);height:calc(var(--spacing-3) * 2 + 1.2em)}.btn-full-width{width:100%}.btn-inline{display:inline;padding:0;font-size:inherit;font-weight:inherit;line-height:inherit;vertical-align:baseline;white-space:normal;text-align:inherit;border-radius:var(--border-radius-sm)}.btn.btn-inline{text-decoration:var(--lc-btn-inline-text-decoration, underline);text-decoration-thickness:max(1px,.0625em);text-underline-offset:.15em;transition-property:color,background-color,border-color,box-shadow}.btn.btn-inline:hover:not(:disabled){text-decoration-thickness:max(2px,.125em)}.btn-link.btn-flush:not(.btn-icon-only,.btn-inline){padding-inline:0;min-width:var(--size-min-touch-width, 2.75rem);min-height:var(--size-min-touch-height, 2.75rem);justify-content:var(--lc-btn-flush-align, start);text-align:var(--lc-btn-flush-align, start);border-radius:var(--border-radius-sm)}.loading-spinner{display:inline-block;width:1em;height:1em;border:2px solid currentColor;border-right-color:transparent;border-radius:50%;animation:spin 1s linear infinite}@keyframes spin{to{transform:rotate(360deg)}}.icon-before,.icon-after{display:inline-flex;align-items:center}\n"],
|
|
381
381
|
changeDetection: i0.ChangeDetectionStrategy.OnPush,
|
|
382
382
|
encapsulation: i0.ViewEncapsulation.None
|
|
383
383
|
});
|
|
@@ -397,7 +397,7 @@ i0.ɵɵngDeclareClassMetadata({
|
|
|
397
397
|
encapsulation: ViewEncapsulation.None,
|
|
398
398
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
399
399
|
host: { "[class]": "hostClasses()" },
|
|
400
|
-
styles: [".btn{display:inline-flex;align-items:center;justify-content:center;gap:var(--spacing-2);font-family:var(--font-family-sans);font-weight:var(--font-weight-semibold);line-height:var(--line-height-tight);border:1px solid transparent;border-radius:var(--border-radius-full);cursor:pointer;transition:
|
|
400
|
+
styles: [".btn{display:inline-flex;align-items:center;justify-content:center;gap:var(--spacing-2);font-family:var(--font-family-sans);font-weight:var(--font-weight-semibold);line-height:var(--line-height-tight);border:1px solid transparent;border-radius:var(--border-radius-full);cursor:pointer;transition-property:color,background-color,border-color,box-shadow;transition-duration:var(--animation-duration-base);transition-timing-function:var(--animation-timing-ease);white-space:normal;text-align:center;overflow-wrap:var(--lc-btn-overflow-wrap, break-word);-webkit-user-select:none;user-select:none}.btn:focus-visible{outline:2px solid var(--color-primary-500);outline-offset:2px}.btn:disabled{opacity:.5;cursor:not-allowed;pointer-events:auto}a.btn{text-decoration:none}.btn-primary{background-color:var(--color-primary-fill);color:var(--color-on-primary)}.btn-primary:hover:not(:disabled){background-color:var(--color-primary-fill-hover)}.btn-primary:active:not(:disabled){background-color:var(--color-primary-fill-active)}.btn-secondary{background-color:var(--color-secondary-fill);color:var(--color-on-secondary)}.btn-secondary:hover:not(:disabled){background-color:var(--color-secondary-fill-hover)}.btn-secondary:active:not(:disabled){background-color:var(--color-secondary-fill-active)}.btn-outline{background-color:#84c7d40f;border-color:var(--color-border-strong);color:var(--color-text-primary)}.btn-outline:hover:not(:disabled){background-color:var(--color-primary-600);border-color:var(--color-primary-500);color:var(--color-neutral-white)}.btn-outline:active:not(:disabled){filter:brightness(.92)}.btn-ghost{background-color:var(--lc-button-ghost-bg, transparent);color:var(--lc-button-ghost-fg, var(--color-text-secondary))}.btn-ghost:hover:not(:disabled){background-color:var(--lc-button-ghost-hover-bg, var(--color-surface-hover));color:var(--lc-button-ghost-hover-fg, var(--lc-button-ghost-fg, var(--color-text-primary)))}.btn-ghost:active:not(:disabled){background-color:var(--lc-button-ghost-active-bg, var(--color-surface-selected))}.btn-link{background-color:transparent;color:var(--lc-button-link-fg, var(--color-primary-600));padding:0;border:none}.btn-link:hover:not(:disabled){color:var(--lc-button-link-hover-fg, var(--color-primary-700));text-decoration:underline}.btn-link:active:not(:disabled){color:var(--lc-button-link-active-fg, var(--color-primary-800))}.btn-danger{background-color:var(--color-error-fill);color:var(--color-on-error)}.btn-danger:hover:not(:disabled){background-color:var(--color-error-fill-hover)}.btn-danger:active:not(:disabled){background-color:var(--color-error-fill-active)}.btn-warning{background-color:#e1a040;color:var(--color-on-warning)}.btn-warning:hover:not(:disabled){filter:brightness(1.05)}.btn-warning:active:not(:disabled){filter:brightness(.94)}.btn-info{background-color:#3b6588;color:var(--color-neutral-white)}.btn-info:hover:not(:disabled){background-color:#27445c}.btn-info:active:not(:disabled){background-color:#27445c;filter:brightness(.85)}.btn-xs{padding:var(--spacing-1) var(--spacing-2);font-size:var(--font-size-xs)}.btn-sm{padding:var(--spacing-2) var(--spacing-3);font-size:var(--font-size-sm)}.btn-md{padding:var(--spacing-2-5) var(--spacing-4);font-size:var(--font-size-base)}.btn-lg{padding:var(--spacing-3) var(--spacing-6);font-size:var(--font-size-lg)}.btn-icon-only.btn-xs{padding:var(--spacing-1);width:calc(var(--spacing-1) * 2 + 1em);height:calc(var(--spacing-1) * 2 + 1em)}.btn-icon-only.btn-sm{padding:var(--spacing-2);width:calc(var(--spacing-2) * 2 + 1em);height:calc(var(--spacing-2) * 2 + 1em)}.btn-icon-only.btn-md{padding:var(--spacing-2-5);width:calc(var(--spacing-2-5) * 2 + 1em);height:calc(var(--spacing-2-5) * 2 + 1em)}.btn-icon-only.btn-lg{padding:var(--spacing-3);width:calc(var(--spacing-3) * 2 + 1.2em);height:calc(var(--spacing-3) * 2 + 1.2em)}.btn-full-width{width:100%}.btn-inline{display:inline;padding:0;font-size:inherit;font-weight:inherit;line-height:inherit;vertical-align:baseline;white-space:normal;text-align:inherit;border-radius:var(--border-radius-sm)}.btn.btn-inline{text-decoration:var(--lc-btn-inline-text-decoration, underline);text-decoration-thickness:max(1px,.0625em);text-underline-offset:.15em;transition-property:color,background-color,border-color,box-shadow}.btn.btn-inline:hover:not(:disabled){text-decoration-thickness:max(2px,.125em)}.btn-link.btn-flush:not(.btn-icon-only,.btn-inline){padding-inline:0;min-width:var(--size-min-touch-width, 2.75rem);min-height:var(--size-min-touch-height, 2.75rem);justify-content:var(--lc-btn-flush-align, start);text-align:var(--lc-btn-flush-align, start);border-radius:var(--border-radius-sm)}.loading-spinner{display:inline-block;width:1em;height:1em;border:2px solid currentColor;border-right-color:transparent;border-radius:50%;animation:spin 1s linear infinite}@keyframes spin{to{transform:rotate(360deg)}}.icon-before,.icon-after{display:inline-flex;align-items:center}\n"]
|
|
401
401
|
}]
|
|
402
402
|
}],
|
|
403
403
|
propDecorators: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lifecorner-angular-ui-kit-button.mjs","names":[],"sources":["../../../../libs/angular-ui-kit/src/lib/button/button.component.ts","../../../../libs/angular-ui-kit/src/lib/button/button.component.html","../../../../libs/angular-ui-kit/src/lib/button/button-link.component.ts"],"sourcesContent":["import {\n Component,\n input,\n output,\n computed,\n ViewChild,\n ElementRef,\n ChangeDetectionStrategy,\n ViewEncapsulation,\n} from '@angular/core';\nimport { NgClass } from '@angular/common';\n\nexport type ButtonVariant =\n | 'primary'\n | 'secondary'\n | 'outline'\n | 'ghost'\n | 'link'\n | 'danger'\n | 'warning'\n | 'info';\nexport type ButtonSize = 'xs' | 'sm' | 'md' | 'lg';\nexport type ButtonType = 'button' | 'submit' | 'reset';\n\n@Component({\n selector: 'lc-button',\n standalone: true,\n imports: [NgClass],\n templateUrl: './button.component.html',\n styleUrl: './button.component.scss',\n encapsulation: ViewEncapsulation.None, // Required for dynamic variant class styling\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\n/**\n * Button component for user actions and form submissions.\n *\n * Features:\n * - Multiple variants (primary, secondary, outline, ghost, danger, link)\n * - Size options (xs, sm, md, lg)\n * - Loading state with spinner\n * - Icon-only mode\n * - Full-width layout option\n * - Keyboard and focus handling\n * - Accessible with ARIA attributes\n *\n * CSS hook `--lc-btn-overflow-wrap` (`break-word | anywhere`, default\n * `break-word`): `anywhere` lets a single word wider than the button's line\n * break inside the word, so the button stays inside its container (WCAG 1.4.10\n * at 320 px or 200 % text). Set it on the button, the `lc-button` host or an\n * ancestor that is a wrapping row or a column. In a non-wrapping row it lets a\n * one-word button shrink with its neighbours, which is why the default stays\n * `break-word`. The kit sets it in `lc-footer`'s link row, the page-header\n * actions and the next-step-card's narrow actions.\n *\n * @example\n * ```html\n * <lc-button variant=\"primary\" size=\"md\">Save</lc-button>\n * ```\n */\nexport class ButtonComponent {\n readonly variant = input<ButtonVariant>('primary');\n readonly size = input<ButtonSize>('md');\n readonly disabled = input(false);\n readonly loading = input(false);\n readonly iconOnly = input(false);\n readonly fullWidth = input(false);\n readonly ariaLabel = input('');\n readonly type = input<ButtonType>('button');\n\n /**\n * Native tooltip (title attribute) on the button.\n */\n readonly title = input('');\n\n /**\n * Reason shown as tooltip while the button is disabled (or loading).\n * Takes precedence over `title` in that state. The tooltip also appears\n * over the disabled button — the component guarantees the inner button\n * never gets `pointer-events: none`.\n */\n readonly disabledReason = input('');\n\n /**\n * Render as an inline text button that inherits font size, weight and\n * line-height from the surrounding text (for links inside copy, clickable\n * row titles, linked counters). Pair with `variant=\"link\"`.\n * @default false\n */\n readonly inline = input(false);\n\n /**\n * Drop the inline padding so a `variant=\"link\"` button sits flush with the\n * content edge: the label starts at the edge, and the button keeps its height\n * and a 44 × 44 px minimum target. At the end edge of a row, set the CSS\n * hook `--lc-btn-flush-align: end` (default `start`) on the host or an\n * ancestor: every line of the label then ends at the edge. Ignored on other\n * variants and with `iconOnly` (3.9, AS-26).\n * @default false\n */\n readonly flush = input(false);\n\n readonly clicked = output<void>();\n readonly focused = output<void>();\n readonly blurred = output<void>();\n\n @ViewChild('buttonElement') buttonElement!: ElementRef<HTMLButtonElement>;\n\n readonly isDisabled = computed(() => this.disabled() || this.loading());\n\n /**\n * Tooltip actually applied to the button: `disabledReason` while disabled,\n * `title` otherwise.\n */\n readonly effectiveTitle = computed(() => {\n if (this.isDisabled() && this.disabledReason()) {\n return this.disabledReason();\n }\n return this.title() || null;\n });\n\n handleClick(): void {\n if (!this.isDisabled()) {\n this.clicked.emit();\n }\n }\n\n handleFocus(): void {\n this.focused.emit();\n }\n\n handleBlur(): void {\n this.blurred.emit();\n }\n\n focus(): void {\n this.buttonElement?.nativeElement.focus();\n }\n\n blur(): void {\n this.buttonElement?.nativeElement.blur();\n }\n}\n","<button\n #buttonElement\n [type]=\"type()\"\n [disabled]=\"isDisabled()\"\n [attr.title]=\"effectiveTitle()\"\n [attr.aria-label]=\"ariaLabel() || null\"\n [attr.aria-disabled]=\"isDisabled() ? 'true' : 'false'\"\n [attr.aria-busy]=\"loading() ? 'true' : 'false'\"\n [ngClass]=\"{\n 'btn': true,\n 'btn-primary': variant() === 'primary',\n 'btn-secondary': variant() === 'secondary',\n 'btn-outline': variant() === 'outline',\n 'btn-ghost': variant() === 'ghost',\n 'btn-link': variant() === 'link',\n 'btn-danger': variant() === 'danger',\n 'btn-warning': variant() === 'warning',\n 'btn-info': variant() === 'info',\n 'btn-xs': size() === 'xs',\n 'btn-sm': size() === 'sm',\n 'btn-md': size() === 'md',\n 'btn-lg': size() === 'lg',\n 'btn-icon-only': iconOnly(),\n 'btn-full-width': fullWidth(),\n 'btn-inline': inline(),\n 'btn-flush': flush()\n }\"\n (click)=\"handleClick()\"\n (focus)=\"handleFocus()\"\n (blur)=\"handleBlur()\"\n>\n @if (loading()) {\n <span class=\"loading-spinner\"></span>\n }\n @if (!loading()) {\n <ng-content select=\"[slot='icon-before']\" />\n }\n <ng-content></ng-content>\n @if (!loading()) {\n <ng-content select=\"[slot='icon-after']\" />\n }\n</button>\n","import {\n ChangeDetectionStrategy,\n Component,\n ViewEncapsulation,\n computed,\n input,\n} from '@angular/core';\nimport type { ButtonSize, ButtonVariant } from './button.component';\n\n/**\n * `lc-button` styling on a native link: `<a lcButton href=\"…\">`.\n *\n * Use it for navigation that looks like a button — calls to action, \"read\n * more\" links, a language switch. The host *is* the anchor, so every native\n * link attribute (`href`, `hreflang`, `lang`, `rel`, `target`, `download`,\n * `title`, `aria-*`) passes through untouched, and the component adds no event\n * listeners: after server-side rendering or prerendering the markup is a plain\n * `<a class=\"btn btn-primary btn-md\" href=\"…\">` that works without JavaScript.\n * `routerLink` can sit on the same anchor for in-app navigation.\n *\n * Same variants, sizes and modifiers as `lc-button` (it shares its stylesheet).\n * Use `size=\"lg\"` (48.5 px) where the link must meet the 44 px touch target. A link\n * cannot be disabled or busy — render plain text or an `lc-button` for those\n * states. An `iconOnly` link needs an `aria-label`.\n *\n * CSS hook `--lc-btn-overflow-wrap` (`break-word | anywhere`, default\n * `break-word`): `anywhere` lets a single word wider than the button's line\n * break inside the word, so the button stays inside its container (WCAG 1.4.10\n * at 320 px or 200 % text). Set it on the button, the `lc-button` host or an\n * ancestor that is a wrapping row or a column. In a non-wrapping row it lets a\n * one-word button shrink with its neighbours, which is why the default stays\n * `break-word`. The kit sets it in `lc-footer`'s link row, the page-header\n * actions and the next-step-card's narrow actions.\n *\n * @example\n * ```html\n * <a lcButton variant=\"primary\" size=\"lg\" href=\"/de/neuigkeiten\">Schau uns beim Bauen zu</a>\n * <a lcButton variant=\"ghost\" href=\"/en/security\" hreflang=\"en\" lang=\"en\">English</a>\n * <a lcButton variant=\"outline\" href=\"https://www.linkedin.com/in/…\" rel=\"me\">\n * <lc-icon slot=\"icon-before\" name=\"external-link\" size=\"sm\" [decorative]=\"true\" />\n * LinkedIn\n * </a>\n * ```\n */\n@Component({\n // An attribute selector on purpose: the anchor must stay the element in the\n // DOM so native link behaviour and attributes are untouched.\n selector: 'a[lcButton]',\n template: `<ng-content select=\"[slot='icon-before']\" /><ng-content /><ng-content\n select=\"[slot='icon-after']\"\n />`,\n // The same stylesheet as lc-button: identical style text is registered once,\n // whichever of the two renders first.\n styleUrl: './button.component.scss',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n host: {\n '[class]': 'hostClasses()',\n },\n})\nexport class ButtonLinkComponent {\n /** Visual variant, as on `lc-button`. */\n readonly variant = input<ButtonVariant>('primary');\n /** Size, as on `lc-button`. `lg` (48.5 px high) meets the 44 px touch target. */\n readonly size = input<ButtonSize>('md');\n /** Stretch the link to the full width of its container. */\n readonly fullWidth = input(false);\n /** Square icon-only link. Give the anchor an `aria-label`. */\n readonly iconOnly = input(false);\n /**\n * Flow with the surrounding text instead of forming a pill (inherits font\n * size, weight and line-height). Pair with `variant=\"link\"`.\n */\n readonly inline = input(false);\n /**\n * Drop the inline padding so a `variant=\"link\"` link sits flush with the\n * content edge: the label starts at the edge, and the link keeps its height\n * and a 44 × 44 px minimum target. At the end edge of a row, set the CSS\n * hook `--lc-btn-flush-align: end` (default `start`) on the link or an\n * ancestor: every line of the label then ends at the edge. Ignored on other\n * variants and with `iconOnly` (3.9, AS-26).\n * @default false\n */\n readonly flush = input(false);\n\n /** Classes on the anchor; merged with the consumer's own `class`. */\n protected readonly hostClasses = computed(() => {\n const classes = ['btn', `btn-${this.variant()}`, `btn-${this.size()}`];\n if (this.iconOnly()) classes.push('btn-icon-only');\n if (this.fullWidth()) classes.push('btn-full-width');\n if (this.inline()) classes.push('btn-inline');\n if (this.flush()) classes.push('btn-flush');\n return classes.join(' ');\n });\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"lifecorner-angular-ui-kit-button.mjs","names":[],"sources":["../../../../libs/angular-ui-kit/src/lib/button/button.component.ts","../../../../libs/angular-ui-kit/src/lib/button/button.component.html","../../../../libs/angular-ui-kit/src/lib/button/button-link.component.ts"],"sourcesContent":["import {\n Component,\n input,\n output,\n computed,\n ViewChild,\n ElementRef,\n ChangeDetectionStrategy,\n ViewEncapsulation,\n} from '@angular/core';\nimport { NgClass } from '@angular/common';\n\nexport type ButtonVariant =\n | 'primary'\n | 'secondary'\n | 'outline'\n | 'ghost'\n | 'link'\n | 'danger'\n | 'warning'\n | 'info';\nexport type ButtonSize = 'xs' | 'sm' | 'md' | 'lg';\nexport type ButtonType = 'button' | 'submit' | 'reset';\n\n@Component({\n selector: 'lc-button',\n standalone: true,\n imports: [NgClass],\n templateUrl: './button.component.html',\n styleUrl: './button.component.scss',\n encapsulation: ViewEncapsulation.None, // Required for dynamic variant class styling\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\n/**\n * Button component for user actions and form submissions.\n *\n * Features:\n * - Multiple variants (primary, secondary, outline, ghost, danger, link)\n * - Size options (xs, sm, md, lg)\n * - Loading state with spinner\n * - Icon-only mode\n * - Full-width layout option\n * - Keyboard and focus handling\n * - Accessible with ARIA attributes\n *\n * CSS hook `--lc-btn-overflow-wrap` (`break-word | anywhere`, default\n * `break-word`): `anywhere` lets a single word wider than the button's line\n * break inside the word, so the button stays inside its container (WCAG 1.4.10\n * at 320 px or 200 % text). Set it on the button, the `lc-button` host or an\n * ancestor that is a wrapping row or a column. In a non-wrapping row it lets a\n * one-word button shrink with its neighbours, which is why the default stays\n * `break-word`. The kit sets it in `lc-footer`'s link row, the page-header\n * actions and the next-step-card's narrow actions.\n *\n * @example\n * ```html\n * <lc-button variant=\"primary\" size=\"md\">Save</lc-button>\n * ```\n */\nexport class ButtonComponent {\n readonly variant = input<ButtonVariant>('primary');\n readonly size = input<ButtonSize>('md');\n readonly disabled = input(false);\n readonly loading = input(false);\n readonly iconOnly = input(false);\n readonly fullWidth = input(false);\n readonly ariaLabel = input('');\n readonly type = input<ButtonType>('button');\n\n /**\n * Native tooltip (title attribute) on the button.\n */\n readonly title = input('');\n\n /**\n * Reason shown as tooltip while the button is disabled (or loading).\n * Takes precedence over `title` in that state. The tooltip also appears\n * over the disabled button — the component guarantees the inner button\n * never gets `pointer-events: none`.\n */\n readonly disabledReason = input('');\n\n /**\n * Render as an inline text button that inherits font size, weight and\n * line-height from the surrounding text (for links inside copy, clickable\n * row titles, linked counters). Pair with `variant=\"link\"`.\n * @default false\n */\n readonly inline = input(false);\n\n /**\n * Drop the inline padding so a `variant=\"link\"` button sits flush with the\n * content edge: the label starts at the edge, and the button keeps its height\n * and a 44 × 44 px minimum target. At the end edge of a row, set the CSS\n * hook `--lc-btn-flush-align: end` (default `start`) on the host or an\n * ancestor: every line of the label then ends at the edge. Ignored on other\n * variants and with `iconOnly` (3.9, AS-26).\n * @default false\n */\n readonly flush = input(false);\n\n readonly clicked = output<void>();\n readonly focused = output<void>();\n readonly blurred = output<void>();\n\n @ViewChild('buttonElement') buttonElement!: ElementRef<HTMLButtonElement>;\n\n readonly isDisabled = computed(() => this.disabled() || this.loading());\n\n /**\n * Tooltip actually applied to the button: `disabledReason` while disabled,\n * `title` otherwise.\n */\n readonly effectiveTitle = computed(() => {\n if (this.isDisabled() && this.disabledReason()) {\n return this.disabledReason();\n }\n return this.title() || null;\n });\n\n handleClick(): void {\n if (!this.isDisabled()) {\n this.clicked.emit();\n }\n }\n\n handleFocus(): void {\n this.focused.emit();\n }\n\n handleBlur(): void {\n this.blurred.emit();\n }\n\n focus(): void {\n this.buttonElement?.nativeElement.focus();\n }\n\n blur(): void {\n this.buttonElement?.nativeElement.blur();\n }\n}\n","<button\n #buttonElement\n [type]=\"type()\"\n [disabled]=\"isDisabled()\"\n [attr.title]=\"effectiveTitle()\"\n [attr.aria-label]=\"ariaLabel() || null\"\n [attr.aria-disabled]=\"isDisabled() ? 'true' : 'false'\"\n [attr.aria-busy]=\"loading() ? 'true' : 'false'\"\n [ngClass]=\"{\n 'btn': true,\n 'btn-primary': variant() === 'primary',\n 'btn-secondary': variant() === 'secondary',\n 'btn-outline': variant() === 'outline',\n 'btn-ghost': variant() === 'ghost',\n 'btn-link': variant() === 'link',\n 'btn-danger': variant() === 'danger',\n 'btn-warning': variant() === 'warning',\n 'btn-info': variant() === 'info',\n 'btn-xs': size() === 'xs',\n 'btn-sm': size() === 'sm',\n 'btn-md': size() === 'md',\n 'btn-lg': size() === 'lg',\n 'btn-icon-only': iconOnly(),\n 'btn-full-width': fullWidth(),\n 'btn-inline': inline(),\n 'btn-flush': flush()\n }\"\n (click)=\"handleClick()\"\n (focus)=\"handleFocus()\"\n (blur)=\"handleBlur()\"\n>\n @if (loading()) {\n <span class=\"loading-spinner\"></span>\n }\n @if (!loading()) {\n <ng-content select=\"[slot='icon-before']\" />\n }\n <ng-content></ng-content>\n @if (!loading()) {\n <ng-content select=\"[slot='icon-after']\" />\n }\n</button>\n","import {\n ChangeDetectionStrategy,\n Component,\n ViewEncapsulation,\n computed,\n input,\n} from '@angular/core';\nimport type { ButtonSize, ButtonVariant } from './button.component';\n\n/**\n * `lc-button` styling on a native link: `<a lcButton href=\"…\">`.\n *\n * Use it for navigation that looks like a button — calls to action, \"read\n * more\" links, a language switch. The host *is* the anchor, so every native\n * link attribute (`href`, `hreflang`, `lang`, `rel`, `target`, `download`,\n * `title`, `aria-*`) passes through untouched, and the component adds no event\n * listeners: after server-side rendering or prerendering the markup is a plain\n * `<a class=\"btn btn-primary btn-md\" href=\"…\">` that works without JavaScript.\n * `routerLink` can sit on the same anchor for in-app navigation.\n *\n * Same variants, sizes and modifiers as `lc-button` (it shares its stylesheet).\n * Use `size=\"lg\"` (48.5 px) where the link must meet the 44 px touch target. A link\n * cannot be disabled or busy — render plain text or an `lc-button` for those\n * states. An `iconOnly` link needs an `aria-label`.\n *\n * CSS hook `--lc-btn-overflow-wrap` (`break-word | anywhere`, default\n * `break-word`): `anywhere` lets a single word wider than the button's line\n * break inside the word, so the button stays inside its container (WCAG 1.4.10\n * at 320 px or 200 % text). Set it on the button, the `lc-button` host or an\n * ancestor that is a wrapping row or a column. In a non-wrapping row it lets a\n * one-word button shrink with its neighbours, which is why the default stays\n * `break-word`. The kit sets it in `lc-footer`'s link row, the page-header\n * actions and the next-step-card's narrow actions.\n *\n * @example\n * ```html\n * <a lcButton variant=\"primary\" size=\"lg\" href=\"/de/neuigkeiten\">Schau uns beim Bauen zu</a>\n * <a lcButton variant=\"ghost\" href=\"/en/security\" hreflang=\"en\" lang=\"en\">English</a>\n * <a lcButton variant=\"outline\" href=\"https://www.linkedin.com/in/…\" rel=\"me\">\n * <lc-icon slot=\"icon-before\" name=\"external-link\" size=\"sm\" [decorative]=\"true\" />\n * LinkedIn\n * </a>\n * ```\n */\n@Component({\n // An attribute selector on purpose: the anchor must stay the element in the\n // DOM so native link behaviour and attributes are untouched.\n selector: 'a[lcButton]',\n template: `<ng-content select=\"[slot='icon-before']\" /><ng-content /><ng-content\n select=\"[slot='icon-after']\"\n />`,\n // The same stylesheet as lc-button: identical style text is registered once,\n // whichever of the two renders first.\n styleUrl: './button.component.scss',\n encapsulation: ViewEncapsulation.None,\n changeDetection: ChangeDetectionStrategy.OnPush,\n host: {\n '[class]': 'hostClasses()',\n },\n})\nexport class ButtonLinkComponent {\n /** Visual variant, as on `lc-button`. */\n readonly variant = input<ButtonVariant>('primary');\n /** Size, as on `lc-button`. `lg` (48.5 px high) meets the 44 px touch target. */\n readonly size = input<ButtonSize>('md');\n /** Stretch the link to the full width of its container. */\n readonly fullWidth = input(false);\n /** Square icon-only link. Give the anchor an `aria-label`. */\n readonly iconOnly = input(false);\n /**\n * Flow with the surrounding text instead of forming a pill (inherits font\n * size, weight and line-height). Pair with `variant=\"link\"`.\n */\n readonly inline = input(false);\n /**\n * Drop the inline padding so a `variant=\"link\"` link sits flush with the\n * content edge: the label starts at the edge, and the link keeps its height\n * and a 44 × 44 px minimum target. At the end edge of a row, set the CSS\n * hook `--lc-btn-flush-align: end` (default `start`) on the link or an\n * ancestor: every line of the label then ends at the edge. Ignored on other\n * variants and with `iconOnly` (3.9, AS-26).\n * @default false\n */\n readonly flush = input(false);\n\n /** Classes on the anchor; merged with the consumer's own `class`. */\n protected readonly hostClasses = computed(() => {\n const classes = ['btn', `btn-${this.variant()}`, `btn-${this.size()}`];\n if (this.iconOnly()) classes.push('btn-icon-only');\n if (this.fullWidth()) classes.push('btn-full-width');\n if (this.inline()) classes.push('btn-inline');\n if (this.flush()) classes.push('btn-flush');\n return classes.join(' ');\n });\n}\n"],"mappings":"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"}
|
|
@@ -39,8 +39,8 @@ const CHARACTER_SVG_IN_HIS_CORNER = {
|
|
|
39
39
|
dark: "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"100\" height=\"100\" viewBox=\"0 0 100 100\"><path d=\"M6 6 L6 92 L98 92\" fill=\"none\" stroke=\"#2a4250\" stroke-width=\"2\" stroke-linecap=\"round\"></path><g transform=\"translate(3 6)\"><g fill=\"none\" stroke=\"#84c7d4\" stroke-width=\"5.5\" stroke-linecap=\"round\"><path d=\"M34 50 C27 58 21 70 14 80\"></path><path d=\"M44 56 C42 66 38 74 33 80\"></path><path d=\"M56 56 C59 66 63 74 68 80\"></path><path d=\"M66 50 C74 58 82 72 90 80\"></path></g><ellipse cx=\"50\" cy=\"38\" rx=\"22\" ry=\"20\" fill=\"#84c7d4\"></ellipse><ellipse cx=\"43\" cy=\"29\" rx=\"8\" ry=\"4.5\" fill=\"#ffffff\" opacity=\"0.22\"></ellipse><circle cx=\"37\" cy=\"46\" r=\"3.2\" fill=\"#1a6a79\" opacity=\"0.55\"></circle><circle cx=\"63\" cy=\"46\" r=\"3.2\" fill=\"#1a6a79\" opacity=\"0.55\"></circle><circle cx=\"42\" cy=\"38\" r=\"4.6\" fill=\"#ffffff\"></circle><circle cx=\"58\" cy=\"38\" r=\"4.6\" fill=\"#ffffff\"></circle><circle cx=\"43.6\" cy=\"38.8\" r=\"2.3\" fill=\"#0c1722\"></circle><circle cx=\"59.6\" cy=\"38.8\" r=\"2.3\" fill=\"#0c1722\"></circle><path d=\"M45 45.5 Q50 49 55 45.5\" fill=\"none\" stroke=\"#0c1722\" stroke-width=\"2\" stroke-linecap=\"round\"></path><g fill=\"#0a121b\" stroke=\"#84c7d4\" stroke-width=\"4\"><circle cx=\"14\" cy=\"80\" r=\"5.5\"></circle><circle cx=\"33\" cy=\"80\" r=\"5.5\"></circle><circle cx=\"68\" cy=\"80\" r=\"5.5\"></circle><circle cx=\"90\" cy=\"80\" r=\"5.5\"></circle></g></g></svg>\n"
|
|
40
40
|
};
|
|
41
41
|
const CHARACTER_SVG_COMFORTS = {
|
|
42
|
-
light: "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"100\" height=\"100\" viewBox=\"0 0 100 100\"><g fill=\"none\" stroke=\"#1a6a79\" stroke-width=\"5.5\" stroke-linecap=\"round\"><path d=\"M34 50 C27 57 22 64 17 68\"></path><path d=\"M44 56 C42 65 39 73 36 79\"></path><path d=\"M56 56 C58 65 61 73 64 79\"></path><path d=\"M66 50 C75 54 83 55 89 52\"></path></g><g transform=\"rotate(-8 50 45)\"><ellipse cx=\"50\" cy=\"38\" rx=\"22\" ry=\"20\" fill=\"#1a6a79\"></ellipse><ellipse cx=\"43\" cy=\"29\" rx=\"8\" ry=\"4.5\" fill=\"#ffffff\" opacity=\"0.14\"></ellipse><circle cx=\"37\" cy=\"46\" r=\"3.2\" fill=\"#84c7d4\" opacity=\"0.55\"></circle><circle cx=\"63\" cy=\"46\" r=\"3.2\" fill=\"#84c7d4\" opacity=\"0.55\"></circle><circle cx=\"42\" cy=\"38\" r=\"4.6\" fill=\"#ffffff\"></circle><circle cx=\"58\" cy=\"38\" r=\"4.6\" fill=\"#ffffff\"></circle><circle cx=\"42\" cy=\"39.8\" r=\"2.3\" fill=\"#0c1722\"></circle><circle cx=\"58\" cy=\"39.8\" r=\"2.3\" fill=\"#0c1722\"></circle><g fill=\"none\" stroke=\"#0c1722\" stroke-width=\"1.8\" stroke-linecap=\"round\"><path d=\"M38
|
|
43
|
-
dark: "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"100\" height=\"100\" viewBox=\"0 0 100 100\"><g fill=\"none\" stroke=\"#84c7d4\" stroke-width=\"5.5\" stroke-linecap=\"round\"><path d=\"M34 50 C27 57 22 64 17 68\"></path><path d=\"M44 56 C42 65 39 73 36 79\"></path><path d=\"M56 56 C58 65 61 73 64 79\"></path><path d=\"M66 50 C75 54 83 55 89 52\"></path></g><g transform=\"rotate(-8 50 45)\"><ellipse cx=\"50\" cy=\"38\" rx=\"22\" ry=\"20\" fill=\"#84c7d4\"></ellipse><ellipse cx=\"43\" cy=\"29\" rx=\"8\" ry=\"4.5\" fill=\"#ffffff\" opacity=\"0.22\"></ellipse><circle cx=\"37\" cy=\"46\" r=\"3.2\" fill=\"#1a6a79\" opacity=\"0.55\"></circle><circle cx=\"63\" cy=\"46\" r=\"3.2\" fill=\"#1a6a79\" opacity=\"0.55\"></circle><circle cx=\"42\" cy=\"38\" r=\"4.6\" fill=\"#ffffff\"></circle><circle cx=\"58\" cy=\"38\" r=\"4.6\" fill=\"#ffffff\"></circle><circle cx=\"42\" cy=\"39.8\" r=\"2.3\" fill=\"#0c1722\"></circle><circle cx=\"58\" cy=\"39.8\" r=\"2.3\" fill=\"#0c1722\"></circle><g fill=\"none\" stroke=\"#0c1722\" stroke-width=\"1.8\" stroke-linecap=\"round\"><path d=\"M38
|
|
42
|
+
light: "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"100\" height=\"100\" viewBox=\"0 0 100 100\"><g fill=\"none\" stroke=\"#1a6a79\" stroke-width=\"5.5\" stroke-linecap=\"round\"><path d=\"M34 50 C27 57 22 64 17 68\"></path><path d=\"M44 56 C42 65 39 73 36 79\"></path><path d=\"M56 56 C58 65 61 73 64 79\"></path><path d=\"M66 50 C75 54 83 55 89 52\"></path></g><g transform=\"rotate(-8 50 45)\"><ellipse cx=\"50\" cy=\"38\" rx=\"22\" ry=\"20\" fill=\"#1a6a79\"></ellipse><ellipse cx=\"43\" cy=\"29\" rx=\"8\" ry=\"4.5\" fill=\"#ffffff\" opacity=\"0.14\"></ellipse><circle cx=\"37\" cy=\"46\" r=\"3.2\" fill=\"#84c7d4\" opacity=\"0.55\"></circle><circle cx=\"63\" cy=\"46\" r=\"3.2\" fill=\"#84c7d4\" opacity=\"0.55\"></circle><circle cx=\"42\" cy=\"38\" r=\"4.6\" fill=\"#ffffff\"></circle><circle cx=\"58\" cy=\"38\" r=\"4.6\" fill=\"#ffffff\"></circle><circle cx=\"42\" cy=\"39.8\" r=\"2.3\" fill=\"#0c1722\"></circle><circle cx=\"58\" cy=\"39.8\" r=\"2.3\" fill=\"#0c1722\"></circle><g fill=\"none\" stroke=\"#0c1722\" stroke-width=\"1.8\" stroke-linecap=\"round\"><path d=\"M38 32.5 L45.5 29.5\"></path><path d=\"M54.5 29.5 L62 32.5\"></path><path d=\"M46 47.5 Q50 48.7 54 47.5\"></path></g></g><g fill=\"#ffffff\" stroke=\"#1a6a79\" stroke-width=\"4\"><circle cx=\"15\" cy=\"70\" r=\"5.5\"></circle><circle cx=\"35\" cy=\"82\" r=\"5.5\"></circle><circle cx=\"65\" cy=\"82\" r=\"5.5\"></circle><circle cx=\"91\" cy=\"51\" r=\"5.5\"></circle></g></svg>\n",
|
|
43
|
+
dark: "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"100\" height=\"100\" viewBox=\"0 0 100 100\"><g fill=\"none\" stroke=\"#84c7d4\" stroke-width=\"5.5\" stroke-linecap=\"round\"><path d=\"M34 50 C27 57 22 64 17 68\"></path><path d=\"M44 56 C42 65 39 73 36 79\"></path><path d=\"M56 56 C58 65 61 73 64 79\"></path><path d=\"M66 50 C75 54 83 55 89 52\"></path></g><g transform=\"rotate(-8 50 45)\"><ellipse cx=\"50\" cy=\"38\" rx=\"22\" ry=\"20\" fill=\"#84c7d4\"></ellipse><ellipse cx=\"43\" cy=\"29\" rx=\"8\" ry=\"4.5\" fill=\"#ffffff\" opacity=\"0.22\"></ellipse><circle cx=\"37\" cy=\"46\" r=\"3.2\" fill=\"#1a6a79\" opacity=\"0.55\"></circle><circle cx=\"63\" cy=\"46\" r=\"3.2\" fill=\"#1a6a79\" opacity=\"0.55\"></circle><circle cx=\"42\" cy=\"38\" r=\"4.6\" fill=\"#ffffff\"></circle><circle cx=\"58\" cy=\"38\" r=\"4.6\" fill=\"#ffffff\"></circle><circle cx=\"42\" cy=\"39.8\" r=\"2.3\" fill=\"#0c1722\"></circle><circle cx=\"58\" cy=\"39.8\" r=\"2.3\" fill=\"#0c1722\"></circle><g fill=\"none\" stroke=\"#0c1722\" stroke-width=\"1.8\" stroke-linecap=\"round\"><path d=\"M38 32.5 L45.5 29.5\"></path><path d=\"M54.5 29.5 L62 32.5\"></path><path d=\"M46 47.5 Q50 48.7 54 47.5\"></path></g></g><g fill=\"#0a121b\" stroke=\"#84c7d4\" stroke-width=\"4\"><circle cx=\"15\" cy=\"70\" r=\"5.5\"></circle><circle cx=\"35\" cy=\"82\" r=\"5.5\"></circle><circle cx=\"65\" cy=\"82\" r=\"5.5\"></circle><circle cx=\"91\" cy=\"51\" r=\"5.5\"></circle></g></svg>\n"
|
|
44
44
|
};
|
|
45
45
|
const CHARACTER_SVG_ALL_DONE = {
|
|
46
46
|
light: "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"100\" height=\"100\" viewBox=\"0 0 100 100\"><g fill=\"none\" stroke=\"#1a6a79\" stroke-width=\"5.5\" stroke-linecap=\"round\"><path d=\"M34 50 C27 57 22 64 17 68\"></path><path d=\"M44 56 C42 65 39 73 36 79\"></path><path d=\"M56 56 C58 65 61 73 64 79\"></path><path d=\"M66 50 C73 57 78 64 83 68\"></path></g><ellipse cx=\"50\" cy=\"38\" rx=\"22\" ry=\"20\" fill=\"#1a6a79\"></ellipse><ellipse cx=\"43\" cy=\"29\" rx=\"8\" ry=\"4.5\" fill=\"#ffffff\" opacity=\"0.14\"></ellipse><circle cx=\"37\" cy=\"46\" r=\"3.2\" fill=\"#84c7d4\" opacity=\"0.55\"></circle><circle cx=\"63\" cy=\"46\" r=\"3.2\" fill=\"#84c7d4\" opacity=\"0.55\"></circle><path d=\"M37.5 38.5 Q42 35 46.5 38.5\" fill=\"none\" stroke=\"#0c1722\" stroke-width=\"2.4\" stroke-linecap=\"round\"></path><circle cx=\"58\" cy=\"38\" r=\"4.6\" fill=\"#ffffff\"></circle><circle cx=\"58.6\" cy=\"38.4\" r=\"2.3\" fill=\"#0c1722\"></circle><path d=\"M44 45 Q50 52 56 45\" fill=\"none\" stroke=\"#0c1722\" stroke-width=\"2.2\" stroke-linecap=\"round\"></path><g fill=\"#84c7d4\" stroke=\"#1a6a79\" stroke-width=\"4\"><circle cx=\"15\" cy=\"70\" r=\"5.5\"></circle><circle cx=\"35\" cy=\"82\" r=\"5.5\"></circle><circle cx=\"65\" cy=\"82\" r=\"5.5\"></circle><circle cx=\"85\" cy=\"70\" r=\"5.5\"></circle></g></svg>\n",
|