@immich/ui 0.21.1 → 0.22.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/dist/common/context.svelte.d.ts +2 -1
- package/dist/common/context.svelte.js +2 -2
- package/dist/components/AppShell/AppShellSidebar.svelte +1 -1
- package/dist/components/AppShell/PageLayout.svelte +1 -1
- package/dist/components/Avatar/Avatar.svelte +10 -10
- package/dist/components/Card/Card.svelte +1 -1
- package/dist/components/Code/Code.svelte +3 -3
- package/dist/components/Container/Container.svelte +4 -4
- package/dist/components/Form/Checkbox.svelte +8 -2
- package/dist/components/Form/Input.svelte +10 -3
- package/dist/components/Heading/Heading.svelte +1 -1
- package/dist/components/Kbd/Kbd.svelte +1 -1
- package/dist/components/LoadingSpinner/LoadingSpinner.svelte +1 -1
- package/dist/components/Logo/Logo.svelte +1 -1
- package/dist/components/Modal/Modal.svelte +9 -9
- package/dist/components/Navbar/NavbarItem.svelte +2 -2
- package/dist/components/SupporterBadge/SupporterBadge.svelte +1 -1
- package/dist/components/Switch/Switch.svelte +13 -4
- package/dist/components/Text/Text.svelte +4 -2
- package/dist/components/Text/Text.svelte.d.ts +2 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.js +0 -2
- package/dist/internal/Button.svelte +7 -7
- package/dist/internal/Select.svelte +3 -3
- package/dist/styles.d.ts +2 -70
- package/dist/theme/default.css +23 -4
- package/dist/types.d.ts +1 -0
- package/package.json +6 -5
- package/dist/theme/default.d.ts +0 -13
- package/dist/theme/default.js +0 -16
|
@@ -3,7 +3,8 @@ export declare const setFieldContext: (field: FieldContext) => FieldContext;
|
|
|
3
3
|
export declare const hasFieldContext: () => boolean;
|
|
4
4
|
export declare const getFieldContext: () => {
|
|
5
5
|
label: string | undefined;
|
|
6
|
-
|
|
6
|
+
description: string | undefined;
|
|
7
|
+
color: "primary" | "secondary" | "success" | "danger" | "warning" | "info" | "muted";
|
|
7
8
|
invalid: boolean;
|
|
8
9
|
readOnly: boolean;
|
|
9
10
|
required: boolean;
|
|
@@ -4,6 +4,6 @@ const fieldKey = Symbol(withPrefix('field'));
|
|
|
4
4
|
export const setFieldContext = (field) => setContext(fieldKey, field);
|
|
5
5
|
export const hasFieldContext = () => hasContext(fieldKey);
|
|
6
6
|
export const getFieldContext = () => {
|
|
7
|
-
const { label, color = 'secondary', invalid = false, readOnly = false, required = false, disabled = false, } = getContext(fieldKey) || {};
|
|
8
|
-
return { label, color, invalid, readOnly, required, disabled };
|
|
7
|
+
const { label, color = 'secondary', invalid = false, readOnly = false, required = false, disabled = false, description, } = getContext(fieldKey) || {};
|
|
8
|
+
return { label, description, color, invalid, readOnly, required, disabled };
|
|
9
9
|
};
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
<Child for={ChildKey.AppShell} as={ChildKey.AppShellSidebar}>
|
|
18
18
|
<Scrollable
|
|
19
19
|
class={cleanClass(
|
|
20
|
-
'
|
|
20
|
+
'bg-light text-dark relative shrink-0 transition-all duration-200',
|
|
21
21
|
open ? 'w-[min(100vw,16rem)]' : 'w-[0px]',
|
|
22
22
|
className,
|
|
23
23
|
)}
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
}: Props = $props();
|
|
19
19
|
|
|
20
20
|
let scrollbarClass = $derived(scrollbar ? 'immich-scrollbar p-2 pb-8' : 'scrollbar-hidden');
|
|
21
|
-
let hasTitleClass = $derived(title ? 'top-16 h-[calc(100%-
|
|
21
|
+
let hasTitleClass = $derived(title ? 'top-16 h-[calc(100%-(--spacing(16)))]' : 'top-0 h-full');
|
|
22
22
|
</script>
|
|
23
23
|
|
|
24
24
|
<section class="relative">
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
const { color = 'primary', size = 'medium', name }: Props = $props();
|
|
22
22
|
|
|
23
23
|
const styles = tv({
|
|
24
|
-
base: 'flex h-full w-full
|
|
24
|
+
base: 'flex h-full w-full items-center justify-center font-medium select-none',
|
|
25
25
|
variants: {
|
|
26
26
|
size: {
|
|
27
27
|
tiny: 'h-5 w-5 text-xs',
|
|
@@ -32,15 +32,15 @@
|
|
|
32
32
|
},
|
|
33
33
|
color: {
|
|
34
34
|
primary: 'bg-primary text-light',
|
|
35
|
-
pink: 'bg-pink-400
|
|
36
|
-
red: 'bg-red-500
|
|
37
|
-
yellow: 'bg-yellow-500
|
|
38
|
-
purple: 'bg-purple-600
|
|
39
|
-
orange: 'bg-orange-600
|
|
40
|
-
gray: 'bg-gray-600
|
|
41
|
-
amber: 'bg-amber-600
|
|
42
|
-
blue: 'bg-blue-500
|
|
43
|
-
green: 'bg-green-600
|
|
35
|
+
pink: 'text-light bg-pink-400',
|
|
36
|
+
red: 'text-light bg-red-500',
|
|
37
|
+
yellow: 'text-light bg-yellow-500',
|
|
38
|
+
purple: 'text-dark bg-purple-600',
|
|
39
|
+
orange: 'text-light bg-orange-600',
|
|
40
|
+
gray: 'text-dark bg-gray-600',
|
|
41
|
+
amber: 'text-light bg-amber-600',
|
|
42
|
+
blue: 'text-dark bg-blue-500',
|
|
43
|
+
green: 'text-dark bg-green-600',
|
|
44
44
|
},
|
|
45
45
|
},
|
|
46
46
|
});
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
variants: {
|
|
49
49
|
color: {
|
|
50
50
|
primary: 'bg-primary/25 dark:bg-primary/25',
|
|
51
|
-
secondary: 'bg-gray-50
|
|
51
|
+
secondary: 'text-dark bg-gray-50 dark:bg-neutral-900 dark:text-white',
|
|
52
52
|
success: 'bg-success/15 dark:bg-success/30',
|
|
53
53
|
danger: 'bg-danger/15 dark:bg-danger/50',
|
|
54
54
|
warning: 'bg-warning/25 dark:bg-warning/50',
|
|
@@ -42,9 +42,9 @@
|
|
|
42
42
|
|
|
43
43
|
filledColor: {
|
|
44
44
|
false: '',
|
|
45
|
-
muted: 'bg-gray-600
|
|
46
|
-
primary: '
|
|
47
|
-
secondary: 'bg-gray-700
|
|
45
|
+
muted: 'text-light bg-gray-600 dark:bg-gray-800',
|
|
46
|
+
primary: 'text-primary dark:bg-primary/20 bg-gray-200 dark:text-gray-200',
|
|
47
|
+
secondary: 'text-light bg-gray-700 dark:bg-gray-200',
|
|
48
48
|
success: 'bg-success text-light',
|
|
49
49
|
danger: 'bg-danger text-light',
|
|
50
50
|
warning: 'bg-warning text-light',
|
|
@@ -18,10 +18,10 @@
|
|
|
18
18
|
variants: {
|
|
19
19
|
size: {
|
|
20
20
|
tiny: 'max-w-lg',
|
|
21
|
-
small: 'max-w-
|
|
22
|
-
medium: 'max-w-
|
|
23
|
-
large: 'max-w-
|
|
24
|
-
giant: 'max-w-
|
|
21
|
+
small: 'max-w-(--breakpoint-sm)',
|
|
22
|
+
medium: 'max-w-(--breakpoint-md)',
|
|
23
|
+
large: 'max-w-(--breakpoint-lg)',
|
|
24
|
+
giant: 'max-w-(--breakpoint-xl)',
|
|
25
25
|
full: 'w-full',
|
|
26
26
|
},
|
|
27
27
|
},
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { getFieldContext } from '../../common/context.svelte.js';
|
|
3
3
|
import Icon from '../Icon/Icon.svelte';
|
|
4
4
|
import Label from '../Label/Label.svelte';
|
|
5
|
+
import Text from '../Text/Text.svelte';
|
|
5
6
|
import type { Color, Shape, Size } from '../../types.js';
|
|
6
7
|
import { cleanClass, generateId } from '../../utils.js';
|
|
7
8
|
import { mdiCheck, mdiMinus } from '@mdi/js';
|
|
@@ -24,11 +25,11 @@
|
|
|
24
25
|
...restProps
|
|
25
26
|
}: CheckboxProps = $props();
|
|
26
27
|
|
|
27
|
-
const { readOnly, required, invalid, disabled, label, ...labelProps } =
|
|
28
|
+
const { readOnly, required, invalid, disabled, label, description, ...labelProps } =
|
|
28
29
|
$derived(getFieldContext());
|
|
29
30
|
|
|
30
31
|
const containerStyles = tv({
|
|
31
|
-
base: 'ring-offset-background focus-visible:ring-ring peer box-content overflow-hidden border-2 focus-visible:
|
|
32
|
+
base: 'ring-offset-background focus-visible:ring-ring peer data-[state=checked]:bg-primary box-content overflow-hidden border-2 focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50 data-[disabled=true]:cursor-not-allowed data-[disabled=true]:opacity-50',
|
|
32
33
|
variants: {
|
|
33
34
|
shape: {
|
|
34
35
|
rectangle: 'rounded-none',
|
|
@@ -79,11 +80,15 @@
|
|
|
79
80
|
const id = generateId();
|
|
80
81
|
const inputId = `input-${id}`;
|
|
81
82
|
const labelId = `label-${id}`;
|
|
83
|
+
const descriptionId = $derived(description ? `description-${id}` : undefined);
|
|
82
84
|
</script>
|
|
83
85
|
|
|
84
86
|
<div class="flex flex-col gap-1">
|
|
85
87
|
{#if label}
|
|
86
88
|
<Label id={labelId} for={inputId} {label} {...labelProps} />
|
|
89
|
+
{#if description}
|
|
90
|
+
<Text color="secondary" size="small" id={descriptionId}>{description}</Text>
|
|
91
|
+
{/if}
|
|
87
92
|
{/if}
|
|
88
93
|
|
|
89
94
|
<CheckboxPrimitive.Root
|
|
@@ -101,6 +106,7 @@
|
|
|
101
106
|
disabled={disabled || readOnly}
|
|
102
107
|
{required}
|
|
103
108
|
aria-readonly={disabled || readOnly}
|
|
109
|
+
aria-describedby={descriptionId}
|
|
104
110
|
{...restProps}
|
|
105
111
|
>
|
|
106
112
|
{#snippet children({ checked, indeterminate })}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import { getFieldContext } from '../../common/context.svelte.js';
|
|
3
3
|
import Label from '../Label/Label.svelte';
|
|
4
|
+
import Text from '../Text/Text.svelte';
|
|
4
5
|
import type { InputProps } from '../../types.js';
|
|
5
6
|
import { cleanClass, generateId } from '../../utils.js';
|
|
6
7
|
import { tv } from 'tailwind-variants';
|
|
@@ -15,11 +16,11 @@
|
|
|
15
16
|
...restProps
|
|
16
17
|
}: InputProps = $props();
|
|
17
18
|
|
|
18
|
-
const { label, readOnly, required, invalid, disabled, ...labelProps } =
|
|
19
|
+
const { label, description, readOnly, required, invalid, disabled, ...labelProps } =
|
|
19
20
|
$derived(getFieldContext());
|
|
20
21
|
|
|
21
22
|
const inputStyles = tv({
|
|
22
|
-
base: 'w-full bg-gray-200 outline-none disabled:cursor-not-allowed disabled:bg-gray-300 disabled:text-gray-400
|
|
23
|
+
base: 'aria-readonly:text-dark/50 dark:aria-readonly:text-dark/75 w-full bg-gray-200 outline-none disabled:cursor-not-allowed disabled:bg-gray-300 disabled:text-gray-400 dark:bg-gray-600 dark:disabled:bg-gray-800 dark:disabled:text-gray-200',
|
|
23
24
|
variants: {
|
|
24
25
|
shape: {
|
|
25
26
|
rectangle: 'rounded-none',
|
|
@@ -53,7 +54,7 @@
|
|
|
53
54
|
giant: 'text-xl',
|
|
54
55
|
},
|
|
55
56
|
invalid: {
|
|
56
|
-
true: 'border
|
|
57
|
+
true: 'border-danger/80 border',
|
|
57
58
|
false: '',
|
|
58
59
|
},
|
|
59
60
|
},
|
|
@@ -62,6 +63,7 @@
|
|
|
62
63
|
const id = generateId();
|
|
63
64
|
const inputId = `input-${id}`;
|
|
64
65
|
const labelId = `label-${id}`;
|
|
66
|
+
const descriptionId = $derived(description ? `description-${id}` : undefined);
|
|
65
67
|
</script>
|
|
66
68
|
|
|
67
69
|
<div class="flex w-full flex-col gap-1" bind:this={containerRef}>
|
|
@@ -69,6 +71,10 @@
|
|
|
69
71
|
<Label id={labelId} for={inputId} {label} {...labelProps} />
|
|
70
72
|
{/if}
|
|
71
73
|
|
|
74
|
+
{#if description}
|
|
75
|
+
<Text color="secondary" size="small" id={descriptionId}>{description}</Text>
|
|
76
|
+
{/if}
|
|
77
|
+
|
|
72
78
|
<div class={cleanClass('relative w-full', label && 'mt-1.5')}>
|
|
73
79
|
<input
|
|
74
80
|
id={inputId}
|
|
@@ -77,6 +83,7 @@
|
|
|
77
83
|
aria-required={required}
|
|
78
84
|
{disabled}
|
|
79
85
|
aria-disabled={disabled}
|
|
86
|
+
aria-describedby={descriptionId}
|
|
80
87
|
readonly={readOnly}
|
|
81
88
|
aria-readonly={readOnly}
|
|
82
89
|
class={cleanClass(
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
const { class: className, size = 'small', children, ...restProps }: Props = $props();
|
|
16
16
|
|
|
17
17
|
const styles = tv({
|
|
18
|
-
base: 'flex flex-col rounded-md border border-b-2
|
|
18
|
+
base: 'bg-subtle text-dark flex flex-col rounded-md border border-b-2 px-1 font-mono shadow',
|
|
19
19
|
variants: {
|
|
20
20
|
size: {
|
|
21
21
|
tiny: 'text-xs',
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
let { size = 'medium', color = 'primary', class: className }: Props = $props();
|
|
13
13
|
|
|
14
14
|
const styles = tv({
|
|
15
|
-
base: 'animate-spin
|
|
15
|
+
base: 'fill-primary animate-spin text-gray-400 dark:text-gray-600',
|
|
16
16
|
variants: {
|
|
17
17
|
size: {
|
|
18
18
|
tiny: 'h-3',
|
|
@@ -37,14 +37,14 @@
|
|
|
37
37
|
}: Props = $props();
|
|
38
38
|
|
|
39
39
|
const modalStyles = tv({
|
|
40
|
-
base: 'flex rounded-none border
|
|
40
|
+
base: 'bg-light dark:bg-subtle border-subtle shadow-primary/20 flex rounded-none border shadow-sm sm:rounded-2xl dark:border-white/10',
|
|
41
41
|
variants: {
|
|
42
42
|
size: {
|
|
43
43
|
tiny: 'h-full sm:h-min md:max-w-sm',
|
|
44
44
|
small: 'h-full sm:h-min md:max-w-md',
|
|
45
|
-
medium: 'h-full sm:h-min md:max-w-
|
|
46
|
-
large: 'h-full sm:h-min md:max-w-
|
|
47
|
-
giant: 'h-full sm:h-min md:max-w-
|
|
45
|
+
medium: 'h-full sm:h-min md:max-w-(--breakpoint-sm)',
|
|
46
|
+
large: 'h-full sm:h-min md:max-w-(--breakpoint-md)',
|
|
47
|
+
giant: 'h-full sm:h-min md:max-w-(--breakpoint-lg)',
|
|
48
48
|
full: 'h-full w-full',
|
|
49
49
|
},
|
|
50
50
|
},
|
|
@@ -69,28 +69,28 @@
|
|
|
69
69
|
'absolute start-0 top-0 flex h-dvh w-screen items-center justify-center overflow-hidden sm:p-4',
|
|
70
70
|
)}
|
|
71
71
|
>
|
|
72
|
-
<div class={cleanClass('flex h-full w-full flex-col items-center justify-center
|
|
72
|
+
<div class={cleanClass('flex h-full w-full flex-col items-center justify-center')}>
|
|
73
73
|
<Card class={cleanClass(modalStyles({ size }), className)}>
|
|
74
|
-
<CardHeader class="border-b border-gray-
|
|
74
|
+
<CardHeader class="border-b border-gray-200 px-5 py-3 dark:border-white/10">
|
|
75
75
|
<div class="flex items-center justify-between gap-2">
|
|
76
76
|
{#if typeof icon === 'string'}
|
|
77
77
|
<Icon {icon} size="1.5rem" aria-hidden />
|
|
78
78
|
{:else if icon}
|
|
79
79
|
<Logo variant="icon" size="tiny" />
|
|
80
80
|
{/if}
|
|
81
|
-
<CardTitle tag="
|
|
81
|
+
<CardTitle tag="p" class="text-dark/90 grow text-lg font-semibold">{title}</CardTitle>
|
|
82
82
|
<Dialog.Close>
|
|
83
83
|
<CloseButton onclick={() => onChange(false)} class="-me-2" />
|
|
84
84
|
</Dialog.Close>
|
|
85
85
|
</div>
|
|
86
86
|
</CardHeader>
|
|
87
87
|
|
|
88
|
-
<CardBody class="grow
|
|
88
|
+
<CardBody class="grow px-5">
|
|
89
89
|
{@render bodyChildren?.snippet()}
|
|
90
90
|
</CardBody>
|
|
91
91
|
|
|
92
92
|
{#if footerChildren}
|
|
93
|
-
<CardFooter class="border-t border-gray-
|
|
93
|
+
<CardFooter class="border-t border-gray-200 dark:border-white/10">
|
|
94
94
|
{@render footerChildren.snippet()}
|
|
95
95
|
</CardFooter>
|
|
96
96
|
{/if}
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
);
|
|
36
36
|
|
|
37
37
|
const styles = tv({
|
|
38
|
-
base: 'flex w-full place-items-center gap-4 rounded-e-full px-5 transition-[padding] delay-100 duration-100
|
|
38
|
+
base: 'hover:bg-subtle hover:text-primary flex w-full place-items-center gap-4 rounded-e-full px-5 transition-[padding] delay-100 duration-100 group-hover:sm:px-5',
|
|
39
39
|
variants: {
|
|
40
40
|
active: {
|
|
41
41
|
true: 'bg-primary/10 text-primary',
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
aria-current={active ? 'page' : undefined}
|
|
56
56
|
class={styles({ active, variant: variant ?? 'default' })}
|
|
57
57
|
>
|
|
58
|
-
<div class="flex w-full place-items-center gap-4 overflow-hidden
|
|
58
|
+
<div class="flex w-full place-items-center gap-4 truncate overflow-hidden">
|
|
59
59
|
{#if iconProps}
|
|
60
60
|
<Icon
|
|
61
61
|
size="1.375em"
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import { getFieldContext } from '../../common/context.svelte.js';
|
|
3
3
|
import Label from '../Label/Label.svelte';
|
|
4
|
+
import Text from '../Text/Text.svelte';
|
|
4
5
|
import type { Color } from '../../types.js';
|
|
5
6
|
import { cleanClass, generateId } from '../../utils.js';
|
|
6
7
|
import { Switch, type WithoutChildrenOrChild } from 'bits-ui';
|
|
@@ -22,7 +23,8 @@
|
|
|
22
23
|
...restProps
|
|
23
24
|
}: Props = $props();
|
|
24
25
|
|
|
25
|
-
const { readOnly, required, disabled, label, ...labelProps } =
|
|
26
|
+
const { readOnly, required, disabled, label, description, ...labelProps } =
|
|
27
|
+
$derived(getFieldContext());
|
|
26
28
|
|
|
27
29
|
const enabled = $derived(checked && !disabled);
|
|
28
30
|
|
|
@@ -52,10 +54,10 @@
|
|
|
52
54
|
});
|
|
53
55
|
|
|
54
56
|
const dot = tv({
|
|
55
|
-
base: 'absolute h-6 w-6 rounded-full transition-transform duration-
|
|
57
|
+
base: 'absolute h-6 w-6 rounded-full transition-transform duration-400',
|
|
56
58
|
variants: {
|
|
57
59
|
checked: {
|
|
58
|
-
true: 'translate-x-6 border border-gray-500/10 shadow-sm dark:border-gray-800/50
|
|
60
|
+
true: 'translate-x-6 border border-gray-500/10 shadow-sm rtl:-translate-x-6 dark:border-gray-800/50',
|
|
59
61
|
false: '',
|
|
60
62
|
},
|
|
61
63
|
fillColor: {
|
|
@@ -72,6 +74,7 @@
|
|
|
72
74
|
|
|
73
75
|
const inputId = `input-${id}`;
|
|
74
76
|
const labelId = `label-${id}`;
|
|
77
|
+
const descriptionId = $derived(description ? `description-${id}` : undefined);
|
|
75
78
|
</script>
|
|
76
79
|
|
|
77
80
|
<Switch.Root
|
|
@@ -83,13 +86,19 @@
|
|
|
83
86
|
class={cleanClass(label && 'w-full', className)}
|
|
84
87
|
aria-readonly={readOnly}
|
|
85
88
|
aria-labelledby={labelId}
|
|
89
|
+
aria-describedby={descriptionId}
|
|
86
90
|
{...restProps}
|
|
87
91
|
>
|
|
88
92
|
<Switch.Thumb>
|
|
89
93
|
{#snippet child()}
|
|
90
94
|
<div class={cleanClass(label && 'flex items-center justify-between gap-1')}>
|
|
91
95
|
{#if label}
|
|
92
|
-
<
|
|
96
|
+
<div class="text-start">
|
|
97
|
+
<Label id={labelId} for={inputId} {label} {...labelProps} />
|
|
98
|
+
{#if description}
|
|
99
|
+
<Text color="secondary" size="small" id={descriptionId}>{description}</Text>
|
|
100
|
+
{/if}
|
|
101
|
+
</div>
|
|
93
102
|
{/if}
|
|
94
103
|
<span class={wrapper({ disabled })}>
|
|
95
104
|
<span class={bar({ fillColor: enabled ? color : 'default' })}> </span>
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import type { Size, TextColor } from '../../types.js';
|
|
3
3
|
import { cleanClass } from '../../utils.js';
|
|
4
4
|
import type { Snippet } from 'svelte';
|
|
5
|
+
import type { HTMLAttributes } from 'svelte/elements';
|
|
5
6
|
import { tv } from 'tailwind-variants';
|
|
6
7
|
|
|
7
8
|
type Props = {
|
|
@@ -11,7 +12,7 @@
|
|
|
11
12
|
children: Snippet;
|
|
12
13
|
variant?: 'italic';
|
|
13
14
|
fontWeight?: 'light' | 'normal' | 'semi-bold' | 'bold';
|
|
14
|
-
}
|
|
15
|
+
} & HTMLAttributes<HTMLParagraphElement>;
|
|
15
16
|
|
|
16
17
|
const {
|
|
17
18
|
color,
|
|
@@ -20,6 +21,7 @@
|
|
|
20
21
|
fontWeight = 'normal',
|
|
21
22
|
children,
|
|
22
23
|
class: className,
|
|
24
|
+
...restProps
|
|
23
25
|
}: Props = $props();
|
|
24
26
|
|
|
25
27
|
const styles = tv({
|
|
@@ -56,6 +58,6 @@
|
|
|
56
58
|
});
|
|
57
59
|
</script>
|
|
58
60
|
|
|
59
|
-
<p class={cleanClass(styles({ color, size, fontWeight, variant }), className)}>
|
|
61
|
+
<p class={cleanClass(styles({ color, size, fontWeight, variant }), className)} {...restProps}>
|
|
60
62
|
{@render children()}
|
|
61
63
|
</p>
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Size, TextColor } from '../../types.js';
|
|
2
2
|
import type { Snippet } from 'svelte';
|
|
3
|
+
import type { HTMLAttributes } from 'svelte/elements';
|
|
3
4
|
type Props = {
|
|
4
5
|
color?: TextColor;
|
|
5
6
|
class?: string;
|
|
@@ -7,7 +8,7 @@ type Props = {
|
|
|
7
8
|
children: Snippet;
|
|
8
9
|
variant?: 'italic';
|
|
9
10
|
fontWeight?: 'light' | 'normal' | 'semi-bold' | 'bold';
|
|
10
|
-
}
|
|
11
|
+
} & HTMLAttributes<HTMLParagraphElement>;
|
|
11
12
|
declare const Text: import("svelte").Component<Props, {}, "">;
|
|
12
13
|
type Text = ReturnType<typeof Text>;
|
|
13
14
|
export default Text;
|
package/dist/index.d.ts
CHANGED
|
@@ -7,7 +7,6 @@ export { default as immichLogoStackedLight } from './assets/immich-logo-stacked-
|
|
|
7
7
|
export { default as immichLogoJson } from './assets/immich-logo.json';
|
|
8
8
|
export { default as immichLogo } from './assets/immich-logo.svg';
|
|
9
9
|
export { default as playStoreBadge } from './assets/playstore-badge.png';
|
|
10
|
-
export * from './theme/default.js';
|
|
11
10
|
export { default as Alert } from './components/Alert/Alert.svelte';
|
|
12
11
|
export { default as AppShell } from './components/AppShell/AppShell.svelte';
|
|
13
12
|
export { default as AppShellHeader } from './components/AppShell/AppShellHeader.svelte';
|
package/dist/index.js
CHANGED
|
@@ -8,8 +8,6 @@ export { default as immichLogoStackedLight } from './assets/immich-logo-stacked-
|
|
|
8
8
|
export { default as immichLogoJson } from './assets/immich-logo.json';
|
|
9
9
|
export { default as immichLogo } from './assets/immich-logo.svg';
|
|
10
10
|
export { default as playStoreBadge } from './assets/playstore-badge.png';
|
|
11
|
-
// theme
|
|
12
|
-
export * from './theme/default.js';
|
|
13
11
|
// components
|
|
14
12
|
export { default as Alert } from './components/Alert/Alert.svelte';
|
|
15
13
|
export { default as AppShell } from './components/AppShell/AppShell.svelte';
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
const disabled = $derived((restProps as HTMLButtonAttributes).disabled || loading);
|
|
34
34
|
|
|
35
35
|
const buttonVariants = tv({
|
|
36
|
-
base: 'ring-offset-background focus-visible:ring-ring flex items-center justify-center gap-1
|
|
36
|
+
base: 'ring-offset-background focus-visible:ring-ring flex items-center justify-center gap-1 rounded-md text-sm font-medium whitespace-nowrap transition-colors focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-none',
|
|
37
37
|
variants: {
|
|
38
38
|
disabled: {
|
|
39
39
|
true: 'disabled:pointer-events-none disabled:opacity-50 aria-disabled:opacity-50',
|
|
@@ -84,12 +84,12 @@
|
|
|
84
84
|
info: 'bg-info text-light hover:bg-info/80',
|
|
85
85
|
},
|
|
86
86
|
outlineColor: {
|
|
87
|
-
primary: 'border
|
|
88
|
-
secondary: 'border
|
|
89
|
-
success: 'border
|
|
90
|
-
danger: 'border
|
|
91
|
-
warning: 'border
|
|
92
|
-
info: 'border
|
|
87
|
+
primary: 'border-primary bg-primary/10 text-primary hover:bg-primary/20 border',
|
|
88
|
+
secondary: 'border-dark bg-dark/10 text-dark hover:bg-dark/20 border',
|
|
89
|
+
success: 'border-success bg-success/10 text-success hover:bg-success/20 border',
|
|
90
|
+
danger: 'border-danger bg-danger/10 text-danger hover:bg-danger/20 border',
|
|
91
|
+
warning: 'border-warning bg-warning/10 text-warning hover:bg-warning/20 border',
|
|
92
|
+
info: 'border-info bg-info/10 text-info hover:bg-info/20 border',
|
|
93
93
|
},
|
|
94
94
|
ghostColor: {
|
|
95
95
|
primary: 'text-primary hover:bg-primary/10',
|
|
@@ -116,7 +116,7 @@
|
|
|
116
116
|
<Select.Portal>
|
|
117
117
|
<Select.Content
|
|
118
118
|
bind:ref={contentRef}
|
|
119
|
-
class="max-h-96
|
|
119
|
+
class="bg-light text-dark max-h-96 rounded-xl border py-3 outline-none select-none"
|
|
120
120
|
sideOffset={10}
|
|
121
121
|
>
|
|
122
122
|
<Select.ScrollUpButton class="flex w-full items-center justify-center">
|
|
@@ -126,7 +126,7 @@
|
|
|
126
126
|
{#each options as { value, label, disabled }, i (i + value)}
|
|
127
127
|
<Select.Item
|
|
128
128
|
class={cleanClass(
|
|
129
|
-
'flex h-10 w-full
|
|
129
|
+
'hover:bg-subtle data-[selected]:bg-primary/10 flex h-10 w-full items-center px-5 py-3 text-sm duration-75 outline-none select-none data-disabled:opacity-50',
|
|
130
130
|
disabled ? 'cursor-not-allowed' : 'cursor-pointer',
|
|
131
131
|
)}
|
|
132
132
|
{value}
|
|
@@ -135,7 +135,7 @@
|
|
|
135
135
|
>
|
|
136
136
|
{#snippet children({ selected })}
|
|
137
137
|
<div
|
|
138
|
-
class="flex cursor-pointer items-center justify-center gap-2
|
|
138
|
+
class="flex cursor-pointer items-center justify-center gap-2 text-sm font-medium whitespace-nowrap transition-colors"
|
|
139
139
|
>
|
|
140
140
|
<span>{label}</span>
|
|
141
141
|
</div>
|
package/dist/styles.d.ts
CHANGED
|
@@ -16,41 +16,7 @@ export declare const styles: {
|
|
|
16
16
|
warning: string;
|
|
17
17
|
info: string;
|
|
18
18
|
};
|
|
19
|
-
}, undefined, "",
|
|
20
|
-
size: {
|
|
21
|
-
tiny: string;
|
|
22
|
-
small: string;
|
|
23
|
-
medium: string;
|
|
24
|
-
large: string;
|
|
25
|
-
giant: string;
|
|
26
|
-
};
|
|
27
|
-
color: {
|
|
28
|
-
muted: string;
|
|
29
|
-
primary: string;
|
|
30
|
-
secondary: string;
|
|
31
|
-
success: string;
|
|
32
|
-
danger: string;
|
|
33
|
-
warning: string;
|
|
34
|
-
info: string;
|
|
35
|
-
};
|
|
36
|
-
}, {
|
|
37
|
-
size: {
|
|
38
|
-
tiny: string;
|
|
39
|
-
small: string;
|
|
40
|
-
medium: string;
|
|
41
|
-
large: string;
|
|
42
|
-
giant: string;
|
|
43
|
-
};
|
|
44
|
-
color: {
|
|
45
|
-
muted: string;
|
|
46
|
-
primary: string;
|
|
47
|
-
secondary: string;
|
|
48
|
-
success: string;
|
|
49
|
-
danger: string;
|
|
50
|
-
warning: string;
|
|
51
|
-
info: string;
|
|
52
|
-
};
|
|
53
|
-
}>, {
|
|
19
|
+
}, undefined, "", {
|
|
54
20
|
size: {
|
|
55
21
|
tiny: string;
|
|
56
22
|
small: string;
|
|
@@ -84,39 +50,5 @@ export declare const styles: {
|
|
|
84
50
|
warning: string;
|
|
85
51
|
info: string;
|
|
86
52
|
};
|
|
87
|
-
}, undefined, "",
|
|
88
|
-
size: {
|
|
89
|
-
tiny: string;
|
|
90
|
-
small: string;
|
|
91
|
-
medium: string;
|
|
92
|
-
large: string;
|
|
93
|
-
giant: string;
|
|
94
|
-
};
|
|
95
|
-
color: {
|
|
96
|
-
muted: string;
|
|
97
|
-
primary: string;
|
|
98
|
-
secondary: string;
|
|
99
|
-
success: string;
|
|
100
|
-
danger: string;
|
|
101
|
-
warning: string;
|
|
102
|
-
info: string;
|
|
103
|
-
};
|
|
104
|
-
}, {
|
|
105
|
-
size: {
|
|
106
|
-
tiny: string;
|
|
107
|
-
small: string;
|
|
108
|
-
medium: string;
|
|
109
|
-
large: string;
|
|
110
|
-
giant: string;
|
|
111
|
-
};
|
|
112
|
-
color: {
|
|
113
|
-
muted: string;
|
|
114
|
-
primary: string;
|
|
115
|
-
secondary: string;
|
|
116
|
-
success: string;
|
|
117
|
-
danger: string;
|
|
118
|
-
warning: string;
|
|
119
|
-
info: string;
|
|
120
|
-
};
|
|
121
|
-
}>, unknown, unknown, undefined>>;
|
|
53
|
+
}, undefined, "", unknown, unknown, undefined>>;
|
|
122
54
|
};
|
package/dist/theme/default.css
CHANGED
|
@@ -1,6 +1,17 @@
|
|
|
1
|
-
@
|
|
2
|
-
|
|
3
|
-
@
|
|
1
|
+
@import 'tailwindcss';
|
|
2
|
+
|
|
3
|
+
@theme inline {
|
|
4
|
+
--color-primary: rgb(var(--immich-ui-primary));
|
|
5
|
+
--color-light: rgb(var(--immich-ui-light));
|
|
6
|
+
--color-dark: rgb(var(--immich-ui-dark));
|
|
7
|
+
--color-success: rgb(var(--immich-ui-success));
|
|
8
|
+
--color-danger: rgb(var(--immich-ui-danger));
|
|
9
|
+
--color-warning: rgb(var(--immich-ui-warning));
|
|
10
|
+
--color-info: rgb(var(--immich-ui-info));
|
|
11
|
+
--color-subtle: rgb(var(--immich-ui-gray));
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
@custom-variant dark (&:where(.dark, .dark *));
|
|
4
15
|
|
|
5
16
|
@layer base {
|
|
6
17
|
:root {
|
|
@@ -28,6 +39,14 @@
|
|
|
28
39
|
--immich-ui-info: 121 183 254;
|
|
29
40
|
--immich-ui-gray: 33 33 33;
|
|
30
41
|
|
|
31
|
-
--immich-ui-default-border:
|
|
42
|
+
--immich-ui-default-border: 33 33 33;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
*,
|
|
46
|
+
::after,
|
|
47
|
+
::before,
|
|
48
|
+
::backdrop,
|
|
49
|
+
::file-selector-button {
|
|
50
|
+
border-color: rgb(var(--immich-ui-default-border));
|
|
32
51
|
}
|
|
33
52
|
}
|
package/dist/types.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@immich/ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.22.1",
|
|
4
4
|
"license": "GNU Affero General Public License version 3",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"create": "node scripts/create.js",
|
|
@@ -35,7 +35,6 @@
|
|
|
35
35
|
"types": "./dist/index.d.ts",
|
|
36
36
|
"svelte": "./dist/index.js"
|
|
37
37
|
},
|
|
38
|
-
"./theme/default.js": "./dist/theme/default.js",
|
|
39
38
|
"./theme/default.css": "./dist/theme/default.css"
|
|
40
39
|
},
|
|
41
40
|
"peerDependencies": {
|
|
@@ -46,6 +45,8 @@
|
|
|
46
45
|
"@sveltejs/kit": "^2.13.0",
|
|
47
46
|
"@sveltejs/package": "^2.0.0",
|
|
48
47
|
"@sveltejs/vite-plugin-svelte": "^5.0.2",
|
|
48
|
+
"@tailwindcss/postcss": "^4.1.7",
|
|
49
|
+
"@tailwindcss/vite": "^4.1.7",
|
|
49
50
|
"@types/eslint": "^9.6.0",
|
|
50
51
|
"autoprefixer": "^10.4.20",
|
|
51
52
|
"eslint": "^9.7.0",
|
|
@@ -54,12 +55,12 @@
|
|
|
54
55
|
"globals": "^16.0.0",
|
|
55
56
|
"prettier": "^3.3.2",
|
|
56
57
|
"prettier-plugin-svelte": "^3.2.6",
|
|
57
|
-
"prettier-plugin-tailwindcss": "^0.6.
|
|
58
|
+
"prettier-plugin-tailwindcss": "^0.6.11",
|
|
58
59
|
"publint": "^0.3.0",
|
|
59
60
|
"svelte": "^5.0.0",
|
|
60
61
|
"svelte-check": "^4.0.0",
|
|
61
62
|
"svelte-highlight": "^7.8.0",
|
|
62
|
-
"tailwindcss": "^
|
|
63
|
+
"tailwindcss": "^4.1.7",
|
|
63
64
|
"typescript": "^5.0.0",
|
|
64
65
|
"typescript-eslint": "^8.15.0",
|
|
65
66
|
"vite": "^6.0.3",
|
|
@@ -69,7 +70,7 @@
|
|
|
69
70
|
"@mdi/js": "^7.4.47",
|
|
70
71
|
"bits-ui": "^1.0.0-next.46",
|
|
71
72
|
"tailwind-merge": "^2.5.4",
|
|
72
|
-
"tailwind-variants": "^0.
|
|
73
|
+
"tailwind-variants": "^1.0.0"
|
|
73
74
|
},
|
|
74
75
|
"volta": {
|
|
75
76
|
"node": "22.15.0"
|
package/dist/theme/default.d.ts
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
export declare const tailwindConfig: () => {
|
|
2
|
-
colors: {
|
|
3
|
-
primary: string;
|
|
4
|
-
light: string;
|
|
5
|
-
dark: string;
|
|
6
|
-
success: string;
|
|
7
|
-
danger: string;
|
|
8
|
-
warning: string;
|
|
9
|
-
info: string;
|
|
10
|
-
subtle: string;
|
|
11
|
-
};
|
|
12
|
-
borderColor: ({ theme }: import("tailwindcss/types/config").PluginUtils) => any;
|
|
13
|
-
};
|
package/dist/theme/default.js
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
export const tailwindConfig = () => ({
|
|
2
|
-
colors: {
|
|
3
|
-
primary: 'rgb(var(--immich-ui-primary) / <alpha-value>)',
|
|
4
|
-
light: 'rgb(var(--immich-ui-light) / <alpha-value>)',
|
|
5
|
-
dark: 'rgb(var(--immich-ui-dark) / <alpha-value>)',
|
|
6
|
-
success: 'rgb(var(--immich-ui-success) / <alpha-value>)',
|
|
7
|
-
danger: 'rgb(var(--immich-ui-danger) / <alpha-value>)',
|
|
8
|
-
warning: 'rgb(var(--immich-ui-warning) / <alpha-value>)',
|
|
9
|
-
info: 'rgb(var(--immich-ui-info) / <alpha-value>)',
|
|
10
|
-
subtle: 'rgb(var(--immich-ui-gray) / <alpha-value>)',
|
|
11
|
-
},
|
|
12
|
-
borderColor: ({ theme }) => ({
|
|
13
|
-
...theme('colors'),
|
|
14
|
-
DEFAULT: 'rgb(var(--immich-ui-default-border) / <alpha-value>)',
|
|
15
|
-
}),
|
|
16
|
-
});
|