@immich/ui 0.58.3 → 0.59.0
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/components/AppShell/AppShellSidebar.svelte +18 -8
- package/dist/components/AppShell/AppShellSidebar.svelte.d.ts +1 -0
- package/dist/components/MultiSelect/MultiSelect.svelte +5 -5
- package/dist/components/Navbar/NavbarGroup.svelte +24 -3
- package/dist/components/Navbar/NavbarGroup.svelte.d.ts +7 -0
- package/dist/components/Navbar/NavbarItem.svelte +68 -33
- package/dist/components/Navbar/NavbarItem.svelte.d.ts +3 -11
- package/dist/components/Select/Select.svelte +6 -6
- package/dist/internal/Select.svelte +13 -11
- package/dist/internal/Select.svelte.d.ts +3 -3
- package/dist/services/translation.svelte.d.ts +2 -0
- package/dist/services/translation.svelte.js +2 -0
- package/dist/types.d.ts +17 -4
- package/package.json +1 -1
|
@@ -4,24 +4,34 @@
|
|
|
4
4
|
import Child from '../../internal/Child.svelte';
|
|
5
5
|
import { cleanClass } from '../../utilities/internal.js';
|
|
6
6
|
import { type Snippet } from 'svelte';
|
|
7
|
+
import { tv } from 'tailwind-variants';
|
|
7
8
|
|
|
8
9
|
type Props = {
|
|
9
10
|
class?: string;
|
|
10
11
|
children: Snippet;
|
|
11
12
|
open?: boolean;
|
|
13
|
+
border?: boolean;
|
|
12
14
|
};
|
|
13
15
|
|
|
14
|
-
let { class: className, children, open = $bindable(true) }: Props = $props();
|
|
16
|
+
let { class: className, border = true, children, open = $bindable(true) }: Props = $props();
|
|
17
|
+
|
|
18
|
+
const styles = tv({
|
|
19
|
+
base: 'bg-light text-dark absolute shrink-0 transition-all duration-200 md:relative',
|
|
20
|
+
variants: {
|
|
21
|
+
border: {
|
|
22
|
+
true: 'border-e shadow-lg',
|
|
23
|
+
false: '',
|
|
24
|
+
},
|
|
25
|
+
open: {
|
|
26
|
+
true: `${zIndex.AppShellSidebar} w-[min(100vw,16rem)]`,
|
|
27
|
+
false: 'w-0 border-e-0',
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
});
|
|
15
31
|
</script>
|
|
16
32
|
|
|
17
33
|
<Child for={ChildKey.AppShell} as={ChildKey.AppShellSidebar}>
|
|
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 ? `${zIndex.AppShellSidebar} w-[min(100vw,16rem)]` : 'w-0 border-e-0',
|
|
22
|
-
className,
|
|
23
|
-
)}
|
|
24
|
-
>
|
|
34
|
+
<Scrollable class={cleanClass(styles({ border, open }), className)}>
|
|
25
35
|
{@render children?.()}
|
|
26
36
|
</Scrollable>
|
|
27
37
|
</Child>
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
<script lang="ts" generics="T extends string">
|
|
2
2
|
import InternalSelect from '../../internal/Select.svelte';
|
|
3
|
-
import type { MultiSelectProps,
|
|
3
|
+
import type { MultiSelectProps, SelectOption } from '../../types.js';
|
|
4
4
|
|
|
5
|
-
let { onChange,
|
|
5
|
+
let { onChange, onSelect, values = $bindable([]), ...restProps }: MultiSelectProps<T> = $props();
|
|
6
6
|
|
|
7
7
|
const handleChange = (values: T[]) => {
|
|
8
8
|
onChange?.(values);
|
|
9
9
|
};
|
|
10
10
|
|
|
11
|
-
const
|
|
12
|
-
|
|
11
|
+
const handleSelect = (items: SelectOption<T>[]) => {
|
|
12
|
+
onSelect?.(items);
|
|
13
13
|
};
|
|
14
14
|
</script>
|
|
15
15
|
|
|
16
|
-
<InternalSelect multiple bind:values
|
|
16
|
+
<InternalSelect multiple bind:values onSelect={handleSelect} onChange={handleChange} {...restProps} />
|
|
@@ -1,11 +1,32 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
+
import Text from '../Text/Text.svelte';
|
|
3
|
+
import type { FontWeight, NavbarVariant, Size, TextColor } from '../../types.js';
|
|
4
|
+
import { cleanClass } from '../../utilities/internal.js';
|
|
5
|
+
import { tv } from 'tailwind-variants';
|
|
6
|
+
|
|
2
7
|
type Props = {
|
|
3
8
|
title: string;
|
|
9
|
+
size?: Size;
|
|
10
|
+
color?: TextColor;
|
|
11
|
+
fontWeight?: FontWeight;
|
|
12
|
+
variant?: NavbarVariant;
|
|
13
|
+
inline?: boolean;
|
|
14
|
+
class?: string;
|
|
4
15
|
};
|
|
5
16
|
|
|
6
|
-
let { title }: Props = $props();
|
|
17
|
+
let { title, size = 'small', variant, fontWeight, color, class: className }: Props = $props();
|
|
18
|
+
|
|
19
|
+
const styles = tv({
|
|
20
|
+
base: 'ps-6 transition-all duration-200',
|
|
21
|
+
variants: {
|
|
22
|
+
variant: {
|
|
23
|
+
compact: 'py-4',
|
|
24
|
+
default: 'py-6',
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
});
|
|
7
28
|
</script>
|
|
8
29
|
|
|
9
|
-
<div class=
|
|
10
|
-
<
|
|
30
|
+
<div class={cleanClass(styles({ variant: variant ?? 'default' }), className)}>
|
|
31
|
+
<Text {color} {size} {fontWeight}>{title}</Text>
|
|
11
32
|
</div>
|
|
@@ -1,5 +1,12 @@
|
|
|
1
|
+
import type { FontWeight, NavbarVariant, Size, TextColor } from '../../types.js';
|
|
1
2
|
type Props = {
|
|
2
3
|
title: string;
|
|
4
|
+
size?: Size;
|
|
5
|
+
color?: TextColor;
|
|
6
|
+
fontWeight?: FontWeight;
|
|
7
|
+
variant?: NavbarVariant;
|
|
8
|
+
inline?: boolean;
|
|
9
|
+
class?: string;
|
|
3
10
|
};
|
|
4
11
|
declare const NavbarGroup: import("svelte").Component<Props, {}, "">;
|
|
5
12
|
type NavbarGroup = ReturnType<typeof NavbarGroup>;
|
|
@@ -2,59 +2,94 @@
|
|
|
2
2
|
import { page } from '$app/state';
|
|
3
3
|
import Icon from '../Icon/Icon.svelte';
|
|
4
4
|
import Link from '../Link/Link.svelte';
|
|
5
|
-
import
|
|
5
|
+
import NavbarItem from './NavbarItem.svelte';
|
|
6
|
+
import { t } from '../../services/translation.svelte.js';
|
|
7
|
+
import type { NavbarProps } from '../../types.js';
|
|
8
|
+
import { cleanClass } from '../../utilities/internal.js';
|
|
9
|
+
import { mdiChevronDown, mdiChevronRight } from '@mdi/js';
|
|
6
10
|
import { tv } from 'tailwind-variants';
|
|
7
11
|
|
|
8
|
-
type Props = {
|
|
9
|
-
title: string;
|
|
10
|
-
href: string;
|
|
11
|
-
active?: boolean;
|
|
12
|
-
variant?: 'compact';
|
|
13
|
-
isActive?: () => boolean;
|
|
14
|
-
icon?: string | IconProps;
|
|
15
|
-
activeIcon?: string | IconProps;
|
|
16
|
-
};
|
|
17
|
-
|
|
18
12
|
const startsWithHref = () => page.url.pathname.startsWith(href);
|
|
19
13
|
|
|
20
|
-
let {
|
|
14
|
+
let {
|
|
15
|
+
href,
|
|
16
|
+
isActive: isActiveOverride,
|
|
17
|
+
title,
|
|
18
|
+
variant,
|
|
19
|
+
active: activeOverride,
|
|
20
|
+
icon,
|
|
21
|
+
activeIcon,
|
|
22
|
+
expanded = $bindable(false),
|
|
23
|
+
items,
|
|
24
|
+
class: className,
|
|
25
|
+
}: NavbarProps = $props();
|
|
21
26
|
|
|
22
|
-
const isActive = isActiveOverride ?? startsWithHref;
|
|
27
|
+
const isActive = $derived(isActiveOverride ?? startsWithHref);
|
|
23
28
|
let active = $derived(activeOverride ?? isActive());
|
|
24
|
-
|
|
25
29
|
const iconProps = $derived(typeof icon === 'string' ? { icon } : icon);
|
|
26
30
|
const activeIconProps = $derived(typeof activeIcon === 'string' ? { icon: activeIcon } : activeIcon);
|
|
27
31
|
|
|
28
32
|
const styles = tv({
|
|
29
|
-
base: 'hover:bg-subtle hover:text-primary flex w-full place-items-center gap-4 rounded-e-full
|
|
33
|
+
base: 'hover:bg-subtle hover:text-primary flex w-full place-items-center gap-4 rounded-e-full ps-5 transition-[padding] delay-100 duration-100',
|
|
30
34
|
variants: {
|
|
31
35
|
active: {
|
|
32
36
|
true: 'bg-primary/10 text-primary',
|
|
33
37
|
false: '',
|
|
34
38
|
},
|
|
35
39
|
variant: {
|
|
36
|
-
default: 'py-3
|
|
37
|
-
compact: 'py-2
|
|
40
|
+
default: 'py-3',
|
|
41
|
+
compact: 'py-2',
|
|
38
42
|
},
|
|
39
43
|
},
|
|
40
44
|
});
|
|
41
45
|
</script>
|
|
42
46
|
|
|
43
|
-
<
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
47
|
+
<div>
|
|
48
|
+
<div class="relative flex items-center">
|
|
49
|
+
{#if items}
|
|
50
|
+
<button
|
|
51
|
+
type="button"
|
|
52
|
+
aria-label={expanded ? t('collapse') : t('expand')}
|
|
53
|
+
class="hover:bg-subtle hover:text-primary absolute me-2 hidden h-full rounded-lg px-0.5 md:block"
|
|
54
|
+
onclick={() => (expanded = !expanded)}
|
|
55
|
+
>
|
|
56
|
+
<Icon
|
|
57
|
+
icon={expanded ? mdiChevronDown : mdiChevronRight}
|
|
58
|
+
size="1em"
|
|
59
|
+
class="shrink-0 delay-100 duration-100 "
|
|
60
|
+
aria-hidden
|
|
61
|
+
/>
|
|
62
|
+
</button>
|
|
57
63
|
{/if}
|
|
58
|
-
<
|
|
64
|
+
<Link
|
|
65
|
+
{href}
|
|
66
|
+
aria-current={active ? 'page' : undefined}
|
|
67
|
+
underline={false}
|
|
68
|
+
class={cleanClass(styles({ active, variant: variant ?? 'default' }), className)}
|
|
69
|
+
>
|
|
70
|
+
<div class="relative flex w-full place-items-center {variant === 'compact' ? 'gap-2' : 'gap-4'}">
|
|
71
|
+
{#if iconProps}
|
|
72
|
+
<Icon
|
|
73
|
+
size="1.375em"
|
|
74
|
+
class="shrink-0"
|
|
75
|
+
aria-hidden={true}
|
|
76
|
+
{...active && activeIconProps ? activeIconProps : iconProps}
|
|
77
|
+
/>
|
|
78
|
+
{/if}
|
|
79
|
+
<span class="truncate text-sm font-medium">{title}</span>
|
|
80
|
+
</div>
|
|
81
|
+
</Link>
|
|
59
82
|
</div>
|
|
60
|
-
|
|
83
|
+
|
|
84
|
+
{#if expanded}
|
|
85
|
+
<div>
|
|
86
|
+
{#if Array.isArray(items)}
|
|
87
|
+
{#each items as { class: className, ...item }, i (i)}
|
|
88
|
+
<NavbarItem {variant} {...item} class={cleanClass('ps-8', className)} />
|
|
89
|
+
{/each}
|
|
90
|
+
{:else if items}
|
|
91
|
+
{@render items()}
|
|
92
|
+
{/if}
|
|
93
|
+
</div>
|
|
94
|
+
{/if}
|
|
95
|
+
</div>
|
|
@@ -1,13 +1,5 @@
|
|
|
1
|
-
import
|
|
2
|
-
type
|
|
3
|
-
|
|
4
|
-
href: string;
|
|
5
|
-
active?: boolean;
|
|
6
|
-
variant?: 'compact';
|
|
7
|
-
isActive?: () => boolean;
|
|
8
|
-
icon?: string | IconProps;
|
|
9
|
-
activeIcon?: string | IconProps;
|
|
10
|
-
};
|
|
11
|
-
declare const NavbarItem: import("svelte").Component<Props, {}, "">;
|
|
1
|
+
import NavbarItem from './NavbarItem.svelte';
|
|
2
|
+
import type { NavbarProps } from '../../types.js';
|
|
3
|
+
declare const NavbarItem: import("svelte").Component<NavbarProps, {}, "expanded">;
|
|
12
4
|
type NavbarItem = ReturnType<typeof NavbarItem>;
|
|
13
5
|
export default NavbarItem;
|
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
<script lang="ts" generics="T extends string">
|
|
2
2
|
import InternalSelect from '../../internal/Select.svelte';
|
|
3
|
-
import type {
|
|
3
|
+
import type { SelectOption, SelectProps } from '../../types.js';
|
|
4
4
|
|
|
5
|
-
let { onChange,
|
|
5
|
+
let { onChange, onSelect, value = $bindable(), ...restProps }: SelectProps<T> = $props();
|
|
6
6
|
|
|
7
|
-
let values = $derived(value ? [
|
|
7
|
+
let values = $derived(value === null || value === undefined ? [] : [value]);
|
|
8
8
|
|
|
9
9
|
const handleChange = (values: T[]) => {
|
|
10
10
|
value = values[0];
|
|
11
11
|
onChange?.(value);
|
|
12
12
|
};
|
|
13
13
|
|
|
14
|
-
const
|
|
15
|
-
|
|
14
|
+
const handleSelect = (items: SelectOption<T>[]) => {
|
|
15
|
+
onSelect?.(items[0]);
|
|
16
16
|
};
|
|
17
17
|
</script>
|
|
18
18
|
|
|
19
|
-
<InternalSelect bind:values onChange={handleChange}
|
|
19
|
+
<InternalSelect bind:values onChange={handleChange} onSelect={handleSelect} {...restProps} />
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
import IconButton from '../components/IconButton/IconButton.svelte';
|
|
5
5
|
import Input from '../components/Input/Input.svelte';
|
|
6
6
|
import { zIndex } from '../constants.js';
|
|
7
|
-
import type { SelectCommonProps,
|
|
7
|
+
import type { SelectCommonProps, SelectOption } from '../types.js';
|
|
8
8
|
import { cleanClass } from '../utilities/internal.js';
|
|
9
9
|
import { mdiArrowDown, mdiArrowUp, mdiCheck, mdiChevronDown } from '@mdi/js';
|
|
10
10
|
import { Select } from 'bits-ui';
|
|
@@ -13,28 +13,28 @@
|
|
|
13
13
|
type Props = {
|
|
14
14
|
multiple?: boolean;
|
|
15
15
|
values: T[];
|
|
16
|
-
asLabel?: (items:
|
|
16
|
+
asLabel?: (items: SelectOption<T>[]) => string;
|
|
17
17
|
onChange?: (values: T[]) => void;
|
|
18
|
-
|
|
18
|
+
onSelect?: (items: SelectOption<T>[]) => void;
|
|
19
19
|
} & SelectCommonProps<T>;
|
|
20
20
|
|
|
21
21
|
let {
|
|
22
|
-
|
|
22
|
+
options: optionsOrItems,
|
|
23
23
|
shape,
|
|
24
24
|
size: initialSize,
|
|
25
25
|
multiple = false,
|
|
26
26
|
values = $bindable([]),
|
|
27
27
|
onChange,
|
|
28
|
-
onItemChange,
|
|
29
|
-
asLabel = (options:
|
|
28
|
+
onSelect: onItemChange,
|
|
29
|
+
asLabel = (options: SelectOption<T>[]) => options.map(({ label }) => label).join(', '),
|
|
30
30
|
placeholder,
|
|
31
31
|
class: className,
|
|
32
32
|
}: Props = $props();
|
|
33
33
|
|
|
34
|
-
const asOptions = (items: string[] |
|
|
34
|
+
const asOptions = (items: string[] | SelectOption<T>[]) => {
|
|
35
35
|
return items.map((item) => {
|
|
36
36
|
if (typeof item === 'string') {
|
|
37
|
-
return { value: item, label: item } as
|
|
37
|
+
return { value: item, label: item } as SelectOption<T>;
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
const label = item.label ?? item.value;
|
|
@@ -45,11 +45,11 @@
|
|
|
45
45
|
const context = getFieldContext();
|
|
46
46
|
const { invalid, disabled, ...labelProps } = $derived(context());
|
|
47
47
|
const size = $derived(initialSize ?? labelProps.size ?? 'small');
|
|
48
|
-
const options = $derived(asOptions(
|
|
48
|
+
const options = $derived(asOptions(optionsOrItems));
|
|
49
49
|
|
|
50
50
|
const findOption = (value: string) => options.find((option) => option.value === value);
|
|
51
51
|
const valuesToOptions = (values: T[]) =>
|
|
52
|
-
values.map(findOption).filter((item): item is
|
|
52
|
+
values.map(findOption).filter((item): item is SelectOption<T> => Boolean(item));
|
|
53
53
|
|
|
54
54
|
const selectedLabel = $derived(asLabel(valuesToOptions(values)));
|
|
55
55
|
|
|
@@ -75,7 +75,9 @@
|
|
|
75
75
|
|
|
76
76
|
const onValueChange = (newValues: string[] | string) => {
|
|
77
77
|
values = (Array.isArray(newValues) ? newValues : [newValues]) as T[];
|
|
78
|
-
const items = values
|
|
78
|
+
const items = values
|
|
79
|
+
.map((value) => findOption(value))
|
|
80
|
+
.filter((item): item is SelectOption<T> => item !== undefined);
|
|
79
81
|
|
|
80
82
|
onChange?.(values);
|
|
81
83
|
onItemChange?.(items);
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import type { SelectCommonProps,
|
|
1
|
+
import type { SelectCommonProps, SelectOption } from '../types.js';
|
|
2
2
|
import { Select } from 'bits-ui';
|
|
3
3
|
declare function $$render<T extends string>(): {
|
|
4
4
|
props: {
|
|
5
5
|
multiple?: boolean;
|
|
6
6
|
values: T[];
|
|
7
|
-
asLabel?: (items:
|
|
7
|
+
asLabel?: (items: SelectOption<T>[]) => string;
|
|
8
8
|
onChange?: (values: T[]) => void;
|
|
9
|
-
|
|
9
|
+
onSelect?: (items: SelectOption<T>[]) => void;
|
|
10
10
|
} & SelectCommonProps<T>;
|
|
11
11
|
exports: {};
|
|
12
12
|
bindings: "values";
|
package/dist/types.d.ts
CHANGED
|
@@ -29,6 +29,19 @@ export type IconLike = string | {
|
|
|
29
29
|
};
|
|
30
30
|
export type MaybeArray<T> = T | T[];
|
|
31
31
|
export type MaybePromise<T> = T | Promise<T>;
|
|
32
|
+
export type NavbarVariant = 'compact';
|
|
33
|
+
export type NavbarProps = {
|
|
34
|
+
title: string;
|
|
35
|
+
href: string;
|
|
36
|
+
active?: boolean;
|
|
37
|
+
variant?: NavbarVariant;
|
|
38
|
+
isActive?: () => boolean;
|
|
39
|
+
icon?: string | IconProps;
|
|
40
|
+
activeIcon?: string | IconProps;
|
|
41
|
+
expanded?: boolean;
|
|
42
|
+
items?: NavbarProps[] | Snippet;
|
|
43
|
+
class?: string;
|
|
44
|
+
};
|
|
32
45
|
export type IconProps = {
|
|
33
46
|
icon: IconLike;
|
|
34
47
|
title?: string;
|
|
@@ -152,13 +165,13 @@ export type TextareaProps = {
|
|
|
152
165
|
shape?: Shape;
|
|
153
166
|
grow?: boolean;
|
|
154
167
|
} & HTMLTextareaAttributes;
|
|
155
|
-
export type
|
|
168
|
+
export type SelectOption<T extends string = string> = {
|
|
156
169
|
label?: string;
|
|
157
170
|
value: T;
|
|
158
171
|
disabled?: boolean;
|
|
159
172
|
};
|
|
160
173
|
export type SelectCommonProps<T extends string> = {
|
|
161
|
-
|
|
174
|
+
options: string[] | SelectOption<T>[];
|
|
162
175
|
size?: Size;
|
|
163
176
|
shape?: Shape;
|
|
164
177
|
placeholder?: string;
|
|
@@ -167,12 +180,12 @@ export type SelectCommonProps<T extends string> = {
|
|
|
167
180
|
export type SelectProps<T extends string> = SelectCommonProps<T> & {
|
|
168
181
|
value?: T;
|
|
169
182
|
onChange?: (value: T) => void;
|
|
170
|
-
|
|
183
|
+
onSelect?: (options: SelectOption<T>) => void;
|
|
171
184
|
};
|
|
172
185
|
export type MultiSelectProps<T extends string> = SelectCommonProps<T> & {
|
|
173
186
|
values?: T[];
|
|
174
187
|
onChange?: (values: T[]) => void;
|
|
175
|
-
|
|
188
|
+
onSelect?: (options: SelectOption<T>[]) => void;
|
|
176
189
|
};
|
|
177
190
|
export type ToastId = {
|
|
178
191
|
id: string;
|