@immich/ui 0.22.8 → 0.23.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.
@@ -26,8 +26,8 @@
26
26
  class="me-1"
27
27
  icon={isVisible ? mdiEyeOffOutline : mdiEyeOutline}
28
28
  onclick={() => (isVisible = !isVisible)}
29
- title={isVisible ? t('hidePassword', translations) : t('showPassword', translations)}
30
- aria-label={t('showPassword', translations)}
29
+ title={isVisible ? t('hide_password', translations) : t('show_password', translations)}
30
+ aria-label={t('show_password', translations)}
31
31
  />
32
32
  {/if}
33
33
  {/snippet}
@@ -17,7 +17,7 @@
17
17
  class?: string;
18
18
  color?: Color;
19
19
  variant?: Variants;
20
- translations?: TranslationProps<'darkTheme'>;
20
+ translations?: TranslationProps<'dark_theme'>;
21
21
  onChange?: (theme: Theme) => void;
22
22
  };
23
23
 
@@ -47,7 +47,7 @@
47
47
  icon={themeIcon}
48
48
  onclick={handleToggleTheme}
49
49
  class={cleanClass(className)}
50
- aria-label={t('darkTheme', translations)}
50
+ aria-label={t('dark_theme', translations)}
51
51
  role="switch"
52
52
  aria-checked={theme.value === Theme.Dark}
53
53
  />
@@ -4,7 +4,7 @@ type Props = {
4
4
  class?: string;
5
5
  color?: Color;
6
6
  variant?: Variants;
7
- translations?: TranslationProps<'darkTheme'>;
7
+ translations?: TranslationProps<'dark_theme'>;
8
8
  onChange?: (theme: Theme) => void;
9
9
  };
10
10
  declare const ThemeSwitcher: import("svelte").Component<Props, {}, "">;
package/dist/index.d.ts CHANGED
@@ -55,3 +55,4 @@ export * from './services/theme.svelte.js';
55
55
  export * from './services/translation.svelte.js';
56
56
  export * from './types.js';
57
57
  export * from './utilities/byte-units.js';
58
+ export * from './services/modalManager.svelte.js';
package/dist/index.js CHANGED
@@ -58,3 +58,4 @@ export * from './services/theme.svelte.js';
58
58
  export * from './services/translation.svelte.js';
59
59
  export * from './types.js';
60
60
  export * from './utilities/byte-units.js';
61
+ export * from './services/modalManager.svelte.js';
@@ -0,0 +1,49 @@
1
+ <script lang="ts">
2
+ import { Button, HStack, Modal, ModalBody, ModalFooter, t, type Color } from '../index.ts';
3
+ import type { Snippet } from 'svelte';
4
+
5
+ interface Props {
6
+ title?: string;
7
+ prompt?: string;
8
+ confirmText?: string;
9
+ confirmColor?: Color;
10
+ disabled?: boolean;
11
+ size?: 'small' | 'medium';
12
+ onClose: (confirmed: boolean) => void;
13
+ promptSnippet?: Snippet;
14
+ }
15
+
16
+ let {
17
+ title = t('confirm'),
18
+ prompt = t('prompt_default'),
19
+ confirmText = t('confirm'),
20
+ confirmColor = 'danger',
21
+ disabled = false,
22
+ size = 'small',
23
+ onClose,
24
+ promptSnippet,
25
+ }: Props = $props();
26
+
27
+ const handleConfirm = () => {
28
+ onClose(true);
29
+ };
30
+ </script>
31
+
32
+ <Modal {title} onClose={() => onClose(false)} {size}>
33
+ <ModalBody>
34
+ {#if promptSnippet}{@render promptSnippet()}{:else}
35
+ <p>{prompt}</p>
36
+ {/if}
37
+ </ModalBody>
38
+
39
+ <ModalFooter>
40
+ <HStack fullWidth>
41
+ <Button shape="round" color="secondary" fullWidth onclick={() => onClose(false)}>
42
+ {t('cancel')}
43
+ </Button>
44
+ <Button shape="round" color={confirmColor} fullWidth onclick={handleConfirm} {disabled}>
45
+ {confirmText}
46
+ </Button>
47
+ </HStack>
48
+ </ModalFooter>
49
+ </Modal>
@@ -0,0 +1,15 @@
1
+ import { type Color } from '../index.ts';
2
+ import type { Snippet } from 'svelte';
3
+ interface Props {
4
+ title?: string;
5
+ prompt?: string;
6
+ confirmText?: string;
7
+ confirmColor?: Color;
8
+ disabled?: boolean;
9
+ size?: 'small' | 'medium';
10
+ onClose: (confirmed: boolean) => void;
11
+ promptSnippet?: Snippet;
12
+ }
13
+ declare const ConfirmModal: import("svelte").Component<Props, {}, "">;
14
+ type ConfirmModal = ReturnType<typeof ConfirmModal>;
15
+ export default ConfirmModal;
@@ -0,0 +1,20 @@
1
+ import { type Component, type ComponentProps } from 'svelte';
2
+ import ConfirmModal from '../internal/ConfirmModal.svelte';
3
+ type OnCloseData<T> = T extends {
4
+ onClose: (data?: infer R) => void;
5
+ } ? R | undefined : T extends {
6
+ onClose: (data: infer R) => void;
7
+ } ? R : never;
8
+ type ExtendsEmptyObject<T> = keyof T extends never ? never : T;
9
+ type StripValueIfOptional<T> = T extends undefined ? undefined : T;
10
+ type OptionalParamIfEmpty<T> = ExtendsEmptyObject<T> extends never ? [] | [Record<string, never> | undefined] : [T];
11
+ declare class ModalManager {
12
+ show<T extends object>(Component: Component<T>, ...props: OptionalParamIfEmpty<Omit<T, 'onClose'>>): Promise<StripValueIfOptional<OnCloseData<T>>>;
13
+ open<T extends object, K = OnCloseData<T>>(Component: Component<T>, ...props: OptionalParamIfEmpty<Omit<T, 'onClose'>>): {
14
+ onClose: Promise<StripValueIfOptional<K>>;
15
+ close: (args_0: StripValueIfOptional<K>) => Promise<void>;
16
+ };
17
+ showDialog(options: Omit<ComponentProps<typeof ConfirmModal>, 'onClose'>): Promise<boolean>;
18
+ }
19
+ export declare const modalManager: ModalManager;
20
+ export {};
@@ -0,0 +1,32 @@
1
+ import { mount, unmount } from 'svelte';
2
+ import ConfirmModal from '../internal/ConfirmModal.svelte';
3
+ class ModalManager {
4
+ show(Component, ...props) {
5
+ return this.open(Component, ...props).onClose;
6
+ }
7
+ open(Component, ...props) {
8
+ let modal = {};
9
+ let onClose;
10
+ const deferred = new Promise((resolve) => {
11
+ onClose = async (...args) => {
12
+ await unmount(modal);
13
+ resolve(args?.[0]);
14
+ };
15
+ modal = mount(Component, {
16
+ target: document.body,
17
+ props: {
18
+ ...(props?.[0] ?? {}),
19
+ onClose,
20
+ },
21
+ });
22
+ });
23
+ return {
24
+ onClose: deferred,
25
+ close: (...args) => onClose(args[0]),
26
+ };
27
+ }
28
+ showDialog(options) {
29
+ return this.show(ConfirmModal, options);
30
+ }
31
+ }
32
+ export const modalManager = new ModalManager();
@@ -1,9 +1,12 @@
1
1
  import type { TranslationProps } from '../types.js';
2
2
  declare const defaultTranslations: {
3
3
  close: string;
4
- showPassword: string;
5
- hidePassword: string;
6
- darkTheme: string;
4
+ show_password: string;
5
+ hide_password: string;
6
+ dark_theme: string;
7
+ confirm: string;
8
+ prompt_default: string;
9
+ cancel: string;
7
10
  };
8
11
  export type Translations = typeof defaultTranslations;
9
12
  export declare const translate: <T extends keyof Translations>(key: T, overrides?: TranslationProps<T>) => string;
@@ -1,8 +1,11 @@
1
1
  const defaultTranslations = {
2
2
  close: 'Close',
3
- showPassword: 'Show password',
4
- hidePassword: 'Hide password',
5
- darkTheme: 'Toggle dark theme',
3
+ show_password: 'Show password',
4
+ hide_password: 'Hide password',
5
+ dark_theme: 'Toggle dark theme',
6
+ confirm: 'Confirm',
7
+ prompt_default: 'Are you sure you want to do this?',
8
+ cancel: 'Cancel',
6
9
  };
7
10
  let translations = $state(defaultTranslations);
8
11
  export const translate = (key, overrides) => overrides?.[key] ?? translations[key];
package/dist/types.d.ts CHANGED
@@ -109,7 +109,7 @@ export type InputProps = BaseInputProps & {
109
109
  trailingIcon?: Snippet;
110
110
  };
111
111
  export type PasswordInputProps = BaseInputProps & {
112
- translations?: TranslationProps<'showPassword' | 'hidePassword'>;
112
+ translations?: TranslationProps<'show_password' | 'hide_password'>;
113
113
  isVisible?: boolean;
114
114
  };
115
115
  export type SelectItem = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@immich/ui",
3
- "version": "0.22.8",
3
+ "version": "0.23.0",
4
4
  "license": "GNU Affero General Public License version 3",
5
5
  "scripts": {
6
6
  "create": "node scripts/create.js",
@@ -44,14 +44,14 @@
44
44
  "@sveltejs/adapter-static": "^3.0.6",
45
45
  "@sveltejs/kit": "^2.13.0",
46
46
  "@sveltejs/package": "^2.0.0",
47
- "@sveltejs/vite-plugin-svelte": "^5.0.2",
47
+ "@sveltejs/vite-plugin-svelte": "^5.1.0",
48
48
  "@tailwindcss/postcss": "^4.1.7",
49
49
  "@tailwindcss/vite": "^4.1.7",
50
50
  "@types/eslint": "^9.6.0",
51
51
  "autoprefixer": "^10.4.20",
52
52
  "eslint": "^9.7.0",
53
53
  "eslint-config-prettier": "^10.0.0",
54
- "eslint-plugin-svelte": "^2.36.0",
54
+ "eslint-plugin-svelte": "^3.9.3",
55
55
  "globals": "^16.0.0",
56
56
  "prettier": "^3.3.2",
57
57
  "prettier-plugin-svelte": "^3.2.6",
@@ -62,7 +62,7 @@
62
62
  "svelte-highlight": "^7.8.0",
63
63
  "tailwindcss": "^4.1.7",
64
64
  "typescript": "^5.0.0",
65
- "typescript-eslint": "^8.15.0",
65
+ "typescript-eslint": "^8.34.1",
66
66
  "vite": "^6.0.3",
67
67
  "vitest": "^3.0.0"
68
68
  },