@openparachute/app 0.22.15-rc.6 → 0.22.15-rc.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/.parachute/info +1 -1
- package/dist/assets/{Account-K_xK2X9B.js → Account-DVrOc5d2.js} +1 -1
- package/dist/assets/{Activity-BL33NLB_.js → Activity-0hs_ikJM.js} +1 -1
- package/dist/assets/{AddVault-CTe-mwRH.js → AddVault-BB-AFOmL.js} +1 -1
- package/dist/assets/{AddVaultChooser-BPJV1MeI.js → AddVaultChooser-n8eLZ11X.js} +1 -1
- package/dist/assets/{AddVaultCreate-DI73o6uE.js → AddVaultCreate-BVyIpnXh.js} +1 -1
- package/dist/assets/AttachmentDropZone-TqaFTJWk.js +1 -0
- package/dist/assets/{Calendar-CaIuHTLe.js → Calendar-BFFWBFvP.js} +1 -1
- package/dist/assets/{CheckEmail-CqFmFCks.js → CheckEmail-PgQKYluA.js} +1 -1
- package/dist/assets/{useAttachmentUploader-DNhr7cOE.js → CodeMirrorEditor-DxXQL_Yv.js} +18 -18
- package/dist/assets/{ConnectAI-DHagDo44.js → ConnectAI-DvGvVaFL.js} +1 -1
- package/dist/assets/{DayView-GOUuDzfi.js → DayView-DckpX5OB.js} +1 -1
- package/dist/assets/{Export-YCQBcJkP.js → Export-nog6GkVZ.js} +1 -1
- package/dist/assets/{Import-kCFoVM-8.js → Import-kMnqJ0Zy.js} +2 -2
- package/dist/assets/NoteEditor-DJJzL6og.js +1 -0
- package/dist/assets/{NoteNew-BHjrbBq2.js → NoteNew-CNO1wteU.js} +2 -2
- package/dist/assets/NoteView-BkwjWffV.js +9 -0
- package/dist/assets/{OAuthCallback-BPLeIM87.js → OAuthCallback-Bqwbh5dE.js} +1 -1
- package/dist/assets/{PinArchiveButtons-z6H_YGSc.js → PinArchiveButtons-6XVGmX0l.js} +1 -1
- package/dist/assets/{Settings-Ck3g9l6D.js → Settings-B44TjE-J.js} +1 -1
- package/dist/assets/{TagPage-oQqARXqf.js → TagPage-BvHAtmih.js} +1 -1
- package/dist/assets/{TagSchemaEditor-D_LYDGRK.js → TagSchemaEditor-Bv9OJXDP.js} +1 -1
- package/dist/assets/{Tags-CyP_yKov.js → Tags-XxPefjNE.js} +1 -1
- package/dist/assets/{VaultGraph-Di0B4NaD.js → VaultGraph-B8m-aKEP.js} +2 -2
- package/dist/assets/{Vaults-BMJUdDaM.js → Vaults-PLbdO3kQ.js} +1 -1
- package/dist/assets/{ViewNew-Um87-wU2.js → ViewNew-WUgtqEUn.js} +1 -1
- package/dist/assets/{ViewSurface-D8xrFE_I.js → ViewSurface-B3tMmOMq.js} +1 -1
- package/dist/assets/{Welcome-Cb7SFRmw.js → Welcome-Bncj2rBF.js} +1 -1
- package/dist/assets/{WizardShell-CDZWRkFh.js → WizardShell-Cp46Sjm6.js} +1 -1
- package/dist/assets/attachment-upload-DML2Fh0E.js +2 -0
- package/dist/assets/{history-B2ZH4y8B.js → history-DeQhlq0x.js} +1 -1
- package/dist/assets/{index-CkXqzhj_.js → index-BwG_4Oup.js} +15 -15
- package/dist/assets/index-eHCCOf4I.css +1 -0
- package/dist/assets/{provenance-DnIXLZVC.js → provenance-D_yuCkJz.js} +1 -1
- package/dist/assets/{react-force-graph-2d-C179xgl7.js → react-force-graph-2d-iGY_edo3.js} +1 -1
- package/dist/assets/{transcribe-default-Z7qqgq1r.js → transcribe-default-Cz5r46Dt.js} +1 -1
- package/dist/assets/{NoteRenderer-CN_XExeX.js → useAttachmentUploader-CR8KEhCu.js} +24 -24
- package/dist/index.html +2 -2
- package/dist/sw.js +1 -1
- package/meta.json +1 -1
- package/package.json +1 -1
- package/dist/assets/NoteEditor-BcJb5-4o.js +0 -1
- package/dist/assets/NoteView-DtbLplBa.js +0 -3
- package/dist/assets/attachment-upload-B0biPzAc.js +0 -2
- package/dist/assets/index-D-RN2HHm.css +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{r as n,j as e,ak as H,ar as le,V as I,al as ce,as as de,b as J,at as ue,N as me,L as $,J as fe,K as he,e as xe,au as K,av as pe,aw as ge,ax as be,ay as ve,am as je,az as P,aA as Ne,aB as we,aC as ye,M as F,aD as Se}from"./index-BwG_4Oup.js";import{A as ke}from"./AttachmentDropZone-TqaFTJWk.js";import{b as Ce,u as Ee,N as Re,A as Ae,a as De}from"./useAttachmentUploader-CR8KEhCu.js";import{C as Te}from"./CodeMirrorEditor-DxXQL_Yv.js";import{P as Pe,D as Ie}from"./PinArchiveButtons-6XVGmX0l.js";import{r as $e}from"./editor-mode-D9fveTEx.js";import"./attachment-upload-DML2Fh0E.js";const Fe=250;function Le({noteId:t,attachment:a}){const[r,i]=n.useState(!1),x=Be(a);return e.jsxs(e.Fragment,{children:[e.jsx("button",{type:"button",onClick:()=>i(!0),"aria-label":`Remove attachment ${x}`,className:"shrink-0 rounded border border-transparent px-1.5 py-0.5 text-fg-dim hover:border-red-500/40 hover:text-red-400",children:"✕"}),r?e.jsx(Ve,{noteId:t,attachment:a,label:x,onClose:()=>i(!1)}):null]})}function Ve({noteId:t,attachment:a,label:r,onClose:i}){const x=H(c=>c.push),l=le(),[u,m]=n.useState(!1),[f,N]=n.useState(null),d=n.useRef(null);n.useEffect(()=>{const c=setTimeout(()=>m(!0),Fe);return()=>clearTimeout(c)},[]),n.useEffect(()=>{var c;(c=d.current)==null||c.focus()},[]),n.useEffect(()=>{const c=k=>{k.key==="Escape"&&i()};return window.addEventListener("keydown",c),()=>window.removeEventListener("keydown",c)},[i]);const g=n.useCallback(()=>{!u||l.isPending||(N(null),l.mutate({noteId:t,attachmentId:a.id},{onSuccess:()=>{x(`Removed ${r}`,"success"),i()},onError:c=>{if(c instanceof I){N("Session expired. Reconnect to remove attachments.");return}if(c instanceof ce){x(`Already removed ${r}`,"info"),i();return}N(c instanceof Error?c.message:"Remove failed")}}))},[u,a.id,r,l,t,i,x]);return e.jsx("dialog",{open:!0,"aria-labelledby":"confirm-remove-attachment-title",className:"fixed inset-0 z-40 m-0 flex h-full max-h-full w-full max-w-full items-center justify-center bg-black/60 p-4",onMouseDown:c=>{c.target===c.currentTarget&&i()},children:e.jsxs("div",{className:"w-full max-w-md rounded-2xl border border-border bg-card p-6 shadow-lift",children:[e.jsx("h2",{id:"confirm-remove-attachment-title",className:"mb-2 font-serif text-lg text-red-400",children:"Remove attachment?"}),e.jsxs("p",{className:"mb-3 text-sm text-fg-muted",children:[e.jsx("span",{className:"rounded bg-bg/60 px-1 py-0.5 font-mono text-xs text-fg",children:r})," ","will be detached from this note. If no other note references the file, it will also be deleted from storage. Markdown referencing it will show a broken link until you update it."]}),f?e.jsx("p",{role:"alert",className:"mb-3 text-sm text-red-400",children:f}):null,e.jsxs("div",{className:"flex justify-end gap-2",children:[e.jsx("button",{ref:d,type:"button",onClick:i,className:"min-h-11 rounded-lg border border-border bg-card px-3 py-1.5 text-sm text-fg-muted hover:text-fg",children:"Cancel"}),e.jsx("button",{type:"button",onClick:g,disabled:!u||l.isPending,className:"btn btn-danger-solid btn-touch",children:l.isPending?"Removing…":"Remove"})]})]})})}function Be(t){if(t.filename)return t.filename;if(t.path){const a=t.path.split("/").pop();return a||t.path}return t.id}function et(){const{id:t}=de(),a=J(i=>i.getActiveVault()),r=ue(t);return a?e.jsxs("div",{className:"page",children:[e.jsx("nav",{className:"mb-6 text-sm text-fg-dim",children:e.jsx($,{to:t?`/n/${encodeURIComponent(t)}`:"/",className:"focus-ring hover:text-accent",children:"← Back to note"})}),r.isPending?e.jsx(_e,{}):r.isError?e.jsx(We,{error:r.error}):r.data?e.jsx(Me,{note:r.data}):e.jsx(ze,{id:t??""})]}):e.jsx(me,{to:"/",replace:!0})}function S(t){return{content:t.content??"",path:t.path??"",tags:[...t.tags??[]]}}function Me({note:t}){const a=xe(),r=H(s=>s.push),i=K(s=>s.on),x=K(s=>s.setOn),l=n.useRef(J.getState().activeVaultId).current,u=n.useRef($e()).current,m=n.useMemo(()=>Ce(t),[t]),[f,N]=n.useState(()=>S(t)),[d,g]=n.useState(()=>S(t)),[c,k]=n.useState(()=>{if(!l)return null;const s=pe(l,t.id);return!s||ge(s.body,S(t))?null:s}),[G,L]=n.useState(""),[V,C]=n.useState(null),[B,E]=n.useState(null),[M,U]=n.useState(!1),w=n.useRef(null);n.useEffect(()=>()=>{w.current!==null&&window.clearTimeout(w.current)},[]);const[R,Q]=n.useState("edit"),j=be(t.id),A=n.useRef(t),D=n.useRef(null),O=n.useRef(null),v=Ee({noteId:t.id,onInsert:s=>{D.current?D.current.insertAtCursor(s):g(o=>({...o,content:`${o.content}${s}`}))},onLinked:()=>{r("Attachment added","success")},onError:s=>r(s,"error")});n.useEffect(()=>{A.current=t},[t]);const h=d.content!==f.content||d.path!==f.path||!qe(d.tags,f.tags);ve(l,t.id,d,h);const y=v.uploads.some(s=>s.status==="uploading"||s.status==="linking"),T=n.useCallback(({navigateToView:s})=>{if(!h||j.isPending||y)return;const o={};d.content!==f.content&&(o.content=d.content),d.path!==f.path&&(o.path=d.path);const b=Ke(f.tags,d.tags);(b.add.length||b.remove.length)&&(o.tags=b);const q=A.current.updatedAt??A.current.createdAt;q&&(o.if_updated_at=q),E(null),C(null),j.mutate(o,{onSuccess:p=>{N(S(p)),g(S(p)),A.current=p,l&&P(l,t.id),s?a(`/n/${encodeURIComponent(p.id)}`,{replace:!0}):p.id!==t.id&&a(`/n/${encodeURIComponent(p.id)}/edit`,{replace:!0}),s||(U(!0),w.current!==null&&window.clearTimeout(w.current),w.current=window.setTimeout(()=>U(!1),1500))},onError:p=>{p instanceof je?C(p):p instanceof I?E("Session expired. Reconnect to save."):E(p instanceof Error?p.message:"Save failed")}})},[f,d,h,j,a,t.id,y,l]),X=n.useCallback(()=>{c&&g(c.body),k(null)},[c]),ee=n.useCallback(()=>{l&&P(l,t.id),k(null)},[l,t.id]),te=n.useCallback(()=>T({navigateToView:!0}),[T]),se=n.useCallback(()=>T({navigateToView:!1}),[T]),ne=n.useCallback(()=>{h&&confirm("Discard all edits and revert to last saved version?")&&(g(f),C(null),E(null))},[f,h]),_=n.useCallback(()=>{h&&!confirm("Discard unsaved changes?")||(l&&P(l,t.id),a(`/n/${encodeURIComponent(t.id)}`))},[h,a,t.id,l]);n.useEffect(()=>{if(!h)return;const s=o=>{o.preventDefault(),o.returnValue=""};return window.addEventListener("beforeunload",s),()=>window.removeEventListener("beforeunload",s)},[h]);const z=n.useRef(i);n.useEffect(()=>{var o;const s=i&&!z.current;z.current=i,s&&((o=D.current)==null||o.focus())},[i]);const ae=d.path!==f.path,re=s=>{const o=Se(s);o&&(d.tags.includes(o)||(g(b=>({...b,tags:[...b.tags,o]})),L("")))},ie=s=>{g(o=>({...o,tags:o.tags.filter(b=>b!==s)}))},oe=d.content,W=i?"h-[85dvh]":"h-[60dvh]";return e.jsxs("article",{children:[i?e.jsx("div",{className:"glass-panel enter-fade fixed top-4 left-4 z-30 rounded-full border border-border px-3 py-1.5 text-xs shadow-lift",style:{marginTop:"env(safe-area-inset-top)"},children:e.jsx(Y,{isDirty:h,justSaved:M,updatedAt:t.updatedAt})}):e.jsxs("header",{className:"card mb-6 p-5 shadow-soft md:p-6",children:[e.jsxs("div",{className:"flex flex-wrap items-center justify-between gap-3",children:[e.jsxs("div",{className:"flex items-center gap-2 text-sm",children:[e.jsx("span",{className:"eyebrow",children:"Editing"}),e.jsx(Y,{isDirty:h,justSaved:M,updatedAt:t.updatedAt})]}),e.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[e.jsx(Pe,{note:t}),e.jsx(Ie,{note:t}),e.jsxs("button",{type:"button",onClick:()=>x(!0),className:"btn btn-ghost btn-touch",title:"Focus (⌘.)",children:[e.jsx(Ne,{width:16,height:16}),"Focus"]}),e.jsx("span",{className:"mx-1 h-5 w-px bg-border","aria-hidden":"true"}),e.jsx("button",{type:"button",onClick:ne,disabled:!h||j.isPending,className:"btn btn-secondary btn-touch",children:"Revert"}),e.jsx("button",{type:"button",onClick:_,className:"btn btn-secondary btn-touch",children:"Cancel"}),e.jsx("button",{type:"button",onClick:te,disabled:!h||j.isPending||y,className:"btn btn-primary btn-touch",title:y?"Waiting for upload…":"Save (⌘S)","aria-label":y?"Save — waiting for upload…":"Save",children:j.isPending?"Saving…":"Save"})]})]}),e.jsx("div",{className:"mt-4",children:e.jsx(we,{tags:d.tags,input:G,onInputChange:L,onAdd:re,onRemove:ie})}),e.jsxs("div",{className:"mt-4 flex items-center gap-2 text-fg-dim",children:[e.jsx("span",{"aria-hidden":"true",className:"shrink-0 text-xs",children:"Path"}),e.jsx("input",{type:"text",value:d.path,onChange:s=>g(o=>({...o,path:s.target.value})),className:"focus-ring w-full min-w-0 truncate rounded border-0 bg-transparent font-mono text-xs text-fg-dim outline-none transition-colors hover:text-fg-muted focus:text-fg placeholder:text-fg-dim","aria-label":"Note path",placeholder:"(no path)",title:d.path||void 0})]}),ae?e.jsx("p",{className:"mt-1 text-xs text-accent",children:"Renaming moves the note — its id may change."}):null,ye(d.path)?e.jsx("p",{className:"mt-1 text-xs text-danger",children:"This path is reserved for a built-in view. Notes saved here will not appear in the Views rail."}):null]}),c?e.jsxs("div",{role:"status","data-testid":"draft-offer",className:"mb-4 flex flex-wrap items-center justify-between gap-2 rounded-xl border border-accent/30 bg-accent/5 px-3 py-2 text-sm",children:[e.jsxs("span",{className:"text-fg-muted",children:["You have an unsaved draft from ",F(c.savedAt),"."]}),e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("button",{type:"button",onClick:X,className:"focus-ring font-medium text-accent hover:underline",children:"Restore"}),e.jsx("button",{type:"button",onClick:ee,className:"focus-ring text-fg-dim hover:text-danger",children:"Discard"})]})]}):null,V?e.jsx(Oe,{conflict:V,onReload:()=>{l&&P(l,t.id),window.location.reload()},onDismiss:()=>C(null)}):null,B?e.jsx("div",{className:"mb-4 rounded-xl border border-danger-border bg-danger-soft p-3 text-sm text-danger",children:B}):null,u?null:e.jsx("div",{role:"tablist","aria-label":"Editor view",className:"mb-3 inline-flex rounded-lg border border-border bg-card p-0.5 text-sm lg:hidden",children:["edit","preview"].map(s=>e.jsx("button",{type:"button",role:"tab","aria-selected":R===s,onClick:()=>Q(s),className:`rounded-sm px-3 py-1.5 capitalize ${R===s?"bg-accent text-on-accent":"text-fg-muted hover:text-accent"}`,children:s},s))}),e.jsxs("div",{className:`grid ${i?"min-h-[85dvh]":"min-h-[60dvh]"} gap-4 ${u?"":"lg:grid-cols-2"}`,children:[e.jsx(ke,{onDropFiles:v.start,className:`card min-h-0 ${W} min-w-0 ${u||R==="edit"?"":"hidden lg:block"}`,hint:Z,children:e.jsx(Te,{ref:D,value:d.content,onChange:s=>g(o=>({...o,content:s})),onSave:se,onCancel:_,onPasteFile:s=>(v.start(s),!0),onRequestAttachment:()=>{var s;return(s=O.current)==null?void 0:s.open()},livePreview:u})}),u?null:e.jsx("div",{className:`card min-h-0 ${W} min-w-0 overflow-auto p-4 ${R==="preview"?"":"hidden lg:block"}`,children:e.jsx(Re,{note:{path:d.path,content:oe},resolve:m})})]}),e.jsx(Ue,{noteId:t.id,pickerRef:O,attachments:t.attachments??[],uploads:v.uploads,onPickFiles:v.start,onCancel:v.cancel,onDismiss:v.dismiss})]})}const Z=e.jsxs(e.Fragment,{children:["Images, audio, webm video."," ",e.jsx("a",{href:"https://github.com/ParachuteComputer/parachute-vault/issues/127",target:"_blank",rel:"noreferrer",className:"text-accent hover:underline",children:"PDF + mp4 coming"})]});function Ue({noteId:t,pickerRef:a,attachments:r,uploads:i,onPickFiles:x,onCancel:l,onDismiss:u}){return e.jsxs("section",{className:"mt-6 border-t border-border pt-4",children:[e.jsxs("div",{className:"mb-3 flex items-center justify-between",children:[e.jsx("h2",{className:"font-serif text-xl",children:"Attachments"}),e.jsx(Ae,{ref:a,onPickFiles:x})]}),e.jsxs("p",{className:"mb-3 text-xs text-fg-dim",children:["Drop or paste files into the editor. Max 100 MB each. ",Z,"."]}),e.jsx(De,{uploads:i,onCancel:l,onDismiss:u}),r.length>0?e.jsx("ul",{className:"mt-3 space-y-1 text-sm",children:r.map(m=>e.jsxs("li",{className:"flex items-center justify-between gap-2 rounded-lg border border-border bg-card/50 px-3 py-1.5 font-mono text-xs",children:[e.jsx("span",{className:"truncate",title:m.path??m.id,children:m.filename??m.path??m.id}),e.jsxs("div",{className:"flex shrink-0 items-center gap-2",children:[m.mimeType?e.jsx("span",{className:"text-fg-dim",children:m.mimeType}):null,e.jsx(Le,{noteId:t,attachment:m})]})]},m.id))}):null]})}function Oe({conflict:t,onReload:a,onDismiss:r}){return e.jsxs("div",{className:"mb-4 rounded-xl border border-warning bg-warning-soft p-4",children:[e.jsx("p",{className:"mb-1 font-medium text-warning",children:"This note was edited elsewhere."}),e.jsxs("p",{className:"mb-3 text-sm text-fg-muted",children:["Your save was rejected to avoid overwriting the other edit.",t.currentUpdatedAt?` Latest update ${F(t.currentUpdatedAt)}.`:""]}),e.jsxs("div",{className:"flex flex-wrap gap-2",children:[e.jsx("button",{type:"button",onClick:a,className:"btn btn-primary btn-touch",children:"Reload latest (discard my edits)"}),e.jsx("button",{type:"button",onClick:r,className:"btn btn-secondary btn-touch",children:"Keep editing"})]})]})}function _e(){return e.jsxs("div",{className:"grid min-h-[60dvh] gap-4 lg:grid-cols-2","aria-busy":"true",children:[e.jsx("div",{className:"card animate-pulse"}),e.jsx("div",{className:"card animate-pulse"})]})}function ze({id:t}){return e.jsx(he,{title:e.jsx("span",{className:"font-serif text-xl text-fg",children:"Note not found"}),description:e.jsxs(e.Fragment,{children:["No note with id ",e.jsx("span",{className:"font-mono",children:t})," in this vault."]}),action:e.jsx($,{to:"/notes",className:"text-sm text-accent hover:underline",children:"Back to all notes"})})}function Y({isDirty:t,justSaved:a,updatedAt:r}){return t?e.jsxs("span",{className:"inline-flex items-center gap-1 text-xs text-accent","aria-label":"unsaved changes",children:[e.jsx("span",{className:"h-1.5 w-1.5 rounded-full bg-accent"}),"unsaved"]}):a?e.jsx("span",{className:"text-xs text-accent","aria-label":"saved",children:"Saved ✓"}):e.jsxs("span",{className:"text-xs text-fg-dim",children:["saved ",F(r)]})}function We({error:t}){const a=t instanceof I;return e.jsx(fe,{title:a?"Session expired":"Could not load note",message:t.message,action:a?e.jsx($,{to:"/add",className:"btn btn-primary",children:"Reconnect vault"}):void 0})}function qe(t,a){if(t.length!==a.length)return!1;const r=new Set(t);for(const i of a)if(!r.has(i))return!1;return!0}function Ke(t,a){const r=new Set(t),i=new Set(a),x=a.filter(u=>!r.has(u)),l=t.filter(u=>!i.has(u));return{add:x,remove:l}}export{et as NoteEditor};
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import{aE as Le,r,aF as Ue,aG as Fe,aH as ge,b as Ve,e as qe,ak as Oe,aI as Be,aJ as Ge,aK as He,aL as We,af as Ye,aj as Ke,aM as Qe,av as Ze,aN as ze,P as Je,ay as Xe,j as e,N as et,aO as tt,aP as st,aQ as xe,V as nt,az as W,aR as at,aS as rt,aT as ot,aU as it,aV as ee,aW as ct,aX as lt,aY as D,L as dt,aB as ut,M as mt,aZ as pt,a_ as ht,aD as ft}from"./index-
|
|
1
|
+
import{aE as Le,r,aF as Ue,aG as Fe,aH as ge,b as Ve,e as qe,ak as Oe,aI as Be,aJ as Ge,aK as He,aL as We,af as Ye,aj as Ke,aM as Qe,av as Ze,aN as ze,P as Je,ay as Xe,j as e,N as et,aO as tt,aP as st,aQ as xe,V as nt,az as W,aR as at,aS as rt,aT as ot,aU as it,aV as ee,aW as ct,aX as lt,aY as D,L as dt,aB as ut,M as mt,aZ as pt,a_ as ht,aD as ft}from"./index-BwG_4Oup.js";import{A as gt}from"./AttachmentDropZone-TqaFTJWk.js";import{u as xt,b as bt,N as vt,A as yt,a as jt}from"./useAttachmentUploader-CR8KEhCu.js";import{C as kt}from"./CodeMirrorEditor-DxXQL_Yv.js";import{l as be,u as wt,a as Nt,b as Rt}from"./transcribe-default-Cz5r46Dt.js";import{r as St}from"./editor-mode-D9fveTEx.js";import{v as Tt}from"./attachment-upload-DML2Fh0E.js";import"./types-BaJkUfo6.js";const Ct=30*6e4,At=20*1024*1024,Et=1e4;function It(t){const i=t.segmentMs??Ct,c=t.setTimer??((m,C)=>setTimeout(m,C)),x=t.clearTimer??(m=>clearTimeout(m)),j=t.makeRecorder??(m=>Le({...m,releaseStreamOnStop:!1})),f=[];let a=null,d=null,p="idle",b=0,h=0,v=!1;const u=()=>{for(const m of t.stream.getTracks())m.stop()},g=()=>{d!==null&&(x(d),d=null)},n=()=>{d=c(()=>{d=null,o()},i)},R=()=>{h+=1;const m=h;a=j({stream:t.stream,mimeType:t.mimeType,releaseStreamOnStop:!1,now:t.now,MediaRecorderCtor:t.MediaRecorderCtor,dataIntervalMs:Et,onData:C=>{m===h&&C>=At&&o()}}),a.start(),b+=1,n()},o=()=>{var m;p!=="recording"||!a||v||(v=!0,g(),f.push(a.stop()),R(),(m=t.onRoll)==null||m.call(t,b),v=!1)};return{get state(){return p},get activePart(){return b},start(){if(p!=="idle")throw new Error(`Cannot start from ${p}`);p="recording",R()},async stop(){if(p!=="recording"||!a)throw new Error(`Cannot stop from ${p}`);p="stopped",g(),f.push(a.stop()),a=null;const m=await Promise.all(f);return u(),m},cancel(){g(),a&&a.cancel(),a=null,p="stopped",u()}}}function Pt(){const[t,i]=r.useState({kind:"idle"}),[c,x]=r.useState(0),[j,f]=r.useState(0),a=r.useRef(null),d=r.useRef(null);r.useEffect(()=>{if(t.kind!=="recording")return;const u=setInterval(()=>x(Date.now()-t.startedAt),250);return()=>clearInterval(u)},[t]),r.useEffect(()=>()=>{d.current&&URL.revokeObjectURL(d.current),a.current&&a.current.state==="recording"&&a.current.cancel()},[]);const p=r.useCallback(async()=>{if(!(t.kind==="recording"||t.kind==="requesting")){i({kind:"requesting"});try{const u=Ue();if(!u){i({kind:"denied",message:"This browser can't record audio in a format we can save."});return}const g=await Fe(),n=It({stream:g,mimeType:u,onRoll:R=>f(R)});a.current=n,n.start(),x(0),f(n.activePart),i({kind:"recording",startedAt:Date.now()})}catch(u){const g=u,n=g.kind==="permission-denied"?"Microphone access was denied. Update your browser's site settings to record.":g.kind==="no-device"?"No microphone was found on this device.":g instanceof Error?g.message:"Microphone is not available in this browser.";i({kind:"denied",message:n})}}},[t]),b=r.useCallback(async()=>{var g;const u=a.current;if(!(!u||t.kind!=="recording"))try{const n=await u.stop();a.current=null,f(0);const R=((g=n[0])==null?void 0:g.mimeType)??"",o=n.reduce((q,Y)=>q+Y.durationMs,0),m=n[0],C=m?URL.createObjectURL(new Blob([m.data],{type:m.mimeType})):"";d.current&&URL.revokeObjectURL(d.current),d.current=C||null,i({kind:"have-audio",segments:n,mimeType:R,url:C,durationMs:o})}catch(n){console.warn(n instanceof Error?`Recording failed: ${n.message}`:"Recording failed."),f(0),i({kind:"idle"})}},[t]),h=r.useCallback(()=>{d.current&&(URL.revokeObjectURL(d.current),d.current=null),i({kind:"idle"}),x(0),f(0)},[]),v=r.useCallback(()=>{h()},[h]);return{phase:t,elapsedMs:c,parts:j,startRecording:p,stopRecording:b,discardAudio:h,reset:v}}function Mt(t){const{segments:i,mimeType:c,recordedAt:x,willTranscribe:j}=t,f=i.length>1,a=t.typedText.trim(),d=i.map((v,u)=>({filename:f?ge(c,x,u+1):ge(c,x),transcribe:j,...j&&f?{segment_index:u}:{}})),p=j?f?i.map((v,u)=>`_Transcript pending (part ${u+1})._`).join(`
|
|
2
2
|
|
|
3
3
|
`):"_Transcript pending._":"",b=d.map(v=>`![[${v.filename}]]`).join(`
|
|
4
4
|
|
|
5
5
|
`),h=[];return a&&h.push(a),p&&h.push(p),h.push(b),{body:`${h.join(`
|
|
6
6
|
|
|
7
7
|
`)}
|
|
8
|
-
`,segments:d}}const ve={content:"",path:"",tags:[]};function Gt(){const t=Ve(s=>s.getActiveVault()),i=qe(),c=Oe(s=>s.push),x=Be(),j=Ge(),f=He(),{db:a,blobStore:d,engine:p}=We(),{roles:b,tagNewNotes:h}=Ye((t==null?void 0:t.id)??null),v=Ke(),u=r.useRef(Qe()),g=r.useRef(Tt()).current,n=r.useRef((t==null?void 0:t.id)??null).current,R=r.useRef(null),[o,m]=r.useState(()=>{if(n){const s=Ze(n,D);if(s)return R.current=s.savedAt,s.body}return{...ve,path:u.current}}),[C,q]=r.useState(()=>R.current),[Y,se]=r.useState(""),[ne,E]=r.useState(null),[O,je]=r.useState([]),[ke,ae]=r.useState(!1),K=r.useRef(null),re=r.useRef(null),y=Pt(),$=ze(),S=$.capability,we=y.phase.kind==="requesting"||y.phase.kind==="recording"||y.phase.kind==="have-audio",Ne=(S==null?void 0:S.enabled)===!1&&!we,Q=typeof(S==null?void 0:S.minutes_remaining)=="number"?S.minutes_remaining:void 0,Z=Q!==void 0&&Q<=0,[z,oe]=r.useState(()=>n?be(n):!0),Re=(S==null?void 0:S.enabled)!==!1,ie=r.useRef(y.phase.kind);r.useEffect(()=>{const s=ie.current,l=y.phase.kind;ie.current=l,l==="idle"&&s!=="idle"&&n&&oe(be(n))},[y.phase.kind,n]);const[Se]=Je(),ce=Se.has("voice"),le=r.useRef(!1);r.useEffect(()=>{var s;!ce||le.current||$.settled&&((s=$.capability)==null?void 0:s.enabled)!==!1&&(le.current=!0,y.startRecording())},[ce,$.settled,$.capability,y.startRecording]);const I=bt({noteId:null,onInsert:s=>{K.current?K.current.insertAtCursor(s):m(l=>({...l,content:`${l.content}${s}`}))},onStaged:s=>je(l=>[...l,s]),onError:s=>c(s,"error")}),Te=o.content.trim().length>0||o.tags.length>0||o.path.trim().length>0&&o.path!==u.current;if(Xe(n,D,o,Te),!t)return e.jsx(et,{to:"/",replace:!0});const P=y.phase.kind==="have-audio",Ce=o.content.trim().length>0,B=o.content.length>0||o.path!==u.current||o.tags.length>0||P,Ae=h?P?b.captureVoice:b.captureText:null,de=tt(o.tags,o.content,Ae),L=o.path.trim().length>0&&(Ce||P),M=x.isPending||ke,ue=r.useCallback(()=>{var k;if(!L||M)return;const s=h?b.captureText:null,l=st({content:o.content,path:o.path,tags:o.tags,inboxTag:s});v&&s&&((k=l.tags)!=null&&k.includes(s))&&xe(t.id,v,s),E(null),x.mutate(l,{onSuccess:async T=>{for(const U of O)try{await j.mutateAsync({noteId:T.id,path:U.path,mimeType:U.mimeType})}catch(G){const _=G instanceof Error?G.message:"Link failed";c(`Failed to attach ${U.filename}: ${_}`,"error")}n&&W(n,D),c(`Created ${T.path??T.id}`,"success"),i(`/n/${encodeURIComponent(T.id)}`,{replace:!0})},onError:T=>{T instanceof nt?E("Session expired. Reconnect to save."):E(T instanceof Error?`${T.message} — if the path is taken, try a different one.`:"Create failed")}})},[t,n,v,o,L,j,x,i,M,c,b.captureText,O,h]),me=r.useCallback(async()=>{if(!L||M||y.phase.kind!=="have-audio")return;if(!a||!d){c("Sync queue not ready — try again in a moment.","error");return}E(null);const s=y.phase,l=s.segments,k=s.mimeType,T=o.path.trim(),U=o.tags,G=at(o.content),_=h?b.captureVoice:null,J=rt([...U,...G],_),_e=new Date,F=ot(),De=!Z&&z,X=Mt({segments:l,mimeType:k,typedText:o.content,recordedAt:_e,willTranscribe:De});for(let w=0;w<l.length;w++){const A=gt(new File([l[w].data],X.segments[w].filename,{type:k}));if(A){c(A,"error"),E(A);return}}ae(!0),v&&_&&J.includes(_)&&xe(t.id,v,_);const fe={content:X.body,path:T,metadata:ht("voice"),...J.length?{tags:J}:{}};try{const w=X.segments.map((N,V)=>({segment:N,data:l[V].data,blobId:it()})),A=[];try{for(const N of w)await d.put(N.blobId,N.data,k,t.id),A.push(N.blobId)}catch(N){throw(await Promise.allSettled(A.map(H=>d.delete(H)))).forEach((H,$e)=>{H.status==="rejected"&&console.warn(`Could not roll back staged voice blob ${A[$e]}; it may need cleanup.`,H.reason)}),N}await ee(a,{kind:"create-note",localId:F,payload:fe},{vaultId:t.id});for(const{segment:N,blobId:V}of w)await ee(a,{kind:"upload-attachment",blobId:V,filename:N.filename,mimeType:k},{vaultId:t.id}),await ee(a,{kind:"link-attachment",noteId:F,pathRef:ct(V),mimeType:k,transcribe:N.transcribe,...N.segment_index!==void 0?{segment_index:N.segment_index}:{}},{vaultId:t.id});p==null||p.runOnce(),f.setQueryData(["note",t.id,F],lt(fe,F)),n&&W(n,D),c("Captured — syncing audio.","success"),y.discardAudio(),i(`/n/${encodeURIComponent(F)}`,{replace:!0})}catch(w){c(w instanceof Error?`Capture failed: ${w.message}`:"Capture failed.","error"),E(w instanceof Error?w.message:"Capture failed")}finally{ae(!1)}},[t,n,d,v,a,o,p,L,i,Z,M,c,f,b.captureVoice,h,z,y]),pe=r.useCallback(()=>{P?me():ue()},[P,ue,me]),he=r.useCallback(()=>{B&&!confirm("Discard this draft?")||(n&&W(n,D),y.discardAudio(),i("/"))},[n,B,i,y]),Ee=r.useCallback(()=>{n&&W(n,D),m({...ve,path:u.current}),y.discardAudio(),q(null)},[n,y]);r.useEffect(()=>{if(!B)return;const s=l=>{l.preventDefault(),l.returnValue=""};return window.addEventListener("beforeunload",s),()=>window.removeEventListener("beforeunload",s)},[B]);const Ie=s=>{const l=ft(s);!l||o.tags.includes(l)||(m(k=>({...k,tags:[...k.tags,l]})),se(""))},Pe=s=>{m(l=>({...l,tags:l.tags.filter(k=>k!==s)}))},Me=kt({id:"__new__",createdAt:new Date().toISOString()});return e.jsxs("div",{className:"page",children:[e.jsx("nav",{className:"mb-6 text-sm text-fg-dim",children:e.jsx(dt,{to:"/notes",className:"hover:text-accent",children:"← All notes"})}),e.jsxs("article",{children:[e.jsxs("header",{className:"composer mb-6 p-5 md:p-6",children:[e.jsxs("div",{className:"flex flex-wrap items-center justify-between gap-3",children:[e.jsx("span",{className:"eyebrow",children:"New note"}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("button",{type:"button",onClick:he,className:"btn btn-secondary btn-touch",children:"Cancel"}),e.jsx("button",{type:"button",onClick:pe,disabled:!L||M,className:"btn btn-primary btn-touch",title:"Create (⌘S)",children:M?"Creating…":"Create"})]})]}),e.jsx("input",{type:"text",value:o.path,onChange:s=>m(l=>({...l,path:s.target.value})),className:o.path===u.current?"mt-4 w-full border-0 bg-transparent font-sans text-sm text-fg-dim outline-none placeholder:text-fg-dim":"mt-4 w-full border-0 bg-transparent font-serif text-2xl text-fg outline-none placeholder:text-fg-dim md:text-3xl","aria-label":"Note path",placeholder:"Name your note — or just start writing"}),e.jsxs("div",{className:"mt-4",children:[e.jsx(ut,{tags:o.tags,input:Y,onInputChange:se,onAdd:Ie,onRemove:Pe}),de?e.jsxs("p",{className:"mt-1.5 text-xs text-fg-dim","data-testid":"inbox-tag-hint",children:["No tags yet, so this note will be saved with #",de,"."]}):null]})]}),C?e.jsxs("div",{role:"status","data-testid":"draft-restored",className:"mb-4 flex flex-wrap items-center justify-between gap-2 rounded-xl border border-accent/30 bg-accent/5 px-3 py-2 text-sm",children:[e.jsxs("span",{className:"text-fg-muted",children:["Unsaved draft restored from ",mt(C),"."]}),e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("button",{type:"button",onClick:Ee,className:"text-fg-dim hover:text-danger",children:"Discard draft"}),e.jsx("button",{type:"button",onClick:()=>q(null),"aria-label":"Dismiss draft-restored notice",className:"text-fg-dim hover:text-accent",children:"✕"})]})]}):null,ne?e.jsx("div",{role:"alert",className:"mb-4 rounded-xl border border-danger-border bg-danger-soft p-3 text-sm text-danger",children:ne}):null,Ne?e.jsx(pt,{capability:S}):e.jsxs(e.Fragment,{children:[e.jsx($t,{voice:y,minutesRemaining:Q,outOfMinutes:Z,transcribe:z,onTranscribeChange:oe,showTranscribeToggle:Re}),e.jsx(_t,{vaultId:t.id,captureEngaged:P})]}),e.jsxs("div",{className:`grid min-h-[60dvh] gap-4 ${g?"":"lg:grid-cols-2"}`,children:[e.jsx(xt,{onDropFiles:I.start,className:"card min-h-0 h-[60dvh] min-w-0",hint:"Images, audio, webm video",children:e.jsx(vt,{ref:K,value:o.content,onChange:s=>m(l=>({...l,content:s})),onSave:pe,onCancel:he,placeholder:"Start writing…",onPasteFile:s=>(I.start(s),!0),onRequestAttachment:()=>{var s;return(s=re.current)==null?void 0:s.open()},livePreview:g})}),g?null:e.jsx("div",{className:"card min-w-0 overflow-auto p-4 lg:h-[60dvh] lg:min-h-0",children:o.content.trim()?e.jsx(wt,{note:{path:o.path,content:o.content},resolve:Me}):e.jsx("p",{className:"text-sm text-fg-dim",children:"Preview appears here as you type."})})]}),e.jsxs("section",{className:"mt-6 border-t border-border pt-4",children:[e.jsxs("div",{className:"mb-3 flex items-center justify-between",children:[e.jsx("h2",{className:"font-serif text-xl",children:"Attachments"}),e.jsx(yt,{ref:re,onPickFiles:I.start})]}),e.jsxs("p",{className:"mb-3 text-xs text-fg-dim",children:["Drop or paste files into the editor. Attachments link to the note when you save. Max 100 MB each. Images, audio, webm video."," ",e.jsx("a",{href:"https://github.com/ParachuteComputer/parachute-vault/issues/127",target:"_blank",rel:"noreferrer",className:"text-accent hover:underline",children:"PDF + mp4 coming"}),"."]}),e.jsx(jt,{uploads:I.uploads,onCancel:I.cancel,onDismiss:I.dismiss}),O.length>0?e.jsx("ul",{className:"mt-3 space-y-1 text-sm",children:O.map(s=>e.jsxs("li",{className:"flex items-center justify-between gap-2 rounded-lg border border-border bg-card/50 px-3 py-1.5 font-mono text-xs text-fg-muted",children:[e.jsx("span",{className:"truncate",children:s.filename}),e.jsx("span",{className:"shrink-0 text-fg-dim",children:"staged"})]},s.path))}):null]})]})]})}function _t({vaultId:t,captureEngaged:i}){const c=Nt(),x=Rt(),{made:j,markMade:f}=St(t),[a,d]=r.useState(null);if(!(i&&!j&&c.supported&&c.value==="keep"))return null;const b=h=>{d(null),x.mutate(h,{onSuccess:()=>f(),onError:()=>d("Couldn't save that choice — this recording is kept (the vault default). We'll ask again next time; you can also set it in Settings.")})};return e.jsxs("div",{"data-testid":"retention-choice",className:"mb-4 flex flex-col gap-2 rounded-xl border border-border bg-card/60 p-3",children:[e.jsx("p",{className:"text-xs text-fg-muted",children:"First voice note here — should this vault keep your audio files after transcribing?"}),e.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[e.jsx("button",{type:"button",onClick:()=>b("keep"),disabled:x.isPending,className:"btn btn-secondary btn-touch",children:"Keep my recordings"}),e.jsx("button",{type:"button",onClick:()=>b("until_transcribed"),disabled:x.isPending,className:"btn btn-secondary btn-touch",children:"Just keep the words"}),e.jsx("span",{className:"text-xs text-fg-dim",children:"(audio deleted after transcribing)"})]}),e.jsx("p",{className:"text-xs text-fg-dim",children:"Either way your capture saves now. Change this anytime in Settings."}),a?e.jsx("p",{className:"text-xs text-danger","data-testid":"retention-choice-error",children:a}):null]})}const Dt=30;function ye({checked:t,disabled:i,onChange:c}){return e.jsxs("div",{className:"flex basis-full items-center gap-3",children:[e.jsx("span",{className:"text-xs text-fg-dim",children:"Transcribe this recording"}),e.jsx("button",{type:"button",role:"switch","aria-checked":t,"aria-label":"Transcribe this recording","data-testid":"transcribe-toggle",disabled:i,onClick:()=>c(!t),className:`relative h-7 w-12 shrink-0 rounded-full transition-colors disabled:opacity-40 ${t?"bg-accent":"bg-border"}`,children:e.jsx("span",{className:`absolute top-0.5 left-0 h-6 w-6 rounded-full bg-card shadow-sm transition-transform ${t?"translate-x-5":"translate-x-0.5"}`})})]})}function $t({voice:t,minutesRemaining:i,outOfMinutes:c,transcribe:x,onTranscribeChange:j,showTranscribeToggle:f}){const{phase:a,elapsedMs:d,parts:p,startRecording:b,stopRecording:h,discardAudio:v}=t,u=a.kind==="recording",g=a.kind==="requesting",n=!c&&x,R=typeof i=="number"&&i<=Dt;return a.kind==="have-audio"?e.jsxs("div",{className:"mb-4 flex flex-col gap-2 rounded-xl border border-accent/30 bg-accent/5 p-3",children:[e.jsxs("div",{className:"flex items-center justify-between gap-3",children:[e.jsxs("span",{className:"text-sm text-fg-muted",children:["🎙 Recorded ",te(a.durationMs),a.segments.length>1?` · ${a.segments.length} parts`:""]}),e.jsx("button",{type:"button",onClick:v,className:"text-xs text-fg-dim hover:text-danger",children:"Discard"})]}),e.jsx("audio",{controls:!0,src:a.url,className:"w-full",children:e.jsx("track",{kind:"captions"})}),f?e.jsx(ye,{checked:n,disabled:c,onChange:j}):null,e.jsx("p",{className:"text-xs text-fg-dim",children:c?"Saved as audio-only — you're out of transcription minutes this month.":n?"Transcript will be appended once your vault processes it. Save to commit.":"Saved as audio-only — transcription is off for this recording."})]}):e.jsxs("div",{className:"mb-4 flex flex-wrap items-center justify-between gap-3 rounded-xl border border-border bg-card/60 p-3",children:[e.jsx("div",{className:"text-xs text-fg-dim",children:u?p>1?`Recording — tap Stop to finish. (part ${p})`:"Recording — tap Stop to finish.":g?"Requesting microphone…":c?"You're out of transcription minutes this month — this saves as audio-only.":n?"Add a voice memo to this note. Audio gets transcribed and appended.":"Add a voice memo to this note. Saved as audio-only — transcription is off for this recording."}),u?e.jsxs("button",{type:"button",onClick:()=>void h(),"aria-label":`Recording — ${te(d)} — stop`,"aria-pressed":"true",className:"flex min-h-11 items-center gap-2 rounded-full border border-danger-border bg-danger-soft px-4 py-2 text-sm font-medium text-danger",children:[e.jsx("span",{"aria-hidden":"true",className:"animate-pulse",children:"🎙"}),e.jsxs("span",{children:["Stop ",te(d)]})]}):e.jsxs("button",{type:"button",onClick:()=>void b(),"aria-label":"Record voice memo",disabled:g,className:"flex min-h-11 items-center gap-2 rounded-full border border-accent/30 bg-accent/10 px-4 py-2 text-sm font-medium text-accent hover:bg-accent/15 disabled:opacity-40",children:[e.jsx("span",{"aria-hidden":"true",children:"🎙"}),e.jsx("span",{children:g?"Requesting…":"Record"})]}),f?e.jsx(ye,{checked:n,disabled:c,onChange:j}):null,R&&!c?e.jsxs("p",{className:"basis-full text-xs text-fg-dim","data-testid":"voice-minutes-left",children:["About ",Math.round(i)," min of transcription left this month."]}):null,a.kind==="denied"?e.jsx("p",{className:"basis-full rounded-xl border border-danger-border bg-danger-soft px-3 py-2 text-xs text-danger",children:a.message}):null]})}function te(t){const i=Math.floor(t/1e3),c=Math.floor(i/60),x=i%60;return`${String(c).padStart(2,"0")}:${String(x).padStart(2,"0")}`}export{Gt as NoteNew};
|
|
8
|
+
`,segments:d}}const ve={content:"",path:"",tags:[]};function Ht(){const t=Ve(s=>s.getActiveVault()),i=qe(),c=Oe(s=>s.push),x=Be(),j=Ge(),f=He(),{db:a,blobStore:d,engine:p}=We(),{roles:b,tagNewNotes:h}=Ye((t==null?void 0:t.id)??null),v=Ke(),u=r.useRef(Qe()),g=r.useRef(St()).current,n=r.useRef((t==null?void 0:t.id)??null).current,R=r.useRef(null),[o,m]=r.useState(()=>{if(n){const s=Ze(n,D);if(s)return R.current=s.savedAt,s.body}return{...ve,path:u.current}}),[C,q]=r.useState(()=>R.current),[Y,se]=r.useState(""),[ne,E]=r.useState(null),[O,je]=r.useState([]),[ke,ae]=r.useState(!1),K=r.useRef(null),re=r.useRef(null),y=Pt(),$=ze(),S=$.capability,we=y.phase.kind==="requesting"||y.phase.kind==="recording"||y.phase.kind==="have-audio",Ne=(S==null?void 0:S.enabled)===!1&&!we,Q=typeof(S==null?void 0:S.minutes_remaining)=="number"?S.minutes_remaining:void 0,Z=Q!==void 0&&Q<=0,[z,oe]=r.useState(()=>n?be(n):!0),Re=(S==null?void 0:S.enabled)!==!1,ie=r.useRef(y.phase.kind);r.useEffect(()=>{const s=ie.current,l=y.phase.kind;ie.current=l,l==="idle"&&s!=="idle"&&n&&oe(be(n))},[y.phase.kind,n]);const[Se]=Je(),ce=Se.has("voice"),le=r.useRef(!1);r.useEffect(()=>{var s;!ce||le.current||$.settled&&((s=$.capability)==null?void 0:s.enabled)!==!1&&(le.current=!0,y.startRecording())},[ce,$.settled,$.capability,y.startRecording]);const I=xt({noteId:null,onInsert:s=>{K.current?K.current.insertAtCursor(s):m(l=>({...l,content:`${l.content}${s}`}))},onStaged:s=>je(l=>[...l,s]),onError:s=>c(s,"error")}),Te=o.content.trim().length>0||o.tags.length>0||o.path.trim().length>0&&o.path!==u.current;if(Xe(n,D,o,Te),!t)return e.jsx(et,{to:"/",replace:!0});const P=y.phase.kind==="have-audio",Ce=o.content.trim().length>0,B=o.content.length>0||o.path!==u.current||o.tags.length>0||P,Ae=h?P?b.captureVoice:b.captureText:null,de=tt(o.tags,o.content,Ae),L=o.path.trim().length>0&&(Ce||P),M=x.isPending||ke,ue=r.useCallback(()=>{var k;if(!L||M)return;const s=h?b.captureText:null,l=st({content:o.content,path:o.path,tags:o.tags,inboxTag:s});v&&s&&((k=l.tags)!=null&&k.includes(s))&&xe(t.id,v,s),E(null),x.mutate(l,{onSuccess:async T=>{for(const U of O)try{await j.mutateAsync({noteId:T.id,path:U.path,mimeType:U.mimeType})}catch(G){const _=G instanceof Error?G.message:"Link failed";c(`Failed to attach ${U.filename}: ${_}`,"error")}n&&W(n,D),c(`Created ${T.path??T.id}`,"success"),i(`/n/${encodeURIComponent(T.id)}`,{replace:!0})},onError:T=>{T instanceof nt?E("Session expired. Reconnect to save."):E(T instanceof Error?`${T.message} — if the path is taken, try a different one.`:"Create failed")}})},[t,n,v,o,L,j,x,i,M,c,b.captureText,O,h]),me=r.useCallback(async()=>{if(!L||M||y.phase.kind!=="have-audio")return;if(!a||!d){c("Sync queue not ready — try again in a moment.","error");return}E(null);const s=y.phase,l=s.segments,k=s.mimeType,T=o.path.trim(),U=o.tags,G=at(o.content),_=h?b.captureVoice:null,J=rt([...U,...G],_),_e=new Date,F=ot(),De=!Z&&z,X=Mt({segments:l,mimeType:k,typedText:o.content,recordedAt:_e,willTranscribe:De});for(let w=0;w<l.length;w++){const A=Tt(new File([l[w].data],X.segments[w].filename,{type:k}));if(A){c(A,"error"),E(A);return}}ae(!0),v&&_&&J.includes(_)&&xe(t.id,v,_);const fe={content:X.body,path:T,metadata:ht("voice"),...J.length?{tags:J}:{}};try{const w=X.segments.map((N,V)=>({segment:N,data:l[V].data,blobId:it()})),A=[];try{for(const N of w)await d.put(N.blobId,N.data,k,t.id),A.push(N.blobId)}catch(N){throw(await Promise.allSettled(A.map(H=>d.delete(H)))).forEach((H,$e)=>{H.status==="rejected"&&console.warn(`Could not roll back staged voice blob ${A[$e]}; it may need cleanup.`,H.reason)}),N}await ee(a,{kind:"create-note",localId:F,payload:fe},{vaultId:t.id});for(const{segment:N,blobId:V}of w)await ee(a,{kind:"upload-attachment",blobId:V,filename:N.filename,mimeType:k},{vaultId:t.id}),await ee(a,{kind:"link-attachment",noteId:F,pathRef:ct(V),mimeType:k,transcribe:N.transcribe,...N.segment_index!==void 0?{segment_index:N.segment_index}:{}},{vaultId:t.id});p==null||p.runOnce(),f.setQueryData(["note",t.id,F],lt(fe,F)),n&&W(n,D),c("Captured — syncing audio.","success"),y.discardAudio(),i(`/n/${encodeURIComponent(F)}`,{replace:!0})}catch(w){c(w instanceof Error?`Capture failed: ${w.message}`:"Capture failed.","error"),E(w instanceof Error?w.message:"Capture failed")}finally{ae(!1)}},[t,n,d,v,a,o,p,L,i,Z,M,c,f,b.captureVoice,h,z,y]),pe=r.useCallback(()=>{P?me():ue()},[P,ue,me]),he=r.useCallback(()=>{B&&!confirm("Discard this draft?")||(n&&W(n,D),y.discardAudio(),i("/"))},[n,B,i,y]),Ee=r.useCallback(()=>{n&&W(n,D),m({...ve,path:u.current}),y.discardAudio(),q(null)},[n,y]);r.useEffect(()=>{if(!B)return;const s=l=>{l.preventDefault(),l.returnValue=""};return window.addEventListener("beforeunload",s),()=>window.removeEventListener("beforeunload",s)},[B]);const Ie=s=>{const l=ft(s);!l||o.tags.includes(l)||(m(k=>({...k,tags:[...k.tags,l]})),se(""))},Pe=s=>{m(l=>({...l,tags:l.tags.filter(k=>k!==s)}))},Me=bt({id:"__new__",createdAt:new Date().toISOString()});return e.jsxs("div",{className:"page",children:[e.jsx("nav",{className:"mb-6 text-sm text-fg-dim",children:e.jsx(dt,{to:"/notes",className:"hover:text-accent",children:"← All notes"})}),e.jsxs("article",{children:[e.jsxs("header",{className:"composer mb-6 p-5 md:p-6",children:[e.jsxs("div",{className:"flex flex-wrap items-center justify-between gap-3",children:[e.jsx("span",{className:"eyebrow",children:"New note"}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("button",{type:"button",onClick:he,className:"btn btn-secondary btn-touch",children:"Cancel"}),e.jsx("button",{type:"button",onClick:pe,disabled:!L||M,className:"btn btn-primary btn-touch",title:"Create (⌘S)",children:M?"Creating…":"Create"})]})]}),e.jsx("input",{type:"text",value:o.path,onChange:s=>m(l=>({...l,path:s.target.value})),className:o.path===u.current?"mt-4 w-full border-0 bg-transparent font-sans text-sm text-fg-dim outline-none placeholder:text-fg-dim":"mt-4 w-full border-0 bg-transparent font-serif text-2xl text-fg outline-none placeholder:text-fg-dim md:text-3xl","aria-label":"Note path",placeholder:"Name your note — or just start writing"}),e.jsxs("div",{className:"mt-4",children:[e.jsx(ut,{tags:o.tags,input:Y,onInputChange:se,onAdd:Ie,onRemove:Pe}),de?e.jsxs("p",{className:"mt-1.5 text-xs text-fg-dim","data-testid":"inbox-tag-hint",children:["No tags yet, so this note will be saved with #",de,"."]}):null]})]}),C?e.jsxs("div",{role:"status","data-testid":"draft-restored",className:"mb-4 flex flex-wrap items-center justify-between gap-2 rounded-xl border border-accent/30 bg-accent/5 px-3 py-2 text-sm",children:[e.jsxs("span",{className:"text-fg-muted",children:["Unsaved draft restored from ",mt(C),"."]}),e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("button",{type:"button",onClick:Ee,className:"text-fg-dim hover:text-danger",children:"Discard draft"}),e.jsx("button",{type:"button",onClick:()=>q(null),"aria-label":"Dismiss draft-restored notice",className:"text-fg-dim hover:text-accent",children:"✕"})]})]}):null,ne?e.jsx("div",{role:"alert",className:"mb-4 rounded-xl border border-danger-border bg-danger-soft p-3 text-sm text-danger",children:ne}):null,Ne?e.jsx(pt,{capability:S}):e.jsxs(e.Fragment,{children:[e.jsx($t,{voice:y,minutesRemaining:Q,outOfMinutes:Z,transcribe:z,onTranscribeChange:oe,showTranscribeToggle:Re}),e.jsx(_t,{vaultId:t.id,captureEngaged:P})]}),e.jsxs("div",{className:`grid min-h-[60dvh] gap-4 ${g?"":"lg:grid-cols-2"}`,children:[e.jsx(gt,{onDropFiles:I.start,className:"card min-h-0 h-[60dvh] min-w-0",hint:"Images, audio, webm video",children:e.jsx(kt,{ref:K,value:o.content,onChange:s=>m(l=>({...l,content:s})),onSave:pe,onCancel:he,placeholder:"Start writing…",onPasteFile:s=>(I.start(s),!0),onRequestAttachment:()=>{var s;return(s=re.current)==null?void 0:s.open()},livePreview:g})}),g?null:e.jsx("div",{className:"card min-w-0 overflow-auto p-4 lg:h-[60dvh] lg:min-h-0",children:o.content.trim()?e.jsx(vt,{note:{path:o.path,content:o.content},resolve:Me}):e.jsx("p",{className:"text-sm text-fg-dim",children:"Preview appears here as you type."})})]}),e.jsxs("section",{className:"mt-6 border-t border-border pt-4",children:[e.jsxs("div",{className:"mb-3 flex items-center justify-between",children:[e.jsx("h2",{className:"font-serif text-xl",children:"Attachments"}),e.jsx(yt,{ref:re,onPickFiles:I.start})]}),e.jsxs("p",{className:"mb-3 text-xs text-fg-dim",children:["Drop or paste files into the editor. Attachments link to the note when you save. Max 100 MB each. Images, audio, webm video."," ",e.jsx("a",{href:"https://github.com/ParachuteComputer/parachute-vault/issues/127",target:"_blank",rel:"noreferrer",className:"text-accent hover:underline",children:"PDF + mp4 coming"}),"."]}),e.jsx(jt,{uploads:I.uploads,onCancel:I.cancel,onDismiss:I.dismiss}),O.length>0?e.jsx("ul",{className:"mt-3 space-y-1 text-sm",children:O.map(s=>e.jsxs("li",{className:"flex items-center justify-between gap-2 rounded-lg border border-border bg-card/50 px-3 py-1.5 font-mono text-xs text-fg-muted",children:[e.jsx("span",{className:"truncate",children:s.filename}),e.jsx("span",{className:"shrink-0 text-fg-dim",children:"staged"})]},s.path))}):null]})]})]})}function _t({vaultId:t,captureEngaged:i}){const c=wt(),x=Nt(),{made:j,markMade:f}=Rt(t),[a,d]=r.useState(null);if(!(i&&!j&&c.supported&&c.value==="keep"))return null;const b=h=>{d(null),x.mutate(h,{onSuccess:()=>f(),onError:()=>d("Couldn't save that choice — this recording is kept (the vault default). We'll ask again next time; you can also set it in Settings.")})};return e.jsxs("div",{"data-testid":"retention-choice",className:"mb-4 flex flex-col gap-2 rounded-xl border border-border bg-card/60 p-3",children:[e.jsx("p",{className:"text-xs text-fg-muted",children:"First voice note here — should this vault keep your audio files after transcribing?"}),e.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[e.jsx("button",{type:"button",onClick:()=>b("keep"),disabled:x.isPending,className:"btn btn-secondary btn-touch",children:"Keep my recordings"}),e.jsx("button",{type:"button",onClick:()=>b("until_transcribed"),disabled:x.isPending,className:"btn btn-secondary btn-touch",children:"Just keep the words"}),e.jsx("span",{className:"text-xs text-fg-dim",children:"(audio deleted after transcribing)"})]}),e.jsx("p",{className:"text-xs text-fg-dim",children:"Either way your capture saves now. Change this anytime in Settings."}),a?e.jsx("p",{className:"text-xs text-danger","data-testid":"retention-choice-error",children:a}):null]})}const Dt=30;function ye({checked:t,disabled:i,onChange:c}){return e.jsxs("div",{className:"flex basis-full items-center gap-3",children:[e.jsx("span",{className:"text-xs text-fg-dim",children:"Transcribe this recording"}),e.jsx("button",{type:"button",role:"switch","aria-checked":t,"aria-label":"Transcribe this recording","data-testid":"transcribe-toggle",disabled:i,onClick:()=>c(!t),className:`relative h-7 w-12 shrink-0 rounded-full transition-colors disabled:opacity-40 ${t?"bg-accent":"bg-border"}`,children:e.jsx("span",{className:`absolute top-0.5 left-0 h-6 w-6 rounded-full bg-card shadow-sm transition-transform ${t?"translate-x-5":"translate-x-0.5"}`})})]})}function $t({voice:t,minutesRemaining:i,outOfMinutes:c,transcribe:x,onTranscribeChange:j,showTranscribeToggle:f}){const{phase:a,elapsedMs:d,parts:p,startRecording:b,stopRecording:h,discardAudio:v}=t,u=a.kind==="recording",g=a.kind==="requesting",n=!c&&x,R=typeof i=="number"&&i<=Dt;return a.kind==="have-audio"?e.jsxs("div",{className:"mb-4 flex flex-col gap-2 rounded-xl border border-accent/30 bg-accent/5 p-3",children:[e.jsxs("div",{className:"flex items-center justify-between gap-3",children:[e.jsxs("span",{className:"text-sm text-fg-muted",children:["🎙 Recorded ",te(a.durationMs),a.segments.length>1?` · ${a.segments.length} parts`:""]}),e.jsx("button",{type:"button",onClick:v,className:"text-xs text-fg-dim hover:text-danger",children:"Discard"})]}),e.jsx("audio",{controls:!0,src:a.url,className:"w-full",children:e.jsx("track",{kind:"captions"})}),f?e.jsx(ye,{checked:n,disabled:c,onChange:j}):null,e.jsx("p",{className:"text-xs text-fg-dim",children:c?"Saved as audio-only — you're out of transcription minutes this month.":n?"Transcript will be appended once your vault processes it. Save to commit.":"Saved as audio-only — transcription is off for this recording."})]}):e.jsxs("div",{className:"mb-4 flex flex-wrap items-center justify-between gap-3 rounded-xl border border-border bg-card/60 p-3",children:[e.jsx("div",{className:"text-xs text-fg-dim",children:u?p>1?`Recording — tap Stop to finish. (part ${p})`:"Recording — tap Stop to finish.":g?"Requesting microphone…":c?"You're out of transcription minutes this month — this saves as audio-only.":n?"Add a voice memo to this note. Audio gets transcribed and appended.":"Add a voice memo to this note. Saved as audio-only — transcription is off for this recording."}),u?e.jsxs("button",{type:"button",onClick:()=>void h(),"aria-label":`Recording — ${te(d)} — stop`,"aria-pressed":"true",className:"flex min-h-11 items-center gap-2 rounded-full border border-danger-border bg-danger-soft px-4 py-2 text-sm font-medium text-danger",children:[e.jsx("span",{"aria-hidden":"true",className:"animate-pulse",children:"🎙"}),e.jsxs("span",{children:["Stop ",te(d)]})]}):e.jsxs("button",{type:"button",onClick:()=>void b(),"aria-label":"Record voice memo",disabled:g,className:"flex min-h-11 items-center gap-2 rounded-full border border-accent/30 bg-accent/10 px-4 py-2 text-sm font-medium text-accent hover:bg-accent/15 disabled:opacity-40",children:[e.jsx("span",{"aria-hidden":"true",children:"🎙"}),e.jsx("span",{children:g?"Requesting…":"Record"})]}),f?e.jsx(ye,{checked:n,disabled:c,onChange:j}):null,R&&!c?e.jsxs("p",{className:"basis-full text-xs text-fg-dim","data-testid":"voice-minutes-left",children:["About ",Math.round(i)," min of transcription left this month."]}):null,a.kind==="denied"?e.jsx("p",{className:"basis-full rounded-xl border border-danger-border bg-danger-soft px-3 py-2 text-xs text-danger",children:a.message}):null]})}function te(t){const i=Math.floor(t/1e3),c=Math.floor(i/60),x=i%60;return`${String(c).padStart(2,"0")}:${String(x).padStart(2,"0")}`}export{Ht as NoteNew};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/react-force-graph-2d-iGY_edo3.js","assets/index-BwG_4Oup.js","assets/index-eHCCOf4I.css"])))=>i.map(i=>d[i]);
|
|
2
|
+
import{aj as A,b as I,aK as L,r as h,a$ as _,j as e,at as H,b0 as q,L as j,b1 as Q,b2 as z,b3 as G,b4 as F,b5 as M,am as W,b6 as J,b7 as V,b8 as X,b9 as Y,as as Z,ba as ee,bb as te,N as se,bc as ne,ae,H as N,af as re,bd as ie,aL as oe,au as B,be as le,bf as ce,bg as de,bh as ue,aA as he,bi as me,J as pe,K as xe,ak as fe,bj as $,M as D,ab as be,bk as ge,V as je,al as ye,bl as ve,bm as Ne}from"./index-BwG_4Oup.js";import{b as we,A as ke,a as Ce,N as Se,u as Ie}from"./useAttachmentUploader-CR8KEhCu.js";import{P as Re,D as Ee}from"./PinArchiveButtons-6XVGmX0l.js";import"./attachment-upload-DML2Fh0E.js";function Te(t,s){const n=A(),a=I(c=>c.activeVaultId),i=L(),[l,r]=h.useState(!1),o=s&&!Ae(s)?s.path:void 0;return h.useEffect(()=>{if(r(!1),!n||!a||!t||!o)return;let c=!0;const u=()=>{c&&i.invalidateQueries({queryKey:["note",a,t]})},m=Pe(n,o,{onUpsert:u,onRemove:u,onStatus:p=>{c&&r(p==="open")}});return()=>{c=!1,r(!1),m()}},[n,a,t,o,i]),{isLive:l}}function Ae(t){return _(t.id)}function Pe(t,s,n){return t.subscribe({path:s},{onSnapshot:()=>{},onUpsert:()=>n.onUpsert(),onRemove:()=>n.onRemove(),onStatus:n.onStatus})}const Le=1,$e=3,Fe=1;function Me(t,s){const n=new Map,a=new Map;for(const l of s.values())for(const r of l.links??[]){if(r.sourceId===r.targetId||!s.has(r.sourceId)||!s.has(r.targetId))continue;const o=`${r.sourceId}|${r.targetId}|${r.relationship}`;n.has(o)||(n.set(o,{source:r.sourceId,target:r.targetId,relationship:r.relationship}),a.set(r.sourceId,(a.get(r.sourceId)??0)+1),a.set(r.targetId,(a.get(r.targetId)??0)+1))}return{nodes:[...s.values()].map(l=>{var r;return{id:l.id,path:l.path,tags:l.tags,summary:typeof((r=l.metadata)==null?void 0:r.summary)=="string"?l.metadata.summary:void 0,isAnchor:l.id===t,linkCount:a.get(l.id)??0}}),edges:[...n.values()]}}async function Ve(t,s,n,a){const i=new Map;i.set(t.id,t);let l=[t];for(let r=1;r<=s;r++){const o=new Set;for(const m of l)for(const p of m.links??[]){const f=p.sourceId===m.id?p.targetId:p.sourceId;f!==m.id&&(i.has(f)||o.add(f))}if(o.size===0)break;const c=await Promise.all([...o].map(m=>n(m).catch(()=>null)));if(a!=null&&a.cancelled)return i;const u=[];for(const m of c)m&&!i.has(m.id)&&(i.set(m.id,m),u.push(m));l=u}return i}function Be(t,s,n){const[a,i]=h.useState(null),[l,r]=h.useState(!1);return h.useEffect(()=>{if(!t||!s){i(null),r(!1);return}const o={cancelled:!1};return r(!0),Ve(s,n,c=>t.getNote(c,{includeLinks:!0}),o).then(c=>{o.cancelled||(i(Me(s.id,c)),r(!1))}).catch(()=>{o.cancelled||r(!1)}),()=>{o.cancelled=!0}},[t,s,n]),{data:a,isLoading:l}}const De=h.lazy(()=>z(()=>import("./react-force-graph-2d-iGY_edo3.js"),__vite__mapDeps([0,1,2])));function Oe({anchor:t}){const[s,n]=h.useState(!0),[a,i]=h.useState(Fe),l=A(),{data:r,isLoading:o}=Be(l,s?t:void 0,a);return e.jsxs("section",{className:"mt-10 border-t border-border pt-6",children:[e.jsxs("header",{className:"mb-4 flex flex-wrap items-center justify-between gap-3",children:[e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsxs("button",{type:"button",onClick:()=>n(c=>!c),"aria-expanded":s,className:"font-serif text-xl text-fg hover:text-accent",children:[s?"▾":"▸"," Neighborhood"]}),s&&r?e.jsxs("span",{className:"text-xs text-fg-dim",children:[r.nodes.length," ",r.nodes.length===1?"note":"notes"]}):null]}),s?e.jsx(Ue,{depth:a,onChange:i}):null]}),s?e.jsx(_e,{data:r,isLoading:o}):null]})}function Ue({depth:t,onChange:s}){const n=[];for(let a=Le;a<=$e;a++)n.push(a);return e.jsxs("fieldset",{className:"flex items-center gap-1 text-xs text-fg-dim",children:[e.jsx("legend",{className:"mr-1 inline-block",children:"Hops"}),n.map(a=>e.jsx("button",{type:"button","aria-pressed":a===t,onClick:()=>s(a),className:a===t?"rounded border border-accent bg-accent/10 px-2 py-0.5 text-accent":"rounded border border-border bg-card px-2 py-0.5 hover:text-accent",children:a},a))]})}function _e({data:t,isLoading:s}){const[n,a]=h.useState(null),i=h.useRef(null);if(h.useEffect(()=>{n&&t&&!t.nodes.some(u=>u.id===n)&&a(null)},[t,n]),!t&&s)return e.jsx(K,{});if(!t)return null;if(t.nodes.length<=1)return e.jsx("div",{className:"rounded-md border border-border bg-card p-6 text-center text-sm text-fg-dim",children:"This note has no neighbors yet."});const l=t.nodes.filter(u=>!u.isAnchor),r=n?t.nodes.find(u=>u.id===n)??null:null,o=u=>{i.current=document.activeElement??null,a(u)},c=u=>{var m,p;a(null),u!=null&&u.restoreFocus&&((p=(m=i.current)==null?void 0:m.focus)==null||p.call(m))};return e.jsxs(e.Fragment,{children:[e.jsx(ze,{data:t,onSelect:o}),r?e.jsx(Ke,{node:r,onClose:c},r.id):null,e.jsx(He,{neighbors:l,selectedId:n,onSelect:o})]})}function He({neighbors:t,selectedId:s,onSelect:n}){return t.length===0?null:e.jsxs("div",{className:"mt-4",children:[e.jsx("h3",{className:"eyebrow mb-2",children:"Neighbors"}),e.jsx("ul",{className:"flex flex-wrap gap-2",children:t.map(a=>{const i=Q(a.path??a.id);return e.jsx("li",{children:e.jsx("button",{type:"button",onClick:()=>n(a.id),"aria-haspopup":"dialog","aria-pressed":s===a.id,"aria-label":`Preview ${i}`,className:`btn btn-sm btn-touch max-w-full ${s===a.id?"btn-primary":"btn-secondary"}`,children:e.jsx("span",{className:"truncate",children:i})})},a.id)})})]})}function Ke({node:t,onClose:s}){var r;const n=H(t.id),a=h.useRef(null);h.useEffect(()=>{var o;(o=a.current)==null||o.focus()},[]);const i=q({id:t.id,path:t.path,content:(r=n.data)==null?void 0:r.content}),l=Qe(n.data);return e.jsxs("div",{role:"dialog",ref:a,"aria-label":"Note preview",tabIndex:-1,"data-testid":"neighbor-preview",onKeyDown:o=>{o.key==="Escape"&&s({restoreFocus:!0})},onBlur:o=>{o.currentTarget.contains(o.relatedTarget)||s()},className:"focus-ring card mt-3 p-4",children:[e.jsxs("div",{className:"flex items-start justify-between gap-3",children:[e.jsx("h3",{className:"min-w-0 truncate font-serif text-lg text-fg",children:i}),e.jsx("button",{type:"button",onClick:()=>s({restoreFocus:!0}),"aria-label":"Close preview",className:"shrink-0 text-fg-dim hover:text-accent",children:"✕"})]}),t.tags&&t.tags.length>0?e.jsx("div",{className:"mt-1.5 flex flex-wrap gap-1.5",children:t.tags.map(o=>e.jsxs("span",{className:"chip chip-tag max-w-full break-all",children:["#",o]},o))}):null,e.jsx(qe,{isPaused:n.fetchStatus==="paused",isPending:n.isPending,isError:n.isError,snippet:l}),e.jsx("div",{className:"mt-3",children:e.jsx(j,{to:`/n/${encodeURIComponent(t.id)}`,className:"btn btn-primary btn-touch",children:"Open note"})})]})}function qe({isPaused:t,isPending:s,isError:n,snippet:a}){return t&&s?e.jsx("p",{className:"mt-2 text-sm text-fg-dim",children:"Preview unavailable offline."}):s?e.jsx("p",{className:"mt-2 text-sm text-fg-dim",children:"Loading preview…"}):n?e.jsx("p",{className:"mt-2 text-sm text-fg-dim",children:"Couldn't load preview."}):a?e.jsx("p",{className:"mt-2 text-sm text-fg-muted",children:a}):e.jsx("p",{className:"mt-2 text-sm text-fg-dim",children:"No preview text."})}function Qe(t){if(!t)return null;const s=(t.preview??G(t.content??"")).trim();return s?s.length>200?`${s.slice(0,200).trimEnd()}…`:s:null}function K(){return e.jsx("div",{"aria-busy":"true",className:"h-[24rem] w-full animate-pulse rounded-md border border-border bg-card"})}function ze({data:t,onSelect:s}){const n=h.useRef(null),[a,i]=h.useState({w:600,h:384});h.useEffect(()=>{const r=n.current;if(!r)return;const o=()=>{const u=r.getBoundingClientRect();i({w:Math.max(320,Math.floor(u.width)),h:384})};o();const c=new ResizeObserver(o);return c.observe(r),()=>c.disconnect()},[]);const l=h.useMemo(()=>({nodes:t.nodes.map(r=>({...r})),links:t.edges.map(r=>({source:r.source,target:r.target,rel:r.relationship}))}),[t]);return e.jsx("div",{ref:n,"data-testid":"neighborhood-graph-canvas",className:"overflow-hidden rounded-md border border-border bg-card",children:e.jsx(h.Suspense,{fallback:e.jsx(K,{}),children:e.jsx(De,{graphData:l,width:a.w,height:a.h,nodeLabel:r=>Ge(r),nodeVal:r=>{const o=r;return o.isAnchor?8:3+Math.min(o.linkCount,8)},nodeColor:r=>r.isAnchor?"#c9b170":"#8a9a7a",linkColor:()=>"rgba(160, 160, 160, 0.4)",linkDirectionalArrowLength:3,linkDirectionalArrowRelPos:1,cooldownTicks:80,onNodeClick:r=>{s(r.id)}})})})}function Ge(t){const s=[t.path??t.id];return t.tags&&t.tags.length>0&&s.push(`tags: ${t.tags.join(", ")}`),t.summary&&s.push(t.summary),s.join(`
|
|
3
|
+
`)}function We({note:t}){const[s,n]=h.useState(!1),a=I(i=>i.activeVaultId);return e.jsxs("section",{className:"mt-6 border-t border-border pt-4",children:[e.jsx("button",{type:"button",className:"btn btn-secondary","aria-expanded":s,onClick:()=>n(!s),children:"Version history"}),s&&a?e.jsx(Je,{note:t,vaultId:a},`${a}:${t.id}`):null]})}function Je({note:t,vaultId:s}){var E,T;const n=A(),a=L(),[i,l]=h.useState(0),[r,o]=h.useState(null),[c,u]=h.useState(null),[m,p]=h.useState(!1),[f,g]=h.useState(null),b=F({queryKey:["history",s,t.id,i],queryFn:()=>n.listHistory(t.id,i),enabled:!!n,retry:!1}),x=F({queryKey:["historyVersion",s,t.id,r],queryFn:()=>n.readHistory(t.id,V(r)),enabled:!!n&&!!r,retry:!1}),y=M({networkMode:"always",retry:!1,mutationFn:()=>n.getNote(t.id),onSuccess:d=>{u(d),p(!1),g(null)}}),w=M({networkMode:"always",retry:!1,mutationFn:()=>{if(!J.isOnline())throw new Error("Connect to the vault before restoring.");if(!n||!r||!(c!=null&&c.updatedAt))throw new Error("Read the current note before restoring.");return n.restoreHistory(t.id,V(r),c.updatedAt)},onSuccess:d=>{a.invalidateQueries({queryKey:["note",s]});for(const v of["history","notes","notesForDateViews","viewList","tags","vaultInfo"])a.invalidateQueries({queryKey:[v,s]});u(d),p(!1),g("Version restored. The change you replaced is retained in history under the vault’s retention policy.")},onError:d=>{p(!1),u(null),g(d instanceof W?"The server refused this restore. The note may have changed or the selected history may be unavailable. Read the current note again and review the comparison.":`Restore could not be confirmed. Read the current note again before retrying. ${d.message}`)}}),P=d=>{o(d),u(null),p(!1),g(null),y.mutate()},k=w.isPending||y.isPending,R=!!x.data&&!x.isFetching&&!x.isError&&!y.isError&&x.data.content!==null&&x.data.encoding!=="overflow"&&!!(c!=null&&c.updatedAt)&&!k;return e.jsxs("div",{className:"mt-4 space-y-4","aria-label":"Note version history",children:[e.jsx("p",{className:"text-sm text-fg-muted",children:"History contains retained snapshots, not every keystroke. Older versions may have been pruned. Imported snapshots are labeled separately. Recovery needs a connection to the vault."}),n?null:e.jsx("p",{role:"alert",children:"Connect to this vault to read history."}),b.fetchStatus==="paused"?e.jsx("p",{role:"alert",children:"Connect to this vault to read history. Offline copies do not include version history."}):null,b.isPending&&n&&b.fetchStatus!=="paused"?e.jsx("output",{children:"Loading history…"}):null,b.isError?e.jsxs("div",{role:"alert",children:[e.jsx("p",{children:"History is unavailable. This server may not support it, the note may be unavailable, or your connection/access may need attention. This is not an empty-history result."}),e.jsx("button",{type:"button",className:"btn btn-secondary",onClick:()=>b.refetch(),children:"Retry history"})]}):null,((E=b.data)==null?void 0:E.versions.length)===0?e.jsx("p",{children:"No retained versions on this page. Earlier edits may predate history capture or have been pruned."}):null,e.jsx("ul",{className:"space-y-2",children:(T=b.data)==null?void 0:T.versions.map((d,v)=>e.jsx("li",{children:e.jsxs("button",{type:"button",className:"btn btn-secondary text-left",disabled:w.isPending,onClick:()=>P(d),children:[d.origin==="git-import"?`Imported snapshot ${d.import_ix}`:`Version ${d.version_ix}`," ","· ",d.superseded_at," · ",d.op]})},`${d.origin??"native"}:${d.import_ix??d.version_ix}:${v}`))}),b.data?e.jsxs("div",{className:"flex gap-2",children:[e.jsx("button",{type:"button",className:"btn btn-ghost",disabled:i===0||k,onClick:()=>l(Math.max(0,i-50)),children:"Newer"}),e.jsx("button",{type:"button",className:"btn btn-ghost",disabled:i+50>=b.data.total||k,onClick:()=>l(i+50),children:"Older"})]}):null,r?e.jsxs("div",{className:"space-y-3",children:[x.isPending||y.isPending?e.jsx("output",{children:"Loading comparison…"}):null,x.isError?e.jsx("p",{role:"alert",children:"This version could not be read. It may have been pruned, exceed history limits, or have damaged stored content. Choose another version."}):null,y.isError?e.jsx("p",{role:"alert",children:"The current note could not be read. Restore is disabled."}):null,x.data&&c?e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"grid gap-4 md:grid-cols-2",children:[e.jsx(O,{title:"Selected version",content:x.data.content,metadata:x.data.metadata,extension:x.data.extension}),e.jsx(O,{title:"Current note when reviewed",content:c.content,metadata:c.metadata,extension:c.extension})]}),x.data.content===null?e.jsx("p",{role:"alert",children:"This version records a change but has no recoverable content. It cannot be restored."}):null,t.updatedAt!==c.updatedAt?e.jsx("output",{children:"The displayed note has changed since this comparison. Refresh the comparison before deciding."}):null,e.jsx("p",{className:"text-sm text-fg-muted",children:"Restore replaces content, metadata and file type. It keeps the current path and tags. It creates a new recoverable change; it does not erase history."})]}):null,e.jsx("button",{type:"button",className:"btn btn-secondary",disabled:k,onClick:()=>{u(null),p(!1),y.mutate()},children:"Read current note again"}),e.jsx("button",{type:"button",className:"btn btn-secondary",disabled:!R,onClick:()=>p(!0),children:"Restore selected version…"}),m?e.jsxs("div",{className:"rounded border border-border p-4",children:[e.jsx("p",{children:"Replace the current note with this version? A newer edit will stop the restore."}),e.jsx("button",{type:"button",className:"btn btn-primary",disabled:!R,onClick:()=>w.mutate(),children:"Confirm restore"}),e.jsx("button",{type:"button",className:"btn btn-ghost",disabled:w.isPending,onClick:()=>p(!1),children:"Cancel"})]}):null]}):null,f?e.jsx("output",{children:f}):null]})}function O({title:t,content:s,metadata:n,extension:a}){return e.jsxs("div",{className:"min-w-0",children:[e.jsx("h3",{className:"font-semibold",children:t}),e.jsx("pre",{className:"max-h-96 overflow-auto whitespace-pre-wrap rounded border border-border p-3 text-sm",children:s??"Content unavailable"}),e.jsxs("details",{children:[e.jsx("summary",{children:"Metadata and file type"}),e.jsx("pre",{className:"overflow-auto text-sm",children:JSON.stringify({extension:a,metadata:n},null,2)})]})]})}function Xe({content:t,attachments:s,onRetry:n,retrying:a=!1}){const i={content:t,attachments:s},l=X(i);if(l==="pending"){const r=Y(i);return e.jsxs("output",{"aria-live":"polite",className:"mb-4 inline-flex items-center gap-2 rounded-md border border-sky-500/30 bg-sky-500/5 px-3 py-1.5 text-xs text-sky-300",children:[e.jsx("span",{"aria-hidden":!0,className:"inline-block h-2 w-2 animate-pulse rounded-full bg-sky-400"}),"Transcribing…",r?e.jsxs("span",{className:"text-sky-300/80",children:["part ",Math.min(r.done+1,r.total)," of ",r.total]}):null]})}return l==="failed"?e.jsxs("output",{className:"mb-4 inline-flex flex-wrap items-center gap-2 rounded-md border border-amber-500/30 bg-amber-500/5 px-3 py-1.5 text-xs text-amber-200",children:[e.jsx("span",{children:"Transcription unavailable — open the audio below and add a note by hand."}),n?e.jsx("button",{type:"button",onClick:n,disabled:a,className:"rounded border border-amber-500/40 px-2 py-0.5 font-medium text-amber-100 hover:bg-amber-500/15 disabled:opacity-50",children:a?"Retrying…":"Retry"}):null]}):l==="voice-limit"?e.jsx("output",{className:"mb-4 inline-flex items-center gap-2 rounded-md border border-border bg-bg/40 px-3 py-1.5 text-xs text-fg-muted",children:"Monthly voice limit reached — transcription resumes next month. The audio is saved below."}):null}function wt(){const{id:t}=Z(),s=I(i=>i.getActiveVault()),n=ee(),a=H(t);return Te(t,a.data),h.useEffect(()=>{s&&t&&te(s.id,t)},[s,t]),s?e.jsxs("div",{className:"page",children:[e.jsx("nav",{className:"mb-6 text-sm text-fg-dim",children:e.jsx(j,{to:"/notes",className:"focus-ring hover:text-accent",children:"← All notes"})}),a.isPending?e.jsx(mt,{}):a.data?e.jsxs(e.Fragment,{children:[a.isError?e.jsx(ae,{}):null,e.jsx(Ye,{note:a.data,cacheId:t})]}):a.isError?e.jsx(gt,{error:a.error,retry:()=>a.refetch()}):e.jsx(bt,{id:t??""})]}):e.jsx(se,{to:ne("/",`${n.pathname}${n.search}`),replace:!0})}function Ye({note:t,cacheId:s}){var E,T;const n=I(d=>d.getActiveVault()),{roles:a}=re((n==null?void 0:n.id)??null),i=ie(),{mirror:l,isOnline:r}=oe(),o=Ze(t,s),c=l.state==="offline",u=t.contentEvicted===!0,m=h.useMemo(()=>we(t),[t]),p=B(d=>d.on),f=B(d=>d.setOn);h.useEffect(()=>{if(!p)return;const d=v=>{v.key==="Escape"&&f(!1)};return window.addEventListener("keydown",d),()=>window.removeEventListener("keydown",d)},[p,f]);const g=t.path??t.id,b=le(t.content),x=b!==null&&!ce(b,t)?b:null,y=x!==null?{kind:"title",text:x}:t.path?de(t.path):{kind:"title",text:t.id},w=h.useMemo(()=>x!==null?{...t,content:ue(t.content??"")}:t,[t,x]),P=typeof((E=t.metadata)==null?void 0:E.summary)=="string"?t.metadata.summary:null,k=h.useMemo(()=>(t.links??[]).filter(d=>d.targetId===t.id&&d.sourceId!==t.id&&d.sourceNote),[t]),R=h.useMemo(()=>{const d=new Set,v=[];for(const C of t.links??[])C.sourceId!==t.id||C.targetId===t.id||C.targetNote&&(d.has(C.targetId)||(d.add(C.targetId),v.push(C)));return v},[t]);return e.jsxs("article",{className:"grid gap-10 lg:grid-cols-[minmax(0,1fr)_18rem]",children:[e.jsxs("div",{className:"min-w-0",children:[e.jsxs("header",{className:"mb-8 border-b border-border pb-5",children:[e.jsx("h1",{className:y.kind==="timestamp"?"page-title title-timestamp":"page-title",children:y.text}),c?e.jsx(xt,{}):null,t.tags&&t.tags.length>0?e.jsx(at,{tags:t.tags}):null,P?e.jsx("p",{className:"mt-3 text-fg-muted",children:P}):null,e.jsxs("div",{className:"mt-4 flex flex-wrap items-center gap-2",children:[e.jsx(j,{to:`/n/${encodeURIComponent(t.id)}/edit`,className:"btn btn-secondary btn-touch",children:"Edit"}),r&&!u&&!_(t.id)?e.jsx(ke,{label:"Attach file",className:"btn btn-secondary btn-touch",onPickFiles:o.start}):null,e.jsx(Re,{note:t,keyboard:!0}),e.jsx(Ee,{note:t}),e.jsxs("button",{type:"button",onClick:()=>f(!0),className:"btn btn-ghost btn-touch",title:"Focus (⌘.)",children:[e.jsx(he,{width:16,height:16}),"Focus"]}),me(t,a.view)?e.jsx(j,{to:`/views/${encodeURIComponent(t.id)}`,className:"btn btn-secondary btn-touch",children:"Open as view"}):null]}),o.uploads.length>0?e.jsx("div",{className:"mt-3",children:e.jsx(Ce,{uploads:o.uploads,onCancel:o.cancel,onDismiss:o.dismiss})}):null,e.jsx(it,{value:g,isPath:!!t.path}),e.jsx(We,{note:t})]}),e.jsx(Xe,{content:t.content??"",attachments:t.attachments,onRetry:()=>i.mutate({cacheId:s??t.id,serverId:t.id}),retrying:i.isPending}),u?e.jsx(ft,{preview:t.preview}):(T=w.content)!=null&&T.trim()?e.jsx(Se,{note:w,resolve:m}):x===null?e.jsx(pt,{noteId:t.id}):null,t.attachments&&t.attachments.length>0?e.jsxs("section",{className:"mt-10 border-t border-border pt-6",children:[e.jsx("h2",{className:"mb-3 font-serif text-xl",children:"Attachments"}),e.jsx("div",{className:"space-y-6",children:t.attachments.map(d=>e.jsx(lt,{attachment:d},d.id))})]}):null,e.jsx(Oe,{anchor:t})]}),e.jsxs("aside",{className:"space-y-6 text-sm lg:sticky lg:top-24 lg:self-start",children:[e.jsx(tt,{note:t}),R.length>0?e.jsx(U,{title:"Outbound",links:R,peer:"target"}):null,k.length>0?e.jsx(U,{title:"Inbound",links:k,peer:"source"}):null]})]})}function Ze(t,s){const n=A(),a=I(o=>o.activeVaultId),i=L(),l=fe(o=>o.push),r=Ie({noteId:t.id,onInsert:()=>{},onLinked:async o=>{const c=["note",a,s??t.id],u=i.getQueryData(c)??t;try{if(!n)throw new Error("No active vault");const m={append:et(u.content)+o};await n.updateNote(t.id,m),l("Attachment added","success")}catch{l("Attached, but couldn't add it to the note text.","error")}await i.invalidateQueries({queryKey:c,exact:!0}),i.invalidateQueries({queryKey:["notes",a]})},onError:o=>l(o,"error")});return{...r,uploads:r.uploads.filter(o=>o.status!=="done")}}function et(t){return t===""||t!=null&&t.endsWith(`
|
|
4
|
+
|
|
5
|
+
`)?"":t!=null&&t.endsWith(`
|
|
6
|
+
`)?`
|
|
7
|
+
`:`
|
|
8
|
+
|
|
9
|
+
`}function tt({note:t}){const s=t.createdAt,n=t.updatedAt,a=Object.entries(t.metadata??{}).filter(([i])=>i!=="summary");return e.jsxs("section",{className:"card shadow-soft p-4",children:[e.jsx("h2",{className:"eyebrow mb-2",children:"Metadata"}),e.jsxs("dl",{className:"space-y-1.5 text-sm",children:[t.path?e.jsx(S,{label:"Title",value:e.jsx("span",{className:"font-mono text-xs break-all",children:t.path})}):null,e.jsx(S,{label:"ID",value:e.jsx("span",{className:"font-mono text-xs break-all",children:t.id})}),e.jsx(S,{label:"Created",value:e.jsx("time",{title:s,children:D(s)})}),n?e.jsx(S,{label:"Updated",value:e.jsx("time",{title:n,children:D(n)})}):null,t.path?e.jsx(S,{label:"Path",value:e.jsx(be,{value:t.path,label:"note path",className:"mt-1"})}):null,a.map(([i,l])=>e.jsx(S,{label:i,value:e.jsx("span",{className:"break-all text-fg-muted",children:String(l)})},i))]}),e.jsx(st,{noteId:t.id}),t.path?e.jsx(nt,{path:t.path}):null,e.jsx(ge,{note:t,variant:"detail",className:"mt-3"})]})}function st({noteId:t}){const s=I(l=>l.getActiveVault()),{copied:n,copy:a}=$(),i=s?ve(s):"";return i?e.jsx("button",{type:"button",onClick:()=>a(Ne(i,t)),className:"btn btn-secondary btn-touch mt-3 w-full","aria-label":"Copy a shareable link to this note",children:n?"Copied ✓":"Copy link"}):null}function nt({path:t}){const{copied:s,copy:n}=$();return e.jsx("button",{type:"button",onClick:()=>n(t),className:"btn btn-secondary btn-touch mt-3 w-full","aria-label":"Copy reference to this note",children:s?"Copied ✓":"Copy reference"})}function S({label:t,value:s}){return e.jsxs("div",{className:"flex flex-col gap-0.5",children:[e.jsx("dt",{className:"eyebrow",children:t}),e.jsx("dd",{children:s})]})}function at({tags:t}){return e.jsx("div",{className:"mt-2 flex flex-wrap gap-1","aria-label":"Tags",children:t.map(s=>e.jsxs(j,{to:`/tags/${encodeURIComponent(s)}`,className:"chip chip-tag focus-ring max-w-full break-all",children:["#",s]},s))})}function rt(t){return e.jsxs("svg",{width:12,height:12,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:1.75,strokeLinecap:"round",strokeLinejoin:"round","aria-hidden":"true",...t,children:[e.jsx("rect",{x:"9",y:"9",width:"11",height:"11",rx:"2"}),e.jsx("path",{d:"M5 15H4.5A1.5 1.5 0 0 1 3 13.5v-9A1.5 1.5 0 0 1 4.5 3h9A1.5 1.5 0 0 1 15 4.5V5"})]})}function it({value:t,isPath:s}){const{copied:n,copy:a}=$();return e.jsxs("button",{type:"button",onClick:()=>a(t),"aria-label":s?"Copy path":"Copy note id",className:"focus-ring group mt-4 flex max-w-full items-center gap-1.5 rounded text-fg-dim transition-colors hover:text-fg-muted",children:[e.jsx(rt,{className:"shrink-0 opacity-70 transition-opacity group-hover:opacity-100"}),e.jsx("span",{className:"min-w-0 truncate font-mono text-xs",children:t}),n?e.jsx("span",{className:"shrink-0 text-xs text-fg-muted",children:"Copied"}):null]})}function U({title:t,links:s,peer:n}){return e.jsxs("section",{className:"card shadow-soft p-4",children:[e.jsxs("h2",{className:"eyebrow mb-2 tabular-nums",children:[t," (",s.length,")"]}),e.jsx("ul",{className:"space-y-1.5",children:s.map(a=>{var o;const i=n==="source"?a.sourceNote:a.targetNote;if(!i)return null;const l=i.path??i.id,r=typeof((o=i.metadata)==null?void 0:o.summary)=="string"?i.metadata.summary:null;return e.jsx("li",{children:e.jsxs(j,{to:`/n/${encodeURIComponent(i.id)}`,className:"block rounded px-1 py-0.5 hover:bg-bg/50",children:[e.jsx("div",{className:"truncate font-mono text-xs text-fg-muted hover:text-accent",children:l}),r?e.jsx("div",{className:"mt-0.5 line-clamp-2 text-xs text-fg-dim",children:r}):null]})},`${a.sourceId}->${a.targetId}:${a.relationship}`)})})]})}function ot(t){var n;const s=(n=t.path)==null?void 0:n.replace(/^\/+/,"");return{filename:t.filename??(s?s.split("/").pop():void 0),url:t.url??(s?`/api/storage/${s}`:void 0)}}function lt({attachment:t}){const{filename:s,url:n}=ot(t);if(!s||!n)return e.jsx("figure",{className:"card shadow-soft p-3",children:e.jsx(ct,{})});const a=(t.mimeType??"").toLowerCase();return e.jsxs("figure",{className:"card shadow-soft p-3",children:[e.jsxs("figcaption",{className:"mb-2 flex items-baseline justify-between gap-3",children:[e.jsx("span",{className:"truncate font-mono text-xs text-fg-muted",children:s}),typeof t.size=="number"?e.jsx("span",{className:"shrink-0 text-xs text-fg-dim",children:ht(t.size)}):null]}),e.jsx(dt,{url:n,mime:a,filename:s})]})}function ct(){return e.jsxs("div",{className:"flex items-center gap-2 text-sm text-fg-dim","aria-busy":"true",children:[e.jsx(N,{className:"h-4 w-32"}),e.jsx("span",{children:"Processing…"})]})}function dt({url:t,mime:s,filename:n}){const a=A(),[i,l]=h.useState(null),[r,o]=h.useState(null),c=ut(s,n),u=c!=="other";if(h.useEffect(()=>{if(!u||!a)return;let p=!1,f=null;return o(null),a.fetchAttachmentBlob(t).then(g=>{p||(f=URL.createObjectURL(g),l(f))}).catch(g=>{p||o(g instanceof Error?g.message:"Failed to load attachment")}),()=>{p=!0,f&&URL.revokeObjectURL(f)}},[u,t,a]),r)return e.jsx("p",{className:"text-sm text-danger",children:r});if(u&&!i)return e.jsx(N,{className:"h-32 w-full"});const m=i??t;return c==="image"?e.jsx("img",{src:m,alt:n,className:"max-h-[32rem] rounded"}):c==="audio"?e.jsx("audio",{controls:!0,src:m,className:"w-full"}):c==="video"?e.jsx("video",{controls:!0,src:m,className:"w-full rounded"}):c==="pdf"?e.jsxs(e.Fragment,{children:[e.jsx("iframe",{src:m,title:n,className:"h-[40rem] w-full rounded border border-border"}),e.jsxs("a",{href:m,download:n,className:"mt-2 inline-block text-sm text-accent hover:underline",children:["Download ",n]})]}):e.jsxs("a",{href:m,download:n,className:"text-sm text-accent hover:underline",children:["Download ",n]})}function ut(t,s){if(t.startsWith("image/"))return"image";if(t.startsWith("audio/"))return"audio";if(t.startsWith("video/"))return"video";if(t==="application/pdf")return"pdf";const n=s.toLowerCase().split(".").pop()??"";return["png","jpg","jpeg","gif","webp","svg"].includes(n)?"image":["mp3","wav","ogg","m4a","flac"].includes(n)?"audio":["mp4","webm","mov"].includes(n)?"video":n==="pdf"?"pdf":"other"}function ht(t){return t<1024?`${t} B`:t<1024*1024?`${(t/1024).toFixed(1)} KB`:t<1024*1024*1024?`${(t/(1024*1024)).toFixed(1)} MB`:`${(t/(1024*1024*1024)).toFixed(2)} GB`}function mt(){return e.jsxs("div",{className:"grid gap-10 lg:grid-cols-[minmax(0,1fr)_18rem]","aria-busy":"true",children:[e.jsxs("div",{className:"min-w-0 space-y-3",children:[e.jsx(N,{className:"h-3 w-32"}),e.jsx(N,{className:"h-8 w-2/3"}),e.jsx(N,{className:"h-4 w-full"}),e.jsx("div",{className:"mt-6 space-y-2",children:[0,1,2,3,4,5].map(t=>e.jsx(N,{className:"h-3",width:`${70+t*13%25}%`},t))})]}),e.jsxs("div",{className:"space-y-4",children:[e.jsx(N,{className:"h-32"}),e.jsx(N,{className:"h-24"})]})]})}function pt({noteId:t}){return e.jsxs("p",{className:"my-8 font-serif text-lg italic text-fg-muted",children:["Nothing here yet."," ",e.jsx(j,{to:`/n/${encodeURIComponent(t)}/edit`,className:"not-italic text-accent hover:underline",children:"Start writing →"})]})}function xt(){return e.jsx("p",{className:"mt-2",children:e.jsx("span",{className:"chip bg-bg-soft text-fg-muted",title:"Served from your offline copy",children:"Saved copy"})})}function ft({preview:t}){return e.jsxs("div",{className:"my-8",children:[t?e.jsx("p",{className:"mb-4 text-fg-muted",children:t}):null,e.jsx("p",{className:"font-serif text-lg italic text-fg-muted",children:"Connect to load this note."})]})}function bt({id:t}){return e.jsx(xe,{title:e.jsx("span",{className:"font-serif text-xl text-fg",children:"Note not found"}),description:e.jsxs(e.Fragment,{children:["No note with id ",e.jsx("span",{className:"font-mono",children:t})," in this vault."]}),action:e.jsx(j,{to:"/notes",className:"text-sm text-accent hover:underline",children:"Back to all notes"})})}function gt({error:t,retry:s}){const n=t instanceof je,a=t instanceof ye,i=n?"Session expired":a?"Note not found":"Could not load note",l=n?t.message:a?"Couldn't find this note. It may have been deleted, or the link may be wrong.":"Something went wrong loading this note. You can try again, or head back to your notes.";return e.jsx(pe,{title:i,message:e.jsxs(e.Fragment,{children:[l,n?null:e.jsxs("details",{className:"mt-3",children:[e.jsx("summary",{className:"cursor-pointer text-xs text-fg-dim hover:text-fg-muted",children:"Technical detail"}),e.jsx("p",{className:"mt-1 whitespace-pre-wrap break-words font-mono text-xs text-fg-dim",children:t.message})]})]}),retry:n?void 0:s,action:n?e.jsx(j,{to:"/add",className:"btn btn-primary",children:"Reconnect vault"}):e.jsx(j,{to:"/notes",className:"btn btn-secondary btn-touch",children:"Back to notes"})})}export{wt as NoteView};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{P as U,e as z,Q as E,b as l,r as u,br as I,bs as A,bt as C,bu as H,R as O,x as P,bv as $,_ as L,bw as M,j as e,$ as d}from"./index-
|
|
1
|
+
import{P as U,e as z,Q as E,b as l,r as u,br as I,bs as A,bt as C,bu as H,R as O,x as P,bv as $,_ as L,bw as M,j as e,$ as d}from"./index-BwG_4Oup.js";import{W as p}from"./WizardShell-Cp46Sjm6.js";import"./history-DeQhlq0x.js";function _(s){try{return new URL(s).host}catch{return"your hub"}}function D(){const[s]=U(),m=z(),h=E(),x=l(r=>r.addVault),[n,c]=u.useState({kind:"working"}),b=u.useRef(!1);if(u.useEffect(()=>{if(b.current)return;b.current=!0;const r=s.get("code"),f=s.get("state"),v=s.get("error");if(v){const o=s.get("error_description");c({kind:"error",message:`Vault returned: ${v}${o?` — ${o}`:""}`});return}if(!r||!f){c({kind:"error",message:"Missing code or state in callback URL."});return}(async()=>{var o,g,j,w;try{const{pending:t,token:a}=await I(r,f),y=a.vault?`vault:${a.vault}`:void 0,S=(y?(g=(o=a.services)==null?void 0:o[y])==null?void 0:g.url:void 0)??((w=(j=a.services)==null?void 0:j.vault)==null?void 0:w.url)??t.issuerUrl,R=l.getState().activeVaultId,i=x({url:S,name:a.vault??t.issuer,issuer:t.issuer,tokenEndpoint:t.tokenEndpoint,clientId:t.clientId,scope:a.scope},A(a));a.services&&C(i,a.services);const k=H.getState();k.clearHalt(i),t.priorHaltedVaultId&&t.priorHaltedVaultId!==i&&k.clearHalt(t.priorHaltedVaultId);const V=O(t.redirect)??"/";if(i!==R){const N=l.getState().vaults[i];N&&P($(N))}h(L(V),{replace:!0})}catch(t){if(t instanceof M){c({kind:"pending-approval",approveUrl:t.approveUrl});return}c({kind:"error",message:t.message})}})()},[s,h,x]),n.kind==="working")return e.jsxs(p,{escape:{kind:"none"},children:[e.jsx(d,{size:72,className:"mx-auto mb-4 animate-pulse"}),e.jsx("p",{className:"eyebrow mb-3",children:"One moment"}),e.jsxs("h1",{className:"hero-title mb-2",style:{fontSize:"clamp(1.8rem, 4vw, 2.3rem)"},children:["Connecting",e.jsx("span",{className:"accent-word",children:"…"})]}),e.jsx("output",{"aria-live":"polite",className:"font-round text-sm text-fg-muted",children:"Exchanging the authorization code with your vault."})]});if(n.kind==="pending-approval"){const r=_(n.approveUrl);return e.jsxs(p,{escape:{kind:"back",to:"/"},children:[e.jsx(d,{size:60,className:"mx-auto mb-6"}),e.jsx("p",{className:"eyebrow mb-3",children:"Redirected"}),e.jsxs("h1",{className:"hero-title mb-4",style:{fontSize:"clamp(1.6rem, 3.5vw, 2.1rem)"},children:["Approving Parachute on ",e.jsx("span",{className:"accent-word",children:r})]}),e.jsx("p",{className:"mx-auto mb-8 max-w-sm text-fg-muted",children:"Your hub admin needs to approve this app before sign-in can complete. Open the approval page in your hub, approve, then try again."}),e.jsxs("div",{className:"flex flex-wrap items-center justify-center gap-4",children:[e.jsx("a",{href:n.approveUrl,target:"_blank",rel:"noopener noreferrer",className:"btn btn-primary btn-lg justify-center rounded-full px-6 shadow-soft",children:"Open approval page →"}),e.jsx("button",{type:"button",onClick:()=>m("/add",{replace:!0}),className:"font-round text-sm font-semibold text-fg-dim hover:text-accent",children:"Retry now"})]})]})}return e.jsxs(p,{escape:{kind:"back",to:"/"},children:[e.jsx(d,{size:60,className:"mx-auto mb-6"}),e.jsx("p",{className:"eyebrow mb-3",children:"Connection failed"}),e.jsxs("h1",{className:"hero-title mb-4",style:{fontSize:"clamp(1.6rem, 3.5vw, 2.1rem)"},children:["Something went ",e.jsx("span",{className:"accent-word",children:"sideways."})]}),e.jsx("p",{className:"mx-auto mb-8 max-w-sm text-fg-muted",children:n.message}),e.jsx("button",{type:"button",onClick:()=>m("/add",{replace:!0}),className:"btn btn-primary btn-lg justify-center rounded-full px-6 shadow-soft",children:"Try again →"})]})}export{D as OAuthCallback};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{r as l,j as t,e as v,ak as h,
|
|
1
|
+
import{r as l,j as t,e as v,ak as h,bn as j,V as y,b as k,af as w,ax as E}from"./index-BwG_4Oup.js";function P({note:a,className:d,label:c="Delete"}){const[r,o]=l.useState(!1);return t.jsxs(t.Fragment,{children:[t.jsx("button",{type:"button",onClick:()=>o(!0),className:d??"min-h-11 rounded-lg border border-red-500/40 bg-transparent px-3 py-1.5 text-sm text-red-400 hover:bg-red-500/10",title:"Delete this note",children:c}),r?t.jsx(N,{note:a,onClose:()=>o(!1)}):null]})}function N({note:a,onClose:d}){const c=v(),r=h(e=>e.push),o=j(),i=a.path??a.id,[f,p]=l.useState(""),[u,b]=l.useState(null),x=l.useRef(null),s=f===i&&!o.isPending;l.useEffect(()=>{var e;(e=x.current)==null||e.focus()},[]),l.useEffect(()=>{const e=m=>{m.key==="Escape"&&d()};return window.addEventListener("keydown",e),()=>window.removeEventListener("keydown",e)},[d]);const n=l.useCallback(()=>{s&&(b(null),o.mutate(a.id,{onSuccess:()=>{r(`Deleted ${i}`,"success"),c("/",{replace:!0})},onError:e=>{e instanceof y?b("Session expired. Reconnect to delete."):b(e instanceof Error?e.message:"Delete failed")}}))},[s,i,o,c,a.id,r]);return t.jsx("dialog",{open:!0,"aria-labelledby":"confirm-delete-title",className:"fixed inset-0 z-40 m-0 flex h-full max-h-full w-full max-w-full items-center justify-center bg-black/60 p-4",onMouseDown:e=>{e.target===e.currentTarget&&d()},children:t.jsxs("div",{className:"w-full max-w-md rounded-2xl border border-border bg-card p-6 shadow-lift",children:[t.jsx("h2",{id:"confirm-delete-title",className:"mb-2 font-serif text-xl text-red-400",children:"Delete this note?"}),t.jsx("p",{className:"mb-3 text-sm text-fg-muted",children:"This permanently removes the note, its tags, and its links. This cannot be undone."}),t.jsxs("p",{className:"mb-3 text-sm text-fg-muted",children:["Type"," ",t.jsx("span",{className:"rounded bg-bg/60 px-1 py-0.5 font-mono text-xs text-fg",children:i})," ","to confirm:"]}),t.jsx("input",{ref:x,type:"text",value:f,onChange:e=>p(e.target.value),onKeyDown:e=>{e.key==="Enter"&&s&&n()},"aria-label":"Type note path to confirm",className:"mb-3 w-full rounded-lg border border-border bg-bg/40 px-2.5 py-1.5 font-mono text-sm text-fg focus:border-red-400 focus:outline-none",placeholder:i,autoComplete:"off",spellCheck:!1}),u?t.jsx("p",{role:"alert",className:"mb-3 text-sm text-red-400",children:u}):null,t.jsxs("div",{className:"flex justify-end gap-2",children:[t.jsx("button",{type:"button",onClick:d,className:"min-h-11 rounded-lg border border-border bg-card px-3 py-1.5 text-sm text-fg-muted hover:text-fg",children:"Cancel"}),t.jsx("button",{type:"button",onClick:n,disabled:!s,className:"btn btn-danger-solid btn-touch",children:o.isPending?"Deleting…":"Delete permanently"})]})]})})}function C({note:a,keyboard:d=!1}){var b,x;const c=k(s=>s.getActiveVault()),{roles:r}=w((c==null?void 0:c.id)??null),o=h(s=>s.push),i=E(a.id),f=((b=a.tags)==null?void 0:b.includes(r.pinned))??!1,p=((x=a.tags)==null?void 0:x.includes(r.archived))??!1,u=l.useCallback(s=>{var m;if(i.isPending)return;const n=r[s],e=((m=a.tags)==null?void 0:m.includes(n))??!1;i.mutate({tags:e?{remove:[n]}:{add:[n]}},{onSuccess:()=>{o(s==="pinned"?e?"Unpinned":"Pinned":e?"Unarchived":"Archived","success")},onError:g=>{g instanceof y?o("Session expired. Reconnect.","error"):o(g instanceof Error?g.message:"Update failed","error")}})},[i,a.tags,o,r]);return l.useEffect(()=>{if(!d)return;const s=n=>{if(n.defaultPrevented)return;const e=n.target;if(e){const m=e.tagName;if(m==="INPUT"||m==="TEXTAREA"||e.isContentEditable)return}n.metaKey||n.ctrlKey||n.altKey||(n.key==="p"||n.key==="P"?(n.preventDefault(),u("pinned")):(n.key==="a"||n.key==="A")&&(n.preventDefault(),u("archived")))};return window.addEventListener("keydown",s),()=>window.removeEventListener("keydown",s)},[d,u]),t.jsxs(t.Fragment,{children:[t.jsx("button",{type:"button",onClick:()=>u("pinned"),disabled:i.isPending,"aria-pressed":f,title:f?`Unpin (${r.pinned})`:`Pin as #${r.pinned} (P)`,className:f?"min-h-11 rounded-lg border border-accent/60 bg-accent/10 px-3 py-1.5 text-sm text-accent hover:bg-accent/20 disabled:opacity-40":"min-h-11 rounded-lg border border-border bg-card px-3 py-1.5 text-sm text-fg-muted hover:text-accent disabled:opacity-40",children:f?"★ Pinned":"☆ Pin"}),t.jsx("button",{type:"button",onClick:()=>u("archived"),disabled:i.isPending,"aria-pressed":p,title:p?`Unarchive (${r.archived})`:`Archive as #${r.archived} (A)`,className:p?"min-h-11 rounded-lg border border-amber-500/40 bg-amber-500/10 px-3 py-1.5 text-sm text-amber-500 hover:bg-amber-500/20 disabled:opacity-40":"min-h-11 rounded-lg border border-border bg-card px-3 py-1.5 text-sm text-fg-muted hover:text-accent disabled:opacity-40",children:p?"Archived":"Archive"})]})}export{P as D,C as P};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{aa as $,r,h as A,v as _,bx as L,j as e,L as j,ak as v,M as C,by as V,i as M,e as R,aK as P,b as D,bz as I,a as B,bA as z,N as Y,bB as F,bC as U,bD as H,bE as K,bF as G,bG as Q,af as W,bH as q,bI as T,bJ as N,aL as J,bK as X,bL as Z,bM as ee,u as te,g as se,bN as ne,bO as ae,o as ie,c as re,bP as oe}from"./index-CkXqzhj_.js";import{u as ce,a as le,b as de,c as ue}from"./transcribe-default-Z7qqgq1r.js";import{r as he,w as me}from"./editor-mode-D9fveTEx.js";import"./types-BaJkUfo6.js";const xe={read:"Can read notes",write:"Can read and write notes",admin:"Full access"};function fe({vault:t,fetchImpl:s}){const a=$(t.clientId),[n,o]=r.useState(!1),[d,l]=r.useState({kind:"loading"});r.useEffect(()=>{if(!a)return;let c=!0;return A(s).then(m=>{var f;c&&o(((f=m==null?void 0:m.capabilities)==null?void 0:f.connections)===!0)}).catch(()=>{}),()=>{c=!1}},[a,s]);const x=_(t.url)??t.name,u=r.useRef(0),i=r.useCallback(async()=>{const c=++u.current;l(m=>m.kind==="ready"?m:{kind:"loading"});try{const m=await L(x,s);if(c!==u.current)return;const f=Array.isArray(m==null?void 0:m.connections)?m.connections.filter(pe):[];l({kind:"ready",connections:f})}catch{c===u.current&&l({kind:"error"})}},[x,s]);return r.useEffect(()=>{u.current++,l({kind:"loading"})},[x]),r.useEffect(()=>{n&&i()},[n,i]),!a||!n?null:e.jsxs("section",{"aria-labelledby":"connected-apps-heading",className:"card space-y-4 rounded-xl p-6 shadow-soft",children:[e.jsxs("div",{children:[e.jsx("h2",{id:"connected-apps-heading",className:"font-serif text-xl text-fg",children:"Connected apps"}),e.jsxs("p",{className:"mt-1 text-sm text-fg-muted",children:["AIs and apps you've allowed into ",t.name,". Disconnect one and it loses access within about a minute."]})]}),d.kind==="loading"?e.jsx("p",{className:"text-sm text-fg-dim","aria-live":"polite",children:"Loading…"}):d.kind==="error"?e.jsxs("div",{className:"flex items-center justify-between gap-4",children:[e.jsx("p",{className:"text-sm text-fg-muted",children:"Couldn't load connected apps."}),e.jsx("button",{type:"button",className:"btn btn-secondary",onClick:()=>void i(),children:"Try again"})]}):d.connections.length===0?e.jsxs("p",{className:"text-sm text-fg-muted",children:["Nothing is connected yet."," ",e.jsx(j,{to:"/connect",className:"text-accent hover:underline",children:"Connect an AI"})," ","to read and write this vault from Claude, ChatGPT, or any MCP client."]}):e.jsx("ul",{className:"divide-y divide-border",children:d.connections.map(c=>e.jsx(ge,{connection:c,vaultSlug:x,fetchImpl:s,onDisconnected:i},c.client_id))})]})}function pe(t){return!!t&&typeof t=="object"&&typeof t.client_id=="string"}function ge({connection:t,vaultSlug:s,fetchImpl:a,onDisconnected:n}){const[o,d]=r.useState(!1),[l,x]=r.useState(!1),u=v(g=>g.push),i=typeof t.client_name=="string"&&t.client_name.trim()?t.client_name:"An app",c=C(t.connected_at),m=t.last_used_at?C(t.last_used_at):"";async function f(){x(!0);try{await V(s,t.client_id,a),u(`${i} is disconnected.`,"success"),await n()}catch{u(`Couldn't disconnect ${i}. Try again.`,"error"),x(!1),d(!1)}}return e.jsxs("li",{className:"py-3 first:pt-0 last:pb-0",children:[e.jsxs("div",{className:"flex items-start justify-between gap-4",children:[e.jsxs("span",{className:"min-w-0",children:[e.jsx("span",{className:"block font-medium text-fg",children:i}),e.jsxs("span",{className:"mt-0.5 block text-sm text-fg-muted",children:[xe[t.access]??"Has access",c?` · connected ${c}`:"",m?` · last used ${m}`:""]}),t.covers==="account"?e.jsx("span",{className:"mt-0.5 block text-xs text-fg-dim",children:"Reaches every vault in your account; disconnecting removes it from all of them."}):null]}),o?null:e.jsx("button",{type:"button",className:"btn btn-secondary shrink-0",onClick:()=>d(!0),children:"Disconnect"})]}),o?e.jsxs("div",{className:"mt-3 flex flex-wrap items-center gap-3",children:[e.jsxs("span",{className:"text-sm text-fg",children:["Disconnect ",i,"? You can connect it again later."]}),e.jsx("button",{type:"button",className:"btn btn-primary",disabled:l,onClick:()=>void f(),children:l?"Disconnecting…":`Yes, disconnect ${i}`}),e.jsx("button",{type:"button",className:"btn btn-secondary",disabled:l,onClick:()=>d(!1),children:"Cancel"})]}):null]})}const be={byCode:{confirm_mismatch:"That doesn't match the vault name.",not_owner:"That vault isn't linked to this account."},sessionEnded:"Your sign-in has ended. Sign in again, then come back here to delete this vault.",fallback:"Couldn't delete this vault. Try again."};function ye({vault:t}){var o;const s=M(t),[a,n]=r.useState(null);return r.useEffect(()=>{if(!s)return;let d=!0;return A().then(l=>{d&&n(l)}),()=>{d=!1}},[s]),!s||(a==null?void 0:a.door)!=="cloud"||((o=a.capabilities)==null?void 0:o.vault_delete)!==!0?null:e.jsx(je,{vault:t})}function je({vault:t}){const s=r.useId(),a=R(),n=P(),o=D(b=>b.removeVault),d=v(b=>b.push),[l,x]=r.useState(""),[u,i]=r.useState(!1),[c,m]=r.useState(null),f=r.useRef(!0),g=r.useRef(null);r.useEffect(()=>(f.current=!0,()=>{f.current=!1,g.current&&o(g.current)}),[o]);const h=_(t.url)??t.name,p=l===h;async function y(b){if(b.preventDefault(),!(!p||u)){i(!0),m(null);try{await I(h,l)}catch(O){f.current&&(m(B(O,be)),i(!1));return}if(n.invalidateQueries({queryKey:z}),d(`Vault ${h} deleted.`,"success"),!f.current){o(t.id);return}g.current=t.id,a("/vaults")}}return e.jsxs("section",{"aria-label":"Delete this vault",className:"card space-y-3 rounded-xl p-6 shadow-soft",children:[e.jsx("h2",{className:"font-serif text-xl text-fg",children:"Delete this vault"}),e.jsxs("p",{className:"text-sm text-fg-muted",children:["This deletes the vault ",e.jsx("b",{className:"font-semibold text-fg",children:h})," now: every note, file, snapshot and export in it. It is immediate and permanent, and there is no undo."," ",e.jsx(j,{to:"/export",className:"focus-ring text-accent underline",children:"Export first"})," ","if you want a copy."]}),e.jsxs("form",{onSubmit:y,className:"space-y-3",children:[e.jsx("label",{htmlFor:s,className:"block text-sm font-medium text-fg",children:"Type the vault name to confirm"}),e.jsx("input",{id:s,value:l,onChange:b=>x(b.target.value),autoComplete:"off",spellCheck:!1,placeholder:h,className:"input"}),e.jsx("button",{type:"submit",disabled:!p||u,className:"btn btn-danger-solid btn-touch",children:u?"Deleting…":"Delete vault"})]}),c?e.jsx("p",{role:"alert",className:"rounded-lg border border-danger-border bg-danger-soft px-3 py-2 text-sm text-danger",children:c}):null]})}function Me(){const t=D(s=>s.getActiveVault());return t?e.jsxs("div",{className:"page-prose",children:[e.jsxs("header",{className:"mb-10",children:[e.jsx("nav",{className:"mb-4 text-sm text-fg-dim",children:e.jsx(j,{to:"/",className:"focus-ring hover:text-accent",children:"← Home"})}),e.jsx("p",{className:"eyebrow mb-1",children:t.name}),e.jsx("h1",{className:"page-title",children:"Settings"}),e.jsx("p",{className:"mt-2 text-fg-muted",children:"Everything about this vault, in one calm place."})]}),e.jsxs("div",{className:"space-y-8",children:[e.jsx(ve,{}),e.jsx(fe,{vault:t}),e.jsx(we,{}),e.jsx(Ce,{vaultId:t.id}),e.jsx(Te,{}),e.jsx(ke,{}),e.jsx(Re,{vaultId:t.id}),e.jsx(De,{vaultId:t.id}),e.jsx(Ee,{vaultId:t.id}),e.jsx(_e,{}),e.jsx(ye,{vault:t})]})]}):e.jsx(Y,{to:"/",replace:!0})}function ve(){return e.jsxs("section",{"aria-label":"Manage",children:[e.jsx("h2",{className:"eyebrow mb-3",children:"Manage"}),e.jsxs("div",{className:"card divide-y divide-border rounded-xl shadow-soft",children:[e.jsx(w,{to:"/account",title:"Account",description:"Your plan, billing, hosted vaults, and sign-in — managed in the app."}),e.jsx(Ne,{}),e.jsx(w,{to:"/connect",title:"Connections",description:"Connect Claude, ChatGPT, or any MCP client to this vault."}),e.jsx(w,{to:"/vaults",title:"Vaults",description:"Add a vault, switch between them, or export."})]})]})}function Ne(){const t=R(),s=te(i=>i.identityEpoch),[a,n]=r.useState(null),[o,d]=r.useState(!1);if(r.useEffect(()=>{let i=!0;return se().then(c=>{i&&n(c.signed_in?{identity:c.email??c.username??null,csrf:c.csrf}:null)}).catch(()=>{i&&n(null)}),()=>{i=!1}},[s]),!a)return null;const{identity:l,csrf:x}=a;async function u(){d(!0);try{await ie(x)}finally{re(),t("/",{replace:!0})}}return e.jsxs("div",{className:"flex items-center justify-between gap-4 px-5 py-4",children:[e.jsxs("span",{className:"min-w-0",children:[e.jsxs("span",{className:"block font-medium text-fg",children:["Signed in",l?` as ${l}`:""]}),e.jsx("span",{className:"mt-0.5 block text-sm text-fg-muted",children:"Signing out ends your account session on this device. Vaults already connected here stay until you remove them."})]}),e.jsx("button",{type:"button",onClick:u,disabled:o,className:"btn btn-secondary btn-touch shrink-0",children:o?"Signing out…":"Sign out"})]})}function w({to:t,href:s,title:a,description:n}){const o=e.jsxs(e.Fragment,{children:[e.jsxs("span",{className:"min-w-0",children:[e.jsx("span",{className:"block font-medium text-fg",children:a}),e.jsx("span",{className:"mt-0.5 block text-sm text-fg-muted",children:n})]}),e.jsx("span",{"aria-hidden":"true",className:"shrink-0 text-fg-dim",children:s?"↗":"→"})]}),d="focus-ring flex items-center justify-between gap-4 px-5 py-4 transition-colors hover:bg-bg-soft first:rounded-t-xl last:rounded-b-xl";return s?e.jsx("a",{href:s,className:d,children:o}):e.jsx(j,{to:t??"/",className:d,children:o})}function we(){return e.jsxs("section",{className:"card space-y-3 rounded-xl p-6 shadow-soft",children:[e.jsxs("div",{children:[e.jsx("h2",{className:"font-serif text-xl text-fg",children:"Import notes"}),e.jsx("p",{className:"mt-1 text-sm text-fg-muted",children:"Bring in an Obsidian vault zip or a folder of markdown files. Parsed in your browser; previewed before any note lands in the vault."})]}),e.jsx(j,{to:"/import",className:"btn btn-primary btn-touch",children:"Open importer"})]})}const Se=[{value:"keep",title:"Keep",help:"Recordings are stored with your notes; included wherever attachments are included."},{value:"until_transcribed",title:"Delete after transcribing",help:"Your words stay; the audio file is removed once the transcript lands."},{value:"never",title:"Never store",help:"Audio is removed even if transcription fails — the transcript is your only copy; failed transcriptions lose the audio."}];function Ce({vaultId:t}){const s=F(),a=ce(),n=le(),{markMade:o}=de(t),{transcribeDefault:d,setTranscribeDefault:l}=ue(t),x=v(i=>i.push);if((s==null?void 0:s.enabled)===!1)return null;const u=i=>{i===a.value||n.isPending||n.mutate(i,{onSuccess:()=>{o(),x("Voice recording setting saved.","success")},onError:c=>{x(c instanceof Error&&c.message?`Couldn't save: ${c.message}`:"Couldn't save the voice recording setting.","error")}})};return e.jsxs("section",{className:"card space-y-6 rounded-xl p-6 shadow-soft",children:[e.jsxs("div",{children:[e.jsx("h2",{className:"font-serif text-xl text-fg",children:"Voice"}),e.jsx("p",{className:"mt-1 text-sm text-fg-muted",children:"How voice capture behaves in this vault."})]}),e.jsxs("div",{className:"flex items-start justify-between gap-4",children:[e.jsxs("div",{children:[e.jsx("h3",{className:"font-medium text-fg",children:"Transcribe recordings by default"}),e.jsx("p",{className:"mt-1 text-sm text-fg-muted",children:"New voice notes start with transcription on — your words are added to the note. Turn it off for a single recording right where you capture. Applies on this device."})]}),e.jsx("button",{type:"button",role:"switch","aria-checked":d,"aria-label":"Transcribe recordings by default","data-testid":"transcribe-default-toggle",onClick:()=>l(!d),className:`relative h-7 w-12 shrink-0 rounded-full transition-colors ${d?"bg-accent":"bg-border"}`,children:e.jsx("span",{className:`absolute top-0.5 left-0 h-6 w-6 rounded-full bg-card shadow-sm transition-transform ${d?"translate-x-5":"translate-x-0.5"}`})})]}),e.jsxs("div",{className:"space-y-4 border-t border-border pt-6",children:[e.jsxs("div",{children:[e.jsx("h3",{className:"font-medium text-fg",children:"Keep recordings"}),e.jsx("p",{className:"mt-1 text-sm text-fg-muted",children:"What happens to the audio file after a voice note is transcribed. Applies to this vault, from every device connected to it."})]}),a.isLoading?e.jsx("p",{className:"text-sm text-fg-dim",children:"Loading…"}):a.isError?e.jsx("p",{className:"text-sm text-fg-dim","data-testid":"retention-load-error",children:"Couldn't load this setting — check the vault connection."}):e.jsxs(e.Fragment,{children:[e.jsxs("fieldset",{className:"space-y-2",disabled:!a.supported||n.isPending,children:[e.jsx("legend",{className:"sr-only",children:"Voice recording retention"}),Se.map(i=>{const c=a.value===i.value;return e.jsxs("label",{className:`flex items-start gap-3 rounded-xl border p-3 transition-colors ${c?"border-accent bg-accent/5":"border-border hover:border-accent/40"}`,children:[e.jsx("input",{type:"radio",name:"audio-retention",value:i.value,checked:c,onChange:()=>u(i.value),className:"mt-1 accent-accent"}),e.jsxs("span",{children:[e.jsx("span",{className:"block font-medium text-fg",children:i.title}),e.jsx("span",{className:"mt-0.5 block text-sm text-fg-muted",children:i.help})]})]},i.value)})]}),a.supported?null:e.jsx("p",{className:"text-xs text-fg-dim","data-testid":"retention-unsupported",children:"This vault doesn't support changing this yet — recordings are kept. Update the vault to choose."})]})]})]})}function Te(){const[t,s]=r.useState(()=>he()),a=n=>{s(n),me(n)};return e.jsx("section",{className:"card space-y-4 rounded-xl p-6 shadow-soft",children:e.jsxs("div",{className:"flex items-start justify-between gap-4",children:[e.jsxs("div",{children:[e.jsx("h2",{className:"font-serif text-xl text-fg",children:"Live preview"}),e.jsx("p",{className:"mt-1 text-sm text-fg-muted",children:"Formats your writing as you type — Markdown stays underneath. Turn off for the raw editor with a side-by-side preview."})]}),e.jsx("button",{type:"button",role:"switch","aria-checked":t,"aria-label":"Live preview",onClick:()=>a(!t),className:`relative h-7 w-12 shrink-0 rounded-full transition-colors ${t?"bg-accent":"bg-border"}`,children:e.jsx("span",{className:`absolute top-0.5 left-0 h-6 w-6 rounded-full bg-card shadow-sm transition-transform ${t?"translate-x-5":"translate-x-0.5"}`})})]})})}function ke(){const[t,s]=r.useState(()=>U()),a=n=>{s(n),ne(n),ae(n)};return e.jsxs("section",{className:"card space-y-4 rounded-xl p-6 shadow-soft",children:[e.jsxs("div",{children:[e.jsx("h2",{className:"font-serif text-xl text-fg",children:"Text size"}),e.jsx("p",{className:"mt-1 text-sm text-fg-muted",children:"Affects the editor and rendered notes on this device. Your markdown isn't changed."})]}),e.jsxs("fieldset",{className:"space-y-2",children:[e.jsx("legend",{className:"sr-only",children:"View text size"}),H.map(n=>{const o=t===n;return e.jsxs("label",{className:`flex items-center gap-3 rounded-xl border p-3 transition-colors ${o?"border-accent bg-accent/5":"border-border hover:border-accent/40"}`,children:[e.jsx("input",{type:"radio",name:"text-size",value:n,checked:o,onChange:()=>a(n),className:"accent-accent"}),e.jsx("span",{className:"font-medium text-fg",children:K(n)})]},n)})]})]})}function Ee({vaultId:t}){const{db:s,mirror:a}=J(),n=v(m=>m.push),[o,d]=r.useState(null),[l,x]=r.useState(null),u=r.useCallback(async()=>{if(!s)return;const[m,f]=await Promise.all([X(s,t),Z(s,t)]);d({bytes:m,count:f})},[s,t]);if(r.useEffect(()=>{u()},[u]),!a.enabled)return null;const i=async()=>{if(!l){x("sync");try{await a.syncNow(),await u(),n("Synced offline copy.","success")}catch{n("Couldn't sync the offline copy right now.","error")}finally{x(null)}}},c=async()=>{if(!l&&confirm("Clear this vault's offline copy from this device? Un-synced changes are kept.")){x("clear");try{await a.clearOffline(),await u(),n("Offline copy cleared.","success")}catch{n("Couldn't clear the offline copy.","error")}finally{x(null)}}};return e.jsxs("section",{className:"card space-y-5 rounded-xl p-6 shadow-soft","aria-label":"Offline",children:[e.jsxs("div",{children:[e.jsx("h2",{className:"font-serif text-xl text-fg",children:"Offline"}),e.jsx("p",{className:"mt-1 text-sm text-fg-muted",children:"A copy of this vault is kept on this device so your notes open without a connection."})]}),e.jsxs("dl",{className:"space-y-2 text-sm",children:[e.jsxs("div",{className:"flex items-baseline justify-between gap-4",children:[e.jsx("dt",{className:"text-fg-muted",children:"Status"}),e.jsx("dd",{className:"text-fg",children:Ae(a.state)})]}),e.jsxs("div",{className:"flex items-baseline justify-between gap-4",children:[e.jsx("dt",{className:"text-fg-muted",children:"Last synced"}),e.jsx("dd",{className:"text-fg-muted",children:a.lastSyncedAt?C(new Date(a.lastSyncedAt).toISOString()):"never"})]}),e.jsxs("div",{className:"flex items-baseline justify-between gap-4",children:[e.jsx("dt",{className:"text-fg-muted",children:"Saved on this device"}),e.jsx("dd",{className:"text-fg-muted tabular-nums","data-testid":"offline-usage",children:o?`${o.count} note${o.count===1?"":"s"} · ${k(o.bytes)} of ${k(oe)}`:"—"})]})]}),e.jsxs("div",{className:"flex flex-wrap items-center gap-3 pt-1",children:[e.jsx("button",{type:"button",onClick:i,disabled:l!==null,className:"btn btn-secondary btn-touch",children:l==="sync"?"Syncing…":"Sync now"}),e.jsx("button",{type:"button",onClick:c,disabled:l!==null,className:"text-sm text-danger hover:underline disabled:opacity-60",children:l==="clear"?"Clearing…":"Clear offline copy"})]})]})}function Ae(t){switch(t){case"hydrating":return"Saving your vault…";case"offline":return"Offline — showing your saved vault";case"error":return"Sync error";default:return"Saved for offline"}}function k(t){return t<1024*1024?`${(t/1024).toFixed(0)} KB`:t<1024*1024*1024?`${(t/(1024*1024)).toFixed(1)} MB`:`${(t/(1024*1024*1024)).toFixed(2)} GB`}function _e(){const[t,s]=r.useState(!1);return r.useEffect(()=>{s(ee())},[]),t?e.jsx("section",{className:"card rounded-xl p-6 text-sm shadow-soft",children:e.jsxs("p",{className:"text-fg-muted",children:[e.jsx("span",{className:"mr-2 inline-block rounded-full bg-positive-soft px-2 py-0.5 text-xs font-medium text-positive",children:"Installed"}),"Parachute is running as an installed app on this device."]})}):null}const E={auto:{title:"Auto",help:"Show the tree only when the vault has enough folders to make it worth the space."},always:{title:"Always",help:"Always show the tree, even on a tag-flat vault."},never:{title:"Never",help:"Hide the tree. The path-prefix text input still works."}};function Re({vaultId:t}){const{mode:s,setMode:a}=G(t);return e.jsxs("section",{className:"card space-y-4 rounded-xl p-6 shadow-soft",children:[e.jsxs("div",{children:[e.jsx("h2",{className:"font-serif text-xl text-fg",children:"Folder tree (Notes sidebar)"}),e.jsx("p",{className:"mt-1 text-sm text-fg-muted",children:"Controls the collapsible folder tree on the notes list page. Auto-detect renders the tree when the vault has at least five top-level folders or twenty notes in folders."})]}),e.jsxs("fieldset",{className:"space-y-2",children:[e.jsx("legend",{className:"sr-only",children:"Path tree visibility"}),Q.map(n=>{const o=s===n;return e.jsxs("label",{className:`flex items-start gap-3 rounded-xl border p-3 transition-colors ${o?"border-accent bg-accent/5":"border-border hover:border-accent/40"}`,children:[e.jsx("input",{type:"radio",name:"path-tree-mode",value:n,checked:o,onChange:()=>a(n),className:"mt-1 accent-accent"}),e.jsxs("span",{children:[e.jsx("span",{className:"block font-medium text-fg",children:E[n].title}),e.jsx("span",{className:"mt-0.5 block text-sm text-fg-muted",children:E[n].help})]})]},n)})]})]})}const S={pinned:{title:"Pinned",help:"Tag for notes you want at the top of views."},archived:{title:"Archived",help:"Tag for notes you've moved out of the way."},captureVoice:{title:"Inbox tag for voice notes",help:"Added to a new voice note with no other tag, when “Tag new notes as an inbox” is on."},captureText:{title:"Inbox tag for typed notes",help:"Added to a new typed note with no other tag, when “Tag new notes as an inbox” is on."},view:{title:"Saved view",help:"Tag that view notes carry. Used to list them in the Views band."}};function De({vaultId:t}){const{roles:s,setRoles:a,tagNewNotes:n,setTagNewNotes:o}=W(t),d=q(),l=v(h=>h.push),x=r.useId(),[u,i]=r.useState(s);r.useEffect(()=>i(s),[s]);const c=r.useMemo(()=>{const h=(d.data??[]).map(p=>p.name);return[...new Set(h)].sort((p,y)=>p.localeCompare(y))},[d.data]),m=T.some(h=>u[h].trim()!==s[h]),f=()=>{a(u),l("Tag roles saved.","success")},g=()=>{a(null),i(N),l("Tag roles reset to defaults.","success")};return e.jsxs("section",{className:"card space-y-5 rounded-xl p-6 shadow-soft",children:[e.jsxs("div",{children:[e.jsx("h2",{className:"font-serif text-xl text-fg",children:"Tag roles"}),e.jsx("p",{className:"mt-1 text-sm text-fg-muted",children:"Point each role at whatever tag your vault already uses. Changes apply to future notes only — existing notes keep their current tags."})]}),e.jsxs("div",{className:"flex items-start justify-between gap-4",children:[e.jsxs("div",{children:[e.jsx("h3",{className:"font-medium text-fg",children:"Tag new notes as an inbox"}),e.jsxs("p",{className:"mt-1 text-sm text-fg-muted",children:["When on, a new note you write or record here that has no tags gets your inbox tag (",s.captureText===s.captureVoice?`#${s.captureText}`:`#${s.captureText} for typed notes, #${s.captureVoice} for voice notes`,"), so you can sort it later. Off by default. Whether a note was typed or spoken is recorded either way."]})]}),e.jsx("button",{type:"button",role:"switch","aria-checked":n,"aria-label":"Tag new notes as an inbox","data-testid":"tag-new-notes-toggle",onClick:()=>o(!n),className:`relative h-7 w-12 shrink-0 rounded-full transition-colors ${n?"bg-accent":"bg-border"}`,children:e.jsx("span",{className:`absolute top-0.5 left-0 h-6 w-6 rounded-full bg-card shadow-sm transition-transform ${n?"translate-x-5":"translate-x-0.5"}`})})]}),e.jsx("datalist",{id:x,children:c.map(h=>e.jsx("option",{value:h},h))}),e.jsx("div",{className:"space-y-4",children:T.map(h=>e.jsxs("label",{className:"block text-sm",children:[e.jsxs("span",{className:"mb-1.5 flex items-baseline justify-between gap-2",children:[e.jsx("span",{className:"font-medium text-fg",children:S[h].title}),e.jsxs("span",{className:"text-xs text-fg-dim",children:["default: #",N[h]]})]}),e.jsx("input",{type:"text",value:u[h],onChange:p=>i(y=>({...y,[h]:p.target.value})),list:x,placeholder:N[h],"aria-label":`${S[h].title} tag role`,spellCheck:!1,autoCapitalize:"none",autoCorrect:"off",className:"input input-on-bg"}),e.jsx("span",{className:"mt-1.5 block text-xs text-fg-dim",children:S[h].help})]},h))}),e.jsxs("div",{className:"flex flex-wrap items-center gap-4 pt-1",children:[e.jsx("button",{type:"button",onClick:f,disabled:!m,className:"btn btn-primary btn-lg",children:"Save"}),e.jsx("button",{type:"button",onClick:g,className:"btn btn-ghost",children:"Reset to defaults"})]})]})}export{Me as Settings};
|
|
1
|
+
import{aa as $,r,h as A,v as _,bx as L,j as e,L as j,ak as v,M as C,by as V,i as M,e as R,aK as P,b as D,bz as I,a as B,bA as z,N as Y,bB as F,bC as U,bD as H,bE as K,bF as G,bG as Q,af as W,bH as q,bI as T,bJ as N,aL as J,bK as X,bL as Z,bM as ee,u as te,g as se,bN as ne,bO as ae,o as ie,c as re,bP as oe}from"./index-BwG_4Oup.js";import{u as ce,a as le,b as de,c as ue}from"./transcribe-default-Cz5r46Dt.js";import{r as he,w as me}from"./editor-mode-D9fveTEx.js";import"./types-BaJkUfo6.js";const xe={read:"Can read notes",write:"Can read and write notes",admin:"Full access"};function fe({vault:t,fetchImpl:s}){const a=$(t.clientId),[n,o]=r.useState(!1),[d,l]=r.useState({kind:"loading"});r.useEffect(()=>{if(!a)return;let c=!0;return A(s).then(m=>{var f;c&&o(((f=m==null?void 0:m.capabilities)==null?void 0:f.connections)===!0)}).catch(()=>{}),()=>{c=!1}},[a,s]);const x=_(t.url)??t.name,u=r.useRef(0),i=r.useCallback(async()=>{const c=++u.current;l(m=>m.kind==="ready"?m:{kind:"loading"});try{const m=await L(x,s);if(c!==u.current)return;const f=Array.isArray(m==null?void 0:m.connections)?m.connections.filter(pe):[];l({kind:"ready",connections:f})}catch{c===u.current&&l({kind:"error"})}},[x,s]);return r.useEffect(()=>{u.current++,l({kind:"loading"})},[x]),r.useEffect(()=>{n&&i()},[n,i]),!a||!n?null:e.jsxs("section",{"aria-labelledby":"connected-apps-heading",className:"card space-y-4 rounded-xl p-6 shadow-soft",children:[e.jsxs("div",{children:[e.jsx("h2",{id:"connected-apps-heading",className:"font-serif text-xl text-fg",children:"Connected apps"}),e.jsxs("p",{className:"mt-1 text-sm text-fg-muted",children:["AIs and apps you've allowed into ",t.name,". Disconnect one and it loses access within about a minute."]})]}),d.kind==="loading"?e.jsx("p",{className:"text-sm text-fg-dim","aria-live":"polite",children:"Loading…"}):d.kind==="error"?e.jsxs("div",{className:"flex items-center justify-between gap-4",children:[e.jsx("p",{className:"text-sm text-fg-muted",children:"Couldn't load connected apps."}),e.jsx("button",{type:"button",className:"btn btn-secondary",onClick:()=>void i(),children:"Try again"})]}):d.connections.length===0?e.jsxs("p",{className:"text-sm text-fg-muted",children:["Nothing is connected yet."," ",e.jsx(j,{to:"/connect",className:"text-accent hover:underline",children:"Connect an AI"})," ","to read and write this vault from Claude, ChatGPT, or any MCP client."]}):e.jsx("ul",{className:"divide-y divide-border",children:d.connections.map(c=>e.jsx(ge,{connection:c,vaultSlug:x,fetchImpl:s,onDisconnected:i},c.client_id))})]})}function pe(t){return!!t&&typeof t=="object"&&typeof t.client_id=="string"}function ge({connection:t,vaultSlug:s,fetchImpl:a,onDisconnected:n}){const[o,d]=r.useState(!1),[l,x]=r.useState(!1),u=v(g=>g.push),i=typeof t.client_name=="string"&&t.client_name.trim()?t.client_name:"An app",c=C(t.connected_at),m=t.last_used_at?C(t.last_used_at):"";async function f(){x(!0);try{await V(s,t.client_id,a),u(`${i} is disconnected.`,"success"),await n()}catch{u(`Couldn't disconnect ${i}. Try again.`,"error"),x(!1),d(!1)}}return e.jsxs("li",{className:"py-3 first:pt-0 last:pb-0",children:[e.jsxs("div",{className:"flex items-start justify-between gap-4",children:[e.jsxs("span",{className:"min-w-0",children:[e.jsx("span",{className:"block font-medium text-fg",children:i}),e.jsxs("span",{className:"mt-0.5 block text-sm text-fg-muted",children:[xe[t.access]??"Has access",c?` · connected ${c}`:"",m?` · last used ${m}`:""]}),t.covers==="account"?e.jsx("span",{className:"mt-0.5 block text-xs text-fg-dim",children:"Reaches every vault in your account; disconnecting removes it from all of them."}):null]}),o?null:e.jsx("button",{type:"button",className:"btn btn-secondary shrink-0",onClick:()=>d(!0),children:"Disconnect"})]}),o?e.jsxs("div",{className:"mt-3 flex flex-wrap items-center gap-3",children:[e.jsxs("span",{className:"text-sm text-fg",children:["Disconnect ",i,"? You can connect it again later."]}),e.jsx("button",{type:"button",className:"btn btn-primary",disabled:l,onClick:()=>void f(),children:l?"Disconnecting…":`Yes, disconnect ${i}`}),e.jsx("button",{type:"button",className:"btn btn-secondary",disabled:l,onClick:()=>d(!1),children:"Cancel"})]}):null]})}const be={byCode:{confirm_mismatch:"That doesn't match the vault name.",not_owner:"That vault isn't linked to this account."},sessionEnded:"Your sign-in has ended. Sign in again, then come back here to delete this vault.",fallback:"Couldn't delete this vault. Try again."};function ye({vault:t}){var o;const s=M(t),[a,n]=r.useState(null);return r.useEffect(()=>{if(!s)return;let d=!0;return A().then(l=>{d&&n(l)}),()=>{d=!1}},[s]),!s||(a==null?void 0:a.door)!=="cloud"||((o=a.capabilities)==null?void 0:o.vault_delete)!==!0?null:e.jsx(je,{vault:t})}function je({vault:t}){const s=r.useId(),a=R(),n=P(),o=D(b=>b.removeVault),d=v(b=>b.push),[l,x]=r.useState(""),[u,i]=r.useState(!1),[c,m]=r.useState(null),f=r.useRef(!0),g=r.useRef(null);r.useEffect(()=>(f.current=!0,()=>{f.current=!1,g.current&&o(g.current)}),[o]);const h=_(t.url)??t.name,p=l===h;async function y(b){if(b.preventDefault(),!(!p||u)){i(!0),m(null);try{await I(h,l)}catch(O){f.current&&(m(B(O,be)),i(!1));return}if(n.invalidateQueries({queryKey:z}),d(`Vault ${h} deleted.`,"success"),!f.current){o(t.id);return}g.current=t.id,a("/vaults")}}return e.jsxs("section",{"aria-label":"Delete this vault",className:"card space-y-3 rounded-xl p-6 shadow-soft",children:[e.jsx("h2",{className:"font-serif text-xl text-fg",children:"Delete this vault"}),e.jsxs("p",{className:"text-sm text-fg-muted",children:["This deletes the vault ",e.jsx("b",{className:"font-semibold text-fg",children:h})," now: every note, file, snapshot and export in it. It is immediate and permanent, and there is no undo."," ",e.jsx(j,{to:"/export",className:"focus-ring text-accent underline",children:"Export first"})," ","if you want a copy."]}),e.jsxs("form",{onSubmit:y,className:"space-y-3",children:[e.jsx("label",{htmlFor:s,className:"block text-sm font-medium text-fg",children:"Type the vault name to confirm"}),e.jsx("input",{id:s,value:l,onChange:b=>x(b.target.value),autoComplete:"off",spellCheck:!1,placeholder:h,className:"input"}),e.jsx("button",{type:"submit",disabled:!p||u,className:"btn btn-danger-solid btn-touch",children:u?"Deleting…":"Delete vault"})]}),c?e.jsx("p",{role:"alert",className:"rounded-lg border border-danger-border bg-danger-soft px-3 py-2 text-sm text-danger",children:c}):null]})}function Me(){const t=D(s=>s.getActiveVault());return t?e.jsxs("div",{className:"page-prose",children:[e.jsxs("header",{className:"mb-10",children:[e.jsx("nav",{className:"mb-4 text-sm text-fg-dim",children:e.jsx(j,{to:"/",className:"focus-ring hover:text-accent",children:"← Home"})}),e.jsx("p",{className:"eyebrow mb-1",children:t.name}),e.jsx("h1",{className:"page-title",children:"Settings"}),e.jsx("p",{className:"mt-2 text-fg-muted",children:"Everything about this vault, in one calm place."})]}),e.jsxs("div",{className:"space-y-8",children:[e.jsx(ve,{}),e.jsx(fe,{vault:t}),e.jsx(we,{}),e.jsx(Ce,{vaultId:t.id}),e.jsx(Te,{}),e.jsx(ke,{}),e.jsx(Re,{vaultId:t.id}),e.jsx(De,{vaultId:t.id}),e.jsx(Ee,{vaultId:t.id}),e.jsx(_e,{}),e.jsx(ye,{vault:t})]})]}):e.jsx(Y,{to:"/",replace:!0})}function ve(){return e.jsxs("section",{"aria-label":"Manage",children:[e.jsx("h2",{className:"eyebrow mb-3",children:"Manage"}),e.jsxs("div",{className:"card divide-y divide-border rounded-xl shadow-soft",children:[e.jsx(w,{to:"/account",title:"Account",description:"Your plan, billing, hosted vaults, and sign-in — managed in the app."}),e.jsx(Ne,{}),e.jsx(w,{to:"/connect",title:"Connections",description:"Connect Claude, ChatGPT, or any MCP client to this vault."}),e.jsx(w,{to:"/vaults",title:"Vaults",description:"Add a vault, switch between them, or export."})]})]})}function Ne(){const t=R(),s=te(i=>i.identityEpoch),[a,n]=r.useState(null),[o,d]=r.useState(!1);if(r.useEffect(()=>{let i=!0;return se().then(c=>{i&&n(c.signed_in?{identity:c.email??c.username??null,csrf:c.csrf}:null)}).catch(()=>{i&&n(null)}),()=>{i=!1}},[s]),!a)return null;const{identity:l,csrf:x}=a;async function u(){d(!0);try{await ie(x)}finally{re(),t("/",{replace:!0})}}return e.jsxs("div",{className:"flex items-center justify-between gap-4 px-5 py-4",children:[e.jsxs("span",{className:"min-w-0",children:[e.jsxs("span",{className:"block font-medium text-fg",children:["Signed in",l?` as ${l}`:""]}),e.jsx("span",{className:"mt-0.5 block text-sm text-fg-muted",children:"Signing out ends your account session on this device. Vaults already connected here stay until you remove them."})]}),e.jsx("button",{type:"button",onClick:u,disabled:o,className:"btn btn-secondary btn-touch shrink-0",children:o?"Signing out…":"Sign out"})]})}function w({to:t,href:s,title:a,description:n}){const o=e.jsxs(e.Fragment,{children:[e.jsxs("span",{className:"min-w-0",children:[e.jsx("span",{className:"block font-medium text-fg",children:a}),e.jsx("span",{className:"mt-0.5 block text-sm text-fg-muted",children:n})]}),e.jsx("span",{"aria-hidden":"true",className:"shrink-0 text-fg-dim",children:s?"↗":"→"})]}),d="focus-ring flex items-center justify-between gap-4 px-5 py-4 transition-colors hover:bg-bg-soft first:rounded-t-xl last:rounded-b-xl";return s?e.jsx("a",{href:s,className:d,children:o}):e.jsx(j,{to:t??"/",className:d,children:o})}function we(){return e.jsxs("section",{className:"card space-y-3 rounded-xl p-6 shadow-soft",children:[e.jsxs("div",{children:[e.jsx("h2",{className:"font-serif text-xl text-fg",children:"Import notes"}),e.jsx("p",{className:"mt-1 text-sm text-fg-muted",children:"Bring in an Obsidian vault zip or a folder of markdown files. Parsed in your browser; previewed before any note lands in the vault."})]}),e.jsx(j,{to:"/import",className:"btn btn-primary btn-touch",children:"Open importer"})]})}const Se=[{value:"keep",title:"Keep",help:"Recordings are stored with your notes; included wherever attachments are included."},{value:"until_transcribed",title:"Delete after transcribing",help:"Your words stay; the audio file is removed once the transcript lands."},{value:"never",title:"Never store",help:"Audio is removed even if transcription fails — the transcript is your only copy; failed transcriptions lose the audio."}];function Ce({vaultId:t}){const s=F(),a=ce(),n=le(),{markMade:o}=de(t),{transcribeDefault:d,setTranscribeDefault:l}=ue(t),x=v(i=>i.push);if((s==null?void 0:s.enabled)===!1)return null;const u=i=>{i===a.value||n.isPending||n.mutate(i,{onSuccess:()=>{o(),x("Voice recording setting saved.","success")},onError:c=>{x(c instanceof Error&&c.message?`Couldn't save: ${c.message}`:"Couldn't save the voice recording setting.","error")}})};return e.jsxs("section",{className:"card space-y-6 rounded-xl p-6 shadow-soft",children:[e.jsxs("div",{children:[e.jsx("h2",{className:"font-serif text-xl text-fg",children:"Voice"}),e.jsx("p",{className:"mt-1 text-sm text-fg-muted",children:"How voice capture behaves in this vault."})]}),e.jsxs("div",{className:"flex items-start justify-between gap-4",children:[e.jsxs("div",{children:[e.jsx("h3",{className:"font-medium text-fg",children:"Transcribe recordings by default"}),e.jsx("p",{className:"mt-1 text-sm text-fg-muted",children:"New voice notes start with transcription on — your words are added to the note. Turn it off for a single recording right where you capture. Applies on this device."})]}),e.jsx("button",{type:"button",role:"switch","aria-checked":d,"aria-label":"Transcribe recordings by default","data-testid":"transcribe-default-toggle",onClick:()=>l(!d),className:`relative h-7 w-12 shrink-0 rounded-full transition-colors ${d?"bg-accent":"bg-border"}`,children:e.jsx("span",{className:`absolute top-0.5 left-0 h-6 w-6 rounded-full bg-card shadow-sm transition-transform ${d?"translate-x-5":"translate-x-0.5"}`})})]}),e.jsxs("div",{className:"space-y-4 border-t border-border pt-6",children:[e.jsxs("div",{children:[e.jsx("h3",{className:"font-medium text-fg",children:"Keep recordings"}),e.jsx("p",{className:"mt-1 text-sm text-fg-muted",children:"What happens to the audio file after a voice note is transcribed. Applies to this vault, from every device connected to it."})]}),a.isLoading?e.jsx("p",{className:"text-sm text-fg-dim",children:"Loading…"}):a.isError?e.jsx("p",{className:"text-sm text-fg-dim","data-testid":"retention-load-error",children:"Couldn't load this setting — check the vault connection."}):e.jsxs(e.Fragment,{children:[e.jsxs("fieldset",{className:"space-y-2",disabled:!a.supported||n.isPending,children:[e.jsx("legend",{className:"sr-only",children:"Voice recording retention"}),Se.map(i=>{const c=a.value===i.value;return e.jsxs("label",{className:`flex items-start gap-3 rounded-xl border p-3 transition-colors ${c?"border-accent bg-accent/5":"border-border hover:border-accent/40"}`,children:[e.jsx("input",{type:"radio",name:"audio-retention",value:i.value,checked:c,onChange:()=>u(i.value),className:"mt-1 accent-accent"}),e.jsxs("span",{children:[e.jsx("span",{className:"block font-medium text-fg",children:i.title}),e.jsx("span",{className:"mt-0.5 block text-sm text-fg-muted",children:i.help})]})]},i.value)})]}),a.supported?null:e.jsx("p",{className:"text-xs text-fg-dim","data-testid":"retention-unsupported",children:"This vault doesn't support changing this yet — recordings are kept. Update the vault to choose."})]})]})]})}function Te(){const[t,s]=r.useState(()=>he()),a=n=>{s(n),me(n)};return e.jsx("section",{className:"card space-y-4 rounded-xl p-6 shadow-soft",children:e.jsxs("div",{className:"flex items-start justify-between gap-4",children:[e.jsxs("div",{children:[e.jsx("h2",{className:"font-serif text-xl text-fg",children:"Live preview"}),e.jsx("p",{className:"mt-1 text-sm text-fg-muted",children:"Formats your writing as you type — Markdown stays underneath. Turn off for the raw editor with a side-by-side preview."})]}),e.jsx("button",{type:"button",role:"switch","aria-checked":t,"aria-label":"Live preview",onClick:()=>a(!t),className:`relative h-7 w-12 shrink-0 rounded-full transition-colors ${t?"bg-accent":"bg-border"}`,children:e.jsx("span",{className:`absolute top-0.5 left-0 h-6 w-6 rounded-full bg-card shadow-sm transition-transform ${t?"translate-x-5":"translate-x-0.5"}`})})]})})}function ke(){const[t,s]=r.useState(()=>U()),a=n=>{s(n),ne(n),ae(n)};return e.jsxs("section",{className:"card space-y-4 rounded-xl p-6 shadow-soft",children:[e.jsxs("div",{children:[e.jsx("h2",{className:"font-serif text-xl text-fg",children:"Text size"}),e.jsx("p",{className:"mt-1 text-sm text-fg-muted",children:"Affects the editor and rendered notes on this device. Your markdown isn't changed."})]}),e.jsxs("fieldset",{className:"space-y-2",children:[e.jsx("legend",{className:"sr-only",children:"View text size"}),H.map(n=>{const o=t===n;return e.jsxs("label",{className:`flex items-center gap-3 rounded-xl border p-3 transition-colors ${o?"border-accent bg-accent/5":"border-border hover:border-accent/40"}`,children:[e.jsx("input",{type:"radio",name:"text-size",value:n,checked:o,onChange:()=>a(n),className:"accent-accent"}),e.jsx("span",{className:"font-medium text-fg",children:K(n)})]},n)})]})]})}function Ee({vaultId:t}){const{db:s,mirror:a}=J(),n=v(m=>m.push),[o,d]=r.useState(null),[l,x]=r.useState(null),u=r.useCallback(async()=>{if(!s)return;const[m,f]=await Promise.all([X(s,t),Z(s,t)]);d({bytes:m,count:f})},[s,t]);if(r.useEffect(()=>{u()},[u]),!a.enabled)return null;const i=async()=>{if(!l){x("sync");try{await a.syncNow(),await u(),n("Synced offline copy.","success")}catch{n("Couldn't sync the offline copy right now.","error")}finally{x(null)}}},c=async()=>{if(!l&&confirm("Clear this vault's offline copy from this device? Un-synced changes are kept.")){x("clear");try{await a.clearOffline(),await u(),n("Offline copy cleared.","success")}catch{n("Couldn't clear the offline copy.","error")}finally{x(null)}}};return e.jsxs("section",{className:"card space-y-5 rounded-xl p-6 shadow-soft","aria-label":"Offline",children:[e.jsxs("div",{children:[e.jsx("h2",{className:"font-serif text-xl text-fg",children:"Offline"}),e.jsx("p",{className:"mt-1 text-sm text-fg-muted",children:"A copy of this vault is kept on this device so your notes open without a connection."})]}),e.jsxs("dl",{className:"space-y-2 text-sm",children:[e.jsxs("div",{className:"flex items-baseline justify-between gap-4",children:[e.jsx("dt",{className:"text-fg-muted",children:"Status"}),e.jsx("dd",{className:"text-fg",children:Ae(a.state)})]}),e.jsxs("div",{className:"flex items-baseline justify-between gap-4",children:[e.jsx("dt",{className:"text-fg-muted",children:"Last synced"}),e.jsx("dd",{className:"text-fg-muted",children:a.lastSyncedAt?C(new Date(a.lastSyncedAt).toISOString()):"never"})]}),e.jsxs("div",{className:"flex items-baseline justify-between gap-4",children:[e.jsx("dt",{className:"text-fg-muted",children:"Saved on this device"}),e.jsx("dd",{className:"text-fg-muted tabular-nums","data-testid":"offline-usage",children:o?`${o.count} note${o.count===1?"":"s"} · ${k(o.bytes)} of ${k(oe)}`:"—"})]})]}),e.jsxs("div",{className:"flex flex-wrap items-center gap-3 pt-1",children:[e.jsx("button",{type:"button",onClick:i,disabled:l!==null,className:"btn btn-secondary btn-touch",children:l==="sync"?"Syncing…":"Sync now"}),e.jsx("button",{type:"button",onClick:c,disabled:l!==null,className:"text-sm text-danger hover:underline disabled:opacity-60",children:l==="clear"?"Clearing…":"Clear offline copy"})]})]})}function Ae(t){switch(t){case"hydrating":return"Saving your vault…";case"offline":return"Offline — showing your saved vault";case"error":return"Sync error";default:return"Saved for offline"}}function k(t){return t<1024*1024?`${(t/1024).toFixed(0)} KB`:t<1024*1024*1024?`${(t/(1024*1024)).toFixed(1)} MB`:`${(t/(1024*1024*1024)).toFixed(2)} GB`}function _e(){const[t,s]=r.useState(!1);return r.useEffect(()=>{s(ee())},[]),t?e.jsx("section",{className:"card rounded-xl p-6 text-sm shadow-soft",children:e.jsxs("p",{className:"text-fg-muted",children:[e.jsx("span",{className:"mr-2 inline-block rounded-full bg-positive-soft px-2 py-0.5 text-xs font-medium text-positive",children:"Installed"}),"Parachute is running as an installed app on this device."]})}):null}const E={auto:{title:"Auto",help:"Show the tree only when the vault has enough folders to make it worth the space."},always:{title:"Always",help:"Always show the tree, even on a tag-flat vault."},never:{title:"Never",help:"Hide the tree. The path-prefix text input still works."}};function Re({vaultId:t}){const{mode:s,setMode:a}=G(t);return e.jsxs("section",{className:"card space-y-4 rounded-xl p-6 shadow-soft",children:[e.jsxs("div",{children:[e.jsx("h2",{className:"font-serif text-xl text-fg",children:"Folder tree (Notes sidebar)"}),e.jsx("p",{className:"mt-1 text-sm text-fg-muted",children:"Controls the collapsible folder tree on the notes list page. Auto-detect renders the tree when the vault has at least five top-level folders or twenty notes in folders."})]}),e.jsxs("fieldset",{className:"space-y-2",children:[e.jsx("legend",{className:"sr-only",children:"Path tree visibility"}),Q.map(n=>{const o=s===n;return e.jsxs("label",{className:`flex items-start gap-3 rounded-xl border p-3 transition-colors ${o?"border-accent bg-accent/5":"border-border hover:border-accent/40"}`,children:[e.jsx("input",{type:"radio",name:"path-tree-mode",value:n,checked:o,onChange:()=>a(n),className:"mt-1 accent-accent"}),e.jsxs("span",{children:[e.jsx("span",{className:"block font-medium text-fg",children:E[n].title}),e.jsx("span",{className:"mt-0.5 block text-sm text-fg-muted",children:E[n].help})]})]},n)})]})]})}const S={pinned:{title:"Pinned",help:"Tag for notes you want at the top of views."},archived:{title:"Archived",help:"Tag for notes you've moved out of the way."},captureVoice:{title:"Inbox tag for voice notes",help:"Added to a new voice note with no other tag, when “Tag new notes as an inbox” is on."},captureText:{title:"Inbox tag for typed notes",help:"Added to a new typed note with no other tag, when “Tag new notes as an inbox” is on."},view:{title:"Saved view",help:"Tag that view notes carry. Used to list them in the Views band."}};function De({vaultId:t}){const{roles:s,setRoles:a,tagNewNotes:n,setTagNewNotes:o}=W(t),d=q(),l=v(h=>h.push),x=r.useId(),[u,i]=r.useState(s);r.useEffect(()=>i(s),[s]);const c=r.useMemo(()=>{const h=(d.data??[]).map(p=>p.name);return[...new Set(h)].sort((p,y)=>p.localeCompare(y))},[d.data]),m=T.some(h=>u[h].trim()!==s[h]),f=()=>{a(u),l("Tag roles saved.","success")},g=()=>{a(null),i(N),l("Tag roles reset to defaults.","success")};return e.jsxs("section",{className:"card space-y-5 rounded-xl p-6 shadow-soft",children:[e.jsxs("div",{children:[e.jsx("h2",{className:"font-serif text-xl text-fg",children:"Tag roles"}),e.jsx("p",{className:"mt-1 text-sm text-fg-muted",children:"Point each role at whatever tag your vault already uses. Changes apply to future notes only — existing notes keep their current tags."})]}),e.jsxs("div",{className:"flex items-start justify-between gap-4",children:[e.jsxs("div",{children:[e.jsx("h3",{className:"font-medium text-fg",children:"Tag new notes as an inbox"}),e.jsxs("p",{className:"mt-1 text-sm text-fg-muted",children:["When on, a new note you write or record here that has no tags gets your inbox tag (",s.captureText===s.captureVoice?`#${s.captureText}`:`#${s.captureText} for typed notes, #${s.captureVoice} for voice notes`,"), so you can sort it later. Off by default. Whether a note was typed or spoken is recorded either way."]})]}),e.jsx("button",{type:"button",role:"switch","aria-checked":n,"aria-label":"Tag new notes as an inbox","data-testid":"tag-new-notes-toggle",onClick:()=>o(!n),className:`relative h-7 w-12 shrink-0 rounded-full transition-colors ${n?"bg-accent":"bg-border"}`,children:e.jsx("span",{className:`absolute top-0.5 left-0 h-6 w-6 rounded-full bg-card shadow-sm transition-transform ${n?"translate-x-5":"translate-x-0.5"}`})})]}),e.jsx("datalist",{id:x,children:c.map(h=>e.jsx("option",{value:h},h))}),e.jsx("div",{className:"space-y-4",children:T.map(h=>e.jsxs("label",{className:"block text-sm",children:[e.jsxs("span",{className:"mb-1.5 flex items-baseline justify-between gap-2",children:[e.jsx("span",{className:"font-medium text-fg",children:S[h].title}),e.jsxs("span",{className:"text-xs text-fg-dim",children:["default: #",N[h]]})]}),e.jsx("input",{type:"text",value:u[h],onChange:p=>i(y=>({...y,[h]:p.target.value})),list:x,placeholder:N[h],"aria-label":`${S[h].title} tag role`,spellCheck:!1,autoCapitalize:"none",autoCorrect:"off",className:"input input-on-bg"}),e.jsx("span",{className:"mt-1.5 block text-xs text-fg-dim",children:S[h].help})]},h))}),e.jsxs("div",{className:"flex flex-wrap items-center gap-4 pt-1",children:[e.jsx("button",{type:"button",onClick:f,disabled:!m,className:"btn btn-primary btn-lg",children:"Save"}),e.jsx("button",{type:"button",onClick:g,className:"btn btn-ghost",children:"Reset to defaults"})]})]})}export{Me as Settings};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{bV as o,as as x,b as l,bW as h,j as e,N as c,L as j,H as r,af as f,r as g}from"./index-
|
|
1
|
+
import{bV as o,as as x,b as l,bW as h,j as e,N as c,L as j,H as r,af as f,r as g}from"./index-BwG_4Oup.js";import{ViewCanvas as m}from"./ViewSurface-B3tMmOMq.js";import"./TagSchemaEditor-Bv9OJXDP.js";function v(t,s,a){const i=s!=null&&s.fields?Object.keys(s.fields).length:0,n={tag:t};return t!==a.archived&&(n.exclude_tags=[a.archived]),n.sort="desc",n.limit=o,{noteId:`derived:tag:${t}`,title:t,kind:i>=1?"table":"list",query:n,problems:[]}}function u(){return e.jsx("nav",{className:"mb-6 text-sm text-fg-dim",children:e.jsx(j,{to:"/tags",className:"focus-ring hover:text-accent",children:"← Tags"})})}function y(){const{name:t}=x(),s=l(i=>i.getActiveVault()),a=h(t??null);return s?t?a.isPending?e.jsxs("div",{className:"page",children:[e.jsx(u,{}),e.jsx(b,{})]}):e.jsx(p,{name:t,tag:a.data??null}):e.jsx(c,{to:"/tags",replace:!0}):e.jsx(c,{to:"/",replace:!0})}function p({name:t,tag:s}){const a=l(d=>d.getActiveVault()),{roles:i}=f((a==null?void 0:a.id)??null),n=g.useMemo(()=>v(t,s,i),[t,s,i]);return e.jsx(m,{def:n,backingNote:null,pageSize:o,total:s==null?void 0:s.count,nav:e.jsx(u,{})})}function b(){return e.jsxs("div",{className:"space-y-4","aria-busy":"true",children:[e.jsx(r,{height:32,width:"40%"}),e.jsx(r,{height:20,width:"60%"}),e.jsxs("div",{className:"space-y-2 pt-4",children:[e.jsx(r,{height:56}),e.jsx(r,{height:56}),e.jsx(r,{height:56})]})]})}export{y as TagPage};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{bW as V,cD as _,r as u,j as e,V as K}from"./index-
|
|
1
|
+
import{bW as V,cD as _,r as u,j as e,V as K}from"./index-BwG_4Oup.js";const W=["string","number","boolean","date"];let C=0;function g(){return C+=1,`row-${C}`}function q(s){return s?Object.entries(s).map(([n,l])=>{var i;return{rowId:g(),name:n,type:l.type||"string",values:((i=l.enum)==null?void 0:i.join(", "))??""}}):[]}function z(s){return s==="date"?{rowId:g(),name:"",type:"date"}:{rowId:g(),name:"",type:"string",values:""}}function B({tagName:s,intent:n,onSaved:l,onClose:i}){var I;const a=V(s),d=_(),[j,v]=u.useState(""),[f,x]=u.useState([]),[N,w]=u.useState(""),[k,T]=u.useState(!1),[E,p]=u.useState(null);u.useEffect(()=>{if(k||a.isPending)return;const t=a.data;let r=[];t&&(v(t.description??""),r=q(t.fields),w((t.parent_names??[]).join(", ")));const m=n==="date"?r.some(c=>c.type==="date"):r.length>0;n&&!m&&(r=[...r,z(n)]),x(r),T(!0)},[k,a.isPending,a.data,n]);const h=((I=a.data)==null?void 0:I.fields)??null,D=!M(h,S(f)),b=(t,r)=>{x(m=>m.map(c=>c.rowId===t?{...c,...r}:c))},P=()=>{x(t=>[...t,{rowId:g(),name:"",type:"string"}])},R=t=>{x(r=>r.filter(m=>m.rowId!==t))},A=async()=>{p(null);const t=f.map(o=>({...o,name:o.name.trim()}));if(t.filter(o=>o.name.length===0).length>0){p("Field names can't be blank. Remove the empty row or fill it in.");return}const m=new Set;for(const o of t){if(m.has(o.name)){p(`Duplicate field name "${o.name}". Each field needs a unique key.`);return}m.add(o.name)}const c=t.length>0?S(t):null,$=h!=null&&Object.keys(h).some(o=>!t.find(O=>O.name===o)),F=N.split(",").map(o=>o.trim()).filter(o=>o.length>0),y={description:j.trim()||null,parent_names:F.length>0?F:null};try{$?(await d.mutateAsync({name:s,payload:{...y,fields:null}}),c&&await d.mutateAsync({name:s,payload:{...y,fields:c}})):await d.mutateAsync({name:s,payload:{...y,fields:c}}),l==null||l(c??{}),i()}catch(o){if(o instanceof K){p("Session expired. Reconnect to save.");return}p(o instanceof Error?o.message:"Save failed")}};return e.jsx("dialog",{open:!0,"aria-modal":"true","aria-label":`Edit schema for #${s}`,className:"fixed inset-0 z-50 m-0 h-dvh w-screen max-h-none max-w-none overflow-y-auto bg-black/60 p-4 md:p-8",onKeyDown:t=>{t.key==="Escape"&&(t.preventDefault(),i())},children:e.jsxs("div",{className:"mx-auto max-w-xl rounded-2xl border border-border bg-card p-5 text-fg shadow-lift md:p-6",children:[e.jsxs("header",{className:"mb-4 flex items-baseline justify-between gap-3",children:[e.jsxs("h2",{className:"font-serif text-lg",children:["Schema for ",e.jsxs("span",{className:"font-mono",children:["#",s]})]}),e.jsx("button",{type:"button",onClick:i,className:"text-sm text-fg-muted hover:text-accent","aria-label":"Close schema editor",children:"Close"})]}),a.isPending?e.jsx("p",{className:"text-sm text-fg-dim","aria-busy":"true",children:"Loading schema…"}):a.isError?e.jsxs("p",{role:"alert",className:"text-sm text-red-400",children:["Could not load schema: ",a.error.message]}):e.jsxs(e.Fragment,{children:[e.jsx("p",{className:"mb-4 text-sm text-fg-muted",children:"A meta tag gives every note carrying it a shared shape — fields it can carry, and where it sits in your tag hierarchy."}),n?e.jsx("p",{className:"mb-4 rounded-md border border-accent/30 bg-accent/5 p-3 text-sm text-fg-muted",children:n==="group"?"Name a field to organize by, then give it a set of values — each value becomes a column on your board.":"Name a date field — the calendar plots notes on the day it holds, and lets you drag them between days."}):null,e.jsxs("label",{className:"mb-4 block",children:[e.jsx("span",{className:"mb-1 block text-xs uppercase tracking-wider text-fg-dim",children:"Description"}),e.jsx("input",{type:"text",value:j,onChange:t=>v(t.target.value),placeholder:"What does this tag mean? Who uses it?","aria-label":"Tag description",className:"w-full rounded-lg border border-border bg-bg px-2.5 py-1.5 text-sm text-fg focus:border-accent focus:outline-none"})]}),e.jsxs("fieldset",{className:"mb-4",children:[e.jsx("legend",{className:"mb-2 text-xs uppercase tracking-wider text-fg-dim",children:"Fields"}),e.jsxs("p",{className:"mb-2 text-xs text-fg-dim",children:["Each field is a key and a type — e.g."," ",e.jsx("span",{className:"font-mono",children:"status — string"}),","," ",e.jsx("span",{className:"font-mono",children:"meeting_date — date"}),"."]}),f.length===0?e.jsx("p",{className:"mb-2 text-xs text-fg-dim",children:"No fields declared yet. Add one to give notes carrying this tag a structured shape."}):e.jsx("ul",{className:"mb-2 space-y-2.5","aria-label":"Schema fields",children:f.map(t=>e.jsxs("li",{className:"space-y-1.5",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("input",{type:"text",value:t.name,onChange:r=>b(t.rowId,{name:r.target.value}),placeholder:"field_name","aria-label":"Field name",className:"flex-1 rounded-lg border border-border bg-bg px-2 py-1 font-mono text-xs text-fg focus:border-accent focus:outline-none"}),e.jsx("select",{value:t.type,onChange:r=>b(t.rowId,{type:r.target.value}),"aria-label":`Type for ${t.name||"new field"}`,className:"rounded-lg border border-border bg-bg px-2 py-1 text-xs text-fg focus:border-accent focus:outline-none",children:W.map(r=>e.jsx("option",{value:r,children:r},r))}),e.jsx("button",{type:"button",onClick:()=>R(t.rowId),"aria-label":`Remove field ${t.name||"new"}`,className:"text-fg-dim hover:text-red-400",children:"×"})]}),t.type==="string"?e.jsxs("div",{className:"pl-1",children:[e.jsx("input",{type:"text",value:t.values??"",onChange:r=>b(t.rowId,{values:r.target.value}),placeholder:"e.g. To do, In progress, Done","aria-label":`Values for ${t.name||"new field"}`,className:"w-full rounded-lg border border-border bg-bg px-2 py-1 text-xs text-fg focus:border-accent focus:outline-none"}),e.jsx("p",{className:"mt-1 text-2xs text-fg-dim",children:"Optional — comma-separated values become columns on a board."})]}):null]},t.rowId))}),e.jsx("button",{type:"button",onClick:P,className:"text-xs text-accent hover:text-accent-hover",children:"+ Add field"})]}),e.jsxs("label",{className:"mb-4 block",children:[e.jsx("span",{className:"mb-1 block text-xs uppercase tracking-wider text-fg-dim",children:"Parent tags"}),e.jsx("input",{type:"text",value:N,onChange:t=>w(t.target.value),placeholder:"comma-separated (e.g. project, area)","aria-label":"Parent tags",className:"w-full rounded-lg border border-border bg-bg px-2.5 py-1.5 font-mono text-xs text-fg focus:border-accent focus:outline-none"}),e.jsx("p",{className:"mt-1 text-xs text-fg-dim",children:"Vault treats parents as a hierarchical relationship — children inherit semantics. Comma-separated; leave blank for a top-level tag."})]}),D?e.jsxs("div",{role:"alert",className:"mb-4 rounded-md border border-amber-500/30 bg-amber-500/5 p-3 text-xs text-amber-300",children:[e.jsx("strong",{className:"block font-medium",children:"Heads up."})," Editing this tag's schema doesn't retroactively update notes already tagged with"," ",e.jsxs("span",{className:"font-mono",children:["#",s]}),". The new schema applies to notes you create or update from here on. Existing notes keep their current shape until you edit them."]}):null,E?e.jsx("p",{role:"alert",className:"mb-3 text-sm text-red-400",children:E}):null,e.jsxs("footer",{className:"flex items-center justify-end gap-2",children:[e.jsx("button",{type:"button",onClick:i,className:"rounded-lg border border-border bg-card px-3 py-1.5 text-sm text-fg-muted hover:text-accent",children:"Cancel"}),e.jsx("button",{type:"button",onClick:A,disabled:d.isPending,className:"rounded-lg bg-accent px-4 py-1.5 text-sm font-medium text-(--color-on-accent) hover:bg-accent-hover disabled:opacity-40",children:d.isPending?"Saving…":"Save schema"})]})]})]})})}function L(s){if(!s)return[];const n=new Set,l=[];for(const i of s.split(/[,\n]/)){const a=i.trim();a&&!n.has(a)&&(n.add(a),l.push(a))}return l}function S(s){const n={};for(const l of s){const i=l.name.trim();if(!i)continue;const a={type:l.type};if(l.type==="string"){const d=L(l.values);d.length>0&&(a.enum=d)}n[i]=a}return n}function H(s,n){const l=s??[],i=n??[];return l.length!==i.length?!1:l.every((a,d)=>a===i[d])}function M(s,n){const l=s?Object.keys(s):[],i=n?Object.keys(n):[];if(l.length!==i.length)return!1;for(const a of l)if(!n||!n[a]||s[a].type!==n[a].type||!H(s[a].enum,n[a].enum))return!1;return!0}export{B as T};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{ak as F,r,an as D,V as M,j as e,b as I,bR as V,aL as z,bS as K,bT as U,bU as B,N as H,H as J,J as W,L as P,K as A}from"./index-CkXqzhj_.js";import{T as Z}from"./TagSchemaEditor-D_LYDGRK.js";const O=t=>Object.values(t).reduce((n,g)=>n+g,0);function L({mode:t,sources:n,tagOptions:g,onClose:i,onRun:y,onRunMerge:l,pending:o,offline:c}){const m=F(a=>a.push),d=r.useId(),[p,h]=r.useState(t==="rename"?n[0]??"":""),[f,u]=r.useState(null),[x,v]=r.useState(null),[w,S]=r.useState(!1),b=r.useRef(null);r.useEffect(()=>{var a,s;(a=b.current)==null||a.focus(),(s=b.current)==null||s.select()},[]),r.useEffect(()=>{const a=s=>{s.key==="Escape"&&i()};return window.addEventListener("keydown",a),()=>window.removeEventListener("keydown",a)},[i]);const j=p.trim().replace(/^#/,""),N=!o&&!c&&!w&&j.length>0&&!(t==="rename"&&j===n[0]),T=r.useCallback(async()=>{if(N){u(null),v(null);try{const a=await y(j);if("renamed"in a)m(`Renamed on ${a.renamed} note${a.renamed===1?"":"s"}.`,"success");else{const s=O(a.merged);m(`Merged into #${a.target} on ${s} note${s===1?"":"s"}.`,"success")}i()}catch(a){if(a instanceof D&&t==="rename"&&l){v(a.target);return}a instanceof M?u("Session expired. Reconnect to retry."):u(a instanceof Error?a.message:"Operation failed.")}}},[N,j,t,i,y,l,m]),E=r.useCallback(async()=>{if(!(!x||!l)){u(null),S(!0);try{const a=await l(x),s=O(a.merged);m(`Merged into #${a.target} on ${s} note${s===1?"":"s"}.`,"success"),i()}catch(a){a instanceof M?u("Session expired. Reconnect to retry."):u(a instanceof Error?a.message:"Merge failed."),S(!1)}}},[x,i,l,m]),k=t==="rename"?"Rename tag":`Merge ${n.length} tags`;return e.jsx("dialog",{open:!0,"aria-labelledby":"tag-op-title",className:"fixed inset-0 z-40 m-0 flex h-full max-h-full w-full max-w-full items-center justify-center bg-black/60 p-4",onMouseDown:a=>{a.target===a.currentTarget&&i()},children:e.jsxs("div",{className:"w-full max-w-md rounded-2xl border border-border bg-card p-6 shadow-lift",children:[e.jsx("h2",{id:"tag-op-title",className:"mb-2 font-serif text-xl text-fg",children:k}),e.jsxs("p",{className:"mb-3 text-sm text-fg-muted",children:[t==="rename"?e.jsxs(e.Fragment,{children:["Rename ",e.jsx(C,{children:n[0]})," on every note that carries it. Notes that already have the new tag will end up with one copy."]}):e.jsxs(e.Fragment,{children:["Combine"," ",n.map((a,s)=>e.jsxs("span",{children:[e.jsx(C,{children:a}),s<n.length-1?", ":""]},a))," ","into one tag. The originals are removed."]})," ","Changes apply atomically on the vault."]}),e.jsxs("label",{className:"mb-3 block text-sm",children:[e.jsx("span",{className:"mb-1 block text-fg-muted",children:t==="rename"?"New tag name":"Target tag"}),e.jsx("input",{ref:b,type:"text",value:p,onChange:a=>{h(a.target.value),x&&v(null)},onKeyDown:a=>{a.key==="Enter"&&N&&T()},list:d,"aria-label":t==="rename"?"New tag name":"Merge target tag",spellCheck:!1,autoCapitalize:"none",autoCorrect:"off",className:"w-full rounded-lg border border-border bg-bg/40 px-2.5 py-1.5 font-mono text-sm text-fg focus:border-accent focus:outline-none",autoComplete:"off"}),e.jsx("datalist",{id:d,children:g.map(a=>e.jsx("option",{value:a},a))})]}),c?e.jsx("p",{className:"mb-3 text-sm text-amber-300",children:"Offline — tag operations need a live vault connection."}):null,x?e.jsxs("div",{role:"alert",className:"mb-3 rounded-md border border-amber-500/40 bg-amber-500/5 p-3 text-sm",children:[e.jsxs("p",{className:"mb-2 text-amber-300",children:["A tag named ",e.jsx(C,{children:x})," already exists."]}),e.jsxs("p",{className:"mb-3 text-fg-muted",children:["Merge ",e.jsx(C,{children:n[0]})," into ",e.jsx(C,{children:x})," instead? Notes that carry both end up with one copy."]}),e.jsx("button",{type:"button",onClick:()=>void E(),disabled:w,className:"rounded-lg bg-accent px-3 py-1.5 text-xs font-medium text-(--color-on-accent) hover:bg-accent-hover disabled:opacity-40",children:w?"Merging…":`Merge into #${x}`})]}):null,f?e.jsx("p",{role:"alert",className:"mb-3 text-sm text-red-400",children:f}):null,e.jsxs("div",{className:"flex justify-end gap-2",children:[e.jsx("button",{type:"button",onClick:i,className:"min-h-11 rounded-lg border border-border bg-card px-3 py-1.5 text-sm text-fg-muted hover:text-fg",children:"Cancel"}),e.jsx("button",{type:"button",onClick:()=>void T(),disabled:!N,className:"min-h-11 rounded-lg bg-accent px-4 py-1.5 text-sm font-medium text-(--color-on-accent) hover:bg-accent-hover disabled:opacity-40",children:o?t==="rename"?"Renaming…":"Merging…":t==="rename"?"Rename":"Merge"})]})]})})}function C({children:t}){return e.jsxs("span",{className:"rounded bg-bg/60 px-1 py-0.5 font-mono text-xs text-fg",children:["#",t]})}function te(){const t=I(s=>s.getActiveVault()),n=V(),{isOnline:g}=z(),{isPinned:i,togglePin:y}=K((t==null?void 0:t.id)??null),[l,o]=r.useState(""),[c,m]=r.useState("count"),[d,p]=r.useState(new Set),[h,f]=r.useState(null),[u,x]=r.useState(!1),[v,w]=r.useState(null),S=U(),b=B(),j=r.useMemo(()=>q(n.data??[],l,c),[n.data,l,c]),N=r.useMemo(()=>(n.data??[]).map(s=>s.name),[n.data]),T=s=>{p($=>{const R=new Set($);return R.has(s)?R.delete(s):R.add(s),R})},E=()=>p(new Set);if(!t)return e.jsx(H,{to:"/",replace:!0});const k=d.size,a=!g;return e.jsxs("div",{className:"page",children:[e.jsxs("header",{className:"mb-5 flex flex-wrap items-baseline justify-between gap-x-4 gap-y-3 md:mb-6",children:[e.jsxs("div",{children:[e.jsx("p",{className:"eyebrow",children:t.name}),e.jsx("h1",{className:"page-title",children:"Tags"})]}),e.jsxs("button",{type:"button",onClick:()=>m(s=>s==="count"?"alpha":"count"),className:"focus-ring text-sm text-fg-muted hover:text-accent","aria-label":"Toggle tag sort",children:["Sort: ",c==="count"?"most used":"A–Z"]})]}),e.jsx("input",{type:"search",placeholder:"Filter tags…",value:l,onChange:s=>o(s.target.value),"aria-label":"Filter tags",className:"input mb-6"}),k>0?e.jsxs("div",{className:"mb-6 flex flex-wrap items-center gap-3 rounded-xl border border-accent/30 bg-accent/5 px-4 py-3 text-sm","aria-label":"Tag selection actions",children:[e.jsxs("span",{className:"text-fg-muted",children:[k," selected: ",Array.from(d).join(", ")]}),e.jsx("button",{type:"button",onClick:()=>x(!0),disabled:k<2||a,className:"btn btn-primary btn-sm",children:"Merge into…"}),e.jsx("button",{type:"button",onClick:E,className:"btn btn-ghost btn-sm",children:"Clear"})]}):null,n.isPending?e.jsx(G,{}):n.isError?e.jsx(Q,{error:n.error}):j.length===0?e.jsx(X,{filtering:l.trim().length>0,hasAny:(n.data??[]).length>0}):e.jsx("ul",{className:"card shadow-soft divide-y divide-border rounded-xl","aria-label":"Tag list",children:j.map(s=>e.jsx(_,{tag:s,selected:d.has(s.name),onToggle:()=>T(s.name),onRename:()=>f(s.name),onEditSchema:()=>w(s.name),pinned:i(s.name),onTogglePin:()=>y(s.name),offline:a},s.name))}),n.data&&n.data.length>0?e.jsxs("p",{className:"mt-6 text-xs tabular-nums text-fg-dim",children:[j.length," / ",n.data.length," tag",n.data.length===1?"":"s"]}):null,h!==null?e.jsx(L,{mode:"rename",sources:[h],tagOptions:N,onClose:()=>f(null),pending:S.isPending||b.isPending,offline:a,onRun:s=>S.mutateAsync({oldName:h,newName:s}),onRunMerge:s=>b.mutateAsync({sources:[h],target:s})}):null,u?e.jsx(L,{mode:"merge",sources:Array.from(d),tagOptions:N,onClose:()=>x(!1),pending:b.isPending,offline:a,onRun:async s=>{const $=await b.mutateAsync({sources:Array.from(d),target:s});return E(),$}}):null,v!==null?e.jsx(Z,{tagName:v,onClose:()=>w(null)}):null]})}function _({tag:t,selected:n,onToggle:g,onRename:i,onEditSchema:y,pinned:l,onTogglePin:o,offline:c}){const m=t.fields?Object.keys(t.fields):[],d=t.parent_names??[],p=!!t.description||m.length>0||d.length>0;return e.jsxs("li",{className:"px-4 py-3 text-sm transition-colors hover:bg-bg-soft",children:[e.jsxs("div",{className:"flex flex-wrap items-center gap-3",children:[e.jsx("input",{type:"checkbox",checked:n,onChange:g,"aria-label":`Select tag ${t.name}`,className:"accent-accent"}),e.jsxs(P,{to:`/tags/${encodeURIComponent(t.name)}`,className:"chip chip-tag focus-ring shrink-0 max-w-full break-all",children:[e.jsxs("span",{className:"font-mono",children:["#",t.name]}),e.jsx("span",{className:"tabular-nums opacity-70",children:t.count??0})]}),e.jsxs("div",{className:"-my-3 ml-auto flex shrink-0 items-center gap-4",children:[e.jsx("button",{type:"button",onClick:o,className:l?"focus-ring flex min-h-11 items-center text-xs font-medium text-accent hover:text-accent-hover":"focus-ring flex min-h-11 items-center text-xs text-fg-muted hover:text-accent","aria-label":l?`Unpin tag ${t.name}`:`Pin tag ${t.name}`,"aria-pressed":l,title:l?"Pinned to home strip — click to unpin":"Pin to home strip",children:l?"★ Pinned":"☆ Pin"}),e.jsx("button",{type:"button",onClick:y,disabled:c,className:"focus-ring flex min-h-11 items-center text-xs text-fg-muted hover:text-accent disabled:opacity-40","aria-label":`Edit schema for tag ${t.name}`,children:p?"Schema":"+ Schema"}),e.jsx("button",{type:"button",onClick:i,disabled:c,className:"focus-ring flex min-h-11 items-center text-xs text-fg-muted hover:text-accent disabled:opacity-40","aria-label":`Rename tag ${t.name}`,children:"Rename"})]})]}),p?e.jsxs("dl",{className:"ml-8 mt-2 flex flex-wrap items-baseline gap-x-3 gap-y-1 text-xs text-fg-dim","aria-label":`Schema for ${t.name}`,children:[t.description?e.jsxs("div",{className:"flex w-full items-baseline gap-1.5",children:[e.jsx("dt",{className:"sr-only",children:"Description"}),e.jsx("dd",{className:"italic",children:t.description})]}):null,m.length>0?e.jsxs("div",{className:"flex items-baseline gap-1.5",children:[e.jsx("dt",{className:"uppercase tracking-wider",children:"Fields"}),e.jsx("dd",{className:"font-mono text-fg-muted",children:m.map(h=>{var f,u;return`${h}: ${((u=(f=t.fields)==null?void 0:f[h])==null?void 0:u.type)??"?"}`}).join(", ")})]}):null,d.length>0?e.jsxs("div",{className:"flex items-baseline gap-1.5",children:[e.jsx("dt",{className:"uppercase tracking-wider",children:"Parents"}),e.jsx("dd",{className:"font-mono text-fg-muted",children:d.join(", ")})]}):null]}):null]})}function q(t,n,g){const i=n.trim().toLowerCase(),l=[...i?t.filter(o=>o.name.toLowerCase().includes(i)):t];return g==="alpha"?l.sort((o,c)=>o.name.localeCompare(c.name)):l.sort((o,c)=>(c.count??0)-(o.count??0)||o.name.localeCompare(c.name)),l}function G(){return e.jsx("div",{className:"space-y-2","aria-busy":"true",children:[0,1,2,3,4].map(t=>e.jsx(J,{className:"h-12 rounded-xl"},t))})}function Q({error:t}){const n=t instanceof M;return e.jsx(W,{title:n?"Session expired":"Could not load tags",message:t.message,action:n?e.jsx(P,{to:"/add",className:"btn btn-primary",children:"Reconnect vault"}):void 0})}function X({filtering:t,hasAny:n}){return t&&n?e.jsx(A,{title:"No tags match your filter."}):e.jsx(A,{title:"No tags in this vault yet.",action:e.jsx(P,{to:"/new",className:"btn btn-primary",children:"Create a note"})})}export{te as Tags};
|
|
1
|
+
import{ak as F,r,an as D,V as M,j as e,b as I,bR as V,aL as z,bS as K,bT as U,bU as B,N as H,H as J,J as W,L as P,K as A}from"./index-BwG_4Oup.js";import{T as Z}from"./TagSchemaEditor-Bv9OJXDP.js";const O=t=>Object.values(t).reduce((n,g)=>n+g,0);function L({mode:t,sources:n,tagOptions:g,onClose:i,onRun:y,onRunMerge:l,pending:o,offline:c}){const m=F(a=>a.push),d=r.useId(),[p,h]=r.useState(t==="rename"?n[0]??"":""),[f,u]=r.useState(null),[x,v]=r.useState(null),[w,S]=r.useState(!1),b=r.useRef(null);r.useEffect(()=>{var a,s;(a=b.current)==null||a.focus(),(s=b.current)==null||s.select()},[]),r.useEffect(()=>{const a=s=>{s.key==="Escape"&&i()};return window.addEventListener("keydown",a),()=>window.removeEventListener("keydown",a)},[i]);const j=p.trim().replace(/^#/,""),N=!o&&!c&&!w&&j.length>0&&!(t==="rename"&&j===n[0]),T=r.useCallback(async()=>{if(N){u(null),v(null);try{const a=await y(j);if("renamed"in a)m(`Renamed on ${a.renamed} note${a.renamed===1?"":"s"}.`,"success");else{const s=O(a.merged);m(`Merged into #${a.target} on ${s} note${s===1?"":"s"}.`,"success")}i()}catch(a){if(a instanceof D&&t==="rename"&&l){v(a.target);return}a instanceof M?u("Session expired. Reconnect to retry."):u(a instanceof Error?a.message:"Operation failed.")}}},[N,j,t,i,y,l,m]),E=r.useCallback(async()=>{if(!(!x||!l)){u(null),S(!0);try{const a=await l(x),s=O(a.merged);m(`Merged into #${a.target} on ${s} note${s===1?"":"s"}.`,"success"),i()}catch(a){a instanceof M?u("Session expired. Reconnect to retry."):u(a instanceof Error?a.message:"Merge failed."),S(!1)}}},[x,i,l,m]),k=t==="rename"?"Rename tag":`Merge ${n.length} tags`;return e.jsx("dialog",{open:!0,"aria-labelledby":"tag-op-title",className:"fixed inset-0 z-40 m-0 flex h-full max-h-full w-full max-w-full items-center justify-center bg-black/60 p-4",onMouseDown:a=>{a.target===a.currentTarget&&i()},children:e.jsxs("div",{className:"w-full max-w-md rounded-2xl border border-border bg-card p-6 shadow-lift",children:[e.jsx("h2",{id:"tag-op-title",className:"mb-2 font-serif text-xl text-fg",children:k}),e.jsxs("p",{className:"mb-3 text-sm text-fg-muted",children:[t==="rename"?e.jsxs(e.Fragment,{children:["Rename ",e.jsx(C,{children:n[0]})," on every note that carries it. Notes that already have the new tag will end up with one copy."]}):e.jsxs(e.Fragment,{children:["Combine"," ",n.map((a,s)=>e.jsxs("span",{children:[e.jsx(C,{children:a}),s<n.length-1?", ":""]},a))," ","into one tag. The originals are removed."]})," ","Changes apply atomically on the vault."]}),e.jsxs("label",{className:"mb-3 block text-sm",children:[e.jsx("span",{className:"mb-1 block text-fg-muted",children:t==="rename"?"New tag name":"Target tag"}),e.jsx("input",{ref:b,type:"text",value:p,onChange:a=>{h(a.target.value),x&&v(null)},onKeyDown:a=>{a.key==="Enter"&&N&&T()},list:d,"aria-label":t==="rename"?"New tag name":"Merge target tag",spellCheck:!1,autoCapitalize:"none",autoCorrect:"off",className:"w-full rounded-lg border border-border bg-bg/40 px-2.5 py-1.5 font-mono text-sm text-fg focus:border-accent focus:outline-none",autoComplete:"off"}),e.jsx("datalist",{id:d,children:g.map(a=>e.jsx("option",{value:a},a))})]}),c?e.jsx("p",{className:"mb-3 text-sm text-amber-300",children:"Offline — tag operations need a live vault connection."}):null,x?e.jsxs("div",{role:"alert",className:"mb-3 rounded-md border border-amber-500/40 bg-amber-500/5 p-3 text-sm",children:[e.jsxs("p",{className:"mb-2 text-amber-300",children:["A tag named ",e.jsx(C,{children:x})," already exists."]}),e.jsxs("p",{className:"mb-3 text-fg-muted",children:["Merge ",e.jsx(C,{children:n[0]})," into ",e.jsx(C,{children:x})," instead? Notes that carry both end up with one copy."]}),e.jsx("button",{type:"button",onClick:()=>void E(),disabled:w,className:"rounded-lg bg-accent px-3 py-1.5 text-xs font-medium text-(--color-on-accent) hover:bg-accent-hover disabled:opacity-40",children:w?"Merging…":`Merge into #${x}`})]}):null,f?e.jsx("p",{role:"alert",className:"mb-3 text-sm text-red-400",children:f}):null,e.jsxs("div",{className:"flex justify-end gap-2",children:[e.jsx("button",{type:"button",onClick:i,className:"min-h-11 rounded-lg border border-border bg-card px-3 py-1.5 text-sm text-fg-muted hover:text-fg",children:"Cancel"}),e.jsx("button",{type:"button",onClick:()=>void T(),disabled:!N,className:"min-h-11 rounded-lg bg-accent px-4 py-1.5 text-sm font-medium text-(--color-on-accent) hover:bg-accent-hover disabled:opacity-40",children:o?t==="rename"?"Renaming…":"Merging…":t==="rename"?"Rename":"Merge"})]})]})})}function C({children:t}){return e.jsxs("span",{className:"rounded bg-bg/60 px-1 py-0.5 font-mono text-xs text-fg",children:["#",t]})}function te(){const t=I(s=>s.getActiveVault()),n=V(),{isOnline:g}=z(),{isPinned:i,togglePin:y}=K((t==null?void 0:t.id)??null),[l,o]=r.useState(""),[c,m]=r.useState("count"),[d,p]=r.useState(new Set),[h,f]=r.useState(null),[u,x]=r.useState(!1),[v,w]=r.useState(null),S=U(),b=B(),j=r.useMemo(()=>q(n.data??[],l,c),[n.data,l,c]),N=r.useMemo(()=>(n.data??[]).map(s=>s.name),[n.data]),T=s=>{p($=>{const R=new Set($);return R.has(s)?R.delete(s):R.add(s),R})},E=()=>p(new Set);if(!t)return e.jsx(H,{to:"/",replace:!0});const k=d.size,a=!g;return e.jsxs("div",{className:"page",children:[e.jsxs("header",{className:"mb-5 flex flex-wrap items-baseline justify-between gap-x-4 gap-y-3 md:mb-6",children:[e.jsxs("div",{children:[e.jsx("p",{className:"eyebrow",children:t.name}),e.jsx("h1",{className:"page-title",children:"Tags"})]}),e.jsxs("button",{type:"button",onClick:()=>m(s=>s==="count"?"alpha":"count"),className:"focus-ring text-sm text-fg-muted hover:text-accent","aria-label":"Toggle tag sort",children:["Sort: ",c==="count"?"most used":"A–Z"]})]}),e.jsx("input",{type:"search",placeholder:"Filter tags…",value:l,onChange:s=>o(s.target.value),"aria-label":"Filter tags",className:"input mb-6"}),k>0?e.jsxs("div",{className:"mb-6 flex flex-wrap items-center gap-3 rounded-xl border border-accent/30 bg-accent/5 px-4 py-3 text-sm","aria-label":"Tag selection actions",children:[e.jsxs("span",{className:"text-fg-muted",children:[k," selected: ",Array.from(d).join(", ")]}),e.jsx("button",{type:"button",onClick:()=>x(!0),disabled:k<2||a,className:"btn btn-primary btn-sm",children:"Merge into…"}),e.jsx("button",{type:"button",onClick:E,className:"btn btn-ghost btn-sm",children:"Clear"})]}):null,n.isPending?e.jsx(G,{}):n.isError?e.jsx(Q,{error:n.error}):j.length===0?e.jsx(X,{filtering:l.trim().length>0,hasAny:(n.data??[]).length>0}):e.jsx("ul",{className:"card shadow-soft divide-y divide-border rounded-xl","aria-label":"Tag list",children:j.map(s=>e.jsx(_,{tag:s,selected:d.has(s.name),onToggle:()=>T(s.name),onRename:()=>f(s.name),onEditSchema:()=>w(s.name),pinned:i(s.name),onTogglePin:()=>y(s.name),offline:a},s.name))}),n.data&&n.data.length>0?e.jsxs("p",{className:"mt-6 text-xs tabular-nums text-fg-dim",children:[j.length," / ",n.data.length," tag",n.data.length===1?"":"s"]}):null,h!==null?e.jsx(L,{mode:"rename",sources:[h],tagOptions:N,onClose:()=>f(null),pending:S.isPending||b.isPending,offline:a,onRun:s=>S.mutateAsync({oldName:h,newName:s}),onRunMerge:s=>b.mutateAsync({sources:[h],target:s})}):null,u?e.jsx(L,{mode:"merge",sources:Array.from(d),tagOptions:N,onClose:()=>x(!1),pending:b.isPending,offline:a,onRun:async s=>{const $=await b.mutateAsync({sources:Array.from(d),target:s});return E(),$}}):null,v!==null?e.jsx(Z,{tagName:v,onClose:()=>w(null)}):null]})}function _({tag:t,selected:n,onToggle:g,onRename:i,onEditSchema:y,pinned:l,onTogglePin:o,offline:c}){const m=t.fields?Object.keys(t.fields):[],d=t.parent_names??[],p=!!t.description||m.length>0||d.length>0;return e.jsxs("li",{className:"px-4 py-3 text-sm transition-colors hover:bg-bg-soft",children:[e.jsxs("div",{className:"flex flex-wrap items-center gap-3",children:[e.jsx("input",{type:"checkbox",checked:n,onChange:g,"aria-label":`Select tag ${t.name}`,className:"accent-accent"}),e.jsxs(P,{to:`/tags/${encodeURIComponent(t.name)}`,className:"chip chip-tag focus-ring shrink-0 max-w-full break-all",children:[e.jsxs("span",{className:"font-mono",children:["#",t.name]}),e.jsx("span",{className:"tabular-nums opacity-70",children:t.count??0})]}),e.jsxs("div",{className:"-my-3 ml-auto flex shrink-0 items-center gap-4",children:[e.jsx("button",{type:"button",onClick:o,className:l?"focus-ring flex min-h-11 items-center text-xs font-medium text-accent hover:text-accent-hover":"focus-ring flex min-h-11 items-center text-xs text-fg-muted hover:text-accent","aria-label":l?`Unpin tag ${t.name}`:`Pin tag ${t.name}`,"aria-pressed":l,title:l?"Pinned to home strip — click to unpin":"Pin to home strip",children:l?"★ Pinned":"☆ Pin"}),e.jsx("button",{type:"button",onClick:y,disabled:c,className:"focus-ring flex min-h-11 items-center text-xs text-fg-muted hover:text-accent disabled:opacity-40","aria-label":`Edit schema for tag ${t.name}`,children:p?"Schema":"+ Schema"}),e.jsx("button",{type:"button",onClick:i,disabled:c,className:"focus-ring flex min-h-11 items-center text-xs text-fg-muted hover:text-accent disabled:opacity-40","aria-label":`Rename tag ${t.name}`,children:"Rename"})]})]}),p?e.jsxs("dl",{className:"ml-8 mt-2 flex flex-wrap items-baseline gap-x-3 gap-y-1 text-xs text-fg-dim","aria-label":`Schema for ${t.name}`,children:[t.description?e.jsxs("div",{className:"flex w-full items-baseline gap-1.5",children:[e.jsx("dt",{className:"sr-only",children:"Description"}),e.jsx("dd",{className:"italic",children:t.description})]}):null,m.length>0?e.jsxs("div",{className:"flex items-baseline gap-1.5",children:[e.jsx("dt",{className:"uppercase tracking-wider",children:"Fields"}),e.jsx("dd",{className:"font-mono text-fg-muted",children:m.map(h=>{var f,u;return`${h}: ${((u=(f=t.fields)==null?void 0:f[h])==null?void 0:u.type)??"?"}`}).join(", ")})]}):null,d.length>0?e.jsxs("div",{className:"flex items-baseline gap-1.5",children:[e.jsx("dt",{className:"uppercase tracking-wider",children:"Parents"}),e.jsx("dd",{className:"font-mono text-fg-muted",children:d.join(", ")})]}):null]}):null]})}function q(t,n,g){const i=n.trim().toLowerCase(),l=[...i?t.filter(o=>o.name.toLowerCase().includes(i)):t];return g==="alpha"?l.sort((o,c)=>o.name.localeCompare(c.name)):l.sort((o,c)=>(c.count??0)-(o.count??0)||o.name.localeCompare(c.name)),l}function G(){return e.jsx("div",{className:"space-y-2","aria-busy":"true",children:[0,1,2,3,4].map(t=>e.jsx(J,{className:"h-12 rounded-xl"},t))})}function Q({error:t}){const n=t instanceof M;return e.jsx(W,{title:n?"Session expired":"Could not load tags",message:t.message,action:n?e.jsx(P,{to:"/add",className:"btn btn-primary",children:"Reconnect vault"}):void 0})}function X({filtering:t,hasAny:n}){return t&&n?e.jsx(A,{title:"No tags match your filter."}):e.jsx(A,{title:"No tags in this vault yet.",action:e.jsx(P,{to:"/new",className:"btn btn-primary",children:"Create a note"})})}export{te as Tags};
|