diff --git a/dist/index.html b/dist/index.html
index bb3c38a..14c0c6e 100644
--- a/dist/index.html
+++ b/dist/index.html
@@ -2326,20 +2326,6 @@ function merge_text_nodes(text) {
//#endregion
//#region node_modules/svelte/src/internal/client/dom/elements/misc.js
/**
-* @param {HTMLElement} dom
-* @param {boolean} value
-* @returns {void}
-*/
-function autofocus(dom, value) {
- if (value) {
- const body = document.body;
- dom.autofocus = true;
- queue_micro_task(() => {
- if (document.activeElement === body) dom.focus();
- });
- }
-}
-/**
* The child of a textarea actually corresponds to the defaultValue property, so we need
* to remove it upon hydration to avoid a bug when someone resets the form value.
* @param {HTMLTextAreaElement} dom
@@ -4192,6 +4178,36 @@ function head(hash, render_fn) {
}
}
//#endregion
+//#region node_modules/svelte/src/internal/client/dom/elements/actions.js
+/** @import { ActionPayload } from '#client' */
+/**
+* @template P
+* @param {Element} dom
+* @param {(dom: Element, value?: P) => ActionPayload
} action
+* @param {() => P} [get_value]
+* @returns {void}
+*/
+function action(dom, action, get_value) {
+ effect(() => {
+ var payload = untrack(() => action(dom, get_value?.()) || {});
+ if (get_value && payload?.update) {
+ var inited = false;
+ /** @type {P} */
+ var prev = {};
+ render_effect(() => {
+ var value = get_value();
+ deep_read_state(value);
+ if (inited && safe_not_equal(prev, value)) {
+ prev = value;
+ /** @type {Function} */ payload.update(value);
+ }
+ });
+ inited = true;
+ }
+ if (payload?.destroy) return () => payload.destroy();
+ });
+}
+//#endregion
//#region node_modules/svelte/src/internal/shared/attributes.js
var whitespace = [..." \n\r\f\xA0\v"];
/**
@@ -5615,6 +5631,15 @@ async function importAll(data, mode = "merge", sourcePassword = "", targetKey =
};
}
//#endregion
+//#region src/lib/autofocus.js
+/**
+* Action that autofocuses an element after mount when the condition is truthy.
+* Uses a microtask to ensure the element is fully rendered.
+*/
+function autofocus(node, condition = true) {
+ if (condition) queueMicrotask(() => node.focus());
+}
+//#endregion
//#region src/components/LockScreen.svelte
var root_1$8 = /* @__PURE__ */ from_html(`
diff --git a/src/components/LockScreen.svelte b/src/components/LockScreen.svelte
index d453c94..4b4e257 100644
--- a/src/components/LockScreen.svelte
+++ b/src/components/LockScreen.svelte
@@ -3,6 +3,7 @@
import { deriveKey, createTestPayload, verifyPassword } from '../lib/crypto/crypto.js'
import { saveVaultMeta, loadVaultMeta, isVaultInitialized } from '../lib/storage/db.js'
import { startAutoLock } from '../lib/stores/security.svelte.js'
+ import { autofocus } from '../lib/autofocus.js'
let masterPassword = $state('')
let confirmPassword = $state('')
@@ -95,7 +96,7 @@
bind:value={masterPassword}
placeholder="Enter master password"
autocomplete="current-password"
- autofocus
+ use:autofocus
disabled={loading}
/>
diff --git a/src/components/Sidebar.svelte b/src/components/Sidebar.svelte
index afcfbaa..c82578e 100644
--- a/src/components/Sidebar.svelte
+++ b/src/components/Sidebar.svelte
@@ -2,6 +2,7 @@
import { getGroups, addGroup, updateGroup, deleteGroup, getEntryCountsByGroup } from '../lib/storage/db.js'
import { createGroup, validateGroup } from '../lib/models/schema.js'
import { search as searchStore } from '../lib/stores/search.svelte.js'
+ import { autofocus } from '../lib/autofocus.js'
let groups = $state([])
let entryCounts = $state(new Map())
@@ -142,7 +143,7 @@
-
+
diff --git a/src/lib/autofocus.js b/src/lib/autofocus.js
new file mode 100644
index 0000000..b90e76d
--- /dev/null
+++ b/src/lib/autofocus.js
@@ -0,0 +1,9 @@
+/**
+ * Action that autofocuses an element after mount when the condition is truthy.
+ * Uses a microtask to ensure the element is fully rendered.
+ */
+export function autofocus(node, condition = true) {
+ if (condition) {
+ queueMicrotask(() => node.focus())
+ }
+}