diff --git a/web/src/lib/components/copiable-text/CopiableText.svelte b/web/src/lib/components/copiable-text/CopiableText.svelte
new file mode 100644
index 0000000..6fa6ef2
--- /dev/null
+++ b/web/src/lib/components/copiable-text/CopiableText.svelte
@@ -0,0 +1,31 @@
+
+
+
+
+ {
+ if (e.key === 'Enter') handleCopy();
+ }}
+ />
+
diff --git a/web/src/lib/components/copiable-text/index.ts b/web/src/lib/components/copiable-text/index.ts
new file mode 100644
index 0000000..a61d73f
--- /dev/null
+++ b/web/src/lib/components/copiable-text/index.ts
@@ -0,0 +1,7 @@
+import Root from './CopiableText.svelte';
+
+export {
+ Root,
+ //
+ Root as CopiableText,
+};
diff --git a/web/src/lib/components/editable-text/EditableText.svelte b/web/src/lib/components/editable-text/EditableText.svelte
new file mode 100644
index 0000000..ae3606d
--- /dev/null
+++ b/web/src/lib/components/editable-text/EditableText.svelte
@@ -0,0 +1,73 @@
+
+
+
+ {#if asChild}
+
+ {:else}
+
+ {value}
+
+ {/if}
+
+ {
+ if (e.key === 'Enter') {
+ // @ts-ignore
+ let val = e.target.value ?? '';
+ if (!schema.safeParse(val).success) {
+ editMode = true;
+ error = true;
+ return;
+ }
+ value = val;
+ handleExitEditMode();
+ } else if (e.key === 'Escape') {
+ editMode = false;
+ }
+ }}
+ />
+
+ {
+ if (e.key === 'Enter') handleEnterEditMode();
+ }}
+ />
+
diff --git a/web/src/lib/components/editable-text/index.ts b/web/src/lib/components/editable-text/index.ts
new file mode 100644
index 0000000..b3449d8
--- /dev/null
+++ b/web/src/lib/components/editable-text/index.ts
@@ -0,0 +1,7 @@
+import Root from './EditableText.svelte';
+
+export {
+ Root,
+ //
+ Root as EditableText
+}
\ No newline at end of file
diff --git a/web/src/lib/components/page/PageHeader.svelte b/web/src/lib/components/page/PageHeader.svelte
index b252da3..4aad49d 100644
--- a/web/src/lib/components/page/PageHeader.svelte
+++ b/web/src/lib/components/page/PageHeader.svelte
@@ -11,7 +11,7 @@
WireAdmin
-
+
{#if showLogout}
-
+