refactor: use immich/ui PasswordInput (#22099)

refactor: password-input
This commit is contained in:
Jason Rasmussen 2025-09-16 16:09:09 -04:00 committed by GitHub
parent 7fe2f19258
commit 6ffd8e679e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 28 additions and 73 deletions

12
pnpm-lock.yaml generated
View File

@ -684,8 +684,8 @@ importers:
specifier: file:../open-api/typescript-sdk
version: link:../open-api/typescript-sdk
'@immich/ui':
specifier: ^0.28.0
version: 0.28.0(@internationalized/date@3.8.2)(svelte@5.35.5)
specifier: ^0.28.1
version: 0.28.1(@internationalized/date@3.8.2)(svelte@5.35.5)
'@mapbox/mapbox-gl-rtl-text':
specifier: 0.2.3
version: 0.2.3(mapbox-gl@1.13.3)
@ -2589,8 +2589,8 @@ packages:
cpu: [x64]
os: [win32]
'@immich/ui@0.28.0':
resolution: {integrity: sha512-plQedwUbAu6FqbkYxYdzTigTQU5GfsIW287VO/EIOjd9hODEZYMfIuS0eiBivWtFmSA/lR+kuNoV6JAAw84PuQ==}
'@immich/ui@0.28.1':
resolution: {integrity: sha512-FAQBPsbPaLtTYsEH+/wQxPbUI19ZPuOEScSHgSqteI601qVZNQcfU7YuinKqK94iva2RNhvUgrNGHweIBentZg==}
peerDependencies:
svelte: ^5.0.0
@ -13114,7 +13114,7 @@ snapshots:
'@docusaurus/react-loadable@6.0.0(react@18.3.1)':
dependencies:
'@types/react': 19.1.13
'@types/react': 19.1.12
react: 18.3.1
'@docusaurus/theme-classic@3.8.1(@types/react@19.1.13)(acorn@8.15.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.2)':
@ -13706,7 +13706,7 @@ snapshots:
'@img/sharp-win32-x64@0.34.3':
optional: true
'@immich/ui@0.28.0(@internationalized/date@3.8.2)(svelte@5.35.5)':
'@immich/ui@0.28.1(@internationalized/date@3.8.2)(svelte@5.35.5)':
dependencies:
'@mdi/js': 7.4.47
bits-ui: 2.9.8(@internationalized/date@3.8.2)(svelte@5.35.5)

View File

@ -28,7 +28,7 @@
"dependencies": {
"@formatjs/icu-messageformat-parser": "^2.9.8",
"@immich/sdk": "file:../open-api/typescript-sdk",
"@immich/ui": "^0.28.0",
"@immich/ui": "^0.28.1",
"@mapbox/mapbox-gl-rtl-text": "0.2.3",
"@mdi/js": "^7.4.47",
"@photo-sphere-viewer/core": "^5.11.5",

View File

@ -182,7 +182,7 @@
/>
<SettingInputField
inputType={SettingInputFieldType.TEXT}
inputType={SettingInputFieldType.NUMBER}
label={$t('admin.oauth_timeout')}
description={$t('admin.oauth_timeout_description')}
required={true}

View File

@ -1,13 +1,13 @@
<script lang="ts">
import SettingButtonsRow from '$lib/components/shared-components/settings/setting-buttons-row.svelte';
import SettingInputField from '$lib/components/shared-components/settings/setting-input-field.svelte';
import { SettingInputFieldType } from '$lib/constants';
import { getJobName } from '$lib/utils';
import { JobName, type SystemConfigDto, type SystemConfigJobDto } from '@immich/sdk';
import { isEqual } from 'lodash-es';
import { t } from 'svelte-i18n';
import { fade } from 'svelte/transition';
import type { SettingsResetEvent, SettingsSaveEvent } from '../admin-settings';
import SettingButtonsRow from '$lib/components/shared-components/settings/setting-buttons-row.svelte';
import SettingInputField from '$lib/components/shared-components/settings/setting-input-field.svelte';
import { t } from 'svelte-i18n';
import { SettingInputFieldType } from '$lib/constants';
interface Props {
savedConfig: SystemConfigDto;
@ -63,7 +63,7 @@
inputType={SettingInputFieldType.NUMBER}
label={$t('admin.job_concurrency', { values: { job: $getJobName(jobName) } })}
description=""
value="1"
value={1}
disabled={true}
title={$t('admin.job_not_concurrency_safe')}
/>

View File

@ -3,7 +3,6 @@
import IndividualSharedViewer from '$lib/components/share-page/individual-shared-viewer.svelte';
import ControlAppBar from '$lib/components/shared-components/control-app-bar.svelte';
import ImmichLogoSmallLink from '$lib/components/shared-components/immich-logo-small-link.svelte';
import PasswordField from '$lib/components/shared-components/password-field.svelte';
import ThemeButton from '$lib/components/shared-components/theme-button.svelte';
import { assetViewingStore } from '$lib/stores/asset-viewing.store';
import { user } from '$lib/stores/user.store';
@ -11,7 +10,7 @@
import { handleError } from '$lib/utils/handle-error';
import { navigate } from '$lib/utils/navigation';
import { getMySharedLink, SharedLinkType, type AssetResponseDto, type SharedLinkResponseDto } from '@immich/sdk';
import { Button } from '@immich/ui';
import { Button, PasswordInput } from '@immich/ui';
import { tick } from 'svelte';
import { t } from 'svelte-i18n';
@ -79,7 +78,7 @@
</div>
<div class="mt-4">
<form class="flex gap-x-2" novalidate {onsubmit}>
<PasswordField autocomplete="off" bind:password placeholder="Password" />
<PasswordInput autocomplete="off" bind:value={password} placeholder="Password" />
<Button type="submit">{$t('submit')}</Button>
</form>
</div>

View File

@ -1,49 +0,0 @@
<script lang="ts">
import { Icon } from '@immich/ui';
import { mdiEyeOffOutline, mdiEyeOutline } from '@mdi/js';
import { t } from 'svelte-i18n';
import type { HTMLInputAttributes } from 'svelte/elements';
interface Props extends HTMLInputAttributes {
password: string;
autocomplete: AutoFill;
required?: boolean;
onInput?: (value: string) => void;
}
let { password = $bindable(), required = true, onInput = undefined, ...rest }: Props = $props();
let showPassword = $state(false);
</script>
<div class="relative w-full">
<input
{...rest}
class="immich-form-input w-full pe-12!"
type={showPassword ? 'text' : 'password'}
{required}
value={password}
oninput={(e) => {
password = e.currentTarget.value;
onInput?.(password);
}}
/>
{#if password.length > 0}
<button
type="button"
tabindex="-1"
class="absolute inset-y-0 end-0 px-4 text-gray-700 dark:text-gray-200"
onclick={() => (showPassword = !showPassword)}
title={showPassword ? $t('hide_password') : $t('show_password')}
>
<Icon icon={showPassword ? mdiEyeOffOutline : mdiEyeOutline} size="1.25em" />
</button>
{/if}
</div>
<style>
input::-ms-reveal {
display: none;
}
</style>

View File

@ -1,15 +1,13 @@
<script lang="ts">
import { SettingInputFieldType } from '$lib/constants';
import { PasswordInput } from '@immich/ui';
import { onMount, tick, type Snippet } from 'svelte';
import { t } from 'svelte-i18n';
import { quintOut } from 'svelte/easing';
import type { FormEventHandler } from 'svelte/elements';
import { fly } from 'svelte/transition';
import PasswordField from '../password-field.svelte';
interface Props {
inputType: SettingInputFieldType;
value: string | number | undefined | null;
type Props = {
min?: number;
max?: number;
step?: string;
@ -23,7 +21,14 @@
passwordAutocomplete?: AutoFill;
descriptionSnippet?: Snippet;
trailingSnippet?: Snippet;
}
} & (
| { inputType: SettingInputFieldType.PASSWORD; value: string }
| { inputType: SettingInputFieldType.NUMBER; value: number | null | undefined }
| {
inputType: SettingInputFieldType.TEXT | SettingInputFieldType.COLOR | SettingInputFieldType.EMAIL;
value: string | null | undefined;
}
);
let {
inputType,
@ -145,15 +150,15 @@
{@render trailingSnippet?.()}
</div>
{:else}
<PasswordField
<PasswordInput
aria-describedby={description ? `${label}-desc` : undefined}
aria-labelledby="{label}-label"
size="small"
id={label}
name={label}
autocomplete={passwordAutocomplete}
{required}
password={(value || '').toString()}
onInput={(passwordValue) => (value = passwordValue)}
bind:value={value as string}
{disabled}
{title}
/>