@immich/ui 0.30.0 → 0.30.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -17
- package/dist/actions/shortcut.js +1 -1
- package/dist/components/Alert/Alert.svelte +92 -94
- package/dist/components/AppShell/AppShell.svelte +26 -26
- package/dist/components/AppShell/AppShellHeader.svelte +8 -8
- package/dist/components/AppShell/AppShellSidebar.svelte +20 -20
- package/dist/components/AppShell/PageLayout.svelte +29 -35
- package/dist/components/Avatar/Avatar.svelte +45 -55
- package/dist/components/Button/Button.svelte +3 -3
- package/dist/components/Card/Card.svelte +131 -135
- package/dist/components/Card/CardBody.svelte +9 -9
- package/dist/components/Card/CardDescription.svelte +9 -9
- package/dist/components/Card/CardFooter.svelte +9 -9
- package/dist/components/Card/CardHeader.svelte +9 -9
- package/dist/components/Card/CardTitle.svelte +14 -14
- package/dist/components/Checkbox/Checkbox.svelte +109 -110
- package/dist/components/CloseButton/CloseButton.svelte +12 -17
- package/dist/components/Code/Code.svelte +58 -65
- package/dist/components/CommandPalette/CommandPalette.svelte +126 -131
- package/dist/components/CommandPalette/CommandPaletteItem.svelte +61 -61
- package/dist/components/ConfirmModal/ConfirmModal.svelte +48 -48
- package/dist/components/Container/Container.svelte +25 -25
- package/dist/components/Field/Field.svelte +21 -21
- package/dist/components/FormatBytes/FormatBytes.svelte +9 -9
- package/dist/components/Heading/Heading.svelte +41 -47
- package/dist/components/HelperText/HelperText.svelte +17 -17
- package/dist/components/Icon/Icon.svelte +37 -42
- package/dist/components/IconButton/IconButton.svelte +6 -13
- package/dist/components/Input/Input.svelte +149 -152
- package/dist/components/Kbd/Kbd.svelte +25 -25
- package/dist/components/Label/Label.svelte +6 -6
- package/dist/components/Link/Link.svelte +18 -25
- package/dist/components/LoadingSpinner/LoadingSpinner.svelte +46 -46
- package/dist/components/Logo/Logo.svelte +53 -53
- package/dist/components/Modal/Modal.svelte +110 -114
- package/dist/components/Modal/ModalBody.svelte +8 -8
- package/dist/components/Modal/ModalFooter.svelte +8 -8
- package/dist/components/Modal/ModalHeader.svelte +8 -8
- package/dist/components/MultiSelect/MultiSelect.svelte +7 -7
- package/dist/components/Navbar/NavbarGroup.svelte +5 -5
- package/dist/components/Navbar/NavbarItem.svelte +59 -61
- package/dist/components/PasswordInput/PasswordInput.svelte +29 -31
- package/dist/components/Scrollable/Scrollable.svelte +49 -49
- package/dist/components/Select/Select.svelte +9 -9
- package/dist/components/Stack/HStack.svelte +4 -4
- package/dist/components/Stack/Stack.svelte +62 -62
- package/dist/components/Stack/VStack.svelte +4 -4
- package/dist/components/SupporterBadge/SupporterBadge.svelte +80 -80
- package/dist/components/Switch/Switch.svelte +95 -96
- package/dist/components/Text/Text.svelte +27 -34
- package/dist/components/Textarea/Textarea.svelte +103 -104
- package/dist/components/ThemeSwitcher/ThemeSwitcher.svelte +30 -43
- package/dist/internal/Button.svelte +177 -177
- package/dist/internal/Child.svelte +21 -21
- package/dist/internal/Select.svelte +151 -158
- package/dist/internal/Text.svelte +42 -50
- package/dist/site/SiteFooter.svelte +60 -76
- package/dist/site/SiteFooterLink.svelte +14 -14
- package/dist/theme/default.css +40 -40
- package/dist/utilities/byte-units.js +2 -13
- package/package.json +77 -77
package/README.md
CHANGED
|
@@ -14,26 +14,18 @@ Import components from `@immich/ui`. For example:
|
|
|
14
14
|
|
|
15
15
|
```html
|
|
16
16
|
<script lang="ts">
|
|
17
|
-
|
|
18
|
-
Card,
|
|
19
|
-
CardBody,
|
|
20
|
-
CardHeader,
|
|
21
|
-
CardTitle,
|
|
22
|
-
CardDescription,
|
|
23
|
-
Heading,
|
|
24
|
-
Text,
|
|
25
|
-
} from '@immich/ui';
|
|
17
|
+
import { Card, CardBody, CardHeader, CardTitle, CardDescription, Heading, Text } from '@immich/ui';
|
|
26
18
|
</script>
|
|
27
19
|
|
|
28
20
|
<Card>
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
21
|
+
<CardHeader>
|
|
22
|
+
<CardTitle>@immich/ui</CardTitle>
|
|
23
|
+
<CardDescription>A component library</CardDescription>
|
|
24
|
+
</CardHeader>
|
|
25
|
+
<CardBody>
|
|
26
|
+
<Lorem />
|
|
27
|
+
</CardBody>
|
|
28
|
+
<CardFooter>Privacy should not be a luxury</CardFooter>
|
|
37
29
|
</Card>
|
|
38
30
|
```
|
|
39
31
|
|
package/dist/actions/shortcut.js
CHANGED
|
@@ -47,7 +47,7 @@ export const shortcut = (node, option) => {
|
|
|
47
47
|
export const shortcuts = (node, options) => {
|
|
48
48
|
function onKeydown(event) {
|
|
49
49
|
const ignoreShortcut = shouldIgnoreEvent(event);
|
|
50
|
-
for (const { shortcut, onShortcut, ignoreInputFields = true, preventDefault = true
|
|
50
|
+
for (const { shortcut, onShortcut, ignoreInputFields = true, preventDefault = true } of options) {
|
|
51
51
|
if (ignoreInputFields && ignoreShortcut) {
|
|
52
52
|
continue;
|
|
53
53
|
}
|
|
@@ -1,110 +1,108 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
2
|
+
import Card from '../Card/Card.svelte';
|
|
3
|
+
import CardBody from '../Card/CardBody.svelte';
|
|
4
|
+
import CloseButton from '../CloseButton/CloseButton.svelte';
|
|
5
|
+
import Icon from '../Icon/Icon.svelte';
|
|
6
|
+
import Text from '../Text/Text.svelte';
|
|
7
|
+
import type { Color, Size } from '../../types.js';
|
|
8
|
+
import { cleanClass } from '../../utils.js';
|
|
9
|
+
import {
|
|
10
|
+
mdiAlertOutline,
|
|
11
|
+
mdiCheckCircleOutline,
|
|
12
|
+
mdiCloseCircleOutline,
|
|
13
|
+
mdiInformationVariantCircleOutline,
|
|
14
|
+
} from '@mdi/js';
|
|
15
|
+
import type { Snippet } from 'svelte';
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
17
|
+
type Props = {
|
|
18
|
+
color?: Color;
|
|
19
|
+
size?: Size;
|
|
20
|
+
icon?: string | false;
|
|
21
|
+
title?: string;
|
|
22
|
+
class?: string;
|
|
23
|
+
duration?: number;
|
|
24
|
+
closable?: boolean;
|
|
25
|
+
controlled?: boolean;
|
|
26
|
+
onClose?: () => void;
|
|
27
|
+
children?: Snippet;
|
|
28
|
+
};
|
|
29
29
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
30
|
+
const {
|
|
31
|
+
color = 'primary',
|
|
32
|
+
icon: iconOverride,
|
|
33
|
+
size = 'large',
|
|
34
|
+
title,
|
|
35
|
+
class: className,
|
|
36
|
+
duration,
|
|
37
|
+
controlled,
|
|
38
|
+
closable,
|
|
39
|
+
onClose,
|
|
40
|
+
children,
|
|
41
|
+
}: Props = $props();
|
|
42
42
|
|
|
43
|
-
|
|
43
|
+
let open = $state(true);
|
|
44
44
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
45
|
+
const iconSizes: Record<Size, string> = {
|
|
46
|
+
tiny: '1em',
|
|
47
|
+
small: '1.25em',
|
|
48
|
+
medium: '1.5em',
|
|
49
|
+
large: '1.75em',
|
|
50
|
+
giant: '1.85em',
|
|
51
|
+
};
|
|
52
52
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
53
|
+
const handleClose = () => {
|
|
54
|
+
if (!open) {
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
57
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
58
|
+
if (!controlled) {
|
|
59
|
+
open = false;
|
|
60
|
+
}
|
|
61
61
|
|
|
62
|
-
|
|
63
|
-
|
|
62
|
+
onClose?.();
|
|
63
|
+
};
|
|
64
64
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
65
|
+
if (duration) {
|
|
66
|
+
setTimeout(handleClose, duration);
|
|
67
|
+
}
|
|
68
68
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
69
|
+
const icons: Partial<Record<Color, string>> = {
|
|
70
|
+
success: mdiCheckCircleOutline,
|
|
71
|
+
warning: mdiAlertOutline,
|
|
72
|
+
danger: mdiCloseCircleOutline,
|
|
73
|
+
};
|
|
74
74
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
: iconOverride || (icons[color] ?? mdiInformationVariantCircleOutline),
|
|
79
|
-
);
|
|
75
|
+
const icon = $derived(
|
|
76
|
+
iconOverride === false ? undefined : iconOverride || (icons[color] ?? mdiInformationVariantCircleOutline),
|
|
77
|
+
);
|
|
80
78
|
</script>
|
|
81
79
|
|
|
82
80
|
{#if open}
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
81
|
+
<Card {color} class={cleanClass(className)}>
|
|
82
|
+
<CardBody>
|
|
83
|
+
<div class="flex items-center justify-between">
|
|
84
|
+
<div class={cleanClass('flex gap-2')}>
|
|
85
|
+
{#if icon}
|
|
86
|
+
<div>
|
|
87
|
+
<Icon {icon} size={iconSizes[size]} />
|
|
88
|
+
</div>
|
|
89
|
+
{/if}
|
|
92
90
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
91
|
+
<div class="flex flex-col gap-2 self-center">
|
|
92
|
+
{#if title}
|
|
93
|
+
<Text {size} fontWeight={children ? 'bold' : undefined}>{title}</Text>
|
|
94
|
+
{/if}
|
|
95
|
+
{#if children}
|
|
96
|
+
{@render children()}
|
|
97
|
+
{/if}
|
|
98
|
+
</div>
|
|
99
|
+
</div>
|
|
100
|
+
{#if closable || onClose}
|
|
101
|
+
<div>
|
|
102
|
+
<CloseButton onclick={handleClose} />
|
|
103
|
+
</div>
|
|
104
|
+
{/if}
|
|
105
|
+
</div>
|
|
106
|
+
</CardBody>
|
|
107
|
+
</Card>
|
|
110
108
|
{/if}
|
|
@@ -1,34 +1,34 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
2
|
+
import { withChildrenSnippets } from '../../common/use-child.svelte.js';
|
|
3
|
+
import Scrollable from '../Scrollable/Scrollable.svelte';
|
|
4
|
+
import { ChildKey } from '../../constants.js';
|
|
5
|
+
import { cleanClass } from '../../utils.js';
|
|
6
|
+
import type { Snippet } from 'svelte';
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
8
|
+
type Props = {
|
|
9
|
+
class?: string;
|
|
10
|
+
children?: Snippet;
|
|
11
|
+
};
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
const { class: className, children }: Props = $props();
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
const { getChildren: getChildSnippet } = withChildrenSnippets(ChildKey.AppShell);
|
|
16
|
+
const header = $derived(getChildSnippet(ChildKey.AppShellHeader));
|
|
17
|
+
const sidebar = $derived(getChildSnippet(ChildKey.AppShellSidebar));
|
|
18
18
|
</script>
|
|
19
19
|
|
|
20
20
|
<div class={cleanClass('flex h-dvh flex-col overflow-hidden', className)}>
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
21
|
+
{#if header}
|
|
22
|
+
<header class="border-b">
|
|
23
|
+
{@render header?.snippet()}
|
|
24
|
+
</header>
|
|
25
|
+
{/if}
|
|
26
|
+
<div class="relative flex w-full grow overflow-y-auto">
|
|
27
|
+
{#if sidebar}
|
|
28
|
+
{@render sidebar?.snippet()}
|
|
29
|
+
{/if}
|
|
30
|
+
<Scrollable class="grow" resetOnNavigate>
|
|
31
|
+
{@render children?.()}
|
|
32
|
+
</Scrollable>
|
|
33
|
+
</div>
|
|
34
34
|
</div>
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
import { ChildKey } from '../../constants.js';
|
|
3
|
+
import Child from '../../internal/Child.svelte';
|
|
4
|
+
import type { Snippet } from 'svelte';
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
type Props = {
|
|
7
|
+
children: Snippet;
|
|
8
|
+
};
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
let { children }: Props = $props();
|
|
11
11
|
</script>
|
|
12
12
|
|
|
13
13
|
<Child for={ChildKey.AppShell} as={ChildKey.AppShellHeader}>
|
|
14
|
-
|
|
14
|
+
{@render children?.()}
|
|
15
15
|
</Child>
|
|
@@ -1,27 +1,27 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
2
|
+
import Scrollable from '../Scrollable/Scrollable.svelte';
|
|
3
|
+
import { ChildKey } from '../../constants.js';
|
|
4
|
+
import Child from '../../internal/Child.svelte';
|
|
5
|
+
import { cleanClass } from '../../utils.js';
|
|
6
|
+
import { type Snippet } from 'svelte';
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
8
|
+
type Props = {
|
|
9
|
+
class?: string;
|
|
10
|
+
children: Snippet;
|
|
11
|
+
open?: boolean;
|
|
12
|
+
};
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
let { class: className, children, open = $bindable(true) }: Props = $props();
|
|
15
15
|
</script>
|
|
16
16
|
|
|
17
17
|
<Child for={ChildKey.AppShell} as={ChildKey.AppShellSidebar}>
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
18
|
+
<Scrollable
|
|
19
|
+
class={cleanClass(
|
|
20
|
+
'bg-light text-dark absolute shrink-0 border-e shadow-lg transition-all duration-200 md:relative',
|
|
21
|
+
open ? 'w-[min(100vw,16rem)]' : 'w-[0px]',
|
|
22
|
+
className,
|
|
23
|
+
)}
|
|
24
|
+
>
|
|
25
|
+
{@render children?.()}
|
|
26
|
+
</Scrollable>
|
|
27
27
|
</Child>
|
|
@@ -1,44 +1,38 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
|
|
2
|
+
import type { Snippet } from 'svelte';
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
4
|
+
interface Props {
|
|
5
|
+
title?: string | undefined;
|
|
6
|
+
description?: string | undefined;
|
|
7
|
+
scrollbar?: boolean;
|
|
8
|
+
buttons?: Snippet;
|
|
9
|
+
children?: Snippet;
|
|
10
|
+
}
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
title = undefined,
|
|
14
|
-
description = undefined,
|
|
15
|
-
scrollbar = true,
|
|
16
|
-
buttons,
|
|
17
|
-
children,
|
|
18
|
-
}: Props = $props();
|
|
12
|
+
let { title = undefined, description = undefined, scrollbar = true, buttons, children }: Props = $props();
|
|
19
13
|
|
|
20
|
-
|
|
21
|
-
|
|
14
|
+
let scrollbarClass = $derived(scrollbar ? 'immich-scrollbar p-2 pb-8' : 'scrollbar-hidden');
|
|
15
|
+
let hasTitleClass = $derived(title ? 'top-16 h-[calc(100%-(--spacing(16)))]' : 'top-0 h-full');
|
|
22
16
|
</script>
|
|
23
17
|
|
|
24
18
|
<section class="relative">
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
19
|
+
{#if title || buttons}
|
|
20
|
+
<div
|
|
21
|
+
class="dark:border-immich-neutral dark:text-immich-dark-fg absolute flex h-16 w-full place-items-center justify-between border-b p-4"
|
|
22
|
+
>
|
|
23
|
+
<div class="flex items-center gap-2">
|
|
24
|
+
{#if title}
|
|
25
|
+
<div class="font-medium" tabindex="-1">{title}</div>
|
|
26
|
+
{/if}
|
|
27
|
+
{#if description}
|
|
28
|
+
<p class="text-sm text-gray-400 dark:text-gray-600">{description}</p>
|
|
29
|
+
{/if}
|
|
30
|
+
</div>
|
|
31
|
+
{@render buttons?.()}
|
|
32
|
+
</div>
|
|
33
|
+
{/if}
|
|
40
34
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
35
|
+
<div class="{scrollbarClass} scrollbar-stable absolute {hasTitleClass} w-full overflow-y-auto">
|
|
36
|
+
{@render children?.()}
|
|
37
|
+
</div>
|
|
44
38
|
</section>
|
|
@@ -1,66 +1,56 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
import type { Size } from '../../types.js';
|
|
3
|
+
import { tv } from 'tailwind-variants';
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
| 'red'
|
|
11
|
-
| 'yellow'
|
|
12
|
-
| 'blue'
|
|
13
|
-
| 'green'
|
|
14
|
-
| 'purple'
|
|
15
|
-
| 'orange'
|
|
16
|
-
| 'gray'
|
|
17
|
-
| 'amber';
|
|
18
|
-
name: string;
|
|
19
|
-
};
|
|
5
|
+
type Props = {
|
|
6
|
+
size?: Size;
|
|
7
|
+
color?: 'primary' | 'pink' | 'red' | 'yellow' | 'blue' | 'green' | 'purple' | 'orange' | 'gray' | 'amber';
|
|
8
|
+
name: string;
|
|
9
|
+
};
|
|
20
10
|
|
|
21
|
-
|
|
11
|
+
const { color = 'primary', size = 'medium', name }: Props = $props();
|
|
22
12
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
13
|
+
const styles = tv({
|
|
14
|
+
base: 'flex h-full w-full items-center justify-center font-medium select-none',
|
|
15
|
+
variants: {
|
|
16
|
+
size: {
|
|
17
|
+
tiny: 'h-5 w-5 text-xs',
|
|
18
|
+
small: 'h-7 w-7 text-sm',
|
|
19
|
+
medium: 'h-10 w-10 text-base',
|
|
20
|
+
large: 'h-12 w-12 text-lg',
|
|
21
|
+
giant: 'h-16 w-16 text-xl',
|
|
22
|
+
},
|
|
23
|
+
color: {
|
|
24
|
+
primary: 'bg-primary text-light',
|
|
25
|
+
pink: 'text-light bg-pink-400',
|
|
26
|
+
red: 'text-light bg-red-500',
|
|
27
|
+
yellow: 'text-light bg-yellow-500',
|
|
28
|
+
purple: 'text-dark bg-purple-600',
|
|
29
|
+
orange: 'text-light bg-orange-600',
|
|
30
|
+
gray: 'text-dark bg-gray-600',
|
|
31
|
+
amber: 'text-light bg-amber-600',
|
|
32
|
+
blue: 'text-dark bg-blue-500',
|
|
33
|
+
green: 'text-dark bg-green-600',
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
});
|
|
47
37
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
38
|
+
const wrapper = tv({
|
|
39
|
+
base: 'overflow-hidden rounded-full shadow-md',
|
|
40
|
+
});
|
|
51
41
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
42
|
+
const getInitials = (name: string) => {
|
|
43
|
+
return name
|
|
44
|
+
.split(' ')
|
|
45
|
+
.map((part) => part.at(0))
|
|
46
|
+
.join('')
|
|
47
|
+
.substr(0, 2)
|
|
48
|
+
.toUpperCase();
|
|
49
|
+
};
|
|
60
50
|
|
|
61
|
-
|
|
51
|
+
const initials = $derived(getInitials(name));
|
|
62
52
|
</script>
|
|
63
53
|
|
|
64
54
|
<figure class={wrapper()}>
|
|
65
|
-
|
|
55
|
+
<span class={styles({ size, color })}>{initials}</span>
|
|
66
56
|
</figure>
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
import Button from '../../internal/Button.svelte';
|
|
3
|
+
import type { ButtonProps } from '../../types.js';
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
let { ref = $bindable(null), ...props }: ButtonProps = $props();
|
|
6
6
|
</script>
|
|
7
7
|
|
|
8
8
|
<Button bind:ref {...props} />
|