refactor(web): use svelte builtin id generator (#32631)
(cherry picked from commit 285552785f1bd7cb5ad431c8b3423d1d5e858188)
This commit is contained in:
@@ -22,7 +22,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { focusOutside } from '#lib/actions/focus-outside.ts';
|
import { focusOutside } from '#lib/actions/focus-outside.ts';
|
||||||
import { shortcuts } from '#lib/actions/shortcut.ts';
|
import { shortcuts } from '#lib/actions/shortcut.ts';
|
||||||
import { generateId } from '#lib/utils/generate-id.ts';
|
|
||||||
import { Icon, IconButton, Label } from '@immich/ui';
|
import { Icon, IconButton, Label } from '@immich/ui';
|
||||||
import { mdiChevronDown, mdiClose, mdiMagnify } from '@mdi/js';
|
import { mdiChevronDown, mdiClose, mdiMagnify } from '@mdi/js';
|
||||||
import { onMount, tick } from 'svelte';
|
import { onMount, tick } from 'svelte';
|
||||||
@@ -62,10 +61,6 @@
|
|||||||
forceFocus = false,
|
forceFocus = false,
|
||||||
}: Props = $props();
|
}: Props = $props();
|
||||||
|
|
||||||
/**
|
|
||||||
* Unique identifier for the combobox.
|
|
||||||
*/
|
|
||||||
let id: string = generateId();
|
|
||||||
/**
|
/**
|
||||||
* Indicates whether or not the dropdown autocomplete list should be visible.
|
* Indicates whether or not the dropdown autocomplete list should be visible.
|
||||||
*/
|
*/
|
||||||
@@ -80,6 +75,7 @@
|
|||||||
let input = $state<HTMLInputElement>();
|
let input = $state<HTMLInputElement>();
|
||||||
let bounds: DOMRect | undefined = $state();
|
let bounds: DOMRect | undefined = $state();
|
||||||
|
|
||||||
|
const id = $props.id();
|
||||||
const inputId = `combobox-${id}`;
|
const inputId = `combobox-${id}`;
|
||||||
const listboxId = `listbox-${id}`;
|
const listboxId = `listbox-${id}`;
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import NumberRangeInput from '#lib/components/shared-components/NumberRangeInput.svelte';
|
import NumberRangeInput from '#lib/components/shared-components/NumberRangeInput.svelte';
|
||||||
import { generateId } from '#lib/utils/generate-id.ts';
|
|
||||||
import { convert } from 'geo-coordinates-parser';
|
import { convert } from 'geo-coordinates-parser';
|
||||||
import { t } from 'svelte-i18n';
|
import { t } from 'svelte-i18n';
|
||||||
|
|
||||||
@@ -12,7 +11,7 @@
|
|||||||
|
|
||||||
let { lat = $bindable(), lng = $bindable(), onUpdate }: Props = $props();
|
let { lat = $bindable(), lng = $bindable(), onUpdate }: Props = $props();
|
||||||
|
|
||||||
const id = generateId();
|
const id = $props.id();
|
||||||
|
|
||||||
const onInput = () => {
|
const onInput = () => {
|
||||||
if (lat !== undefined && lng !== undefined) {
|
if (lat !== undefined && lng !== undefined) {
|
||||||
|
|||||||
@@ -9,7 +9,6 @@
|
|||||||
getContextMenuPositionFromEvent,
|
getContextMenuPositionFromEvent,
|
||||||
type Align,
|
type Align,
|
||||||
} from '#lib/utils/context-menu.ts';
|
} from '#lib/utils/context-menu.ts';
|
||||||
import { generateId } from '#lib/utils/generate-id.ts';
|
|
||||||
import { IconButton, type Color, type Size, type Variants } from '@immich/ui';
|
import { IconButton, type Color, type Size, type Variants } from '@immich/ui';
|
||||||
import type { Snippet } from 'svelte';
|
import type { Snippet } from 'svelte';
|
||||||
import type { HTMLAttributes } from 'svelte/elements';
|
import type { HTMLAttributes } from 'svelte/elements';
|
||||||
@@ -61,7 +60,7 @@
|
|||||||
let menuContainer: HTMLUListElement | undefined = $state();
|
let menuContainer: HTMLUListElement | undefined = $state();
|
||||||
let buttonContainer: HTMLDivElement | undefined = $state();
|
let buttonContainer: HTMLDivElement | undefined = $state();
|
||||||
|
|
||||||
const id = generateId();
|
const id = $props.id();
|
||||||
const buttonId = `context-menu-button-${id}`;
|
const buttonId = `context-menu-button-${id}`;
|
||||||
const menuId = `context-menu-${id}`;
|
const menuId = `context-menu-${id}`;
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
import type { Shortcut } from '#lib/actions/shortcut.ts';
|
import type { Shortcut } from '#lib/actions/shortcut.ts';
|
||||||
import { shortcut as bindShortcut, shortcutLabel as computeShortcutLabel } from '#lib/actions/shortcut.ts';
|
import { shortcut as bindShortcut, shortcutLabel as computeShortcutLabel } from '#lib/actions/shortcut.ts';
|
||||||
import { optionClickCallbackStore, selectedIdStore } from '#lib/stores/context-menu.store.ts';
|
import { optionClickCallbackStore, selectedIdStore } from '#lib/stores/context-menu.store.ts';
|
||||||
import { generateId } from '#lib/utils/generate-id.ts';
|
|
||||||
import { Icon, type IconLike } from '@immich/ui';
|
import { Icon, type IconLike } from '@immich/ui';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
@@ -27,9 +26,8 @@
|
|||||||
shortcutLabel = '',
|
shortcutLabel = '',
|
||||||
}: Props = $props();
|
}: Props = $props();
|
||||||
|
|
||||||
let id: string = generateId();
|
const id = $props.id();
|
||||||
|
const isActive = $derived($selectedIdStore === id);
|
||||||
let isActive = $derived($selectedIdStore === id);
|
|
||||||
|
|
||||||
const handleClick = (event: MouseEvent) => {
|
const handleClick = (event: MouseEvent) => {
|
||||||
// eslint-disable-next-line unicorn/no-optional-chaining-on-undeclared-variable
|
// eslint-disable-next-line unicorn/no-optional-chaining-on-undeclared-variable
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
import { Route } from '#lib/route.ts';
|
import { Route } from '#lib/route.ts';
|
||||||
import { searchStore } from '#lib/stores/search.svelte.ts';
|
import { searchStore } from '#lib/stores/search.svelte.ts';
|
||||||
import { handlePromiseError } from '#lib/utils.ts';
|
import { handlePromiseError } from '#lib/utils.ts';
|
||||||
import { generateId } from '#lib/utils/generate-id.ts';
|
|
||||||
import { IconButton } from '@immich/ui';
|
import { IconButton } from '@immich/ui';
|
||||||
import { mdiClose, mdiMagnify } from '@mdi/js';
|
import { mdiClose, mdiMagnify } from '@mdi/js';
|
||||||
import { onDestroy, tick } from 'svelte';
|
import { onDestroy, tick } from 'svelte';
|
||||||
@@ -29,8 +28,7 @@
|
|||||||
let showSuggestions = $state(false);
|
let showSuggestions = $state(false);
|
||||||
let selectedId: string | undefined = $state();
|
let selectedId: string | undefined = $state();
|
||||||
|
|
||||||
const listboxId = generateId();
|
const listboxId = $props.id();
|
||||||
const searchTypeId = generateId();
|
|
||||||
|
|
||||||
onDestroy(() => {
|
onDestroy(() => {
|
||||||
searchStore.isSearchEnabled = false;
|
searchStore.isSearchEnabled = false;
|
||||||
@@ -173,7 +171,6 @@
|
|||||||
aria-activedescendant={selectedId ?? ''}
|
aria-activedescendant={selectedId ?? ''}
|
||||||
aria-expanded={showSuggestions}
|
aria-expanded={showSuggestions}
|
||||||
aria-autocomplete="list"
|
aria-autocomplete="list"
|
||||||
aria-describedby={searchTypeId}
|
|
||||||
use:shortcuts={[
|
use:shortcuts={[
|
||||||
{ shortcut: { key: 'Escape' }, onShortcut: onEscape },
|
{ shortcut: { key: 'Escape' }, onShortcut: onEscape },
|
||||||
{ shortcut: { key: 'ArrowUp' }, onShortcut: () => onArrow(-1) },
|
{ shortcut: { key: 'ArrowUp' }, onShortcut: () => onArrow(-1) },
|
||||||
|
|||||||
@@ -1,12 +1,11 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { generateId } from '#lib/utils/generate-id.ts';
|
|
||||||
import { Switch } from '@immich/ui';
|
import { Switch } from '@immich/ui';
|
||||||
import type { Snippet } from 'svelte';
|
import type { Snippet } from 'svelte';
|
||||||
import { t } from 'svelte-i18n';
|
import { t } from 'svelte-i18n';
|
||||||
import { quintOut } from 'svelte/easing';
|
import { quintOut } from 'svelte/easing';
|
||||||
import { fly } from 'svelte/transition';
|
import { fly } from 'svelte/transition';
|
||||||
|
|
||||||
interface Props {
|
type Props = {
|
||||||
title: string;
|
title: string;
|
||||||
subtitle?: string;
|
subtitle?: string;
|
||||||
checked?: boolean;
|
checked?: boolean;
|
||||||
@@ -14,7 +13,7 @@
|
|||||||
isEdited?: boolean;
|
isEdited?: boolean;
|
||||||
onToggle?: (isChecked: boolean) => void;
|
onToggle?: (isChecked: boolean) => void;
|
||||||
children?: Snippet;
|
children?: Snippet;
|
||||||
}
|
};
|
||||||
|
|
||||||
let {
|
let {
|
||||||
title,
|
title,
|
||||||
@@ -26,10 +25,9 @@
|
|||||||
children,
|
children,
|
||||||
}: Props = $props();
|
}: Props = $props();
|
||||||
|
|
||||||
let id: string = generateId();
|
const id = $props.id();
|
||||||
|
const switchId = `input-${id}`;
|
||||||
let switchId = $derived(`input-${id}`);
|
const subtitleId = $derived(subtitle ? `${id}-subtitle` : undefined);
|
||||||
let subtitleId = $derived(subtitle ? `${id}-subtitle` : undefined);
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="flex place-items-center justify-between">
|
<div class="flex place-items-center justify-between">
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { generateId } from '#lib/utils/generate-id.ts';
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
filters: string[];
|
filters: string[];
|
||||||
labels?: string[];
|
labels?: string[];
|
||||||
@@ -9,9 +7,9 @@
|
|||||||
onSelect: (selected: string) => void;
|
onSelect: (selected: string) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
let { filters, selected, label, labels, onSelect }: Props = $props();
|
const { filters, selected, label, labels, onSelect }: Props = $props();
|
||||||
|
|
||||||
const id = `group-tab-${generateId()}`;
|
const id = $props.id();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<fieldset
|
<fieldset
|
||||||
|
|||||||
@@ -1,28 +1,27 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { focusOutside } from '#lib/actions/focus-outside.ts';
|
import { focusOutside } from '#lib/actions/focus-outside.ts';
|
||||||
import { shortcuts } from '#lib/actions/shortcut.ts';
|
import { shortcuts } from '#lib/actions/shortcut.ts';
|
||||||
import { generateId } from '#lib/utils/generate-id.ts';
|
|
||||||
import { Icon } from '@immich/ui';
|
import { Icon } from '@immich/ui';
|
||||||
import { mdiStar, mdiStarOutline } from '@mdi/js';
|
import { mdiStar, mdiStarOutline } from '@mdi/js';
|
||||||
import { t } from 'svelte-i18n';
|
import { t } from 'svelte-i18n';
|
||||||
|
|
||||||
export type Rating = -1 | 1 | 2 | 3 | 4 | 5 | null;
|
export type Rating = -1 | 1 | 2 | 3 | 4 | 5 | null;
|
||||||
|
|
||||||
interface Props {
|
type Props = {
|
||||||
count?: number;
|
count?: number;
|
||||||
rating: Rating;
|
rating: Rating;
|
||||||
readOnly?: boolean;
|
readOnly?: boolean;
|
||||||
onRating: (rating: Rating) => void | undefined;
|
onRating: (rating: Rating) => void | undefined;
|
||||||
}
|
};
|
||||||
|
|
||||||
let { count = 5, rating, readOnly = false, onRating }: Props = $props();
|
const { count = 5, rating, readOnly = false, onRating }: Props = $props();
|
||||||
|
|
||||||
let ratingSelection = $derived(rating);
|
let ratingSelection = $derived(rating);
|
||||||
let hoverRating: Rating = $state(null);
|
let hoverRating: Rating = $state(null);
|
||||||
let focusRating: Rating = $state(null);
|
let focusRating: Rating = $state(null);
|
||||||
let timeoutId: ReturnType<typeof setTimeout> | undefined;
|
let timeoutId: ReturnType<typeof setTimeout> | undefined;
|
||||||
|
|
||||||
const id = generateId();
|
const id = $props.id();
|
||||||
|
|
||||||
const handleSelect = (newRating: Rating) => {
|
const handleSelect = (newRating: Rating) => {
|
||||||
if (readOnly) {
|
if (readOnly) {
|
||||||
|
|||||||
@@ -1,2 +0,0 @@
|
|||||||
let _count = 0;
|
|
||||||
export const generateId = (): string => `id-${_count++}`;
|
|
||||||
@@ -7,7 +7,6 @@
|
|||||||
import { getWorkflowQuery, updateWorkflowMutation } from '#lib/queries/workflow.query.ts';
|
import { getWorkflowQuery, updateWorkflowMutation } from '#lib/queries/workflow.query.ts';
|
||||||
import { Route } from '#lib/route.ts';
|
import { Route } from '#lib/route.ts';
|
||||||
import { getWorkflowActions } from '#lib/services/workflow.service.ts';
|
import { getWorkflowActions } from '#lib/services/workflow.service.ts';
|
||||||
import { generateId } from '#lib/utils/generate-id.ts';
|
|
||||||
import { getTriggerDescription, getTriggerName } from '#lib/utils/workflow.ts';
|
import { getTriggerDescription, getTriggerName } from '#lib/utils/workflow.ts';
|
||||||
import type { WorkflowUpdateDto } from '@immich/sdk';
|
import type { WorkflowUpdateDto } from '@immich/sdk';
|
||||||
import {
|
import {
|
||||||
@@ -63,6 +62,9 @@
|
|||||||
const query = createPreloadedQuery(() => getWorkflowQuery(params.workflowId));
|
const query = createPreloadedQuery(() => getWorkflowQuery(params.workflowId));
|
||||||
const workflow = $derived(query.data);
|
const workflow = $derived(query.data);
|
||||||
|
|
||||||
|
let stepCounter = 0;
|
||||||
|
const generateId = () => `step-${stepCounter++}`;
|
||||||
|
|
||||||
let { id, enabled, name, description, trigger } = $state(query.data);
|
let { id, enabled, name, description, trigger } = $state(query.data);
|
||||||
let steps = $state(query.data.steps.map((step) => ({ ...step, id: generateId() })));
|
let steps = $state(query.data.steps.map((step) => ({ ...step, id: generateId() })));
|
||||||
const savedWorkflow = $derived(cloneDeep(workflow));
|
const savedWorkflow = $derived(cloneDeep(workflow));
|
||||||
|
|||||||
Reference in New Issue
Block a user