@openparachute/notes-ui 0.1.1 → 0.1.4-rc.1

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.
Files changed (28) hide show
  1. package/CHANGELOG.md +80 -0
  2. package/dist/.parachute/info +1 -1
  3. package/dist/CNAME +1 -0
  4. package/dist/assets/{Activity-DCz02G45.js → Activity-D45lyieR.js} +1 -1
  5. package/dist/assets/{AddVault-KGZOIx2j.js → AddVault-CU4XgZVQ.js} +1 -1
  6. package/dist/assets/{Calendar-CgYUCaSZ.js → Calendar-CWAc8XWz.js} +1 -1
  7. package/dist/assets/{Capture-YgzRoZZX.js → Capture-D_hhqLiB.js} +2 -2
  8. package/dist/assets/{NoteEditor-DNYo0bPT.js → NoteEditor-CyY4zLMN.js} +1 -1
  9. package/dist/assets/NoteNew-0NxE4hzz.js +1 -0
  10. package/dist/assets/{NoteRenderer-CWW2zAJs.js → NoteRenderer-CbVbDcm6.js} +1 -1
  11. package/dist/assets/NoteView-COXz1-0X.js +3 -0
  12. package/dist/assets/{OAuthCallback-5pCjuCLO.js → OAuthCallback-CRL1swoB.js} +1 -1
  13. package/dist/assets/{PinArchiveButtons-BO3QwhOp.js → PinArchiveButtons-Co9x5XtS.js} +1 -1
  14. package/dist/assets/{Settings-D8q_-oSw.js → Settings-C04J50qQ.js} +1 -1
  15. package/dist/assets/{Tags-BQjXsHYG.js → Tags-Ci-07E0X.js} +1 -1
  16. package/dist/assets/{Today-BZ5ksWIi.js → Today-BhqaiSa2.js} +1 -1
  17. package/dist/assets/{VaultGraph-mQzbyY3l.js → VaultGraph-DqTqupmq.js} +2 -2
  18. package/dist/assets/{Vaults-EaMq5ivX.js → Vaults-BzOgFkRm.js} +1 -1
  19. package/dist/assets/index-RQd3jtWY.js +62 -0
  20. package/dist/assets/{react-force-graph-2d-CtvMkQ0a.js → react-force-graph-2d-DXfKuqMP.js} +1 -1
  21. package/dist/assets/{useAttachmentUploader-Du2IiCzJ.js → useAttachmentUploader-NEobOH0b.js} +1 -1
  22. package/dist/index.html +1 -1
  23. package/dist/sw.js +1 -1
  24. package/meta.json +2 -2
  25. package/package.json +12 -6
  26. package/dist/assets/NoteNew-BWuLHfJV.js +0 -1
  27. package/dist/assets/NoteView-DR9WYC4s.js +0 -3
  28. package/dist/assets/index-BF1NxtUe.js +0 -62
package/CHANGELOG.md CHANGED
@@ -1,5 +1,85 @@
1
1
  # Changelog — @openparachute/notes-ui
2
2
 
3
+ ## [0.1.3] - 2026-05-23
4
+
5
+ ### Changed
6
+ - `detectMountBase()`'s canonical (meta-tag) path now delegates to
7
+ `@openparachute/app-client`'s `getMountBase()` instead of parsing the
8
+ meta tag locally. The thin wrapper preserves the legacy `/notes`
9
+ fallback and keeps the existing `(pathname?, doc?)` signature so
10
+ existing callers' shapes are unchanged. The local regex fallback
11
+ stays in place for pathname-passing callers (`sw-bootstrap.ts`) —
12
+ app-client's helper intentionally does not read
13
+ `window.location.pathname`, so pathname-based detection remains a
14
+ notes-ui concern until every host injects the meta tag (tracked at
15
+ parachute-app#21, partially shipped in app#25). Closes notes#163.
16
+
17
+ ### Fixed
18
+ - Removed unreachable `|| undefined` branch in `App.tsx`'s
19
+ `<BrowserRouter basename>`. `detectMountBase()` always returns a
20
+ non-empty string, so the fallback was dead (notes#162 nit).
21
+ - Strengthened the SSR/no-window test in `base-url.test.ts` from
22
+ `.toBeDefined()` to `.toBe("/notes")` so the assertion actually
23
+ proves the legacy fallback shape (notes#162 nit).
24
+
25
+ ### Dependencies
26
+ - Bumps `@openparachute/app-client` from `^0.1.0-rc.3` to
27
+ `^0.1.0-rc.4`. app-client rc.4 added the runtime tenancy helpers
28
+ (`getMountBase`, `getTenantId`, `getHubOrigin`, `getVaultUrl`) this
29
+ release consumes (parachute-app#27).
30
+
31
+ ## [0.1.2] - 2026-05-23
32
+
33
+ ### Fixed
34
+ - Service-worker registration now gates on the runtime mount matching
35
+ the build-time vite base. Resolves the OAuth-callback breakage and
36
+ MIME errors that hit operators running notes-ui under parachute-app
37
+ at the canonical `/app/notes/` mount. The previous build auto-
38
+ registered the SW unconditionally at the page's current scope; the
39
+ precache table was built for `/notes/` so workbox served HTML for
40
+ what should have been JS modules and JSON manifests:
41
+
42
+ ```
43
+ Uncaught (in promise) non-precached-url: non-precached-url ::
44
+ [{"url":"/notes/index.html"}]
45
+ Failed to load module script: Expected JavaScript-or-Wasm module,
46
+ got "text/html"
47
+ Manifest: Line: 1, column: 1, Syntax error.
48
+ ```
49
+
50
+ The fix:
51
+ - New `src/lib/sw-bootstrap.ts` exports `shouldRegisterServiceWorker()`
52
+ and `cleanupStaleServiceWorker()`. The gate compares the
53
+ build-time vite base (`import.meta.env.BASE_URL` / `VITE_BASE_PATH`)
54
+ against `detectMountBase()` and only registers when they match.
55
+ - `UpdateBanner` splits the `useRegisterSW` call into an inner
56
+ component that only renders when the gate is open — React hooks
57
+ can't be conditional within a single component, but conditional
58
+ *rendering* is fine.
59
+ - `main.tsx` fires `cleanupStaleServiceWorker()` on boot to
60
+ unregister any `/notes/`-scoped SW left over from a pre-0.1.2
61
+ install when the bundle is now being served at a different mount.
62
+ Operators auto-recover on first page load — no DevTools manual
63
+ cleanup needed.
64
+ - `vite.config.ts` declares `injectRegister: false` explicitly,
65
+ documenting that app code is the only registration path (defensive
66
+ — vite-plugin-pwa v1's default already skips auto-inject when
67
+ `useRegisterSW` is used, but the explicit declaration makes the
68
+ contract grep-able).
69
+ - `meta.json`'s `version` field synced to the package version (was
70
+ stuck at `0.1.0` through 0.1.1). Cosmetic — `meta.json`'s `version`
71
+ is informational; parachute-app reads `package.json` for install
72
+ resolution — but worth keeping accurate.
73
+
74
+ ### Known limitations
75
+ - PWA "Add to Home Screen" install still requires a custom build with
76
+ `VITE_BASE_PATH=/app/<name>` when running under parachute-app at a
77
+ non-default mount. The default bundle targets the daemon-era
78
+ `/notes/` scope for back-compat; in-browser use works at any mount
79
+ from the default bundle (just no installable PWA). A future
80
+ parachute-app manifest-rewrite hook will lift this — tracked
81
+ separately (see 0.1.1 entry below for the original limitation note).
82
+
3
83
  ## [0.1.1] - 2026-05-23
4
84
 
5
85
  - **Fix: runtime mount detection — same built bundle works at any
@@ -2,7 +2,7 @@
2
2
  "name": "parachute-notes",
3
3
  "displayName": "Notes",
4
4
  "tagline": "Web client for your Parachute Vault",
5
- "version": "0.1.1",
5
+ "version": "0.1.4-rc.1",
6
6
  "iconUrl": "/notes/icon.svg",
7
7
  "kind": "frontend"
8
8
  }
package/dist/CNAME ADDED
@@ -0,0 +1 @@
1
+ notes.parachute.computer
@@ -1 +1 @@
1
- import{aa as h,W as g,x as l,r as e,N as f,L as m,z as b,V as y}from"./index-BF1NxtUe.js";const p=1440*60*1e3,j=5e3;function N(n,r=30,s=new Date){const d=s.getTime()-r*p,a=[];for(const t of n){const c=t.path??t.id,o=Date.parse(t.createdAt);if(Number.isFinite(o)&&o>=d&&a.push({id:`${t.id}:created`,noteId:t.id,noteName:c,kind:"created",at:t.createdAt,preview:t.preview,tags:t.tags}),t.updatedAt){const i=Date.parse(t.updatedAt);Number.isFinite(i)&&i>=d&&Number.isFinite(o)&&i-o>j&&a.push({id:`${t.id}:updated`,noteId:t.id,noteName:c,kind:"updated",at:t.updatedAt,preview:t.preview,tags:t.tags})}}return a.sort((t,c)=>Date.parse(c.at)-Date.parse(t.at)),a}const v=["today","yesterday","thisWeek","older"],k={today:"Today",yesterday:"Yesterday",thisWeek:"This week",older:"Older"};function w(n,r=new Date){const s=Date.parse(n);if(!Number.isFinite(s))return null;const d=u(r),a=u(new Date(s)),t=Math.round((d.getTime()-a.getTime())/p);return t<0||t===0?"today":t===1?"yesterday":t<7?"thisWeek":"older"}function u(n){return new Date(n.getFullYear(),n.getMonth(),n.getDate())}function D(n,r=new Date){const s={today:[],yesterday:[],thisWeek:[],older:[]};for(const d of n){const a=w(d.at,r);a&&s[a].push(d)}return s}const x=50;function F(){const n=h(i=>i.getActiveVault()),r=g(),[s,d]=l.useState(x),a=l.useMemo(()=>r.data?N(r.data):[],[r.data]),t=l.useMemo(()=>a.slice(0,s),[a,s]),c=l.useMemo(()=>D(t),[t]),o=a.length-t.length;return n?e.jsxs("div",{className:"mx-auto max-w-3xl px-4 py-6 md:px-6 md:py-10",children:[e.jsxs("header",{className:"mb-5 md:mb-6",children:[e.jsx("p",{className:"text-xs uppercase tracking-wider text-fg-dim",children:"Activity"}),e.jsx("h1",{className:"font-serif text-2xl tracking-tight md:text-3xl",children:"Recent changes"}),e.jsx("p",{className:"mt-1 text-sm text-fg-muted",children:"Last 30 days, newest first. Deletions aren't tracked yet."})]}),r.isPending?e.jsx(T,{}):r.isError?e.jsx(B,{error:r.error}):a.length===0?e.jsx(S,{}):e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"space-y-8",children:v.map(i=>c[i].length>0?e.jsx(E,{title:k[i],events:c[i]},i):null)}),o>0?e.jsx("div",{className:"mt-8 flex justify-center",children:e.jsxs("button",{type:"button",onClick:()=>d(i=>i+x),className:"rounded-md border border-border bg-card px-4 py-2 text-sm text-fg-muted hover:text-accent",children:["Load more (",o," remaining)"]})}):null]})]}):e.jsx(f,{to:"/",replace:!0})}function E({title:n,events:r}){return e.jsxs("section",{children:[e.jsxs("h2",{className:"mb-2 text-xs uppercase tracking-wider text-fg-dim",children:[n," (",r.length,")"]}),e.jsx("ol",{className:"divide-y divide-border rounded-md border border-border bg-card",children:r.map(s=>e.jsx("li",{children:e.jsxs(m,{to:`/n/${encodeURIComponent(s.noteId)}`,className:"block px-4 py-3 hover:bg-bg/60 focus:bg-bg/60 focus:outline-none",children:[e.jsxs("div",{className:"flex items-baseline justify-between gap-4",children:[e.jsxs("div",{className:"flex min-w-0 items-baseline gap-2",children:[e.jsx(A,{kind:s.kind}),e.jsx("span",{className:"truncate font-mono text-sm text-fg",children:s.noteName})]}),e.jsx("span",{className:"shrink-0 text-xs text-fg-dim",children:b(s.at)})]}),s.preview?e.jsx("p",{className:"mt-1 truncate text-sm text-fg-muted",children:s.preview}):null,s.tags&&s.tags.length>0?e.jsx("div",{className:"mt-2 flex flex-wrap gap-1",children:s.tags.map(d=>e.jsxs("span",{className:"rounded-md bg-border/40 px-1.5 py-0.5 text-xs text-fg-dim",children:["#",d]},d))}):null]})},s.id))})]})}function A({kind:n}){return n==="created"?e.jsx("span",{className:"shrink-0 rounded-md bg-accent/10 px-1.5 py-0.5 text-xs text-accent",children:"Created"}):e.jsx("span",{className:"shrink-0 rounded-md bg-border/40 px-1.5 py-0.5 text-xs text-fg-muted",children:"Edited"})}function S(){return e.jsxs("div",{className:"rounded-md border border-border bg-card p-10 text-center",children:[e.jsx("p",{className:"mb-4 text-fg-muted",children:"No activity in the last 30 days."}),e.jsx(m,{to:"/capture",className:"inline-block rounded-md bg-accent px-4 py-2 text-sm font-medium text-white hover:bg-accent-hover",children:"Open capture"})]})}function T(){return e.jsx("div",{className:"space-y-3","aria-busy":"true",children:[0,1,2,3,4].map(n=>e.jsx("div",{className:"h-16 animate-pulse rounded-md bg-border/30"},n))})}function B({error:n}){const r=n instanceof y;return e.jsxs("div",{className:"rounded-md border border-red-500/30 bg-red-500/5 p-6",children:[e.jsx("p",{className:"mb-2 font-medium text-red-400",children:r?"Session expired":"Could not load activity"}),e.jsx("p",{className:"mb-4 text-sm text-fg-muted",children:n.message}),r?e.jsx(m,{to:"/add",className:"inline-block rounded-md bg-accent px-4 py-2 text-sm font-medium text-white hover:bg-accent-hover",children:"Reconnect vault"}):null]})}export{F as Activity};
1
+ import{aa as h,W as g,x as l,r as e,N as f,L as m,z as b,V as y}from"./index-RQd3jtWY.js";const p=1440*60*1e3,j=5e3;function N(n,r=30,s=new Date){const d=s.getTime()-r*p,a=[];for(const t of n){const c=t.path??t.id,o=Date.parse(t.createdAt);if(Number.isFinite(o)&&o>=d&&a.push({id:`${t.id}:created`,noteId:t.id,noteName:c,kind:"created",at:t.createdAt,preview:t.preview,tags:t.tags}),t.updatedAt){const i=Date.parse(t.updatedAt);Number.isFinite(i)&&i>=d&&Number.isFinite(o)&&i-o>j&&a.push({id:`${t.id}:updated`,noteId:t.id,noteName:c,kind:"updated",at:t.updatedAt,preview:t.preview,tags:t.tags})}}return a.sort((t,c)=>Date.parse(c.at)-Date.parse(t.at)),a}const v=["today","yesterday","thisWeek","older"],k={today:"Today",yesterday:"Yesterday",thisWeek:"This week",older:"Older"};function w(n,r=new Date){const s=Date.parse(n);if(!Number.isFinite(s))return null;const d=u(r),a=u(new Date(s)),t=Math.round((d.getTime()-a.getTime())/p);return t<0||t===0?"today":t===1?"yesterday":t<7?"thisWeek":"older"}function u(n){return new Date(n.getFullYear(),n.getMonth(),n.getDate())}function D(n,r=new Date){const s={today:[],yesterday:[],thisWeek:[],older:[]};for(const d of n){const a=w(d.at,r);a&&s[a].push(d)}return s}const x=50;function F(){const n=h(i=>i.getActiveVault()),r=g(),[s,d]=l.useState(x),a=l.useMemo(()=>r.data?N(r.data):[],[r.data]),t=l.useMemo(()=>a.slice(0,s),[a,s]),c=l.useMemo(()=>D(t),[t]),o=a.length-t.length;return n?e.jsxs("div",{className:"mx-auto max-w-3xl px-4 py-6 md:px-6 md:py-10",children:[e.jsxs("header",{className:"mb-5 md:mb-6",children:[e.jsx("p",{className:"text-xs uppercase tracking-wider text-fg-dim",children:"Activity"}),e.jsx("h1",{className:"font-serif text-2xl tracking-tight md:text-3xl",children:"Recent changes"}),e.jsx("p",{className:"mt-1 text-sm text-fg-muted",children:"Last 30 days, newest first. Deletions aren't tracked yet."})]}),r.isPending?e.jsx(T,{}):r.isError?e.jsx(B,{error:r.error}):a.length===0?e.jsx(S,{}):e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"space-y-8",children:v.map(i=>c[i].length>0?e.jsx(E,{title:k[i],events:c[i]},i):null)}),o>0?e.jsx("div",{className:"mt-8 flex justify-center",children:e.jsxs("button",{type:"button",onClick:()=>d(i=>i+x),className:"rounded-md border border-border bg-card px-4 py-2 text-sm text-fg-muted hover:text-accent",children:["Load more (",o," remaining)"]})}):null]})]}):e.jsx(f,{to:"/",replace:!0})}function E({title:n,events:r}){return e.jsxs("section",{children:[e.jsxs("h2",{className:"mb-2 text-xs uppercase tracking-wider text-fg-dim",children:[n," (",r.length,")"]}),e.jsx("ol",{className:"divide-y divide-border rounded-md border border-border bg-card",children:r.map(s=>e.jsx("li",{children:e.jsxs(m,{to:`/n/${encodeURIComponent(s.noteId)}`,className:"block px-4 py-3 hover:bg-bg/60 focus:bg-bg/60 focus:outline-none",children:[e.jsxs("div",{className:"flex items-baseline justify-between gap-4",children:[e.jsxs("div",{className:"flex min-w-0 items-baseline gap-2",children:[e.jsx(A,{kind:s.kind}),e.jsx("span",{className:"truncate font-mono text-sm text-fg",children:s.noteName})]}),e.jsx("span",{className:"shrink-0 text-xs text-fg-dim",children:b(s.at)})]}),s.preview?e.jsx("p",{className:"mt-1 truncate text-sm text-fg-muted",children:s.preview}):null,s.tags&&s.tags.length>0?e.jsx("div",{className:"mt-2 flex flex-wrap gap-1",children:s.tags.map(d=>e.jsxs("span",{className:"rounded-md bg-border/40 px-1.5 py-0.5 text-xs text-fg-dim",children:["#",d]},d))}):null]})},s.id))})]})}function A({kind:n}){return n==="created"?e.jsx("span",{className:"shrink-0 rounded-md bg-accent/10 px-1.5 py-0.5 text-xs text-accent",children:"Created"}):e.jsx("span",{className:"shrink-0 rounded-md bg-border/40 px-1.5 py-0.5 text-xs text-fg-muted",children:"Edited"})}function S(){return e.jsxs("div",{className:"rounded-md border border-border bg-card p-10 text-center",children:[e.jsx("p",{className:"mb-4 text-fg-muted",children:"No activity in the last 30 days."}),e.jsx(m,{to:"/capture",className:"inline-block rounded-md bg-accent px-4 py-2 text-sm font-medium text-white hover:bg-accent-hover",children:"Open capture"})]})}function T(){return e.jsx("div",{className:"space-y-3","aria-busy":"true",children:[0,1,2,3,4].map(n=>e.jsx("div",{className:"h-16 animate-pulse rounded-md bg-border/30"},n))})}function B({error:n}){const r=n instanceof y;return e.jsxs("div",{className:"rounded-md border border-red-500/30 bg-red-500/5 p-6",children:[e.jsx("p",{className:"mb-2 font-medium text-red-400",children:r?"Session expired":"Could not load activity"}),e.jsx("p",{className:"mb-4 text-sm text-fg-muted",children:n.message}),r?e.jsx(m,{to:"/add",className:"inline-block rounded-md bg-accent px-4 py-2 text-sm font-medium text-white hover:bg-accent-hover",children:"Reconnect vault"}):null]})}export{F as Activity};
@@ -1 +1 @@
1
- import{a3 as v,x as t,X as j,r as e,I as y,v as w,j as N,a as S}from"./index-BF1NxtUe.js";function R(){const[b]=v(),u=b.get("url")??"",[a,c]=t.useState(u),[i,l]=t.useState(null),[g,d]=t.useState(!1),[o,m]=t.useState(!1),x=t.useRef(null),h=t.useRef(u.length>0),n=j();t.useEffect(()=>{var s;(s=x.current)==null||s.focus()},[]),t.useEffect(()=>{h.current||n.status==="found"&&n.origin&&a===""&&(c(n.origin),h.current=!0)},[n.status,n.origin,a]);async function p(s){s.preventDefault(),l(null),d(!1);let f;try{f=w(a)}catch(r){l(r.message);return}m(!0);try{const{authorizeUrl:r}=await N(f);window.location.assign(r)}catch(r){r instanceof S?d(!0):l(r.message),m(!1)}}return e.jsxs("div",{className:"mx-auto max-w-xl px-6 py-16",children:[e.jsx("h1",{className:"mb-2 font-serif text-4xl tracking-tight",children:"Connect a vault"}),e.jsx("p",{className:"mb-8 text-fg-muted",children:"Paste your Parachute hub URL. You'll be taken to its consent page to authorize Parachute Notes."}),e.jsxs("form",{onSubmit:p,className:"space-y-4",children:[e.jsxs("div",{children:[e.jsx("label",{htmlFor:"vault-url",className:"mb-1.5 block text-sm font-medium text-fg",children:"Hub URL"}),e.jsx("input",{id:"vault-url",ref:x,type:"url",required:!0,placeholder:"http://localhost:1939",value:a,onChange:s=>c(s.target.value),disabled:o,className:"w-full rounded-md border border-border bg-card px-3 py-2 font-mono text-sm text-fg focus:border-accent focus:outline-none"}),e.jsxs("p",{className:"mt-1.5 text-xs text-fg-dim",children:["For a local install the hub lives at ",e.jsx("code",{children:"http://localhost:1939"}),". A standalone vault URL (e.g. ",e.jsx("code",{children:"https://host/vault/default"}),") also works — Notes will OAuth against whichever issuer answers."]})]}),g?e.jsx(y,{}):null,i?e.jsx("div",{className:"rounded-md border border-red-400/30 bg-red-400/5 px-3 py-2 text-sm text-red-400",children:i}):null,e.jsx("button",{type:"submit",disabled:o||!a,className:"w-full rounded-md bg-accent px-4 py-2.5 text-sm font-medium text-white hover:bg-accent-hover disabled:cursor-not-allowed disabled:opacity-60",children:o?"Starting OAuth…":"Continue"})]})]})}export{R as AddVault};
1
+ import{a3 as v,x as t,X as j,r as e,I as y,v as w,j as N,a as S}from"./index-RQd3jtWY.js";function R(){const[b]=v(),u=b.get("url")??"",[a,c]=t.useState(u),[i,l]=t.useState(null),[g,d]=t.useState(!1),[o,m]=t.useState(!1),x=t.useRef(null),h=t.useRef(u.length>0),n=j();t.useEffect(()=>{var s;(s=x.current)==null||s.focus()},[]),t.useEffect(()=>{h.current||n.status==="found"&&n.origin&&a===""&&(c(n.origin),h.current=!0)},[n.status,n.origin,a]);async function p(s){s.preventDefault(),l(null),d(!1);let f;try{f=w(a)}catch(r){l(r.message);return}m(!0);try{const{authorizeUrl:r}=await N(f);window.location.assign(r)}catch(r){r instanceof S?d(!0):l(r.message),m(!1)}}return e.jsxs("div",{className:"mx-auto max-w-xl px-6 py-16",children:[e.jsx("h1",{className:"mb-2 font-serif text-4xl tracking-tight",children:"Connect a vault"}),e.jsx("p",{className:"mb-8 text-fg-muted",children:"Paste your Parachute hub URL. You'll be taken to its consent page to authorize Parachute Notes."}),e.jsxs("form",{onSubmit:p,className:"space-y-4",children:[e.jsxs("div",{children:[e.jsx("label",{htmlFor:"vault-url",className:"mb-1.5 block text-sm font-medium text-fg",children:"Hub URL"}),e.jsx("input",{id:"vault-url",ref:x,type:"url",required:!0,placeholder:"http://localhost:1939",value:a,onChange:s=>c(s.target.value),disabled:o,className:"w-full rounded-md border border-border bg-card px-3 py-2 font-mono text-sm text-fg focus:border-accent focus:outline-none"}),e.jsxs("p",{className:"mt-1.5 text-xs text-fg-dim",children:["For a local install the hub lives at ",e.jsx("code",{children:"http://localhost:1939"}),". A standalone vault URL (e.g. ",e.jsx("code",{children:"https://host/vault/default"}),") also works — Notes will OAuth against whichever issuer answers."]})]}),g?e.jsx(y,{}):null,i?e.jsx("div",{className:"rounded-md border border-red-400/30 bg-red-400/5 px-3 py-2 text-sm text-red-400",children:i}):null,e.jsx("button",{type:"submit",disabled:o||!a,className:"w-full rounded-md bg-accent px-4 py-2.5 text-sm font-medium text-white hover:bg-accent-hover disabled:cursor-not-allowed disabled:opacity-60",children:o?"Starting OAuth…":"Continue"})]})]})}export{R as AddVault};
@@ -1 +1 @@
1
- import{aa as k,a3 as E,W as A,x as y,r as e,N as K,L as d,V as S}from"./index-BF1NxtUe.js";import{d as f,c as j,e as P,m as T,t as V,s as N,p as i,a as C}from"./dates-BGZoWpL2.js";const _=["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],x=5;function Y(){const a=k(t=>t.getActiveVault()),[o]=E(),l=o.get("month"),r=f(l)??f(j()),s=A(),h=P(),v=y.useMemo(()=>T(r.year,r.month),[r.year,r.month]),$=y.useMemo(()=>{const t=new Map;if(!s.data)return t;for(const n of s.data){const c=V(n.createdAt);c&&t.set(c,(t.get(c)??0)+1)}return t},[s.data]);if(!a)return e.jsx(K,{to:"/",replace:!0});const u=N(r.year,r.month,-1),p=N(r.year,r.month,1),b=`${u.year}-${i(u.month)}`,g=`${p.year}-${i(p.month)}`,M=j(),w=`${r.year}-${i(r.month)}`===M;return e.jsxs("div",{className:"mx-auto max-w-4xl px-4 py-6 md:px-6 md:py-10",children:[e.jsxs("header",{className:"mb-6 flex flex-wrap items-baseline justify-between gap-3",children:[e.jsxs("div",{children:[e.jsx("p",{className:"text-xs uppercase tracking-wider text-fg-dim",children:"Calendar"}),e.jsx("h1",{className:"font-serif text-3xl tracking-tight",children:C(r.year,r.month)})]}),e.jsxs("div",{className:"flex flex-wrap items-center gap-2 text-sm",children:[e.jsxs(d,{to:`/calendar?month=${b}`,className:"rounded-md border border-border bg-card px-3 py-1.5 text-fg-muted hover:text-accent","aria-label":"Previous month",children:["← ",b]}),w?null:e.jsx(d,{to:"/calendar",className:"rounded-md border border-border bg-card px-3 py-1.5 text-fg-muted hover:text-accent",children:"This month"}),e.jsxs(d,{to:`/calendar?month=${g}`,className:"rounded-md border border-border bg-card px-3 py-1.5 text-fg-muted hover:text-accent","aria-label":"Next month",children:[g," →"]}),e.jsx(d,{to:`/today?date=${h}`,className:"rounded-md border border-border bg-card px-3 py-1.5 text-fg-muted hover:text-accent",children:"Today"})]})]}),s.isError?e.jsx(L,{error:s.error}):e.jsxs("div",{className:"rounded-md border border-border bg-card","aria-busy":s.isPending,children:[e.jsx("div",{className:"grid grid-cols-7 border-b border-border text-xs uppercase tracking-wider text-fg-dim",children:_.map(t=>e.jsx("div",{className:"px-2 py-2 text-center",children:t},t))}),e.jsx("div",{className:"grid grid-cols-7",children:v.map(t=>{const n=`${t.getFullYear()}-${i(t.getMonth()+1)}-${i(t.getDate())}`,c=t.getMonth()+1===r.month,m=$.get(n)??0,D=n===h;return e.jsxs(d,{to:`/today?date=${n}`,className:`flex min-h-20 flex-col border-b border-r border-border p-1.5 text-xs hover:bg-bg/60 focus:bg-bg/60 focus:outline-none ${c?"":"opacity-40"}`,"aria-label":`${n} — ${m} notes`,children:[e.jsx("span",{className:`mb-1 inline-flex h-6 w-6 items-center justify-center rounded-full ${D?"bg-accent text-white":"text-fg"}`,children:t.getDate()}),m>0?e.jsx(F,{count:m}):e.jsx("span",{className:"sr-only",children:"no notes"})]},n)})})]}),e.jsx("p",{className:"mt-3 text-xs text-fg-dim",children:"Each dot is a note created on that day. Click any day to open /today."})]})}function F({count:a}){const o=Math.min(a,x),l=a>x?a-x:0;return e.jsxs("span",{className:"flex flex-wrap items-center gap-0.5",children:[Array.from({length:o}).map((r,s)=>e.jsx("span",{className:"h-1.5 w-1.5 rounded-full bg-accent","aria-hidden":"true"},s)),l>0?e.jsxs("span",{className:"ml-0.5 text-[10px] text-fg-dim",children:["+",l]}):null]})}function L({error:a}){const o=a instanceof S;return e.jsxs("div",{className:"rounded-md border border-red-500/30 bg-red-500/5 p-6",children:[e.jsx("p",{className:"mb-2 font-medium text-red-400",children:o?"Session expired":"Could not load notes"}),e.jsx("p",{className:"mb-4 text-sm text-fg-muted",children:a.message}),o?e.jsx(d,{to:"/add",className:"inline-block rounded-md bg-accent px-4 py-2 text-sm font-medium text-white hover:bg-accent-hover",children:"Reconnect vault"}):null]})}export{Y as Calendar};
1
+ import{aa as k,a3 as E,W as A,x as y,r as e,N as K,L as d,V as S}from"./index-RQd3jtWY.js";import{d as f,c as j,e as P,m as T,t as V,s as N,p as i,a as C}from"./dates-BGZoWpL2.js";const _=["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],x=5;function Y(){const a=k(t=>t.getActiveVault()),[o]=E(),l=o.get("month"),r=f(l)??f(j()),s=A(),h=P(),v=y.useMemo(()=>T(r.year,r.month),[r.year,r.month]),$=y.useMemo(()=>{const t=new Map;if(!s.data)return t;for(const n of s.data){const c=V(n.createdAt);c&&t.set(c,(t.get(c)??0)+1)}return t},[s.data]);if(!a)return e.jsx(K,{to:"/",replace:!0});const u=N(r.year,r.month,-1),p=N(r.year,r.month,1),b=`${u.year}-${i(u.month)}`,g=`${p.year}-${i(p.month)}`,M=j(),w=`${r.year}-${i(r.month)}`===M;return e.jsxs("div",{className:"mx-auto max-w-4xl px-4 py-6 md:px-6 md:py-10",children:[e.jsxs("header",{className:"mb-6 flex flex-wrap items-baseline justify-between gap-3",children:[e.jsxs("div",{children:[e.jsx("p",{className:"text-xs uppercase tracking-wider text-fg-dim",children:"Calendar"}),e.jsx("h1",{className:"font-serif text-3xl tracking-tight",children:C(r.year,r.month)})]}),e.jsxs("div",{className:"flex flex-wrap items-center gap-2 text-sm",children:[e.jsxs(d,{to:`/calendar?month=${b}`,className:"rounded-md border border-border bg-card px-3 py-1.5 text-fg-muted hover:text-accent","aria-label":"Previous month",children:["← ",b]}),w?null:e.jsx(d,{to:"/calendar",className:"rounded-md border border-border bg-card px-3 py-1.5 text-fg-muted hover:text-accent",children:"This month"}),e.jsxs(d,{to:`/calendar?month=${g}`,className:"rounded-md border border-border bg-card px-3 py-1.5 text-fg-muted hover:text-accent","aria-label":"Next month",children:[g," →"]}),e.jsx(d,{to:`/today?date=${h}`,className:"rounded-md border border-border bg-card px-3 py-1.5 text-fg-muted hover:text-accent",children:"Today"})]})]}),s.isError?e.jsx(L,{error:s.error}):e.jsxs("div",{className:"rounded-md border border-border bg-card","aria-busy":s.isPending,children:[e.jsx("div",{className:"grid grid-cols-7 border-b border-border text-xs uppercase tracking-wider text-fg-dim",children:_.map(t=>e.jsx("div",{className:"px-2 py-2 text-center",children:t},t))}),e.jsx("div",{className:"grid grid-cols-7",children:v.map(t=>{const n=`${t.getFullYear()}-${i(t.getMonth()+1)}-${i(t.getDate())}`,c=t.getMonth()+1===r.month,m=$.get(n)??0,D=n===h;return e.jsxs(d,{to:`/today?date=${n}`,className:`flex min-h-20 flex-col border-b border-r border-border p-1.5 text-xs hover:bg-bg/60 focus:bg-bg/60 focus:outline-none ${c?"":"opacity-40"}`,"aria-label":`${n} — ${m} notes`,children:[e.jsx("span",{className:`mb-1 inline-flex h-6 w-6 items-center justify-center rounded-full ${D?"bg-accent text-white":"text-fg"}`,children:t.getDate()}),m>0?e.jsx(F,{count:m}):e.jsx("span",{className:"sr-only",children:"no notes"})]},n)})})]}),e.jsx("p",{className:"mt-3 text-xs text-fg-dim",children:"Each dot is a note created on that day. Click any day to open /today."})]})}function F({count:a}){const o=Math.min(a,x),l=a>x?a-x:0;return e.jsxs("span",{className:"flex flex-wrap items-center gap-0.5",children:[Array.from({length:o}).map((r,s)=>e.jsx("span",{className:"h-1.5 w-1.5 rounded-full bg-accent","aria-hidden":"true"},s)),l>0?e.jsxs("span",{className:"ml-0.5 text-[10px] text-fg-dim",children:["+",l]}):null]})}function L({error:a}){const o=a instanceof S;return e.jsxs("div",{className:"rounded-md border border-red-500/30 bg-red-500/5 p-6",children:[e.jsx("p",{className:"mb-2 font-medium text-red-400",children:o?"Session expired":"Could not load notes"}),e.jsx("p",{className:"mb-4 text-sm text-fg-muted",children:a.message}),o?e.jsx(d,{to:"/add",className:"inline-block rounded-md bg-accent px-4 py-2 text-sm font-medium text-white hover:bg-accent-hover",children:"Reconnect vault"}):null]})}export{Y as Calendar};
@@ -1,4 +1,4 @@
1
- import{aa as xe,a7 as be,a4 as ye,a5 as ve,E as we,x as i,t as Y,n as ke,s as Te,m as S,k as Re,r as a,N as Se,z as je,e as Ne,u as oe,L as Ee}from"./index-BF1NxtUe.js";const Ie=["audio/webm;codecs=opus","audio/mp4","audio/ogg;codecs=opus"];function Ce(r=Ie){if(typeof MediaRecorder>"u")return null;for(const t of r)if(MediaRecorder.isTypeSupported(t))return t;return null}function Me(r){return r.startsWith("audio/webm")?"webm":r.startsWith("audio/mp4")?"m4a":r.startsWith("audio/ogg")?"ogg":r.startsWith("audio/wav")?"wav":"bin"}function Ae(r){const t=r.now??(()=>Date.now()),d=r.MediaRecorderCtor??MediaRecorder,n=new d(r.stream,{mimeType:r.mimeType}),l=[];let s="idle",m=0,A=0;n.ondataavailable=k=>{k.data&&k.data.size>0&&l.push(k.data)};const p=()=>{for(const k of r.stream.getTracks())k.stop()};return{get state(){return s},get mimeType(){return r.mimeType},start(){if(s!=="idle")throw new Error(`Cannot start from ${s}`);n.start(),m=t(),s="recording"},pause(){s==="recording"&&(n.pause(),A+=t()-m,s="paused")},resume(){s==="paused"&&(n.resume(),m=t(),s="recording")},async stop(){if(s==="idle"||s==="stopped")throw new Error(`Cannot stop from ${s}`);s==="recording"&&(A+=t()-m);const k=new Promise(x=>{n.onstop=async()=>{const L=await $e(l);x({data:L,mimeType:r.mimeType,durationMs:A})}});return n.stop(),s="stopped",p(),k},cancel(){if(s==="recording"||s==="paused")try{n.stop()}catch{}s="stopped",l.length=0,p()}}}async function De(r){const t=r;return typeof t.arrayBuffer=="function"?t.arrayBuffer():new Promise((d,n)=>{const l=new FileReader;l.onload=()=>d(l.result),l.onerror=()=>n(l.error??new Error("FileReader error")),l.readAsArrayBuffer(r)})}async function $e(r){if(r.length===0)return new ArrayBuffer(0);const t=await Promise.all(r.map(s=>De(s))),d=t.reduce((s,m)=>s+m.byteLength,0),n=new Uint8Array(d);let l=0;for(const s of t)n.set(new Uint8Array(s),l),l+=s.byteLength;return n.buffer}async function Oe(){var r;if(typeof navigator>"u"||!((r=navigator.mediaDevices)!=null&&r.getUserMedia)){const t=new Error("Microphone is not available in this browser.");throw t.kind="unavailable",t}try{return await navigator.mediaDevices.getUserMedia({audio:!0})}catch(t){const d=new Error(t instanceof Error?t.message:"Microphone permission denied."),n=t instanceof DOMException?t.name:"";throw d.kind=n==="NotFoundError"||n==="OverconstrainedError"?"no-device":"permission-denied",d}}function Le(r,t=new Date){return`memo-${t.toISOString().replace(/[:.]/g,"-").replace(/Z$/,"")}.${Me(r)}`}function se(r=new Date){const t=r.getFullYear(),d=String(r.getMonth()+1).padStart(2,"0"),n=String(r.getDate()).padStart(2,"0"),l=String(r.getHours()).padStart(2,"0"),s=String(r.getMinutes()).padStart(2,"0"),m=String(r.getSeconds()).padStart(2,"0");return`Notes/${t}/${d}-${n}/${l}-${s}-${m}`}const Pe=/(?:^|\s)#([a-zA-Z][\w-]*)/g;function Z(r){const t=new Set;for(const d of r.matchAll(Pe)){const n=oe(d[1]??"");n&&t.add(n)}return[...t]}function G(r){const t=Math.floor(r/1e3),d=Math.floor(t/60),n=t%60;return`${String(d).padStart(2,"0")}:${String(n).padStart(2,"0")}`}function Fe({moreFieldsOpenDefault:r=!1}={}){const t=xe(e=>e.getActiveVault()),d=be(e=>e.push),{db:n,blobStore:l,engine:s}=ye(),{roles:m}=ve((t==null?void 0:t.id)??null),A=we(),[p,k]=i.useState(""),[x,L]=i.useState([]),[ie,F]=i.useState(""),[ce,de]=i.useState(r),D=i.useRef(se()),J=i.useRef(!1),[j,Q]=i.useState(()=>D.current),le=i.useCallback(e=>{J.current=e.trim()!==""&&e!==D.current,Q(e)},[]),[N,ue]=i.useState(""),[c,b]=i.useState({kind:"idle"}),[me,B]=i.useState(0),$=i.useRef(null),[q,X]=i.useState(null),[pe,fe]=i.useState(0),V=i.useRef(null),E=i.useRef(null),W=i.useRef(null),P=i.useRef(!1);i.useEffect(()=>{if(c.kind!=="recording")return;const e=setInterval(()=>B(Date.now()-c.startedAt),250);return()=>clearInterval(e)},[c]),i.useEffect(()=>()=>{E.current&&URL.revokeObjectURL(E.current)},[]),i.useEffect(()=>{var e;(e=W.current)==null||e.focus()},[]);const ge=i.useCallback(async()=>{if(!(c.kind==="recording"||c.kind==="requesting")){b({kind:"requesting"});try{const e=Ce();if(!e){b({kind:"denied",message:"This browser can't record audio in a format we can save."});return}const o=await Oe(),u=Ae({stream:o,mimeType:e});V.current=u,u.start(),B(0),b({kind:"recording",startedAt:Date.now()})}catch(e){const o=e,u=o.kind==="permission-denied"?"Microphone access was denied. Update your browser's site settings to record.":o.kind==="no-device"?"No microphone was found on this device.":o instanceof Error?o.message:"Microphone is not available in this browser.";b({kind:"denied",message:u})}}},[c]),ee=i.useCallback(async()=>{const e=V.current;if(!(!e||c.kind!=="recording"))try{const o=await e.stop();V.current=null;const u=new Blob([o.data],{type:o.mimeType}),y=URL.createObjectURL(u);E.current&&URL.revokeObjectURL(E.current),E.current=y,b({kind:"have-audio",data:o.data,mimeType:o.mimeType,url:y,durationMs:o.durationMs})}catch(o){d(o instanceof Error?`Recording failed: ${o.message}`:"Recording failed.","error"),b({kind:"idle"})}},[c,d]);i.useEffect(()=>{if(c.kind!=="recording")return;const e=()=>{ee()};return window.addEventListener("pointerup",e),window.addEventListener("pointercancel",e),()=>{window.removeEventListener("pointerup",e),window.removeEventListener("pointercancel",e)}},[c,ee]);const _=i.useCallback(()=>{E.current&&(URL.revokeObjectURL(E.current),E.current=null),b({kind:"idle"}),B(0)},[]),te=i.useCallback(()=>{var e;if($.current=null,X(null),k(""),L([]),F(""),!J.current){const o=se();D.current=o,Q(o)}_(),(e=W.current)==null||e.focus()},[_]),U=c.kind==="have-audio",T=p.trim().length>0,H=(T||U)&&c.kind!=="saving",z=i.useCallback(async()=>{if(!H||!n||!t)return;if(U&&!l){d("Sync queue not ready — try again in a moment.","error");return}const e=c.kind==="have-audio"?c:null;P.current=!0,b({kind:"saving"});const o=x.filter(g=>g.length>0),u=Z(p),y=[];T&&y.push(m.captureText),e&&y.push(m.captureVoice);const v=Array.from(new Set([...y,...o,...u].filter(g=>g.length>0))),f=$.current,w=(f==null?void 0:f.localId)??Y(),I=j.trim()||D.current,C=N.trim(),h=C?{summary:C}:void 0;A&&ke(t.id,A);try{if(e){const g=new Date,O=Le(e.mimeType,g),M=Te(),R=T?`${p.trim()}
1
+ import{aa as xe,a7 as be,a4 as ye,a5 as ve,E as we,x as i,t as Y,n as ke,s as Te,m as S,k as Re,r as a,N as Se,z as je,e as Ne,u as oe,L as Ee}from"./index-RQd3jtWY.js";const Ie=["audio/webm;codecs=opus","audio/mp4","audio/ogg;codecs=opus"];function Ce(r=Ie){if(typeof MediaRecorder>"u")return null;for(const t of r)if(MediaRecorder.isTypeSupported(t))return t;return null}function Me(r){return r.startsWith("audio/webm")?"webm":r.startsWith("audio/mp4")?"m4a":r.startsWith("audio/ogg")?"ogg":r.startsWith("audio/wav")?"wav":"bin"}function Ae(r){const t=r.now??(()=>Date.now()),d=r.MediaRecorderCtor??MediaRecorder,n=new d(r.stream,{mimeType:r.mimeType}),l=[];let s="idle",m=0,A=0;n.ondataavailable=k=>{k.data&&k.data.size>0&&l.push(k.data)};const p=()=>{for(const k of r.stream.getTracks())k.stop()};return{get state(){return s},get mimeType(){return r.mimeType},start(){if(s!=="idle")throw new Error(`Cannot start from ${s}`);n.start(),m=t(),s="recording"},pause(){s==="recording"&&(n.pause(),A+=t()-m,s="paused")},resume(){s==="paused"&&(n.resume(),m=t(),s="recording")},async stop(){if(s==="idle"||s==="stopped")throw new Error(`Cannot stop from ${s}`);s==="recording"&&(A+=t()-m);const k=new Promise(x=>{n.onstop=async()=>{const L=await $e(l);x({data:L,mimeType:r.mimeType,durationMs:A})}});return n.stop(),s="stopped",p(),k},cancel(){if(s==="recording"||s==="paused")try{n.stop()}catch{}s="stopped",l.length=0,p()}}}async function De(r){const t=r;return typeof t.arrayBuffer=="function"?t.arrayBuffer():new Promise((d,n)=>{const l=new FileReader;l.onload=()=>d(l.result),l.onerror=()=>n(l.error??new Error("FileReader error")),l.readAsArrayBuffer(r)})}async function $e(r){if(r.length===0)return new ArrayBuffer(0);const t=await Promise.all(r.map(s=>De(s))),d=t.reduce((s,m)=>s+m.byteLength,0),n=new Uint8Array(d);let l=0;for(const s of t)n.set(new Uint8Array(s),l),l+=s.byteLength;return n.buffer}async function Oe(){var r;if(typeof navigator>"u"||!((r=navigator.mediaDevices)!=null&&r.getUserMedia)){const t=new Error("Microphone is not available in this browser.");throw t.kind="unavailable",t}try{return await navigator.mediaDevices.getUserMedia({audio:!0})}catch(t){const d=new Error(t instanceof Error?t.message:"Microphone permission denied."),n=t instanceof DOMException?t.name:"";throw d.kind=n==="NotFoundError"||n==="OverconstrainedError"?"no-device":"permission-denied",d}}function Le(r,t=new Date){return`memo-${t.toISOString().replace(/[:.]/g,"-").replace(/Z$/,"")}.${Me(r)}`}function se(r=new Date){const t=r.getFullYear(),d=String(r.getMonth()+1).padStart(2,"0"),n=String(r.getDate()).padStart(2,"0"),l=String(r.getHours()).padStart(2,"0"),s=String(r.getMinutes()).padStart(2,"0"),m=String(r.getSeconds()).padStart(2,"0");return`Notes/${t}/${d}-${n}/${l}-${s}-${m}`}const Ue=/(?:^|\s)#([a-zA-Z][\w-]*)/g;function Z(r){const t=new Set;for(const d of r.matchAll(Ue)){const n=oe(d[1]??"");n&&t.add(n)}return[...t]}function G(r){const t=Math.floor(r/1e3),d=Math.floor(t/60),n=t%60;return`${String(d).padStart(2,"0")}:${String(n).padStart(2,"0")}`}function Fe({moreFieldsOpenDefault:r=!1}={}){const t=xe(e=>e.getActiveVault()),d=be(e=>e.push),{db:n,blobStore:l,engine:s}=ye(),{roles:m}=ve((t==null?void 0:t.id)??null),A=we(),[p,k]=i.useState(""),[x,L]=i.useState([]),[ie,F]=i.useState(""),[ce,de]=i.useState(r),D=i.useRef(se()),J=i.useRef(!1),[j,Q]=i.useState(()=>D.current),le=i.useCallback(e=>{J.current=e.trim()!==""&&e!==D.current,Q(e)},[]),[N,ue]=i.useState(""),[c,b]=i.useState({kind:"idle"}),[me,B]=i.useState(0),$=i.useRef(null),[q,X]=i.useState(null),[pe,fe]=i.useState(0),V=i.useRef(null),E=i.useRef(null),W=i.useRef(null),U=i.useRef(!1);i.useEffect(()=>{if(c.kind!=="recording")return;const e=setInterval(()=>B(Date.now()-c.startedAt),250);return()=>clearInterval(e)},[c]),i.useEffect(()=>()=>{E.current&&URL.revokeObjectURL(E.current)},[]),i.useEffect(()=>{var e;(e=W.current)==null||e.focus()},[]);const ge=i.useCallback(async()=>{if(!(c.kind==="recording"||c.kind==="requesting")){b({kind:"requesting"});try{const e=Ce();if(!e){b({kind:"denied",message:"This browser can't record audio in a format we can save."});return}const o=await Oe(),u=Ae({stream:o,mimeType:e});V.current=u,u.start(),B(0),b({kind:"recording",startedAt:Date.now()})}catch(e){const o=e,u=o.kind==="permission-denied"?"Microphone access was denied. Update your browser's site settings to record.":o.kind==="no-device"?"No microphone was found on this device.":o instanceof Error?o.message:"Microphone is not available in this browser.";b({kind:"denied",message:u})}}},[c]),ee=i.useCallback(async()=>{const e=V.current;if(!(!e||c.kind!=="recording"))try{const o=await e.stop();V.current=null;const u=new Blob([o.data],{type:o.mimeType}),y=URL.createObjectURL(u);E.current&&URL.revokeObjectURL(E.current),E.current=y,b({kind:"have-audio",data:o.data,mimeType:o.mimeType,url:y,durationMs:o.durationMs})}catch(o){d(o instanceof Error?`Recording failed: ${o.message}`:"Recording failed.","error"),b({kind:"idle"})}},[c,d]);i.useEffect(()=>{if(c.kind!=="recording")return;const e=()=>{ee()};return window.addEventListener("pointerup",e),window.addEventListener("pointercancel",e),()=>{window.removeEventListener("pointerup",e),window.removeEventListener("pointercancel",e)}},[c,ee]);const _=i.useCallback(()=>{E.current&&(URL.revokeObjectURL(E.current),E.current=null),b({kind:"idle"}),B(0)},[]),te=i.useCallback(()=>{var e;if($.current=null,X(null),k(""),L([]),F(""),!J.current){const o=se();D.current=o,Q(o)}_(),(e=W.current)==null||e.focus()},[_]),P=c.kind==="have-audio",T=p.trim().length>0,H=(T||P)&&c.kind!=="saving",z=i.useCallback(async()=>{if(!H||!n||!t)return;if(P&&!l){d("Sync queue not ready — try again in a moment.","error");return}const e=c.kind==="have-audio"?c:null;U.current=!0,b({kind:"saving"});const o=x.filter(g=>g.length>0),u=Z(p),y=[];T&&y.push(m.captureText),e&&y.push(m.captureVoice);const v=Array.from(new Set([...y,...o,...u].filter(g=>g.length>0))),f=$.current,w=(f==null?void 0:f.localId)??Y(),I=j.trim()||D.current,C=N.trim(),h=C?{summary:C}:void 0;A&&ke(t.id,A);try{if(e){const g=new Date,O=Le(e.mimeType,g),M=Te(),R=T?`${p.trim()}
2
2
 
3
3
  _Transcript pending._
4
4
 
@@ -6,4 +6,4 @@ _Transcript pending._
6
6
  `:`_Transcript pending._
7
7
 
8
8
  ![[${O}]]
9
- `,ae=I;if(!l)throw new Error("blob store missing");await l.put(M,e.data,e.mimeType,t.id),await S(n,{kind:"create-note",localId:w,payload:{content:R,path:ae,...v.length?{tags:v}:{},...h?{metadata:h}:{}}},{vaultId:t.id}),await S(n,{kind:"upload-attachment",blobId:M,filename:O,mimeType:e.mimeType},{vaultId:t.id}),await S(n,{kind:"link-attachment",noteId:w,pathRef:Re(M),mimeType:e.mimeType,transcribe:!0},{vaultId:t.id})}else f!=null&&f.createCommitted?await S(n,{kind:"update-note",targetId:w,payload:{content:p,path:I,...v.length?{tags:{add:v}}:{},...h?{metadata:h}:{}}},{vaultId:t.id}):await S(n,{kind:"create-note",localId:w,payload:{content:p,path:I,...v.length?{tags:v}:{},...h?{metadata:h}:{}}},{vaultId:t.id});s==null||s.runOnce(),d(e?"Captured — syncing audio.":"Captured.","success"),te(),b({kind:"idle"}),P.current=!1}catch(g){d(g instanceof Error?`Capture failed: ${g.message}`:"Capture failed.","error"),P.current=!1,b(e?{kind:"have-audio",data:e.data,mimeType:e.mimeType,url:e.url,durationMs:e.durationMs}:{kind:"idle"})}},[H,n,t,l,A,c,U,T,x,p,j,N,m.captureText,m.captureVoice,s,d,te]),re=i.useCallback(async()=>{if(!n||!t||c.kind!=="idle"||!T)return;const e=x.filter(h=>h.length>0),o=Z(p),u=Array.from(new Set([m.captureText,...e,...o].filter(h=>h.length>0))),y=j.trim()||D.current,v=N.trim(),f=v?{summary:v}:void 0,w=$.current,I=!w,C=(w==null?void 0:w.localId)??Y();I&&($.current={localId:C,createCommitted:!0});try{I?await S(n,{kind:"create-note",localId:C,payload:{content:p,path:y,...u.length?{tags:u}:{},...f?{metadata:f}:{}}},{vaultId:t.id}):await S(n,{kind:"update-note",targetId:C,payload:{content:p,path:y,...u.length?{tags:{add:u}}:{},...f?{metadata:f}:{}}},{vaultId:t.id}),s==null||s.runOnce(),X(Date.now())}catch{I&&($.current=null)}},[n,t,c.kind,T,p,x,j,N,m.captureText,s]),he=i.useCallback(e=>{(e.metaKey||e.ctrlKey)&&e.key==="Enter"&&(e.preventDefault(),z())},[z]),ne=i.useRef({db:n,activeVaultId:(t==null?void 0:t.id)??null,content:p,tags:x,pathOverride:j,summary:N,roles:m});return ne.current={db:n,activeVaultId:(t==null?void 0:t.id)??null,content:p,tags:x,pathOverride:j,summary:N,roles:m},i.useEffect(()=>()=>{if(P.current)return;const{db:e,activeVaultId:o,content:u,tags:y,pathOverride:v,summary:f,roles:w}=ne.current;if(!u.trim()||!e||!o)return;const C=y.filter(K=>K.length>0),h=Z(u),g=Array.from(new Set([w.captureText,...C,...h].filter(K=>K.length>0))),O=v.trim()||D.current,M=f.trim(),R=$.current;(R!=null&&R.createCommitted?S(e,{kind:"update-note",targetId:R.localId,payload:{content:u,path:O,...g.length?{tags:{add:g}}:{},...M?{metadata:{summary:M}}:{}}},{vaultId:o}):S(e,{kind:"create-note",localId:(R==null?void 0:R.localId)??Y(),payload:{content:u,path:O,...g.length?{tags:g}:{},...M?{metadata:{summary:M}}:{}}},{vaultId:o})).catch(()=>{})},[]),i.useEffect(()=>{if(q===null)return;const e=setInterval(()=>{fe(o=>o+1)},15e3);return()=>clearInterval(e)},[q]),i.useEffect(()=>{if(c.kind==="recording"||c.kind==="requesting"||c.kind==="saving"||c.kind==="have-audio"||!T)return;const e=setTimeout(()=>{P.current||re()},5e3);return()=>clearTimeout(e)},[c.kind,T,p,x,j,N,re]),t?a.jsxs("div",{className:"mx-auto max-w-2xl px-4 py-5 md:px-6 md:py-8",children:[a.jsxs("header",{className:"mb-5",children:[a.jsx("h1",{className:"font-serif text-2xl text-fg md:text-3xl",children:"Capture"}),a.jsxs("p",{className:"mt-1 text-xs text-fg-dim",children:["Type a thought, hold the mic to record, or both."," ",a.jsx("kbd",{className:"rounded bg-bg/60 px-1",children:"⌘"}),a.jsx("kbd",{className:"rounded bg-bg/60 px-1",children:"↵"})," to send."]})]}),a.jsxs("section",{className:"flex flex-col gap-4 rounded-xl border border-border bg-card p-5 md:p-6",children:[a.jsx("textarea",{ref:W,value:p,onChange:e=>k(e.target.value),onKeyDown:he,placeholder:"What are you thinking?","aria-label":"Capture content",rows:8,disabled:c.kind==="saving",className:"min-h-[30vh] w-full resize-y rounded-md border border-border bg-bg px-3 py-2 text-sm text-fg placeholder:text-fg-dim focus:border-accent focus:outline-none disabled:opacity-60"}),q!==null?a.jsxs("p",{className:"-mt-2 text-right text-[11px] text-fg-dim","aria-live":"polite","data-indicator-tick":pe,children:["Draft saved · ",je(new Date(q).toISOString())]}):null,c.kind==="have-audio"?a.jsxs("div",{className:"flex flex-col gap-2 rounded-md border border-accent/30 bg-accent/5 p-3",children:[a.jsxs("div",{className:"flex items-center justify-between gap-3",children:[a.jsxs("span",{className:"text-sm text-fg-muted",children:["🎙 Recorded ",G(c.durationMs)]}),a.jsx("button",{type:"button",onClick:_,className:"text-xs text-fg-dim hover:text-red-400",children:"Discard"})]}),a.jsx("audio",{controls:!0,src:c.url,className:"w-full",children:a.jsx("track",{kind:"captions"})}),a.jsx("p",{className:"text-xs text-fg-dim",children:"Transcript will be appended once your vault processes it."})]}):null,c.kind==="denied"?a.jsx("p",{className:"rounded-md border border-red-500/30 bg-red-500/5 px-3 py-2 text-xs text-red-400",children:c.message}):null,a.jsx(Ne,{tags:x,input:ie,onInputChange:F,onAdd:e=>{const o=oe(e);!o||x.includes(o)||(L(u=>[...u,o]),F(""))},onRemove:e=>L(o=>o.filter(u=>u!==e))}),a.jsxs("details",{className:"group rounded-md border border-border bg-bg/50",open:ce,onToggle:e=>de(e.currentTarget.open),children:[a.jsx("summary",{className:"cursor-pointer select-none px-3 py-2 text-xs text-fg-muted hover:text-accent",children:"More fields"}),a.jsxs("div",{className:"space-y-3 px-3 pb-3 pt-1",children:[a.jsxs("label",{className:"flex flex-col gap-1 text-xs",children:[a.jsx("span",{className:"text-fg-dim",children:"Path"}),a.jsx("input",{type:"text",value:j,onChange:e=>le(e.target.value),placeholder:"(blank → uses generated path)","aria-label":"Path override",className:"rounded-md border border-border bg-card px-2.5 py-1.5 font-mono text-xs text-fg focus:border-accent focus:outline-none"})]}),a.jsxs("label",{className:"flex flex-col gap-1 text-xs",children:[a.jsx("span",{className:"text-fg-dim",children:"Summary"}),a.jsx("input",{type:"text",value:N,onChange:e=>ue(e.target.value),placeholder:"(optional one-line description)","aria-label":"Summary",className:"rounded-md border border-border bg-card px-2.5 py-1.5 text-xs text-fg focus:border-accent focus:outline-none"})]}),a.jsxs("p",{className:"text-xs text-fg-dim",children:["Need to attach a file?"," ",a.jsx(Ee,{to:"/new",className:"text-accent hover:underline",children:"Open the full editor"}),"."]})]})]}),a.jsxs("div",{className:"flex items-center justify-between gap-3 pt-2",children:[a.jsx(Ue,{phase:c,elapsedMs:me,onPointerDown:()=>void ge()}),a.jsxs("div",{className:"flex flex-col items-end gap-1",children:[a.jsx("button",{type:"button",onClick:()=>void z(),disabled:!H,className:"min-h-11 rounded-md bg-accent px-4 py-2 text-sm font-medium text-white hover:bg-accent-hover disabled:opacity-40",children:c.kind==="saving"?"Saving…":"Capture"}),a.jsx("span",{className:"text-[11px] text-fg-dim",children:U&&T?"Will save as a note with audio attached.":U?"Will save as a voice memo.":T?"Will save as a text note.":"Type or record to capture."})]})]})]})]}):a.jsx(Se,{to:"/",replace:!0})}function Ue({phase:r,elapsedMs:t,onPointerDown:d}){const n=r.kind==="recording",l=r.kind==="requesting",s=n?`Recording — release to stop (${G(t)})`:l?"Requesting microphone…":"Hold to record";return a.jsxs("button",{type:"button",onPointerDown:m=>{m.preventDefault(),d()},"aria-label":s,"aria-pressed":n,disabled:r.kind==="saving",className:`flex min-h-11 items-center gap-2 rounded-full border px-4 py-2 text-sm font-medium transition select-none ${n?"border-red-500/40 bg-red-500/10 text-red-400":"border-accent/30 bg-accent/10 text-accent hover:bg-accent/15"} disabled:opacity-40`,children:[a.jsx("span",{"aria-hidden":"true",className:n?"animate-pulse":"",children:"🎙"}),a.jsx("span",{children:n?`Rec ${G(t)}`:l?"Requesting…":"Hold to record"})]})}export{Fe as Capture,Z as extractHashtags};
9
+ `,ae=I;if(!l)throw new Error("blob store missing");await l.put(M,e.data,e.mimeType,t.id),await S(n,{kind:"create-note",localId:w,payload:{content:R,path:ae,...v.length?{tags:v}:{},...h?{metadata:h}:{}}},{vaultId:t.id}),await S(n,{kind:"upload-attachment",blobId:M,filename:O,mimeType:e.mimeType},{vaultId:t.id}),await S(n,{kind:"link-attachment",noteId:w,pathRef:Re(M),mimeType:e.mimeType,transcribe:!0},{vaultId:t.id})}else f!=null&&f.createCommitted?await S(n,{kind:"update-note",targetId:w,payload:{content:p,path:I,...v.length?{tags:{add:v}}:{},...h?{metadata:h}:{}}},{vaultId:t.id}):await S(n,{kind:"create-note",localId:w,payload:{content:p,path:I,...v.length?{tags:v}:{},...h?{metadata:h}:{}}},{vaultId:t.id});s==null||s.runOnce(),d(e?"Captured — syncing audio.":"Captured.","success"),te(),b({kind:"idle"}),U.current=!1}catch(g){d(g instanceof Error?`Capture failed: ${g.message}`:"Capture failed.","error"),U.current=!1,b(e?{kind:"have-audio",data:e.data,mimeType:e.mimeType,url:e.url,durationMs:e.durationMs}:{kind:"idle"})}},[H,n,t,l,A,c,P,T,x,p,j,N,m.captureText,m.captureVoice,s,d,te]),re=i.useCallback(async()=>{if(!n||!t||c.kind!=="idle"||!T)return;const e=x.filter(h=>h.length>0),o=Z(p),u=Array.from(new Set([m.captureText,...e,...o].filter(h=>h.length>0))),y=j.trim()||D.current,v=N.trim(),f=v?{summary:v}:void 0,w=$.current,I=!w,C=(w==null?void 0:w.localId)??Y();I&&($.current={localId:C,createCommitted:!0});try{I?await S(n,{kind:"create-note",localId:C,payload:{content:p,path:y,...u.length?{tags:u}:{},...f?{metadata:f}:{}}},{vaultId:t.id}):await S(n,{kind:"update-note",targetId:C,payload:{content:p,path:y,...u.length?{tags:{add:u}}:{},...f?{metadata:f}:{}}},{vaultId:t.id}),s==null||s.runOnce(),X(Date.now())}catch{I&&($.current=null)}},[n,t,c.kind,T,p,x,j,N,m.captureText,s]),he=i.useCallback(e=>{(e.metaKey||e.ctrlKey)&&e.key==="Enter"&&(e.preventDefault(),z())},[z]),ne=i.useRef({db:n,activeVaultId:(t==null?void 0:t.id)??null,content:p,tags:x,pathOverride:j,summary:N,roles:m});return ne.current={db:n,activeVaultId:(t==null?void 0:t.id)??null,content:p,tags:x,pathOverride:j,summary:N,roles:m},i.useEffect(()=>()=>{if(U.current)return;const{db:e,activeVaultId:o,content:u,tags:y,pathOverride:v,summary:f,roles:w}=ne.current;if(!u.trim()||!e||!o)return;const C=y.filter(K=>K.length>0),h=Z(u),g=Array.from(new Set([w.captureText,...C,...h].filter(K=>K.length>0))),O=v.trim()||D.current,M=f.trim(),R=$.current;(R!=null&&R.createCommitted?S(e,{kind:"update-note",targetId:R.localId,payload:{content:u,path:O,...g.length?{tags:{add:g}}:{},...M?{metadata:{summary:M}}:{}}},{vaultId:o}):S(e,{kind:"create-note",localId:(R==null?void 0:R.localId)??Y(),payload:{content:u,path:O,...g.length?{tags:g}:{},...M?{metadata:{summary:M}}:{}}},{vaultId:o})).catch(()=>{})},[]),i.useEffect(()=>{if(q===null)return;const e=setInterval(()=>{fe(o=>o+1)},15e3);return()=>clearInterval(e)},[q]),i.useEffect(()=>{if(c.kind==="recording"||c.kind==="requesting"||c.kind==="saving"||c.kind==="have-audio"||!T)return;const e=setTimeout(()=>{U.current||re()},5e3);return()=>clearTimeout(e)},[c.kind,T,p,x,j,N,re]),t?a.jsxs("div",{className:"mx-auto max-w-2xl px-4 py-5 md:px-6 md:py-8",children:[a.jsxs("header",{className:"mb-5",children:[a.jsx("h1",{className:"font-serif text-2xl text-fg md:text-3xl",children:"Capture"}),a.jsxs("p",{className:"mt-1 text-xs text-fg-dim",children:["Type a thought, hold the mic to record, or both."," ",a.jsx("kbd",{className:"rounded bg-bg/60 px-1",children:"⌘"}),a.jsx("kbd",{className:"rounded bg-bg/60 px-1",children:"↵"})," to send."]})]}),a.jsxs("section",{className:"flex flex-col gap-4 rounded-xl border border-border bg-card p-5 md:p-6",children:[a.jsx("textarea",{ref:W,value:p,onChange:e=>k(e.target.value),onKeyDown:he,placeholder:"What are you thinking?","aria-label":"Capture content",rows:8,disabled:c.kind==="saving",className:"min-h-[30vh] w-full resize-y rounded-md border border-border bg-bg px-3 py-2 text-sm text-fg placeholder:text-fg-dim focus:border-accent focus:outline-none disabled:opacity-60"}),q!==null?a.jsxs("p",{className:"-mt-2 text-right text-[11px] text-fg-dim","aria-live":"polite","data-indicator-tick":pe,children:["Draft saved · ",je(new Date(q).toISOString())]}):null,c.kind==="have-audio"?a.jsxs("div",{className:"flex flex-col gap-2 rounded-md border border-accent/30 bg-accent/5 p-3",children:[a.jsxs("div",{className:"flex items-center justify-between gap-3",children:[a.jsxs("span",{className:"text-sm text-fg-muted",children:["🎙 Recorded ",G(c.durationMs)]}),a.jsx("button",{type:"button",onClick:_,className:"text-xs text-fg-dim hover:text-red-400",children:"Discard"})]}),a.jsx("audio",{controls:!0,src:c.url,className:"w-full",children:a.jsx("track",{kind:"captions"})}),a.jsx("p",{className:"text-xs text-fg-dim",children:"Transcript will be appended once your vault processes it."})]}):null,c.kind==="denied"?a.jsx("p",{className:"rounded-md border border-red-500/30 bg-red-500/5 px-3 py-2 text-xs text-red-400",children:c.message}):null,a.jsx(Ne,{tags:x,input:ie,onInputChange:F,onAdd:e=>{const o=oe(e);!o||x.includes(o)||(L(u=>[...u,o]),F(""))},onRemove:e=>L(o=>o.filter(u=>u!==e))}),a.jsxs("details",{className:"group rounded-md border border-border bg-bg/50",open:ce,onToggle:e=>de(e.currentTarget.open),children:[a.jsx("summary",{className:"cursor-pointer select-none px-3 py-2 text-xs text-fg-muted hover:text-accent",children:"More fields"}),a.jsxs("div",{className:"space-y-3 px-3 pb-3 pt-1",children:[a.jsxs("label",{className:"flex flex-col gap-1 text-xs",children:[a.jsx("span",{className:"text-fg-dim",children:"Title"}),a.jsx("input",{type:"text",value:j,onChange:e=>le(e.target.value),placeholder:"(blank → auto-generated)","aria-label":"Title override",className:"rounded-md border border-border bg-card px-2.5 py-1.5 font-mono text-xs text-fg focus:border-accent focus:outline-none"})]}),a.jsxs("label",{className:"flex flex-col gap-1 text-xs",children:[a.jsx("span",{className:"text-fg-dim",children:"Summary"}),a.jsx("input",{type:"text",value:N,onChange:e=>ue(e.target.value),placeholder:"(optional one-line description)","aria-label":"Summary",className:"rounded-md border border-border bg-card px-2.5 py-1.5 text-xs text-fg focus:border-accent focus:outline-none"})]}),a.jsxs("p",{className:"text-xs text-fg-dim",children:["Need to attach a file?"," ",a.jsx(Ee,{to:"/new",className:"text-accent hover:underline",children:"Open the full editor"}),"."]})]})]}),a.jsxs("div",{className:"flex items-center justify-between gap-3 pt-2",children:[a.jsx(Pe,{phase:c,elapsedMs:me,onPointerDown:()=>void ge()}),a.jsxs("div",{className:"flex flex-col items-end gap-1",children:[a.jsx("button",{type:"button",onClick:()=>void z(),disabled:!H,className:"min-h-11 rounded-md bg-accent px-4 py-2 text-sm font-medium text-white hover:bg-accent-hover disabled:opacity-40",children:c.kind==="saving"?"Saving…":"Capture"}),a.jsx("span",{className:"text-[11px] text-fg-dim",children:P&&T?"Will save as a note with audio attached.":P?"Will save as a voice memo.":T?"Will save as a text note.":"Type or record to capture."})]})]})]})]}):a.jsx(Se,{to:"/",replace:!0})}function Pe({phase:r,elapsedMs:t,onPointerDown:d}){const n=r.kind==="recording",l=r.kind==="requesting",s=n?`Recording — release to stop (${G(t)})`:l?"Requesting microphone…":"Hold to record";return a.jsxs("button",{type:"button",onPointerDown:m=>{m.preventDefault(),d()},"aria-label":s,"aria-pressed":n,disabled:r.kind==="saving",className:`flex min-h-11 items-center gap-2 rounded-full border px-4 py-2 text-sm font-medium transition select-none ${n?"border-red-500/40 bg-red-500/10 text-red-400":"border-accent/30 bg-accent/10 text-accent hover:bg-accent/15"} disabled:opacity-40`,children:[a.jsx("span",{"aria-hidden":"true",className:n?"animate-pulse":"",children:"🎙"}),a.jsx("span",{children:n?`Rec ${G(t)}`:l?"Requesting…":"Hold to record"})]})}export{Fe as Capture,Z as extractHashtags};
@@ -1 +1 @@
1
- import{x as d,r as e,a7 as D,J as V,V as C,g as _,Y as z,aa as O,U as Y,N as K,L as R,Q as W,a8 as q,f as H,z as T,e as J,u as Q}from"./index-BF1NxtUe.js";import{u as Z,A as G,C as X,a as ee,b as te}from"./useAttachmentUploader-Du2IiCzJ.js";import{P as se,D as ne}from"./PinArchiveButtons-BO3QwhOp.js";import{b as re,N as ae}from"./NoteRenderer-CWW2zAJs.js";const oe=250;function de({noteId:t,attachment:n}){const[l,a]=d.useState(!1),o=ce(n);return e.jsxs(e.Fragment,{children:[e.jsx("button",{type:"button",onClick:()=>a(!0),"aria-label":`Remove attachment ${o}`,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:"✕"}),l?e.jsx(ie,{noteId:t,attachment:n,label:o,onClose:()=>a(!1)}):null]})}function ie({noteId:t,attachment:n,label:l,onClose:a}){const o=D(i=>i.push),m=V(),[s,h]=d.useState(!1),[w,p]=d.useState(null),N=d.useRef(null);d.useEffect(()=>{const i=setTimeout(()=>h(!0),oe);return()=>clearTimeout(i)},[]),d.useEffect(()=>{var i;(i=N.current)==null||i.focus()},[]),d.useEffect(()=>{const i=g=>{g.key==="Escape"&&a()};return window.addEventListener("keydown",i),()=>window.removeEventListener("keydown",i)},[a]);const b=d.useCallback(()=>{!s||m.isPending||(p(null),m.mutate({noteId:t,attachmentId:n.id},{onSuccess:()=>{o(`Removed ${l}`,"success"),a()},onError:i=>{if(i instanceof C){p("Session expired. Reconnect to remove attachments.");return}if(i instanceof _){o(`Already removed ${l}`,"info"),a();return}p(i instanceof Error?i.message:"Remove failed")}}))},[s,n.id,l,m,t,a,o]);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:i=>{i.target===i.currentTarget&&a()},children:e.jsxs("div",{className:"w-full max-w-md rounded-md border border-border bg-card p-6 shadow-xl",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:l})," ","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."]}),w?e.jsx("p",{role:"alert",className:"mb-3 text-sm text-red-400",children:w}):null,e.jsxs("div",{className:"flex justify-end gap-2",children:[e.jsx("button",{ref:N,type:"button",onClick:a,className:"min-h-11 rounded-md 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:b,disabled:!s||m.isPending,className:"min-h-11 rounded-md bg-red-500 px-4 py-1.5 text-sm font-medium text-white hover:bg-red-600 disabled:opacity-40",children:m.isPending?"Removing…":"Remove"})]})]})})}function ce(t){if(t.filename)return t.filename;if(t.path){const n=t.path.split("/").pop();return n||t.path}return t.id}function we(){const{id:t}=z(),n=t?decodeURIComponent(t):void 0,l=O(o=>o.getActiveVault()),a=Y(n);return l?e.jsxs("div",{className:"mx-auto max-w-6xl px-4 py-5 md:px-6 md:py-8",children:[e.jsx("nav",{className:"mb-4 text-sm text-fg-dim",children:e.jsx(R,{to:n?`/n/${encodeURIComponent(n)}`:"/",className:"hover:text-accent",children:"← Back to note"})}),a.isPending?e.jsx(xe,{}):a.isError?e.jsx(fe,{error:a.error}):a.data?e.jsx(le,{note:a.data}):e.jsx(he,{id:n??""})]}):e.jsx(K,{to:"/",replace:!0})}function S(t){return{content:t.content??"",path:t.path??"",tags:[...t.tags??[]]}}function le({note:t}){const n=W(),l=D(r=>r.push),a=d.useMemo(()=>re(t),[t]),[o,m]=d.useState(()=>S(t)),[s,h]=d.useState(()=>S(t)),[w,p]=d.useState(""),[N,b]=d.useState(null),[i,g]=d.useState(null),[y,L]=d.useState("edit"),v=q(t.id),k=d.useRef(t),E=d.useRef(null),j=Z({noteId:t.id,onInsert:r=>{E.current?E.current.insertAtCursor(r):h(c=>({...c,content:`${c.content}${r}`}))},onLinked:()=>{l("Attachment added","success")},onError:r=>l(r,"error")});d.useEffect(()=>{k.current=t},[t]);const u=s.content!==o.content||s.path!==o.path||!pe(s.tags,o.tags),A=d.useCallback(()=>{if(!u||v.isPending)return;const r={};s.content!==o.content&&(r.content=s.content),s.path!==o.path&&(r.path=s.path);const c=be(o.tags,s.tags);(c.add.length||c.remove.length)&&(r.tags=c);const f=k.current.updatedAt??k.current.createdAt;f&&(r.if_updated_at=f),g(null),b(null),v.mutate(r,{onSuccess:x=>{m(S(x)),h(S(x)),k.current=x,x.id!==t.id&&n(`/n/${encodeURIComponent(x.id)}/edit`,{replace:!0})},onError:x=>{x instanceof H?b(x):x instanceof C?g("Session expired. Reconnect to save."):g(x instanceof Error?x.message:"Save failed")}})},[o,s,u,v,n,t.id]),U=d.useCallback(()=>{u&&confirm("Discard all edits and revert to last saved version?")&&(h(o),b(null),g(null))},[o,u]),P=d.useCallback(()=>{u&&!confirm("Discard unsaved changes?")||n(`/n/${encodeURIComponent(t.id)}`)},[u,n,t.id]);d.useEffect(()=>{if(!u)return;const r=c=>{c.preventDefault(),c.returnValue=""};return window.addEventListener("beforeunload",r),()=>window.removeEventListener("beforeunload",r)},[u]);const $=s.path!==o.path,B=r=>{const c=Q(r);c&&(s.tags.includes(c)||(h(f=>({...f,tags:[...f.tags,c]})),p("")))},F=r=>{h(c=>({...c,tags:c.tags.filter(f=>f!==r)}))},M=s.content;return e.jsxs("article",{children:[e.jsxs("header",{className:"mb-4 border-b border-border pb-4",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:"text-xs uppercase tracking-wider text-fg-dim",children:"Editing"}),u?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"]}):e.jsxs("span",{className:"text-xs text-fg-dim",children:["saved ",T(t.updatedAt)]})]}),e.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[e.jsx(se,{note:t}),e.jsx(ne,{note:t}),e.jsx("span",{className:"mx-1 h-5 w-px bg-border","aria-hidden":"true"}),e.jsx("button",{type:"button",onClick:U,disabled:!u||v.isPending,className:"min-h-11 rounded-md border border-border bg-card px-3 py-1.5 text-sm text-fg-muted hover:text-accent disabled:opacity-40",children:"Revert"}),e.jsx("button",{type:"button",onClick:P,className:"min-h-11 rounded-md 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:!u||v.isPending,className:"min-h-11 rounded-md bg-accent px-4 py-1.5 text-sm font-medium text-white hover:bg-accent-hover disabled:opacity-40",title:"Save (⌘S)",children:v.isPending?"Saving…":"Save"})]})]}),e.jsxs("div",{className:"mt-3 flex flex-col gap-2",children:[e.jsx(J,{tags:s.tags,input:w,onInputChange:p,onAdd:B,onRemove:F}),e.jsxs("label",{className:"flex items-baseline gap-3 text-sm",children:[e.jsx("span",{className:"shrink-0 text-xs uppercase tracking-wider text-fg-dim",children:"Path"}),e.jsx("input",{type:"text",value:s.path,onChange:r=>h(c=>({...c,path:r.target.value})),className:"flex-1 rounded-md border border-border bg-card px-2.5 py-1 font-mono text-sm text-fg focus:border-accent focus:outline-none","aria-label":"Note path",placeholder:"(no path)"})]}),$?e.jsx("p",{className:"text-xs text-accent",children:"Renaming moves the note — its id may change."}):null]})]}),N?e.jsx(ue,{conflict:N,onReload:()=>{window.location.reload()},onDismiss:()=>b(null)}):null,i?e.jsx("div",{className:"mb-4 rounded-md border border-red-500/30 bg-red-500/5 p-3 text-sm text-red-400",children:i}):null,e.jsx("div",{role:"tablist","aria-label":"Editor view",className:"mb-3 inline-flex rounded-md border border-border bg-card p-0.5 text-sm lg:hidden",children:["edit","preview"].map(r=>e.jsx("button",{type:"button",role:"tab","aria-selected":y===r,onClick:()=>L(r),className:`rounded px-3 py-1.5 capitalize ${y===r?"bg-accent text-white":"text-fg-muted hover:text-accent"}`,children:r},r))}),e.jsxs("div",{className:"grid min-h-[60vh] gap-4 lg:grid-cols-2",children:[e.jsx(G,{onDropFiles:j.start,className:`min-w-0 rounded-md border border-border bg-card ${y==="edit"?"":"hidden lg:block"}`,hint:I,children:e.jsx(X,{ref:E,value:s.content,onChange:r=>h(c=>({...c,content:r})),onSave:A,onCancel:P,onPasteFile:r=>(j.start(r),!0)})}),e.jsx("div",{className:`min-w-0 overflow-auto rounded-md border border-border bg-card p-4 ${y==="preview"?"":"hidden lg:block"}`,children:e.jsx(ae,{note:{path:s.path,content:M},resolve:a})})]}),e.jsx(me,{noteId:t.id,attachments:t.attachments??[],uploads:j.uploads,onPickFiles:j.start,onCancel:j.cancel,onDismiss:j.dismiss})]})}const I=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:"underline",children:"PDF + mp4 coming"})]});function me({noteId:t,attachments:n,uploads:l,onPickFiles:a,onCancel:o,onDismiss:m}){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-lg",children:"Attachments"}),e.jsx(ee,{onPickFiles:a})]}),e.jsxs("p",{className:"mb-3 text-xs text-fg-dim",children:["Drop or paste files into the editor. Max 100 MB each. ",I,"."]}),e.jsx(te,{uploads:l,onCancel:o,onDismiss:m}),n.length>0?e.jsx("ul",{className:"mt-3 space-y-1 text-sm",children:n.map(s=>e.jsxs("li",{className:"flex items-center justify-between gap-2 rounded border border-border bg-card/50 px-3 py-1.5 font-mono text-xs",children:[e.jsx("span",{className:"truncate",title:s.path??s.id,children:s.filename??s.path??s.id}),e.jsxs("div",{className:"flex shrink-0 items-center gap-2",children:[s.mimeType?e.jsx("span",{className:"text-fg-dim",children:s.mimeType}):null,e.jsx(de,{noteId:t,attachment:s})]})]},s.id))}):null]})}function ue({conflict:t,onReload:n,onDismiss:l}){return e.jsxs("div",{className:"mb-4 rounded-md border border-amber-500/40 bg-amber-500/10 p-4",children:[e.jsx("p",{className:"mb-1 font-medium text-amber-500",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 ${T(t.currentUpdatedAt)}.`:""]}),e.jsxs("div",{className:"flex flex-wrap gap-2",children:[e.jsx("button",{type:"button",onClick:n,className:"rounded-md bg-accent px-3 py-1.5 text-sm font-medium text-white hover:bg-accent-hover",children:"Reload latest (discard my edits)"}),e.jsx("button",{type:"button",onClick:l,className:"rounded-md border border-border px-3 py-1.5 text-sm text-fg-muted hover:text-fg",children:"Keep editing"})]})]})}function xe(){return e.jsxs("div",{className:"grid min-h-[60vh] gap-4 lg:grid-cols-2","aria-busy":"true",children:[e.jsx("div",{className:"animate-pulse rounded-md border border-border bg-card"}),e.jsx("div",{className:"animate-pulse rounded-md border border-border bg-card"})]})}function he({id:t}){return e.jsxs("div",{className:"rounded-md border border-border bg-card p-10 text-center",children:[e.jsx("p",{className:"mb-2 font-serif text-xl",children:"Note not found"}),e.jsxs("p",{className:"mb-4 text-sm text-fg-muted",children:["No note with id ",e.jsx("span",{className:"font-mono",children:t})," in this vault."]}),e.jsx(R,{to:"/",className:"text-sm text-accent hover:underline",children:"Back to all notes"})]})}function fe({error:t}){const n=t instanceof C;return e.jsxs("div",{className:"rounded-md border border-red-500/30 bg-red-500/5 p-6",children:[e.jsx("p",{className:"mb-2 font-medium text-red-400",children:n?"Session expired":"Could not load note"}),e.jsx("p",{className:"mb-4 text-sm text-fg-muted",children:t.message}),n?e.jsx(R,{to:"/add",className:"inline-block rounded-md bg-accent px-4 py-2 text-sm font-medium text-white hover:bg-accent-hover",children:"Reconnect vault"}):null]})}function pe(t,n){if(t.length!==n.length)return!1;const l=new Set(t);for(const a of n)if(!l.has(a))return!1;return!0}function be(t,n){const l=new Set(t),a=new Set(n),o=n.filter(s=>!l.has(s)),m=t.filter(s=>!a.has(s));return{add:o,remove:m}}export{we as NoteEditor};
1
+ import{x as d,r as e,a7 as D,J as V,V as C,g as _,Y as z,aa as O,U as Y,N as K,L as R,Q as W,a8 as q,f as H,z as P,e as J,u as Q}from"./index-RQd3jtWY.js";import{u as Z,A as G,C as X,a as ee,b as te}from"./useAttachmentUploader-NEobOH0b.js";import{P as se,D as ne}from"./PinArchiveButtons-Co9x5XtS.js";import{b as re,N as ae}from"./NoteRenderer-CbVbDcm6.js";const oe=250;function de({noteId:t,attachment:n}){const[l,a]=d.useState(!1),o=ce(n);return e.jsxs(e.Fragment,{children:[e.jsx("button",{type:"button",onClick:()=>a(!0),"aria-label":`Remove attachment ${o}`,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:"✕"}),l?e.jsx(ie,{noteId:t,attachment:n,label:o,onClose:()=>a(!1)}):null]})}function ie({noteId:t,attachment:n,label:l,onClose:a}){const o=D(i=>i.push),m=V(),[s,h]=d.useState(!1),[w,p]=d.useState(null),N=d.useRef(null);d.useEffect(()=>{const i=setTimeout(()=>h(!0),oe);return()=>clearTimeout(i)},[]),d.useEffect(()=>{var i;(i=N.current)==null||i.focus()},[]),d.useEffect(()=>{const i=g=>{g.key==="Escape"&&a()};return window.addEventListener("keydown",i),()=>window.removeEventListener("keydown",i)},[a]);const b=d.useCallback(()=>{!s||m.isPending||(p(null),m.mutate({noteId:t,attachmentId:n.id},{onSuccess:()=>{o(`Removed ${l}`,"success"),a()},onError:i=>{if(i instanceof C){p("Session expired. Reconnect to remove attachments.");return}if(i instanceof _){o(`Already removed ${l}`,"info"),a();return}p(i instanceof Error?i.message:"Remove failed")}}))},[s,n.id,l,m,t,a,o]);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:i=>{i.target===i.currentTarget&&a()},children:e.jsxs("div",{className:"w-full max-w-md rounded-md border border-border bg-card p-6 shadow-xl",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:l})," ","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."]}),w?e.jsx("p",{role:"alert",className:"mb-3 text-sm text-red-400",children:w}):null,e.jsxs("div",{className:"flex justify-end gap-2",children:[e.jsx("button",{ref:N,type:"button",onClick:a,className:"min-h-11 rounded-md 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:b,disabled:!s||m.isPending,className:"min-h-11 rounded-md bg-red-500 px-4 py-1.5 text-sm font-medium text-white hover:bg-red-600 disabled:opacity-40",children:m.isPending?"Removing…":"Remove"})]})]})})}function ce(t){if(t.filename)return t.filename;if(t.path){const n=t.path.split("/").pop();return n||t.path}return t.id}function we(){const{id:t}=z(),n=t?decodeURIComponent(t):void 0,l=O(o=>o.getActiveVault()),a=Y(n);return l?e.jsxs("div",{className:"mx-auto max-w-6xl px-4 py-5 md:px-6 md:py-8",children:[e.jsx("nav",{className:"mb-4 text-sm text-fg-dim",children:e.jsx(R,{to:n?`/n/${encodeURIComponent(n)}`:"/",className:"hover:text-accent",children:"← Back to note"})}),a.isPending?e.jsx(xe,{}):a.isError?e.jsx(fe,{error:a.error}):a.data?e.jsx(le,{note:a.data}):e.jsx(he,{id:n??""})]}):e.jsx(K,{to:"/",replace:!0})}function S(t){return{content:t.content??"",path:t.path??"",tags:[...t.tags??[]]}}function le({note:t}){const n=W(),l=D(r=>r.push),a=d.useMemo(()=>re(t),[t]),[o,m]=d.useState(()=>S(t)),[s,h]=d.useState(()=>S(t)),[w,p]=d.useState(""),[N,b]=d.useState(null),[i,g]=d.useState(null),[y,L]=d.useState("edit"),v=q(t.id),k=d.useRef(t),E=d.useRef(null),j=Z({noteId:t.id,onInsert:r=>{E.current?E.current.insertAtCursor(r):h(c=>({...c,content:`${c.content}${r}`}))},onLinked:()=>{l("Attachment added","success")},onError:r=>l(r,"error")});d.useEffect(()=>{k.current=t},[t]);const u=s.content!==o.content||s.path!==o.path||!pe(s.tags,o.tags),A=d.useCallback(()=>{if(!u||v.isPending)return;const r={};s.content!==o.content&&(r.content=s.content),s.path!==o.path&&(r.path=s.path);const c=be(o.tags,s.tags);(c.add.length||c.remove.length)&&(r.tags=c);const f=k.current.updatedAt??k.current.createdAt;f&&(r.if_updated_at=f),g(null),b(null),v.mutate(r,{onSuccess:x=>{m(S(x)),h(S(x)),k.current=x,x.id!==t.id&&n(`/n/${encodeURIComponent(x.id)}/edit`,{replace:!0})},onError:x=>{x instanceof H?b(x):x instanceof C?g("Session expired. Reconnect to save."):g(x instanceof Error?x.message:"Save failed")}})},[o,s,u,v,n,t.id]),U=d.useCallback(()=>{u&&confirm("Discard all edits and revert to last saved version?")&&(h(o),b(null),g(null))},[o,u]),T=d.useCallback(()=>{u&&!confirm("Discard unsaved changes?")||n(`/n/${encodeURIComponent(t.id)}`)},[u,n,t.id]);d.useEffect(()=>{if(!u)return;const r=c=>{c.preventDefault(),c.returnValue=""};return window.addEventListener("beforeunload",r),()=>window.removeEventListener("beforeunload",r)},[u]);const $=s.path!==o.path,B=r=>{const c=Q(r);c&&(s.tags.includes(c)||(h(f=>({...f,tags:[...f.tags,c]})),p("")))},F=r=>{h(c=>({...c,tags:c.tags.filter(f=>f!==r)}))},M=s.content;return e.jsxs("article",{children:[e.jsxs("header",{className:"mb-4 border-b border-border pb-4",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:"text-xs uppercase tracking-wider text-fg-dim",children:"Editing"}),u?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"]}):e.jsxs("span",{className:"text-xs text-fg-dim",children:["saved ",P(t.updatedAt)]})]}),e.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[e.jsx(se,{note:t}),e.jsx(ne,{note:t}),e.jsx("span",{className:"mx-1 h-5 w-px bg-border","aria-hidden":"true"}),e.jsx("button",{type:"button",onClick:U,disabled:!u||v.isPending,className:"min-h-11 rounded-md border border-border bg-card px-3 py-1.5 text-sm text-fg-muted hover:text-accent disabled:opacity-40",children:"Revert"}),e.jsx("button",{type:"button",onClick:T,className:"min-h-11 rounded-md 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:!u||v.isPending,className:"min-h-11 rounded-md bg-accent px-4 py-1.5 text-sm font-medium text-white hover:bg-accent-hover disabled:opacity-40",title:"Save (⌘S)",children:v.isPending?"Saving…":"Save"})]})]}),e.jsxs("div",{className:"mt-3 flex flex-col gap-2",children:[e.jsx(J,{tags:s.tags,input:w,onInputChange:p,onAdd:B,onRemove:F}),e.jsxs("label",{className:"flex items-baseline gap-3 text-sm",children:[e.jsx("span",{className:"shrink-0 text-xs uppercase tracking-wider text-fg-dim",children:"Title"}),e.jsx("input",{type:"text",value:s.path,onChange:r=>h(c=>({...c,path:r.target.value})),className:"flex-1 rounded-md border border-border bg-card px-2.5 py-1 font-mono text-sm text-fg focus:border-accent focus:outline-none","aria-label":"Note path",placeholder:"(no path)"})]}),$?e.jsx("p",{className:"text-xs text-accent",children:"Renaming moves the note — its id may change."}):null]})]}),N?e.jsx(ue,{conflict:N,onReload:()=>{window.location.reload()},onDismiss:()=>b(null)}):null,i?e.jsx("div",{className:"mb-4 rounded-md border border-red-500/30 bg-red-500/5 p-3 text-sm text-red-400",children:i}):null,e.jsx("div",{role:"tablist","aria-label":"Editor view",className:"mb-3 inline-flex rounded-md border border-border bg-card p-0.5 text-sm lg:hidden",children:["edit","preview"].map(r=>e.jsx("button",{type:"button",role:"tab","aria-selected":y===r,onClick:()=>L(r),className:`rounded px-3 py-1.5 capitalize ${y===r?"bg-accent text-white":"text-fg-muted hover:text-accent"}`,children:r},r))}),e.jsxs("div",{className:"grid min-h-[60vh] gap-4 lg:grid-cols-2",children:[e.jsx(G,{onDropFiles:j.start,className:`min-w-0 rounded-md border border-border bg-card ${y==="edit"?"":"hidden lg:block"}`,hint:I,children:e.jsx(X,{ref:E,value:s.content,onChange:r=>h(c=>({...c,content:r})),onSave:A,onCancel:T,onPasteFile:r=>(j.start(r),!0)})}),e.jsx("div",{className:`min-w-0 overflow-auto rounded-md border border-border bg-card p-4 ${y==="preview"?"":"hidden lg:block"}`,children:e.jsx(ae,{note:{path:s.path,content:M},resolve:a})})]}),e.jsx(me,{noteId:t.id,attachments:t.attachments??[],uploads:j.uploads,onPickFiles:j.start,onCancel:j.cancel,onDismiss:j.dismiss})]})}const I=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:"underline",children:"PDF + mp4 coming"})]});function me({noteId:t,attachments:n,uploads:l,onPickFiles:a,onCancel:o,onDismiss:m}){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-lg",children:"Attachments"}),e.jsx(ee,{onPickFiles:a})]}),e.jsxs("p",{className:"mb-3 text-xs text-fg-dim",children:["Drop or paste files into the editor. Max 100 MB each. ",I,"."]}),e.jsx(te,{uploads:l,onCancel:o,onDismiss:m}),n.length>0?e.jsx("ul",{className:"mt-3 space-y-1 text-sm",children:n.map(s=>e.jsxs("li",{className:"flex items-center justify-between gap-2 rounded border border-border bg-card/50 px-3 py-1.5 font-mono text-xs",children:[e.jsx("span",{className:"truncate",title:s.path??s.id,children:s.filename??s.path??s.id}),e.jsxs("div",{className:"flex shrink-0 items-center gap-2",children:[s.mimeType?e.jsx("span",{className:"text-fg-dim",children:s.mimeType}):null,e.jsx(de,{noteId:t,attachment:s})]})]},s.id))}):null]})}function ue({conflict:t,onReload:n,onDismiss:l}){return e.jsxs("div",{className:"mb-4 rounded-md border border-amber-500/40 bg-amber-500/10 p-4",children:[e.jsx("p",{className:"mb-1 font-medium text-amber-500",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 ${P(t.currentUpdatedAt)}.`:""]}),e.jsxs("div",{className:"flex flex-wrap gap-2",children:[e.jsx("button",{type:"button",onClick:n,className:"rounded-md bg-accent px-3 py-1.5 text-sm font-medium text-white hover:bg-accent-hover",children:"Reload latest (discard my edits)"}),e.jsx("button",{type:"button",onClick:l,className:"rounded-md border border-border px-3 py-1.5 text-sm text-fg-muted hover:text-fg",children:"Keep editing"})]})]})}function xe(){return e.jsxs("div",{className:"grid min-h-[60vh] gap-4 lg:grid-cols-2","aria-busy":"true",children:[e.jsx("div",{className:"animate-pulse rounded-md border border-border bg-card"}),e.jsx("div",{className:"animate-pulse rounded-md border border-border bg-card"})]})}function he({id:t}){return e.jsxs("div",{className:"rounded-md border border-border bg-card p-10 text-center",children:[e.jsx("p",{className:"mb-2 font-serif text-xl",children:"Note not found"}),e.jsxs("p",{className:"mb-4 text-sm text-fg-muted",children:["No note with id ",e.jsx("span",{className:"font-mono",children:t})," in this vault."]}),e.jsx(R,{to:"/",className:"text-sm text-accent hover:underline",children:"Back to all notes"})]})}function fe({error:t}){const n=t instanceof C;return e.jsxs("div",{className:"rounded-md border border-red-500/30 bg-red-500/5 p-6",children:[e.jsx("p",{className:"mb-2 font-medium text-red-400",children:n?"Session expired":"Could not load note"}),e.jsx("p",{className:"mb-4 text-sm text-fg-muted",children:t.message}),n?e.jsx(R,{to:"/add",className:"inline-block rounded-md bg-accent px-4 py-2 text-sm font-medium text-white hover:bg-accent-hover",children:"Reconnect vault"}):null]})}function pe(t,n){if(t.length!==n.length)return!1;const l=new Set(t);for(const a of n)if(!l.has(a))return!1;return!0}function be(t,n){const l=new Set(t),a=new Set(n),o=n.filter(s=>!l.has(s)),m=t.filter(s=>!a.has(s));return{add:o,remove:m}}export{we as NoteEditor};
@@ -0,0 +1 @@
1
+ import{aa as T,Q as P,a7 as I,H as R,M as L,x as n,r as e,N as V,V as $,L as F,e as M,u as _}from"./index-RQd3jtWY.js";import{u as U,A as B,C as z,a as H,b as O}from"./useAttachmentUploader-NEobOH0b.js";import{b as Q,N as W}from"./NoteRenderer-CbVbDcm6.js";const Y={content:"",path:"",tags:[],summary:""};function J(){const w=T(t=>t.getActiveVault()),l=P(),d=I(t=>t.push),c=R(),f=L(),[a,o]=n.useState(Y),[C,b]=n.useState(""),[v,x]=n.useState(null),[m,k]=n.useState([]),p=n.useRef(null),i=U({noteId:null,onInsert:t=>{p.current?p.current.insertAtCursor(t):o(s=>({...s,content:`${s.content}${t}`}))},onStaged:t=>k(s=>[...s,t]),onError:t=>d(t,"error")});if(!w)return e.jsx(V,{to:"/",replace:!0});const u=a.content.length>0||a.path.length>0||a.tags.length>0||a.summary.length>0,h=a.content.trim().length>0&&a.path.trim().length>0,j=n.useCallback(()=>{if(!h||c.isPending)return;const t={content:a.content,path:a.path.trim()};a.tags.length&&(t.tags=a.tags);const s=a.summary.trim();s&&(t.metadata={summary:s}),x(null),c.mutate(t,{onSuccess:async r=>{for(const g of m)try{await f.mutateAsync({noteId:r.id,path:g.path,mimeType:g.mimeType})}catch(y){const D=y instanceof Error?y.message:"Link failed";d(`Failed to attach ${g.filename}: ${D}`,"error")}d(`Created ${r.path??r.id}`,"success"),l(`/n/${encodeURIComponent(r.id)}`)},onError:r=>{r instanceof $?x("Session expired. Reconnect to save."):x(r instanceof Error?`${r.message} — if the path is taken, try a different one.`:"Create failed")}})},[a,h,f,c,l,d,m]),N=n.useCallback(()=>{u&&!confirm("Discard this draft?")||l("/")},[u,l]);n.useEffect(()=>{if(!u)return;const t=s=>{s.preventDefault(),s.returnValue=""};return window.addEventListener("beforeunload",t),()=>window.removeEventListener("beforeunload",t)},[u]);const A=t=>{const s=_(t);!s||a.tags.includes(s)||(o(r=>({...r,tags:[...r.tags,s]})),b(""))},E=t=>{o(s=>({...s,tags:s.tags.filter(r=>r!==t)}))},S=Q({id:"__new__",createdAt:new Date().toISOString()});return e.jsxs("div",{className:"mx-auto max-w-6xl px-4 py-5 md:px-6 md:py-8",children:[e.jsx("nav",{className:"mb-4 text-sm text-fg-dim",children:e.jsx(F,{to:"/",className:"hover:text-accent",children:"← All notes"})}),e.jsxs("article",{children:[e.jsxs("header",{className:"mb-4 border-b border-border pb-4",children:[e.jsxs("div",{className:"flex flex-wrap items-center justify-between gap-3",children:[e.jsx("div",{className:"flex items-center gap-2 text-sm",children:e.jsx("span",{className:"text-xs uppercase tracking-wider text-fg-dim",children:"New note"})}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("button",{type:"button",onClick:N,className:"min-h-11 rounded-md 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:j,disabled:!h||c.isPending,className:"min-h-11 rounded-md bg-accent px-4 py-1.5 text-sm font-medium text-white hover:bg-accent-hover disabled:opacity-40",title:"Create (⌘S)",children:c.isPending?"Creating…":"Create"})]})]}),e.jsxs("div",{className:"mt-3 flex flex-col gap-2",children:[e.jsxs("label",{className:"flex items-baseline gap-3 text-sm",children:[e.jsx("span",{className:"shrink-0 text-xs uppercase tracking-wider text-fg-dim",children:"Title"}),e.jsx("input",{type:"text",value:a.path,onChange:t=>o(s=>({...s,path:t.target.value})),className:"flex-1 rounded-md border border-border bg-card px-2.5 py-1 font-mono text-sm text-fg focus:border-accent focus:outline-none","aria-label":"Note path",placeholder:"e.g. Projects/README"})]}),e.jsxs("label",{className:"flex items-baseline gap-3 text-sm",children:[e.jsx("span",{className:"shrink-0 text-xs uppercase tracking-wider text-fg-dim",children:"Summary"}),e.jsx("input",{type:"text",value:a.summary,onChange:t=>o(s=>({...s,summary:t.target.value})),className:"flex-1 rounded-md border border-border bg-card px-2.5 py-1 text-sm text-fg focus:border-accent focus:outline-none","aria-label":"Note summary",placeholder:"(optional one-line description)"})]}),e.jsx(M,{tags:a.tags,input:C,onInputChange:b,onAdd:A,onRemove:E})]})]}),v?e.jsx("div",{role:"alert",className:"mb-4 rounded-md border border-red-500/30 bg-red-500/5 p-3 text-sm text-red-400",children:v}):null,e.jsxs("div",{className:"grid min-h-[60vh] gap-4 lg:grid-cols-2",children:[e.jsx(B,{onDropFiles:i.start,className:"min-w-0 rounded-md border border-border bg-card",hint:"Images, audio, webm video",children:e.jsx(z,{ref:p,value:a.content,onChange:t=>o(s=>({...s,content:t})),onSave:j,onCancel:N,onPasteFile:t=>(i.start(t),!0)})}),e.jsx("div",{className:"min-w-0 overflow-auto rounded-md border border-border bg-card p-4",children:a.content.trim()?e.jsx(W,{note:{path:a.path,content:a.content},resolve:S}):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-lg",children:"Attachments"}),e.jsx(H,{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:"underline",children:"PDF + mp4 coming"}),"."]}),e.jsx(O,{uploads:i.uploads,onCancel:i.cancel,onDismiss:i.dismiss}),m.length>0?e.jsx("ul",{className:"mt-3 space-y-1 text-sm",children:m.map(t=>e.jsxs("li",{className:"flex items-center justify-between gap-2 rounded 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:t.filename}),e.jsx("span",{className:"shrink-0 text-fg-dim",children:"staged"})]},t.path))}):null]})]})]})}export{J as NoteNew};