edit form

This commit is contained in:
Seth Trowbridge 2026-03-14 21:38:19 -04:00
parent 3f999b9258
commit b4f3a7c348
2 changed files with 97 additions and 10 deletions

93
app.js
View File

@ -34,6 +34,12 @@ const decrypt =(secret)=>
} }
}; };
const copyToClipboard =(str)=>
{
alert("copied to clipboard")
// todo copy string to clipboard;
}
/** @typedef {[domain:string, username:string, password:string, codegen:string, timestamp:number, custom_kvp:Record<string, string>]} CredSet */ /** @typedef {[domain:string, username:string, password:string, codegen:string, timestamp:number, custom_kvp:Record<string, string>]} CredSet */
const vault = van.state(/**@type{CredSet[]}*/([])); const vault = van.state(/**@type{CredSet[]}*/([]));
const vaultSerialized = van.state(""); const vaultSerialized = van.state("");
@ -42,6 +48,10 @@ const password = van.state("");
const attemptsFailed = van.state(0); const attemptsFailed = van.state(0);
const preexisting = (localStorage.getItem(writeKey)||""); const preexisting = (localStorage.getItem(writeKey)||"");
const editCred = van.state(/**@type{null|CredSet}*/null);
const editInd = van.state(0);
const PasswordChange =()=> const PasswordChange =()=>
{ {
if(preexisting && attemptsFailed.val > -1) if(preexisting && attemptsFailed.val > -1)
@ -112,6 +122,54 @@ const Components = {
) )
}, },
/**@type {(label:string, cred:CredSet, credIndex:Util.Indices<CredSet>)=>HTMLFieldSetElement} */
SingleFieldForm(label, cred, credIndex){
const edit = van.state(false);
const show = van.state(false);
return $.fieldset(
$.label(
{onclick(){
if(!edit.rawVal)
{
copyToClipboard()
}
}},
label),
$.button({onclick(){editCred.val = cred; editInd.val = credIndex;}}, "Edit")
//()=> $.button({onclick(){show.val = !show.val}}, show.val ? "Hide":"Show"),
//()=> $.button({onclick(){edit.val = !edit.val}}, edit.val ? "Cancel":"Edit"),
//()=> edit.val ? $.input({type:"text", value:cred[credIndex].toString()}) : null,
//()=> edit.val ? $.button({onclick(){}}, "Save") : null,
)
},
/**@type {(cred:CredSet)=>HTMLDivElement} */
ExistingForm(cred)
{
return $.div(
$.details(
$.summary(
$.h2(cred[0]),
),
Components.SingleFieldForm("User", cred, 1),
Components.SingleFieldForm("Pass", cred, 2),
$.details(
$.summary("Delete this record"),
$.button("Delete")
)
)
)
},
Root() Root()
{ {
const input = $.input({id:"passwordField", value:password.val}); const input = $.input({id:"passwordField", value:password.val});
@ -140,6 +198,7 @@ const Components = {
else else
{ {
message = `You are starting a new session.`; message = `You are starting a new session.`;
button = `Encrypt`;
showVault = true; showVault = true;
} }
return [message, button, showVault] return [message, button, showVault]
@ -170,20 +229,36 @@ const Components = {
}, },
Modal()
{
if(editCred.val)
{
const input = $.input({value:editCred.val[editInd.val]});
return $.div(
input,
$.button({onclick(){
editCred.val[editInd.val] = input.value;
editCred.val = null;
encrypt(password.val);
}}, "Save"),
$.button({onclick(){
editCred.val = null;
}}, "Cancel")
)
}
else
{
return "no compoent"
}
},
Vault() Vault()
{ {
return $.div( return $.div(
$.h2("Vault"), $.h2("Vault"),
Components.Form, Components.Form,
vault.val.map((cred)=>{ Components.Modal,
return $.details( vault.val.map(Components.ExistingForm)
$.summary(cred[0]),
$.p(
$.strong("User Name:"),
cred[1]
)
)
})
); );
} }
} }

14
types.d.ts vendored
View File

@ -45,4 +45,16 @@ declare global
readonly tags: Van.Tags & ((namespaceURI: string) => Readonly<Record<string, Van.TagFunc<Element>>>) readonly tags: Van.Tags & ((namespaceURI: string) => Readonly<Record<string, Van.TagFunc<Element>>>)
readonly hydrate: <T extends Node>(dom: T, f: (dom: T) => T | null | undefined) => T readonly hydrate: <T extends Node>(dom: T, f: (dom: T) => T | null | undefined) => T
}; };
}
namespace Util
{
type Indices<T extends readonly unknown[]> =
Exclude<keyof T, keyof any[]> extends infer K
? K extends `${infer N extends number}` ? N : never
: never;
}
}