@immich/ui 0.45.1 → 0.47.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.
Files changed (34) hide show
  1. package/dist/components/AnnouncementBanner/AnnouncementBanner.svelte +6 -6
  2. package/dist/components/Badge/Badge.svelte +16 -16
  3. package/dist/components/Card/Card.svelte +13 -9
  4. package/dist/components/Code/Code.svelte +2 -2
  5. package/dist/components/CommandPalette/CommandPaletteContext.svelte +1 -1
  6. package/dist/components/CommandPalette/CommandPaletteItem.svelte +40 -38
  7. package/dist/components/CommandPalette/CommandPaletteItem.svelte.d.ts +2 -2
  8. package/dist/components/ContextMenu/ContextMenu.svelte +5 -5
  9. package/dist/components/Input/Input.svelte +3 -10
  10. package/dist/components/Label/Label.svelte +1 -1
  11. package/dist/components/Modal/Modal.svelte +1 -1
  12. package/dist/components/ProgressBar/ProgressBar.svelte +59 -0
  13. package/dist/components/ProgressBar/ProgressBar.svelte.d.ts +13 -0
  14. package/dist/components/SupporterBadge/SupporterBadge.svelte +2 -1
  15. package/dist/components/Switch/Switch.svelte +8 -8
  16. package/dist/components/Toast/ToastContainer.svelte +7 -8
  17. package/dist/components/Toast/ToastContent.svelte +18 -5
  18. package/dist/index.d.ts +1 -0
  19. package/dist/index.js +1 -0
  20. package/dist/internal/Button.svelte +7 -7
  21. package/dist/internal/DatePicker.svelte +4 -4
  22. package/dist/internal/Select.svelte +2 -1
  23. package/dist/services/command-palette-manager.svelte.d.ts +13 -18
  24. package/dist/services/command-palette-manager.svelte.js +6 -2
  25. package/dist/services/modal-manager.svelte.d.ts +0 -2
  26. package/dist/services/modal-manager.svelte.js +0 -6
  27. package/dist/services/translation.svelte.d.ts +2 -0
  28. package/dist/services/translation.svelte.js +2 -0
  29. package/dist/styles.js +1 -1
  30. package/dist/theme/default.css +192 -120
  31. package/dist/types.d.ts +0 -2
  32. package/package.json +1 -1
  33. package/dist/components/AppShell/PageLayout.svelte +0 -38
  34. package/dist/components/AppShell/PageLayout.svelte.d.ts +0 -11
@@ -29,13 +29,13 @@
29
29
  false: '',
30
30
  },
31
31
  color: {
32
- primary: 'bg-primary-100 text-primary dark:bg-primary-900',
33
- secondary: 'text-dark dark:bg-dark/25 bg-gray-200',
32
+ primary: 'bg-primary-100 text-primary',
33
+ secondary: 'text-dark bg-light-200 dark:bg-light-300',
34
34
  muted: 'bg-subtle text-subtle dark:bg-subtle',
35
- info: 'bg-info-100 text-info dark:bg-info-900',
36
- warning: 'bg-warning-100 text-warning dark:bg-warning-900',
37
- danger: 'bg-danger-100 text-danger dark:bg-danger-900',
38
- success: 'bg-success-100 text-success dark:bg-success-900',
35
+ info: 'bg-info-100 text-info',
36
+ warning: 'bg-warning-100 text-warning',
37
+ danger: 'bg-danger-100 text-danger',
38
+ success: 'bg-success-100 text-success',
39
39
  },
40
40
  },
41
41
  });
@@ -28,27 +28,27 @@
28
28
  variants: {
29
29
  shape: styleVariants.shape,
30
30
  color: {
31
- primary: 'bg-primary-200 text-primary-950 dark:text-primary-50 dark:bg-primary-800',
32
- secondary: 'bg-neutral-200 text-neutral-950 dark:bg-neutral-800 dark:text-neutral-50',
33
- success: 'bg-success-200 text-success-950 dark:text-success-50 dark:bg-success-800',
34
- danger: 'bg-danger-200 text-danger-950 dark:text-danger-50 dark:bg-danger-800',
35
- warning: 'bg-warning-200 text-warning-950 dark:text-warning-50 dark:bg-warning-800',
36
- info: 'bg-info-200 text-info-950 dark:text-info-50 dark:bg-info-800',
31
+ primary: 'border-primary-100 bg-primary-100 text-primary-950 dark:bg-primary-200 dark:border-primary-200',
32
+ secondary: 'border-light-300 bg-light-100 text-light-950 dark:bg-light-200',
33
+ success: 'border-success-100 bg-success-100 text-success-950 dark:bg-success-200 dark:border-success-200',
34
+ info: 'border-info-200 bg-info-200 text-info-950',
35
+ warning: 'border-warning-200 bg-warning-200 text-warning-950',
36
+ danger: 'border-danger-200 bg-danger-200 text-danger-950 dark:bg-danger-200',
37
37
  },
38
38
  textSize: styleVariants.textSize,
39
39
  paddingSize: {
40
- tiny: 'px-1 py-0.5',
41
- small: 'px-2 py-0.5',
42
- medium: 'px-2 py-0.5',
43
- large: 'px-2 py-1.5',
44
- giant: 'px-3 py-1',
40
+ tiny: 'px-1.5 py-px',
41
+ small: 'px-1.75 py-0.5',
42
+ medium: 'px-2.5 py-0.75',
43
+ large: 'px-2.75 py-1',
44
+ giant: 'px-3 py-1.25',
45
45
  },
46
46
  roundedSize: {
47
- tiny: 'rounded-sm',
48
- small: 'rounded-sm',
49
- medium: 'rounded-sm',
50
- large: 'rounded-md',
51
- giant: 'rounded-md',
47
+ tiny: 'rounded-md',
48
+ small: 'rounded-md',
49
+ medium: 'rounded-md',
50
+ large: 'rounded-lg',
51
+ giant: 'rounded-lg',
52
52
  },
53
53
  },
54
54
  });
@@ -6,6 +6,8 @@
6
6
  import type { Color } from '../../types.js';
7
7
  import { cleanClass } from '../../utilities/internal.js';
8
8
  import { mdiChevronDown } from '@mdi/js';
9
+ import { slide } from 'svelte/transition';
10
+ import { cubicOut } from 'svelte/easing';
9
11
  import { type Snippet } from 'svelte';
10
12
  import type { HTMLAttributes } from 'svelte/elements';
11
13
  import { twMerge } from 'tailwind-merge';
@@ -49,12 +51,12 @@
49
51
  base: 'flex w-full grow flex-col',
50
52
  variants: {
51
53
  color: {
52
- primary: 'bg-primary-100 dark:bg-primary-900',
53
- secondary: 'text-dark bg-gray-100 dark:bg-neutral-900 dark:text-white',
54
- success: 'bg-success-100 dark:bg-success-900',
55
- danger: 'bg-danger-100 dark:bg-danger-900',
56
- warning: 'bg-warning-100 dark:bg-warning-900',
57
- info: 'bg-info-100 dark:bg-info-900',
54
+ primary: 'bg-primary-50 dark:bg-primary-100',
55
+ secondary: 'text-dark bg-light-50 dark:bg-light-100 dark:text-white',
56
+ success: 'bg-success-50 dark:bg-success-100',
57
+ danger: 'bg-danger-50 dark:bg-danger-100',
58
+ warning: 'bg-warning-50 dark:bg-warning-100',
59
+ info: 'bg-info-50 dark:bg-info-100',
58
60
  },
59
61
  },
60
62
  });
@@ -134,9 +136,11 @@
134
136
  {/if}
135
137
 
136
138
  {#if bodyChild && expanded}
137
- <Scrollable class={twMerge(cleanClass('p-4', bodyChild?.class))}>
138
- {@render bodyChild?.snippet()}
139
- </Scrollable>
139
+ <div transition:slide={{ duration: expandable ? 200 : 0, easing: cubicOut }}>
140
+ <Scrollable class={twMerge(cleanClass('p-4', bodyChild?.class))}>
141
+ {@render bodyChild?.snippet()}
142
+ </Scrollable>
143
+ </div>
140
144
  {/if}
141
145
 
142
146
  {#if footerChild}
@@ -41,7 +41,7 @@
41
41
  false: '',
42
42
  muted: 'text-dark bg-subtle',
43
43
  primary: 'text-dark dark:bg-primary/20 bg-gray-200 dark:text-gray-200',
44
- secondary: 'text-light bg-gray-700 dark:bg-gray-200',
44
+ secondary: 'text-light bg-light-700',
45
45
  success: 'bg-success text-light',
46
46
  danger: 'bg-danger text-light',
47
47
  warning: 'bg-warning text-light',
@@ -50,7 +50,7 @@
50
50
 
51
51
  outlineTheme: {
52
52
  false: '',
53
- muted: 'border border-gray-600 text-gray-600 dark:border-gray-400 dark:text-gray-400',
53
+ muted: 'border-light-600 text-light-600 border',
54
54
  primary: 'border-primary text-primary border',
55
55
  secondary: 'border-dark text-dark border',
56
56
  success: 'border-success text-success border',
@@ -11,7 +11,7 @@
11
11
 
12
12
  $effect(() => {
13
13
  // prevent reactivity loop
14
- const addCommands = (commands: CommandItem[], global?: boolean) =>
14
+ const addCommands = (commands: CommandItem[], global: boolean = false) =>
15
15
  untrack(() => commandPaletteManager.addCommands(commands, { global }));
16
16
 
17
17
  return addCommands(commands, global);
@@ -1,15 +1,17 @@
1
1
  <script lang="ts">
2
2
  import { renderShortcut } from '../../actions/shortcut.js';
3
+ import Badge from '../Badge/Badge.svelte';
3
4
  import Button from '../Button/Button.svelte';
4
5
  import Icon from '../Icon/Icon.svelte';
5
6
  import IconButton from '../IconButton/IconButton.svelte';
6
7
  import Kbd from '../Kbd/Kbd.svelte';
7
8
  import Text from '../Text/Text.svelte';
8
- import type { CommandItem } from '../../services/command-palette-manager.svelte';
9
+ import type { CommandItemResponse } from '../../services/command-palette-manager.svelte';
10
+ import { cleanClass } from '../../utilities/internal.js';
9
11
  import { mdiClose } from '@mdi/js';
10
12
 
11
13
  type Props = {
12
- item: CommandItem;
14
+ item: CommandItemResponse;
13
15
  selected: boolean;
14
16
  onSelect: () => void;
15
17
  onRemove?: () => void;
@@ -41,46 +43,46 @@
41
43
  fullWidth
42
44
  variant={selected ? 'outline' : 'ghost'}
43
45
  color="secondary"
44
- class="overflow-hidden border"
46
+ class="flex justify-between gap-3 border text-start {selected ? 'border-neutral-500!' : ''}"
45
47
  >
46
- <div class="flex w-full place-items-center justify-between gap-2">
47
- <div class="flex min-w-0 place-items-center gap-2">
48
- <Icon icon={item.icon} size="2rem" class={item.iconClass} />
49
- <div class="flex min-w-0 flex-col">
50
- <div class="flex place-items-center gap-1">
51
- <Text fontWeight="bold">{item.title}</Text>
52
- </div>
53
- {#if item.description}
54
- <Text
55
- size="small"
56
- class="overflow-hidden text-ellipsis whitespace-nowrap"
57
- color={selected ? undefined : 'muted'}>{item.description}</Text
58
- >
59
- {/if}
60
- </div>
48
+ <div class="flex flex-col">
49
+ <div class="flex items-center gap-1">
50
+ <Text fontWeight="bold">{item.title}</Text>
51
+ <Icon icon={item.icon} size="1.25rem" class={item.iconClass} />
61
52
  </div>
62
- <div class="flex flex-col items-end gap-1">
63
- {#if onRemove}
64
- <IconButton
65
- size="small"
66
- onclick={handleRemove}
67
- icon={mdiClose}
68
- shape="round"
69
- variant="ghost"
70
- color="secondary"
71
- aria-label="Remove"
72
- />
73
- {:else}
74
- <span class="shrink-0">[{item.type}]</span>
75
- {/if}
76
- {#if renderedShortcuts.length > 0}
77
- <div class="flex justify-end gap-1">
78
- {#each renderedShortcuts[0] as key (key)}
79
- <Kbd size="small">{key}</Kbd>
80
- {/each}
81
- </div>
53
+ {#if item.description}
54
+ <Text
55
+ size="small"
56
+ class="mt-0.5 line-clamp-4 w-full overflow-hidden text-ellipsis md:line-clamp-2"
57
+ color="muted">{item.description}</Text
58
+ >
59
+ {/if}
60
+ <div class="mt-2">
61
+ <Badge size="small" color="primary" shape="rectangle">{item.type}</Badge>
62
+ {#if item.isGlobal}
63
+ <Badge size="small" shape="rectangle" color="warning">Global</Badge>
82
64
  {/if}
83
65
  </div>
84
66
  </div>
67
+ {#if onRemove}
68
+ <IconButton
69
+ size="small"
70
+ onclick={handleRemove}
71
+ class="shrink-0"
72
+ icon={mdiClose}
73
+ shape="round"
74
+ variant="ghost"
75
+ color="secondary"
76
+ aria-label="Remove"
77
+ />
78
+ {:else if renderedShortcuts.length > 0}
79
+ <div class="flex shrink-0 flex-col justify-end gap-1">
80
+ {#each renderedShortcuts as shortcut (shortcut.join('-'))}
81
+ <div class="flex justify-end">
82
+ <Kbd size="tiny" class={cleanClass(selected && 'border')}>{shortcut.join(' ')}</Kbd>
83
+ </div>
84
+ {/each}
85
+ </div>
86
+ {/if}
85
87
  </Button>
86
88
  </div>
@@ -1,6 +1,6 @@
1
- import type { CommandItem } from '../../services/command-palette-manager.svelte';
1
+ import type { CommandItemResponse } from '../../services/command-palette-manager.svelte';
2
2
  type Props = {
3
- item: CommandItem;
3
+ item: CommandItemResponse;
4
4
  selected: boolean;
5
5
  onSelect: () => void;
6
6
  onRemove?: () => void;
@@ -25,14 +25,14 @@
25
25
  };
26
26
 
27
27
  const itemStyles = tv({
28
- base: 'hover:bg-subtle flex w-full items-center gap-1 rounded-md px-1 py-0.5 text-start',
28
+ base: 'hover:bg-light-200 flex w-full items-center gap-1 rounded-lg p-1 text-start hover:cursor-pointer',
29
29
  variants: {
30
30
  color: styleVariants.textColor,
31
31
  },
32
32
  });
33
33
 
34
34
  const wrapperStyles = tv({
35
- base: 'bg-light flex flex-col gap-1 overflow-hidden rounded-lg border py-1',
35
+ base: 'bg-light-100 dark:border-light-300 flex flex-col gap-1 overflow-hidden rounded-xl border py-1 shadow-sm',
36
36
  variants: {
37
37
  size: {
38
38
  tiny: 'w-32',
@@ -102,7 +102,7 @@
102
102
  <div {...props} {...restProps} class={cleanClass(wrapperStyles({ size }), className)} transition:fly>
103
103
  {#each filteredItems as item, i (isDivider(item) ? i : item.title)}
104
104
  {#if isDivider(item)}
105
- <DropdownMenu.Separator class="my-0.5 border-t" />
105
+ <DropdownMenu.Separator class="dark:border-light-300 my-0.5 border-t" />
106
106
  {:else}
107
107
  <DropdownMenu.Item
108
108
  textValue={item.title}
@@ -112,14 +112,14 @@
112
112
  >
113
113
  <div class={itemStyles({ color: item.color })}>
114
114
  <Icon icon={item.icon} class="m-2 shrink-0" />
115
- <Text class="grow text-start">{item.title}</Text>
115
+ <Text class="grow text-start font-medium select-none" size="medium">{item.title}</Text>
116
116
  </div>
117
117
  </DropdownMenu.Item>
118
118
  {/if}
119
119
  {/each}
120
120
 
121
121
  {#if filteredBottomItems}
122
- <DropdownMenu.Separator class="my-0.5 border-t" />
122
+ <DropdownMenu.Separator class="dark:border-light-300 my-0.5 border-t" />
123
123
  <div class="flex gap-1 px-1">
124
124
  {#each filteredBottomItems as item (item.title)}
125
125
  <DropdownMenu.Item
@@ -50,7 +50,7 @@
50
50
  });
51
51
 
52
52
  const inputStyles = tv({
53
- base: cleanClass(styleVariants.inputCommon, 'flex-1 py-2'),
53
+ base: cleanClass(styleVariants.inputCommon, 'flex-1 py-2.5'),
54
54
  variants: {
55
55
  textSize: styleVariants.textSize,
56
56
  leadingPadding: {
@@ -88,18 +88,11 @@
88
88
 
89
89
  <div class="flex w-full flex-col gap-1" bind:this={containerRef}>
90
90
  {#if label}
91
- <Label
92
- id={labelId}
93
- for={inputId}
94
- {label}
95
- requiredIndicator={required === 'indicator'}
96
- {...labelProps}
97
- class="font-medium"
98
- />
91
+ <Label id={labelId} for={inputId} {label} requiredIndicator={required === 'indicator'} {...labelProps} />
99
92
  {/if}
100
93
 
101
94
  {#if description}
102
- <Text color="muted" size="small" id={descriptionId} class="mb-1">{description}</Text>
95
+ <Text color="muted" size="small" id={descriptionId} class="mb-2">{description}</Text>
103
96
  {/if}
104
97
 
105
98
  <div
@@ -7,7 +7,7 @@
7
7
  const { label, size, color, class: className, children, requiredIndicator, ...restProps }: LabelProps = $props();
8
8
 
9
9
  const styles = tv({
10
- base: '',
10
+ base: 'font-medium',
11
11
  variants: {
12
12
  size: styleVariants.textSize,
13
13
  color: styleVariants.textColor,
@@ -99,7 +99,7 @@
99
99
  {interactOutsideBehavior}
100
100
  class={cleanClass(modalContentStyles({ size }))}
101
101
  >
102
- <div class={cleanClass('flex grow flex-col justify-center')}>
102
+ <div class={cleanClass('flex w-full grow flex-col justify-center')}>
103
103
  <Card bind:ref={cardRef} class={cleanClass(modalStyles({ size }), className)}>
104
104
  <CardHeader class="border-b border-gray-200 px-5 py-3 dark:border-white/10">
105
105
  {#if headerChildren}
@@ -0,0 +1,59 @@
1
+ <script lang="ts">
2
+ import { styleVariants } from '../../styles.js';
3
+ import type { Color, Shape, Size } from '../../types.js';
4
+ import { cleanClass } from '../../utilities/internal.js';
5
+ import type { Snippet } from 'svelte';
6
+ import { tv } from 'tailwind-variants';
7
+
8
+ type Props = {
9
+ progress: number;
10
+ size?: Size;
11
+ shape?: Shape;
12
+ color?: Color;
13
+ class?: string;
14
+ children?: Snippet;
15
+ };
16
+
17
+ let { progress, shape = 'round', size = 'medium', color = 'primary', class: className, children }: Props = $props();
18
+
19
+ const containerStyles = tv({
20
+ base: 'bg-light-100 dark:bg-light-200 dark:border-light-300 relative w-full overflow-hidden border',
21
+ variants: {
22
+ shape: styleVariants.shape,
23
+ size: {
24
+ tiny: 'h-3',
25
+ small: 'h-4',
26
+ medium: 'h-5',
27
+ large: 'h-6',
28
+ giant: 'h-12',
29
+ },
30
+ roundedSize: {
31
+ tiny: 'rounded-sm',
32
+ small: 'rounded-md',
33
+ medium: 'rounded-md',
34
+ large: 'rounded-lg',
35
+ giant: 'rounded-xl',
36
+ },
37
+ },
38
+ });
39
+
40
+ const barStyles = tv({
41
+ base: 'h-full transition-all duration-700 ease-in-out',
42
+ variants: {
43
+ color: styleVariants.filledColor,
44
+ shape: styleVariants.shape,
45
+ },
46
+ });
47
+ </script>
48
+
49
+ <div
50
+ class={cleanClass(
51
+ containerStyles({ size, shape, roundedSize: shape === 'semi-round' ? size : undefined }),
52
+ className,
53
+ )}
54
+ >
55
+ <div class="absolute flex h-full w-full items-center justify-center">
56
+ {@render children?.()}
57
+ </div>
58
+ <div class={cleanClass(barStyles({ color, shape }))} style="width: {progress * 100}%"></div>
59
+ </div>
@@ -0,0 +1,13 @@
1
+ import type { Color, Shape, Size } from '../../types.js';
2
+ import type { Snippet } from 'svelte';
3
+ type Props = {
4
+ progress: number;
5
+ size?: Size;
6
+ shape?: Shape;
7
+ color?: Color;
8
+ class?: string;
9
+ children?: Snippet;
10
+ };
11
+ declare const ProgressBar: import("svelte").Component<Props, {}, "">;
12
+ type ProgressBar = ReturnType<typeof ProgressBar>;
13
+ export default ProgressBar;
@@ -1,6 +1,7 @@
1
1
  <script lang="ts">
2
2
  import Logo from '../Logo/Logo.svelte';
3
3
  import Text from '../Text/Text.svelte';
4
+ import { t } from '../../services/translation.svelte.js';
4
5
  import type { Size } from '../../types.js';
5
6
  import { cleanClass } from '../../utilities/internal.js';
6
7
  import type { Snippet } from 'svelte';
@@ -13,7 +14,7 @@
13
14
  children?: Snippet;
14
15
  };
15
16
 
16
- const { effect = 'hover', text = 'Supporter', size = 'medium', children }: Props = $props();
17
+ const { effect = 'hover', text = t('supporter'), size = 'medium', children }: Props = $props();
17
18
 
18
19
  const iconSize: Record<Size, Size> = {
19
20
  tiny: 'tiny',
@@ -41,13 +41,13 @@
41
41
  base: 'h-8 w-13 rounded-full border-2',
42
42
  variants: {
43
43
  fillColor: {
44
- default: 'border-gray-400 bg-gray-200 dark:border-gray-500 dark:bg-gray-800',
45
- primary: 'bg-primary-200 dark:bg-primary-800 border-transparent',
46
- secondary: 'border-transparent bg-neutral-300 dark:bg-neutral-700',
47
- success: 'bg-success-200 dark:bg-success-800 border-transparent',
48
- danger: 'bg-danger-200 dark:bg-danger-800 border-transparent',
49
- warning: 'bg-warning-200 dark:bg-warning-800 border-transparent',
50
- info: 'bg-info-200 dark:bg-info-800 border-transparent',
44
+ default: 'border-light-400 bg-light-200 dark:border-gray-500',
45
+ primary: 'bg-primary-100 dark:bg-primary-200 border-transparent',
46
+ secondary: 'bg-light-200 dark:bg-light-300 border-transparent',
47
+ success: 'bg-success-100 dark:bg-success-200 border-transparent',
48
+ danger: 'bg-danger-100 dark:bg-danger-200 border-transparent',
49
+ warning: 'bg-warning-100 dark:bg-warning-200 border-transparent',
50
+ info: 'bg-info-100 dark:bg-info-200 border-transparent',
51
51
  },
52
52
  },
53
53
  });
@@ -95,7 +95,7 @@
95
95
  <div class="text-start">
96
96
  <Label id={labelId} for={inputId} {label} requiredIndicator={required === 'indicator'} {...labelProps} />
97
97
  {#if description}
98
- <Text color="secondary" size="small" id={descriptionId}>{description}</Text>
98
+ <Text color="muted" size="small" id={descriptionId}>{description}</Text>
99
99
  {/if}
100
100
  </div>
101
101
  {/if}
@@ -15,16 +15,15 @@
15
15
  }: ToastContainerProps = $props();
16
16
 
17
17
  const containerStyles = tv({
18
- base: 'bg-light text-dark overflow-hidden py-1.5 shadow-xs transition-all',
18
+ base: 'bg-light text-dark overflow-hidden border py-1.5 shadow-xs transition-all',
19
19
  variants: {
20
20
  color: {
21
- primary: 'bg-primary-100 dark:bg-primary-900',
22
- secondary: 'bg-neutral-100 dark:bg-neutral-900',
23
- muted: 'bg-subtle dark:bg-subtle',
24
- info: 'bg-info-100 dark:bg-info-900',
25
- warning: 'bg-warning-100 dark:bg-warning-900',
26
- danger: 'bg-danger-100 dark:bg-danger-900',
27
- success: 'bg-success-100 dark:bg-success-900',
21
+ primary: 'border-primary-100 bg-primary-50 dark:bg-primary-100 dark:border-primary-200',
22
+ secondary: 'border-light-200 bg-light-100 dark:bg-light-200 dark:border-light-300',
23
+ success: 'border-success-100 bg-success-50 dark:bg-success-100 dark:border-success-200',
24
+ info: 'border-info-100 bg-info-50 dark:bg-info-100 dark:border-info-200',
25
+ warning: 'border-warning-100 bg-warning-50 dark:bg-warning-100 dark:border-warning-200',
26
+ danger: 'border-danger-100 bg-danger-50 dark:bg-danger-100 dark:border-danger-200',
28
27
  },
29
28
  shape: styleVariants.shape,
30
29
  size: {
@@ -27,7 +27,20 @@
27
27
  );
28
28
 
29
29
  const iconStyles = tv({
30
- base: 'h-10 w-10 shrink-0 py-2',
30
+ base: 'h-8 w-8 shrink-0 rounded-xl py-1.75',
31
+ variants: {
32
+ color: {
33
+ primary: 'bg-primary-100 dark:bg-primary-200 text-primary',
34
+ secondary: 'bg-light-200 dark:bg-light-300',
35
+ success: 'bg-success-100 dark:bg-success-200 text-success',
36
+ info: 'bg-info-200 text-info',
37
+ warning: 'bg-warning-200 text-warning',
38
+ danger: 'bg-danger-200 text-danger',
39
+ },
40
+ },
41
+ });
42
+
43
+ const titleStyles = tv({
31
44
  variants: {
32
45
  color: styleVariants.textColor,
33
46
  },
@@ -38,16 +51,16 @@
38
51
  {#if typeof text === 'string'}{text}{:else}{@render text()}{/if}
39
52
  {/snippet}
40
53
 
41
- <div class="flex items-center px-2">
54
+ <div class="flex items-center px-3">
42
55
  <div class="flex items-center">
43
56
  {#if icon}
44
- <Icon {icon} class={iconStyles({ color })} />
57
+ <Icon {icon} class={iconStyles({ color })} size="18" />
45
58
  {/if}
46
59
  </div>
47
- <div class="flex grow justify-between">
60
+ <div class="ms-1 flex grow justify-between">
48
61
  <div class="flex flex-col p-2">
49
62
  {#if title}
50
- <Text fontWeight="bold">{@render resolve(title)}</Text>
63
+ <Text fontWeight="semi-bold" class={titleStyles({ color })}>{@render resolve(title)}</Text>
51
64
  {/if}
52
65
  {#if description}
53
66
  <Text size="small">{@render resolve(description)}</Text>
package/dist/index.d.ts CHANGED
@@ -55,6 +55,7 @@ export { default as NavbarGroup } from './components/Navbar/NavbarGroup.svelte';
55
55
  export { default as NavbarItem } from './components/Navbar/NavbarItem.svelte';
56
56
  export { default as NumberInput } from './components/NumberInput/NumberInput.svelte';
57
57
  export { default as PasswordInput } from './components/PasswordInput/PasswordInput.svelte';
58
+ export { default as ProgressBar } from './components/ProgressBar/ProgressBar.svelte';
58
59
  export { default as Scrollable } from './components/Scrollable/Scrollable.svelte';
59
60
  export { default as Select } from './components/Select/Select.svelte';
60
61
  export { default as SiteMetadata } from './components/SiteMetadata/SiteMetadata.svelte';
package/dist/index.js CHANGED
@@ -57,6 +57,7 @@ export { default as NavbarGroup } from './components/Navbar/NavbarGroup.svelte';
57
57
  export { default as NavbarItem } from './components/Navbar/NavbarItem.svelte';
58
58
  export { default as NumberInput } from './components/NumberInput/NumberInput.svelte';
59
59
  export { default as PasswordInput } from './components/PasswordInput/PasswordInput.svelte';
60
+ export { default as ProgressBar } from './components/ProgressBar/ProgressBar.svelte';
60
61
  export { default as Scrollable } from './components/Scrollable/Scrollable.svelte';
61
62
  export { default as Select } from './components/Select/Select.svelte';
62
63
  export { default as SiteMetadata } from './components/SiteMetadata/SiteMetadata.svelte';
@@ -72,19 +72,19 @@
72
72
  filledColorHover: styleVariants.filledColorHover,
73
73
  outlineColor: {
74
74
  primary: 'border-primary bg-primary/10 text-primary hover:bg-primary/20 border',
75
- secondary: 'border-dark bg-dark/10 text-dark hover:bg-dark/20 border',
75
+ secondary: 'border-dark bg-light-100 text-dark hover:bg-light-200 border',
76
76
  success: 'border-success bg-success/10 text-success hover:bg-success/20 border',
77
77
  danger: 'border-danger bg-danger/10 text-danger hover:bg-danger/20 border',
78
78
  warning: 'border-warning bg-warning/10 text-warning hover:bg-warning/20 border',
79
79
  info: 'border-info bg-info/10 text-info hover:bg-info/20 border',
80
80
  },
81
81
  ghostColor: {
82
- primary: 'text-primary hover:bg-primary-50 dark:hover:bg-primary-950',
83
- secondary: 'text-dark hover:bg-dark/10',
84
- success: 'text-success hover:bg-success-50 dark:hover:bg-success-950',
85
- danger: 'text-danger hover:bg-danger-50 dark:hover:bg-danger-950',
86
- warning: 'text-warning hover:bg-warning-50 dark:hover:bg-warning-950',
87
- info: 'text-info hover:bg-info-50 dark:hover:bg-info-950',
82
+ primary: 'text-primary hover:bg-primary-50',
83
+ secondary: 'text-dark hover:bg-light-100',
84
+ success: 'text-success hover:bg-success-50',
85
+ danger: 'text-danger hover:bg-danger-50',
86
+ warning: 'text-warning hover:bg-warning-50',
87
+ info: 'text-info hover:bg-info-50',
88
88
  },
89
89
  },
90
90
  });
@@ -51,11 +51,11 @@
51
51
  });
52
52
 
53
53
  const buttonStyles = tv({
54
- base: 'flex h-8 w-8 items-center justify-center rounded-lg transition-colors hover:bg-neutral-200 hover:dark:bg-neutral-700',
54
+ base: 'hover:bg-light-200 hover:dark:bg-light-300 flex h-10 w-10 items-center justify-center rounded-lg hover:cursor-pointer',
55
55
  });
56
56
 
57
57
  const segmentStyles = tv({
58
- base: 'rounded px-1 py-0.5 tabular-nums outline-none focus:bg-gray-300 focus:text-gray-900 data-disabled:cursor-not-allowed data-focused:bg-gray-300 data-focused:text-gray-900 data-placeholder:text-gray-400 dark:focus:bg-gray-700 dark:focus:text-gray-100 dark:data-focused:bg-gray-700 dark:data-focused:text-gray-100',
58
+ base: 'focus:bg-light-300 focus:text-light-900 data-focused:bg-light-300 data-focused:text-light-900 data-placeholder:text-light-400 dark:focus:bg-light-700 dark:focus:text-light-100 dark:data-focused:bg-light-300 dark:data-focused:text-light-900 rounded px-1 py-0.5 tabular-nums outline-none data-disabled:cursor-not-allowed',
59
59
  variants: {
60
60
  textSize: styleVariants.textSize,
61
61
  },
@@ -85,7 +85,7 @@
85
85
  })}
86
86
  >
87
87
  {#snippet children({ segments })}
88
- <div class={cleanClass(styleVariants.inputCommon, 'w-full px-4 py-2')}>
88
+ <div class={cleanClass(styleVariants.inputCommon, 'w-full px-3 py-2 font-medium')}>
89
89
  {#each segments as { part, value }, i (`segment-${i}`)}
90
90
  <DatePicker.Segment {part} class={segmentStyles({ textSize: size })}>
91
91
  {value}
@@ -140,7 +140,7 @@
140
140
  {#each weekDates as date (`date-${date.toString()}`)}
141
141
  <DatePicker.Cell {date} month={month.value} class="flex-1">
142
142
  <DatePicker.Day
143
- class="{buttonStyles()} data-selected:bg-primary data-selected:text-light data-today:border-primary border border-transparent data-disabled:cursor-not-allowed data-disabled:opacity-40 data-outside-month:text-gray-400 data-unavailable:cursor-not-allowed data-unavailable:text-gray-300 data-unavailable:line-through"
143
+ class="{buttonStyles()} data-selected:bg-primary data-selected:hover:bg-primary-300 data-selected:text-light data-today:border-primary-200 data-today:dark:border-primary-400 data-today:dark:bg-primary-200 data-today:bg-primary-50 data-outside-month:text-light-400 data-unavailable:text-light-300 border border-transparent text-sm data-disabled:cursor-not-allowed data-disabled:opacity-40 data-unavailable:cursor-not-allowed data-unavailable:line-through"
144
144
  >
145
145
  {date.day}
146
146
  </DatePicker.Day>
@@ -84,7 +84,7 @@
84
84
  <Select.Root type={multiple ? 'multiple' : 'single'} bind:value={internalValue as never} {onValueChange}>
85
85
  <Select.Trigger
86
86
  {disabled}
87
- class="w-full items-center gap-1 rounded-lg focus-visible:outline-none"
87
+ class="w-full items-center gap-1 rounded-lg py-0 focus-visible:outline-none"
88
88
  aria-label={placeholder}
89
89
  >
90
90
  <Field {readOnly} {required} {disabled} {invalid}>
@@ -104,6 +104,7 @@
104
104
  variant="ghost"
105
105
  shape="round"
106
106
  color="secondary"
107
+ size="tiny"
107
108
  class="m-1"
108
109
  icon={mdiUnfoldMoreHorizontal}
109
110
  {disabled}
@@ -12,28 +12,25 @@ export type CommandItem = {
12
12
  ignoreInputFields?: boolean;
13
13
  preventDefault?: boolean;
14
14
  };
15
+ id?: string;
15
16
  } & IfLike & ({
16
17
  href: string;
17
18
  } | {
18
- action: (command: CommandItem) => void;
19
+ action: (command: CommandItemResponse) => void;
19
20
  });
20
- export type CommandPaletteTranslations = TranslationProps<'search_placeholder' | 'search_no_results' | 'search_recently_used' | 'command_palette_prompt_default' | 'command_palette_to_select' | 'command_palette_to_close' | 'command_palette_to_navigate' | 'command_palette_to_show_all'>;
21
+ export type CommandItemResponse = CommandItem & {
22
+ id: string;
23
+ isGlobal: boolean;
24
+ };
25
+ export type CommandPaletteTranslations = TranslationProps<'search_placeholder' | 'search_no_results' | 'search_recently_used' | 'command_palette_prompt_default' | 'command_palette_to_select' | 'command_palette_to_close' | 'command_palette_to_navigate' | 'command_palette_to_show_all' | 'global'>;
21
26
  export declare const asText: (...items: unknown[]) => string;
22
27
  declare class CommandPaletteManager {
23
28
  #private;
24
29
  selectedIndex: number;
25
- items: (CommandItem & {
26
- id: string;
27
- })[];
28
- filteredItems: (CommandItem & {
29
- id: string;
30
- })[];
31
- recentItems: (CommandItem & {
32
- id: string;
33
- })[];
34
- results: (CommandItem & {
35
- id: string;
36
- })[];
30
+ items: CommandItemResponse[];
31
+ filteredItems: CommandItemResponse[];
32
+ recentItems: CommandItemResponse[];
33
+ results: CommandItemResponse[];
37
34
  get isEnabled(): boolean;
38
35
  enable(): void;
39
36
  get query(): string;
@@ -50,10 +47,8 @@ declare class CommandPaletteManager {
50
47
  up(): void;
51
48
  down(): void;
52
49
  reset(): void;
53
- addCommands(itemOrItems: MaybeArray<CommandItem & {
54
- id?: string;
55
- }>, options?: {
56
- global?: boolean;
50
+ addCommands(itemOrItems: MaybeArray<CommandItem>, options?: {
51
+ global: boolean;
57
52
  }): () => void;
58
53
  removeCommands(itemOrItems: MaybeArray<{
59
54
  id: string;
@@ -178,9 +178,13 @@ class CommandPaletteManager {
178
178
  this.#globalLayer = { items: [], recentItems: [] };
179
179
  this.#query = '';
180
180
  }
181
- addCommands(itemOrItems, options = {}) {
181
+ addCommands(itemOrItems, options = { global: false }) {
182
182
  const items = Array.isArray(itemOrItems) ? itemOrItems : [itemOrItems];
183
- const itemsWithId = items.map((item) => ({ ...item, id: item.id ?? generateId() }));
183
+ const itemsWithId = items.map((item) => ({
184
+ ...item,
185
+ id: item.id ?? generateId(),
186
+ isGlobal: options.global,
187
+ }));
184
188
  if (options.global) {
185
189
  this.#globalLayer.items.push(...itemsWithId);
186
190
  }
@@ -9,8 +9,6 @@ type ExtendsEmptyObject<T> = keyof T extends never ? never : T;
9
9
  type StripParamIfOptional<T> = T extends void ? [] : [T];
10
10
  type OptionalParamIfEmpty<T> = ExtendsEmptyObject<T> extends never ? [] | [Record<string, never> | undefined] : [T];
11
11
  declare class ModalManager {
12
- #private;
13
- get openCount(): number;
14
12
  show<T extends object>(Component: Component<T>, ...props: OptionalParamIfEmpty<Omit<T, 'onClose'>>): Promise<OnCloseData<T>>;
15
13
  open<T extends object, K = OnCloseData<T>>(Component: Component<T>, ...props: OptionalParamIfEmpty<Omit<T, 'onClose'>>): {
16
14
  onClose: Promise<K>;
@@ -1,10 +1,6 @@
1
1
  import { mount, unmount } from 'svelte';
2
2
  import ConfirmModal from '../components/ConfirmModal/ConfirmModal.svelte';
3
3
  class ModalManager {
4
- #openCount = $state(0);
5
- get openCount() {
6
- return this.#openCount;
7
- }
8
4
  show(Component, ...props) {
9
5
  return this.open(Component, ...props).onClose;
10
6
  }
@@ -14,7 +10,6 @@ class ModalManager {
14
10
  const deferred = new Promise((resolve) => {
15
11
  onClose = async (...args) => {
16
12
  await unmount(modal);
17
- this.#openCount--;
18
13
  // make sure bits-ui clean up finishes before resolving
19
14
  setTimeout(() => resolve(args[0]), 10);
20
15
  };
@@ -25,7 +20,6 @@ class ModalManager {
25
20
  onClose,
26
21
  },
27
22
  });
28
- this.#openCount++;
29
23
  });
30
24
  return {
31
25
  onClose: deferred,
@@ -22,6 +22,8 @@ declare const defaultTranslations: {
22
22
  toast_warning_title: string;
23
23
  toast_danger_title: string;
24
24
  save: string;
25
+ supporter: string;
26
+ global: string;
25
27
  };
26
28
  export type Translations = typeof defaultTranslations;
27
29
  export declare const translate: <T extends keyof Translations>(key: T, overrides?: TranslationProps<T>) => string;
@@ -28,6 +28,8 @@ const defaultTranslations = {
28
28
  toast_warning_title: 'Warning',
29
29
  toast_danger_title: 'Error',
30
30
  save: 'Save',
31
+ supporter: 'Supporter',
32
+ global: 'Global',
31
33
  };
32
34
  let translations = $state(defaultTranslations);
33
35
  export const translate = (key, overrides) => overrides?.[key] ?? translations[key];
package/dist/styles.js CHANGED
@@ -13,7 +13,7 @@ export const styleVariants = {
13
13
  muted: 'text-gray-600 dark:text-gray-400',
14
14
  },
15
15
  inputCommon: 'disabled:bg-gray-300 disabled:text-dark dark:disabled:bg-gray-900 dark:disabled:text-gray-200 bg-transparent transition outline-none disabled:cursor-not-allowed ',
16
- inputContainerCommon: 'bg-gray-100 ring-1 ring-gray-200 focus-within:ring-primary dark:focus-within:ring-primary transition outline-none focus-within:ring-1 disabled:cursor-not-allowed dark:bg-gray-600 dark:ring-black',
16
+ inputContainerCommon: 'bg-gray-100 ring-1 ring-gray-200 focus-within:ring-primary dark:focus-within:ring-primary transition outline-none focus-within:ring-1 disabled:cursor-not-allowed dark:bg-gray-800 dark:ring-black',
17
17
  shape: {
18
18
  rectangle: 'rounded-none',
19
19
  'semi-round': '',
@@ -66,15 +66,39 @@
66
66
  --color-info-900: var(--immich-ui-info-900);
67
67
  --color-info-950: var(--immich-ui-info-950);
68
68
 
69
+ --color-light-50: var(--immich-ui-light-50);
70
+ --color-light-100: var(--immich-ui-light-100);
71
+ --color-light-200: var(--immich-ui-light-200);
72
+ --color-light-300: var(--immich-ui-light-300);
73
+ --color-light-400: var(--immich-ui-light-400);
74
+ --color-light-500: var(--immich-ui-light-500);
75
+ --color-light-600: var(--immich-ui-light-600);
76
+ --color-light-700: var(--immich-ui-light-700);
77
+ --color-light-800: var(--immich-ui-light-800);
78
+ --color-light-900: var(--immich-ui-light-900);
79
+ --color-light-950: var(--immich-ui-light-950);
80
+
81
+ --color-dark-50: var(--immich-ui-dark-50);
82
+ --color-dark-100: var(--immich-ui-dark-100);
83
+ --color-dark-200: var(--immich-ui-dark-200);
84
+ --color-dark-300: var(--immich-ui-dark-300);
85
+ --color-dark-400: var(--immich-ui-dark-400);
86
+ --color-dark-500: var(--immich-ui-dark-500);
87
+ --color-dark-600: var(--immich-ui-dark-600);
88
+ --color-dark-700: var(--immich-ui-dark-700);
89
+ --color-dark-800: var(--immich-ui-dark-800);
90
+ --color-dark-900: var(--immich-ui-dark-900);
91
+ --color-dark-950: var(--immich-ui-dark-950);
92
+
69
93
  --color-primary: var(--immich-ui-primary-500);
70
94
  --color-success: var(--immich-ui-success-500);
71
95
  --color-danger: var(--immich-ui-danger-500);
72
96
  --color-warning: var(--immich-ui-warning-500);
73
97
  --color-info: var(--immich-ui-info-500);
74
- --color-light: rgb(var(--immich-ui-light));
98
+ --color-light: var(--immich-ui-light);
75
99
  --color-dark: var(--immich-ui-dark);
76
- --color-muted: rgb(var(--immich-ui-muted));
77
- --color-subtle: rgb(var(--immich-ui-gray));
100
+ --color-muted: var(--immich-ui-muted);
101
+ --color-subtle: var(--immich-ui-gray);
78
102
  }
79
103
 
80
104
  @custom-variant dark (&:where(.dark, .dark *):not(.light));
@@ -83,140 +107,188 @@
83
107
  :root,
84
108
  .light {
85
109
  /* light */
86
- --immich-ui-primary-50: oklch(0.949 0.016 282.34);
110
+ --immich-ui-primary-50: oklch(0.9616 0.0166 271.24);
87
111
  --immich-ui-primary-100: oklch(0.897 0.033 281.96);
88
112
  --immich-ui-primary-200: oklch(0.787 0.07 281.03);
89
113
  --immich-ui-primary-300: oklch(0.686 0.106 278.96);
90
114
  --immich-ui-primary-400: oklch(0.577 0.142 275.93);
91
- --immich-ui-primary-500: oklch(0.473 0.151 272.94);
115
+ --immich-ui-primary-500: #4250af;
92
116
  --immich-ui-primary-600: oklch(0.404 0.129 273.18);
93
117
  --immich-ui-primary-700: oklch(0.343 0.109 272.56);
94
118
  --immich-ui-primary-800: oklch(0.272 0.088 272.94);
95
119
  --immich-ui-primary-900: oklch(0.211 0.068 273.01);
96
120
  --immich-ui-primary-950: oklch(0.15 0.05 273.01);
97
121
 
98
- --immich-ui-success-50: oklch(0.969 0.048 153.5);
99
- --immich-ui-success-100: oklch(0.926 0.124 152.83);
100
- --immich-ui-success-200: oklch(0.864 0.223 152.18);
101
- --immich-ui-success-300: oklch(0.804 0.206 152.33);
102
- --immich-ui-success-400: oklch(0.755 0.194 152.36);
103
- --immich-ui-success-500: oklch(0.698 0.179 152.3);
104
- --immich-ui-success-600: oklch(0.588 0.151 152.25);
105
- --immich-ui-success-700: oklch(0.469 0.12 152.39);
106
- --immich-ui-success-800: oklch(0.359 0.093 152.23);
107
- --immich-ui-success-900: oklch(0.243 0.063 151.99);
108
- --immich-ui-success-950: oklch(0.169 0.042 151.99);
109
-
110
- --immich-ui-danger-50: oklch(0.976 0.008 17.52);
111
- --immich-ui-danger-100: oklch(0.951 0.015 17.54);
112
- --immich-ui-danger-200: oklch(0.867 0.046 18.1);
113
- --immich-ui-danger-300: oklch(0.778 0.085 19.18);
114
- --immich-ui-danger-400: oklch(0.696 0.129 20.93);
115
- --immich-ui-danger-500: oklch(0.608 0.179 24.17);
116
- --immich-ui-danger-600: oklch(0.518 0.153 24.17);
117
- --immich-ui-danger-700: oklch(0.422 0.124 24.12);
118
- --immich-ui-danger-800: oklch(0.331 0.098 24.2);
119
- --immich-ui-danger-900: oklch(0.231 0.069 24.25);
120
- --immich-ui-danger-950: oklch(0.184 0.055 24.33);
121
-
122
- --immich-ui-warning: oklch(0.689 0.133 67.56);
123
- --immich-ui-warning-50: oklch(0.974 0.013 67.56);
124
- --immich-ui-warning-100: oklch(0.947 0.029 67.56);
125
- --immich-ui-warning-200: oklch(0.892 0.061 67.56);
126
- --immich-ui-warning-300: oklch(0.825 0.097 67.56);
127
- --immich-ui-warning-400: oklch(0.757 0.115 67.56);
128
- --immich-ui-warning-500: oklch(0.689 0.133 67.56);
129
- --immich-ui-warning-600: oklch(0.604 0.117 67.56);
130
- --immich-ui-warning-700: oklch(0.509 0.099 67.56);
131
- --immich-ui-warning-800: oklch(0.418 0.081 67.56);
132
- --immich-ui-warning-900: oklch(0.341 0.066 67.56);
133
- --immich-ui-warning-950: oklch(0.273 0.053 67.56);
134
-
135
- --immich-ui-info-50: oklch(0.967 0.018 254.53);
136
- --immich-ui-info-100: oklch(0.933 0.037 254.53);
137
- --immich-ui-info-200: oklch(0.862 0.078 254.53);
138
- --immich-ui-info-300: oklch(0.768 0.126 254.53);
139
- --immich-ui-info-400: oklch(0.667 0.152 254.53);
140
- --immich-ui-info-500: oklch(0.567 0.177 254.53);
141
- --immich-ui-info-600: oklch(0.492 0.155 254.53);
142
- --immich-ui-info-700: oklch(0.419 0.132 254.53);
143
- --immich-ui-info-800: oklch(0.347 0.109 254.53);
144
- --immich-ui-info-900: oklch(0.285 0.089 254.53);
145
- --immich-ui-info-950: oklch(0.232 0.073 254.53);
146
-
147
- --immich-ui-light: 255 255 255;
148
- --immich-ui-dark: rgb(63, 60, 60);
149
- --immich-ui-muted: 161 161 161;
150
- --immich-ui-gray: 246 246 246;
151
- --immich-ui-default-border: 209 213 219;
122
+ --immich-ui-success-50: oklch(0.969 0.051 148.59);
123
+ --immich-ui-success-100: oklch(0.937 0.109 148.66);
124
+ --immich-ui-success-200: oklch(0.863 0.249 147.5);
125
+ --immich-ui-success-300: oklch(0.813 0.234 147.54);
126
+ --immich-ui-success-400: oklch(0.762 0.219 147.59);
127
+ --immich-ui-success-500: oklch(0.708 0.204 147.56);
128
+ --immich-ui-success-600: oklch(0.594 0.171 147.56);
129
+ --immich-ui-success-700: oklch(0.476 0.136 147.69);
130
+ --immich-ui-success-800: oklch(0.36 0.104 147.58);
131
+ --immich-ui-success-900: oklch(0.252 0.073 147.47);
132
+ --immich-ui-success-950: oklch(0.194 0.056 147.87);
133
+
134
+ --immich-ui-danger-50: oklch(0.96 0.018 17.57);
135
+ --immich-ui-danger-100: oklch(0.926 0.034 17.84);
136
+ --immich-ui-danger-200: oklch(0.853 0.074 19.77);
137
+ --immich-ui-danger-300: oklch(0.774 0.125 21.53);
138
+ --immich-ui-danger-400: oklch(0.701 0.178 23.61);
139
+ --immich-ui-danger-500: oklch(0.633 0.24 28.79);
140
+ --immich-ui-danger-600: oklch(0.533 0.204 28.97);
141
+ --immich-ui-danger-700: oklch(0.433 0.166 28.91);
142
+ --immich-ui-danger-800: oklch(0.342 0.131 28.79);
143
+ --immich-ui-danger-900: oklch(0.245 0.094 29.51);
144
+ --immich-ui-danger-950: oklch(0.186 0.07 29.56);
145
+
146
+ --immich-ui-warning: oklch(0.812 0.17 76.3);
147
+ --immich-ui-warning-50: oklch(0.983 0.01 58.27);
148
+ --immich-ui-warning-100: oklch(0.959 0.027 63.96);
149
+ --immich-ui-warning-200: oklch(0.925 0.051 64.24);
150
+ --immich-ui-warning-300: oklch(0.882 0.086 67.45);
151
+ --immich-ui-warning-400: oklch(0.85 0.12 70.92);
152
+ --immich-ui-warning-500: oklch(0.812 0.17 76.3);
153
+ --immich-ui-warning-600: oklch(0.679 0.142 76.48);
154
+ --immich-ui-warning-700: oklch(0.539 0.113 76.63);
155
+ --immich-ui-warning-800: oklch(0.408 0.086 75.75);
156
+ --immich-ui-warning-900: oklch(0.27 0.057 76.33);
157
+ --immich-ui-warning-950: oklch(0.209 0.044 77.51);
158
+
159
+ --immich-ui-info-50: oklch(0.958 0.02 267.31);
160
+ --immich-ui-info-100: oklch(0.922 0.036 268.3);
161
+ --immich-ui-info-200: oklch(0.845 0.073 265.19);
162
+ --immich-ui-info-300: oklch(0.769 0.114 261.53);
163
+ --immich-ui-info-400: oklch(0.691 0.159 256.82);
164
+ --immich-ui-info-500: oklch(0.611 0.177 252.85);
165
+ --immich-ui-info-600: oklch(0.519 0.149 252.81);
166
+ --immich-ui-info-700: oklch(0.422 0.123 252.93);
167
+ --immich-ui-info-800: oklch(0.328 0.096 253.05);
168
+ --immich-ui-info-900: oklch(0.234 0.067 252.62);
169
+ --immich-ui-info-950: oklch(0.178 0.052 253.61);
170
+
171
+ --immich-ui-light-50: var(--color-neutral-50);
172
+ --immich-ui-light-100: var(--color-neutral-100);
173
+ --immich-ui-light-200: var(--color-neutral-200);
174
+ --immich-ui-light-300: var(--color-neutral-300);
175
+ --immich-ui-light-400: var(--color-neutral-400);
176
+ --immich-ui-light-500: var(--color-neutral-500);
177
+ --immich-ui-light-600: var(--color-neutral-600);
178
+ --immich-ui-light-700: var(--color-neutral-700);
179
+ --immich-ui-light-800: var(--color-neutral-800);
180
+ --immich-ui-light-900: var(--color-neutral-900);
181
+ --immich-ui-light-950: var(--color-neutral-950);
182
+
183
+ --immich-ui-dark-50: var(--color-neutral-950);
184
+ --immich-ui-dark-100: var(--color-neutral-900);
185
+ --immich-ui-dark-200: var(--color-neutral-800);
186
+ --immich-ui-dark-300: var(--color-neutral-700);
187
+ --immich-ui-dark-400: var(--color-neutral-600);
188
+ --immich-ui-dark-500: var(--color-neutral-500);
189
+ --immich-ui-dark-600: var(--color-neutral-400);
190
+ --immich-ui-dark-700: var(--color-neutral-300);
191
+ --immich-ui-dark-800: var(--color-neutral-200);
192
+ --immich-ui-dark-900: var(--color-neutral-100);
193
+ --immich-ui-dark-950: var(--color-neutral-50);
194
+
195
+ --immich-ui-light: oklch(100% 0 0);
196
+ --immich-ui-dark: oklch(36% 0 17);
197
+ --immich-ui-muted: oklch(71% 0 271);
198
+ --immich-ui-gray: oklch(97% 0 271);
199
+ --immich-ui-default-border: var(--immich-ui-light-300);
152
200
  }
153
201
 
154
202
  .dark {
155
- --immich-ui-primary-50: oklch(0.982 0.007 268.63);
156
- --immich-ui-primary-100: oklch(0.966 0.015 260.75);
157
- --immich-ui-primary-200: oklch(0.932 0.03 262.55);
158
- --immich-ui-primary-300: oklch(0.906 0.041 260.95);
159
- --immich-ui-primary-400: oklch(0.871 0.057 259.89);
203
+ --immich-ui-primary-950: oklch(0.982 0.007 268.63);
204
+ --immich-ui-primary-900: oklch(0.966 0.015 260.75);
205
+ --immich-ui-primary-800: oklch(0.932 0.03 262.55);
206
+ --immich-ui-primary-700: oklch(0.906 0.041 260.95);
207
+ --immich-ui-primary-600: oklch(0.871 0.057 259.89);
160
208
  --immich-ui-primary-500: oklch(0.836 0.074 258.58);
161
- --immich-ui-primary-600: oklch(0.526 0.063 256.86);
162
- --immich-ui-primary-700: oklch(0.449 0.054 257.6);
163
- --immich-ui-primary-800: oklch(0.372 0.045 257.42);
164
- --immich-ui-primary-900: oklch(0.258 0.032 258.31);
165
- --immich-ui-primary-950: oklch(0.198 0.023 257.29);
166
-
167
- --immich-ui-success-50: oklch(0.979 0.027 157.32);
168
- --immich-ui-success-100: oklch(0.969 0.043 155.86);
169
- --immich-ui-success-200: oklch(0.937 0.09 156.81);
170
- --immich-ui-success-300: oklch(0.894 0.164 156.29);
171
- --immich-ui-success-400: oklch(0.866 0.186 156.06);
209
+ --immich-ui-primary-400: oklch(0.526 0.063 256.86);
210
+ --immich-ui-primary-300: oklch(0.449 0.054 257.6);
211
+ --immich-ui-primary-200: oklch(0.372 0.045 257.42);
212
+ --immich-ui-primary-100: oklch(0.258 0.032 258.31);
213
+ --immich-ui-primary-50: oklch(0.198 0.023 257.29);
214
+
215
+ --immich-ui-success-950: oklch(0.979 0.027 157.32);
216
+ --immich-ui-success-900: oklch(0.969 0.043 155.86);
217
+ --immich-ui-success-800: oklch(0.937 0.09 156.81);
218
+ --immich-ui-success-700: oklch(0.894 0.164 156.29);
219
+ --immich-ui-success-600: oklch(0.866 0.186 156.06);
172
220
  --immich-ui-success-500: oklch(0.842 0.181 156.04);
173
- --immich-ui-success-600: oklch(0.699 0.151 155.85);
174
- --immich-ui-success-700: oklch(0.555 0.119 156.26);
175
- --immich-ui-success-800: oklch(0.419 0.089 156.41);
176
- --immich-ui-success-900: oklch(0.279 0.06 155.24);
177
- --immich-ui-success-950: oklch(0.181 0.04 155.24);
178
-
179
- --immich-ui-danger-50: oklch(0.975 0.011 17.5);
180
- --immich-ui-danger-100: oklch(0.943 0.025 17.67);
181
- --immich-ui-danger-200: oklch(0.894 0.049 18.13);
182
- --immich-ui-danger-300: oklch(0.836 0.079 18.9);
183
- --immich-ui-danger-400: oklch(0.781 0.112 19.92);
221
+ --immich-ui-success-400: oklch(0.699 0.151 155.85);
222
+ --immich-ui-success-300: oklch(0.555 0.119 156.26);
223
+ --immich-ui-success-200: oklch(0.419 0.089 156.41);
224
+ --immich-ui-success-100: oklch(0.279 0.06 155.24);
225
+ --immich-ui-success-50: oklch(0.181 0.04 155.24);
226
+
227
+ --immich-ui-danger-950: oklch(0.975 0.011 17.5);
228
+ --immich-ui-danger-900: oklch(0.943 0.025 17.67);
229
+ --immich-ui-danger-800: oklch(0.894 0.049 18.13);
230
+ --immich-ui-danger-700: oklch(0.836 0.079 18.9);
231
+ --immich-ui-danger-600: oklch(0.781 0.112 19.92);
184
232
  --immich-ui-danger-500: oklch(0.727 0.149 21.41);
185
- --immich-ui-danger-600: oklch(0.622 0.232 27.33);
186
- --immich-ui-danger-700: oklch(0.505 0.188 27.33);
187
- --immich-ui-danger-800: oklch(0.387 0.144 27.27);
188
- --immich-ui-danger-900: oklch(0.262 0.097 27.31);
189
- --immich-ui-danger-950: oklch(0.207 0.077 27.3);
190
-
191
- --immich-ui-warning-50: oklch(0.993 0.005 67.8);
192
- --immich-ui-warning-100: oklch(0.975 0.017 67.63);
193
- --immich-ui-warning-200: oklch(0.958 0.029 67.47);
194
- --immich-ui-warning-300: oklch(0.934 0.048 69.18);
195
- --immich-ui-warning-400: oklch(0.907 0.07 70.22);
233
+ --immich-ui-danger-400: oklch(0.622 0.232 27.33);
234
+ --immich-ui-danger-300: oklch(0.505 0.188 27.33);
235
+ --immich-ui-danger-200: oklch(0.387 0.144 27.27);
236
+ --immich-ui-danger-100: oklch(0.262 0.097 27.31);
237
+ --immich-ui-danger-50: oklch(0.207 0.077 27.3);
238
+
239
+ --immich-ui-warning-950: oklch(0.993 0.005 67.8);
240
+ --immich-ui-warning-900: oklch(0.975 0.017 67.63);
241
+ --immich-ui-warning-800: oklch(0.958 0.029 67.47);
242
+ --immich-ui-warning-700: oklch(0.934 0.048 69.18);
243
+ --immich-ui-warning-600: oklch(0.907 0.07 70.22);
196
244
  --immich-ui-warning-500: oklch(0.888 0.089 72.24);
197
- --immich-ui-warning-600: oklch(0.738 0.153 79.79);
198
- --immich-ui-warning-700: oklch(0.589 0.122 79.52);
199
- --immich-ui-warning-800: oklch(0.442 0.092 79.1);
200
- --immich-ui-warning-900: oklch(0.286 0.059 78.61);
201
- --immich-ui-warning-950: oklch(0.197 0.039 78.61);
202
-
203
- --immich-ui-info-50: oklch(0.975 0.012 259.84);
204
- --immich-ui-info-100: oklch(0.956 0.021 261.78);
205
- --immich-ui-info-200: oklch(0.905 0.046 259.51);
206
- --immich-ui-info-300: oklch(0.861 0.068 259.36);
207
- --immich-ui-info-400: oklch(0.811 0.096 255.92);
245
+ --immich-ui-warning-400: oklch(0.738 0.153 79.79);
246
+ --immich-ui-warning-300: oklch(0.589 0.122 79.52);
247
+ --immich-ui-warning-200: oklch(0.442 0.092 79.1);
248
+ --immich-ui-warning-100: oklch(0.286 0.059 78.61);
249
+ --immich-ui-warning-50: oklch(0.197 0.039 78.61);
250
+
251
+ --immich-ui-info-950: oklch(0.975 0.012 259.84);
252
+ --immich-ui-info-900: oklch(0.956 0.021 261.78);
253
+ --immich-ui-info-800: oklch(0.905 0.046 259.51);
254
+ --immich-ui-info-700: oklch(0.861 0.068 259.36);
255
+ --immich-ui-info-600: oklch(0.811 0.096 255.92);
208
256
  --immich-ui-info-500: oklch(0.767 0.122 253.35);
209
- --immich-ui-info-600: oklch(0.638 0.166 246.52);
210
- --immich-ui-info-700: oklch(0.516 0.135 246.69);
211
- --immich-ui-info-800: oklch(0.386 0.1 246.5);
212
- --immich-ui-info-900: oklch(0.265 0.07 247.05);
213
- --immich-ui-info-950: oklch(0.186 0.049 247.05);
214
-
215
- --immich-ui-light: 0 0 0;
216
- --immich-ui-dark: rgb(221, 221, 221);
217
- --immich-ui-muted: 212 212 212;
218
- --immich-ui-gray: 33 33 33;
219
- --immich-ui-default-border: 33 33 33;
257
+ --immich-ui-info-400: oklch(0.638 0.166 246.52);
258
+ --immich-ui-info-300: oklch(0.516 0.135 246.69);
259
+ --immich-ui-info-200: oklch(0.386 0.1 246.5);
260
+ --immich-ui-info-100: oklch(0.265 0.07 247.05);
261
+ --immich-ui-info-50: oklch(0.186 0.049 247.05);
262
+
263
+ --immich-ui-light-50: var(--color-neutral-950);
264
+ --immich-ui-light-100: var(--color-neutral-900);
265
+ --immich-ui-light-200: var(--color-neutral-800);
266
+ --immich-ui-light-300: var(--color-neutral-700);
267
+ --immich-ui-light-400: var(--color-neutral-600);
268
+ --immich-ui-light-500: var(--color-neutral-500);
269
+ --immich-ui-light-600: var(--color-neutral-400);
270
+ --immich-ui-light-700: var(--color-neutral-300);
271
+ --immich-ui-light-800: var(--color-neutral-200);
272
+ --immich-ui-light-900: var(--color-neutral-100);
273
+ --immich-ui-light-950: var(--color-neutral-50);
274
+
275
+ --immich-ui-dark-50: var(--color-neutral-50);
276
+ --immich-ui-dark-100: var(--color-neutral-100);
277
+ --immich-ui-dark-200: var(--color-neutral-200);
278
+ --immich-ui-dark-300: var(--color-neutral-300);
279
+ --immich-ui-dark-400: var(--color-neutral-400);
280
+ --immich-ui-dark-500: var(--color-neutral-500);
281
+ --immich-ui-dark-600: var(--color-neutral-600);
282
+ --immich-ui-dark-700: var(--color-neutral-700);
283
+ --immich-ui-dark-800: var(--color-neutral-800);
284
+ --immich-ui-dark-900: var(--color-neutral-900);
285
+ --immich-ui-dark-950: var(--color-neutral-950);
286
+
287
+ --immich-ui-light: oklch(0% 0 0);
288
+ --immich-ui-dark: oklch(89% 0 271);
289
+ --immich-ui-muted: oklch(87% 0 271);
290
+ --immich-ui-gray: oklch(25% 0 271);
291
+ --immich-ui-default-border: var(--immich-ui-light-200);
220
292
  }
221
293
 
222
294
  *,
@@ -224,6 +296,6 @@
224
296
  ::before,
225
297
  ::backdrop,
226
298
  ::file-selector-button {
227
- border-color: rgb(var(--immich-ui-default-border));
299
+ border-color: var(--immich-ui-default-border);
228
300
  }
229
301
  }
package/dist/types.d.ts CHANGED
@@ -15,7 +15,6 @@ export type HeadingSize = Size | 'title';
15
15
  export type HeadingTag = 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'p';
16
16
  export type Shape = 'rectangle' | 'semi-round' | 'round';
17
17
  export type Variants = 'filled' | 'outline' | 'ghost';
18
- export type ToastVariant = 'filled' | 'outline';
19
18
  export type Gap = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8;
20
19
  export declare enum Theme {
21
20
  Light = "light",
@@ -189,7 +188,6 @@ export type ToastShow = {
189
188
  shape?: Shape;
190
189
  icon?: IconLike | false;
191
190
  size?: ContainerSize;
192
- variant?: ToastVariant;
193
191
  };
194
192
  export type ToastOptions = {
195
193
  id?: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@immich/ui",
3
- "version": "0.45.1",
3
+ "version": "0.47.0",
4
4
  "license": "GNU Affero General Public License version 3",
5
5
  "repository": {
6
6
  "type": "git",
@@ -1,38 +0,0 @@
1
- <script lang="ts">
2
- import type { Snippet } from 'svelte';
3
-
4
- interface Props {
5
- title?: string | undefined;
6
- description?: string | undefined;
7
- scrollbar?: boolean;
8
- buttons?: Snippet;
9
- children?: Snippet;
10
- }
11
-
12
- let { title = undefined, description = undefined, scrollbar = true, buttons, children }: Props = $props();
13
-
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');
16
- </script>
17
-
18
- <section class="relative">
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}
34
-
35
- <div class="{scrollbarClass} scrollbar-stable absolute {hasTitleClass} w-full overflow-y-auto">
36
- {@render children?.()}
37
- </div>
38
- </section>
@@ -1,11 +0,0 @@
1
- import type { Snippet } from 'svelte';
2
- interface Props {
3
- title?: string | undefined;
4
- description?: string | undefined;
5
- scrollbar?: boolean;
6
- buttons?: Snippet;
7
- children?: Snippet;
8
- }
9
- declare const PageLayout: import("svelte").Component<Props, {}, "">;
10
- type PageLayout = ReturnType<typeof PageLayout>;
11
- export default PageLayout;