@openparachute/notes
Advanced tools
+811
| # Changelog | ||
| ## [0.3.17-rc.2] - 2026-05-22 — DEPRECATION RELEASE | ||
| This is the deprecation release. notes-daemon is no longer the recommended way to ship Notes. | ||
| - **DEPRECATED**: see [DEPRECATED.md](./DEPRECATED.md) for migration to parachute-app + @openparachute/notes-ui | ||
| - **No functional changes**: this release ships the same dist/ as 0.3.17-rc.1, just with the deprecation banner + DEPRECATED.md | ||
| - **Hub redirect**: hub#316 adds `/notes/*` → `/app/notes/*` redirect for transparent migration | ||
| Migrate at your own pace. notes-daemon will continue to serve until Phase 3 retirement (~Q3 2026). | ||
| ## [0.3.17-rc.1] - 2026-05-21 | ||
| - **feat(notes): Phase 1 migration — monorepo restructure, dual-publish | ||
| `@openparachute/notes-ui` alongside this package.** The parachute-notes | ||
| repo is now a bun workspace with two publish targets: | ||
| - `@openparachute/notes-ui` (new at `0.1.0-rc.1`) — UI bundle only, | ||
| no daemon, no `.parachute/module.json`. Installed under | ||
| [parachute-app][app] as the canonical first app per the [notes | ||
| migration arc Section 16][s16]. | ||
| - `@openparachute/notes` (this package, bumped to `0.3.17-rc.1`) — | ||
| unchanged daemon shape. Hub continues to install via | ||
| `parachute install notes`; `dist/` continues to land at the same | ||
| resolved path; `.parachute/module.json` continues to declare port | ||
| 1942 + the `/notes` mount. | ||
| Restructure mechanics: | ||
| - All source moves from repo-root `src/`, `scripts/`, `public/`, | ||
| `index.html`, `vite.config.ts`, etc. into `packages/notes-ui/`. | ||
| No source code changes — only path changes. | ||
| - `.parachute/module.json` and the (now lean) CHANGELOG + README | ||
| move into `packages/notes-daemon/`. This package's publish payload | ||
| (`files: ["dist", ".parachute/module.json", "README.md", ...]`) | ||
| is unchanged in shape. | ||
| - `packages/notes-daemon` declares `@openparachute/notes-ui` as a | ||
| workspace devDependency. The build step (`scripts/build.mjs`) | ||
| copies notes-ui's `dist/` into this package's `dist/`. Both | ||
| packages ship byte-identical bundles. | ||
| - Root `package.json` becomes a workspace root (`workspaces: | ||
| ["packages/*"]`); `bun run build` runs notes-ui's build then | ||
| this package's copy step. | ||
| Two new direct deps surface on notes-ui that were previously | ||
| unhoisted transitives: `@lezer/highlight` (used in | ||
| `CodeMirrorEditor.tsx`) and `@types/mdast` (used in remark-wikilinks | ||
| types). The flat-layout was hiding the latent missing-declaration; | ||
| bun's workspace isolated layout surfaced it. Declaring them | ||
| directly is the correct fix regardless of layout. | ||
| Phase 2 (deprecate the daemon form) and Phase 3 (retire the daemon | ||
| + reclaim port 1942) happen in later PRs. This PR is additive. | ||
| [s16]: https://github.com/ParachuteComputer/parachute.computer/blob/main/design/2026-05-21-parachute-apps-design.md#16-notes-migration-to-app | ||
| [app]: https://github.com/ParachuteComputer/parachute-app | ||
| ## [0.3.16-rc.6] - 2026-05-21 | ||
| - **fix(notes): SW update reload + OAuth reconnect 401 clearing (#148).** | ||
| Two blocking bugs Aaron hit while smoke-testing rc.5. Both shipped | ||
| with regression + structural-contract tests. | ||
| - *SW update banner — clicking "Reload" did nothing.* The banner | ||
| relies on `vite-plugin-pwa`'s `useRegisterSW`, which arms its own | ||
| `controlling` listener inside `showSkipWaitingPrompt` to refresh | ||
| the page once the new SW takes over. In real PWAs (especially iOS | ||
| standalone, BFCache restores, and races where the listener gets | ||
| attached after the activation already fired) that event can be | ||
| silently missed and the click visibly does nothing. The banner | ||
| now wires its own `controllerchange` listener via | ||
| `reloadAfterServiceWorkerUpdate` in `src/lib/pwa.ts` **before** | ||
| sending `skipWaiting`, plus a 2.5s fallback `setTimeout` — whichever | ||
| signal lands first forces `window.location.reload()` exactly once. | ||
| Idempotent under double-clicks via a module-level "reload armed" | ||
| guard. Five unit tests pin the controllerchange path, the timeout | ||
| path, the both-fire-once contract, idempotency, and the | ||
| no-serviceWorker-container fallback; the UpdateBanner component | ||
| test pins that the click flow attaches the listener BEFORE asking | ||
| workbox to skipWaiting. | ||
| - *Vault 401 banner — reconnect completes but banner stays.* When | ||
| a vault was added standalone (e.g. `localhost:1940`) and the user | ||
| later reconnects via a hub-fronted issuer, the hub's token catalog | ||
| can resolve the vault to a different URL (`hub.example/vault/default`). | ||
| `addVault` then registers a NEW vault entry under a different id | ||
| via `vaultIdFromUrl`, switches `activeVaultId` to it, and clears | ||
| the halt for the new id — which was never halted in the first | ||
| place. The halt entry on the OLD vault id stayed in `localStorage` | ||
| forever, re-surfacing the banner on the next activeVault switch | ||
| or page reload. Fix: the reconnect button now threads the | ||
| currently-halted vault id through OAuth via | ||
| `PendingOAuthState.priorHaltedVaultId` (sessionStorage), and | ||
| `OAuthCallback` clears the halt for BOTH the new id AND the | ||
| originally-halted id on success. Three OAuthCallback tests pin | ||
| the same-URL baseline, the different-URL reconnect, and the | ||
| persistent-storage-survives-reload contract; one | ||
| VaultStatusBanner test pins that the reconnect button passes the | ||
| active vault id to `beginOAuth`; two `beginOAuth` tests pin the | ||
| sessionStorage round-trip on both code paths. | ||
| ## [0.3.16-rc.5] - 2026-05-21 | ||
| - **fix(notes): header responsive under text-size scaling (#136).** | ||
| Surfaced during Aaron's testing of the global-zoom text-size landed in | ||
| 0.3.15-rc.10/rc.11. At `larger`/`largest` the html root scales to | ||
| 18–22px and every rem-based Tailwind size (gaps, padding, `text-sm`) | ||
| grows in lockstep — the 11-control inline cluster at `md:flex` (768px) | ||
| overflowed `max-w-5xl` and clipped controls. Two changes: | ||
| - *Cluster breakpoint moved from `md` (768px) to `lg` (1024px)*, so | ||
| tablet and narrow-desktop widths use the existing hamburger menu | ||
| (which lays out vertically and never clips). The cluster also gains | ||
| `flex-wrap` + `gap-y-2` so at lg+ a still-overflowing row wraps to a | ||
| second line rather than truncating. | ||
| - *Vault popover trigger gains a rem-based width cap* (`max-w-[12rem]` | ||
| + `truncate`). Long vault names now compress with ellipsis instead | ||
| of pushing chrome buttons off-screen. The cap is in rem so it | ||
| scales proportionally with text-size — a "12rem" label at `largest` | ||
| is still ~12rem visually, not a fixed-px shrinking target. | ||
| Mobile menu also gains `flex-wrap` on its chrome-buttons row so the | ||
| Install/TextSize/Theme triplet wraps cleanly on narrow phones at | ||
| largest text-size. Three new Header regression tests pin the `lg:` | ||
| breakpoint, the `flex-wrap` class, and the rem-based label cap. | ||
| ## [0.3.16-rc.4] - 2026-05-21 | ||
| - **fix(notes): capture race + draft-saved indicator staleness (#135).** | ||
| Two small follow-ups from the #134 review on the rc.10 draft-save | ||
| redesign: | ||
| - *Race window in `draftSave`*: the ref was set to `{ localId, | ||
| hasEnqueuedCreate: false }` BEFORE awaiting the create-note | ||
| enqueue and flipped to `true` after. During that sub-millisecond | ||
| window, a manual Capture click (or unmount-flush) read | ||
| `hasEnqueuedCreate === false`, fell into the fresh-create branch, | ||
| and enqueued a SECOND `create-note` row with the same localId. | ||
| Fix: flip the committed flag SYNCHRONOUSLY before the await — | ||
| renamed to `createCommitted` for clarity. IndexedDB's | ||
| autoincrement `seq` orders the create's `db.add()` before any | ||
| racing update by call order, so FIFO drain processes | ||
| create-then-update correctly regardless of which await resolves | ||
| first. If the create enqueue itself throws, the catch block now | ||
| resets the ref back to null so the next attempt creates fresh | ||
| (update-note failures leave the ref alone — the create already | ||
| shipped). Three new regression tests cover (a) manual Capture | ||
| racing the autosave, (b) unmount racing the autosave, (c) | ||
| create-failure roll-back so the next autosave creates fresh. | ||
| - *Draft-saved indicator staleness*: the "Draft saved · just now" | ||
| label was computed at render time from `draftSavedAt`, but nothing | ||
| else in the component changed while the user idled — so the label | ||
| could stay at "just now" for the full 5s autosave window (and | ||
| longer if the user idled after a finalized draft) even though | ||
| wall-clock had moved on. Fix: a 15s `setInterval` bumps a tick | ||
| state while `draftSavedAt !== null` so `relativeTime()` keeps | ||
| tracking. One new test confirms the label transitions from "just | ||
| now" to "1m ago" after 70s without user interaction. | ||
| ## [0.3.16-rc.3] - 2026-05-21 | ||
| - **test(notes): component-level insecure-context tests for VaultPopover | ||
| + VaultStatusBanner (#143 follow-up).** The rc.2 refactor pointed both | ||
| components at the relocated `InsecureContextBanner` but the only | ||
| insecure-context coverage lived in `AddVault.test.tsx`. Extends each | ||
| consumer's test file with focused tests pinned at the right | ||
| boundary: spy on `beginOAuth` and reject with `InsecureContextError` | ||
| to verify the dedicated banner renders, plus a negative test that a | ||
| generic `Error` falls through to the regular error UI (and not the | ||
| insecure-context banner). Catches future refactors that would | ||
| silently break the wiring. | ||
| ## 0.3.16-rc.2 (2026-05-21) | ||
| - **refactor(notes): move `InsecureContextBanner` to `src/components/`.** | ||
| The banner was originally defined and exported from | ||
| `src/app/routes/AddVault.tsx` (where it was first used) and imported | ||
| from there by `VaultPopover.tsx` and `VaultStatusBanner.tsx`. That's | ||
| a components-importing-from-routes dependency inversion — routes | ||
| should be leaves. Relocated to | ||
| `src/components/InsecureContextBanner.tsx` with no behavior change; | ||
| three import sites updated. Closes #143. | ||
| ## 0.3.16-rc.1 (2026-05-20) | ||
| - **fix(notes): clear error message when OAuth attempted from insecure | ||
| context.** Aaron hit `Cannot read properties of undefined (reading | ||
| 'digest')` on fresh-install testing when connecting Notes (served | ||
| from a non-loopback HTTP origin) to a vault. Root cause: Web Crypto | ||
| (`crypto.subtle`) is only exposed in W3C secure contexts — HTTPS, | ||
| `http://localhost`, or `http://127.0.0.1` — and Aaron's hub URL was | ||
| `http://192.168.1.10:1939`. There is no polyfill: the gating is | ||
| deliberate, and PKCE genuinely can't run there. | ||
| - `src/lib/vault/pkce.ts`: introduce `InsecureContextError` and | ||
| assert `crypto.subtle?.digest` is present at the top of | ||
| `deriveCodeChallenge` (and `crypto.getRandomValues` in | ||
| `generateCodeVerifier` / `generateState`). Throws an | ||
| operator-facing message that names the cause and lists both | ||
| remediations (HTTPS via Tailscale Serve / Cloudflare Tunnel / | ||
| reverse proxy, or switch to the `http://localhost` form). | ||
| - `src/app/routes/AddVault.tsx`: catch `InsecureContextError` | ||
| distinctly in the connect handler and render a new | ||
| `InsecureContextBanner` — amber palette + structured list of | ||
| remediations, deliberately different from the red "Connection | ||
| failed" strip so the operator can tell at a glance this is a | ||
| browser-policy failure, not a "hub is down" failure. Banner | ||
| shows the exact `window.location.origin` so there's no doubt | ||
| which URL the browser flagged. | ||
| - `src/components/VaultPopover.tsx`, | ||
| `src/components/VaultStatusBanner.tsx`: same catch + banner in | ||
| the other two OAuth-initiating call sites so the messaging is | ||
| consistent wherever PKCE can fail. | ||
| Does **not** make PKCE work in insecure contexts (it can't); makes | ||
| the failure mode obvious and points the operator at the two fixes. | ||
| ## 0.3.15 (2026-05-20) | ||
| Stable release. Cumulative changes since `0.3.14`: | ||
| - **Format-aware rendering Phase 2** (#139): native rendering for CSV (table), JSON (pretty-print), YAML (formatted), code (syntax-highlighted) note bodies. Auto-detected by content type. | ||
| - **Hierarchical capture** (#134, others): autosave draft model + text-size global zoom + capture-flow polish across multiple rc.10-rc.13 iterations. | ||
| - **Cross-tab sync** (#131, others): notes edited in one tab reflect in others within seconds. | ||
| - **Schema-audit UI** (#136): surface vault schema state from the notes UI. | ||
| - **Pending-approval render polish** (#140): dropped the CLI alternative from the OAuth pending-approval screen — the web-based approval path is now the only displayed path. Added "Retry now" button that navigates back to `/add` (works correctly with single-use OAuth codes). | ||
| See individual rc entries below for full detail. | ||
| ## Unreleased | ||
| ### OAuth pending-approval polish | ||
| - **polish(oauth): drop CLI alternative from pending-approval render + | ||
| add retry button (0.3.15-rc.14).** The web-approval path is the path | ||
| now; the `parachute auth approve-client <id>` fallback alongside the | ||
| "Open approval page" button made operators think they still needed | ||
| terminal access, contradicting the hub#266 wizard goal of | ||
| "everything from a browser." | ||
| - `OAuthCallback.tsx`: drop the `<code>parachute auth …</code>` | ||
| block from the pending-approval screen; drop `cliAlternative` from | ||
| the `Status` discriminated union and the `setStatus` call in the | ||
| catch branch. | ||
| - `OAuthCallback.tsx`: add a "Retry now" button alongside "Open | ||
| approval page" so operators can re-attempt OAuth completion after | ||
| approving in the new tab without restarting the connect flow. | ||
| Implementation uses `window.location.reload()` — re-runs the | ||
| `OAuthCallback` effect with the same code/state params. | ||
| - `oauth.ts`: drop `cliAlternative` from `PendingApprovalError` | ||
| (field, constructor, doc-comment) and from `parsePendingApproval`. | ||
| Without an `approve_url`, we now fall through to the generic | ||
| token-exchange-failed error rather than rendering an empty | ||
| "Waiting for hub approval" screen with nothing to click. | ||
| - Hub still emits `cli_alternative` in its `invalid_client` JSON; | ||
| Notes simply ignores it. Pre-#240 hubs that only emit | ||
| `cli_alternative` (no `approve_url`) get the generic error UI. | ||
| ### Phase 2 polish | ||
| - **chore(render): fold reviewer polish nits (0.3.15-rc.13).** | ||
| `escapeHtml` in `src/lib/render/highlight.ts` now escapes `"` (→ | ||
| `"`) and `'` (→ `'`) in addition to `&` / `<` / `>` — current | ||
| callers only use content context, but the generic name invites future | ||
| attribute-context use, so close the hole up front. Added two test | ||
| cases in `format.test.ts` pinning `formatForPath` hidden-file behavior | ||
| (`.gitignore` → `"plain"`, `.ts` → `"code"`) — falls out of the | ||
| extension-driven model, but worth pinning since it was unspecified. | ||
| ### Phase 2 format-aware rendering | ||
| - **feat(render): NoteRenderer dispatches CSV / JSON / YAML / code to | ||
| format-specific renderers (0.3.15-rc.12).** Closes #138. Phase 1 | ||
| (parachute-vault) added file-extension support so non-markdown notes can | ||
| be stored; Phase 2 (this) renders them appropriately on the read path. | ||
| A new `NoteRenderer` dispatcher in `src/components/NoteRenderer.tsx` | ||
| examines the note's path extension and routes to one of six renderers: | ||
| - `MarkdownView` (unchanged) — `.md`, `.mdx`, `.markdown`, no extension | ||
| - `CsvRenderer` — `.csv` rendered as an HTML table (first row = | ||
| headers); inline RFC-4180 parser handles quoted cells, escaped | ||
| quotes, newlines-in-cells, CRLF, missing trailing newline | ||
| - `JsonRenderer` — `.json` pretty-printed + syntax-highlighted; invalid | ||
| JSON falls back to the plain monospace block | ||
| - `YamlRenderer` — `.yaml` / `.yml` syntax-highlighted (no re-emit; | ||
| bytes render as authored) | ||
| - `CodeRenderer` — `.ts` / `.tsx` / `.js` / `.jsx` / `.py` / `.rs` / | ||
| `.go` / `.sh` syntax-highlighted via `highlight.js/lib/core` with | ||
| explicit per-language registration (avoids the `/common` bundle's | ||
| ~35 KB of unused languages) | ||
| - `PlainRenderer` — fallback for unknown extensions and parse failures | ||
| All three existing call sites (`NoteView`, `NoteEditor` preview, | ||
| `NoteNew` preview) now go through `NoteRenderer`. The editor preview | ||
| reads `draft.path` so renaming a draft to `.csv` switches the preview | ||
| live. | ||
| No new dependencies — `highlight.js` was already a dep (used by | ||
| rehype-highlight for fenced code in markdown notes); the new renderers | ||
| reuse it directly. The hljs github theme already imported in | ||
| `styles/index.css` styles both code paths uniformly. | ||
| Bundle: `NoteRenderer` chunk 340.80 kB / 103.55 kB gzip (was | ||
| `MarkdownView` 337.29 kB / 102.30 kB gzip) — delta **+3.51 kB raw / | ||
| +1.25 kB gzip**. Total PWA precache 1578.53 KiB (was 1574.85 KiB). | ||
| Deferred (out of scope for #138): MDX with custom React components in | ||
| the markdown body, image-format thumbnails in non-markdown notes, and | ||
| CodeMirror language-aware editing (the editor still uses markdown | ||
| grammar for every note — Phase 3). | ||
| ### Text-size ramp retune | ||
| - **tune(ui): widen text-size ramp + bump default (0.3.15-rc.11).** | ||
| Aaron's testing of rc.10 surfaced two complaints: default felt small | ||
| for a reading-first app (16px root × 1rem prose = 16px reader), and | ||
| largest was a modest ceiling. Retune to a wider ramp Aaron picked | ||
| from a three-option comparison. Rendered px per step: | ||
| | step | root | `.prose-note` | CodeMirror editor | | ||
| |-----------|-------|---------------|-------------------| | ||
| | default | 16px | 18px | 15px | | ||
| | larger | 18px | 22px | 18px | | ||
| | largest | 22px | 26px | 22px | | ||
| Default `--font-size-prose` bumped from `1rem` → `18px` (absolute, so | ||
| the rendered target is unambiguous). Defaults for editor 14 → 15. | ||
| Larger / largest blocks retuned to hit the px targets via absolute | ||
| values on prose + editor (no rem×root math to verify). rc.10's CSS | ||
| architecture (root font-size scales chrome via rem cascade, prose + | ||
| editor scale independently) is unchanged — only the rendered ramp | ||
| moves. | ||
| No test changes — `TextSizeControl.test.tsx` asserts attribute | ||
| manipulation, not px values, so it passes unchanged. Intentional: | ||
| pinning px would lock the implementation to numbers Aaron will | ||
| likely keep iterating. | ||
| ### Capture draft-save + global text-size zoom | ||
| - **fix(capture): autosave is now a background draft, not a finalize-and- | ||
| clear (0.3.15-rc.10).** P0 bug from Aaron's morning report: typing | ||
| "hello world" in Capture and waiting 5s wiped the textarea. Root | ||
| cause: `save()`'s success path called `reset()` (clears content + | ||
| path) AND never set `phase: "idle"` back, so `canSubmit` stayed | ||
| false and the textarea (`disabled={phase === "saving"}`) stayed | ||
| locked. | ||
| - The redesign: a new `draftSave()` writes a partial as a background | ||
| draft. First fire enqueues `create-note` with a fresh localId; | ||
| subsequent fires on the same mount enqueue `update-note` for the | ||
| same localId (no duplicate notes). Never touches `phase`, never | ||
| clears `content`. A `draftRef.current` carries | ||
| `{ localId, hasEnqueuedCreate }` across the mount. | ||
| - The manual Capture click (and ⌘↵) is the finalize action — if a | ||
| draft is in flight, it enqueues `update-note` (the create already | ||
| shipped) and clears `draftRef` via `reset()`. Phase explicitly | ||
| resets to `idle` after success so the textarea unlocks for the | ||
| next capture on the same mount. | ||
| - Unmount-flush mirrors the same shape: enqueues `update-note` if | ||
| a draft is in flight (otherwise `create-note`). Nav-away no longer | ||
| duplicates the draft. | ||
| - Subtle "Draft saved · <relative time>" indicator below the | ||
| textarea (right-aligned, `text-fg-dim` micro size). Only renders | ||
| after the first successful draft save. | ||
| - Audio captures still finalize-and-clear via the manual Capture | ||
| click — autosave stays suppressed when `phase === "have-audio"`. | ||
| - **fix(ui): text-size knob now scales the whole app, not just `.prose- | ||
| note` + CodeMirror (0.3.15-rc.10).** Aaron reported the Larger / | ||
| Largest radios "appeared to do nothing" on Settings. rc.6's scope | ||
| was too narrow: only `.prose-note` and CodeMirror consumed the | ||
| `--font-size-*` variables, so headers, lists, capture, Settings, | ||
| bottom-tab — none scaled. Added `font-size` on the html root inside | ||
| the `:root[data-text-size="larger"]` (17.5px) and `"largest"` (19px) | ||
| blocks. Tailwind sizes are rem-based, so every chrome element scales | ||
| proportionally. The prose / editor variables stay so the reader | ||
| remains slightly larger than the chrome (read-content > navigation | ||
| feels right). | ||
| - **Tests.** 4 existing autosave tests rewritten for draft-save | ||
| semantics — assert queue rows directly instead of "Captured." toast, | ||
| assert content is preserved across autosaves (the bug), assert | ||
| update-note enqueues on the second draft fire and on unmount-flush | ||
| after a draft. Test names renamed to reflect the new model. | ||
| ### Schema-ensure audit UI — Settings panel + connect-time banner | ||
| - **feat(schema): audit UI for the required Notes schema (0.3.15-rc.9).** | ||
| Closes notes#129. Builds directly on rc.8's `NOTES_REQUIRED_SCHEMA` + | ||
| `ensureNotesSchema`. Until now schema-ensure was first-capture-driven | ||
| (idempotent, silent). This PR adds the operator-facing audit: a | ||
| Settings panel that shows expected-vs-actual for each declared tag, a | ||
| connect-time banner that surfaces when the active vault is missing or | ||
| has misaligned tags, and a one-click "Set up missing tags" action. | ||
| - **`auditSchema(client)`** (`src/lib/vault/schema-audit.ts`) calls | ||
| `GET /api/tags?include_schema=true` and diffs each declared tag | ||
| against the vault row. Returns `{ ok, missing, misaligned, rows }` | ||
| with per-tag `differences: ("description" | "parent_names")[]`. | ||
| Treats null and empty-array `parent_names` as equivalent. | ||
| - **`VaultClient.listTagsWithSchema()`** wraps the schema-detail | ||
| variant of `GET /api/tags`. Narrow return type — only the fields | ||
| audit reads. | ||
| - **`fixSchema(vaultId, client)`** in `schema-ensure.ts` is the | ||
| user-driven entry point. Bypasses the per-session ensure guard | ||
| (user explicitly asked to write), rethrows on failure so UI can | ||
| show "fix failed" toast / banner error, and marks the vault as | ||
| ensured on success so subsequent first-captures don't redo work. | ||
| - **`useSchemaAuditStore`** (volatile, not persisted) holds per-vault | ||
| audit results with `ensure(vaultId, client)` (cache-respecting, | ||
| 5min TTL) + `refresh()` (force-refetch) + `set()` (post-fix update | ||
| without refetch). Mirrors `auth-halt-store` shape. | ||
| - **`useSchemaBannerStore`** (persisted) tracks per-vault banner | ||
| dismissal under `notes:schema-banner-dismissed:<vaultId>` so | ||
| dismissal survives reloads. Mirrors `auth-halt-store` cross-tab | ||
| pattern. | ||
| - **`SchemaAuditRunnerMount`** at the App root auto-fires `ensure` | ||
| when the active vault or its client changes. No DOM, only effect. | ||
| - **`SchemaAuditBanner`** (`src/components/`) renders below | ||
| `VaultStatusBanner` — amber/yellow, less urgent than auth-halt or | ||
| unreachable. Two affordances: "Set up" → calls `fixSchema` then | ||
| marks the cached audit ok; "Dismiss" → persists per-vault. Uses | ||
| `<output role="status" aria-live="polite">` rather than `<div | ||
| role="status">` per Biome's a11y rule. | ||
| - **Settings "Vault schema" section** (top of the Settings page — | ||
| above Text size). Status pill (ok = emerald, !ok = amber), per-tag | ||
| rows showing expected description + parent_names, a "Refresh" link | ||
| and a "Set up missing tags" button. "Schema updated." toast on | ||
| success. | ||
| - **Tests.** 7 new in `schema-audit.test.ts` (ok / missing / desc | ||
| misalignment / parent_names misalignment / null-vs-empty | ||
| equivalence / row completeness / extra-tags-don't-flag). 3 new in | ||
| `schema-ensure.test.ts` (fixSchema bypasses session guard / | ||
| rethrows on failure / marks ensured after success). 4 new in | ||
| `schema-banner-store.test.ts` (dismiss + clear + multi-vault + | ||
| cross-tab reload). 6 new in `SchemaAuditBanner.test.tsx` (renders | ||
| nothing pre-audit / nothing on ok / renders on misalign / hides | ||
| when dismissed / Dismiss persists / Set up calls updateTag for | ||
| each + marks ok). | ||
| ### Capture reshape — hierarchical capture/* tags + schema-ensure + option (d) + path-collision fix | ||
| - **feat(capture): hierarchical capture tags + schema-ensure + option (d) + | ||
| path-collision fix (0.3.15-rc.8).** Closes notes#126 (reshaped scope). | ||
| Builds on rc.7's `quickPath()` pre-fill with Aaron's confirmed `capture/*` | ||
| classification model + several reviewer follow-ups bundled. | ||
| - **`NOTES_REQUIRED_SCHEMA` in `src/lib/vault/schema.ts`** declares the | ||
| `capture` parent + `capture/text` + `capture/voice` children with | ||
| `parent_names: ["capture"]`. First instance of patterns#57 (surface- | ||
| declares-required-schema). Future extensions (`capture/photo`, | ||
| `capture/web-clip`) slot in without rename. | ||
| - **Tag Role defaults rename**: `DEFAULT_TAG_ROLES.captureText` → | ||
| `"capture/text"`, `DEFAULT_TAG_ROLES.captureVoice` → `"capture/voice"`. | ||
| **Existing vaults preserve their stored values** — if a user has | ||
| `captureText = "quick"` from rc.6, that stays. Only fresh-vault | ||
| inheritance changes. | ||
| - **`update-tag` client method + idempotent `ensureNotesSchema()` hook** | ||
| in `src/lib/vault/schema-ensure.ts`. PUTs each declared tag against | ||
| `/api/tags/:name` (field-merged vault-side; no-op when already-correct). | ||
| Per-vault per-session ref guard so repeated captures don't hammer the | ||
| vault. Failure rolls back the guard so the next capture retries. | ||
| Captures-side wiring is fire-and-forget — schema setup doesn't block | ||
| the user's save. | ||
| - **Option (d) bundled** (was the closed PR #131): clearing the path | ||
| input reverts to the mount-time generated value, never vault-picks. | ||
| Resolution becomes `pathOverride.trim() || generatedPathRef.current`. | ||
| The rc.6 `memoPath()` audio-only fallback is dropped — unreachable | ||
| under option (d). One canonical Notes-side rule, no phase-dependent | ||
| forks. Aaron's framing: don't re-introduce hidden vault-picks magic | ||
| via the cleared-input path. | ||
| - **Path-collision fix** (raised in #130 review): `quickPath()` is | ||
| second-granularity, so two captures within the same wall-clock second | ||
| would land at the same path. `reset()` after successful save now | ||
| regenerates `quickPath()` AND updates the input — but only when the | ||
| operator hasn't manually edited. A user typing an explicit path | ||
| (e.g. `Daily/2026-05-12`) is capturing into a deliberate location; | ||
| don't fight them. `pathEditedRef` tracks edit intent; restoring the | ||
| generated value clears the flag. | ||
| - **Placeholder text** updated: `"(blank → vault picks)"` → | ||
| `"(blank → uses generated path)"` so the UI itself describes the | ||
| option-(d) rule. | ||
| - **Tests.** 6 new in `schema-ensure.test.ts` (declaration-order PUTs, | ||
| parent-before-children, per-session per-vault idempotence, multi-vault | ||
| independence, retry-on-failure, swallow-failure-doesn't-throw). 2 new | ||
| in `Capture.test.tsx` (regen-on-reset when unedited; preserve user | ||
| edit across reset). 4 existing tests flipped where defaults changed | ||
| (captureText → `capture/text`, captureVoice → `capture/voice`, | ||
| text+voice combined now both hierarchical) or option (d) changed | ||
| semantics ("empty path reverts to generated", "audio-only cleared | ||
| path reverts to generated"). `Capture.test.tsx` adds a `vi.mock` for | ||
| `@/lib/vault/schema-ensure` so capture tests don't hit the real PUT | ||
| (covered by schema-ensure.test.ts). | ||
| ### Not in scope (deferred) | ||
| - Full Settings audit UI + connect-time banner → notes#129. | ||
| - Per-vault customization of path templates → notes#128. | ||
| ### Text-size shortcuts + header control; Capture path pre-fill | ||
| - **feat(ui): accessible text-size (shortcuts + header) + locally-generated | ||
| capture path (0.3.15-rc.7).** Two follow-ups to rc.6 bundled because | ||
| they touch the same chrome / Capture surfaces. Closes notes#127 + #126. | ||
| - **Text-size keyboard shortcuts (notes#127).** Cmd+= / Cmd+Plus steps | ||
| up the ramp (default → larger → largest → default); Cmd+- / | ||
| Cmd+Underscore steps down; Cmd+0 resets to default. Bound at the | ||
| app root via `TextSizeShortcutsMount` so the listener lives in one | ||
| place — the visible `TextSizeControl` in the Header would otherwise | ||
| register twice (desktop + mobile menu). Ignored when Shift, Alt, or | ||
| neither modifier is held. | ||
| - **Header chrome control (notes#127).** Adds `TextSizeControl` — a | ||
| small "Aa" button next to the existing chrome (Install / Theme). | ||
| Click opens a 3-option popover (Default / Larger / Largest) with a | ||
| ✓ on the active row. Same persist + apply path as the Settings | ||
| dropdown via `lib/text-size.ts`. A same-tab `CustomEvent` keeps the | ||
| popover's active indicator in sync when a shortcut or sibling | ||
| control changes the size (the `storage` event only fires | ||
| cross-tab). Lives on both desktop and mobile menu so phones (no | ||
| keyboard) keep the path. | ||
| - **`nextTextSize` / `previousTextSize` helpers.** Added to | ||
| `lib/text-size.ts` for the shortcut handlers; mirror `nextTheme` | ||
| in `theme.ts` shape. Each direction is explicit so the call site | ||
| doesn't have to think about wrap-around arithmetic. | ||
| - **Capture path pre-fill (notes#126).** Adds `quickPath()` helper | ||
| next to `memoPath()` in `lib/capture/recorder.ts`. Same | ||
| `<root>/YYYY/MM-DD/HH-MM-SS` shape under `Notes/`. Capture's | ||
| `pathOverride` state is now seeded with `quickPath()` on mount so | ||
| the operator sees the generated path the moment they expand More | ||
| fields — no more invisible "vault auto-assigns" magic. | ||
| - **Audio-only memos.** With the pre-fill non-empty, audio captures | ||
| also land under `Notes/` by default (parallel to the text case). | ||
| Operators who want the old `Memos/` rule can clear the path input | ||
| — the existing rc.6 fallback to `memoPath()` for audio-only with | ||
| no override is preserved as the escape valve. New test pins this. | ||
| - **Tests.** 2 new in `text-size.test.ts` (cycle direction helpers). | ||
| 12 new in `TextSizeControl.test.tsx` (button + popover behavior, | ||
| keyboard handlers, same-tab sync). 1 new in `recorder.test.ts` | ||
| (quickPath shape). 2 new in `Capture.test.tsx` (pre-fill is | ||
| editable + saved; audio-only fallback to `memoPath` when path is | ||
| cleared). Existing tests updated where pre-fill changed observable | ||
| behavior (text-only payload now carries `Notes/...`, combined | ||
| text+voice payload now carries `Notes/...` instead of vault-picks). | ||
| ### Capture polish + view-level text-size | ||
| - **feat(ui): unified capture surface refinements + view-level text-size | ||
| control (0.3.15-rc.6).** Two items from `design/2026-05-12-notes-ui-audit.md` | ||
| §3 (north-star "Apple-Notes-grade ease"): #12 (unified capture) and | ||
| #11 (text-size knob). Both behind one PR per the audit's sequencing. | ||
| - **More fields panel (audit §3 #12).** Adds a collapsible | ||
| `<details>` to `Capture` exposing a path override + summary input — | ||
| the audit's "structured form when wanted, hidden when not". Defaults | ||
| to closed so the textarea stays the unfocused-friction default; | ||
| operators who need to set an explicit path (e.g. capturing into | ||
| `Daily/2026-05-12`) get the form without leaving Capture. Empty | ||
| path means "let the vault auto-assign"; empty summary means "no | ||
| metadata.summary". Path override wins over the audio-only memo | ||
| auto-path. | ||
| - **Inactivity autosave (audit §3 #12).** Capture now flushes | ||
| save() after 5 seconds of editing inactivity in addition to the | ||
| existing unmount-flush — protects against browser crashes and | ||
| accidental closes. Skipped while audio is staged (manual Capture | ||
| click only), while recording/saving, and while body is empty. | ||
| - **Escape hatch to NoteNew.** A "Need to attach a file? Open the | ||
| full editor" link in the More-fields panel points at `/new`, which | ||
| still renders `NoteNew` for the file-drop / file-picker / | ||
| `link-on-create` flow. Capture is canonical for the 95% quick path; | ||
| the heavy editor stays available for the 5% that needs attachments. | ||
| Cmd+K keeps both entries for discoverability. | ||
| - **View-level text-size knob (audit §3 #11).** New `lib/text-size.ts` | ||
| mirrors `lib/theme.ts` shape — three steps (Default / Larger / | ||
| Largest), per-device localStorage at `notes:textSize`, applied via | ||
| a `data-text-size` attribute on `<html>`. `styles/index.css` | ||
| defines `--font-size-prose` + `--font-size-editor` CSS variables; | ||
| `.prose-note` reads the prose one (markdown reader), `CodeMirror` | ||
| reads the editor one. Settings gains a `TextSizeSection` with | ||
| three radio buttons that apply + persist in one motion. Markdown | ||
| on disk is unaffected — pure view preference. | ||
| - **Tests.** 4 new in `text-size.test.ts` (round-trip, default | ||
| handling, data-attribute application, labels). 8 new in | ||
| `Capture.test.tsx` covering disclosure default-closed, path/summary | ||
| override payload shape, empty-path fallback, path-override winning | ||
| over memo auto-path, autosave-after-5s, edit-resets-timer, | ||
| empty-content-no-autosave, audio-staged-suppresses-autosave. | ||
| - **Unmount-flush hardening.** The unmount enqueue now swallows IDB | ||
| teardown rejections (SyncProvider closing its handle in the same | ||
| tick is a known race documented in `SyncProvider.tsx:60`). No | ||
| user-visible surface to report failures during nav-away anyway. | ||
| ### Multi-vault hubs — consume per-vault services keys | ||
| - **feat(oauth): prefer `services["vault:<name>"].url` in OAuthCallback | ||
| (0.3.15-rc.5).** Companion consumer for the hub-side change in | ||
| hub#247/#248. Hub now emits per-vault entries in the OAuth services | ||
| catalog alongside the legacy collapsed `vault` key; OAuthCallback | ||
| picks the entry matching the token's `vault` claim. Before this PR, | ||
| every vault on a multi-vault hub (boulder, gitcoin, techne) would | ||
| resolve to the collapsed-first-vault URL, so VaultRecords collided | ||
| on URL and only one entry survived in Manage Vaults. Fallback chain | ||
| is per-vault key → collapsed `vault` → `pending.issuerUrl`, so | ||
| pre-#247 hubs and standalone vaults keep working unchanged. Tests | ||
| cover all three fallback rungs. Closes notes#121. | ||
| ### Retry-now integration test | ||
| - **test(ui): integration coverage for Retry-now → real client → store flush | ||
| (0.3.15-rc.4).** Adds `VaultStatusBanner.retry.integration.test.tsx` | ||
| exercising the load-bearing recovery interaction end-to-end through a | ||
| real `VaultClient` (no `useActiveVaultClient` mock). Three response | ||
| paths covered: 200 (vault healthy) + 401 (vault answering, still | ||
| auth-broken) both flush the store and unmount the banner via the real | ||
| `onReachability("healthy")` callback; 502 keeps the banner up and | ||
| extends `backoffIndex`. Regression-pins the precedence flow so a | ||
| future refactor that disconnects the client→store wiring fails this | ||
| test instead of slipping through. Closes notes#118. | ||
| ### LAN-IP vaults get the operator hint | ||
| - **fix(ui): RFC 1918 detection in `isLoopbackOrLocal` (0.3.15-rc.3).** | ||
| The banner from rc.2 only showed the `Try `parachute start vault`` | ||
| operator hint for `localhost` / `127.0.0.1` / `.local` URLs, so a | ||
| self-hosted vault on a home LAN at e.g. `192.168.1.10:1940` got no | ||
| hint even though the recovery is identical. Adds RFC 1918 private | ||
| IPv4 range matching (10/8, 172.16-31/12, 192.168/16). Tailnet and | ||
| cloud vaults remain correctly unaffected. Tests cover all three | ||
| ranges, the 172.15/172.32 boundary excludes, and public-IP | ||
| negatives that share a prefix digit. Closes notes#117. | ||
| ### Graceful vault-unreachable UX | ||
| - **feat(ui): banner + status dot + retry backoff when vault is unreachable | ||
| (0.3.15-rc.2).** Replaces the raw 502 / blank-screen + console-error | ||
| behaviour Aaron hit after a Mac restart left vault un-started (notes#113). | ||
| - **`VaultUnreachableError`** distinguishes 5xx and network-level failures | ||
| (ECONNREFUSED, DNS, fetch TypeError) from auth/conflict/not-found in | ||
| `VaultClient.request()`. Auth-halt and 4xx errors still mean the vault | ||
| *answered*, so they don't touch reachability state. | ||
| - **`useVaultReachabilityStore`** runs the per-vault state machine | ||
| `healthy → retrying → down`. Promotion to `down` after 3 consecutive | ||
| failures (or an immediate `ECONNREFUSED`). Exponential backoff for the | ||
| recovery probe: 1s → 2s → 4s → 8s → 16s → 30s (cap matches the sync | ||
| engine tick). Not persisted to localStorage — unlike auth-halt, this | ||
| state should re-probe from scratch on reload. | ||
| - **`useReachabilityProbe`** schedules a single `setTimeout` per active | ||
| vault, pings `GET /api/vault` at `nextProbeAt`, and on success the | ||
| client's own `onReachability("healthy")` flush clears the store. Probe | ||
| auto-invalidates `notes`/`tags`/`vaultInfo`/`note` query keys so cached | ||
| data refreshes on recovery. | ||
| - **`VaultStatusBanner`** (renamed from `ReconnectBanner`) covers both | ||
| failure axes with one component: auth-halt has precedence over | ||
| unreachable (different recovery paths — re-OAuth vs wait/retry). The | ||
| unreachable banner offers `Retry now` (forces a probe + invalidates | ||
| queries) and `Dismiss` (one-shot escape hatch via `resetToHealthy`). | ||
| Local-vault operator hint (`Try `parachute start vault``) is shown | ||
| only for loopback / `.local` URLs. | ||
| - **`SyncStatusIndicator`** gains a 5th tone `unreachable` ("Vault down", | ||
| `bg-red-400`). Precedence: `halted → unreachable → offline → syncing → | ||
| online`. Auth-halt still wins; unreachable beats `navigator.onLine` | ||
| because it points at a more specific recovery. | ||
| - **`QueryProvider` retry policy** pauses React Query retries on | ||
| `VaultUnreachableError` once the store crosses `down` — this is what | ||
| stops the `/api/notes` 404 hammering in the vault log (every list/get | ||
| call legitimately hits `/api/notes?...`; nothing was stopping React | ||
| Query from retrying twice per query forever). While still `retrying` | ||
| (≤2 failures) one retry is allowed so a single blip self-heals | ||
| without ever showing the banner. | ||
| - **Tests.** `client.test.ts` adds 502/503/TypeError/AbortError mappings | ||
| and the `healthy` reset on 4xx. `reachability-store.test.ts` covers | ||
| the full state machine + backoff index growth + per-vault isolation. | ||
| `VaultStatusBanner.test.tsx` covers both modes, the auth-halt-wins | ||
| precedence, the loopback hint, the Retry/Dismiss buttons, and | ||
| `isLoopbackOrLocal`. `SyncStatusIndicator.test.tsx` adds the | ||
| `Vault down` tone test (above offline in precedence). | ||
| ### Vault popover (header) | ||
| - **feat(ui): vault popover + hub-discovery + OAuth `vault=<name>` hint | ||
| (0.3.15-rc.1).** Replaces the bare `<select>` switcher in the header | ||
| with a popover that surfaces the operator's full hub-side vault list | ||
| alongside the locally-connected vaults. Implements §2 of | ||
| [`design/2026-05-12-notes-ui-audit.md`](./design/2026-05-12-notes-ui-audit.md); | ||
| the first item in the §5 ship sequence. | ||
| - **Two sections.** "Connected" lists vaults Notes has tokens for | ||
| (active vault gets a filled accent dot + "current" tag; the rest | ||
| are one click to switch). "Available from your hub" lists vaults | ||
| published at `<hub>/.well-known/parachute.json` that Notes hasn't | ||
| connected to yet, each with an inline "Connect" button. Footer | ||
| links to the existing `/vaults` management page. | ||
| - **Hub-origin discovery.** Derived from `VaultRecord.issuer` (which | ||
| under hub-as-issuer is the hub origin itself, captured at OAuth | ||
| time in `OAuthCallback.tsx`) — no schema change to the stored | ||
| record, no migration. For a standalone-vault deployment the | ||
| well-known fetch returns no peers and the Available section is | ||
| omitted (graceful degradation). | ||
| - **OAuth `vault=<name>` hint (Path A).** `beginOAuth` now accepts an | ||
| `options.params` bag appended to the authorize URL last, guarded | ||
| so caller-supplied params can never overwrite standard OAuth/PKCE | ||
| params. Notes sends `vault=<name>` so future hubs that adopt the | ||
| hint can pre-select on the consent screen; pre-#240 hubs ignore it | ||
| and the picker renders as today. | ||
| - **Mobile.** Same component, rendered as `variant="inline"` inside | ||
| the existing hamburger menu — replaces the mobile `<select>` plus | ||
| the standalone "Manage vaults" button. | ||
| ### Design | ||
| ## 0.3.14 (2026-05-11) | ||
| ### OAuth pending-approval UX | ||
| - **feat(oauth): consume hub's `approve_url` field from the | ||
| pending-approval response.** When `/oauth/token` answers with | ||
| `error: "invalid_client"` and the hub#240 hint fields | ||
| (`approve_url`, `cli_alternative`), `completeOAuth` now throws a | ||
| typed `PendingApprovalError` instead of folding the raw JSON into a | ||
| generic "Token exchange failed" string. The `OAuthCallback` route | ||
| renders a dedicated "Waiting for hub approval" screen with a | ||
| one-click "Open approval page" link (the hub's | ||
| `/admin/approve-client/<id>` SPA route) plus the | ||
| `parachute auth approve-client …` CLI as a secondary path. | ||
| Back-compat: pre-#240 hubs that emit only `cli_alternative` still | ||
| surface the friendly screen with the CLI fallback alone; an | ||
| `invalid_client` response with no hint fields (unknown client_id, | ||
| revoked client) falls through to the generic error UI rather than | ||
| getting swallowed into the approval flow. Defense-in-depth: only | ||
| `http(s)` `approve_url` schemes make it to the rendered `href` — | ||
| any other scheme (`javascript:`, malformed) is dropped at parse | ||
| time, with the CLI alternative still surfaced if present. | ||
| ## 0.3.13 (2026-05-10) | ||
| ### Module manifest | ||
| - **docs(module): declare `uiUrl: "/notes"` per | ||
| [`patterns/module-ui-declaration.md`](https://github.com/ParachuteComputer/parachute-patterns/blob/main/patterns/module-ui-declaration.md).** | ||
| Lets hub render the Notes discovery tile dynamically from the | ||
| well-known doc instead of from its hardcoded `SERVICE_LABELS` map. | ||
| No runtime change in Notes itself; the field is opaque to the PWA. | ||
| ## 0.3.12 (2026-05-09) | ||
| ### OAuth / DCR | ||
| - **feat(oauth): include credentials on DCR registration so hub session | ||
| cookie reaches /oauth/register (#106).** Adds `credentials: 'include'` | ||
| to the `POST /oauth/register` fetch in `src/lib/vault/discovery.ts` so | ||
| the browser sends the `parachute_hub_session` cookie when registering. | ||
| Companion to hub#199 (hub-side auto-approve) and agent#140 (sibling | ||
| fix on agent's SPA). | ||
| **Scope:** Same-origin auto-approve (notes loaded at `<hub>/notes/` → | ||
| DCR at `<hub>/oauth/register`) activates as soon as hub#199/200 lands. | ||
| Cross-origin auto-approve (e.g. notes on a cloudflare URL → hub on | ||
| tailnet) does NOT work yet — it requires hub-side CORS with | ||
| `Access-Control-Allow-Credentials`, a first-party origin allowlist, and | ||
| a `SameSite` relaxation or alternative credential, tracked at | ||
| parachute-hub#201. Until that lands, cross-origin DCR continues to | ||
| register as `pending` and requires manual `parachute auth approve-client`. | ||
| ## 0.3.11 (2026-05-05) | ||
| First `@latest` publish since launch (`0.3.0`). Bundles every change merged | ||
| since launch into a single tagged release plus the discovery-protocol fix | ||
| needed for hub well-known to resolve notes correctly. | ||
| ### Discovery / module protocol | ||
| - **fix(spa): serve `.parachute/info` as JSON before SPA catch-all (#102).** | ||
| Notes' Vite preview SPA fallback was matching `/.parachute/info` and | ||
| `/notes/.parachute/info` and returning the index.html shell, so hub's | ||
| well-known builder couldn't read notes' module identity. The | ||
| `infoEndpointPlugin` now registers Connect middleware at both the | ||
| basePath-prefixed path (`/notes/.parachute/info`) and the root | ||
| (`/.parachute/info`) — matching the canonical contract used by vault and | ||
| scribe (no `.json` extension). The middleware runs before sirv and the | ||
| SPA fallback. Build still emits `dist/.parachute/info` as a static asset | ||
| for static-deploy scenarios. | ||
| ### Accessibility | ||
| - **fix(a11y): visible RouteFallback with announceable status (#98).** The | ||
| route-level lazy fallback now renders a visible spinner with `role="status"` | ||
| so screen readers announce route transitions. | ||
| - **fix(a11y): explicit `aria-live="polite"` on RouteFallback + smoke test | ||
| (#101).** Hardens the fallback's announcement contract and adds a | ||
| regression test. | ||
| ### Feature work and cleanup since launch | ||
| - **chore: closeout — capture race + queue nit + route-level lazy (#96).** | ||
| - **feat: unified single-screen capture (#94).** Capture flow consolidated. | ||
| - **feat: saved-view management UI + cluster-A closeout (#93).** | ||
| - **sync: reconnect banner + cross-tab vault sync (#92).** | ||
| - **Cleanup bundle: pinned hint, group test, vault-switch reset, settings | ||
| drain, module.json (#90).** | ||
| - **fix: capture `if_updated_at` baseline for offline note edits (#88).** | ||
| - **feat: OAuth via hub-as-issuer with refresh + DCR cache (#83).** | ||
| - **release: 0.3.2 (+ ignore `.claude` in lint/test) (#82).** | ||
| - **docs: update parachute-cli refs to parachute-hub (#81).** | ||
| - **feat: probe local hub at :1939 when same-origin probe fails (#80).** | ||
| - **docs(readme): status note — PWA install flow coming with public | ||
| exposure (#77).** | ||
| ### Repo hygiene | ||
| - **chore: gitignore `.claude/` stray artifacts.** Local agent worktrees / | ||
| scheduled-task locks no longer show up as untracked files. | ||
| ## 0.3.0 (2026-04-23) | ||
| Launch. |
| # parachute-notes daemon — DEPRECATED | ||
| **Status**: Deprecated as of 2026-05-22 — see migration below. | ||
| The `@openparachute/notes` daemon is deprecated. Notes now ships as a UI bundle (`@openparachute/notes-ui`) consumed by [parachute-app](https://github.com/ParachuteComputer/parachute-app). | ||
| ## Migration | ||
| If you have notes-daemon installed today: | ||
| 1. Install parachute-app: `parachute install app` | ||
| 2. Apps auto-bootstraps Notes on fresh installs; if you have an existing apps install, add it manually: | ||
| `parachute-app add @openparachute/notes-ui --name notes --path /app/notes` | ||
| 3. Your existing bookmarks/links to `/notes/*` continue working — hub redirects to `/app/notes/*` automatically (Phase 2 redirect window) | ||
| 4. Optional: uninstall the old daemon: `parachute uninstall notes` (keeps your vault notes intact — they live in vault, not the daemon) | ||
| ## Why the change | ||
| - Notes is conceptually an "app" that consumes a vault — not its own backend service | ||
| - parachute-app is the host module for custom UIs (Gitcoin Brain, Unforced Brain, etc.); Notes joins them as the first canonical app | ||
| - Reduces ecosystem surface (4 committed-core modules → 3 + 1 host module) | ||
| - New UIs can ship as bundles without each becoming a full npm-published module | ||
| Full migration arc: https://parachute.computer/design/2026-05-21-parachute-apps-design — Section 16. | ||
| ## Timeline | ||
| - **Phase 1** (done): @openparachute/notes-ui published. notes-daemon continues alongside. | ||
| - **Phase 2** (this release): notes-daemon deprecated. Hub redirects /notes/* → /app/notes/*. Operators can migrate at their own pace. | ||
| - **Phase 3** (TBD, ~Q3 2026): notes-daemon retires. Port 1942 reclaimed. | ||
| - **Phase 4** (cleanup): notes-daemon package archived. Source moves to UI-only. | ||
| ## Questions / Issues | ||
| File at https://github.com/ParachuteComputer/parachute-notes/issues |
| 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-BDPMEkxL.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}; |
| 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-BDPMEkxL.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}; |
| 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-BDPMEkxL.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}; |
| 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-BDPMEkxL.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()} | ||
| _Transcript pending._ | ||
| ![[${O}]] | ||
| `:`_Transcript pending._ | ||
| ![[${O}]] | ||
| `,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}; |
| function u(t){return t<10?`0${t}`:String(t)}function s(t=new Date){return`${t.getFullYear()}-${u(t.getMonth()+1)}-${u(t.getDate())}`}function l(t){if(!t)return null;const e=new Date(t);return Number.isNaN(e.getTime())?null:s(e)}function c(t){if(!t||!/^\d{4}-\d{2}-\d{2}$/.test(t))return null;const[e,n,r]=t.split("-").map(Number),a=new Date(e,n-1,r);return Number.isNaN(a.getTime())?null:a}function f(t=new Date){return`${t.getFullYear()}-${u(t.getMonth()+1)}`}function d(t){if(!t||!/^\d{4}-\d{2}$/.test(t))return null;const[e,n]=t.split("-").map(Number);return n<1||n>12?null:{year:e,month:n}}function g(t,e,n){const r=t*12+(e-1)+n;return{year:Math.floor(r/12),month:r%12+1}}function m(t,e){const r=new Date(t,e-1,1).getDay(),a=new Date(t,e-1,1-r),i=[];for(let o=0;o<42;o++)i.push(new Date(a.getFullYear(),a.getMonth(),a.getDate()+o));return i}function D(t){const e=c(t);return e?e.toLocaleDateString(void 0,{weekday:"long",year:"numeric",month:"long",day:"numeric"}):t}function h(t,e){return new Date(t,e-1,1).toLocaleDateString(void 0,{year:"numeric",month:"long"})}export{h as a,c as b,f as c,d,s as e,D as f,m,u as p,g as s,l as t}; |
Sorry, the diff of this file is too big to display
| @import"https://fonts.googleapis.com/css2?family=Instrument+Serif:ital@0;1&family=DM+Sans:ital,opsz,wght@0,9..40,300;0,9..40,400;0,9..40,500;1,9..40,300;1,9..40,400&family=JetBrains+Mono:wght@400;500&display=swap";/*! tailwindcss v4.3.0 | MIT License | https://tailwindcss.com */@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-space-y-reverse:0;--tw-divide-y-reverse:0;--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-ordinal:initial;--tw-slashed-zero:initial;--tw-numeric-figure:initial;--tw-numeric-spacing:initial;--tw-numeric-fraction:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-outline-style:solid;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-backdrop-blur:initial;--tw-backdrop-brightness:initial;--tw-backdrop-contrast:initial;--tw-backdrop-grayscale:initial;--tw-backdrop-hue-rotate:initial;--tw-backdrop-invert:initial;--tw-backdrop-opacity:initial;--tw-backdrop-saturate:initial;--tw-backdrop-sepia:initial}}}@layer theme{:root,:host{--font-sans:"DM Sans", -apple-system, BlinkMacSystemFont, sans-serif;--font-serif:"Instrument Serif", Georgia, serif;--font-mono:"JetBrains Mono", "SF Mono", Monaco, monospace;--color-red-50:oklch(97.1% .013 17.38);--color-red-100:oklch(93.6% .032 17.717);--color-red-200:oklch(88.5% .062 18.334);--color-red-300:oklch(80.8% .114 19.571);--color-red-400:oklch(70.4% .191 22.216);--color-red-500:oklch(63.7% .237 25.331);--color-red-600:oklch(57.7% .245 27.325);--color-amber-50:oklch(98.7% .022 95.277);--color-amber-100:oklch(96.2% .059 95.617);--color-amber-200:oklch(92.4% .12 95.746);--color-amber-300:oklch(87.9% .169 91.605);--color-amber-400:oklch(82.8% .189 84.429);--color-amber-500:oklch(76.9% .188 70.08);--color-amber-700:oklch(55.5% .163 48.998);--color-emerald-300:oklch(84.5% .143 164.978);--color-emerald-400:oklch(76.5% .177 163.223);--color-emerald-500:oklch(69.6% .17 162.48);--color-sky-300:oklch(82.8% .111 230.318);--color-sky-400:oklch(74.6% .16 232.661);--color-sky-500:oklch(68.5% .169 237.323);--color-black:#000;--color-white:#fff;--spacing:.25rem;--container-sm:24rem;--container-md:28rem;--container-xl:36rem;--container-2xl:42rem;--container-3xl:48rem;--container-4xl:56rem;--container-5xl:64rem;--container-6xl:72rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--text-base:1rem;--text-base--line-height: 1.5 ;--text-lg:1.125rem;--text-lg--line-height:calc(1.75 / 1.125);--text-xl:1.25rem;--text-xl--line-height:calc(1.75 / 1.25);--text-2xl:1.5rem;--text-2xl--line-height:calc(2 / 1.5);--text-3xl:1.875rem;--text-3xl--line-height: 1.2 ;--text-4xl:2.25rem;--text-4xl--line-height:calc(2.5 / 2.25);--text-5xl:3rem;--text-5xl--line-height:1;--font-weight-medium:500;--tracking-tight:-.025em;--tracking-wide:.025em;--tracking-wider:.05em;--radius-md:.375rem;--radius-lg:.5rem;--radius-xl:.75rem;--animate-pulse:pulse 2s cubic-bezier(.4, 0, .6, 1) infinite;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono);--color-bg:#faf8f4;--color-bg-soft:#f3f0ea;--color-fg:#2c2a26;--color-fg-muted:#6b6860;--color-fg-dim:#9a9690;--color-accent:#4a7c59;--color-accent-hover:#3d6849;--color-accent-light:#6a9b77;--color-border:#e4e0d8;--color-card:#fff;--font-size-prose:18px;--font-size-editor:15px}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;-moz-tab-size:4;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab,red,red)){::placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){-webkit-appearance:button;-moz-appearance:button;appearance:button}::file-selector-button{-webkit-appearance:button;-moz-appearance:button;appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.pointer-events-auto{pointer-events:auto}.pointer-events-none{pointer-events:none}.collapse{visibility:collapse}.invisible{visibility:hidden}.visible{visibility:visible}.sr-only{clip-path:inset(50%);white-space:nowrap;border-width:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.static{position:static}.sticky{position:sticky}.inset-0{inset:calc(var(--spacing) * 0)}.inset-x-0{inset-inline:calc(var(--spacing) * 0)}.top-0{top:calc(var(--spacing) * 0)}.top-full{top:100%}.right-0{right:calc(var(--spacing) * 0)}.right-3{right:calc(var(--spacing) * 3)}.bottom-0{bottom:calc(var(--spacing) * 0)}.bottom-3{bottom:calc(var(--spacing) * 3)}.bottom-4{bottom:calc(var(--spacing) * 4)}.bottom-6{bottom:calc(var(--spacing) * 6)}.left-1\/2{left:50%}.z-10{z-index:10}.z-20{z-index:20}.z-30{z-index:30}.z-40{z-index:40}.z-50{z-index:50}.container{width:100%}@media(min-width:40rem){.container{max-width:40rem}}@media(min-width:48rem){.container{max-width:48rem}}@media(min-width:64rem){.container{max-width:64rem}}@media(min-width:80rem){.container{max-width:80rem}}@media(min-width:96rem){.container{max-width:96rem}}.m-0{margin:calc(var(--spacing) * 0)}.m-auto{margin:auto}.mx-1{margin-inline:calc(var(--spacing) * 1)}.mx-auto{margin-inline:auto}.-mt-2{margin-top:calc(var(--spacing) * -2)}.mt-0\.5{margin-top:calc(var(--spacing) * .5)}.mt-1{margin-top:calc(var(--spacing) * 1)}.mt-1\.5{margin-top:calc(var(--spacing) * 1.5)}.mt-2{margin-top:calc(var(--spacing) * 2)}.mt-3{margin-top:calc(var(--spacing) * 3)}.mt-4{margin-top:calc(var(--spacing) * 4)}.mt-6{margin-top:calc(var(--spacing) * 6)}.mt-8{margin-top:calc(var(--spacing) * 8)}.mt-10{margin-top:calc(var(--spacing) * 10)}.mr-1{margin-right:calc(var(--spacing) * 1)}.mr-2{margin-right:calc(var(--spacing) * 2)}.mb-1{margin-bottom:calc(var(--spacing) * 1)}.mb-1\.5{margin-bottom:calc(var(--spacing) * 1.5)}.mb-2{margin-bottom:calc(var(--spacing) * 2)}.mb-3{margin-bottom:calc(var(--spacing) * 3)}.mb-4{margin-bottom:calc(var(--spacing) * 4)}.mb-5{margin-bottom:calc(var(--spacing) * 5)}.mb-6{margin-bottom:calc(var(--spacing) * 6)}.mb-8{margin-bottom:calc(var(--spacing) * 8)}.mb-10{margin-bottom:calc(var(--spacing) * 10)}.ml-0\.5{margin-left:calc(var(--spacing) * .5)}.ml-1{margin-left:calc(var(--spacing) * 1)}.ml-2{margin-left:calc(var(--spacing) * 2)}.ml-4{margin-left:calc(var(--spacing) * 4)}.ml-auto{margin-left:auto}.line-clamp-2{-webkit-line-clamp:2;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.block{display:block}.contents{display:contents}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline{display:inline}.inline-block{display:inline-block}.inline-flex{display:inline-flex}.table{display:table}.h-1{height:calc(var(--spacing) * 1)}.h-1\.5{height:calc(var(--spacing) * 1.5)}.h-2{height:calc(var(--spacing) * 2)}.h-3{height:calc(var(--spacing) * 3)}.h-4{height:calc(var(--spacing) * 4)}.h-5{height:calc(var(--spacing) * 5)}.h-6{height:calc(var(--spacing) * 6)}.h-8{height:calc(var(--spacing) * 8)}.h-10{height:calc(var(--spacing) * 10)}.h-14{height:calc(var(--spacing) * 14)}.h-16{height:calc(var(--spacing) * 16)}.h-24{height:calc(var(--spacing) * 24)}.h-28{height:calc(var(--spacing) * 28)}.h-32{height:calc(var(--spacing) * 32)}.h-\[24rem\]{height:24rem}.h-\[40rem\]{height:40rem}.h-\[calc\(100dvh-5rem\)\]{height:calc(100dvh - 5rem)}.h-full{height:100%}.max-h-48{max-height:calc(var(--spacing) * 48)}.max-h-56{max-height:calc(var(--spacing) * 56)}.max-h-\[32rem\]{max-height:32rem}.max-h-\[50vh\]{max-height:50vh}.max-h-\[60vh\]{max-height:60vh}.max-h-full{max-height:100%}.min-h-0{min-height:calc(var(--spacing) * 0)}.min-h-11{min-height:calc(var(--spacing) * 11)}.min-h-20{min-height:calc(var(--spacing) * 20)}.min-h-\[30vh\]{min-height:30vh}.min-h-\[60vh\]{min-height:60vh}.min-h-dvh{min-height:100dvh}.w-1\.5{width:calc(var(--spacing) * 1.5)}.w-1\/3{width:33.3333%}.w-2{width:calc(var(--spacing) * 2)}.w-2\/3{width:66.6667%}.w-4{width:calc(var(--spacing) * 4)}.w-5{width:calc(var(--spacing) * 5)}.w-6{width:calc(var(--spacing) * 6)}.w-10{width:calc(var(--spacing) * 10)}.w-32{width:calc(var(--spacing) * 32)}.w-40{width:calc(var(--spacing) * 40)}.w-44{width:calc(var(--spacing) * 44)}.w-48{width:calc(var(--spacing) * 48)}.w-72{width:calc(var(--spacing) * 72)}.w-80{width:calc(var(--spacing) * 80)}.w-full{width:100%}.w-px{width:1px}.max-w-2xl{max-width:var(--container-2xl)}.max-w-3xl{max-width:var(--container-3xl)}.max-w-4xl{max-width:var(--container-4xl)}.max-w-5xl{max-width:var(--container-5xl)}.max-w-6xl{max-width:var(--container-6xl)}.max-w-\[12rem\]{max-width:12rem}.max-w-full{max-width:100%}.max-w-md{max-width:var(--container-md)}.max-w-sm{max-width:var(--container-sm)}.max-w-xl{max-width:var(--container-xl)}.min-w-0{min-width:calc(var(--spacing) * 0)}.min-w-11{min-width:calc(var(--spacing) * 11)}.min-w-24{min-width:calc(var(--spacing) * 24)}.min-w-48{min-width:calc(var(--spacing) * 48)}.flex-1{flex:1}.shrink{flex-shrink:1}.shrink-0{flex-shrink:0}.grow{flex-grow:1}.-translate-x-1\/2{--tw-translate-x: -50% ;translate:var(--tw-translate-x) var(--tw-translate-y)}.animate-pulse{animation:var(--animate-pulse)}.cursor-pointer{cursor:pointer}.touch-none{touch-action:none}.resize-y{resize:vertical}.list-decimal{list-style-type:decimal}.list-disc{list-style-type:disc}.list-none{list-style-type:none}.grid-cols-7{grid-template-columns:repeat(7,minmax(0,1fr))}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-baseline{align-items:baseline}.items-center{align-items:center}.items-end{align-items:flex-end}.items-start{align-items:flex-start}.items-stretch{align-items:stretch}.justify-around{justify-content:space-around}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.justify-end{justify-content:flex-end}.gap-0\.5{gap:calc(var(--spacing) * .5)}.gap-1{gap:calc(var(--spacing) * 1)}.gap-1\.5{gap:calc(var(--spacing) * 1.5)}.gap-2{gap:calc(var(--spacing) * 2)}.gap-3{gap:calc(var(--spacing) * 3)}.gap-4{gap:calc(var(--spacing) * 4)}.gap-6{gap:calc(var(--spacing) * 6)}.gap-10{gap:calc(var(--spacing) * 10)}:where(.space-y-0\.5>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * .5) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * .5) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-1>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 1) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 1) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-1\.5>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 1.5) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 1.5) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-2>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 2) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 2) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-3>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 3) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 3) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-4>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 4) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 4) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-6>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 6) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 6) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-8>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 8) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 8) * calc(1 - var(--tw-space-y-reverse)))}.gap-x-3{column-gap:calc(var(--spacing) * 3)}.gap-x-4{column-gap:calc(var(--spacing) * 4)}.gap-y-2{row-gap:calc(var(--spacing) * 2)}.gap-y-3{row-gap:calc(var(--spacing) * 3)}:where(.divide-y>:not(:last-child)){--tw-divide-y-reverse:0;border-bottom-style:var(--tw-border-style);border-top-style:var(--tw-border-style);border-top-width:calc(1px * var(--tw-divide-y-reverse));border-bottom-width:calc(1px * calc(1 - var(--tw-divide-y-reverse)))}:where(.divide-border>:not(:last-child)){border-color:var(--color-border)}.self-start{align-self:flex-start}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-x-hidden{overflow-x:hidden}.overflow-y-auto{overflow-y:auto}.rounded{border-radius:.25rem}.rounded-full{border-radius:3.40282e38px}.rounded-lg{border-radius:var(--radius-lg)}.rounded-md{border-radius:var(--radius-md)}.rounded-xl{border-radius:var(--radius-xl)}.rounded-t-md{border-top-left-radius:var(--radius-md);border-top-right-radius:var(--radius-md)}.border{border-style:var(--tw-border-style);border-width:1px}.border-2{border-style:var(--tw-border-style);border-width:2px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-r{border-right-style:var(--tw-border-style);border-right-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-l{border-left-style:var(--tw-border-style);border-left-width:1px}.border-dashed{--tw-border-style:dashed;border-style:dashed}.border-accent{border-color:var(--color-accent)}.border-accent\/30{border-color:#4a7c594d}@supports (color:color-mix(in lab,red,red)){.border-accent\/30{border-color:color-mix(in oklab,var(--color-accent) 30%,transparent)}}.border-accent\/40{border-color:#4a7c5966}@supports (color:color-mix(in lab,red,red)){.border-accent\/40{border-color:color-mix(in oklab,var(--color-accent) 40%,transparent)}}.border-accent\/60{border-color:#4a7c5999}@supports (color:color-mix(in lab,red,red)){.border-accent\/60{border-color:color-mix(in oklab,var(--color-accent) 60%,transparent)}}.border-amber-400\/40{border-color:#fcbb0066}@supports (color:color-mix(in lab,red,red)){.border-amber-400\/40{border-color:color-mix(in oklab,var(--color-amber-400) 40%,transparent)}}.border-amber-500\/30{border-color:#f99c004d}@supports (color:color-mix(in lab,red,red)){.border-amber-500\/30{border-color:color-mix(in oklab,var(--color-amber-500) 30%,transparent)}}.border-amber-500\/40{border-color:#f99c0066}@supports (color:color-mix(in lab,red,red)){.border-amber-500\/40{border-color:color-mix(in oklab,var(--color-amber-500) 40%,transparent)}}.border-border{border-color:var(--color-border)}.border-red-400\/30{border-color:#ff65684d}@supports (color:color-mix(in lab,red,red)){.border-red-400\/30{border-color:color-mix(in oklab,var(--color-red-400) 30%,transparent)}}.border-red-500\/30{border-color:#fb2c364d}@supports (color:color-mix(in lab,red,red)){.border-red-500\/30{border-color:color-mix(in oklab,var(--color-red-500) 30%,transparent)}}.border-red-500\/40{border-color:#fb2c3666}@supports (color:color-mix(in lab,red,red)){.border-red-500\/40{border-color:color-mix(in oklab,var(--color-red-500) 40%,transparent)}}.border-sky-500\/30{border-color:#00a5ef4d}@supports (color:color-mix(in lab,red,red)){.border-sky-500\/30{border-color:color-mix(in oklab,var(--color-sky-500) 30%,transparent)}}.border-transparent{border-color:#0000}.bg-accent{background-color:var(--color-accent)}.bg-accent\/5{background-color:#4a7c590d}@supports (color:color-mix(in lab,red,red)){.bg-accent\/5{background-color:color-mix(in oklab,var(--color-accent) 5%,transparent)}}.bg-accent\/10{background-color:#4a7c591a}@supports (color:color-mix(in lab,red,red)){.bg-accent\/10{background-color:color-mix(in oklab,var(--color-accent) 10%,transparent)}}.bg-accent\/15{background-color:#4a7c5926}@supports (color:color-mix(in lab,red,red)){.bg-accent\/15{background-color:color-mix(in oklab,var(--color-accent) 15%,transparent)}}.bg-accent\/20{background-color:#4a7c5933}@supports (color:color-mix(in lab,red,red)){.bg-accent\/20{background-color:color-mix(in oklab,var(--color-accent) 20%,transparent)}}.bg-amber-400{background-color:var(--color-amber-400)}.bg-amber-400\/10{background-color:#fcbb001a}@supports (color:color-mix(in lab,red,red)){.bg-amber-400\/10{background-color:color-mix(in oklab,var(--color-amber-400) 10%,transparent)}}.bg-amber-500\/5{background-color:#f99c000d}@supports (color:color-mix(in lab,red,red)){.bg-amber-500\/5{background-color:color-mix(in oklab,var(--color-amber-500) 5%,transparent)}}.bg-amber-500\/10{background-color:#f99c001a}@supports (color:color-mix(in lab,red,red)){.bg-amber-500\/10{background-color:color-mix(in oklab,var(--color-amber-500) 10%,transparent)}}.bg-amber-500\/20{background-color:#f99c0033}@supports (color:color-mix(in lab,red,red)){.bg-amber-500\/20{background-color:color-mix(in oklab,var(--color-amber-500) 20%,transparent)}}.bg-amber-500\/30{background-color:#f99c004d}@supports (color:color-mix(in lab,red,red)){.bg-amber-500\/30{background-color:color-mix(in oklab,var(--color-amber-500) 30%,transparent)}}.bg-bg{background-color:var(--color-bg)}.bg-bg\/40{background-color:#faf8f466}@supports (color:color-mix(in lab,red,red)){.bg-bg\/40{background-color:color-mix(in oklab,var(--color-bg) 40%,transparent)}}.bg-bg\/50{background-color:#faf8f480}@supports (color:color-mix(in lab,red,red)){.bg-bg\/50{background-color:color-mix(in oklab,var(--color-bg) 50%,transparent)}}.bg-bg\/60{background-color:#faf8f499}@supports (color:color-mix(in lab,red,red)){.bg-bg\/60{background-color:color-mix(in oklab,var(--color-bg) 60%,transparent)}}.bg-bg\/80{background-color:#faf8f4cc}@supports (color:color-mix(in lab,red,red)){.bg-bg\/80{background-color:color-mix(in oklab,var(--color-bg) 80%,transparent)}}.bg-bg\/90{background-color:#faf8f4e6}@supports (color:color-mix(in lab,red,red)){.bg-bg\/90{background-color:color-mix(in oklab,var(--color-bg) 90%,transparent)}}.bg-bg\/95{background-color:#faf8f4f2}@supports (color:color-mix(in lab,red,red)){.bg-bg\/95{background-color:color-mix(in oklab,var(--color-bg) 95%,transparent)}}.bg-black\/60{background-color:#0009}@supports (color:color-mix(in lab,red,red)){.bg-black\/60{background-color:color-mix(in oklab,var(--color-black) 60%,transparent)}}.bg-border{background-color:var(--color-border)}.bg-border\/30{background-color:#e4e0d84d}@supports (color:color-mix(in lab,red,red)){.bg-border\/30{background-color:color-mix(in oklab,var(--color-border) 30%,transparent)}}.bg-border\/40{background-color:#e4e0d866}@supports (color:color-mix(in lab,red,red)){.bg-border\/40{background-color:color-mix(in oklab,var(--color-border) 40%,transparent)}}.bg-border\/60{background-color:#e4e0d899}@supports (color:color-mix(in lab,red,red)){.bg-border\/60{background-color:color-mix(in oklab,var(--color-border) 60%,transparent)}}.bg-card{background-color:var(--color-card)}.bg-card\/30{background-color:#ffffff4d}@supports (color:color-mix(in lab,red,red)){.bg-card\/30{background-color:color-mix(in oklab,var(--color-card) 30%,transparent)}}.bg-card\/40{background-color:#fff6}@supports (color:color-mix(in lab,red,red)){.bg-card\/40{background-color:color-mix(in oklab,var(--color-card) 40%,transparent)}}.bg-card\/50{background-color:#ffffff80}@supports (color:color-mix(in lab,red,red)){.bg-card\/50{background-color:color-mix(in oklab,var(--color-card) 50%,transparent)}}.bg-card\/60{background-color:#fff9}@supports (color:color-mix(in lab,red,red)){.bg-card\/60{background-color:color-mix(in oklab,var(--color-card) 60%,transparent)}}.bg-card\/90{background-color:#ffffffe6}@supports (color:color-mix(in lab,red,red)){.bg-card\/90{background-color:color-mix(in oklab,var(--color-card) 90%,transparent)}}.bg-emerald-400{background-color:var(--color-emerald-400)}.bg-emerald-500\/20{background-color:#00bb7f33}@supports (color:color-mix(in lab,red,red)){.bg-emerald-500\/20{background-color:color-mix(in oklab,var(--color-emerald-500) 20%,transparent)}}.bg-red-400{background-color:var(--color-red-400)}.bg-red-400\/5{background-color:#ff65680d}@supports (color:color-mix(in lab,red,red)){.bg-red-400\/5{background-color:color-mix(in oklab,var(--color-red-400) 5%,transparent)}}.bg-red-500{background-color:var(--color-red-500)}.bg-red-500\/5{background-color:#fb2c360d}@supports (color:color-mix(in lab,red,red)){.bg-red-500\/5{background-color:color-mix(in oklab,var(--color-red-500) 5%,transparent)}}.bg-red-500\/10{background-color:#fb2c361a}@supports (color:color-mix(in lab,red,red)){.bg-red-500\/10{background-color:color-mix(in oklab,var(--color-red-500) 10%,transparent)}}.bg-red-500\/20{background-color:#fb2c3633}@supports (color:color-mix(in lab,red,red)){.bg-red-500\/20{background-color:color-mix(in oklab,var(--color-red-500) 20%,transparent)}}.bg-red-500\/30{background-color:#fb2c364d}@supports (color:color-mix(in lab,red,red)){.bg-red-500\/30{background-color:color-mix(in oklab,var(--color-red-500) 30%,transparent)}}.bg-sky-400{background-color:var(--color-sky-400)}.bg-sky-500\/5{background-color:#00a5ef0d}@supports (color:color-mix(in lab,red,red)){.bg-sky-500\/5{background-color:color-mix(in oklab,var(--color-sky-500) 5%,transparent)}}.bg-transparent{background-color:#0000}.p-0\.5{padding:calc(var(--spacing) * .5)}.p-1\.5{padding:calc(var(--spacing) * 1.5)}.p-2{padding:calc(var(--spacing) * 2)}.p-3{padding:calc(var(--spacing) * 3)}.p-4{padding:calc(var(--spacing) * 4)}.p-5{padding:calc(var(--spacing) * 5)}.p-6{padding:calc(var(--spacing) * 6)}.p-8{padding:calc(var(--spacing) * 8)}.p-10{padding:calc(var(--spacing) * 10)}.px-1{padding-inline:calc(var(--spacing) * 1)}.px-1\.5{padding-inline:calc(var(--spacing) * 1.5)}.px-2{padding-inline:calc(var(--spacing) * 2)}.px-2\.5{padding-inline:calc(var(--spacing) * 2.5)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-4{padding-inline:calc(var(--spacing) * 4)}.px-6{padding-inline:calc(var(--spacing) * 6)}.py-0\.5{padding-block:calc(var(--spacing) * .5)}.py-1{padding-block:calc(var(--spacing) * 1)}.py-1\.5{padding-block:calc(var(--spacing) * 1.5)}.py-2{padding-block:calc(var(--spacing) * 2)}.py-2\.5{padding-block:calc(var(--spacing) * 2.5)}.py-3{padding-block:calc(var(--spacing) * 3)}.py-4{padding-block:calc(var(--spacing) * 4)}.py-5{padding-block:calc(var(--spacing) * 5)}.py-6{padding-block:calc(var(--spacing) * 6)}.py-7{padding-block:calc(var(--spacing) * 7)}.py-10{padding-block:calc(var(--spacing) * 10)}.py-16{padding-block:calc(var(--spacing) * 16)}.py-20{padding-block:calc(var(--spacing) * 20)}.py-24{padding-block:calc(var(--spacing) * 24)}.pt-1{padding-top:calc(var(--spacing) * 1)}.pt-2{padding-top:calc(var(--spacing) * 2)}.pt-3{padding-top:calc(var(--spacing) * 3)}.pt-4{padding-top:calc(var(--spacing) * 4)}.pt-6{padding-top:calc(var(--spacing) * 6)}.pt-\[10vh\]{padding-top:10vh}.pr-1{padding-right:calc(var(--spacing) * 1)}.pb-1\.5{padding-bottom:calc(var(--spacing) * 1.5)}.pb-2{padding-bottom:calc(var(--spacing) * 2)}.pb-3{padding-bottom:calc(var(--spacing) * 3)}.pb-4{padding-bottom:calc(var(--spacing) * 4)}.pb-16{padding-bottom:calc(var(--spacing) * 16)}.pl-2{padding-left:calc(var(--spacing) * 2)}.pl-5{padding-left:calc(var(--spacing) * 5)}.text-center{text-align:center}.text-left{text-align:left}.text-right{text-align:right}.font-mono{font-family:var(--font-mono)}.font-serif{font-family:var(--font-serif)}.text-2xl{font-size:var(--text-2xl);line-height:var(--tw-leading,var(--text-2xl--line-height))}.text-3xl{font-size:var(--text-3xl);line-height:var(--tw-leading,var(--text-3xl--line-height))}.text-4xl{font-size:var(--text-4xl);line-height:var(--tw-leading,var(--text-4xl--line-height))}.text-5xl{font-size:var(--text-5xl);line-height:var(--tw-leading,var(--text-5xl--line-height))}.text-base{font-size:var(--text-base);line-height:var(--tw-leading,var(--text-base--line-height))}.text-lg{font-size:var(--text-lg);line-height:var(--tw-leading,var(--text-lg--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xl{font-size:var(--text-xl);line-height:var(--tw-leading,var(--text-xl--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.text-\[10px\]{font-size:10px}.text-\[11px\]{font-size:11px}.leading-none{--tw-leading:1;line-height:1}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.tracking-tight{--tw-tracking:var(--tracking-tight);letter-spacing:var(--tracking-tight)}.tracking-wide{--tw-tracking:var(--tracking-wide);letter-spacing:var(--tracking-wide)}.tracking-wider{--tw-tracking:var(--tracking-wider);letter-spacing:var(--tracking-wider)}.break-words{overflow-wrap:break-word}.break-all{word-break:break-all}.text-accent{color:var(--color-accent)}.text-accent\/70{color:#4a7c59b3}@supports (color:color-mix(in lab,red,red)){.text-accent\/70{color:color-mix(in oklab,var(--color-accent) 70%,transparent)}}.text-amber-50{color:var(--color-amber-50)}.text-amber-100{color:var(--color-amber-100)}.text-amber-100\/70{color:#fef3c6b3}@supports (color:color-mix(in lab,red,red)){.text-amber-100\/70{color:color-mix(in oklab,var(--color-amber-100) 70%,transparent)}}.text-amber-100\/90{color:#fef3c6e6}@supports (color:color-mix(in lab,red,red)){.text-amber-100\/90{color:color-mix(in oklab,var(--color-amber-100) 90%,transparent)}}.text-amber-200{color:var(--color-amber-200)}.text-amber-200\/80{color:#fee685cc}@supports (color:color-mix(in lab,red,red)){.text-amber-200\/80{color:color-mix(in oklab,var(--color-amber-200) 80%,transparent)}}.text-amber-300{color:var(--color-amber-300)}.text-amber-500{color:var(--color-amber-500)}.text-amber-700{color:var(--color-amber-700)}.text-emerald-300{color:var(--color-emerald-300)}.text-fg{color:var(--color-fg)}.text-fg-dim{color:var(--color-fg-dim)}.text-fg-muted{color:var(--color-fg-muted)}.text-red-50{color:var(--color-red-50)}.text-red-100{color:var(--color-red-100)}.text-red-200{color:var(--color-red-200)}.text-red-200\/80{color:#ffcacacc}@supports (color:color-mix(in lab,red,red)){.text-red-200\/80{color:color-mix(in oklab,var(--color-red-200) 80%,transparent)}}.text-red-300{color:var(--color-red-300)}.text-red-400{color:var(--color-red-400)}.text-sky-300{color:var(--color-sky-300)}.text-white{color:var(--color-white)}.text-white\/80{color:#fffc}@supports (color:color-mix(in lab,red,red)){.text-white\/80{color:color-mix(in oklab,var(--color-white) 80%,transparent)}}.capitalize{text-transform:capitalize}.lowercase{text-transform:lowercase}.uppercase{text-transform:uppercase}.italic{font-style:italic}.tabular-nums{--tw-numeric-spacing:tabular-nums;font-variant-numeric:var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,)}.underline{text-decoration-line:underline}.decoration-dashed{text-decoration-style:dashed}.underline-offset-4{text-underline-offset:4px}.accent-accent{accent-color:var(--color-accent)}.opacity-40{opacity:.4}.opacity-60{opacity:.6}.shadow{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-lg{--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,#0000001a), 0 4px 6px -4px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-sm{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-xl{--tw-shadow:0 20px 25px -5px var(--tw-shadow-color,#0000001a), 0 8px 10px -6px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.outline{outline-style:var(--tw-outline-style);outline-width:1px}.filter{filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.backdrop-blur{--tw-backdrop-blur:blur(8px);-webkit-backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,)}.transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,content-visibility,overlay,pointer-events;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-\[width\]{transition-property:width;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-transform{transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.select-none{-webkit-user-select:none;user-select:none}.group-open\:rotate-90:is(:where(.group):is([open],:popover-open,:open) *){rotate:90deg}.placeholder\:text-fg-dim::placeholder{color:var(--color-fg-dim)}.backdrop\:bg-black\/40::backdrop{background-color:#0006}@supports (color:color-mix(in lab,red,red)){.backdrop\:bg-black\/40::backdrop{background-color:color-mix(in oklab,var(--color-black) 40%,transparent)}}@media(hover:hover){.hover\:border-accent:hover{border-color:var(--color-accent)}.hover\:border-accent\/50:hover{border-color:#4a7c5980}@supports (color:color-mix(in lab,red,red)){.hover\:border-accent\/50:hover{border-color:color-mix(in oklab,var(--color-accent) 50%,transparent)}}.hover\:border-border:hover{border-color:var(--color-border)}.hover\:border-red-500\/40:hover{border-color:#fb2c3666}@supports (color:color-mix(in lab,red,red)){.hover\:border-red-500\/40:hover{border-color:color-mix(in oklab,var(--color-red-500) 40%,transparent)}}.hover\:bg-accent-hover:hover{background-color:var(--color-accent-hover)}.hover\:bg-accent\/5:hover{background-color:#4a7c590d}@supports (color:color-mix(in lab,red,red)){.hover\:bg-accent\/5:hover{background-color:color-mix(in oklab,var(--color-accent) 5%,transparent)}}.hover\:bg-accent\/10:hover{background-color:#4a7c591a}@supports (color:color-mix(in lab,red,red)){.hover\:bg-accent\/10:hover{background-color:color-mix(in oklab,var(--color-accent) 10%,transparent)}}.hover\:bg-accent\/15:hover{background-color:#4a7c5926}@supports (color:color-mix(in lab,red,red)){.hover\:bg-accent\/15:hover{background-color:color-mix(in oklab,var(--color-accent) 15%,transparent)}}.hover\:bg-accent\/20:hover{background-color:#4a7c5933}@supports (color:color-mix(in lab,red,red)){.hover\:bg-accent\/20:hover{background-color:color-mix(in oklab,var(--color-accent) 20%,transparent)}}.hover\:bg-amber-500\/20:hover{background-color:#f99c0033}@supports (color:color-mix(in lab,red,red)){.hover\:bg-amber-500\/20:hover{background-color:color-mix(in oklab,var(--color-amber-500) 20%,transparent)}}.hover\:bg-amber-500\/50:hover{background-color:#f99c0080}@supports (color:color-mix(in lab,red,red)){.hover\:bg-amber-500\/50:hover{background-color:color-mix(in oklab,var(--color-amber-500) 50%,transparent)}}.hover\:bg-bg:hover{background-color:var(--color-bg)}.hover\:bg-bg\/50:hover{background-color:#faf8f480}@supports (color:color-mix(in lab,red,red)){.hover\:bg-bg\/50:hover{background-color:color-mix(in oklab,var(--color-bg) 50%,transparent)}}.hover\:bg-bg\/60:hover{background-color:#faf8f499}@supports (color:color-mix(in lab,red,red)){.hover\:bg-bg\/60:hover{background-color:color-mix(in oklab,var(--color-bg) 60%,transparent)}}.hover\:bg-card:hover{background-color:var(--color-card)}.hover\:bg-red-500\/10:hover{background-color:#fb2c361a}@supports (color:color-mix(in lab,red,red)){.hover\:bg-red-500\/10:hover{background-color:color-mix(in oklab,var(--color-red-500) 10%,transparent)}}.hover\:bg-red-500\/40:hover{background-color:#fb2c3666}@supports (color:color-mix(in lab,red,red)){.hover\:bg-red-500\/40:hover{background-color:color-mix(in oklab,var(--color-red-500) 40%,transparent)}}.hover\:bg-red-500\/50:hover{background-color:#fb2c3680}@supports (color:color-mix(in lab,red,red)){.hover\:bg-red-500\/50:hover{background-color:color-mix(in oklab,var(--color-red-500) 50%,transparent)}}.hover\:bg-red-600:hover{background-color:var(--color-red-600)}.hover\:text-accent:hover{color:var(--color-accent)}.hover\:text-accent-hover:hover{color:var(--color-accent-hover)}.hover\:text-amber-100:hover{color:var(--color-amber-100)}.hover\:text-fg:hover{color:var(--color-fg)}.hover\:text-red-100:hover{color:var(--color-red-100)}.hover\:text-red-300:hover{color:var(--color-red-300)}.hover\:text-red-400:hover{color:var(--color-red-400)}.hover\:underline:hover{text-decoration-line:underline}}.focus\:border-accent:focus{border-color:var(--color-accent)}.focus\:border-border:focus{border-color:var(--color-border)}.focus\:border-red-400:focus{border-color:var(--color-red-400)}.focus\:bg-bg\/60:focus{background-color:#faf8f499}@supports (color:color-mix(in lab,red,red)){.focus\:bg-bg\/60:focus{background-color:color-mix(in oklab,var(--color-bg) 60%,transparent)}}.focus\:outline-none:focus{--tw-outline-style:none;outline-style:none}.focus-visible\:outline-2:focus-visible{outline-style:var(--tw-outline-style);outline-width:2px}.focus-visible\:outline-accent:focus-visible{outline-color:var(--color-accent)}@media(hover:hover){.enabled\:hover\:text-accent:enabled:hover{color:var(--color-accent)}}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:opacity-40:disabled{opacity:.4}.disabled\:opacity-50:disabled{opacity:.5}.disabled\:opacity-60:disabled{opacity:.6}@media(min-width:40rem){.sm\:inline{display:inline}}@media(min-width:48rem){.md\:sticky{position:sticky}.md\:top-6{top:calc(var(--spacing) * 6)}.md\:mb-6{margin-bottom:calc(var(--spacing) * 6)}.md\:block{display:block}.md\:hidden{display:none}.md\:min-h-0{min-height:calc(var(--spacing) * 0)}.md\:grid-cols-\[14rem_1fr\]{grid-template-columns:14rem 1fr}.md\:flex-row{flex-direction:row}.md\:items-center{align-items:center}.md\:justify-between{justify-content:space-between}:where(.md\:space-y-6>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 6) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 6) * calc(1 - var(--tw-space-y-reverse)))}.md\:self-auto{align-self:auto}.md\:self-start{align-self:flex-start}.md\:p-6{padding:calc(var(--spacing) * 6)}.md\:px-4{padding-inline:calc(var(--spacing) * 4)}.md\:px-6{padding-inline:calc(var(--spacing) * 6)}.md\:py-3{padding-block:calc(var(--spacing) * 3)}.md\:py-8{padding-block:calc(var(--spacing) * 8)}.md\:py-10{padding-block:calc(var(--spacing) * 10)}.md\:py-12{padding-block:calc(var(--spacing) * 12)}.md\:pb-0{padding-bottom:calc(var(--spacing) * 0)}.md\:text-3xl{font-size:var(--text-3xl);line-height:var(--tw-leading,var(--text-3xl--line-height))}}@media(min-width:64rem){.lg\:sticky{position:sticky}.lg\:top-24{top:calc(var(--spacing) * 24)}.lg\:block{display:block}.lg\:flex{display:flex}.lg\:hidden{display:none}.lg\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.lg\:grid-cols-\[minmax\(0\,1fr\)_18rem\]{grid-template-columns:minmax(0,1fr) 18rem}.lg\:self-start{align-self:flex-start}.lg\:px-6{padding-inline:calc(var(--spacing) * 6)}.lg\:py-5{padding-block:calc(var(--spacing) * 5)}.lg\:text-xl{font-size:var(--text-xl);line-height:var(--tw-leading,var(--text-xl--line-height))}}@media(prefers-color-scheme:dark){.dark\:text-amber-300{color:var(--color-amber-300)}}}pre code.hljs{padding:1em;display:block;overflow-x:auto}code.hljs{padding:3px 5px}.hljs{color:#24292e;background:#fff}.hljs-doctag,.hljs-keyword,.hljs-meta .hljs-keyword,.hljs-template-tag,.hljs-template-variable,.hljs-type,.hljs-variable.language_{color:#d73a49}.hljs-title,.hljs-title.class_,.hljs-title.class_.inherited__,.hljs-title.function_{color:#6f42c1}.hljs-attr,.hljs-attribute,.hljs-literal,.hljs-meta,.hljs-number,.hljs-operator,.hljs-variable,.hljs-selector-attr,.hljs-selector-class,.hljs-selector-id{color:#005cc5}.hljs-regexp,.hljs-string,.hljs-meta .hljs-string{color:#032f62}.hljs-built_in,.hljs-symbol{color:#e36209}.hljs-comment,.hljs-code,.hljs-formula{color:#6a737d}.hljs-name,.hljs-quote,.hljs-selector-tag,.hljs-selector-pseudo{color:#22863a}.hljs-subst{color:#24292e}.hljs-section{color:#005cc5;font-weight:700}.hljs-bullet{color:#735c0f}.hljs-emphasis{color:#24292e;font-style:italic}.hljs-strong{color:#24292e;font-weight:700}.hljs-addition{color:#22863a;background-color:#f0fff4}.hljs-deletion{color:#b31d28;background-color:#ffeef0}:root[data-text-size=larger]{--font-size-prose:22px;--font-size-editor:18px;font-size:18px}:root[data-text-size=largest]{--font-size-prose:26px;--font-size-editor:22px;font-size:22px}@media(prefers-color-scheme:dark){:root:not([data-theme=light]){--color-bg:#1a1917;--color-bg-soft:#23221f;--color-fg:#e8e5de;--color-fg-muted:#a8a49b;--color-fg-dim:#706c64;--color-accent:#7ab087;--color-accent-hover:#8bc098;--color-accent-light:#5b8c6a;--color-sky:#7fb3cc;--color-border:#33312d;--color-border-light:#2a2926;--color-card:#23221f;--color-card-hover:#2a2926}}:root[data-theme=dark]{--color-bg:#1a1917;--color-bg-soft:#23221f;--color-fg:#e8e5de;--color-fg-muted:#a8a49b;--color-fg-dim:#706c64;--color-accent:#7ab087;--color-accent-hover:#8bc098;--color-accent-light:#5b8c6a;--color-sky:#7fb3cc;--color-border:#33312d;--color-border-light:#2a2926;--color-card:#23221f;--color-card-hover:#2a2926}html,body{font-family:var(--font-sans);-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;line-height:1.65}body{padding-left:env(safe-area-inset-left);padding-right:env(safe-area-inset-right);padding-bottom:env(safe-area-inset-bottom)}.prose-note{color:var(--color-fg);font-size:var(--font-size-prose);line-height:1.7}.prose-note h1,.prose-note h2,.prose-note h3,.prose-note h4{font-family:var(--font-serif);color:var(--color-fg);letter-spacing:-.015em;margin-top:1.75em;margin-bottom:.5em;line-height:1.25}.prose-note h1{font-size:1.875rem}.prose-note h2{font-size:1.5rem}.prose-note h3{font-size:1.25rem}.prose-note h4{font-size:1.1rem}.prose-note p{margin:.75em 0}.prose-note ul,.prose-note ol{margin:.75em 0;padding-left:1.5rem}.prose-note ul{list-style:outside}.prose-note ol{list-style:decimal}.prose-note li,.prose-note li>p{margin:.25em 0}.prose-note blockquote{border-left:3px solid var(--color-border);color:var(--color-fg-muted);margin:1em 0;padding-left:1rem;font-style:italic}.prose-note code{font-family:var(--font-mono);background:var(--color-bg-soft);border-radius:3px;padding:.1em .35em;font-size:.875em}.prose-note pre{background:var(--color-bg-soft);border:1px solid var(--color-border);border-radius:6px;margin:1em 0;padding:.9rem 1rem;font-size:.875em;line-height:1.5;overflow-x:auto}.prose-note pre code{font-size:inherit;background:0 0;border-radius:0;padding:0}.prose-note table{border-collapse:collapse;width:100%;margin:1em 0;font-size:.9em}.prose-note th,.prose-note td{border:1px solid var(--color-border);text-align:left;padding:.5rem .75rem}.prose-note th{background:var(--color-bg-soft);font-weight:500}.prose-note hr{border:0;border-top:1px solid var(--color-border);margin:1.5em 0}.prose-note img{border-radius:6px;max-width:100%;height:auto}.prose-note input[type=checkbox]{margin-right:.4em}@media(prefers-color-scheme:dark){:root:not([data-theme=light]) .prose-note code,:root:not([data-theme=light]) .prose-note pre{border-color:var(--color-border);background:#1f1e1b}:root:not([data-theme=light]) .prose-note .hljs{color:var(--color-fg);background:#1f1e1b!important}}:root[data-theme=dark] .prose-note code,:root[data-theme=dark] .prose-note pre{border-color:var(--color-border);background:#1f1e1b}:root[data-theme=dark] .prose-note .hljs{color:var(--color-fg);background:#1f1e1b!important}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}@property --tw-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-divide-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-ordinal{syntax:"*";inherits:false}@property --tw-slashed-zero{syntax:"*";inherits:false}@property --tw-numeric-figure{syntax:"*";inherits:false}@property --tw-numeric-spacing{syntax:"*";inherits:false}@property --tw-numeric-fraction{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}@property --tw-backdrop-blur{syntax:"*";inherits:false}@property --tw-backdrop-brightness{syntax:"*";inherits:false}@property --tw-backdrop-contrast{syntax:"*";inherits:false}@property --tw-backdrop-grayscale{syntax:"*";inherits:false}@property --tw-backdrop-hue-rotate{syntax:"*";inherits:false}@property --tw-backdrop-invert{syntax:"*";inherits:false}@property --tw-backdrop-opacity{syntax:"*";inherits:false}@property --tw-backdrop-saturate{syntax:"*";inherits:false}@property --tw-backdrop-sepia{syntax:"*";inherits:false}@keyframes pulse{50%{opacity:.5}} |
| 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-BDPMEkxL.js";import{u as Z,A as G,C as X,a as ee,b as te}from"./useAttachmentUploader-CRSqlwYK.js";import{P as se,D as ne}from"./PinArchiveButtons-DogtDLiB.js";import{b as re,N as ae}from"./NoteRenderer-cz03kLyS.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}; |
| import{aa as P,Q as T,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-BDPMEkxL.js";import{u as U,A as B,C as z,a as H,b as O}from"./useAttachmentUploader-CRSqlwYK.js";import{b as Q,N as W}from"./NoteRenderer-cz03kLyS.js";const Y={content:"",path:"",tags:[],summary:""};function J(){const w=P(t=>t.getActiveVault()),l=T(),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:"Path"}),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}; |
Sorry, the diff of this file is too big to display
| const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/react-force-graph-2d-CokIfB0T.js","assets/index-BDPMEkxL.js","assets/index-D_L2igjK.css"])))=>i.map(i=>d[i]); | ||
| import{x as c,E as v,r as t,Q as k,_ as y,Y as I,aa as R,U as A,w as E,N as C,L as p,V as L,z as j}from"./index-BDPMEkxL.js";import{P as _,D}from"./PinArchiveButtons-DogtDLiB.js";import{b as T,N as U}from"./NoteRenderer-cz03kLyS.js";const M=1,S=3,$=1;function B(e,s){const a=new Map,n=new Map;for(const d of s.values())for(const r of d.links??[]){if(r.sourceId===r.targetId||!s.has(r.sourceId)||!s.has(r.targetId))continue;const o=`${r.sourceId}|${r.targetId}|${r.relationship}`;a.has(o)||(a.set(o,{source:r.sourceId,target:r.targetId,relationship:r.relationship}),n.set(r.sourceId,(n.get(r.sourceId)??0)+1),n.set(r.targetId,(n.get(r.targetId)??0)+1))}return{nodes:[...s.values()].map(d=>{var r;return{id:d.id,path:d.path,tags:d.tags,summary:typeof((r=d.metadata)==null?void 0:r.summary)=="string"?d.metadata.summary:void 0,isAnchor:d.id===e,linkCount:n.get(d.id)??0}}),edges:[...a.values()]}}async function P(e,s,a,n){const i=new Map;i.set(e.id,e);let d=[e];for(let r=1;r<=s;r++){const o=new Set;for(const u of d)for(const x of u.links??[]){const h=x.sourceId===u.id?x.targetId:x.sourceId;h!==u.id&&(i.has(h)||o.add(h))}if(o.size===0)break;const l=await Promise.all([...o].map(u=>a(u).catch(()=>null)));if(n!=null&&n.cancelled)return i;const m=[];for(const u of l)u&&!i.has(u.id)&&(i.set(u.id,u),m.push(u));d=m}return i}function V(e,s,a){const[n,i]=c.useState(null),[d,r]=c.useState(!1);return c.useEffect(()=>{if(!e||!s){i(null),r(!1);return}const o={cancelled:!1};return r(!0),P(s,a,l=>e.getNote(l,{includeLinks:!0}),o).then(l=>{o.cancelled||(i(B(s.id,l)),r(!1))}).catch(()=>{o.cancelled||r(!1)}),()=>{o.cancelled=!0}},[e,s,a]),{data:n,isLoading:d}}const F=c.lazy(()=>y(()=>import("./react-force-graph-2d-CokIfB0T.js"),__vite__mapDeps([0,1,2])));function z({anchor:e}){const[s,a]=c.useState(!0),[n,i]=c.useState($),d=v(),{data:r,isLoading:o}=V(d,s?e:void 0,n);return t.jsxs("section",{className:"mt-10 border-t border-border pt-6",children:[t.jsxs("header",{className:"mb-4 flex flex-wrap items-center justify-between gap-3",children:[t.jsxs("div",{className:"flex items-center gap-3",children:[t.jsxs("button",{type:"button",onClick:()=>a(l=>!l),"aria-expanded":s,className:"font-serif text-xl text-fg hover:text-accent",children:[s?"▾":"▸"," Neighborhood"]}),s&&r?t.jsxs("span",{className:"text-xs text-fg-dim",children:[r.nodes.length," ",r.nodes.length===1?"note":"notes"]}):null]}),s?t.jsx(G,{depth:n,onChange:i}):null]}),s?t.jsx(O,{data:r,isLoading:o}):null]})}function G({depth:e,onChange:s}){const a=[];for(let n=M;n<=S;n++)a.push(n);return t.jsxs("fieldset",{className:"flex items-center gap-1 text-xs text-fg-dim",children:[t.jsx("legend",{className:"mr-1 inline-block",children:"Hops"}),a.map(n=>t.jsx("button",{type:"button","aria-pressed":n===e,onClick:()=>s(n),className:n===e?"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:n},n))]})}function O({data:e,isLoading:s}){return!e&&s?t.jsx(w,{}):e?e.nodes.length<=1?t.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."}):t.jsx(H,{data:e}):null}function w(){return t.jsx("div",{"aria-busy":"true",className:"h-[24rem] w-full animate-pulse rounded-md border border-border bg-card"})}function H({data:e}){const s=k(),a=c.useRef(null),[n,i]=c.useState({w:600,h:384});c.useEffect(()=>{const r=a.current;if(!r)return;const o=()=>{const m=r.getBoundingClientRect();i({w:Math.max(320,Math.floor(m.width)),h:384})};o();const l=new ResizeObserver(o);return l.observe(r),()=>l.disconnect()},[]);const d=c.useMemo(()=>({nodes:e.nodes.map(r=>({...r})),links:e.edges.map(r=>({source:r.source,target:r.target,rel:r.relationship}))}),[e]);return t.jsx("div",{ref:a,"data-testid":"neighborhood-graph-canvas",className:"overflow-hidden rounded-md border border-border bg-card",children:t.jsx(c.Suspense,{fallback:t.jsx(w,{}),children:t.jsx(F,{graphData:d,width:n.w,height:n.h,nodeLabel:r=>K(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(`/n/${encodeURIComponent(r.id)}`)}})})})}function K(e){const s=[e.path??e.id];return e.tags&&e.tags.length>0&&s.push(`tags: ${e.tags.join(", ")}`),e.summary&&s.push(e.summary),s.join(` | ||
| `)}const W="_Transcript pending._",Q="_Transcription unavailable._";function X({content:e}){const s=e.includes(W),a=!s&&e.includes(Q);return s?t.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:[t.jsx("span",{"aria-hidden":!0,className:"inline-block h-2 w-2 animate-pulse rounded-full bg-sky-400"}),"Transcribing…"]}):a?t.jsx("output",{className:"mb-4 inline-flex 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:"Transcription unavailable — open the audio below and add a note by hand."}):null}function ce(){const{id:e}=I(),s=e?decodeURIComponent(e):void 0,a=R(i=>i.getActiveVault()),n=A(s);return c.useEffect(()=>{a&&s&&E(a.id,s)},[a,s]),a?t.jsxs("div",{className:"mx-auto max-w-6xl px-4 py-6 md:px-6 md:py-10",children:[t.jsx("nav",{className:"mb-6 text-sm text-fg-dim",children:t.jsx(p,{to:"/",className:"hover:text-accent",children:"← All notes"})}),n.isPending?t.jsx(ne,{}):n.isError?t.jsx(oe,{error:n.error}):n.data?t.jsx(Y,{note:n.data}):t.jsx(ae,{id:s??""})]}):t.jsx(C,{to:"/",replace:!0})}function Y({note:e}){var r;const s=c.useMemo(()=>T(e),[e]),a=e.path??e.id,n=typeof((r=e.metadata)==null?void 0:r.summary)=="string"?e.metadata.summary:null,i=c.useMemo(()=>(e.links??[]).filter(o=>o.targetId===e.id&&o.sourceId!==e.id&&o.sourceNote),[e]),d=c.useMemo(()=>{const o=new Set,l=[];for(const m of e.links??[])m.sourceId!==e.id||m.targetId===e.id||m.targetNote&&(o.has(m.targetId)||(o.add(m.targetId),l.push(m)));return l},[e]);return t.jsxs("article",{className:"grid gap-10 lg:grid-cols-[minmax(0,1fr)_18rem]",children:[t.jsxs("div",{className:"min-w-0",children:[t.jsxs("header",{className:"mb-6 border-b border-border pb-4",children:[t.jsx("h1",{className:"font-serif text-3xl tracking-tight",children:e.path?q(e.path):e.id}),e.tags&&e.tags.length>0?t.jsx(Z,{tags:e.tags}):null,t.jsx("p",{className:"mt-2 font-mono text-xs text-fg-dim break-all",children:a}),n?t.jsx("p",{className:"mt-3 text-fg-muted",children:n}):null,t.jsxs("div",{className:"mt-4 flex flex-wrap items-center gap-2",children:[t.jsx(p,{to:`/n/${encodeURIComponent(e.id)}/edit`,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:"Edit"}),t.jsx(_,{note:e,keyboard:!0}),t.jsx(D,{note:e})]})]}),t.jsx(X,{content:e.content??""}),t.jsx(U,{note:e,resolve:s}),e.attachments&&e.attachments.length>0?t.jsxs("section",{className:"mt-10 border-t border-border pt-6",children:[t.jsx("h2",{className:"mb-3 font-serif text-xl",children:"Attachments"}),t.jsx("div",{className:"space-y-6",children:e.attachments.map(o=>t.jsx(ee,{attachment:o},o.id))})]}):null,t.jsx(z,{anchor:e})]}),t.jsxs("aside",{className:"space-y-6 text-sm lg:sticky lg:top-24 lg:self-start",children:[t.jsx(J,{note:e}),d.length>0?t.jsx(N,{title:"Outbound",links:d,peer:"target"}):null,i.length>0?t.jsx(N,{title:"Inbound",links:i,peer:"source"}):null]})]})}function q(e){return(e.split("/").pop()??e).replace(/\.md$/i,"")}function J({note:e}){const s=e.createdAt,a=e.updatedAt,n=Object.entries(e.metadata??{}).filter(([i])=>i!=="summary");return t.jsxs("section",{className:"rounded-md border border-border bg-card p-4",children:[t.jsx("h2",{className:"mb-2 text-xs uppercase tracking-wider text-fg-dim",children:"Metadata"}),t.jsxs("dl",{className:"space-y-1.5 text-sm",children:[e.path?t.jsx(f,{label:"Path",value:t.jsx("span",{className:"font-mono text-xs break-all",children:e.path})}):null,t.jsx(f,{label:"ID",value:t.jsx("span",{className:"font-mono text-xs break-all",children:e.id})}),t.jsx(f,{label:"Created",value:t.jsx("time",{title:s,children:j(s)})}),a?t.jsx(f,{label:"Updated",value:t.jsx("time",{title:a,children:j(a)})}):null,n.map(([i,d])=>t.jsx(f,{label:i,value:t.jsx("span",{className:"break-all text-fg-muted",children:String(d)})},i))]})]})}function f({label:e,value:s}){return t.jsxs("div",{className:"flex flex-col gap-0.5",children:[t.jsx("dt",{className:"text-xs uppercase tracking-wider text-fg-dim",children:e}),t.jsx("dd",{children:s})]})}function Z({tags:e}){return t.jsx("div",{className:"mt-3 flex flex-wrap gap-1.5","aria-label":"Tags",children:e.map(s=>t.jsxs(p,{to:`/?tag=${encodeURIComponent(s)}`,className:"max-w-full break-all rounded-full border border-accent/40 bg-accent/10 px-2.5 py-0.5 text-xs font-medium text-accent hover:border-accent hover:bg-accent/20",children:["#",s]},s))})}function N({title:e,links:s,peer:a}){return t.jsxs("section",{className:"rounded-md border border-border bg-card p-4",children:[t.jsxs("h2",{className:"mb-2 text-xs uppercase tracking-wider text-fg-dim",children:[e," (",s.length,")"]}),t.jsx("ul",{className:"space-y-1.5",children:s.map(n=>{var o;const i=a==="source"?n.sourceNote:n.targetNote;if(!i)return null;const d=i.path??i.id,r=typeof((o=i.metadata)==null?void 0:o.summary)=="string"?i.metadata.summary:null;return t.jsx("li",{children:t.jsxs(p,{to:`/n/${encodeURIComponent(i.id)}`,className:"block rounded px-1 py-0.5 hover:bg-bg/50",children:[t.jsx("div",{className:"truncate font-mono text-xs text-fg-muted hover:text-accent",children:d}),r?t.jsx("div",{className:"mt-0.5 line-clamp-2 text-xs text-fg-dim",children:r}):null]})},`${n.sourceId}->${n.targetId}:${n.relationship}`)})})]})}function ee({attachment:e}){const s=(e.mimeType??"").toLowerCase(),a=e.filename??e.id;return t.jsxs("figure",{className:"rounded-md border border-border bg-card p-3",children:[t.jsxs("figcaption",{className:"mb-2 flex items-baseline justify-between gap-3",children:[t.jsx("span",{className:"truncate font-mono text-xs text-fg-muted",children:a}),typeof e.size=="number"?t.jsx("span",{className:"shrink-0 text-xs text-fg-dim",children:re(e.size)}):null]}),t.jsx(te,{attachment:e,mime:s,filename:a})]})}function te({attachment:e,mime:s,filename:a}){const n=v(),[i,d]=c.useState(null),[r,o]=c.useState(null),l=se(s,a),m=l!=="other",u=e.url;if(c.useEffect(()=>{if(!m||!u||!n)return;let h=!1,b=null;return o(null),n.fetchAttachmentBlob(u).then(g=>{h||(b=URL.createObjectURL(g),d(b))}).catch(g=>{h||o(g instanceof Error?g.message:"Failed to load attachment")}),()=>{h=!0,b&&URL.revokeObjectURL(b)}},[m,u,n]),!u)return t.jsx("p",{className:"text-sm text-fg-dim",children:"(no URL)"});if(r)return t.jsx("p",{className:"text-sm text-red-400",children:r});if(m&&!i)return t.jsx("div",{className:"h-32 animate-pulse rounded bg-border/40","aria-busy":"true"});const x=i??u;return l==="image"?t.jsx("img",{src:x,alt:a,className:"max-h-[32rem] rounded"}):l==="audio"?t.jsx("audio",{controls:!0,src:x,className:"w-full"}):l==="video"?t.jsx("video",{controls:!0,src:x,className:"w-full rounded"}):l==="pdf"?t.jsxs(t.Fragment,{children:[t.jsx("iframe",{src:x,title:a,className:"h-[40rem] w-full rounded border border-border"}),t.jsxs("a",{href:x,download:a,className:"mt-2 inline-block text-sm text-accent hover:underline",children:["Download ",a]})]}):t.jsxs("a",{href:x,download:a,className:"text-sm text-accent hover:underline",children:["Download ",a]})}function se(e,s){if(e.startsWith("image/"))return"image";if(e.startsWith("audio/"))return"audio";if(e.startsWith("video/"))return"video";if(e==="application/pdf")return"pdf";const a=s.toLowerCase().split(".").pop()??"";return["png","jpg","jpeg","gif","webp","svg"].includes(a)?"image":["mp3","wav","ogg","m4a","flac"].includes(a)?"audio":["mp4","webm","mov"].includes(a)?"video":a==="pdf"?"pdf":"other"}function re(e){return e<1024?`${e} B`:e<1024*1024?`${(e/1024).toFixed(1)} KB`:e<1024*1024*1024?`${(e/(1024*1024)).toFixed(1)} MB`:`${(e/(1024*1024*1024)).toFixed(2)} GB`}function ne(){return t.jsxs("div",{className:"grid gap-10 lg:grid-cols-[minmax(0,1fr)_18rem]","aria-busy":"true",children:[t.jsxs("div",{className:"min-w-0 space-y-3",children:[t.jsx("div",{className:"h-3 w-32 animate-pulse rounded bg-border/40"}),t.jsx("div",{className:"h-8 w-2/3 animate-pulse rounded bg-border/60"}),t.jsx("div",{className:"h-4 w-full animate-pulse rounded bg-border/30"}),t.jsx("div",{className:"mt-6 space-y-2",children:[0,1,2,3,4,5].map(e=>t.jsx("div",{className:"h-3 animate-pulse rounded bg-border/30",style:{width:`${70+e*13%25}%`}},e))})]}),t.jsxs("div",{className:"space-y-4",children:[t.jsx("div",{className:"h-32 animate-pulse rounded bg-border/30"}),t.jsx("div",{className:"h-24 animate-pulse rounded bg-border/30"})]})]})}function ae({id:e}){return t.jsxs("div",{className:"rounded-md border border-border bg-card p-10 text-center",children:[t.jsx("p",{className:"mb-2 font-serif text-xl",children:"Note not found"}),t.jsxs("p",{className:"mb-4 text-sm text-fg-muted",children:["No note with id ",t.jsx("span",{className:"font-mono",children:e})," in this vault."]}),t.jsx(p,{to:"/",className:"text-sm text-accent hover:underline",children:"Back to all notes"})]})}function oe({error:e}){const s=e instanceof L;return t.jsxs("div",{className:"rounded-md border border-red-500/30 bg-red-500/5 p-6",children:[t.jsx("p",{className:"mb-2 font-medium text-red-400",children:s?"Session expired":"Could not load note"}),t.jsx("p",{className:"mb-4 text-sm text-fg-muted",children:e.message}),s?t.jsx(p,{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{ce as NoteView}; |
| import{a3 as y,Q as j,aa as N,x as l,l as w,B as E,A as V,G as S,b as C,r as e}from"./index-BDPMEkxL.js";function R(){const[a]=y(),s=j(),d=N(c=>c.addVault),[n,o]=l.useState({kind:"working"}),u=l.useRef(!1);return l.useEffect(()=>{if(u.current)return;u.current=!0;const c=a.get("code"),p=a.get("state"),x=a.get("error");if(x){o({kind:"error",message:`Vault returned: ${x}`});return}if(!c||!p){o({kind:"error",message:"Missing code or state in callback URL."});return}(async()=>{var m,h,g,v;try{const{pending:t,token:r}=await w(c,p),f=r.vault?`vault:${r.vault}`:void 0,k=(f?(h=(m=r.services)==null?void 0:m[f])==null?void 0:h.url:void 0)??((v=(g=r.services)==null?void 0:g.vault)==null?void 0:v.url)??t.issuerUrl,i=d({url:k,name:r.vault??t.issuer,issuer:t.issuer,tokenEndpoint:t.tokenEndpoint,clientId:t.clientId,scope:r.scope},E(r));r.services&&V(i,r.services);const b=S.getState();b.clearHalt(i),t.priorHaltedVaultId&&t.priorHaltedVaultId!==i&&b.clearHalt(t.priorHaltedVaultId),s("/",{replace:!0})}catch(t){if(t instanceof C){o({kind:"pending-approval",approveUrl:t.approveUrl});return}o({kind:"error",message:t.message})}})()},[a,s,d]),n.kind==="working"?e.jsxs("div",{className:"mx-auto max-w-xl px-6 py-24 text-center",children:[e.jsx("h1",{className:"mb-3 font-serif text-3xl",children:"Connecting…"}),e.jsx("p",{className:"text-fg-muted",children:"Exchanging the authorization code with your vault."})]}):n.kind==="pending-approval"?e.jsxs("div",{className:"mx-auto max-w-xl px-6 py-24 text-center",children:[e.jsx("h1",{className:"mb-3 font-serif text-3xl",children:"Waiting for hub approval"}),e.jsx("p",{className:"mb-8 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-3",children:[e.jsx("a",{href:n.approveUrl,target:"_blank",rel:"noopener noreferrer",className:"inline-block rounded-md bg-accent px-4 py-2 text-sm text-white hover:bg-accent-hover",children:"Open approval page"}),e.jsx("button",{type:"button",onClick:()=>s("/add",{replace:!0}),className:"inline-block rounded-md border border-border bg-card px-4 py-2 text-sm text-fg-muted hover:text-accent",children:"Retry now"})]})]}):e.jsxs("div",{className:"mx-auto max-w-xl px-6 py-24 text-center",children:[e.jsx("h1",{className:"mb-3 font-serif text-3xl text-red-400",children:"Connection failed"}),e.jsx("p",{className:"mb-8 text-fg-muted",children:n.message}),e.jsx("button",{type:"button",onClick:()=>s("/add",{replace:!0}),className:"rounded-md bg-accent px-4 py-2 text-sm text-white hover:bg-accent-hover",children:"Try again"})]})}export{R as OAuthCallback}; |
| import{x as c,r as t,Q as v,a7 as g,K as w,V as y,aa as j,a5 as E,a8 as N}from"./index-BDPMEkxL.js";function P({note:a,className:i,label:l="Delete"}){const[r,d]=c.useState(!1);return t.jsxs(t.Fragment,{children:[t.jsx("button",{type:"button",onClick:()=>d(!0),className:i??"min-h-11 rounded-md 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:l}),r?t.jsx(k,{note:a,onClose:()=>d(!1)}):null]})}function k({note:a,onClose:i}){const l=v(),r=g(e=>e.push),d=w(),o=a.path??a.id,[m,p]=c.useState(""),[u,b]=c.useState(null),x=c.useRef(null),s=m===o&&!d.isPending;c.useEffect(()=>{var e;(e=x.current)==null||e.focus()},[]),c.useEffect(()=>{const e=f=>{f.key==="Escape"&&i()};return window.addEventListener("keydown",e),()=>window.removeEventListener("keydown",e)},[i]);const n=c.useCallback(()=>{s&&(b(null),d.mutate(a.id,{onSuccess:()=>{r(`Deleted ${o}`,"success"),l("/")},onError:e=>{e instanceof y?b("Session expired. Reconnect to delete."):b(e instanceof Error?e.message:"Delete failed")}}))},[s,o,d,l,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&&i()},children:t.jsxs("div",{className:"w-full max-w-md rounded-md border border-border bg-card p-6 shadow-xl",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:o})," ","to confirm:"]}),t.jsx("input",{ref:x,type:"text",value:m,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-md 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:o,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:i,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"}),t.jsx("button",{type:"button",onClick:n,disabled:!s,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:d.isPending?"Deleting…":"Delete permanently"})]})]})})}function C({note:a,keyboard:i=!1}){var b,x;const l=j(s=>s.getActiveVault()),{roles:r}=E((l==null?void 0:l.id)??null),d=g(s=>s.push),o=N(a.id),m=((b=a.tags)==null?void 0:b.includes(r.pinned))??!1,p=((x=a.tags)==null?void 0:x.includes(r.archived))??!1,u=c.useCallback(s=>{var f;if(o.isPending)return;const n=r[s],e=((f=a.tags)==null?void 0:f.includes(n))??!1;o.mutate({tags:e?{remove:[n]}:{add:[n]}},{onSuccess:()=>{d(s==="pinned"?e?"Unpinned":"Pinned":e?"Unarchived":"Archived","success")},onError:h=>{h instanceof y?d("Session expired. Reconnect.","error"):d(h instanceof Error?h.message:"Update failed","error")}})},[o,a.tags,d,r]);return c.useEffect(()=>{if(!i)return;const s=n=>{if(n.defaultPrevented)return;const e=n.target;if(e){const f=e.tagName;if(f==="INPUT"||f==="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)},[i,u]),t.jsxs(t.Fragment,{children:[t.jsx("button",{type:"button",onClick:()=>u("pinned"),disabled:o.isPending,"aria-pressed":m,title:m?`Unpin (${r.pinned})`:`Pin as #${r.pinned} (P)`,className:m?"min-h-11 rounded-md 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-md border border-border bg-card px-3 py-1.5 text-sm text-fg-muted hover:text-accent disabled:opacity-40",children:m?"★ Pinned":"☆ Pin"}),t.jsx("button",{type:"button",onClick:()=>u("archived"),disabled:o.isPending,"aria-pressed":p,title:p?`Unarchive (${r.archived})`:`Archive as #${r.archived} (A)`,className:p?"min-h-11 rounded-md 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-md 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}; |
Sorry, the diff of this file is too big to display
| import{aa as T,r as e,N as E,L as k,a1 as b,a2 as C,E as A,a7 as S,x as o,y as R,d as D,C as L,Z as _,P as z,a5 as P,a6 as V,T as v,D as j,q as M,o as O,ab as F,i as I}from"./index-BDPMEkxL.js";function K(){const t=T(s=>s.getActiveVault());return t?e.jsxs("div",{className:"mx-auto max-w-2xl px-4 py-7 md:px-6 md:py-12",children:[e.jsxs("header",{className:"mb-8",children:[e.jsx("nav",{className:"mb-3 text-sm text-fg-dim",children:e.jsx(k,{to:"/",className:"hover:text-accent",children:"← Home"})}),e.jsx("h1",{className:"font-serif text-2xl tracking-tight md:text-3xl",children:"Settings"}),e.jsxs("p",{className:"mt-1 text-sm text-fg-muted",children:["Configuring ",e.jsx("span",{className:"text-fg",children:t.name}),"."]})]}),e.jsx($,{vaultId:t.id}),e.jsx(q,{}),e.jsx(U,{vaultId:t.id}),e.jsx(Y,{vaultId:t.id}),e.jsx(G,{})]}):e.jsx(E,{to:"/",replace:!0})}function $({vaultId:t}){const s=b(l=>l.byVault[t]??null),r=b(l=>l.refresh),n=b(l=>l.set),h=C(l=>l.clearDismissed),i=A(),d=S(l=>l.push),[x,u]=o.useState(!1),f=async()=>{i&&await r(t,i)},g=async()=>{var l;if(i){u(!0);try{await O(t,i);const m=(l=s==null?void 0:s.result)==null?void 0:l.rows.map(w=>({...w,status:"ok",differences:[]}));m&&n(t,{ok:!0,missing:[],misaligned:[],rows:m}),h(t),d("Schema updated.","success")}catch(m){d(m instanceof Error?`Schema fix failed: ${m.message}`:"Schema fix failed.","error")}finally{u(!1)}}},p=(s==null?void 0:s.loading)??!s,a=(s==null?void 0:s.result)??null,c=(s==null?void 0:s.error)??null;return e.jsxs("section",{className:"mt-6 space-y-4 rounded-xl border border-border bg-card p-6",children:[e.jsxs("div",{className:"flex items-baseline justify-between gap-3",children:[e.jsxs("div",{children:[e.jsx("h2",{className:"font-serif text-xl text-fg",children:"Vault schema"}),e.jsxs("p",{className:"mt-1 text-xs text-fg-dim",children:["Notes declares three tags it uses to classify captures: ",e.jsx("code",{children:"capture"}),","," ",e.jsx("code",{children:"capture/text"}),", ",e.jsx("code",{children:"capture/voice"}),". This panel confirms the active vault has them set up; one click writes any missing or misaligned rows. Doesn't touch your Tag Role choices below."]})]}),e.jsx("button",{type:"button",onClick:()=>void f(),disabled:p||!i,className:"shrink-0 text-xs text-fg-dim hover:text-accent disabled:cursor-not-allowed disabled:opacity-60",children:p?"Checking…":"Refresh"})]}),c?e.jsxs("p",{className:"rounded-md border border-red-500/30 bg-red-500/5 px-3 py-2 text-xs text-red-300",children:["Audit failed: ",c]}):null,!a&&!c?e.jsx("p",{className:"text-xs text-fg-dim",children:"Loading audit…"}):null,a?e.jsxs(e.Fragment,{children:[e.jsx(H,{ok:a.ok}),e.jsx("ul",{className:"space-y-2",children:a.rows.map(l=>e.jsx(B,{row:l},l.name))}),a.ok?null:e.jsx("button",{type:"button",onClick:()=>void g(),disabled:x||!i,className:"min-h-11 rounded-md bg-accent px-3 py-1.5 text-xs font-medium text-white hover:bg-accent-hover disabled:cursor-not-allowed disabled:opacity-60",children:x?"Setting up…":"Set up missing tags"})]}):null]})}function H({ok:t}){return e.jsxs("p",{className:`inline-flex items-center gap-1.5 rounded-full px-2 py-0.5 text-xs ${t?"bg-emerald-500/20 text-emerald-300":"bg-amber-500/20 text-amber-300"}`,children:[e.jsx("span",{"aria-hidden":!0,className:`h-1.5 w-1.5 rounded-full ${t?"bg-emerald-400":"bg-amber-400"}`}),t?"Matches Notes' schema":"Needs setup"]})}function B({row:t}){const s=t.status==="ok"?"ok":t.status==="missing"?"missing":"misaligned",r=t.status==="ok"?"text-emerald-300":"text-amber-300";return e.jsxs("li",{className:"rounded-md border border-border bg-bg/40 px-3 py-2 text-xs",children:[e.jsxs("div",{className:"flex items-center justify-between gap-2",children:[e.jsx("code",{className:"font-mono text-sm text-fg",children:t.name}),e.jsx("span",{className:`text-xs ${r}`,children:s})]}),t.status==="misaligned"?e.jsxs("p",{className:"mt-1 text-fg-dim",children:["Differs in: ",t.differences.join(", ")]}):null,e.jsx("p",{className:"mt-1 text-fg-dim",children:t.expected.description}),t.expected.parent_names?e.jsxs("p",{className:"text-fg-dim",children:["Parent: ",e.jsx("code",{className:"font-mono",children:t.expected.parent_names.join(", ")})]}):null]})}function q(){const[t,s]=o.useState(()=>R()),r=n=>{s(n),F(n),I(n)};return e.jsxs("section",{className:"mt-6 space-y-4 rounded-xl border border-border bg-card p-6",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-xs text-fg-dim",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"}),D.map(n=>e.jsxs("label",{className:"flex items-start gap-2 text-sm",children:[e.jsx("input",{type:"radio",name:"text-size",value:n,checked:t===n,onChange:()=>r(n),className:"mt-1 accent-accent"}),e.jsx("span",{className:"text-fg",children:L(n)})]},n))]})]})}function G(){const[t,s]=o.useState(!1);return o.useEffect(()=>{s(M())},[]),t?e.jsx("section",{className:"mt-6 rounded-md border border-border bg-card p-4 text-sm",children:e.jsxs("p",{className:"text-fg-muted",children:[e.jsx("span",{className:"mr-2 inline-block rounded-full bg-emerald-500/20 px-2 py-0.5 text-xs font-medium text-emerald-300",children:"Installed"}),"Parachute Notes is running as an installed app on this device."]})}):null}const y={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 U({vaultId:t}){const{mode:s,setMode:r}=_(t);return e.jsxs("section",{className:"mt-6 space-y-4 rounded-xl border border-border bg-card p-6",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-xs text-fg-dim",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"}),z.map(n=>e.jsxs("label",{className:"flex items-start gap-2 text-sm",children:[e.jsx("input",{type:"radio",name:"path-tree-mode",value:n,checked:s===n,onChange:()=>r(n),className:"mt-1 accent-accent"}),e.jsxs("span",{children:[e.jsx("span",{className:"text-fg",children:y[n].title}),e.jsx("span",{className:"ml-2 text-xs text-fg-dim",children:y[n].help})]})]},n))]})]})}const N={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:"Voice capture",help:"Default tag for new voice memos."},captureText:{title:"Text capture",help:"Default tag for quick typed notes."},view:{title:"Saved view",help:"Tag the saved-view notes carry. Used to list them in the notes sidebar."}};function Y({vaultId:t}){const{roles:s,setRoles:r}=P(t),n=V(),h=S(a=>a.push),i=o.useId(),[d,x]=o.useState(s);o.useEffect(()=>x(s),[s]);const u=o.useMemo(()=>{const a=(n.data??[]).map(c=>c.name);return[...new Set(a)].sort((c,l)=>c.localeCompare(l))},[n.data]),f=v.some(a=>d[a].trim()!==s[a]),g=()=>{r(d),h("Tag roles saved.","success")},p=()=>{r(null),x(j),h("Tag roles reset to defaults.","success")};return e.jsxs("section",{className:"mt-6 space-y-4 rounded-xl border border-border bg-card p-6",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-xs text-fg-dim",children:"Point each role at whatever tag your vault already uses. Changes apply to future notes only — existing notes keep their current tags."})]}),e.jsx("datalist",{id:i,children:u.map(a=>e.jsx("option",{value:a},a))}),e.jsx("div",{className:"space-y-3",children:v.map(a=>e.jsxs("label",{className:"block text-sm",children:[e.jsxs("span",{className:"mb-1 flex items-baseline justify-between gap-2",children:[e.jsx("span",{className:"text-fg-muted",children:N[a].title}),e.jsxs("span",{className:"text-xs text-fg-dim",children:["default: #",j[a]]})]}),e.jsx("input",{type:"text",value:d[a],onChange:c=>x(l=>({...l,[a]:c.target.value})),list:i,placeholder:j[a],"aria-label":`${N[a].title} tag role`,spellCheck:!1,autoCapitalize:"none",autoCorrect:"off",className:"w-full 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"}),e.jsx("span",{className:"mt-1 block text-xs text-fg-dim",children:N[a].help})]},a))}),e.jsxs("div",{className:"flex flex-wrap items-center gap-3 pt-2",children:[e.jsx("button",{type:"button",onClick:g,disabled:!f,className:"rounded-md bg-accent px-4 py-2 text-sm font-medium text-white hover:bg-accent-hover disabled:opacity-40",children:"Save"}),e.jsx("button",{type:"button",onClick:p,className:"text-sm text-fg-muted hover:text-accent",children:"Reset to defaults"})]})]})}export{K as Settings}; |
| import{a7 as P,x as l,h as O,V as R,r as e,aa as L,a6 as F,a4 as I,$ as V,a0 as z,O as D,N as B,L as E}from"./index-BDPMEkxL.js";const $=a=>Object.values(a).reduce((n,x)=>n+x,0);function A({mode:a,sources:n,tagOptions:x,onClose:c,onRun:d,onRunMerge:o,pending:i,offline:m}){const p=P(t=>t.push),g=l.useId(),[S,j]=l.useState(a==="rename"?n[0]??"":""),[T,h]=l.useState(null),[u,y]=l.useState(null),[b,N]=l.useState(!1),v=l.useRef(null);l.useEffect(()=>{var t,r;(t=v.current)==null||t.focus(),(r=v.current)==null||r.select()},[]),l.useEffect(()=>{const t=r=>{r.key==="Escape"&&c()};return window.addEventListener("keydown",t),()=>window.removeEventListener("keydown",t)},[c]);const w=S.trim().replace(/^#/,""),f=!i&&!m&&!b&&w.length>0&&!(a==="rename"&&w===n[0]),C=l.useCallback(async()=>{if(f){h(null),y(null);try{const t=await d(w);if("renamed"in t)p(`Renamed on ${t.renamed} note${t.renamed===1?"":"s"}.`,"success");else{const r=$(t.merged);p(`Merged into #${t.target} on ${r} note${r===1?"":"s"}.`,"success")}c()}catch(t){if(t instanceof O&&a==="rename"&&o){y(t.target);return}t instanceof R?h("Session expired. Reconnect to retry."):h(t instanceof Error?t.message:"Operation failed.")}}},[f,w,a,c,d,o,p]),k=l.useCallback(async()=>{if(!(!u||!o)){h(null),N(!0);try{const t=await o(u),r=$(t.merged);p(`Merged into #${t.target} on ${r} note${r===1?"":"s"}.`,"success"),c()}catch(t){t instanceof R?h("Session expired. Reconnect to retry."):h(t instanceof Error?t.message:"Merge failed."),N(!1)}}},[u,c,o,p]),s=a==="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:t=>{t.target===t.currentTarget&&c()},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:"tag-op-title",className:"mb-2 font-serif text-xl text-fg",children:s}),e.jsxs("p",{className:"mb-3 text-sm text-fg-muted",children:[a==="rename"?e.jsxs(e.Fragment,{children:["Rename ",e.jsx(M,{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((t,r)=>e.jsxs("span",{children:[e.jsx(M,{children:t}),r<n.length-1?", ":""]},t))," ","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:a==="rename"?"New tag name":"Target tag"}),e.jsx("input",{ref:v,type:"text",value:S,onChange:t=>{j(t.target.value),u&&y(null)},onKeyDown:t=>{t.key==="Enter"&&f&&C()},list:g,"aria-label":a==="rename"?"New tag name":"Merge target tag",spellCheck:!1,autoCapitalize:"none",autoCorrect:"off",className:"w-full rounded-md 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:g,children:x.map(t=>e.jsx("option",{value:t},t))})]}),m?e.jsx("p",{className:"mb-3 text-sm text-amber-300",children:"Offline — tag operations need a live vault connection."}):null,u?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(M,{children:u})," already exists."]}),e.jsxs("p",{className:"mb-3 text-fg-muted",children:["Merge ",e.jsx(M,{children:n[0]})," into ",e.jsx(M,{children:u})," instead? Notes that carry both end up with one copy."]}),e.jsx("button",{type:"button",onClick:()=>void k(),disabled:b,className:"rounded-md bg-accent px-3 py-1.5 text-xs font-medium text-white hover:bg-accent-hover disabled:opacity-40",children:b?"Merging…":`Merge into #${u}`})]}):null,T?e.jsx("p",{role:"alert",className:"mb-3 text-sm text-red-400",children:T}):null,e.jsxs("div",{className:"flex justify-end gap-2",children:[e.jsx("button",{type:"button",onClick:c,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:()=>void C(),disabled:!f,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",children:i?a==="rename"?"Renaming…":"Merging…":a==="rename"?"Rename":"Merge"})]})]})})}function M({children:a}){return e.jsxs("span",{className:"rounded bg-bg/60 px-1 py-0.5 font-mono text-xs text-fg",children:["#",a]})}function J(){const a=L(s=>s.getActiveVault()),n=F(),{isOnline:x}=I(),{isPinned:c,togglePin:d}=V((a==null?void 0:a.id)??null),[o,i]=l.useState(""),[m,p]=l.useState("count"),[g,S]=l.useState(new Set),[j,T]=l.useState(null),[h,u]=l.useState(!1),y=z(),b=D(),N=l.useMemo(()=>U(n.data??[],o,m),[n.data,o,m]),v=l.useMemo(()=>(n.data??[]).map(s=>s.name),[n.data]),w=s=>{S(t=>{const r=new Set(t);return r.has(s)?r.delete(s):r.add(s),r})},f=()=>S(new Set);if(!a)return e.jsx(B,{to:"/",replace:!0});const C=g.size,k=!x;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-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:"text-xs uppercase tracking-wider text-fg-dim",children:a.name}),e.jsx("h1",{className:"font-serif text-2xl tracking-tight md:text-3xl",children:"Tags"})]}),e.jsxs("button",{type:"button",onClick:()=>p(s=>s==="count"?"alpha":"count"),className:"text-sm text-fg-muted hover:text-accent","aria-label":"Toggle tag sort",children:["Sort: ",m==="count"?"most used":"A–Z"]})]}),e.jsx("input",{type:"search",placeholder:"Filter tags…",value:o,onChange:s=>i(s.target.value),"aria-label":"Filter tags",className:"mb-4 w-full rounded-md border border-border bg-card px-3 py-2 text-sm text-fg focus:border-accent focus:outline-none"}),C>0?e.jsxs("div",{className:"mb-4 flex flex-wrap items-center gap-3 rounded-md border border-accent/30 bg-accent/5 px-3 py-2 text-sm","aria-label":"Tag selection actions",children:[e.jsxs("span",{className:"text-fg-muted",children:[C," selected: ",Array.from(g).join(", ")]}),e.jsx("button",{type:"button",onClick:()=>u(!0),disabled:C<2||k,className:"rounded-md bg-accent px-3 py-1 text-xs font-medium text-white hover:bg-accent-hover disabled:opacity-40",children:"Merge into…"}),e.jsx("button",{type:"button",onClick:f,className:"text-xs text-fg-muted hover:text-accent",children:"Clear"})]}):null,n.isPending?e.jsx(Z,{}):n.isError?e.jsx(q,{error:n.error}):N.length===0?e.jsx(G,{filtering:o.trim().length>0,hasAny:(n.data??[]).length>0}):e.jsx("ul",{className:"divide-y divide-border rounded-md border border-border bg-card","aria-label":"Tag list",children:N.map(s=>e.jsx(K,{tag:s,selected:g.has(s.name),onToggle:()=>w(s.name),onRename:()=>T(s.name),pinned:c(s.name),onTogglePin:()=>d(s.name),offline:k},s.name))}),n.data&&n.data.length>0?e.jsxs("p",{className:"mt-6 text-xs text-fg-dim",children:[N.length," / ",n.data.length," tag",n.data.length===1?"":"s"]}):null,j!==null?e.jsx(A,{mode:"rename",sources:[j],tagOptions:v,onClose:()=>T(null),pending:y.isPending||b.isPending,offline:k,onRun:s=>y.mutateAsync({oldName:j,newName:s}),onRunMerge:s=>b.mutateAsync({sources:[j],target:s})}):null,h?e.jsx(A,{mode:"merge",sources:Array.from(g),tagOptions:v,onClose:()=>u(!1),pending:b.isPending,offline:k,onRun:async s=>{const t=await b.mutateAsync({sources:Array.from(g),target:s});return f(),t}}):null]})}function K({tag:a,selected:n,onToggle:x,onRename:c,pinned:d,onTogglePin:o,offline:i}){return e.jsxs("li",{className:"flex items-center gap-3 px-3 py-2 text-sm",children:[e.jsx("input",{type:"checkbox",checked:n,onChange:x,"aria-label":`Select tag ${a.name}`,className:"accent-accent"}),e.jsxs(E,{to:`/?tag=${encodeURIComponent(a.name)}`,className:"flex flex-1 items-baseline gap-2 text-fg hover:text-accent focus-visible:outline-2 focus-visible:outline-accent",children:[e.jsxs("span",{className:"font-mono",children:["#",a.name]}),e.jsx("span",{className:"text-xs text-fg-dim",children:a.count})]}),e.jsx("button",{type:"button",onClick:o,className:d?"text-xs font-medium text-accent hover:text-accent-hover":"text-xs text-fg-muted hover:text-accent","aria-label":d?`Unpin tag ${a.name}`:`Pin tag ${a.name}`,"aria-pressed":d,title:d?"Pinned to home strip — click to unpin":"Pin to home strip",children:d?"★ Pinned":"☆ Pin"}),e.jsx("button",{type:"button",onClick:c,disabled:i,className:"text-xs text-fg-muted hover:text-accent disabled:opacity-40","aria-label":`Rename tag ${a.name}`,children:"Rename"})]})}function U(a,n,x){const c=n.trim().toLowerCase(),o=[...c?a.filter(i=>i.name.toLowerCase().includes(c)):a];return x==="alpha"?o.sort((i,m)=>i.name.localeCompare(m.name)):o.sort((i,m)=>m.count-i.count||i.name.localeCompare(m.name)),o}function Z(){return e.jsx("div",{className:"divide-y divide-border rounded-md border border-border bg-card","aria-busy":"true",children:[0,1,2,3,4].map(a=>e.jsx("div",{className:"h-10 animate-pulse bg-card/60"},a))})}function q({error:a}){const n=a instanceof R;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 tags"}),e.jsx("p",{className:"mb-4 text-sm text-fg-muted",children:a.message}),n?e.jsx(E,{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 G({filtering:a,hasAny:n}){return a&&n?e.jsx("div",{className:"rounded-md border border-border bg-card p-10 text-center",children:e.jsx("p",{className:"text-fg-muted",children:"No tags match your filter."})}):e.jsxs("div",{className:"rounded-md border border-border bg-card p-10 text-center",children:[e.jsx("p",{className:"mb-3 text-fg-muted",children:"No tags in this vault yet."}),e.jsx(E,{to:"/new",className:"inline-block rounded-md bg-accent px-4 py-2 text-sm font-medium text-white hover:bg-accent-hover",children:"Create a note"})]})}export{J as Tags}; |
| import{aa as w,a3 as $,W as A,x as D,r as e,N as E,L as d,z as C,V as S}from"./index-BDPMEkxL.js";import{e as V,b as N,t as g,f as K,p as f}from"./dates-BGZoWpL2.js";function F(){const a=w(i=>i.getActiveVault()),[s]=$(),t=s.get("date"),u=V(),r=t??u,x=N(r),n=A(),c=D.useMemo(()=>{const i=[],m=[];if(!n.data||!x)return{created:i,edited:m};for(const l of n.data){const b=g(l.createdAt),k=g(l.updatedAt??l.createdAt);b===r&&i.push(l),k===r&&b!==r&&m.push(l)}return{created:i,edited:m}},[n.data,x,r]);if(!a)return e.jsx(E,{to:"/",replace:!0});if(!x)return e.jsxs("div",{className:"mx-auto max-w-3xl px-4 py-6 md:px-6 md:py-10",children:[e.jsxs("p",{className:"text-sm text-red-400",children:["Invalid date in URL: ",r]}),e.jsx(d,{to:"/today",className:"text-sm text-accent hover:underline",children:"Back to today"})]});const o=r===u,p=j(r,-1),h=j(r,1),v=r.slice(0,7);return 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-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:o?"Today":"On"}),e.jsx("h1",{className:"font-serif text-2xl tracking-tight md:text-3xl",children:K(r)})]}),e.jsxs("div",{className:"flex flex-wrap items-center gap-2 text-sm",children:[e.jsxs(d,{to:`/today?date=${p}`,className:"rounded-md border border-border bg-card px-3 py-1.5 text-fg-muted hover:text-accent","aria-label":"Previous day",children:["← ",p]}),o?null:e.jsx(d,{to:"/today",className:"rounded-md border border-border bg-card px-3 py-1.5 text-fg-muted hover:text-accent",children:"Today"}),e.jsxs(d,{to:`/today?date=${h}`,className:"rounded-md border border-border bg-card px-3 py-1.5 text-fg-muted hover:text-accent","aria-label":"Next day",children:[h," →"]}),e.jsx(d,{to:`/calendar?month=${v}`,className:"rounded-md border border-border bg-card px-3 py-1.5 text-fg-muted hover:text-accent",children:"Calendar"}),e.jsx(d,{to:"/capture",className:"rounded-md bg-accent px-3 py-1.5 font-medium text-white hover:bg-accent-hover",children:"+ Capture"})]})]}),n.isPending?e.jsx(L,{}):n.isError?e.jsx(R,{error:n.error}):c.created.length===0&&c.edited.length===0?e.jsx(P,{isToday:o,targetKey:r}):e.jsxs("div",{className:"space-y-8",children:[c.created.length>0?e.jsx(y,{title:o?"Created today":`Created on ${r}`,notes:c.created}):null,c.edited.length>0?e.jsx(y,{title:o?"Edited today":`Edited on ${r}`,notes:c.edited}):null]})]})}function j(a,s){const t=N(a);return t?(t.setDate(t.getDate()+s),`${t.getFullYear()}-${f(t.getMonth()+1)}-${f(t.getDate())}`):a}function y({title:a,notes:s}){return e.jsxs("section",{children:[e.jsxs("h2",{className:"mb-2 text-xs uppercase tracking-wider text-fg-dim",children:[a," (",s.length,")"]}),e.jsx("ol",{className:"divide-y divide-border rounded-md border border-border bg-card",children:s.map(t=>e.jsx("li",{children:e.jsxs(d,{to:`/n/${encodeURIComponent(t.id)}`,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.jsx("span",{className:"truncate font-mono text-sm text-fg",children:t.path??t.id}),e.jsx("span",{className:"shrink-0 text-xs text-fg-dim",children:C(t.updatedAt??t.createdAt)})]}),t.preview?e.jsx("p",{className:"mt-1 truncate text-sm text-fg-muted",children:t.preview}):null]})},t.id))})]})}function P({isToday:a,targetKey: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:a?"Nothing yet today — start capturing.":`Nothing on ${s}.`}),a?e.jsx(d,{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"}):null]})}function L(){return e.jsx("div",{className:"space-y-3","aria-busy":"true",children:[0,1,2,3].map(a=>e.jsx("div",{className:"h-14 animate-pulse rounded-md bg-border/30"},a))})}function R({error:a}){const s=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:s?"Session expired":"Could not load notes"}),e.jsx("p",{className:"mb-4 text-sm text-fg-muted",children:a.message}),s?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{F as Today}; |
Sorry, the diff of this file is too big to display
| const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/react-force-graph-2d-CokIfB0T.js","assets/index-BDPMEkxL.js","assets/index-D_L2igjK.css"])))=>i.map(i=>d[i]); | ||
| import{aa as w,F as N,x as f,r as s,N as k,L as v,Q as C,V as I,_ as M}from"./index-BDPMEkxL.js";const S={search:"",tags:[]};function T(e){const t=new Map;for(const i of e)t.set(i.id,i);const a=new Map,o=new Map;for(const i of e)for(const n of i.links??[]){if(n.sourceId===n.targetId||!t.has(n.sourceId)||!t.has(n.targetId))continue;const c=`${n.sourceId}|${n.targetId}|${n.relationship}`;a.has(c)||(a.set(c,{source:n.sourceId,target:n.targetId,relationship:n.relationship}),o.set(n.sourceId,(o.get(n.sourceId)??0)+1),o.set(n.targetId,(o.get(n.targetId)??0)+1))}return{nodes:e.map(i=>{var c;const n=i.tags??[];return{id:i.id,path:i.path,title:A(i),tags:n,topTag:n[0],degree:o.get(i.id)??0,summary:typeof((c=i.metadata)==null?void 0:c.summary)=="string"?i.metadata.summary:void 0}}),edges:[...a.values()]}}function A(e){return e.path?(e.path.split("/").pop()??e.path).replace(/\.md$/i,""):e.id}function R(e,t){const a=t.search.trim().toLowerCase();return!(a&&![e.path??"",e.title,e.id].join(" ").toLowerCase().includes(a)||t.tags.length>0&&!t.tags.some(d=>e.tags.includes(d)))}function E(e){const t=new Map;for(const a of e)for(const o of a.tags)t.set(o,(t.get(o)??0)+1);return[...t.entries()].sort((a,o)=>o[1]-a[1]||a[0].localeCompare(o[0])).map(([a])=>a)}function F(e){if(!e)return"#8a9a7a";let t=0;for(let o=0;o<e.length;o++)t=t*31+e.charCodeAt(o)&16777215;return`hsl(${t%360}, 40%, 55%)`}const _=f.lazy(()=>M(()=>import("./react-force-graph-2d-CokIfB0T.js"),__vite__mapDeps([0,1,2]))),L=20;function O(){const e=w(c=>c.getActiveVault()),t=N(),[a,o]=f.useState(S),d=f.useMemo(()=>t.data?T(t.data):null,[t.data]),i=f.useMemo(()=>d?E(d.nodes):[],[d]),n=f.useMemo(()=>d?new Set(d.nodes.filter(c=>R(c,a)).map(c=>c.id)):new Set,[d,a]);return e?s.jsxs("div",{className:"flex h-[calc(100dvh-5rem)] flex-col",children:[s.jsx("div",{className:"border-b border-border bg-card/40 px-6 py-3",children:s.jsxs("div",{className:"mx-auto flex max-w-6xl flex-wrap items-center gap-4",children:[s.jsx("input",{type:"search",value:a.search,onChange:c=>o(m=>({...m,search:c.target.value})),placeholder:"Search nodes…","aria-label":"Search graph nodes",className:"min-w-48 rounded-md border border-border bg-card px-3 py-1.5 text-sm text-fg focus:border-accent focus:outline-none"}),s.jsx($,{allTags:i,selected:a.tags,onChange:c=>o(m=>({...m,tags:c}))}),d?s.jsxs("span",{className:"text-xs text-fg-dim",children:[n.size," / ",d.nodes.length," notes"]}):null]})}),s.jsx("div",{className:"min-h-0 flex-1",children:s.jsx(P,{query:t,graph:d,matched:n})})]}):s.jsx(k,{to:"/",replace:!0})}function P({query:e,graph:t,matched:a}){return e.isPending?s.jsx(y,{message:"Loading vault…"}):e.isError?s.jsx(B,{error:e.error}):!t||t.nodes.length===0?s.jsx("div",{className:"flex h-full items-center justify-center p-10",children:s.jsxs("div",{className:"max-w-sm rounded-md border border-border bg-card p-8 text-center",children:[s.jsx("p",{className:"mb-2 font-serif text-xl",children:"No notes yet"}),s.jsx("p",{className:"mb-4 text-sm text-fg-muted",children:"This vault is empty. Start by creating the first note."}),s.jsx(v,{to:"/new",className:"inline-block rounded-md bg-accent px-4 py-2 text-sm font-medium text-white hover:bg-accent-hover",children:"Create a note"})]})}):s.jsx(z,{graph:t,matched:a})}function $({allTags:e,selected:t,onChange:a}){const o=e.slice(0,L);if(o.length===0)return null;const d=i=>a(t.includes(i)?t.filter(n=>n!==i):[...t,i]);return s.jsxs("fieldset",{"aria-label":"Filter by tag",className:"flex flex-wrap items-center gap-1 text-xs text-fg-dim",children:[s.jsx("legend",{className:"mr-1 inline-block",children:"Tags"}),o.map(i=>{const n=t.includes(i);return s.jsx("button",{type:"button","aria-pressed":n,onClick:()=>d(i),className:n?"max-w-full break-all rounded-full border border-accent bg-accent/10 px-2 py-0.5 text-accent":"max-w-full break-all rounded-full border border-border bg-card px-2 py-0.5 hover:text-accent",children:i},i)}),t.length>0?s.jsx("button",{type:"button",onClick:()=>a([]),className:"ml-1 text-xs text-fg-dim hover:text-accent",children:"Clear"}):null]})}function y({message:e}){return s.jsx("div",{"aria-busy":"true",className:"flex h-full animate-pulse items-center justify-center bg-card/30 text-sm text-fg-dim",children:e})}function z({graph:e,matched:t}){const a=C(),o=f.useRef(null),d=f.useRef(null),[i,n]=f.useState({w:800,h:600});f.useEffect(()=>{const r=o.current;if(!r)return;const l=()=>{const u=r.getBoundingClientRect();n({w:Math.max(320,Math.floor(u.width)),h:Math.max(320,Math.floor(u.height))})};l();const h=new ResizeObserver(l);return h.observe(r),()=>h.disconnect()},[]);const c=()=>{var r,l;(l=(r=d.current)==null?void 0:r.zoomToFit)==null||l.call(r,400,40)},m=f.useMemo(()=>({nodes:e.nodes.map(r=>({...r})),links:e.edges.map(r=>({source:r.source,target:r.target,rel:r.relationship}))}),[e]),g=t.size!==e.nodes.length,j=r=>!g||t.has(r)?1:.15;return s.jsxs("div",{ref:o,"data-testid":"vault-graph-canvas",className:"relative h-full w-full touch-none",children:[s.jsx(f.Suspense,{fallback:s.jsx(y,{message:"Rendering graph…"}),children:s.jsx(_,{ref:d,graphData:m,width:i.w,height:i.h,backgroundColor:"rgba(0,0,0,0)",nodeLabel:r=>V(r),nodeRelSize:5,nodeVal:r=>2+Math.min(r.degree,12),nodeColor:r=>{const l=r,h=F(l.topTag);return g&&!t.has(l.id)?G(h):h},nodePointerAreaPaint:(r,l,h)=>{const u=r;if(u.x==null||u.y==null)return;const x=2+Math.min(u.degree,12),p=Math.max(Math.sqrt(x)*5,10);h.fillStyle=l,h.beginPath(),h.arc(u.x,u.y,p,0,2*Math.PI),h.fill()},linkColor:r=>{const l=r,h=b(l.source),u=b(l.target);return g&&(!t.has(h)||!t.has(u))?"rgba(160, 160, 160, 0.08)":"rgba(160, 160, 160, 0.35)"},linkDirectionalArrowLength:2.5,linkDirectionalArrowRelPos:1,cooldownTicks:100,onEngineStop:()=>c(),nodeCanvasObjectMode:()=>"after",nodeCanvasObject:(r,l,h)=>{const u=r;if(u.x==null||u.y==null||j(u.id)<.5)return;const p=10/h;l.font=`${p}px sans-serif`,l.fillStyle="rgba(220, 220, 220, 0.8)",l.textAlign="left",l.textBaseline="middle",l.fillText(u.title,u.x+6,u.y)},onNodeClick:r=>{a(`/n/${encodeURIComponent(r.id)}`)}})}),s.jsx("button",{type:"button",onClick:c,className:"absolute right-3 bottom-3 rounded-md border border-border bg-card/90 px-3 py-1.5 text-xs text-fg-muted shadow-sm backdrop-blur hover:text-accent",children:"Fit to screen"})]})}function V(e){const t=[e.path??e.id,`${e.degree} link${e.degree===1?"":"s"}`];return e.tags.length>0&&t.push(`tags: ${e.tags.join(", ")}`),e.summary&&t.push(e.summary),t.join(` | ||
| `)}function G(e){return e.startsWith("hsl(")?e.replace("hsl(","hsla(").replace(")",", 0.2)"):e}function b(e){return typeof e=="string"?e:e&&typeof e=="object"&&"id"in e?String(e.id):""}function B({error:e}){const t=e instanceof I;return s.jsx("div",{className:"flex h-full items-center justify-center p-10",children:s.jsxs("div",{className:"max-w-md rounded-md border border-red-500/30 bg-red-500/5 p-6",children:[s.jsx("p",{className:"mb-2 font-medium text-red-400",children:t?"Session expired":"Could not load vault"}),s.jsx("p",{className:"mb-4 text-sm text-fg-muted",children:e.message}),t?s.jsx(v,{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{O as VaultGraph}; |
| import{aa as r,r as e,L as i}from"./index-BDPMEkxL.js";function m(c){let s;try{s=new URL(c)}catch{return!1}const a=s.pathname.split("/").filter(Boolean);return!(a.length>=2&&a[0]==="vault")}function u(){const c=r(t=>t.vaults),s=r(t=>t.activeVaultId),a=r(t=>t.removeVault),o=r(t=>t.setActiveVault),l=Object.values(c).sort((t,n)=>t.name.localeCompare(n.name));return e.jsxs("div",{className:"mx-auto max-w-3xl px-6 py-16",children:[e.jsxs("div",{className:"mb-8 flex items-center justify-between",children:[e.jsx("h1",{className:"font-serif text-4xl tracking-tight",children:"Vaults"}),e.jsx(i,{to:"/add",className:"rounded-md bg-accent px-4 py-2 text-sm font-medium text-white hover:bg-accent-hover",children:"Add vault"})]}),l.length===0?e.jsx("p",{className:"text-fg-muted",children:"No vaults connected yet."}):e.jsx("ul",{className:"space-y-3",children:l.map(t=>{const n=t.id===s,d=m(t.url);return e.jsxs("li",{className:"rounded-lg border border-border bg-card p-4",children:[e.jsxs("div",{className:"flex items-center justify-between gap-4",children:[e.jsxs("div",{className:"min-w-0",children:[e.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[e.jsx("span",{className:"font-serif text-lg text-fg",children:t.name}),n?e.jsx("span",{className:"rounded bg-accent/10 px-2 py-0.5 text-xs text-accent",children:"active"}):null,e.jsx("span",{className:"rounded border border-border px-2 py-0.5 text-xs text-fg-dim",children:t.scope}),d?e.jsx("span",{className:"rounded border border-amber-500/40 bg-amber-500/10 px-2 py-0.5 text-xs text-amber-500",children:"needs reconnect"}):null]}),e.jsx("p",{className:"mt-1 truncate font-mono text-xs text-fg-muted",children:t.url})]}),e.jsxs("div",{className:"flex shrink-0 items-center gap-4 text-sm",children:[n?null:e.jsx("button",{type:"button",onClick:()=>o(t.id),className:"text-fg-muted hover:text-accent",children:"Make active"}),e.jsx("button",{type:"button",onClick:()=>{confirm(`Remove ${t.name}? The access token will be deleted.`)&&a(t.id)},className:"text-red-400 hover:text-red-300",children:"Remove"})]})]}),d?e.jsxs("p",{className:"mt-3 rounded border border-amber-500/30 bg-amber-500/5 px-3 py-2 text-xs text-amber-500",children:["Vault now serves under ",e.jsx("code",{children:"/vault/<name>/"}),". This stored URL is from the older scheme and won't reach the new endpoints. Remove this entry and"," ",e.jsx(i,{to:"/add",className:"underline",children:"add it again"})," ","— discovery will pick the right URL automatically."]}):null]},t.id)})})]})}export{u as Vaults}; |
| try{self["workbox:window:7.4.0"]&&_()}catch{}function b(t,r){return new Promise((function(n){var u=new MessageChannel;u.port1.onmessage=function(s){n(s.data)},t.postMessage(r,[u.port2])}))}function P(t,r){(r==null||r>t.length)&&(r=t.length);for(var n=0,u=Array(r);n<r;n++)u[n]=t[n];return u}function j(t,r,n){return r&&(function(u,s){for(var c=0;c<s.length;c++){var o=s[c];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(u,W(o.key),o)}})(t.prototype,r),Object.defineProperty(t,"prototype",{writable:!1}),t}function S(t,r){var n=typeof Symbol<"u"&&t[Symbol.iterator]||t["@@iterator"];if(n)return(n=n.call(t)).next.bind(n);if(Array.isArray(t)||(n=(function(s,c){if(s){if(typeof s=="string")return P(s,c);var o={}.toString.call(s).slice(8,-1);return o==="Object"&&s.constructor&&(o=s.constructor.name),o==="Map"||o==="Set"?Array.from(s):o==="Arguments"||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(o)?P(s,c):void 0}})(t))||r){n&&(t=n);var u=0;return function(){return u>=t.length?{done:!0}:{done:!1,value:t[u++]}}}throw new TypeError(`Invalid attempt to iterate non-iterable instance. | ||
| In order to be iterable, non-array objects must have a [Symbol.iterator]() method.`)}function w(t,r){return w=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(n,u){return n.__proto__=u,n},w(t,r)}function W(t){var r=(function(n,u){if(typeof n!="object"||!n)return n;var s=n[Symbol.toPrimitive];if(s!==void 0){var c=s.call(n,u);if(typeof c!="object")return c;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(n)})(t,"string");return typeof r=="symbol"?r:r+""}try{self["workbox:core:7.4.0"]&&_()}catch{}var m=function(){var t=this;this.promise=new Promise((function(r,n){t.resolve=r,t.reject=n}))};function y(t,r){var n=location.href;return new URL(t,n).href===new URL(r,n).href}var d=function(t,r){this.type=t,Object.assign(this,r)};function l(t,r,n){return t&&t.then||(t=Promise.resolve(t)),r?t.then(r):t}function k(){}var L={type:"SKIP_WAITING"};function E(t,r){return t&&t.then?t.then(k):Promise.resolve()}var O=(function(t){function r(c,o){var e,i;return o===void 0&&(o={}),(e=t.call(this)||this).nn={},e.tn=0,e.rn=new m,e.en=new m,e.on=new m,e.un=0,e.an=new Set,e.cn=function(){var f=e.fn,a=f.installing;e.tn>0||!y(a.scriptURL,e.sn.toString())||performance.now()>e.un+6e4?(e.vn=a,f.removeEventListener("updatefound",e.cn)):(e.hn=a,e.an.add(a),e.rn.resolve(a)),++e.tn,a.addEventListener("statechange",e.ln)},e.ln=function(f){var a=e.fn,v=f.target,h=v.state,p=v===e.vn,g={sw:v,isExternal:p,originalEvent:f};!p&&e.mn&&(g.isUpdate=!0),e.dispatchEvent(new d(h,g)),h==="installed"?e.wn=self.setTimeout((function(){h==="installed"&&a.waiting===v&&e.dispatchEvent(new d("waiting",g))}),200):h==="activating"&&(clearTimeout(e.wn),p||e.en.resolve(v))},e.yn=function(f){var a=e.hn,v=a!==navigator.serviceWorker.controller;e.dispatchEvent(new d("controlling",{isExternal:v,originalEvent:f,sw:a,isUpdate:e.mn})),v||e.on.resolve(a)},e.gn=(i=function(f){var a=f.data,v=f.ports,h=f.source;return l(e.getSW(),(function(){e.an.has(h)&&e.dispatchEvent(new d("message",{data:a,originalEvent:f,ports:v,sw:h}))}))},function(){for(var f=[],a=0;a<arguments.length;a++)f[a]=arguments[a];try{return Promise.resolve(i.apply(this,f))}catch(v){return Promise.reject(v)}}),e.sn=c,e.nn=o,navigator.serviceWorker.addEventListener("message",e.gn),e}var n,u;u=t,(n=r).prototype=Object.create(u.prototype),n.prototype.constructor=n,w(n,u);var s=r.prototype;return s.register=function(c){var o=(c===void 0?{}:c).immediate,e=o!==void 0&&o;try{var i=this;return l((function(f,a){var v=f();return v&&v.then?v.then(a):a(v)})((function(){if(!e&&document.readyState!=="complete")return E(new Promise((function(f){return window.addEventListener("load",f)})))}),(function(){return i.mn=!!navigator.serviceWorker.controller,i.dn=i.pn(),l(i.bn(),(function(f){i.fn=f,i.dn&&(i.hn=i.dn,i.en.resolve(i.dn),i.on.resolve(i.dn),i.dn.addEventListener("statechange",i.ln,{once:!0}));var a=i.fn.waiting;return a&&y(a.scriptURL,i.sn.toString())&&(i.hn=a,Promise.resolve().then((function(){i.dispatchEvent(new d("waiting",{sw:a,wasWaitingBeforeRegister:!0}))})).then((function(){}))),i.hn&&(i.rn.resolve(i.hn),i.an.add(i.hn)),i.fn.addEventListener("updatefound",i.cn),navigator.serviceWorker.addEventListener("controllerchange",i.yn),i.fn}))})))}catch(f){return Promise.reject(f)}},s.update=function(){try{return this.fn?l(E(this.fn.update())):l()}catch(c){return Promise.reject(c)}},s.getSW=function(){return this.hn!==void 0?Promise.resolve(this.hn):this.rn.promise},s.messageSW=function(c){try{return l(this.getSW(),(function(o){return b(o,c)}))}catch(o){return Promise.reject(o)}},s.messageSkipWaiting=function(){this.fn&&this.fn.waiting&&b(this.fn.waiting,L)},s.pn=function(){var c=navigator.serviceWorker.controller;return c&&y(c.scriptURL,this.sn.toString())?c:void 0},s.bn=function(){try{var c=this;return l((function(o,e){try{var i=o()}catch(f){return e(f)}return i&&i.then?i.then(void 0,e):i})((function(){return l(navigator.serviceWorker.register(c.sn,c.nn),(function(o){return c.un=performance.now(),o}))}),(function(o){throw o})))}catch(o){return Promise.reject(o)}},j(r,[{key:"active",get:function(){return this.en.promise}},{key:"controlling",get:function(){return this.on.promise}}])})((function(){function t(){this.Pn=new Map}var r=t.prototype;return r.addEventListener=function(n,u){this.jn(n).add(u)},r.removeEventListener=function(n,u){this.jn(n).delete(u)},r.dispatchEvent=function(n){n.target=this;for(var u,s=S(this.jn(n.type));!(u=s()).done;)(0,u.value)(n)},r.jn=function(n){return this.Pn.has(n)||this.Pn.set(n,new Set),this.Pn.get(n)},t})());export{O as Workbox,d as WorkboxEvent,b as messageSW}; |
| define(["exports"],function(t){"use strict";try{self["workbox:core:7.4.0"]&&_()}catch(t){}const e=(t,...e)=>{let s=t;return e.length>0&&(s+=` :: ${JSON.stringify(e)}`),s};class s extends Error{constructor(t,s){super(e(t,s)),this.name=t,this.details=s}}try{self["workbox:routing:7.4.0"]&&_()}catch(t){}const n=t=>t&&"object"==typeof t?t:{handle:t};class i{constructor(t,e,s="GET"){this.handler=n(e),this.match=t,this.method=s}setCatchHandler(t){this.catchHandler=n(t)}}class r extends i{constructor(t,e,s){super(({url:e})=>{const s=t.exec(e.href);if(s&&(e.origin===location.origin||0===s.index))return s.slice(1)},e,s)}}class a{constructor(){this.t=new Map,this.i=new Map}get routes(){return this.t}addFetchListener(){self.addEventListener("fetch",t=>{const{request:e}=t,s=this.handleRequest({request:e,event:t});s&&t.respondWith(s)})}addCacheListener(){self.addEventListener("message",t=>{if(t.data&&"CACHE_URLS"===t.data.type){const{payload:e}=t.data,s=Promise.all(e.urlsToCache.map(e=>{"string"==typeof e&&(e=[e]);const s=new Request(...e);return this.handleRequest({request:s,event:t})}));t.waitUntil(s),t.ports&&t.ports[0]&&s.then(()=>t.ports[0].postMessage(!0))}})}handleRequest({request:t,event:e}){const s=new URL(t.url,location.href);if(!s.protocol.startsWith("http"))return;const n=s.origin===location.origin,{params:i,route:r}=this.findMatchingRoute({event:e,request:t,sameOrigin:n,url:s});let a=r&&r.handler;const o=t.method;if(!a&&this.i.has(o)&&(a=this.i.get(o)),!a)return;let c;try{c=a.handle({url:s,request:t,event:e,params:i})}catch(t){c=Promise.reject(t)}const h=r&&r.catchHandler;return c instanceof Promise&&(this.o||h)&&(c=c.catch(async n=>{if(h)try{return await h.handle({url:s,request:t,event:e,params:i})}catch(t){t instanceof Error&&(n=t)}if(this.o)return this.o.handle({url:s,request:t,event:e});throw n})),c}findMatchingRoute({url:t,sameOrigin:e,request:s,event:n}){const i=this.t.get(s.method)||[];for(const r of i){let i;const a=r.match({url:t,sameOrigin:e,request:s,event:n});if(a)return i=a,(Array.isArray(i)&&0===i.length||a.constructor===Object&&0===Object.keys(a).length||"boolean"==typeof a)&&(i=void 0),{route:r,params:i}}return{}}setDefaultHandler(t,e="GET"){this.i.set(e,n(t))}setCatchHandler(t){this.o=n(t)}registerRoute(t){this.t.has(t.method)||this.t.set(t.method,[]),this.t.get(t.method).push(t)}unregisterRoute(t){if(!this.t.has(t.method))throw new s("unregister-route-but-not-found-with-method",{method:t.method});const e=this.t.get(t.method).indexOf(t);if(!(e>-1))throw new s("unregister-route-route-not-registered");this.t.get(t.method).splice(e,1)}}let o;const c=()=>(o||(o=new a,o.addFetchListener(),o.addCacheListener()),o);function h(t,e,n){let a;if("string"==typeof t){const s=new URL(t,location.href);a=new i(({url:t})=>t.href===s.href,e,n)}else if(t instanceof RegExp)a=new r(t,e,n);else if("function"==typeof t)a=new i(t,e,n);else{if(!(t instanceof i))throw new s("unsupported-route-type",{moduleName:"workbox-routing",funcName:"registerRoute",paramName:"capture"});a=t}return c().registerRoute(a),a}const u={googleAnalytics:"googleAnalytics",precache:"precache-v2",prefix:"workbox",runtime:"runtime",suffix:"undefined"!=typeof registration?registration.scope:""},l=t=>[u.prefix,t,u.suffix].filter(t=>t&&t.length>0).join("-"),f=t=>t||l(u.precache),w=t=>t||l(u.runtime);function d(t){t.then(()=>{})}const p=new Set;function y(){return y=Object.assign?Object.assign.bind():function(t){for(var e=1;e<arguments.length;e++){var s=arguments[e];for(var n in s)({}).hasOwnProperty.call(s,n)&&(t[n]=s[n])}return t},y.apply(null,arguments)}let m,g;const R=new WeakMap,v=new WeakMap,b=new WeakMap,q=new WeakMap,D=new WeakMap;let U={get(t,e,s){if(t instanceof IDBTransaction){if("done"===e)return v.get(t);if("objectStoreNames"===e)return t.objectStoreNames||b.get(t);if("store"===e)return s.objectStoreNames[1]?void 0:s.objectStore(s.objectStoreNames[0])}return I(t[e])},set:(t,e,s)=>(t[e]=s,!0),has:(t,e)=>t instanceof IDBTransaction&&("done"===e||"store"===e)||e in t};function x(t){return t!==IDBDatabase.prototype.transaction||"objectStoreNames"in IDBTransaction.prototype?(g||(g=[IDBCursor.prototype.advance,IDBCursor.prototype.continue,IDBCursor.prototype.continuePrimaryKey])).includes(t)?function(...e){return t.apply(C(this),e),I(R.get(this))}:function(...e){return I(t.apply(C(this),e))}:function(e,...s){const n=t.call(C(this),e,...s);return b.set(n,e.sort?e.sort():[e]),I(n)}}function L(t){return"function"==typeof t?x(t):(t instanceof IDBTransaction&&function(t){if(v.has(t))return;const e=new Promise((e,s)=>{const n=()=>{t.removeEventListener("complete",i),t.removeEventListener("error",r),t.removeEventListener("abort",r)},i=()=>{e(),n()},r=()=>{s(t.error||new DOMException("AbortError","AbortError")),n()};t.addEventListener("complete",i),t.addEventListener("error",r),t.addEventListener("abort",r)});v.set(t,e)}(t),e=t,(m||(m=[IDBDatabase,IDBObjectStore,IDBIndex,IDBCursor,IDBTransaction])).some(t=>e instanceof t)?new Proxy(t,U):t);var e}function I(t){if(t instanceof IDBRequest)return function(t){const e=new Promise((e,s)=>{const n=()=>{t.removeEventListener("success",i),t.removeEventListener("error",r)},i=()=>{e(I(t.result)),n()},r=()=>{s(t.error),n()};t.addEventListener("success",i),t.addEventListener("error",r)});return e.then(e=>{e instanceof IDBCursor&&R.set(e,t)}).catch(()=>{}),D.set(e,t),e}(t);if(q.has(t))return q.get(t);const e=L(t);return e!==t&&(q.set(t,e),D.set(e,t)),e}const C=t=>D.get(t);const E=["get","getKey","getAll","getAllKeys","count"],N=["put","add","delete","clear"],O=new Map;function B(t,e){if(!(t instanceof IDBDatabase)||e in t||"string"!=typeof e)return;if(O.get(e))return O.get(e);const s=e.replace(/FromIndex$/,""),n=e!==s,i=N.includes(s);if(!(s in(n?IDBIndex:IDBObjectStore).prototype)||!i&&!E.includes(s))return;const r=async function(t,...e){const r=this.transaction(t,i?"readwrite":"readonly");let a=r.store;return n&&(a=a.index(e.shift())),(await Promise.all([a[s](...e),i&&r.done]))[0]};return O.set(e,r),r}U=(t=>y({},t,{get:(e,s,n)=>B(e,s)||t.get(e,s,n),has:(e,s)=>!!B(e,s)||t.has(e,s)}))(U);try{self["workbox:expiration:7.4.0"]&&_()}catch(t){}const k="cache-entries",M=t=>{const e=new URL(t,location.href);return e.hash="",e.href};class T{constructor(t){this.h=null,this.u=t}l(t){const e=t.createObjectStore(k,{keyPath:"id"});e.createIndex("cacheName","cacheName",{unique:!1}),e.createIndex("timestamp","timestamp",{unique:!1})}p(t){this.l(t),this.u&&function(t,{blocked:e}={}){const s=indexedDB.deleteDatabase(t);e&&s.addEventListener("blocked",t=>e(t.oldVersion,t)),I(s).then(()=>{})}(this.u)}async setTimestamp(t,e){const s={url:t=M(t),timestamp:e,cacheName:this.u,id:this.m(t)},n=(await this.getDb()).transaction(k,"readwrite",{durability:"relaxed"});await n.store.put(s),await n.done}async getTimestamp(t){const e=await this.getDb(),s=await e.get(k,this.m(t));return null==s?void 0:s.timestamp}async expireEntries(t,e){const s=await this.getDb();let n=await s.transaction(k).store.index("timestamp").openCursor(null,"prev");const i=[];let r=0;for(;n;){const s=n.value;s.cacheName===this.u&&(t&&s.timestamp<t||e&&r>=e?i.push(n.value):r++),n=await n.continue()}const a=[];for(const t of i)await s.delete(k,t.id),a.push(t.url);return a}m(t){return this.u+"|"+M(t)}async getDb(){return this.h||(this.h=await function(t,e,{blocked:s,upgrade:n,blocking:i,terminated:r}={}){const a=indexedDB.open(t,e),o=I(a);return n&&a.addEventListener("upgradeneeded",t=>{n(I(a.result),t.oldVersion,t.newVersion,I(a.transaction),t)}),s&&a.addEventListener("blocked",t=>s(t.oldVersion,t.newVersion,t)),o.then(t=>{r&&t.addEventListener("close",()=>r()),i&&t.addEventListener("versionchange",t=>i(t.oldVersion,t.newVersion,t))}).catch(()=>{}),o}("workbox-expiration",1,{upgrade:this.p.bind(this)})),this.h}}class j{constructor(t,e={}){this.R=!1,this.v=!1,this.q=e.maxEntries,this.D=e.maxAgeSeconds,this.U=e.matchOptions,this.u=t,this._=new T(t)}async expireEntries(){if(this.R)return void(this.v=!0);this.R=!0;const t=this.D?Date.now()-1e3*this.D:0,e=await this._.expireEntries(t,this.q),s=await self.caches.open(this.u);for(const t of e)await s.delete(t,this.U);this.R=!1,this.v&&(this.v=!1,d(this.expireEntries()))}async updateTimestamp(t){await this._.setTimestamp(t,Date.now())}async isURLExpired(t){if(this.D){const e=await this._.getTimestamp(t),s=Date.now()-1e3*this.D;return void 0===e||e<s}return!1}async delete(){this.v=!1,await this._.expireEntries(1/0)}}try{self["workbox:cacheable-response:7.4.0"]&&_()}catch(t){}class W{constructor(t={}){this.L=t.statuses,this.I=t.headers}isResponseCacheable(t){let e=!0;return this.L&&(e=this.L.includes(t.status)),this.I&&e&&(e=Object.keys(this.I).some(e=>t.headers.get(e)===this.I[e])),e}}try{self["workbox:strategies:7.4.0"]&&_()}catch(t){}const P={cacheWillUpdate:async({response:t})=>200===t.status||0===t.status?t:null};function S(t,e){const s=new URL(t);for(const t of e)s.searchParams.delete(t);return s.href}class K{constructor(){this.promise=new Promise((t,e)=>{this.resolve=t,this.reject=e})}}function A(t){return"string"==typeof t?new Request(t):t}class F{constructor(t,e){this.C={},Object.assign(this,e),this.event=e.event,this.N=t,this.O=new K,this.B=[],this.k=[...t.plugins],this.M=new Map;for(const t of this.k)this.M.set(t,{});this.event.waitUntil(this.O.promise)}async fetch(t){const{event:e}=this;let n=A(t);if("navigate"===n.mode&&e instanceof FetchEvent&&e.preloadResponse){const t=await e.preloadResponse;if(t)return t}const i=this.hasCallback("fetchDidFail")?n.clone():null;try{for(const t of this.iterateCallbacks("requestWillFetch"))n=await t({request:n.clone(),event:e})}catch(t){if(t instanceof Error)throw new s("plugin-error-request-will-fetch",{thrownErrorMessage:t.message})}const r=n.clone();try{let t;t=await fetch(n,"navigate"===n.mode?void 0:this.N.fetchOptions);for(const s of this.iterateCallbacks("fetchDidSucceed"))t=await s({event:e,request:r,response:t});return t}catch(t){throw i&&await this.runCallbacks("fetchDidFail",{error:t,event:e,originalRequest:i.clone(),request:r.clone()}),t}}async fetchAndCachePut(t){const e=await this.fetch(t),s=e.clone();return this.waitUntil(this.cachePut(t,s)),e}async cacheMatch(t){const e=A(t);let s;const{cacheName:n,matchOptions:i}=this.N,r=await this.getCacheKey(e,"read"),a=Object.assign(Object.assign({},i),{cacheName:n});s=await caches.match(r,a);for(const t of this.iterateCallbacks("cachedResponseWillBeUsed"))s=await t({cacheName:n,matchOptions:i,cachedResponse:s,request:r,event:this.event})||void 0;return s}async cachePut(t,e){const n=A(t);var i;await(i=0,new Promise(t=>setTimeout(t,i)));const r=await this.getCacheKey(n,"write");if(!e)throw new s("cache-put-with-no-response",{url:(a=r.url,new URL(String(a),location.href).href.replace(new RegExp(`^${location.origin}`),""))});var a;const o=await this.T(e);if(!o)return!1;const{cacheName:c,matchOptions:h}=this.N,u=await self.caches.open(c),l=this.hasCallback("cacheDidUpdate"),f=l?await async function(t,e,s,n){const i=S(e.url,s);if(e.url===i)return t.match(e,n);const r=Object.assign(Object.assign({},n),{ignoreSearch:!0}),a=await t.keys(e,r);for(const e of a)if(i===S(e.url,s))return t.match(e,n)}(u,r.clone(),["__WB_REVISION__"],h):null;try{await u.put(r,l?o.clone():o)}catch(t){if(t instanceof Error)throw"QuotaExceededError"===t.name&&await async function(){for(const t of p)await t()}(),t}for(const t of this.iterateCallbacks("cacheDidUpdate"))await t({cacheName:c,oldResponse:f,newResponse:o.clone(),request:r,event:this.event});return!0}async getCacheKey(t,e){const s=`${t.url} | ${e}`;if(!this.C[s]){let n=t;for(const t of this.iterateCallbacks("cacheKeyWillBeUsed"))n=A(await t({mode:e,request:n,event:this.event,params:this.params}));this.C[s]=n}return this.C[s]}hasCallback(t){for(const e of this.N.plugins)if(t in e)return!0;return!1}async runCallbacks(t,e){for(const s of this.iterateCallbacks(t))await s(e)}*iterateCallbacks(t){for(const e of this.N.plugins)if("function"==typeof e[t]){const s=this.M.get(e),n=n=>{const i=Object.assign(Object.assign({},n),{state:s});return e[t](i)};yield n}}waitUntil(t){return this.B.push(t),t}async doneWaiting(){for(;this.B.length;){const t=this.B.splice(0),e=(await Promise.allSettled(t)).find(t=>"rejected"===t.status);if(e)throw e.reason}}destroy(){this.O.resolve(null)}async T(t){let e=t,s=!1;for(const t of this.iterateCallbacks("cacheWillUpdate"))if(e=await t({request:this.request,response:e,event:this.event})||void 0,s=!0,!e)break;return s||e&&200!==e.status&&(e=void 0),e}}class H{constructor(t={}){this.cacheName=w(t.cacheName),this.plugins=t.plugins||[],this.fetchOptions=t.fetchOptions,this.matchOptions=t.matchOptions}handle(t){const[e]=this.handleAll(t);return e}handleAll(t){t instanceof FetchEvent&&(t={event:t,request:t.request});const e=t.event,s="string"==typeof t.request?new Request(t.request):t.request,n="params"in t?t.params:void 0,i=new F(this,{event:e,request:s,params:n}),r=this.j(i,s,e);return[r,this.W(r,i,s,e)]}async j(t,e,n){let i;await t.runCallbacks("handlerWillStart",{event:n,request:e});try{if(i=await this.P(e,t),!i||"error"===i.type)throw new s("no-response",{url:e.url})}catch(s){if(s instanceof Error)for(const r of t.iterateCallbacks("handlerDidError"))if(i=await r({error:s,event:n,request:e}),i)break;if(!i)throw s}for(const s of t.iterateCallbacks("handlerWillRespond"))i=await s({event:n,request:e,response:i});return i}async W(t,e,s,n){let i,r;try{i=await t}catch(r){}try{await e.runCallbacks("handlerDidRespond",{event:n,request:s,response:i}),await e.doneWaiting()}catch(t){t instanceof Error&&(r=t)}if(await e.runCallbacks("handlerDidComplete",{event:n,request:s,response:i,error:r}),e.destroy(),r)throw r}}function $(t,e){const s=e();return t.waitUntil(s),s}try{self["workbox:precaching:7.4.0"]&&_()}catch(t){}function G(t){if(!t)throw new s("add-to-cache-list-unexpected-type",{entry:t});if("string"==typeof t){const e=new URL(t,location.href);return{cacheKey:e.href,url:e.href}}const{revision:e,url:n}=t;if(!n)throw new s("add-to-cache-list-unexpected-type",{entry:t});if(!e){const t=new URL(n,location.href);return{cacheKey:t.href,url:t.href}}const i=new URL(n,location.href),r=new URL(n,location.href);return i.searchParams.set("__WB_REVISION__",e),{cacheKey:i.href,url:r.href}}class V{constructor(){this.updatedURLs=[],this.notUpdatedURLs=[],this.handlerWillStart=async({request:t,state:e})=>{e&&(e.originalRequest=t)},this.cachedResponseWillBeUsed=async({event:t,state:e,cachedResponse:s})=>{if("install"===t.type&&e&&e.originalRequest&&e.originalRequest instanceof Request){const t=e.originalRequest.url;s?this.notUpdatedURLs.push(t):this.updatedURLs.push(t)}return s}}}class J{constructor({precacheController:t}){this.cacheKeyWillBeUsed=async({request:t,params:e})=>{const s=(null==e?void 0:e.cacheKey)||this.S.getCacheKeyForURL(t.url);return s?new Request(s,{headers:t.headers}):t},this.S=t}}let Q,z;async function X(t,e){let n=null;if(t.url){n=new URL(t.url).origin}if(n!==self.location.origin)throw new s("cross-origin-copy-response",{origin:n});const i=t.clone(),r={headers:new Headers(i.headers),status:i.status,statusText:i.statusText},a=function(){if(void 0===Q){const t=new Response("");if("body"in t)try{new Response(t.body),Q=!0}catch(t){Q=!1}Q=!1}return Q}()?i.body:await i.blob();return new Response(a,r)}class Y extends H{constructor(t={}){t.cacheName=f(t.cacheName),super(t),this.K=!1!==t.fallbackToNetwork,this.plugins.push(Y.copyRedirectedCacheableResponsesPlugin)}async P(t,e){const s=await e.cacheMatch(t);return s||(e.event&&"install"===e.event.type?await this.A(t,e):await this.F(t,e))}async F(t,e){let n;const i=e.params||{};if(!this.K)throw new s("missing-precache-entry",{cacheName:this.cacheName,url:t.url});{const s=i.integrity,r=t.integrity,a=!r||r===s;n=await e.fetch(new Request(t,{integrity:"no-cors"!==t.mode?r||s:void 0})),s&&a&&"no-cors"!==t.mode&&(this.H(),await e.cachePut(t,n.clone()))}return n}async A(t,e){this.H();const n=await e.fetch(t);if(!await e.cachePut(t,n.clone()))throw new s("bad-precaching-response",{url:t.url,status:n.status});return n}H(){let t=null,e=0;for(const[s,n]of this.plugins.entries())n!==Y.copyRedirectedCacheableResponsesPlugin&&(n===Y.defaultPrecacheCacheabilityPlugin&&(t=s),n.cacheWillUpdate&&e++);0===e?this.plugins.push(Y.defaultPrecacheCacheabilityPlugin):e>1&&null!==t&&this.plugins.splice(t,1)}}Y.defaultPrecacheCacheabilityPlugin={cacheWillUpdate:async({response:t})=>!t||t.status>=400?null:t},Y.copyRedirectedCacheableResponsesPlugin={cacheWillUpdate:async({response:t})=>t.redirected?await X(t):t};class Z{constructor({cacheName:t,plugins:e=[],fallbackToNetwork:s=!0}={}){this.$=new Map,this.G=new Map,this.V=new Map,this.N=new Y({cacheName:f(t),plugins:[...e,new J({precacheController:this})],fallbackToNetwork:s}),this.install=this.install.bind(this),this.activate=this.activate.bind(this)}get strategy(){return this.N}precache(t){this.addToCacheList(t),this.J||(self.addEventListener("install",this.install),self.addEventListener("activate",this.activate),this.J=!0)}addToCacheList(t){const e=[];for(const n of t){"string"==typeof n?e.push(n):n&&void 0===n.revision&&e.push(n.url);const{cacheKey:t,url:i}=G(n),r="string"!=typeof n&&n.revision?"reload":"default";if(this.$.has(i)&&this.$.get(i)!==t)throw new s("add-to-cache-list-conflicting-entries",{firstEntry:this.$.get(i),secondEntry:t});if("string"!=typeof n&&n.integrity){if(this.V.has(t)&&this.V.get(t)!==n.integrity)throw new s("add-to-cache-list-conflicting-integrities",{url:i});this.V.set(t,n.integrity)}if(this.$.set(i,t),this.G.set(i,r),e.length>0){const t=`Workbox is precaching URLs without revision info: ${e.join(", ")}\nThis is generally NOT safe. Learn more at https://bit.ly/wb-precache`;console.warn(t)}}}install(t){return $(t,async()=>{const e=new V;this.strategy.plugins.push(e);for(const[e,s]of this.$){const n=this.V.get(s),i=this.G.get(e),r=new Request(e,{integrity:n,cache:i,credentials:"same-origin"});await Promise.all(this.strategy.handleAll({params:{cacheKey:s},request:r,event:t}))}const{updatedURLs:s,notUpdatedURLs:n}=e;return{updatedURLs:s,notUpdatedURLs:n}})}activate(t){return $(t,async()=>{const t=await self.caches.open(this.strategy.cacheName),e=await t.keys(),s=new Set(this.$.values()),n=[];for(const i of e)s.has(i.url)||(await t.delete(i),n.push(i.url));return{deletedURLs:n}})}getURLsToCacheKeys(){return this.$}getCachedURLs(){return[...this.$.keys()]}getCacheKeyForURL(t){const e=new URL(t,location.href);return this.$.get(e.href)}getIntegrityForCacheKey(t){return this.V.get(t)}async matchPrecache(t){const e=t instanceof Request?t.url:t,s=this.getCacheKeyForURL(e);if(s){return(await self.caches.open(this.strategy.cacheName)).match(s)}}createHandlerBoundToURL(t){const e=this.getCacheKeyForURL(t);if(!e)throw new s("non-precached-url",{url:t});return s=>(s.request=new Request(t),s.params=Object.assign({cacheKey:e},s.params),this.strategy.handle(s))}}const tt=()=>(z||(z=new Z),z);class et extends i{constructor(t,e){super(({request:s})=>{const n=t.getURLsToCacheKeys();for(const i of function*(t,{ignoreURLParametersMatching:e=[/^utm_/,/^fbclid$/],directoryIndex:s="index.html",cleanURLs:n=!0,urlManipulation:i}={}){const r=new URL(t,location.href);r.hash="",yield r.href;const a=function(t,e=[]){for(const s of[...t.searchParams.keys()])e.some(t=>t.test(s))&&t.searchParams.delete(s);return t}(r,e);if(yield a.href,s&&a.pathname.endsWith("/")){const t=new URL(a.href);t.pathname+=s,yield t.href}if(n){const t=new URL(a.href);t.pathname+=".html",yield t.href}if(i){const t=i({url:r});for(const e of t)yield e.href}}(s.url,e)){const e=n.get(i);if(e){return{cacheKey:e,integrity:t.getIntegrityForCacheKey(e)}}}},t.strategy)}}t.CacheableResponsePlugin=class{constructor(t){this.cacheWillUpdate=async({response:t})=>this.X.isResponseCacheable(t)?t:null,this.X=new W(t)}},t.ExpirationPlugin=class{constructor(t={}){this.cachedResponseWillBeUsed=async({event:t,request:e,cacheName:s,cachedResponse:n})=>{if(!n)return null;const i=this.Y(n),r=this.Z(s);d(r.expireEntries());const a=r.updateTimestamp(e.url);if(t)try{t.waitUntil(a)}catch(t){}return i?n:null},this.cacheDidUpdate=async({cacheName:t,request:e})=>{const s=this.Z(t);await s.updateTimestamp(e.url),await s.expireEntries()},this.tt=t,this.D=t.maxAgeSeconds,this.et=new Map,t.purgeOnQuotaError&&function(t){p.add(t)}(()=>this.deleteCacheAndMetadata())}Z(t){if(t===w())throw new s("expire-custom-caches-only");let e=this.et.get(t);return e||(e=new j(t,this.tt),this.et.set(t,e)),e}Y(t){if(!this.D)return!0;const e=this.st(t);if(null===e)return!0;return e>=Date.now()-1e3*this.D}st(t){if(!t.headers.has("date"))return null;const e=t.headers.get("date"),s=new Date(e).getTime();return isNaN(s)?null:s}async deleteCacheAndMetadata(){for(const[t,e]of this.et)await self.caches.delete(t),await e.delete();this.et=new Map}},t.NavigationRoute=class extends i{constructor(t,{allowlist:e=[/./],denylist:s=[]}={}){super(t=>this.nt(t),t),this.it=e,this.rt=s}nt({url:t,request:e}){if(e&&"navigate"!==e.mode)return!1;const s=t.pathname+t.search;for(const t of this.rt)if(t.test(s))return!1;return!!this.it.some(t=>t.test(s))}},t.StaleWhileRevalidate=class extends H{constructor(t={}){super(t),this.plugins.some(t=>"cacheWillUpdate"in t)||this.plugins.unshift(P)}async P(t,e){const n=e.fetchAndCachePut(t).catch(()=>{});e.waitUntil(n);let i,r=await e.cacheMatch(t);if(r);else try{r=await n}catch(t){t instanceof Error&&(i=t)}if(!r)throw new s("no-response",{url:t.url,error:i});return r}},t.cleanupOutdatedCaches=function(){self.addEventListener("activate",t=>{const e=f();t.waitUntil((async(t,e="-precache-")=>{const s=(await self.caches.keys()).filter(s=>s.includes(e)&&s.includes(self.registration.scope)&&s!==t);return await Promise.all(s.map(t=>self.caches.delete(t))),s})(e).then(t=>{}))})},t.createHandlerBoundToURL=function(t){return tt().createHandlerBoundToURL(t)},t.precacheAndRoute=function(t,e){!function(t){tt().precache(t)}(t),function(t){const e=tt();h(new et(e,t))}(e)},t.registerRoute=h}); |
+2
-2
@@ -22,4 +22,4 @@ <!doctype html> | ||
| </script> | ||
| <script type="module" crossorigin src="/notes/assets/index-DKKYWfqC.js"></script> | ||
| <link rel="stylesheet" crossorigin href="/notes/assets/index-BU6cVU21.css"> | ||
| <script type="module" crossorigin src="/notes/assets/index-BDPMEkxL.js"></script> | ||
| <link rel="stylesheet" crossorigin href="/notes/assets/index-D_L2igjK.css"> | ||
| <link rel="manifest" href="/notes/manifest.webmanifest"></head> | ||
@@ -26,0 +26,0 @@ <body> |
+1
-1
@@ -1,1 +0,1 @@ | ||
| if(!self.define){let e,s={};const i=(i,n)=>(i=new URL(i+".js",n).href,s[i]||new Promise(s=>{if("document"in self){const e=document.createElement("script");e.src=i,e.onload=s,document.head.appendChild(e)}else e=i,importScripts(i),s()}).then(()=>{let e=s[i];if(!e)throw new Error(`Module ${i} didn’t register its module`);return e}));self.define=(n,l)=>{const r=e||("document"in self?document.currentScript.src:"")||location.href;if(s[r])return;let a={};const o=e=>i(e,r),t={module:{uri:r},exports:a,require:o};s[r]=Promise.all(n.map(e=>t[e]||o(e))).then(e=>(l(...e),a))}}define(["./workbox-d24cdb67"],function(e){"use strict";self.addEventListener("message",e=>{e.data&&"SKIP_WAITING"===e.data.type&&self.skipWaiting()}),e.precacheAndRoute([{url:"pwa-64x64.png",revision:"52bb73fe0f7c4274aa55047dc0d5479d"},{url:"pwa-512x512.png",revision:"ebdabf19d41be24e3f47062e89399c09"},{url:"pwa-192x192.png",revision:"ec3f52a07bade7b8a295997c236dac75"},{url:"maskable-icon-512x512.png",revision:"e0d671a48eed68b28f8e7ded8a86ef88"},{url:"manifest.webmanifest",revision:"4e69789fa00f6df17850c3426d2041a9"},{url:"index.html",revision:"64fa908326b71b0a23b8793334255ad8"},{url:"icon.svg",revision:"899549fbb9d379c3b78ab012abe72061"},{url:"favicon.ico",revision:"01d978be2c7b93a7348d91107b5bf8ad"},{url:"apple-touch-icon-180x180.png",revision:"dd71bb172b849f6328130ba825ae606d"},{url:"assets/workbox-window.prod.es5-BIl4cyR9.js",revision:null},{url:"assets/useAttachmentUploader-vNDFzDKT.js",revision:null},{url:"assets/react-force-graph-2d-YVoN3oXw.js",revision:null},{url:"assets/index-DKKYWfqC.js",revision:null},{url:"assets/index-BU6cVU21.css",revision:null},{url:"assets/dates-DfXc2iZW.js",revision:null},{url:"assets/Vaults-5R2-DK5a.js",revision:null},{url:"assets/VaultGraph-DqP0DsuL.js",revision:null},{url:"assets/Today-C2Kb8hh1.js",revision:null},{url:"assets/Tags-6zA2UpSB.js",revision:null},{url:"assets/Settings-BSqpi3KX.js",revision:null},{url:"assets/PinArchiveButtons-CCZolBUN.js",revision:null},{url:"assets/OAuthCallback-CdZpQ983.js",revision:null},{url:"assets/NoteView-BRQa1cQ-.js",revision:null},{url:"assets/NoteRenderer-BuDmZBkP.js",revision:null},{url:"assets/NoteNew-BQJfAS3F.js",revision:null},{url:"assets/NoteEditor-DABNXYJR.js",revision:null},{url:"assets/Capture-ClHlAbHb.js",revision:null},{url:"assets/Calendar-Bbh8ywV0.js",revision:null},{url:"assets/AddVault-CE0_abUh.js",revision:null},{url:"assets/Activity-DEE2UNMC.js",revision:null},{url:"apple-touch-icon-180x180.png",revision:"dd71bb172b849f6328130ba825ae606d"},{url:"favicon.ico",revision:"01d978be2c7b93a7348d91107b5bf8ad"},{url:"icon.svg",revision:"899549fbb9d379c3b78ab012abe72061"},{url:"maskable-icon-512x512.png",revision:"e0d671a48eed68b28f8e7ded8a86ef88"},{url:"pwa-192x192.png",revision:"ec3f52a07bade7b8a295997c236dac75"},{url:"pwa-512x512.png",revision:"ebdabf19d41be24e3f47062e89399c09"},{url:"pwa-64x64.png",revision:"52bb73fe0f7c4274aa55047dc0d5479d"},{url:"manifest.webmanifest",revision:"4e69789fa00f6df17850c3426d2041a9"}],{}),e.cleanupOutdatedCaches(),e.registerRoute(new e.NavigationRoute(e.createHandlerBoundToURL("/notes/index.html"),{denylist:[/^\/api\//,/^\/oauth\//,/^\/\.well-known\//]})),e.registerRoute(/^https:\/\/fonts\.(googleapis|gstatic)\.com\/.*/i,new e.StaleWhileRevalidate({cacheName:"google-fonts",plugins:[new e.ExpirationPlugin({maxEntries:30,maxAgeSeconds:2592e3}),new e.CacheableResponsePlugin({statuses:[0,200]})]}),"GET")}); | ||
| if(!self.define){let e,s={};const i=(i,n)=>(i=new URL(i+".js",n).href,s[i]||new Promise(s=>{if("document"in self){const e=document.createElement("script");e.src=i,e.onload=s,document.head.appendChild(e)}else e=i,importScripts(i),s()}).then(()=>{let e=s[i];if(!e)throw new Error(`Module ${i} didn’t register its module`);return e}));self.define=(n,l)=>{const r=e||("document"in self?document.currentScript.src:"")||location.href;if(s[r])return;let a={};const o=e=>i(e,r),t={module:{uri:r},exports:a,require:o};s[r]=Promise.all(n.map(e=>t[e]||o(e))).then(e=>(l(...e),a))}}define(["./workbox-b9acee4e"],function(e){"use strict";self.addEventListener("message",e=>{e.data&&"SKIP_WAITING"===e.data.type&&self.skipWaiting()}),e.precacheAndRoute([{url:"pwa-64x64.png",revision:"52bb73fe0f7c4274aa55047dc0d5479d"},{url:"pwa-512x512.png",revision:"ebdabf19d41be24e3f47062e89399c09"},{url:"pwa-192x192.png",revision:"ec3f52a07bade7b8a295997c236dac75"},{url:"maskable-icon-512x512.png",revision:"e0d671a48eed68b28f8e7ded8a86ef88"},{url:"manifest.webmanifest",revision:"4e69789fa00f6df17850c3426d2041a9"},{url:"index.html",revision:"d074b242ddc4950517bca2c97eabb6b5"},{url:"icon.svg",revision:"899549fbb9d379c3b78ab012abe72061"},{url:"favicon.ico",revision:"01d978be2c7b93a7348d91107b5bf8ad"},{url:"apple-touch-icon-180x180.png",revision:"dd71bb172b849f6328130ba825ae606d"},{url:"assets/workbox-window.prod.es5-BBnX5xw4.js",revision:null},{url:"assets/useAttachmentUploader-CRSqlwYK.js",revision:null},{url:"assets/react-force-graph-2d-CokIfB0T.js",revision:null},{url:"assets/index-D_L2igjK.css",revision:null},{url:"assets/index-BDPMEkxL.js",revision:null},{url:"assets/dates-BGZoWpL2.js",revision:null},{url:"assets/Vaults-GFmUZ3tT.js",revision:null},{url:"assets/VaultGraph-9bEHl7fl.js",revision:null},{url:"assets/Today-Co3rl2Tl.js",revision:null},{url:"assets/Tags-C2seZlc0.js",revision:null},{url:"assets/Settings-DpNYPt6E.js",revision:null},{url:"assets/PinArchiveButtons-DogtDLiB.js",revision:null},{url:"assets/OAuthCallback-CHpF2exs.js",revision:null},{url:"assets/NoteView-B8BN-Dm4.js",revision:null},{url:"assets/NoteRenderer-cz03kLyS.js",revision:null},{url:"assets/NoteNew-CTTJ_2cU.js",revision:null},{url:"assets/NoteEditor-CxoH85Is.js",revision:null},{url:"assets/Capture-C_s94G98.js",revision:null},{url:"assets/Calendar-Dgd0dTEM.js",revision:null},{url:"assets/AddVault-DA_s9Ua2.js",revision:null},{url:"assets/Activity-B6k-9wWy.js",revision:null},{url:"apple-touch-icon-180x180.png",revision:"dd71bb172b849f6328130ba825ae606d"},{url:"favicon.ico",revision:"01d978be2c7b93a7348d91107b5bf8ad"},{url:"icon.svg",revision:"899549fbb9d379c3b78ab012abe72061"},{url:"maskable-icon-512x512.png",revision:"e0d671a48eed68b28f8e7ded8a86ef88"},{url:"pwa-192x192.png",revision:"ec3f52a07bade7b8a295997c236dac75"},{url:"pwa-512x512.png",revision:"ebdabf19d41be24e3f47062e89399c09"},{url:"pwa-64x64.png",revision:"52bb73fe0f7c4274aa55047dc0d5479d"},{url:"manifest.webmanifest",revision:"4e69789fa00f6df17850c3426d2041a9"}],{}),e.cleanupOutdatedCaches(),e.registerRoute(new e.NavigationRoute(e.createHandlerBoundToURL("/notes/index.html"),{denylist:[/^\/api\//,/^\/oauth\//,/^\/\.well-known\//]})),e.registerRoute(/^https:\/\/fonts\.(googleapis|gstatic)\.com\/.*/i,new e.StaleWhileRevalidate({cacheName:"google-fonts",plugins:[new e.ExpirationPlugin({maxEntries:30,maxAgeSeconds:2592e3}),new e.CacheableResponsePlugin({statuses:[0,200]})]}),"GET")}); |
+8
-51
| { | ||
| "name": "@openparachute/notes", | ||
| "version": "0.3.16-rc.6", | ||
| "version": "0.3.17-rc.2", | ||
| "private": false, | ||
@@ -8,60 +8,17 @@ "type": "module", | ||
| "license": "AGPL-3.0-only", | ||
| "deprecated": "@openparachute/notes is deprecated. Use @openparachute/app + @openparachute/notes-ui via parachute-app. See https://github.com/ParachuteComputer/parachute-notes/blob/main/packages/notes-daemon/DEPRECATED.md", | ||
| "repository": { | ||
| "type": "git", | ||
| "url": "https://github.com/ParachuteComputer/parachute-notes.git" | ||
| "url": "https://github.com/ParachuteComputer/parachute-notes.git", | ||
| "directory": "packages/notes-daemon" | ||
| }, | ||
| "files": ["dist", ".parachute/module.json", "README.md", "LICENSE"], | ||
| "files": ["dist", ".parachute/module.json", "README.md", "LICENSE", "CHANGELOG.md", "DEPRECATED.md"], | ||
| "scripts": { | ||
| "dev": "vite", | ||
| "build": "tsc -b && vite build", | ||
| "preview": "vite preview", | ||
| "test": "vitest run", | ||
| "test:watch": "vitest", | ||
| "lint": "biome check .", | ||
| "lint:fix": "biome check --write .", | ||
| "format": "biome format --write .", | ||
| "typecheck": "tsc -b --noEmit", | ||
| "build": "node scripts/build.mjs", | ||
| "test": "node scripts/build.test.mjs", | ||
| "prepublishOnly": "bun run build" | ||
| }, | ||
| "dependencies": { | ||
| "@codemirror/commands": "^6.10.3", | ||
| "@codemirror/lang-markdown": "^6.5.0", | ||
| "@codemirror/language": "^6.12.3", | ||
| "@codemirror/state": "^6.6.0", | ||
| "@codemirror/view": "^6.41.1", | ||
| "@tanstack/react-query": "^5", | ||
| "highlight.js": "^11.11.1", | ||
| "idb": "^8.0.3", | ||
| "react": "^19.1.0", | ||
| "react-dom": "^19.1.0", | ||
| "react-force-graph-2d": "^1.29.1", | ||
| "react-markdown": "^10.1.0", | ||
| "react-router": "^7", | ||
| "rehype-highlight": "^7.0.2", | ||
| "remark-gfm": "^4.0.1", | ||
| "zustand": "^5" | ||
| }, | ||
| "devDependencies": { | ||
| "@biomejs/biome": "^1.9.4", | ||
| "@tailwindcss/vite": "^4.1.0", | ||
| "@testing-library/dom": "^10.4.0", | ||
| "@testing-library/jest-dom": "^6.6.3", | ||
| "@testing-library/react": "^16.1.0", | ||
| "@types/node": "^22", | ||
| "@types/react": "^19.1.0", | ||
| "@types/react-dom": "^19.1.0", | ||
| "@vite-pwa/assets-generator": "^1.0.2", | ||
| "@vitejs/plugin-react": "^4.3.0", | ||
| "fake-indexeddb": "^6.2.5", | ||
| "jsdom": "^25.0.1", | ||
| "remark-parse": "^11.0.0", | ||
| "remark-stringify": "^11.0.0", | ||
| "tailwindcss": "^4.1.0", | ||
| "typescript": "~5.6.0", | ||
| "unified": "^11.0.5", | ||
| "vite": "^6.0.0", | ||
| "vite-plugin-pwa": "^1.2.0", | ||
| "vitest": "^3", | ||
| "workbox-window": "^7.4.0" | ||
| "@openparachute/notes-ui": "workspace:*" | ||
| } | ||
| } |
+36
-9
@@ -1,3 +0,7 @@ | ||
| # Parachute Notes | ||
| > ⚠️ **DEPRECATED** — this daemon is deprecated as of 2026-05-22. | ||
| > Notes ships as a UI bundle (`@openparachute/notes-ui`) hosted by [parachute-app](https://github.com/ParachuteComputer/parachute-app). | ||
| > See [DEPRECATED.md](./DEPRECATED.md) for the migration path. | ||
| # Parachute Notes (`@openparachute/notes`) | ||
| The default frontend for [Parachute](https://parachute.computer). Browse, edit, and capture in any [Parachute Vault](https://github.com/ParachuteComputer/parachute-vault). | ||
@@ -7,2 +11,9 @@ | ||
| > **Monorepo note.** This package (`@openparachute/notes`) is the module-shaped wrapper hub installs via `parachute install notes`. The SPA source lives in [`../notes-ui`](../notes-ui), which also publishes as `@openparachute/notes-ui` for installation under [parachute-app][app]. Both packages ship the same `dist/`. Source code edits happen in `../notes-ui/src/`; this package's build step (`scripts/build.mjs`) copies notes-ui's `dist/` into its own publish payload. | ||
| > | ||
| > The migration arc retiring this package in favor of notes-ui-under-parachute-app is documented in [design Section 16][s16]. This is Phase 1 (additive). Phase 2 deprecates the module form; Phase 3 retires it. | ||
| > | ||
| > [app]: https://github.com/ParachuteComputer/parachute-app | ||
| > [s16]: https://github.com/ParachuteComputer/parachute.computer/blob/main/design/2026-05-21-parachute-apps-design.md#16-notes-migration-to-app | ||
| ## Status | ||
@@ -28,2 +39,4 @@ | ||
| From the workspace root (`parachute-notes/`): | ||
| ```sh | ||
@@ -34,3 +47,3 @@ bun install | ||
| Open the dev URL, paste your vault URL, connect. | ||
| Open the dev URL, paste your vault URL, connect. `bun run dev` dispatches to `notes-ui`'s Vite dev server. | ||
@@ -55,16 +68,19 @@ ## What it gives you | ||
| bun run build | ||
| # static output in dist/ — host anywhere | ||
| # notes-ui builds first into packages/notes-ui/dist/; | ||
| # this package's build step copies that into packages/notes-daemon/dist/. | ||
| ``` | ||
| The output `dist/` here is what hub serves via `parachute start notes` — host that directory anywhere if you want to bypass hub. | ||
| ## Development | ||
| Vite + React 19 + TypeScript (strict), Tailwind CSS v4, Biome for lint/format, Vitest + Testing Library for tests. | ||
| Vite + React 19 + TypeScript (strict), Tailwind CSS v4, Biome for lint/format, Vitest + Testing Library for tests. All scripts are workspace-rooted; they dispatch to the right sub-package via `bun --filter`. | ||
| ```sh | ||
| bun run dev # dev server | ||
| bun run typecheck # tsc --noEmit across the project references | ||
| bun run lint # biome check | ||
| bun run dev # notes-ui dev server (port 1942) | ||
| bun run typecheck # tsc --noEmit across notes-ui's project references | ||
| bun run lint # biome check over notes-ui | ||
| bun run lint:fix # biome check --write | ||
| bun run test # vitest run | ||
| bun run build # tsc -b && vite build | ||
| bun run test # notes-ui vitest suite, then daemon smoke test | ||
| bun run build # notes-ui vite build, then daemon dist-copy step | ||
| ``` | ||
@@ -81,4 +97,15 @@ | ||
| ### Local-link development against hub | ||
| Aaron's `parachute` binary resolves `@openparachute/notes` via the bun-linked global. Re-establish the link after the monorepo move: | ||
| ```sh | ||
| cd packages/notes-daemon | ||
| bun link | ||
| ``` | ||
| Then from any consumer (hub, in particular), `bun link @openparachute/notes` references the local `packages/notes-daemon/` checkout. `parachute start notes` will then serve the locally-built `dist/`. | ||
| ## License | ||
| AGPL-3.0 — same as Parachute Vault. |
| import{u as h,a as g,r as l,j as e,N as f,L as m,b,V as y}from"./index-DKKYWfqC.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}; |
| import{c as j,r as t,d as v,j as e,I as y,n as w,e as N,f as S}from"./index-DKKYWfqC.js";function R(){const[b]=j(),u=b.get("url")??"",[a,c]=t.useState(u),[i,l]=t.useState(null),[g,d]=t.useState(!1),[o,m]=t.useState(!1),h=t.useRef(null),x=t.useRef(u.length>0),n=v();t.useEffect(()=>{var s;(s=h.current)==null||s.focus()},[]),t.useEffect(()=>{x.current||n.status==="found"&&n.origin&&a===""&&(c(n.origin),x.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:h,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}; |
| import{u as k,c as E,a as A,r as f,j as e,N as K,L as d,V as S}from"./index-DKKYWfqC.js";import{p as y,c as j,t as P,m as T,a as V,s as N,b as i,f as C}from"./dates-DfXc2iZW.js";const _=["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],x=5;function B(){const a=k(t=>t.getActiveVault()),[o]=E(),l=o.get("month"),r=y(l)??y(j()),s=A(),h=P(),v=f.useMemo(()=>T(r.year,r.month),[r.year,r.month]),$=f.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{B as Calendar}; |
| import{u as xe,g as be,h as ye,i as ve,k as we,r as i,l as Y,m as ke,o as Te,p as S,q as Re,j as a,N as Se,b as je,T as Ne,s as oe,L as Ee}from"./index-DKKYWfqC.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()} | ||
| _Transcript pending._ | ||
| ![[${O}]] | ||
| `:`_Transcript pending._ | ||
| ![[${O}]] | ||
| `,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}; |
| function u(t){return t<10?`0${t}`:String(t)}function s(t=new Date){return`${t.getFullYear()}-${u(t.getMonth()+1)}-${u(t.getDate())}`}function l(t){if(!t)return null;const e=new Date(t);return Number.isNaN(e.getTime())?null:s(e)}function c(t){if(!t||!/^\d{4}-\d{2}-\d{2}$/.test(t))return null;const[e,n,r]=t.split("-").map(Number),a=new Date(e,n-1,r);return Number.isNaN(a.getTime())?null:a}function f(t=new Date){return`${t.getFullYear()}-${u(t.getMonth()+1)}`}function d(t){if(!t||!/^\d{4}-\d{2}$/.test(t))return null;const[e,n]=t.split("-").map(Number);return n<1||n>12?null:{year:e,month:n}}function g(t,e,n){const r=t*12+(e-1)+n;return{year:Math.floor(r/12),month:r%12+1}}function m(t,e){const r=new Date(t,e-1,1).getDay(),a=new Date(t,e-1,1-r),i=[];for(let o=0;o<42;o++)i.push(new Date(a.getFullYear(),a.getMonth(),a.getDate()+o));return i}function D(t){const e=c(t);return e?e.toLocaleDateString(void 0,{weekday:"long",year:"numeric",month:"long",day:"numeric"}):t}function h(t,e){return new Date(t,e-1,1).toLocaleDateString(void 0,{year:"numeric",month:"long"})}export{l as a,u as b,f as c,c as d,D as e,h as f,m,d as p,g as s,s as t}; |
| @import"https://fonts.googleapis.com/css2?family=Instrument+Serif:ital@0;1&family=DM+Sans:ital,opsz,wght@0,9..40,300;0,9..40,400;0,9..40,500;1,9..40,300;1,9..40,400&family=JetBrains+Mono:wght@400;500&display=swap";/*! tailwindcss v4.2.4 | MIT License | https://tailwindcss.com */@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-space-y-reverse:0;--tw-divide-y-reverse:0;--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-ordinal:initial;--tw-slashed-zero:initial;--tw-numeric-figure:initial;--tw-numeric-spacing:initial;--tw-numeric-fraction:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-outline-style:solid;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-backdrop-blur:initial;--tw-backdrop-brightness:initial;--tw-backdrop-contrast:initial;--tw-backdrop-grayscale:initial;--tw-backdrop-hue-rotate:initial;--tw-backdrop-invert:initial;--tw-backdrop-opacity:initial;--tw-backdrop-saturate:initial;--tw-backdrop-sepia:initial}}}@layer theme{:root,:host{--font-sans:"DM Sans", -apple-system, BlinkMacSystemFont, sans-serif;--font-serif:"Instrument Serif", Georgia, serif;--font-mono:"JetBrains Mono", "SF Mono", Monaco, monospace;--color-red-50:oklch(97.1% .013 17.38);--color-red-100:oklch(93.6% .032 17.717);--color-red-200:oklch(88.5% .062 18.334);--color-red-300:oklch(80.8% .114 19.571);--color-red-400:oklch(70.4% .191 22.216);--color-red-500:oklch(63.7% .237 25.331);--color-red-600:oklch(57.7% .245 27.325);--color-amber-50:oklch(98.7% .022 95.277);--color-amber-100:oklch(96.2% .059 95.617);--color-amber-200:oklch(92.4% .12 95.746);--color-amber-300:oklch(87.9% .169 91.605);--color-amber-400:oklch(82.8% .189 84.429);--color-amber-500:oklch(76.9% .188 70.08);--color-amber-700:oklch(55.5% .163 48.998);--color-emerald-300:oklch(84.5% .143 164.978);--color-emerald-400:oklch(76.5% .177 163.223);--color-emerald-500:oklch(69.6% .17 162.48);--color-sky-300:oklch(82.8% .111 230.318);--color-sky-400:oklch(74.6% .16 232.661);--color-sky-500:oklch(68.5% .169 237.323);--color-black:#000;--color-white:#fff;--spacing:.25rem;--container-sm:24rem;--container-md:28rem;--container-xl:36rem;--container-2xl:42rem;--container-3xl:48rem;--container-4xl:56rem;--container-5xl:64rem;--container-6xl:72rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--text-base:1rem;--text-base--line-height: 1.5 ;--text-lg:1.125rem;--text-lg--line-height:calc(1.75 / 1.125);--text-xl:1.25rem;--text-xl--line-height:calc(1.75 / 1.25);--text-2xl:1.5rem;--text-2xl--line-height:calc(2 / 1.5);--text-3xl:1.875rem;--text-3xl--line-height: 1.2 ;--text-4xl:2.25rem;--text-4xl--line-height:calc(2.5 / 2.25);--text-5xl:3rem;--text-5xl--line-height:1;--font-weight-medium:500;--tracking-tight:-.025em;--tracking-wide:.025em;--tracking-wider:.05em;--radius-md:.375rem;--radius-lg:.5rem;--radius-xl:.75rem;--animate-pulse:pulse 2s cubic-bezier(.4, 0, .6, 1) infinite;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono);--color-bg:#faf8f4;--color-bg-soft:#f3f0ea;--color-fg:#2c2a26;--color-fg-muted:#6b6860;--color-fg-dim:#9a9690;--color-accent:#4a7c59;--color-accent-hover:#3d6849;--color-accent-light:#6a9b77;--color-border:#e4e0d8;--color-card:#fff;--font-size-prose:18px;--font-size-editor:15px}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;-moz-tab-size:4;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab,red,red)){::placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){-webkit-appearance:button;-moz-appearance:button;appearance:button}::file-selector-button{-webkit-appearance:button;-moz-appearance:button;appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.pointer-events-auto{pointer-events:auto}.pointer-events-none{pointer-events:none}.collapse{visibility:collapse}.invisible{visibility:hidden}.visible{visibility:visible}.sr-only{clip-path:inset(50%);white-space:nowrap;border-width:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.static{position:static}.sticky{position:sticky}.inset-0{inset:calc(var(--spacing) * 0)}.inset-x-0{inset-inline:calc(var(--spacing) * 0)}.start{inset-inline-start:var(--spacing)}.end{inset-inline-end:var(--spacing)}.top-0{top:calc(var(--spacing) * 0)}.top-full{top:100%}.right-0{right:calc(var(--spacing) * 0)}.right-3{right:calc(var(--spacing) * 3)}.bottom-0{bottom:calc(var(--spacing) * 0)}.bottom-3{bottom:calc(var(--spacing) * 3)}.bottom-4{bottom:calc(var(--spacing) * 4)}.bottom-6{bottom:calc(var(--spacing) * 6)}.left-1\/2{left:50%}.z-10{z-index:10}.z-20{z-index:20}.z-30{z-index:30}.z-40{z-index:40}.z-50{z-index:50}.container{width:100%}@media(min-width:40rem){.container{max-width:40rem}}@media(min-width:48rem){.container{max-width:48rem}}@media(min-width:64rem){.container{max-width:64rem}}@media(min-width:80rem){.container{max-width:80rem}}@media(min-width:96rem){.container{max-width:96rem}}.m-0{margin:calc(var(--spacing) * 0)}.m-auto{margin:auto}.mx-1{margin-inline:calc(var(--spacing) * 1)}.mx-auto{margin-inline:auto}.-mt-2{margin-top:calc(var(--spacing) * -2)}.mt-0\.5{margin-top:calc(var(--spacing) * .5)}.mt-1{margin-top:calc(var(--spacing) * 1)}.mt-1\.5{margin-top:calc(var(--spacing) * 1.5)}.mt-2{margin-top:calc(var(--spacing) * 2)}.mt-3{margin-top:calc(var(--spacing) * 3)}.mt-4{margin-top:calc(var(--spacing) * 4)}.mt-6{margin-top:calc(var(--spacing) * 6)}.mt-8{margin-top:calc(var(--spacing) * 8)}.mt-10{margin-top:calc(var(--spacing) * 10)}.mr-1{margin-right:calc(var(--spacing) * 1)}.mr-2{margin-right:calc(var(--spacing) * 2)}.mb-1{margin-bottom:calc(var(--spacing) * 1)}.mb-1\.5{margin-bottom:calc(var(--spacing) * 1.5)}.mb-2{margin-bottom:calc(var(--spacing) * 2)}.mb-3{margin-bottom:calc(var(--spacing) * 3)}.mb-4{margin-bottom:calc(var(--spacing) * 4)}.mb-5{margin-bottom:calc(var(--spacing) * 5)}.mb-6{margin-bottom:calc(var(--spacing) * 6)}.mb-8{margin-bottom:calc(var(--spacing) * 8)}.mb-10{margin-bottom:calc(var(--spacing) * 10)}.ml-0\.5{margin-left:calc(var(--spacing) * .5)}.ml-1{margin-left:calc(var(--spacing) * 1)}.ml-2{margin-left:calc(var(--spacing) * 2)}.ml-4{margin-left:calc(var(--spacing) * 4)}.ml-auto{margin-left:auto}.line-clamp-2{-webkit-line-clamp:2;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.block{display:block}.contents{display:contents}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline{display:inline}.inline-block{display:inline-block}.inline-flex{display:inline-flex}.table{display:table}.h-1{height:calc(var(--spacing) * 1)}.h-1\.5{height:calc(var(--spacing) * 1.5)}.h-2{height:calc(var(--spacing) * 2)}.h-3{height:calc(var(--spacing) * 3)}.h-4{height:calc(var(--spacing) * 4)}.h-5{height:calc(var(--spacing) * 5)}.h-6{height:calc(var(--spacing) * 6)}.h-8{height:calc(var(--spacing) * 8)}.h-10{height:calc(var(--spacing) * 10)}.h-14{height:calc(var(--spacing) * 14)}.h-16{height:calc(var(--spacing) * 16)}.h-24{height:calc(var(--spacing) * 24)}.h-28{height:calc(var(--spacing) * 28)}.h-32{height:calc(var(--spacing) * 32)}.h-\[24rem\]{height:24rem}.h-\[40rem\]{height:40rem}.h-\[calc\(100dvh-5rem\)\]{height:calc(100dvh - 5rem)}.h-full{height:100%}.max-h-48{max-height:calc(var(--spacing) * 48)}.max-h-56{max-height:calc(var(--spacing) * 56)}.max-h-\[32rem\]{max-height:32rem}.max-h-\[50vh\]{max-height:50vh}.max-h-\[60vh\]{max-height:60vh}.max-h-full{max-height:100%}.min-h-0{min-height:calc(var(--spacing) * 0)}.min-h-11{min-height:calc(var(--spacing) * 11)}.min-h-20{min-height:calc(var(--spacing) * 20)}.min-h-\[30vh\]{min-height:30vh}.min-h-\[60vh\]{min-height:60vh}.min-h-dvh{min-height:100dvh}.w-1\.5{width:calc(var(--spacing) * 1.5)}.w-1\/3{width:33.3333%}.w-2{width:calc(var(--spacing) * 2)}.w-2\/3{width:66.6667%}.w-4{width:calc(var(--spacing) * 4)}.w-5{width:calc(var(--spacing) * 5)}.w-6{width:calc(var(--spacing) * 6)}.w-10{width:calc(var(--spacing) * 10)}.w-32{width:calc(var(--spacing) * 32)}.w-40{width:calc(var(--spacing) * 40)}.w-44{width:calc(var(--spacing) * 44)}.w-48{width:calc(var(--spacing) * 48)}.w-72{width:calc(var(--spacing) * 72)}.w-80{width:calc(var(--spacing) * 80)}.w-full{width:100%}.w-px{width:1px}.max-w-2xl{max-width:var(--container-2xl)}.max-w-3xl{max-width:var(--container-3xl)}.max-w-4xl{max-width:var(--container-4xl)}.max-w-5xl{max-width:var(--container-5xl)}.max-w-6xl{max-width:var(--container-6xl)}.max-w-\[12rem\]{max-width:12rem}.max-w-full{max-width:100%}.max-w-md{max-width:var(--container-md)}.max-w-sm{max-width:var(--container-sm)}.max-w-xl{max-width:var(--container-xl)}.min-w-0{min-width:calc(var(--spacing) * 0)}.min-w-11{min-width:calc(var(--spacing) * 11)}.min-w-24{min-width:calc(var(--spacing) * 24)}.min-w-48{min-width:calc(var(--spacing) * 48)}.flex-1{flex:1}.shrink{flex-shrink:1}.shrink-0{flex-shrink:0}.grow{flex-grow:1}.-translate-x-1\/2{--tw-translate-x: -50% ;translate:var(--tw-translate-x) var(--tw-translate-y)}.animate-pulse{animation:var(--animate-pulse)}.cursor-pointer{cursor:pointer}.touch-none{touch-action:none}.resize-y{resize:vertical}.list-decimal{list-style-type:decimal}.list-disc{list-style-type:disc}.list-none{list-style-type:none}.grid-cols-7{grid-template-columns:repeat(7,minmax(0,1fr))}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-baseline{align-items:baseline}.items-center{align-items:center}.items-end{align-items:flex-end}.items-start{align-items:flex-start}.items-stretch{align-items:stretch}.justify-around{justify-content:space-around}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.justify-end{justify-content:flex-end}.gap-0\.5{gap:calc(var(--spacing) * .5)}.gap-1{gap:calc(var(--spacing) * 1)}.gap-1\.5{gap:calc(var(--spacing) * 1.5)}.gap-2{gap:calc(var(--spacing) * 2)}.gap-3{gap:calc(var(--spacing) * 3)}.gap-4{gap:calc(var(--spacing) * 4)}.gap-6{gap:calc(var(--spacing) * 6)}.gap-10{gap:calc(var(--spacing) * 10)}:where(.space-y-0\.5>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * .5) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * .5) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-1>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 1) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 1) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-1\.5>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 1.5) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 1.5) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-2>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 2) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 2) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-3>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 3) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 3) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-4>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 4) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 4) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-6>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 6) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 6) * calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-8>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 8) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 8) * calc(1 - var(--tw-space-y-reverse)))}.gap-x-3{column-gap:calc(var(--spacing) * 3)}.gap-x-4{column-gap:calc(var(--spacing) * 4)}.gap-y-2{row-gap:calc(var(--spacing) * 2)}.gap-y-3{row-gap:calc(var(--spacing) * 3)}:where(.divide-y>:not(:last-child)){--tw-divide-y-reverse:0;border-bottom-style:var(--tw-border-style);border-top-style:var(--tw-border-style);border-top-width:calc(1px * var(--tw-divide-y-reverse));border-bottom-width:calc(1px * calc(1 - var(--tw-divide-y-reverse)))}:where(.divide-border>:not(:last-child)){border-color:var(--color-border)}.self-start{align-self:flex-start}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-x-hidden{overflow-x:hidden}.overflow-y-auto{overflow-y:auto}.rounded{border-radius:.25rem}.rounded-full{border-radius:3.40282e38px}.rounded-lg{border-radius:var(--radius-lg)}.rounded-md{border-radius:var(--radius-md)}.rounded-xl{border-radius:var(--radius-xl)}.rounded-t-md{border-top-left-radius:var(--radius-md);border-top-right-radius:var(--radius-md)}.border{border-style:var(--tw-border-style);border-width:1px}.border-2{border-style:var(--tw-border-style);border-width:2px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-r{border-right-style:var(--tw-border-style);border-right-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-l{border-left-style:var(--tw-border-style);border-left-width:1px}.border-dashed{--tw-border-style:dashed;border-style:dashed}.border-accent{border-color:var(--color-accent)}.border-accent\/30{border-color:#4a7c594d}@supports (color:color-mix(in lab,red,red)){.border-accent\/30{border-color:color-mix(in oklab,var(--color-accent) 30%,transparent)}}.border-accent\/40{border-color:#4a7c5966}@supports (color:color-mix(in lab,red,red)){.border-accent\/40{border-color:color-mix(in oklab,var(--color-accent) 40%,transparent)}}.border-accent\/60{border-color:#4a7c5999}@supports (color:color-mix(in lab,red,red)){.border-accent\/60{border-color:color-mix(in oklab,var(--color-accent) 60%,transparent)}}.border-amber-400\/40{border-color:#fcbb0066}@supports (color:color-mix(in lab,red,red)){.border-amber-400\/40{border-color:color-mix(in oklab,var(--color-amber-400) 40%,transparent)}}.border-amber-500\/30{border-color:#f99c004d}@supports (color:color-mix(in lab,red,red)){.border-amber-500\/30{border-color:color-mix(in oklab,var(--color-amber-500) 30%,transparent)}}.border-amber-500\/40{border-color:#f99c0066}@supports (color:color-mix(in lab,red,red)){.border-amber-500\/40{border-color:color-mix(in oklab,var(--color-amber-500) 40%,transparent)}}.border-border{border-color:var(--color-border)}.border-red-400\/30{border-color:#ff65684d}@supports (color:color-mix(in lab,red,red)){.border-red-400\/30{border-color:color-mix(in oklab,var(--color-red-400) 30%,transparent)}}.border-red-500\/30{border-color:#fb2c364d}@supports (color:color-mix(in lab,red,red)){.border-red-500\/30{border-color:color-mix(in oklab,var(--color-red-500) 30%,transparent)}}.border-red-500\/40{border-color:#fb2c3666}@supports (color:color-mix(in lab,red,red)){.border-red-500\/40{border-color:color-mix(in oklab,var(--color-red-500) 40%,transparent)}}.border-sky-500\/30{border-color:#00a5ef4d}@supports (color:color-mix(in lab,red,red)){.border-sky-500\/30{border-color:color-mix(in oklab,var(--color-sky-500) 30%,transparent)}}.border-transparent{border-color:#0000}.bg-accent{background-color:var(--color-accent)}.bg-accent\/5{background-color:#4a7c590d}@supports (color:color-mix(in lab,red,red)){.bg-accent\/5{background-color:color-mix(in oklab,var(--color-accent) 5%,transparent)}}.bg-accent\/10{background-color:#4a7c591a}@supports (color:color-mix(in lab,red,red)){.bg-accent\/10{background-color:color-mix(in oklab,var(--color-accent) 10%,transparent)}}.bg-accent\/15{background-color:#4a7c5926}@supports (color:color-mix(in lab,red,red)){.bg-accent\/15{background-color:color-mix(in oklab,var(--color-accent) 15%,transparent)}}.bg-accent\/20{background-color:#4a7c5933}@supports (color:color-mix(in lab,red,red)){.bg-accent\/20{background-color:color-mix(in oklab,var(--color-accent) 20%,transparent)}}.bg-amber-400{background-color:var(--color-amber-400)}.bg-amber-400\/10{background-color:#fcbb001a}@supports (color:color-mix(in lab,red,red)){.bg-amber-400\/10{background-color:color-mix(in oklab,var(--color-amber-400) 10%,transparent)}}.bg-amber-500\/5{background-color:#f99c000d}@supports (color:color-mix(in lab,red,red)){.bg-amber-500\/5{background-color:color-mix(in oklab,var(--color-amber-500) 5%,transparent)}}.bg-amber-500\/10{background-color:#f99c001a}@supports (color:color-mix(in lab,red,red)){.bg-amber-500\/10{background-color:color-mix(in oklab,var(--color-amber-500) 10%,transparent)}}.bg-amber-500\/20{background-color:#f99c0033}@supports (color:color-mix(in lab,red,red)){.bg-amber-500\/20{background-color:color-mix(in oklab,var(--color-amber-500) 20%,transparent)}}.bg-amber-500\/30{background-color:#f99c004d}@supports (color:color-mix(in lab,red,red)){.bg-amber-500\/30{background-color:color-mix(in oklab,var(--color-amber-500) 30%,transparent)}}.bg-bg{background-color:var(--color-bg)}.bg-bg\/40{background-color:#faf8f466}@supports (color:color-mix(in lab,red,red)){.bg-bg\/40{background-color:color-mix(in oklab,var(--color-bg) 40%,transparent)}}.bg-bg\/50{background-color:#faf8f480}@supports (color:color-mix(in lab,red,red)){.bg-bg\/50{background-color:color-mix(in oklab,var(--color-bg) 50%,transparent)}}.bg-bg\/60{background-color:#faf8f499}@supports (color:color-mix(in lab,red,red)){.bg-bg\/60{background-color:color-mix(in oklab,var(--color-bg) 60%,transparent)}}.bg-bg\/80{background-color:#faf8f4cc}@supports (color:color-mix(in lab,red,red)){.bg-bg\/80{background-color:color-mix(in oklab,var(--color-bg) 80%,transparent)}}.bg-bg\/90{background-color:#faf8f4e6}@supports (color:color-mix(in lab,red,red)){.bg-bg\/90{background-color:color-mix(in oklab,var(--color-bg) 90%,transparent)}}.bg-bg\/95{background-color:#faf8f4f2}@supports (color:color-mix(in lab,red,red)){.bg-bg\/95{background-color:color-mix(in oklab,var(--color-bg) 95%,transparent)}}.bg-black\/60{background-color:#0009}@supports (color:color-mix(in lab,red,red)){.bg-black\/60{background-color:color-mix(in oklab,var(--color-black) 60%,transparent)}}.bg-border{background-color:var(--color-border)}.bg-border\/30{background-color:#e4e0d84d}@supports (color:color-mix(in lab,red,red)){.bg-border\/30{background-color:color-mix(in oklab,var(--color-border) 30%,transparent)}}.bg-border\/40{background-color:#e4e0d866}@supports (color:color-mix(in lab,red,red)){.bg-border\/40{background-color:color-mix(in oklab,var(--color-border) 40%,transparent)}}.bg-border\/60{background-color:#e4e0d899}@supports (color:color-mix(in lab,red,red)){.bg-border\/60{background-color:color-mix(in oklab,var(--color-border) 60%,transparent)}}.bg-card{background-color:var(--color-card)}.bg-card\/30{background-color:#ffffff4d}@supports (color:color-mix(in lab,red,red)){.bg-card\/30{background-color:color-mix(in oklab,var(--color-card) 30%,transparent)}}.bg-card\/40{background-color:#fff6}@supports (color:color-mix(in lab,red,red)){.bg-card\/40{background-color:color-mix(in oklab,var(--color-card) 40%,transparent)}}.bg-card\/50{background-color:#ffffff80}@supports (color:color-mix(in lab,red,red)){.bg-card\/50{background-color:color-mix(in oklab,var(--color-card) 50%,transparent)}}.bg-card\/60{background-color:#fff9}@supports (color:color-mix(in lab,red,red)){.bg-card\/60{background-color:color-mix(in oklab,var(--color-card) 60%,transparent)}}.bg-card\/90{background-color:#ffffffe6}@supports (color:color-mix(in lab,red,red)){.bg-card\/90{background-color:color-mix(in oklab,var(--color-card) 90%,transparent)}}.bg-emerald-400{background-color:var(--color-emerald-400)}.bg-emerald-500\/20{background-color:#00bb7f33}@supports (color:color-mix(in lab,red,red)){.bg-emerald-500\/20{background-color:color-mix(in oklab,var(--color-emerald-500) 20%,transparent)}}.bg-red-400{background-color:var(--color-red-400)}.bg-red-400\/5{background-color:#ff65680d}@supports (color:color-mix(in lab,red,red)){.bg-red-400\/5{background-color:color-mix(in oklab,var(--color-red-400) 5%,transparent)}}.bg-red-500{background-color:var(--color-red-500)}.bg-red-500\/5{background-color:#fb2c360d}@supports (color:color-mix(in lab,red,red)){.bg-red-500\/5{background-color:color-mix(in oklab,var(--color-red-500) 5%,transparent)}}.bg-red-500\/10{background-color:#fb2c361a}@supports (color:color-mix(in lab,red,red)){.bg-red-500\/10{background-color:color-mix(in oklab,var(--color-red-500) 10%,transparent)}}.bg-red-500\/20{background-color:#fb2c3633}@supports (color:color-mix(in lab,red,red)){.bg-red-500\/20{background-color:color-mix(in oklab,var(--color-red-500) 20%,transparent)}}.bg-red-500\/30{background-color:#fb2c364d}@supports (color:color-mix(in lab,red,red)){.bg-red-500\/30{background-color:color-mix(in oklab,var(--color-red-500) 30%,transparent)}}.bg-sky-400{background-color:var(--color-sky-400)}.bg-sky-500\/5{background-color:#00a5ef0d}@supports (color:color-mix(in lab,red,red)){.bg-sky-500\/5{background-color:color-mix(in oklab,var(--color-sky-500) 5%,transparent)}}.bg-transparent{background-color:#0000}.p-0\.5{padding:calc(var(--spacing) * .5)}.p-1\.5{padding:calc(var(--spacing) * 1.5)}.p-2{padding:calc(var(--spacing) * 2)}.p-3{padding:calc(var(--spacing) * 3)}.p-4{padding:calc(var(--spacing) * 4)}.p-5{padding:calc(var(--spacing) * 5)}.p-6{padding:calc(var(--spacing) * 6)}.p-8{padding:calc(var(--spacing) * 8)}.p-10{padding:calc(var(--spacing) * 10)}.px-1{padding-inline:calc(var(--spacing) * 1)}.px-1\.5{padding-inline:calc(var(--spacing) * 1.5)}.px-2{padding-inline:calc(var(--spacing) * 2)}.px-2\.5{padding-inline:calc(var(--spacing) * 2.5)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-4{padding-inline:calc(var(--spacing) * 4)}.px-6{padding-inline:calc(var(--spacing) * 6)}.py-0\.5{padding-block:calc(var(--spacing) * .5)}.py-1{padding-block:calc(var(--spacing) * 1)}.py-1\.5{padding-block:calc(var(--spacing) * 1.5)}.py-2{padding-block:calc(var(--spacing) * 2)}.py-2\.5{padding-block:calc(var(--spacing) * 2.5)}.py-3{padding-block:calc(var(--spacing) * 3)}.py-4{padding-block:calc(var(--spacing) * 4)}.py-5{padding-block:calc(var(--spacing) * 5)}.py-6{padding-block:calc(var(--spacing) * 6)}.py-7{padding-block:calc(var(--spacing) * 7)}.py-10{padding-block:calc(var(--spacing) * 10)}.py-16{padding-block:calc(var(--spacing) * 16)}.py-20{padding-block:calc(var(--spacing) * 20)}.py-24{padding-block:calc(var(--spacing) * 24)}.pt-1{padding-top:calc(var(--spacing) * 1)}.pt-2{padding-top:calc(var(--spacing) * 2)}.pt-3{padding-top:calc(var(--spacing) * 3)}.pt-4{padding-top:calc(var(--spacing) * 4)}.pt-6{padding-top:calc(var(--spacing) * 6)}.pt-\[10vh\]{padding-top:10vh}.pr-1{padding-right:calc(var(--spacing) * 1)}.pb-1\.5{padding-bottom:calc(var(--spacing) * 1.5)}.pb-2{padding-bottom:calc(var(--spacing) * 2)}.pb-3{padding-bottom:calc(var(--spacing) * 3)}.pb-4{padding-bottom:calc(var(--spacing) * 4)}.pb-16{padding-bottom:calc(var(--spacing) * 16)}.pl-2{padding-left:calc(var(--spacing) * 2)}.pl-5{padding-left:calc(var(--spacing) * 5)}.text-center{text-align:center}.text-left{text-align:left}.text-right{text-align:right}.font-mono{font-family:var(--font-mono)}.font-serif{font-family:var(--font-serif)}.text-2xl{font-size:var(--text-2xl);line-height:var(--tw-leading,var(--text-2xl--line-height))}.text-3xl{font-size:var(--text-3xl);line-height:var(--tw-leading,var(--text-3xl--line-height))}.text-4xl{font-size:var(--text-4xl);line-height:var(--tw-leading,var(--text-4xl--line-height))}.text-5xl{font-size:var(--text-5xl);line-height:var(--tw-leading,var(--text-5xl--line-height))}.text-base{font-size:var(--text-base);line-height:var(--tw-leading,var(--text-base--line-height))}.text-lg{font-size:var(--text-lg);line-height:var(--tw-leading,var(--text-lg--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xl{font-size:var(--text-xl);line-height:var(--tw-leading,var(--text-xl--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.text-\[10px\]{font-size:10px}.text-\[11px\]{font-size:11px}.leading-none{--tw-leading:1;line-height:1}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.tracking-tight{--tw-tracking:var(--tracking-tight);letter-spacing:var(--tracking-tight)}.tracking-wide{--tw-tracking:var(--tracking-wide);letter-spacing:var(--tracking-wide)}.tracking-wider{--tw-tracking:var(--tracking-wider);letter-spacing:var(--tracking-wider)}.break-words{overflow-wrap:break-word}.break-all{word-break:break-all}.text-accent{color:var(--color-accent)}.text-accent\/70{color:#4a7c59b3}@supports (color:color-mix(in lab,red,red)){.text-accent\/70{color:color-mix(in oklab,var(--color-accent) 70%,transparent)}}.text-amber-50{color:var(--color-amber-50)}.text-amber-100{color:var(--color-amber-100)}.text-amber-100\/70{color:#fef3c6b3}@supports (color:color-mix(in lab,red,red)){.text-amber-100\/70{color:color-mix(in oklab,var(--color-amber-100) 70%,transparent)}}.text-amber-100\/90{color:#fef3c6e6}@supports (color:color-mix(in lab,red,red)){.text-amber-100\/90{color:color-mix(in oklab,var(--color-amber-100) 90%,transparent)}}.text-amber-200{color:var(--color-amber-200)}.text-amber-200\/80{color:#fee685cc}@supports (color:color-mix(in lab,red,red)){.text-amber-200\/80{color:color-mix(in oklab,var(--color-amber-200) 80%,transparent)}}.text-amber-300{color:var(--color-amber-300)}.text-amber-500{color:var(--color-amber-500)}.text-amber-700{color:var(--color-amber-700)}.text-emerald-300{color:var(--color-emerald-300)}.text-fg{color:var(--color-fg)}.text-fg-dim{color:var(--color-fg-dim)}.text-fg-muted{color:var(--color-fg-muted)}.text-red-50{color:var(--color-red-50)}.text-red-100{color:var(--color-red-100)}.text-red-200{color:var(--color-red-200)}.text-red-200\/80{color:#ffcacacc}@supports (color:color-mix(in lab,red,red)){.text-red-200\/80{color:color-mix(in oklab,var(--color-red-200) 80%,transparent)}}.text-red-300{color:var(--color-red-300)}.text-red-400{color:var(--color-red-400)}.text-sky-300{color:var(--color-sky-300)}.text-white{color:var(--color-white)}.text-white\/80{color:#fffc}@supports (color:color-mix(in lab,red,red)){.text-white\/80{color:color-mix(in oklab,var(--color-white) 80%,transparent)}}.capitalize{text-transform:capitalize}.lowercase{text-transform:lowercase}.uppercase{text-transform:uppercase}.italic{font-style:italic}.tabular-nums{--tw-numeric-spacing:tabular-nums;font-variant-numeric:var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,)}.underline{text-decoration-line:underline}.decoration-dashed{text-decoration-style:dashed}.underline-offset-4{text-underline-offset:4px}.accent-accent{accent-color:var(--color-accent)}.opacity-40{opacity:.4}.opacity-60{opacity:.6}.shadow{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-lg{--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,#0000001a), 0 4px 6px -4px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-sm{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-xl{--tw-shadow:0 20px 25px -5px var(--tw-shadow-color,#0000001a), 0 8px 10px -6px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.outline{outline-style:var(--tw-outline-style);outline-width:1px}.filter{filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.backdrop-blur{--tw-backdrop-blur:blur(8px);-webkit-backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,)}.transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,content-visibility,overlay,pointer-events;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-\[width\]{transition-property:width;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-transform{transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.select-none{-webkit-user-select:none;user-select:none}.group-open\:rotate-90:is(:where(.group):is([open],:popover-open,:open) *){rotate:90deg}.placeholder\:text-fg-dim::placeholder{color:var(--color-fg-dim)}.backdrop\:bg-black\/40::backdrop{background-color:#0006}@supports (color:color-mix(in lab,red,red)){.backdrop\:bg-black\/40::backdrop{background-color:color-mix(in oklab,var(--color-black) 40%,transparent)}}@media(hover:hover){.hover\:border-accent:hover{border-color:var(--color-accent)}.hover\:border-accent\/50:hover{border-color:#4a7c5980}@supports (color:color-mix(in lab,red,red)){.hover\:border-accent\/50:hover{border-color:color-mix(in oklab,var(--color-accent) 50%,transparent)}}.hover\:border-border:hover{border-color:var(--color-border)}.hover\:border-red-500\/40:hover{border-color:#fb2c3666}@supports (color:color-mix(in lab,red,red)){.hover\:border-red-500\/40:hover{border-color:color-mix(in oklab,var(--color-red-500) 40%,transparent)}}.hover\:bg-accent-hover:hover{background-color:var(--color-accent-hover)}.hover\:bg-accent\/5:hover{background-color:#4a7c590d}@supports (color:color-mix(in lab,red,red)){.hover\:bg-accent\/5:hover{background-color:color-mix(in oklab,var(--color-accent) 5%,transparent)}}.hover\:bg-accent\/10:hover{background-color:#4a7c591a}@supports (color:color-mix(in lab,red,red)){.hover\:bg-accent\/10:hover{background-color:color-mix(in oklab,var(--color-accent) 10%,transparent)}}.hover\:bg-accent\/15:hover{background-color:#4a7c5926}@supports (color:color-mix(in lab,red,red)){.hover\:bg-accent\/15:hover{background-color:color-mix(in oklab,var(--color-accent) 15%,transparent)}}.hover\:bg-accent\/20:hover{background-color:#4a7c5933}@supports (color:color-mix(in lab,red,red)){.hover\:bg-accent\/20:hover{background-color:color-mix(in oklab,var(--color-accent) 20%,transparent)}}.hover\:bg-amber-500\/20:hover{background-color:#f99c0033}@supports (color:color-mix(in lab,red,red)){.hover\:bg-amber-500\/20:hover{background-color:color-mix(in oklab,var(--color-amber-500) 20%,transparent)}}.hover\:bg-amber-500\/50:hover{background-color:#f99c0080}@supports (color:color-mix(in lab,red,red)){.hover\:bg-amber-500\/50:hover{background-color:color-mix(in oklab,var(--color-amber-500) 50%,transparent)}}.hover\:bg-bg:hover{background-color:var(--color-bg)}.hover\:bg-bg\/50:hover{background-color:#faf8f480}@supports (color:color-mix(in lab,red,red)){.hover\:bg-bg\/50:hover{background-color:color-mix(in oklab,var(--color-bg) 50%,transparent)}}.hover\:bg-bg\/60:hover{background-color:#faf8f499}@supports (color:color-mix(in lab,red,red)){.hover\:bg-bg\/60:hover{background-color:color-mix(in oklab,var(--color-bg) 60%,transparent)}}.hover\:bg-card:hover{background-color:var(--color-card)}.hover\:bg-red-500\/10:hover{background-color:#fb2c361a}@supports (color:color-mix(in lab,red,red)){.hover\:bg-red-500\/10:hover{background-color:color-mix(in oklab,var(--color-red-500) 10%,transparent)}}.hover\:bg-red-500\/40:hover{background-color:#fb2c3666}@supports (color:color-mix(in lab,red,red)){.hover\:bg-red-500\/40:hover{background-color:color-mix(in oklab,var(--color-red-500) 40%,transparent)}}.hover\:bg-red-500\/50:hover{background-color:#fb2c3680}@supports (color:color-mix(in lab,red,red)){.hover\:bg-red-500\/50:hover{background-color:color-mix(in oklab,var(--color-red-500) 50%,transparent)}}.hover\:bg-red-600:hover{background-color:var(--color-red-600)}.hover\:text-accent:hover{color:var(--color-accent)}.hover\:text-accent-hover:hover{color:var(--color-accent-hover)}.hover\:text-amber-100:hover{color:var(--color-amber-100)}.hover\:text-fg:hover{color:var(--color-fg)}.hover\:text-red-100:hover{color:var(--color-red-100)}.hover\:text-red-300:hover{color:var(--color-red-300)}.hover\:text-red-400:hover{color:var(--color-red-400)}.hover\:underline:hover{text-decoration-line:underline}}.focus\:border-accent:focus{border-color:var(--color-accent)}.focus\:border-border:focus{border-color:var(--color-border)}.focus\:border-red-400:focus{border-color:var(--color-red-400)}.focus\:bg-bg\/60:focus{background-color:#faf8f499}@supports (color:color-mix(in lab,red,red)){.focus\:bg-bg\/60:focus{background-color:color-mix(in oklab,var(--color-bg) 60%,transparent)}}.focus\:outline-none:focus{--tw-outline-style:none;outline-style:none}.focus-visible\:outline-2:focus-visible{outline-style:var(--tw-outline-style);outline-width:2px}.focus-visible\:outline-accent:focus-visible{outline-color:var(--color-accent)}@media(hover:hover){.enabled\:hover\:text-accent:enabled:hover{color:var(--color-accent)}}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:opacity-40:disabled{opacity:.4}.disabled\:opacity-50:disabled{opacity:.5}.disabled\:opacity-60:disabled{opacity:.6}@media(min-width:40rem){.sm\:inline{display:inline}}@media(min-width:48rem){.md\:sticky{position:sticky}.md\:top-6{top:calc(var(--spacing) * 6)}.md\:mb-6{margin-bottom:calc(var(--spacing) * 6)}.md\:block{display:block}.md\:flex{display:flex}.md\:hidden{display:none}.md\:min-h-0{min-height:calc(var(--spacing) * 0)}.md\:grid-cols-\[14rem_1fr\]{grid-template-columns:14rem 1fr}.md\:flex-row{flex-direction:row}.md\:items-center{align-items:center}.md\:justify-between{justify-content:space-between}:where(.md\:space-y-6>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing) * 6) * var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing) * 6) * calc(1 - var(--tw-space-y-reverse)))}.md\:self-auto{align-self:auto}.md\:self-start{align-self:flex-start}.md\:p-6{padding:calc(var(--spacing) * 6)}.md\:px-4{padding-inline:calc(var(--spacing) * 4)}.md\:px-6{padding-inline:calc(var(--spacing) * 6)}.md\:py-3{padding-block:calc(var(--spacing) * 3)}.md\:py-8{padding-block:calc(var(--spacing) * 8)}.md\:py-10{padding-block:calc(var(--spacing) * 10)}.md\:py-12{padding-block:calc(var(--spacing) * 12)}.md\:pb-0{padding-bottom:calc(var(--spacing) * 0)}.md\:text-3xl{font-size:var(--text-3xl);line-height:var(--tw-leading,var(--text-3xl--line-height))}}@media(min-width:64rem){.lg\:sticky{position:sticky}.lg\:top-24{top:calc(var(--spacing) * 24)}.lg\:block{display:block}.lg\:flex{display:flex}.lg\:hidden{display:none}.lg\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.lg\:grid-cols-\[minmax\(0\,1fr\)_18rem\]{grid-template-columns:minmax(0,1fr) 18rem}.lg\:self-start{align-self:flex-start}.lg\:px-6{padding-inline:calc(var(--spacing) * 6)}.lg\:py-5{padding-block:calc(var(--spacing) * 5)}.lg\:text-xl{font-size:var(--text-xl);line-height:var(--tw-leading,var(--text-xl--line-height))}}@media(prefers-color-scheme:dark){.dark\:text-amber-300{color:var(--color-amber-300)}}}pre code.hljs{padding:1em;display:block;overflow-x:auto}code.hljs{padding:3px 5px}.hljs{color:#24292e;background:#fff}.hljs-doctag,.hljs-keyword,.hljs-meta .hljs-keyword,.hljs-template-tag,.hljs-template-variable,.hljs-type,.hljs-variable.language_{color:#d73a49}.hljs-title,.hljs-title.class_,.hljs-title.class_.inherited__,.hljs-title.function_{color:#6f42c1}.hljs-attr,.hljs-attribute,.hljs-literal,.hljs-meta,.hljs-number,.hljs-operator,.hljs-variable,.hljs-selector-attr,.hljs-selector-class,.hljs-selector-id{color:#005cc5}.hljs-regexp,.hljs-string,.hljs-meta .hljs-string{color:#032f62}.hljs-built_in,.hljs-symbol{color:#e36209}.hljs-comment,.hljs-code,.hljs-formula{color:#6a737d}.hljs-name,.hljs-quote,.hljs-selector-tag,.hljs-selector-pseudo{color:#22863a}.hljs-subst{color:#24292e}.hljs-section{color:#005cc5;font-weight:700}.hljs-bullet{color:#735c0f}.hljs-emphasis{color:#24292e;font-style:italic}.hljs-strong{color:#24292e;font-weight:700}.hljs-addition{color:#22863a;background-color:#f0fff4}.hljs-deletion{color:#b31d28;background-color:#ffeef0}:root[data-text-size=larger]{--font-size-prose:22px;--font-size-editor:18px;font-size:18px}:root[data-text-size=largest]{--font-size-prose:26px;--font-size-editor:22px;font-size:22px}@media(prefers-color-scheme:dark){:root:not([data-theme=light]){--color-bg:#1a1917;--color-bg-soft:#23221f;--color-fg:#e8e5de;--color-fg-muted:#a8a49b;--color-fg-dim:#706c64;--color-accent:#7ab087;--color-accent-hover:#8bc098;--color-accent-light:#5b8c6a;--color-sky:#7fb3cc;--color-border:#33312d;--color-border-light:#2a2926;--color-card:#23221f;--color-card-hover:#2a2926}}:root[data-theme=dark]{--color-bg:#1a1917;--color-bg-soft:#23221f;--color-fg:#e8e5de;--color-fg-muted:#a8a49b;--color-fg-dim:#706c64;--color-accent:#7ab087;--color-accent-hover:#8bc098;--color-accent-light:#5b8c6a;--color-sky:#7fb3cc;--color-border:#33312d;--color-border-light:#2a2926;--color-card:#23221f;--color-card-hover:#2a2926}html,body{font-family:var(--font-sans);-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;line-height:1.65}body{padding-left:env(safe-area-inset-left);padding-right:env(safe-area-inset-right);padding-bottom:env(safe-area-inset-bottom)}.prose-note{color:var(--color-fg);font-size:var(--font-size-prose);line-height:1.7}.prose-note h1,.prose-note h2,.prose-note h3,.prose-note h4{font-family:var(--font-serif);color:var(--color-fg);letter-spacing:-.015em;margin-top:1.75em;margin-bottom:.5em;line-height:1.25}.prose-note h1{font-size:1.875rem}.prose-note h2{font-size:1.5rem}.prose-note h3{font-size:1.25rem}.prose-note h4{font-size:1.1rem}.prose-note p{margin:.75em 0}.prose-note ul,.prose-note ol{margin:.75em 0;padding-left:1.5rem}.prose-note ul{list-style:outside}.prose-note ol{list-style:decimal}.prose-note li,.prose-note li>p{margin:.25em 0}.prose-note blockquote{border-left:3px solid var(--color-border);color:var(--color-fg-muted);margin:1em 0;padding-left:1rem;font-style:italic}.prose-note code{font-family:var(--font-mono);background:var(--color-bg-soft);border-radius:3px;padding:.1em .35em;font-size:.875em}.prose-note pre{background:var(--color-bg-soft);border:1px solid var(--color-border);border-radius:6px;margin:1em 0;padding:.9rem 1rem;font-size:.875em;line-height:1.5;overflow-x:auto}.prose-note pre code{font-size:inherit;background:0 0;border-radius:0;padding:0}.prose-note table{border-collapse:collapse;width:100%;margin:1em 0;font-size:.9em}.prose-note th,.prose-note td{border:1px solid var(--color-border);text-align:left;padding:.5rem .75rem}.prose-note th{background:var(--color-bg-soft);font-weight:500}.prose-note hr{border:0;border-top:1px solid var(--color-border);margin:1.5em 0}.prose-note img{border-radius:6px;max-width:100%;height:auto}.prose-note input[type=checkbox]{margin-right:.4em}@media(prefers-color-scheme:dark){:root:not([data-theme=light]) .prose-note code,:root:not([data-theme=light]) .prose-note pre{border-color:var(--color-border);background:#1f1e1b}:root:not([data-theme=light]) .prose-note .hljs{color:var(--color-fg);background:#1f1e1b!important}}:root[data-theme=dark] .prose-note code,:root[data-theme=dark] .prose-note pre{border-color:var(--color-border);background:#1f1e1b}:root[data-theme=dark] .prose-note .hljs{color:var(--color-fg);background:#1f1e1b!important}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}@property --tw-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-divide-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-ordinal{syntax:"*";inherits:false}@property --tw-slashed-zero{syntax:"*";inherits:false}@property --tw-numeric-figure{syntax:"*";inherits:false}@property --tw-numeric-spacing{syntax:"*";inherits:false}@property --tw-numeric-fraction{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}@property --tw-backdrop-blur{syntax:"*";inherits:false}@property --tw-backdrop-brightness{syntax:"*";inherits:false}@property --tw-backdrop-contrast{syntax:"*";inherits:false}@property --tw-backdrop-grayscale{syntax:"*";inherits:false}@property --tw-backdrop-hue-rotate{syntax:"*";inherits:false}@property --tw-backdrop-invert{syntax:"*";inherits:false}@property --tw-backdrop-opacity{syntax:"*";inherits:false}@property --tw-backdrop-saturate{syntax:"*";inherits:false}@property --tw-backdrop-sepia{syntax:"*";inherits:false}@keyframes pulse{50%{opacity:.5}} |
Sorry, the diff of this file is too big to display
| import{r as d,j as e,g as T,t as V,V as C,v as _,w as z,u as O,x as K,N as W,L as R,y as Y,z as q,A as H,b as D,T as Z,s as G}from"./index-DKKYWfqC.js";import{u as J,A as Q,C as X,a as ee,b as te}from"./useAttachmentUploader-vNDFzDKT.js";import{P as se,D as ne}from"./PinArchiveButtons-CCZolBUN.js";import{b as re,N as ae}from"./NoteRenderer-BuDmZBkP.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=T(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=K(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(W,{to:"/",replace:!0})}function S(t){return{content:t.content??"",path:t.path??"",tags:[...t.tags??[]]}}function le({note:t}){const n=Y(),l=T(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=J({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]),$=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 B=s.path!==o.path,U=r=>{const c=G(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 ",D(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:$,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(Z,{tags:s.tags,input:w,onInputChange:p,onAdd:U,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)"})]}),B?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(Q,{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 ${D(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}; |
| import{u as P,y as T,g as I,B as R,C as L,r as n,j as e,N as V,V as $,L as F,T as _,s as M}from"./index-DKKYWfqC.js";import{u as U,A as B,C as z,a as O,b as W}from"./useAttachmentUploader-vNDFzDKT.js";import{b as Y,N as Z}from"./NoteRenderer-BuDmZBkP.js";const q={content:"",path:"",tags:[],summary:""};function K(){const w=P(t=>t.getActiveVault()),l=T(),d=I(t=>t.push),c=R(),f=L(),[a,o]=n.useState(q),[C,b]=n.useState(""),[j,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,v=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=M(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=Y({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:v,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:"Path"}),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(_,{tags:a.tags,input:C,onInputChange:b,onAdd:A,onRemove:E})]})]}),j?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:j}):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:v,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(Z,{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(O,{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(W,{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{K as NoteNew}; |
Sorry, the diff of this file is too big to display
| const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/react-force-graph-2d-YVoN3oXw.js","assets/index-DKKYWfqC.js","assets/index-BU6cVU21.css"])))=>i.map(i=>d[i]); | ||
| import{r as c,k as v,j as t,y as k,_ as y,w as I,u as R,x as A,F as E,N as C,L as p,V as L,b as j}from"./index-DKKYWfqC.js";import{P as _,D}from"./PinArchiveButtons-CCZolBUN.js";import{b as T,N as M}from"./NoteRenderer-BuDmZBkP.js";const S=1,U=3,$=1;function B(e,s){const a=new Map,n=new Map;for(const d of s.values())for(const r of d.links??[]){if(r.sourceId===r.targetId||!s.has(r.sourceId)||!s.has(r.targetId))continue;const o=`${r.sourceId}|${r.targetId}|${r.relationship}`;a.has(o)||(a.set(o,{source:r.sourceId,target:r.targetId,relationship:r.relationship}),n.set(r.sourceId,(n.get(r.sourceId)??0)+1),n.set(r.targetId,(n.get(r.targetId)??0)+1))}return{nodes:[...s.values()].map(d=>{var r;return{id:d.id,path:d.path,tags:d.tags,summary:typeof((r=d.metadata)==null?void 0:r.summary)=="string"?d.metadata.summary:void 0,isAnchor:d.id===e,linkCount:n.get(d.id)??0}}),edges:[...a.values()]}}async function P(e,s,a,n){const i=new Map;i.set(e.id,e);let d=[e];for(let r=1;r<=s;r++){const o=new Set;for(const u of d)for(const x of u.links??[]){const h=x.sourceId===u.id?x.targetId:x.sourceId;h!==u.id&&(i.has(h)||o.add(h))}if(o.size===0)break;const l=await Promise.all([...o].map(u=>a(u).catch(()=>null)));if(n!=null&&n.cancelled)return i;const m=[];for(const u of l)u&&!i.has(u.id)&&(i.set(u.id,u),m.push(u));d=m}return i}function V(e,s,a){const[n,i]=c.useState(null),[d,r]=c.useState(!1);return c.useEffect(()=>{if(!e||!s){i(null),r(!1);return}const o={cancelled:!1};return r(!0),P(s,a,l=>e.getNote(l,{includeLinks:!0}),o).then(l=>{o.cancelled||(i(B(s.id,l)),r(!1))}).catch(()=>{o.cancelled||r(!1)}),()=>{o.cancelled=!0}},[e,s,a]),{data:n,isLoading:d}}const F=c.lazy(()=>y(()=>import("./react-force-graph-2d-YVoN3oXw.js"),__vite__mapDeps([0,1,2])));function z({anchor:e}){const[s,a]=c.useState(!0),[n,i]=c.useState($),d=v(),{data:r,isLoading:o}=V(d,s?e:void 0,n);return t.jsxs("section",{className:"mt-10 border-t border-border pt-6",children:[t.jsxs("header",{className:"mb-4 flex flex-wrap items-center justify-between gap-3",children:[t.jsxs("div",{className:"flex items-center gap-3",children:[t.jsxs("button",{type:"button",onClick:()=>a(l=>!l),"aria-expanded":s,className:"font-serif text-xl text-fg hover:text-accent",children:[s?"▾":"▸"," Neighborhood"]}),s&&r?t.jsxs("span",{className:"text-xs text-fg-dim",children:[r.nodes.length," ",r.nodes.length===1?"note":"notes"]}):null]}),s?t.jsx(G,{depth:n,onChange:i}):null]}),s?t.jsx(O,{data:r,isLoading:o}):null]})}function G({depth:e,onChange:s}){const a=[];for(let n=S;n<=U;n++)a.push(n);return t.jsxs("fieldset",{className:"flex items-center gap-1 text-xs text-fg-dim",children:[t.jsx("legend",{className:"mr-1 inline-block",children:"Hops"}),a.map(n=>t.jsx("button",{type:"button","aria-pressed":n===e,onClick:()=>s(n),className:n===e?"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:n},n))]})}function O({data:e,isLoading:s}){return!e&&s?t.jsx(w,{}):e?e.nodes.length<=1?t.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."}):t.jsx(H,{data:e}):null}function w(){return t.jsx("div",{"aria-busy":"true",className:"h-[24rem] w-full animate-pulse rounded-md border border-border bg-card"})}function H({data:e}){const s=k(),a=c.useRef(null),[n,i]=c.useState({w:600,h:384});c.useEffect(()=>{const r=a.current;if(!r)return;const o=()=>{const m=r.getBoundingClientRect();i({w:Math.max(320,Math.floor(m.width)),h:384})};o();const l=new ResizeObserver(o);return l.observe(r),()=>l.disconnect()},[]);const d=c.useMemo(()=>({nodes:e.nodes.map(r=>({...r})),links:e.edges.map(r=>({source:r.source,target:r.target,rel:r.relationship}))}),[e]);return t.jsx("div",{ref:a,"data-testid":"neighborhood-graph-canvas",className:"overflow-hidden rounded-md border border-border bg-card",children:t.jsx(c.Suspense,{fallback:t.jsx(w,{}),children:t.jsx(F,{graphData:d,width:n.w,height:n.h,nodeLabel:r=>K(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(`/n/${encodeURIComponent(r.id)}`)}})})})}function K(e){const s=[e.path??e.id];return e.tags&&e.tags.length>0&&s.push(`tags: ${e.tags.join(", ")}`),e.summary&&s.push(e.summary),s.join(` | ||
| `)}const W="_Transcript pending._",X="_Transcription unavailable._";function q({content:e}){const s=e.includes(W),a=!s&&e.includes(X);return s?t.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:[t.jsx("span",{"aria-hidden":!0,className:"inline-block h-2 w-2 animate-pulse rounded-full bg-sky-400"}),"Transcribing…"]}):a?t.jsx("output",{className:"mb-4 inline-flex 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:"Transcription unavailable — open the audio below and add a note by hand."}):null}function ce(){const{id:e}=I(),s=e?decodeURIComponent(e):void 0,a=R(i=>i.getActiveVault()),n=A(s);return c.useEffect(()=>{a&&s&&E(a.id,s)},[a,s]),a?t.jsxs("div",{className:"mx-auto max-w-6xl px-4 py-6 md:px-6 md:py-10",children:[t.jsx("nav",{className:"mb-6 text-sm text-fg-dim",children:t.jsx(p,{to:"/",className:"hover:text-accent",children:"← All notes"})}),n.isPending?t.jsx(ne,{}):n.isError?t.jsx(oe,{error:n.error}):n.data?t.jsx(J,{note:n.data}):t.jsx(ae,{id:s??""})]}):t.jsx(C,{to:"/",replace:!0})}function J({note:e}){var r;const s=c.useMemo(()=>T(e),[e]),a=e.path??e.id,n=typeof((r=e.metadata)==null?void 0:r.summary)=="string"?e.metadata.summary:null,i=c.useMemo(()=>(e.links??[]).filter(o=>o.targetId===e.id&&o.sourceId!==e.id&&o.sourceNote),[e]),d=c.useMemo(()=>{const o=new Set,l=[];for(const m of e.links??[])m.sourceId!==e.id||m.targetId===e.id||m.targetNote&&(o.has(m.targetId)||(o.add(m.targetId),l.push(m)));return l},[e]);return t.jsxs("article",{className:"grid gap-10 lg:grid-cols-[minmax(0,1fr)_18rem]",children:[t.jsxs("div",{className:"min-w-0",children:[t.jsxs("header",{className:"mb-6 border-b border-border pb-4",children:[t.jsx("h1",{className:"font-serif text-3xl tracking-tight",children:e.path?Q(e.path):e.id}),e.tags&&e.tags.length>0?t.jsx(Z,{tags:e.tags}):null,t.jsx("p",{className:"mt-2 font-mono text-xs text-fg-dim break-all",children:a}),n?t.jsx("p",{className:"mt-3 text-fg-muted",children:n}):null,t.jsxs("div",{className:"mt-4 flex flex-wrap items-center gap-2",children:[t.jsx(p,{to:`/n/${encodeURIComponent(e.id)}/edit`,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:"Edit"}),t.jsx(_,{note:e,keyboard:!0}),t.jsx(D,{note:e})]})]}),t.jsx(q,{content:e.content??""}),t.jsx(M,{note:e,resolve:s}),e.attachments&&e.attachments.length>0?t.jsxs("section",{className:"mt-10 border-t border-border pt-6",children:[t.jsx("h2",{className:"mb-3 font-serif text-xl",children:"Attachments"}),t.jsx("div",{className:"space-y-6",children:e.attachments.map(o=>t.jsx(ee,{attachment:o},o.id))})]}):null,t.jsx(z,{anchor:e})]}),t.jsxs("aside",{className:"space-y-6 text-sm lg:sticky lg:top-24 lg:self-start",children:[t.jsx(Y,{note:e}),d.length>0?t.jsx(N,{title:"Outbound",links:d,peer:"target"}):null,i.length>0?t.jsx(N,{title:"Inbound",links:i,peer:"source"}):null]})]})}function Q(e){return(e.split("/").pop()??e).replace(/\.md$/i,"")}function Y({note:e}){const s=e.createdAt,a=e.updatedAt,n=Object.entries(e.metadata??{}).filter(([i])=>i!=="summary");return t.jsxs("section",{className:"rounded-md border border-border bg-card p-4",children:[t.jsx("h2",{className:"mb-2 text-xs uppercase tracking-wider text-fg-dim",children:"Metadata"}),t.jsxs("dl",{className:"space-y-1.5 text-sm",children:[e.path?t.jsx(f,{label:"Path",value:t.jsx("span",{className:"font-mono text-xs break-all",children:e.path})}):null,t.jsx(f,{label:"ID",value:t.jsx("span",{className:"font-mono text-xs break-all",children:e.id})}),t.jsx(f,{label:"Created",value:t.jsx("time",{title:s,children:j(s)})}),a?t.jsx(f,{label:"Updated",value:t.jsx("time",{title:a,children:j(a)})}):null,n.map(([i,d])=>t.jsx(f,{label:i,value:t.jsx("span",{className:"break-all text-fg-muted",children:String(d)})},i))]})]})}function f({label:e,value:s}){return t.jsxs("div",{className:"flex flex-col gap-0.5",children:[t.jsx("dt",{className:"text-xs uppercase tracking-wider text-fg-dim",children:e}),t.jsx("dd",{children:s})]})}function Z({tags:e}){return t.jsx("div",{className:"mt-3 flex flex-wrap gap-1.5","aria-label":"Tags",children:e.map(s=>t.jsxs(p,{to:`/?tag=${encodeURIComponent(s)}`,className:"max-w-full break-all rounded-full border border-accent/40 bg-accent/10 px-2.5 py-0.5 text-xs font-medium text-accent hover:border-accent hover:bg-accent/20",children:["#",s]},s))})}function N({title:e,links:s,peer:a}){return t.jsxs("section",{className:"rounded-md border border-border bg-card p-4",children:[t.jsxs("h2",{className:"mb-2 text-xs uppercase tracking-wider text-fg-dim",children:[e," (",s.length,")"]}),t.jsx("ul",{className:"space-y-1.5",children:s.map(n=>{var o;const i=a==="source"?n.sourceNote:n.targetNote;if(!i)return null;const d=i.path??i.id,r=typeof((o=i.metadata)==null?void 0:o.summary)=="string"?i.metadata.summary:null;return t.jsx("li",{children:t.jsxs(p,{to:`/n/${encodeURIComponent(i.id)}`,className:"block rounded px-1 py-0.5 hover:bg-bg/50",children:[t.jsx("div",{className:"truncate font-mono text-xs text-fg-muted hover:text-accent",children:d}),r?t.jsx("div",{className:"mt-0.5 line-clamp-2 text-xs text-fg-dim",children:r}):null]})},`${n.sourceId}->${n.targetId}:${n.relationship}`)})})]})}function ee({attachment:e}){const s=(e.mimeType??"").toLowerCase(),a=e.filename??e.id;return t.jsxs("figure",{className:"rounded-md border border-border bg-card p-3",children:[t.jsxs("figcaption",{className:"mb-2 flex items-baseline justify-between gap-3",children:[t.jsx("span",{className:"truncate font-mono text-xs text-fg-muted",children:a}),typeof e.size=="number"?t.jsx("span",{className:"shrink-0 text-xs text-fg-dim",children:re(e.size)}):null]}),t.jsx(te,{attachment:e,mime:s,filename:a})]})}function te({attachment:e,mime:s,filename:a}){const n=v(),[i,d]=c.useState(null),[r,o]=c.useState(null),l=se(s,a),m=l!=="other",u=e.url;if(c.useEffect(()=>{if(!m||!u||!n)return;let h=!1,b=null;return o(null),n.fetchAttachmentBlob(u).then(g=>{h||(b=URL.createObjectURL(g),d(b))}).catch(g=>{h||o(g instanceof Error?g.message:"Failed to load attachment")}),()=>{h=!0,b&&URL.revokeObjectURL(b)}},[m,u,n]),!u)return t.jsx("p",{className:"text-sm text-fg-dim",children:"(no URL)"});if(r)return t.jsx("p",{className:"text-sm text-red-400",children:r});if(m&&!i)return t.jsx("div",{className:"h-32 animate-pulse rounded bg-border/40","aria-busy":"true"});const x=i??u;return l==="image"?t.jsx("img",{src:x,alt:a,className:"max-h-[32rem] rounded"}):l==="audio"?t.jsx("audio",{controls:!0,src:x,className:"w-full"}):l==="video"?t.jsx("video",{controls:!0,src:x,className:"w-full rounded"}):l==="pdf"?t.jsxs(t.Fragment,{children:[t.jsx("iframe",{src:x,title:a,className:"h-[40rem] w-full rounded border border-border"}),t.jsxs("a",{href:x,download:a,className:"mt-2 inline-block text-sm text-accent hover:underline",children:["Download ",a]})]}):t.jsxs("a",{href:x,download:a,className:"text-sm text-accent hover:underline",children:["Download ",a]})}function se(e,s){if(e.startsWith("image/"))return"image";if(e.startsWith("audio/"))return"audio";if(e.startsWith("video/"))return"video";if(e==="application/pdf")return"pdf";const a=s.toLowerCase().split(".").pop()??"";return["png","jpg","jpeg","gif","webp","svg"].includes(a)?"image":["mp3","wav","ogg","m4a","flac"].includes(a)?"audio":["mp4","webm","mov"].includes(a)?"video":a==="pdf"?"pdf":"other"}function re(e){return e<1024?`${e} B`:e<1024*1024?`${(e/1024).toFixed(1)} KB`:e<1024*1024*1024?`${(e/(1024*1024)).toFixed(1)} MB`:`${(e/(1024*1024*1024)).toFixed(2)} GB`}function ne(){return t.jsxs("div",{className:"grid gap-10 lg:grid-cols-[minmax(0,1fr)_18rem]","aria-busy":"true",children:[t.jsxs("div",{className:"min-w-0 space-y-3",children:[t.jsx("div",{className:"h-3 w-32 animate-pulse rounded bg-border/40"}),t.jsx("div",{className:"h-8 w-2/3 animate-pulse rounded bg-border/60"}),t.jsx("div",{className:"h-4 w-full animate-pulse rounded bg-border/30"}),t.jsx("div",{className:"mt-6 space-y-2",children:[0,1,2,3,4,5].map(e=>t.jsx("div",{className:"h-3 animate-pulse rounded bg-border/30",style:{width:`${70+e*13%25}%`}},e))})]}),t.jsxs("div",{className:"space-y-4",children:[t.jsx("div",{className:"h-32 animate-pulse rounded bg-border/30"}),t.jsx("div",{className:"h-24 animate-pulse rounded bg-border/30"})]})]})}function ae({id:e}){return t.jsxs("div",{className:"rounded-md border border-border bg-card p-10 text-center",children:[t.jsx("p",{className:"mb-2 font-serif text-xl",children:"Note not found"}),t.jsxs("p",{className:"mb-4 text-sm text-fg-muted",children:["No note with id ",t.jsx("span",{className:"font-mono",children:e})," in this vault."]}),t.jsx(p,{to:"/",className:"text-sm text-accent hover:underline",children:"Back to all notes"})]})}function oe({error:e}){const s=e instanceof L;return t.jsxs("div",{className:"rounded-md border border-red-500/30 bg-red-500/5 p-6",children:[t.jsx("p",{className:"mb-2 font-medium text-red-400",children:s?"Session expired":"Could not load note"}),t.jsx("p",{className:"mb-4 text-sm text-fg-muted",children:e.message}),s?t.jsx(p,{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{ce as NoteView}; |
| import{c as y,y as j,u as N,r as l,J as w,K as E,M as V,O as S,P as C,j as e}from"./index-DKKYWfqC.js";function R(){const[a]=y(),s=j(),d=N(c=>c.addVault),[n,o]=l.useState({kind:"working"}),u=l.useRef(!1);return l.useEffect(()=>{if(u.current)return;u.current=!0;const c=a.get("code"),p=a.get("state"),x=a.get("error");if(x){o({kind:"error",message:`Vault returned: ${x}`});return}if(!c||!p){o({kind:"error",message:"Missing code or state in callback URL."});return}(async()=>{var m,h,g,v;try{const{pending:t,token:r}=await w(c,p),f=r.vault?`vault:${r.vault}`:void 0,k=(f?(h=(m=r.services)==null?void 0:m[f])==null?void 0:h.url:void 0)??((v=(g=r.services)==null?void 0:g.vault)==null?void 0:v.url)??t.issuerUrl,i=d({url:k,name:r.vault,issuer:t.issuer,tokenEndpoint:t.tokenEndpoint,clientId:t.clientId,scope:r.scope},E(r));r.services&&V(i,r.services);const b=S.getState();b.clearHalt(i),t.priorHaltedVaultId&&t.priorHaltedVaultId!==i&&b.clearHalt(t.priorHaltedVaultId),s("/",{replace:!0})}catch(t){if(t instanceof C){o({kind:"pending-approval",approveUrl:t.approveUrl});return}o({kind:"error",message:t.message})}})()},[a,s,d]),n.kind==="working"?e.jsxs("div",{className:"mx-auto max-w-xl px-6 py-24 text-center",children:[e.jsx("h1",{className:"mb-3 font-serif text-3xl",children:"Connecting…"}),e.jsx("p",{className:"text-fg-muted",children:"Exchanging the authorization code with your vault."})]}):n.kind==="pending-approval"?e.jsxs("div",{className:"mx-auto max-w-xl px-6 py-24 text-center",children:[e.jsx("h1",{className:"mb-3 font-serif text-3xl",children:"Waiting for hub approval"}),e.jsx("p",{className:"mb-8 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-3",children:[e.jsx("a",{href:n.approveUrl,target:"_blank",rel:"noopener noreferrer",className:"inline-block rounded-md bg-accent px-4 py-2 text-sm text-white hover:bg-accent-hover",children:"Open approval page"}),e.jsx("button",{type:"button",onClick:()=>s("/add",{replace:!0}),className:"inline-block rounded-md border border-border bg-card px-4 py-2 text-sm text-fg-muted hover:text-accent",children:"Retry now"})]})]}):e.jsxs("div",{className:"mx-auto max-w-xl px-6 py-24 text-center",children:[e.jsx("h1",{className:"mb-3 font-serif text-3xl text-red-400",children:"Connection failed"}),e.jsx("p",{className:"mb-8 text-fg-muted",children:n.message}),e.jsx("button",{type:"button",onClick:()=>s("/add",{replace:!0}),className:"rounded-md bg-accent px-4 py-2 text-sm text-white hover:bg-accent-hover",children:"Try again"})]})}export{R as OAuthCallback}; |
| import{r as c,j as t,y as v,g,G as j,V as y,u as w,i as E,z as N}from"./index-DKKYWfqC.js";function P({note:a,className:o,label:l="Delete"}){const[r,d]=c.useState(!1);return t.jsxs(t.Fragment,{children:[t.jsx("button",{type:"button",onClick:()=>d(!0),className:o??"min-h-11 rounded-md 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:l}),r?t.jsx(k,{note:a,onClose:()=>d(!1)}):null]})}function k({note:a,onClose:o}){const l=v(),r=g(e=>e.push),d=j(),i=a.path??a.id,[m,p]=c.useState(""),[u,b]=c.useState(null),x=c.useRef(null),s=m===i&&!d.isPending;c.useEffect(()=>{var e;(e=x.current)==null||e.focus()},[]),c.useEffect(()=>{const e=f=>{f.key==="Escape"&&o()};return window.addEventListener("keydown",e),()=>window.removeEventListener("keydown",e)},[o]);const n=c.useCallback(()=>{s&&(b(null),d.mutate(a.id,{onSuccess:()=>{r(`Deleted ${i}`,"success"),l("/")},onError:e=>{e instanceof y?b("Session expired. Reconnect to delete."):b(e instanceof Error?e.message:"Delete failed")}}))},[s,i,d,l,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&&o()},children:t.jsxs("div",{className:"w-full max-w-md rounded-md border border-border bg-card p-6 shadow-xl",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:m,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-md 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:o,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"}),t.jsx("button",{type:"button",onClick:n,disabled:!s,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:d.isPending?"Deleting…":"Delete permanently"})]})]})})}function C({note:a,keyboard:o=!1}){var b,x;const l=w(s=>s.getActiveVault()),{roles:r}=E((l==null?void 0:l.id)??null),d=g(s=>s.push),i=N(a.id),m=((b=a.tags)==null?void 0:b.includes(r.pinned))??!1,p=((x=a.tags)==null?void 0:x.includes(r.archived))??!1,u=c.useCallback(s=>{var f;if(i.isPending)return;const n=r[s],e=((f=a.tags)==null?void 0:f.includes(n))??!1;i.mutate({tags:e?{remove:[n]}:{add:[n]}},{onSuccess:()=>{d(s==="pinned"?e?"Unpinned":"Pinned":e?"Unarchived":"Archived","success")},onError:h=>{h instanceof y?d("Session expired. Reconnect.","error"):d(h instanceof Error?h.message:"Update failed","error")}})},[i,a.tags,d,r]);return c.useEffect(()=>{if(!o)return;const s=n=>{if(n.defaultPrevented)return;const e=n.target;if(e){const f=e.tagName;if(f==="INPUT"||f==="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)},[o,u]),t.jsxs(t.Fragment,{children:[t.jsx("button",{type:"button",onClick:()=>u("pinned"),disabled:i.isPending,"aria-pressed":m,title:m?`Unpin (${r.pinned})`:`Pin as #${r.pinned} (P)`,className:m?"min-h-11 rounded-md 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-md border border-border bg-card px-3 py-1.5 text-sm text-fg-muted hover:text-accent disabled:opacity-40",children:m?"★ 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-md 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-md 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}; |
Sorry, the diff of this file is too big to display
| import{u as T,j as e,N as k,L as E,Q as b,R as A,k as C,g as S,r as o,U as R,W as L,X as _,Y as D,Z as z,i as P,$ as V,a0 as v,a1 as j,a2 as M,a3 as O,a4 as $,a5 as F}from"./index-DKKYWfqC.js";function Z(){const t=T(s=>s.getActiveVault());return t?e.jsxs("div",{className:"mx-auto max-w-2xl px-4 py-7 md:px-6 md:py-12",children:[e.jsxs("header",{className:"mb-8",children:[e.jsx("nav",{className:"mb-3 text-sm text-fg-dim",children:e.jsx(E,{to:"/",className:"hover:text-accent",children:"← Home"})}),e.jsx("h1",{className:"font-serif text-2xl tracking-tight md:text-3xl",children:"Settings"}),e.jsxs("p",{className:"mt-1 text-sm text-fg-muted",children:["Configuring ",e.jsx("span",{className:"text-fg",children:t.name}),"."]})]}),e.jsx(I,{vaultId:t.id}),e.jsx(U,{}),e.jsx(G,{vaultId:t.id}),e.jsx(Q,{vaultId:t.id}),e.jsx(Y,{})]}):e.jsx(k,{to:"/",replace:!0})}function I({vaultId:t}){const s=b(l=>l.byVault[t]??null),r=b(l=>l.refresh),n=b(l=>l.set),h=A(l=>l.clearDismissed),i=C(),d=S(l=>l.push),[x,u]=o.useState(!1),f=async()=>{i&&await r(t,i)},g=async()=>{var l;if(i){u(!0);try{await O(t,i);const m=(l=s==null?void 0:s.result)==null?void 0:l.rows.map(w=>({...w,status:"ok",differences:[]}));m&&n(t,{ok:!0,missing:[],misaligned:[],rows:m}),h(t),d("Schema updated.","success")}catch(m){d(m instanceof Error?`Schema fix failed: ${m.message}`:"Schema fix failed.","error")}finally{u(!1)}}},p=(s==null?void 0:s.loading)??!s,a=(s==null?void 0:s.result)??null,c=(s==null?void 0:s.error)??null;return e.jsxs("section",{className:"mt-6 space-y-4 rounded-xl border border-border bg-card p-6",children:[e.jsxs("div",{className:"flex items-baseline justify-between gap-3",children:[e.jsxs("div",{children:[e.jsx("h2",{className:"font-serif text-xl text-fg",children:"Vault schema"}),e.jsxs("p",{className:"mt-1 text-xs text-fg-dim",children:["Notes declares three tags it uses to classify captures: ",e.jsx("code",{children:"capture"}),","," ",e.jsx("code",{children:"capture/text"}),", ",e.jsx("code",{children:"capture/voice"}),". This panel confirms the active vault has them set up; one click writes any missing or misaligned rows. Doesn't touch your Tag Role choices below."]})]}),e.jsx("button",{type:"button",onClick:()=>void f(),disabled:p||!i,className:"shrink-0 text-xs text-fg-dim hover:text-accent disabled:cursor-not-allowed disabled:opacity-60",children:p?"Checking…":"Refresh"})]}),c?e.jsxs("p",{className:"rounded-md border border-red-500/30 bg-red-500/5 px-3 py-2 text-xs text-red-300",children:["Audit failed: ",c]}):null,!a&&!c?e.jsx("p",{className:"text-xs text-fg-dim",children:"Loading audit…"}):null,a?e.jsxs(e.Fragment,{children:[e.jsx(H,{ok:a.ok}),e.jsx("ul",{className:"space-y-2",children:a.rows.map(l=>e.jsx(B,{row:l},l.name))}),a.ok?null:e.jsx("button",{type:"button",onClick:()=>void g(),disabled:x||!i,className:"min-h-11 rounded-md bg-accent px-3 py-1.5 text-xs font-medium text-white hover:bg-accent-hover disabled:cursor-not-allowed disabled:opacity-60",children:x?"Setting up…":"Set up missing tags"})]}):null]})}function H({ok:t}){return e.jsxs("p",{className:`inline-flex items-center gap-1.5 rounded-full px-2 py-0.5 text-xs ${t?"bg-emerald-500/20 text-emerald-300":"bg-amber-500/20 text-amber-300"}`,children:[e.jsx("span",{"aria-hidden":!0,className:`h-1.5 w-1.5 rounded-full ${t?"bg-emerald-400":"bg-amber-400"}`}),t?"Matches Notes' schema":"Needs setup"]})}function B({row:t}){const s=t.status==="ok"?"ok":t.status==="missing"?"missing":"misaligned",r=t.status==="ok"?"text-emerald-300":"text-amber-300";return e.jsxs("li",{className:"rounded-md border border-border bg-bg/40 px-3 py-2 text-xs",children:[e.jsxs("div",{className:"flex items-center justify-between gap-2",children:[e.jsx("code",{className:"font-mono text-sm text-fg",children:t.name}),e.jsx("span",{className:`text-xs ${r}`,children:s})]}),t.status==="misaligned"?e.jsxs("p",{className:"mt-1 text-fg-dim",children:["Differs in: ",t.differences.join(", ")]}):null,e.jsx("p",{className:"mt-1 text-fg-dim",children:t.expected.description}),t.expected.parent_names?e.jsxs("p",{className:"text-fg-dim",children:["Parent: ",e.jsx("code",{className:"font-mono",children:t.expected.parent_names.join(", ")})]}):null]})}function U(){const[t,s]=o.useState(()=>R()),r=n=>{s(n),$(n),F(n)};return e.jsxs("section",{className:"mt-6 space-y-4 rounded-xl border border-border bg-card p-6",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-xs text-fg-dim",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"}),L.map(n=>e.jsxs("label",{className:"flex items-start gap-2 text-sm",children:[e.jsx("input",{type:"radio",name:"text-size",value:n,checked:t===n,onChange:()=>r(n),className:"mt-1 accent-accent"}),e.jsx("span",{className:"text-fg",children:_(n)})]},n))]})]})}function Y(){const[t,s]=o.useState(!1);return o.useEffect(()=>{s(M())},[]),t?e.jsx("section",{className:"mt-6 rounded-md border border-border bg-card p-4 text-sm",children:e.jsxs("p",{className:"text-fg-muted",children:[e.jsx("span",{className:"mr-2 inline-block rounded-full bg-emerald-500/20 px-2 py-0.5 text-xs font-medium text-emerald-300",children:"Installed"}),"Parachute Notes is running as an installed app on this device."]})}):null}const y={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 G({vaultId:t}){const{mode:s,setMode:r}=D(t);return e.jsxs("section",{className:"mt-6 space-y-4 rounded-xl border border-border bg-card p-6",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-xs text-fg-dim",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"}),z.map(n=>e.jsxs("label",{className:"flex items-start gap-2 text-sm",children:[e.jsx("input",{type:"radio",name:"path-tree-mode",value:n,checked:s===n,onChange:()=>r(n),className:"mt-1 accent-accent"}),e.jsxs("span",{children:[e.jsx("span",{className:"text-fg",children:y[n].title}),e.jsx("span",{className:"ml-2 text-xs text-fg-dim",children:y[n].help})]})]},n))]})]})}const N={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:"Voice capture",help:"Default tag for new voice memos."},captureText:{title:"Text capture",help:"Default tag for quick typed notes."},view:{title:"Saved view",help:"Tag the saved-view notes carry. Used to list them in the notes sidebar."}};function Q({vaultId:t}){const{roles:s,setRoles:r}=P(t),n=V(),h=S(a=>a.push),i=o.useId(),[d,x]=o.useState(s);o.useEffect(()=>x(s),[s]);const u=o.useMemo(()=>{const a=(n.data??[]).map(c=>c.name);return[...new Set(a)].sort((c,l)=>c.localeCompare(l))},[n.data]),f=v.some(a=>d[a].trim()!==s[a]),g=()=>{r(d),h("Tag roles saved.","success")},p=()=>{r(null),x(j),h("Tag roles reset to defaults.","success")};return e.jsxs("section",{className:"mt-6 space-y-4 rounded-xl border border-border bg-card p-6",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-xs text-fg-dim",children:"Point each role at whatever tag your vault already uses. Changes apply to future notes only — existing notes keep their current tags."})]}),e.jsx("datalist",{id:i,children:u.map(a=>e.jsx("option",{value:a},a))}),e.jsx("div",{className:"space-y-3",children:v.map(a=>e.jsxs("label",{className:"block text-sm",children:[e.jsxs("span",{className:"mb-1 flex items-baseline justify-between gap-2",children:[e.jsx("span",{className:"text-fg-muted",children:N[a].title}),e.jsxs("span",{className:"text-xs text-fg-dim",children:["default: #",j[a]]})]}),e.jsx("input",{type:"text",value:d[a],onChange:c=>x(l=>({...l,[a]:c.target.value})),list:i,placeholder:j[a],"aria-label":`${N[a].title} tag role`,spellCheck:!1,autoCapitalize:"none",autoCorrect:"off",className:"w-full 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"}),e.jsx("span",{className:"mt-1 block text-xs text-fg-dim",children:N[a].help})]},a))}),e.jsxs("div",{className:"flex flex-wrap items-center gap-3 pt-2",children:[e.jsx("button",{type:"button",onClick:g,disabled:!f,className:"rounded-md bg-accent px-4 py-2 text-sm font-medium text-white hover:bg-accent-hover disabled:opacity-40",children:"Save"}),e.jsx("button",{type:"button",onClick:p,className:"text-sm text-fg-muted hover:text-accent",children:"Reset to defaults"})]})]})}export{Z as Settings}; |
| import{g as P,r as l,a6 as O,V as R,j as e,u as L,$ as F,h as I,a7 as V,a8 as z,a9 as D,N as B,L as E}from"./index-DKKYWfqC.js";const $=a=>Object.values(a).reduce((n,x)=>n+x,0);function A({mode:a,sources:n,tagOptions:x,onClose:c,onRun:d,onRunMerge:o,pending:i,offline:m}){const p=P(t=>t.push),g=l.useId(),[S,j]=l.useState(a==="rename"?n[0]??"":""),[T,h]=l.useState(null),[u,y]=l.useState(null),[b,N]=l.useState(!1),v=l.useRef(null);l.useEffect(()=>{var t,r;(t=v.current)==null||t.focus(),(r=v.current)==null||r.select()},[]),l.useEffect(()=>{const t=r=>{r.key==="Escape"&&c()};return window.addEventListener("keydown",t),()=>window.removeEventListener("keydown",t)},[c]);const w=S.trim().replace(/^#/,""),f=!i&&!m&&!b&&w.length>0&&!(a==="rename"&&w===n[0]),C=l.useCallback(async()=>{if(f){h(null),y(null);try{const t=await d(w);if("renamed"in t)p(`Renamed on ${t.renamed} note${t.renamed===1?"":"s"}.`,"success");else{const r=$(t.merged);p(`Merged into #${t.target} on ${r} note${r===1?"":"s"}.`,"success")}c()}catch(t){if(t instanceof O&&a==="rename"&&o){y(t.target);return}t instanceof R?h("Session expired. Reconnect to retry."):h(t instanceof Error?t.message:"Operation failed.")}}},[f,w,a,c,d,o,p]),k=l.useCallback(async()=>{if(!(!u||!o)){h(null),N(!0);try{const t=await o(u),r=$(t.merged);p(`Merged into #${t.target} on ${r} note${r===1?"":"s"}.`,"success"),c()}catch(t){t instanceof R?h("Session expired. Reconnect to retry."):h(t instanceof Error?t.message:"Merge failed."),N(!1)}}},[u,c,o,p]),s=a==="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:t=>{t.target===t.currentTarget&&c()},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:"tag-op-title",className:"mb-2 font-serif text-xl text-fg",children:s}),e.jsxs("p",{className:"mb-3 text-sm text-fg-muted",children:[a==="rename"?e.jsxs(e.Fragment,{children:["Rename ",e.jsx(M,{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((t,r)=>e.jsxs("span",{children:[e.jsx(M,{children:t}),r<n.length-1?", ":""]},t))," ","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:a==="rename"?"New tag name":"Target tag"}),e.jsx("input",{ref:v,type:"text",value:S,onChange:t=>{j(t.target.value),u&&y(null)},onKeyDown:t=>{t.key==="Enter"&&f&&C()},list:g,"aria-label":a==="rename"?"New tag name":"Merge target tag",spellCheck:!1,autoCapitalize:"none",autoCorrect:"off",className:"w-full rounded-md 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:g,children:x.map(t=>e.jsx("option",{value:t},t))})]}),m?e.jsx("p",{className:"mb-3 text-sm text-amber-300",children:"Offline — tag operations need a live vault connection."}):null,u?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(M,{children:u})," already exists."]}),e.jsxs("p",{className:"mb-3 text-fg-muted",children:["Merge ",e.jsx(M,{children:n[0]})," into ",e.jsx(M,{children:u})," instead? Notes that carry both end up with one copy."]}),e.jsx("button",{type:"button",onClick:()=>void k(),disabled:b,className:"rounded-md bg-accent px-3 py-1.5 text-xs font-medium text-white hover:bg-accent-hover disabled:opacity-40",children:b?"Merging…":`Merge into #${u}`})]}):null,T?e.jsx("p",{role:"alert",className:"mb-3 text-sm text-red-400",children:T}):null,e.jsxs("div",{className:"flex justify-end gap-2",children:[e.jsx("button",{type:"button",onClick:c,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:()=>void C(),disabled:!f,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",children:i?a==="rename"?"Renaming…":"Merging…":a==="rename"?"Rename":"Merge"})]})]})})}function M({children:a}){return e.jsxs("span",{className:"rounded bg-bg/60 px-1 py-0.5 font-mono text-xs text-fg",children:["#",a]})}function J(){const a=L(s=>s.getActiveVault()),n=F(),{isOnline:x}=I(),{isPinned:c,togglePin:d}=V((a==null?void 0:a.id)??null),[o,i]=l.useState(""),[m,p]=l.useState("count"),[g,S]=l.useState(new Set),[j,T]=l.useState(null),[h,u]=l.useState(!1),y=z(),b=D(),N=l.useMemo(()=>U(n.data??[],o,m),[n.data,o,m]),v=l.useMemo(()=>(n.data??[]).map(s=>s.name),[n.data]),w=s=>{S(t=>{const r=new Set(t);return r.has(s)?r.delete(s):r.add(s),r})},f=()=>S(new Set);if(!a)return e.jsx(B,{to:"/",replace:!0});const C=g.size,k=!x;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-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:"text-xs uppercase tracking-wider text-fg-dim",children:a.name}),e.jsx("h1",{className:"font-serif text-2xl tracking-tight md:text-3xl",children:"Tags"})]}),e.jsxs("button",{type:"button",onClick:()=>p(s=>s==="count"?"alpha":"count"),className:"text-sm text-fg-muted hover:text-accent","aria-label":"Toggle tag sort",children:["Sort: ",m==="count"?"most used":"A–Z"]})]}),e.jsx("input",{type:"search",placeholder:"Filter tags…",value:o,onChange:s=>i(s.target.value),"aria-label":"Filter tags",className:"mb-4 w-full rounded-md border border-border bg-card px-3 py-2 text-sm text-fg focus:border-accent focus:outline-none"}),C>0?e.jsxs("div",{className:"mb-4 flex flex-wrap items-center gap-3 rounded-md border border-accent/30 bg-accent/5 px-3 py-2 text-sm","aria-label":"Tag selection actions",children:[e.jsxs("span",{className:"text-fg-muted",children:[C," selected: ",Array.from(g).join(", ")]}),e.jsx("button",{type:"button",onClick:()=>u(!0),disabled:C<2||k,className:"rounded-md bg-accent px-3 py-1 text-xs font-medium text-white hover:bg-accent-hover disabled:opacity-40",children:"Merge into…"}),e.jsx("button",{type:"button",onClick:f,className:"text-xs text-fg-muted hover:text-accent",children:"Clear"})]}):null,n.isPending?e.jsx(Z,{}):n.isError?e.jsx(q,{error:n.error}):N.length===0?e.jsx(G,{filtering:o.trim().length>0,hasAny:(n.data??[]).length>0}):e.jsx("ul",{className:"divide-y divide-border rounded-md border border-border bg-card","aria-label":"Tag list",children:N.map(s=>e.jsx(K,{tag:s,selected:g.has(s.name),onToggle:()=>w(s.name),onRename:()=>T(s.name),pinned:c(s.name),onTogglePin:()=>d(s.name),offline:k},s.name))}),n.data&&n.data.length>0?e.jsxs("p",{className:"mt-6 text-xs text-fg-dim",children:[N.length," / ",n.data.length," tag",n.data.length===1?"":"s"]}):null,j!==null?e.jsx(A,{mode:"rename",sources:[j],tagOptions:v,onClose:()=>T(null),pending:y.isPending||b.isPending,offline:k,onRun:s=>y.mutateAsync({oldName:j,newName:s}),onRunMerge:s=>b.mutateAsync({sources:[j],target:s})}):null,h?e.jsx(A,{mode:"merge",sources:Array.from(g),tagOptions:v,onClose:()=>u(!1),pending:b.isPending,offline:k,onRun:async s=>{const t=await b.mutateAsync({sources:Array.from(g),target:s});return f(),t}}):null]})}function K({tag:a,selected:n,onToggle:x,onRename:c,pinned:d,onTogglePin:o,offline:i}){return e.jsxs("li",{className:"flex items-center gap-3 px-3 py-2 text-sm",children:[e.jsx("input",{type:"checkbox",checked:n,onChange:x,"aria-label":`Select tag ${a.name}`,className:"accent-accent"}),e.jsxs(E,{to:`/?tag=${encodeURIComponent(a.name)}`,className:"flex flex-1 items-baseline gap-2 text-fg hover:text-accent focus-visible:outline-2 focus-visible:outline-accent",children:[e.jsxs("span",{className:"font-mono",children:["#",a.name]}),e.jsx("span",{className:"text-xs text-fg-dim",children:a.count})]}),e.jsx("button",{type:"button",onClick:o,className:d?"text-xs font-medium text-accent hover:text-accent-hover":"text-xs text-fg-muted hover:text-accent","aria-label":d?`Unpin tag ${a.name}`:`Pin tag ${a.name}`,"aria-pressed":d,title:d?"Pinned to home strip — click to unpin":"Pin to home strip",children:d?"★ Pinned":"☆ Pin"}),e.jsx("button",{type:"button",onClick:c,disabled:i,className:"text-xs text-fg-muted hover:text-accent disabled:opacity-40","aria-label":`Rename tag ${a.name}`,children:"Rename"})]})}function U(a,n,x){const c=n.trim().toLowerCase(),o=[...c?a.filter(i=>i.name.toLowerCase().includes(c)):a];return x==="alpha"?o.sort((i,m)=>i.name.localeCompare(m.name)):o.sort((i,m)=>m.count-i.count||i.name.localeCompare(m.name)),o}function Z(){return e.jsx("div",{className:"divide-y divide-border rounded-md border border-border bg-card","aria-busy":"true",children:[0,1,2,3,4].map(a=>e.jsx("div",{className:"h-10 animate-pulse bg-card/60"},a))})}function q({error:a}){const n=a instanceof R;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 tags"}),e.jsx("p",{className:"mb-4 text-sm text-fg-muted",children:a.message}),n?e.jsx(E,{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 G({filtering:a,hasAny:n}){return a&&n?e.jsx("div",{className:"rounded-md border border-border bg-card p-10 text-center",children:e.jsx("p",{className:"text-fg-muted",children:"No tags match your filter."})}):e.jsxs("div",{className:"rounded-md border border-border bg-card p-10 text-center",children:[e.jsx("p",{className:"mb-3 text-fg-muted",children:"No tags in this vault yet."}),e.jsx(E,{to:"/new",className:"inline-block rounded-md bg-accent px-4 py-2 text-sm font-medium text-white hover:bg-accent-hover",children:"Create a note"})]})}export{J as Tags}; |
| import{u as w,c as $,a as A,r as D,j as e,N as E,L as d,b as C,V as S}from"./index-DKKYWfqC.js";import{t as V,d as N,a as g,e as K,b as f}from"./dates-DfXc2iZW.js";function F(){const a=w(i=>i.getActiveVault()),[s]=$(),t=s.get("date"),u=V(),r=t??u,x=N(r),n=A(),c=D.useMemo(()=>{const i=[],m=[];if(!n.data||!x)return{created:i,edited:m};for(const l of n.data){const b=g(l.createdAt),k=g(l.updatedAt??l.createdAt);b===r&&i.push(l),k===r&&b!==r&&m.push(l)}return{created:i,edited:m}},[n.data,x,r]);if(!a)return e.jsx(E,{to:"/",replace:!0});if(!x)return e.jsxs("div",{className:"mx-auto max-w-3xl px-4 py-6 md:px-6 md:py-10",children:[e.jsxs("p",{className:"text-sm text-red-400",children:["Invalid date in URL: ",r]}),e.jsx(d,{to:"/today",className:"text-sm text-accent hover:underline",children:"Back to today"})]});const o=r===u,p=j(r,-1),h=j(r,1),v=r.slice(0,7);return 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-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:o?"Today":"On"}),e.jsx("h1",{className:"font-serif text-2xl tracking-tight md:text-3xl",children:K(r)})]}),e.jsxs("div",{className:"flex flex-wrap items-center gap-2 text-sm",children:[e.jsxs(d,{to:`/today?date=${p}`,className:"rounded-md border border-border bg-card px-3 py-1.5 text-fg-muted hover:text-accent","aria-label":"Previous day",children:["← ",p]}),o?null:e.jsx(d,{to:"/today",className:"rounded-md border border-border bg-card px-3 py-1.5 text-fg-muted hover:text-accent",children:"Today"}),e.jsxs(d,{to:`/today?date=${h}`,className:"rounded-md border border-border bg-card px-3 py-1.5 text-fg-muted hover:text-accent","aria-label":"Next day",children:[h," →"]}),e.jsx(d,{to:`/calendar?month=${v}`,className:"rounded-md border border-border bg-card px-3 py-1.5 text-fg-muted hover:text-accent",children:"Calendar"}),e.jsx(d,{to:"/capture",className:"rounded-md bg-accent px-3 py-1.5 font-medium text-white hover:bg-accent-hover",children:"+ Capture"})]})]}),n.isPending?e.jsx(L,{}):n.isError?e.jsx(R,{error:n.error}):c.created.length===0&&c.edited.length===0?e.jsx(P,{isToday:o,targetKey:r}):e.jsxs("div",{className:"space-y-8",children:[c.created.length>0?e.jsx(y,{title:o?"Created today":`Created on ${r}`,notes:c.created}):null,c.edited.length>0?e.jsx(y,{title:o?"Edited today":`Edited on ${r}`,notes:c.edited}):null]})]})}function j(a,s){const t=N(a);return t?(t.setDate(t.getDate()+s),`${t.getFullYear()}-${f(t.getMonth()+1)}-${f(t.getDate())}`):a}function y({title:a,notes:s}){return e.jsxs("section",{children:[e.jsxs("h2",{className:"mb-2 text-xs uppercase tracking-wider text-fg-dim",children:[a," (",s.length,")"]}),e.jsx("ol",{className:"divide-y divide-border rounded-md border border-border bg-card",children:s.map(t=>e.jsx("li",{children:e.jsxs(d,{to:`/n/${encodeURIComponent(t.id)}`,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.jsx("span",{className:"truncate font-mono text-sm text-fg",children:t.path??t.id}),e.jsx("span",{className:"shrink-0 text-xs text-fg-dim",children:C(t.updatedAt??t.createdAt)})]}),t.preview?e.jsx("p",{className:"mt-1 truncate text-sm text-fg-muted",children:t.preview}):null]})},t.id))})]})}function P({isToday:a,targetKey: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:a?"Nothing yet today — start capturing.":`Nothing on ${s}.`}),a?e.jsx(d,{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"}):null]})}function L(){return e.jsx("div",{className:"space-y-3","aria-busy":"true",children:[0,1,2,3].map(a=>e.jsx("div",{className:"h-14 animate-pulse rounded-md bg-border/30"},a))})}function R({error:a}){const s=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:s?"Session expired":"Could not load notes"}),e.jsx("p",{className:"mb-4 text-sm text-fg-muted",children:a.message}),s?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{F as Today}; |
Sorry, the diff of this file is too big to display
| const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/react-force-graph-2d-YVoN3oXw.js","assets/index-DKKYWfqC.js","assets/index-BU6cVU21.css"])))=>i.map(i=>d[i]); | ||
| import{u as w,aa as N,r as f,j as s,N as k,L as v,y as C,V as I,_ as M}from"./index-DKKYWfqC.js";const S={search:"",tags:[]};function T(e){const t=new Map;for(const i of e)t.set(i.id,i);const a=new Map,o=new Map;for(const i of e)for(const n of i.links??[]){if(n.sourceId===n.targetId||!t.has(n.sourceId)||!t.has(n.targetId))continue;const c=`${n.sourceId}|${n.targetId}|${n.relationship}`;a.has(c)||(a.set(c,{source:n.sourceId,target:n.targetId,relationship:n.relationship}),o.set(n.sourceId,(o.get(n.sourceId)??0)+1),o.set(n.targetId,(o.get(n.targetId)??0)+1))}return{nodes:e.map(i=>{var c;const n=i.tags??[];return{id:i.id,path:i.path,title:A(i),tags:n,topTag:n[0],degree:o.get(i.id)??0,summary:typeof((c=i.metadata)==null?void 0:c.summary)=="string"?i.metadata.summary:void 0}}),edges:[...a.values()]}}function A(e){return e.path?(e.path.split("/").pop()??e.path).replace(/\.md$/i,""):e.id}function R(e,t){const a=t.search.trim().toLowerCase();return!(a&&![e.path??"",e.title,e.id].join(" ").toLowerCase().includes(a)||t.tags.length>0&&!t.tags.some(d=>e.tags.includes(d)))}function E(e){const t=new Map;for(const a of e)for(const o of a.tags)t.set(o,(t.get(o)??0)+1);return[...t.entries()].sort((a,o)=>o[1]-a[1]||a[0].localeCompare(o[0])).map(([a])=>a)}function _(e){if(!e)return"#8a9a7a";let t=0;for(let o=0;o<e.length;o++)t=t*31+e.charCodeAt(o)&16777215;return`hsl(${t%360}, 40%, 55%)`}const F=f.lazy(()=>M(()=>import("./react-force-graph-2d-YVoN3oXw.js"),__vite__mapDeps([0,1,2]))),L=20;function O(){const e=w(c=>c.getActiveVault()),t=N(),[a,o]=f.useState(S),d=f.useMemo(()=>t.data?T(t.data):null,[t.data]),i=f.useMemo(()=>d?E(d.nodes):[],[d]),n=f.useMemo(()=>d?new Set(d.nodes.filter(c=>R(c,a)).map(c=>c.id)):new Set,[d,a]);return e?s.jsxs("div",{className:"flex h-[calc(100dvh-5rem)] flex-col",children:[s.jsx("div",{className:"border-b border-border bg-card/40 px-6 py-3",children:s.jsxs("div",{className:"mx-auto flex max-w-6xl flex-wrap items-center gap-4",children:[s.jsx("input",{type:"search",value:a.search,onChange:c=>o(m=>({...m,search:c.target.value})),placeholder:"Search nodes…","aria-label":"Search graph nodes",className:"min-w-48 rounded-md border border-border bg-card px-3 py-1.5 text-sm text-fg focus:border-accent focus:outline-none"}),s.jsx($,{allTags:i,selected:a.tags,onChange:c=>o(m=>({...m,tags:c}))}),d?s.jsxs("span",{className:"text-xs text-fg-dim",children:[n.size," / ",d.nodes.length," notes"]}):null]})}),s.jsx("div",{className:"min-h-0 flex-1",children:s.jsx(P,{query:t,graph:d,matched:n})})]}):s.jsx(k,{to:"/",replace:!0})}function P({query:e,graph:t,matched:a}){return e.isPending?s.jsx(y,{message:"Loading vault…"}):e.isError?s.jsx(B,{error:e.error}):!t||t.nodes.length===0?s.jsx("div",{className:"flex h-full items-center justify-center p-10",children:s.jsxs("div",{className:"max-w-sm rounded-md border border-border bg-card p-8 text-center",children:[s.jsx("p",{className:"mb-2 font-serif text-xl",children:"No notes yet"}),s.jsx("p",{className:"mb-4 text-sm text-fg-muted",children:"This vault is empty. Start by creating the first note."}),s.jsx(v,{to:"/new",className:"inline-block rounded-md bg-accent px-4 py-2 text-sm font-medium text-white hover:bg-accent-hover",children:"Create a note"})]})}):s.jsx(z,{graph:t,matched:a})}function $({allTags:e,selected:t,onChange:a}){const o=e.slice(0,L);if(o.length===0)return null;const d=i=>a(t.includes(i)?t.filter(n=>n!==i):[...t,i]);return s.jsxs("fieldset",{"aria-label":"Filter by tag",className:"flex flex-wrap items-center gap-1 text-xs text-fg-dim",children:[s.jsx("legend",{className:"mr-1 inline-block",children:"Tags"}),o.map(i=>{const n=t.includes(i);return s.jsx("button",{type:"button","aria-pressed":n,onClick:()=>d(i),className:n?"max-w-full break-all rounded-full border border-accent bg-accent/10 px-2 py-0.5 text-accent":"max-w-full break-all rounded-full border border-border bg-card px-2 py-0.5 hover:text-accent",children:i},i)}),t.length>0?s.jsx("button",{type:"button",onClick:()=>a([]),className:"ml-1 text-xs text-fg-dim hover:text-accent",children:"Clear"}):null]})}function y({message:e}){return s.jsx("div",{"aria-busy":"true",className:"flex h-full animate-pulse items-center justify-center bg-card/30 text-sm text-fg-dim",children:e})}function z({graph:e,matched:t}){const a=C(),o=f.useRef(null),d=f.useRef(null),[i,n]=f.useState({w:800,h:600});f.useEffect(()=>{const r=o.current;if(!r)return;const l=()=>{const u=r.getBoundingClientRect();n({w:Math.max(320,Math.floor(u.width)),h:Math.max(320,Math.floor(u.height))})};l();const h=new ResizeObserver(l);return h.observe(r),()=>h.disconnect()},[]);const c=()=>{var r,l;(l=(r=d.current)==null?void 0:r.zoomToFit)==null||l.call(r,400,40)},m=f.useMemo(()=>({nodes:e.nodes.map(r=>({...r})),links:e.edges.map(r=>({source:r.source,target:r.target,rel:r.relationship}))}),[e]),g=t.size!==e.nodes.length,j=r=>!g||t.has(r)?1:.15;return s.jsxs("div",{ref:o,"data-testid":"vault-graph-canvas",className:"relative h-full w-full touch-none",children:[s.jsx(f.Suspense,{fallback:s.jsx(y,{message:"Rendering graph…"}),children:s.jsx(F,{ref:d,graphData:m,width:i.w,height:i.h,backgroundColor:"rgba(0,0,0,0)",nodeLabel:r=>V(r),nodeRelSize:5,nodeVal:r=>2+Math.min(r.degree,12),nodeColor:r=>{const l=r,h=_(l.topTag);return g&&!t.has(l.id)?G(h):h},nodePointerAreaPaint:(r,l,h)=>{const u=r;if(u.x==null||u.y==null)return;const x=2+Math.min(u.degree,12),p=Math.max(Math.sqrt(x)*5,10);h.fillStyle=l,h.beginPath(),h.arc(u.x,u.y,p,0,2*Math.PI),h.fill()},linkColor:r=>{const l=r,h=b(l.source),u=b(l.target);return g&&(!t.has(h)||!t.has(u))?"rgba(160, 160, 160, 0.08)":"rgba(160, 160, 160, 0.35)"},linkDirectionalArrowLength:2.5,linkDirectionalArrowRelPos:1,cooldownTicks:100,onEngineStop:()=>c(),nodeCanvasObjectMode:()=>"after",nodeCanvasObject:(r,l,h)=>{const u=r;if(u.x==null||u.y==null||j(u.id)<.5)return;const p=10/h;l.font=`${p}px sans-serif`,l.fillStyle="rgba(220, 220, 220, 0.8)",l.textAlign="left",l.textBaseline="middle",l.fillText(u.title,u.x+6,u.y)},onNodeClick:r=>{a(`/n/${encodeURIComponent(r.id)}`)}})}),s.jsx("button",{type:"button",onClick:c,className:"absolute right-3 bottom-3 rounded-md border border-border bg-card/90 px-3 py-1.5 text-xs text-fg-muted shadow-sm backdrop-blur hover:text-accent",children:"Fit to screen"})]})}function V(e){const t=[e.path??e.id,`${e.degree} link${e.degree===1?"":"s"}`];return e.tags.length>0&&t.push(`tags: ${e.tags.join(", ")}`),e.summary&&t.push(e.summary),t.join(` | ||
| `)}function G(e){return e.startsWith("hsl(")?e.replace("hsl(","hsla(").replace(")",", 0.2)"):e}function b(e){return typeof e=="string"?e:e&&typeof e=="object"&&"id"in e?String(e.id):""}function B({error:e}){const t=e instanceof I;return s.jsx("div",{className:"flex h-full items-center justify-center p-10",children:s.jsxs("div",{className:"max-w-md rounded-md border border-red-500/30 bg-red-500/5 p-6",children:[s.jsx("p",{className:"mb-2 font-medium text-red-400",children:t?"Session expired":"Could not load vault"}),s.jsx("p",{className:"mb-4 text-sm text-fg-muted",children:e.message}),t?s.jsx(v,{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{O as VaultGraph}; |
| import{u as a,j as e,L as c,ab as m}from"./index-DKKYWfqC.js";function u(){const l=a(t=>t.vaults),d=a(t=>t.activeVaultId),i=a(t=>t.removeVault),o=a(t=>t.setActiveVault),n=Object.values(l).sort((t,s)=>t.name.localeCompare(s.name));return e.jsxs("div",{className:"mx-auto max-w-3xl px-6 py-16",children:[e.jsxs("div",{className:"mb-8 flex items-center justify-between",children:[e.jsx("h1",{className:"font-serif text-4xl tracking-tight",children:"Vaults"}),e.jsx(c,{to:"/add",className:"rounded-md bg-accent px-4 py-2 text-sm font-medium text-white hover:bg-accent-hover",children:"Add vault"})]}),n.length===0?e.jsx("p",{className:"text-fg-muted",children:"No vaults connected yet."}):e.jsx("ul",{className:"space-y-3",children:n.map(t=>{const s=t.id===d,r=m(t.url);return e.jsxs("li",{className:"rounded-lg border border-border bg-card p-4",children:[e.jsxs("div",{className:"flex items-center justify-between gap-4",children:[e.jsxs("div",{className:"min-w-0",children:[e.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[e.jsx("span",{className:"font-serif text-lg text-fg",children:t.name}),s?e.jsx("span",{className:"rounded bg-accent/10 px-2 py-0.5 text-xs text-accent",children:"active"}):null,e.jsx("span",{className:"rounded border border-border px-2 py-0.5 text-xs text-fg-dim",children:t.scope}),r?e.jsx("span",{className:"rounded border border-amber-500/40 bg-amber-500/10 px-2 py-0.5 text-xs text-amber-500",children:"needs reconnect"}):null]}),e.jsx("p",{className:"mt-1 truncate font-mono text-xs text-fg-muted",children:t.url})]}),e.jsxs("div",{className:"flex shrink-0 items-center gap-4 text-sm",children:[s?null:e.jsx("button",{type:"button",onClick:()=>o(t.id),className:"text-fg-muted hover:text-accent",children:"Make active"}),e.jsx("button",{type:"button",onClick:()=>{confirm(`Remove ${t.name}? The access token will be deleted.`)&&i(t.id)},className:"text-red-400 hover:text-red-300",children:"Remove"})]})]}),r?e.jsxs("p",{className:"mt-3 rounded border border-amber-500/30 bg-amber-500/5 px-3 py-2 text-xs text-amber-500",children:["Vault now serves under ",e.jsx("code",{children:"/vault/<name>/"}),". This stored URL is from the older scheme and won't reach the new endpoints. Remove this entry and"," ",e.jsx(c,{to:"/add",className:"underline",children:"add it again"})," ","— discovery will pick the right URL automatically."]}):null]},t.id)})})]})}export{u as Vaults}; |
| try{self["workbox:window:7.3.0"]&&_()}catch{}function b(n,r){return new Promise((function(t){var o=new MessageChannel;o.port1.onmessage=function(f){t(f.data)},n.postMessage(r,[o.port2])}))}function P(n,r){(r==null||r>n.length)&&(r=n.length);for(var t=0,o=Array(r);t<r;t++)o[t]=n[t];return o}function j(n,r){for(var t=0;t<r.length;t++){var o=r[t];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(n,W(o.key),o)}}function S(n,r){var t=typeof Symbol<"u"&&n[Symbol.iterator]||n["@@iterator"];if(t)return(t=t.call(n)).next.bind(t);if(Array.isArray(n)||(t=(function(f,c){if(f){if(typeof f=="string")return P(f,c);var a={}.toString.call(f).slice(8,-1);return a==="Object"&&f.constructor&&(a=f.constructor.name),a==="Map"||a==="Set"?Array.from(f):a==="Arguments"||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(a)?P(f,c):void 0}})(n))||r){t&&(n=t);var o=0;return function(){return o>=n.length?{done:!0}:{done:!1,value:n[o++]}}}throw new TypeError(`Invalid attempt to iterate non-iterable instance. | ||
| In order to be iterable, non-array objects must have a [Symbol.iterator]() method.`)}function w(n,r){return w=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(t,o){return t.__proto__=o,t},w(n,r)}function W(n){var r=(function(t,o){if(typeof t!="object"||!t)return t;var f=t[Symbol.toPrimitive];if(f!==void 0){var c=f.call(t,o);if(typeof c!="object")return c;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(t)})(n,"string");return typeof r=="symbol"?r:r+""}try{self["workbox:core:7.3.0"]&&_()}catch{}var m=function(){var n=this;this.promise=new Promise((function(r,t){n.resolve=r,n.reject=t}))};function y(n,r){var t=location.href;return new URL(n,t).href===new URL(r,t).href}var d=function(n,r){this.type=n,Object.assign(this,r)};function l(n,r,t){return t?r?r(n):n:(n&&n.then||(n=Promise.resolve(n)),r?n.then(r):n)}function k(){}var L={type:"SKIP_WAITING"};function E(n,r){return n&&n.then?n.then(k):Promise.resolve()}var O=(function(n){function r(c,a){var e,i;return a===void 0&&(a={}),(e=n.call(this)||this).nn={},e.tn=0,e.rn=new m,e.en=new m,e.on=new m,e.un=0,e.an=new Set,e.cn=function(){var u=e.fn,s=u.installing;e.tn>0||!y(s.scriptURL,e.sn.toString())||performance.now()>e.un+6e4?(e.vn=s,u.removeEventListener("updatefound",e.cn)):(e.hn=s,e.an.add(s),e.rn.resolve(s)),++e.tn,s.addEventListener("statechange",e.ln)},e.ln=function(u){var s=e.fn,v=u.target,h=v.state,p=v===e.vn,g={sw:v,isExternal:p,originalEvent:u};!p&&e.mn&&(g.isUpdate=!0),e.dispatchEvent(new d(h,g)),h==="installed"?e.wn=self.setTimeout((function(){h==="installed"&&s.waiting===v&&e.dispatchEvent(new d("waiting",g))}),200):h==="activating"&&(clearTimeout(e.wn),p||e.en.resolve(v))},e.yn=function(u){var s=e.hn,v=s!==navigator.serviceWorker.controller;e.dispatchEvent(new d("controlling",{isExternal:v,originalEvent:u,sw:s,isUpdate:e.mn})),v||e.on.resolve(s)},e.gn=(i=function(u){var s=u.data,v=u.ports,h=u.source;return l(e.getSW(),(function(){e.an.has(h)&&e.dispatchEvent(new d("message",{data:s,originalEvent:u,ports:v,sw:h}))}))},function(){for(var u=[],s=0;s<arguments.length;s++)u[s]=arguments[s];try{return Promise.resolve(i.apply(this,u))}catch(v){return Promise.reject(v)}}),e.sn=c,e.nn=a,navigator.serviceWorker.addEventListener("message",e.gn),e}var t,o;o=n,(t=r).prototype=Object.create(o.prototype),t.prototype.constructor=t,w(t,o);var f=r.prototype;return f.register=function(c){var a=(c===void 0?{}:c).immediate,e=a!==void 0&&a;try{var i=this;return l((function(u,s){var v=u();return v&&v.then?v.then(s):s(v)})((function(){if(!e&&document.readyState!=="complete")return E(new Promise((function(u){return window.addEventListener("load",u)})))}),(function(){return i.mn=!!navigator.serviceWorker.controller,i.dn=i.pn(),l(i.bn(),(function(u){i.fn=u,i.dn&&(i.hn=i.dn,i.en.resolve(i.dn),i.on.resolve(i.dn),i.dn.addEventListener("statechange",i.ln,{once:!0}));var s=i.fn.waiting;return s&&y(s.scriptURL,i.sn.toString())&&(i.hn=s,Promise.resolve().then((function(){i.dispatchEvent(new d("waiting",{sw:s,wasWaitingBeforeRegister:!0}))})).then((function(){}))),i.hn&&(i.rn.resolve(i.hn),i.an.add(i.hn)),i.fn.addEventListener("updatefound",i.cn),navigator.serviceWorker.addEventListener("controllerchange",i.yn),i.fn}))})))}catch(u){return Promise.reject(u)}},f.update=function(){try{return this.fn?l(E(this.fn.update())):l()}catch(c){return Promise.reject(c)}},f.getSW=function(){return this.hn!==void 0?Promise.resolve(this.hn):this.rn.promise},f.messageSW=function(c){try{return l(this.getSW(),(function(a){return b(a,c)}))}catch(a){return Promise.reject(a)}},f.messageSkipWaiting=function(){this.fn&&this.fn.waiting&&b(this.fn.waiting,L)},f.pn=function(){var c=navigator.serviceWorker.controller;return c&&y(c.scriptURL,this.sn.toString())?c:void 0},f.bn=function(){try{var c=this;return l((function(a,e){try{var i=a()}catch(u){return e(u)}return i&&i.then?i.then(void 0,e):i})((function(){return l(navigator.serviceWorker.register(c.sn,c.nn),(function(a){return c.un=performance.now(),a}))}),(function(a){throw a})))}catch(a){return Promise.reject(a)}},(function(c,a,e){return a&&j(c.prototype,a),Object.defineProperty(c,"prototype",{writable:!1}),c})(r,[{key:"active",get:function(){return this.en.promise}},{key:"controlling",get:function(){return this.on.promise}}])})((function(){function n(){this.Pn=new Map}var r=n.prototype;return r.addEventListener=function(t,o){this.jn(t).add(o)},r.removeEventListener=function(t,o){this.jn(t).delete(o)},r.dispatchEvent=function(t){t.target=this;for(var o,f=S(this.jn(t.type));!(o=f()).done;)(0,o.value)(t)},r.jn=function(t){return this.Pn.has(t)||this.Pn.set(t,new Set),this.Pn.get(t)},n})());export{O as Workbox,d as WorkboxEvent,b as messageSW}; |
| define(["exports"],function(t){"use strict";try{self["workbox:core:7.3.0"]&&_()}catch(t){}const e=(t,...e)=>{let s=t;return e.length>0&&(s+=` :: ${JSON.stringify(e)}`),s};class s extends Error{constructor(t,s){super(e(t,s)),this.name=t,this.details=s}}try{self["workbox:routing:7.3.0"]&&_()}catch(t){}const n=t=>t&&"object"==typeof t?t:{handle:t};class i{constructor(t,e,s="GET"){this.handler=n(e),this.match=t,this.method=s}setCatchHandler(t){this.catchHandler=n(t)}}class r extends i{constructor(t,e,s){super(({url:e})=>{const s=t.exec(e.href);if(s&&(e.origin===location.origin||0===s.index))return s.slice(1)},e,s)}}class a{constructor(){this.t=new Map,this.i=new Map}get routes(){return this.t}addFetchListener(){self.addEventListener("fetch",t=>{const{request:e}=t,s=this.handleRequest({request:e,event:t});s&&t.respondWith(s)})}addCacheListener(){self.addEventListener("message",t=>{if(t.data&&"CACHE_URLS"===t.data.type){const{payload:e}=t.data,s=Promise.all(e.urlsToCache.map(e=>{"string"==typeof e&&(e=[e]);const s=new Request(...e);return this.handleRequest({request:s,event:t})}));t.waitUntil(s),t.ports&&t.ports[0]&&s.then(()=>t.ports[0].postMessage(!0))}})}handleRequest({request:t,event:e}){const s=new URL(t.url,location.href);if(!s.protocol.startsWith("http"))return;const n=s.origin===location.origin,{params:i,route:r}=this.findMatchingRoute({event:e,request:t,sameOrigin:n,url:s});let a=r&&r.handler;const o=t.method;if(!a&&this.i.has(o)&&(a=this.i.get(o)),!a)return;let c;try{c=a.handle({url:s,request:t,event:e,params:i})}catch(t){c=Promise.reject(t)}const h=r&&r.catchHandler;return c instanceof Promise&&(this.o||h)&&(c=c.catch(async n=>{if(h)try{return await h.handle({url:s,request:t,event:e,params:i})}catch(t){t instanceof Error&&(n=t)}if(this.o)return this.o.handle({url:s,request:t,event:e});throw n})),c}findMatchingRoute({url:t,sameOrigin:e,request:s,event:n}){const i=this.t.get(s.method)||[];for(const r of i){let i;const a=r.match({url:t,sameOrigin:e,request:s,event:n});if(a)return i=a,(Array.isArray(i)&&0===i.length||a.constructor===Object&&0===Object.keys(a).length||"boolean"==typeof a)&&(i=void 0),{route:r,params:i}}return{}}setDefaultHandler(t,e="GET"){this.i.set(e,n(t))}setCatchHandler(t){this.o=n(t)}registerRoute(t){this.t.has(t.method)||this.t.set(t.method,[]),this.t.get(t.method).push(t)}unregisterRoute(t){if(!this.t.has(t.method))throw new s("unregister-route-but-not-found-with-method",{method:t.method});const e=this.t.get(t.method).indexOf(t);if(!(e>-1))throw new s("unregister-route-route-not-registered");this.t.get(t.method).splice(e,1)}}let o;const c=()=>(o||(o=new a,o.addFetchListener(),o.addCacheListener()),o);function h(t,e,n){let a;if("string"==typeof t){const s=new URL(t,location.href);a=new i(({url:t})=>t.href===s.href,e,n)}else if(t instanceof RegExp)a=new r(t,e,n);else if("function"==typeof t)a=new i(t,e,n);else{if(!(t instanceof i))throw new s("unsupported-route-type",{moduleName:"workbox-routing",funcName:"registerRoute",paramName:"capture"});a=t}return c().registerRoute(a),a}const u={googleAnalytics:"googleAnalytics",precache:"precache-v2",prefix:"workbox",runtime:"runtime",suffix:"undefined"!=typeof registration?registration.scope:""},l=t=>[u.prefix,t,u.suffix].filter(t=>t&&t.length>0).join("-"),f=t=>t||l(u.precache),w=t=>t||l(u.runtime);function d(t){t.then(()=>{})}const p=new Set;function y(){return y=Object.assign?Object.assign.bind():function(t){for(var e=1;e<arguments.length;e++){var s=arguments[e];for(var n in s)({}).hasOwnProperty.call(s,n)&&(t[n]=s[n])}return t},y.apply(null,arguments)}let m,g;const R=new WeakMap,v=new WeakMap,b=new WeakMap,q=new WeakMap,D=new WeakMap;let U={get(t,e,s){if(t instanceof IDBTransaction){if("done"===e)return v.get(t);if("objectStoreNames"===e)return t.objectStoreNames||b.get(t);if("store"===e)return s.objectStoreNames[1]?void 0:s.objectStore(s.objectStoreNames[0])}return I(t[e])},set:(t,e,s)=>(t[e]=s,!0),has:(t,e)=>t instanceof IDBTransaction&&("done"===e||"store"===e)||e in t};function x(t){return t!==IDBDatabase.prototype.transaction||"objectStoreNames"in IDBTransaction.prototype?(g||(g=[IDBCursor.prototype.advance,IDBCursor.prototype.continue,IDBCursor.prototype.continuePrimaryKey])).includes(t)?function(...e){return t.apply(C(this),e),I(R.get(this))}:function(...e){return I(t.apply(C(this),e))}:function(e,...s){const n=t.call(C(this),e,...s);return b.set(n,e.sort?e.sort():[e]),I(n)}}function L(t){return"function"==typeof t?x(t):(t instanceof IDBTransaction&&function(t){if(v.has(t))return;const e=new Promise((e,s)=>{const n=()=>{t.removeEventListener("complete",i),t.removeEventListener("error",r),t.removeEventListener("abort",r)},i=()=>{e(),n()},r=()=>{s(t.error||new DOMException("AbortError","AbortError")),n()};t.addEventListener("complete",i),t.addEventListener("error",r),t.addEventListener("abort",r)});v.set(t,e)}(t),e=t,(m||(m=[IDBDatabase,IDBObjectStore,IDBIndex,IDBCursor,IDBTransaction])).some(t=>e instanceof t)?new Proxy(t,U):t);var e}function I(t){if(t instanceof IDBRequest)return function(t){const e=new Promise((e,s)=>{const n=()=>{t.removeEventListener("success",i),t.removeEventListener("error",r)},i=()=>{e(I(t.result)),n()},r=()=>{s(t.error),n()};t.addEventListener("success",i),t.addEventListener("error",r)});return e.then(e=>{e instanceof IDBCursor&&R.set(e,t)}).catch(()=>{}),D.set(e,t),e}(t);if(q.has(t))return q.get(t);const e=L(t);return e!==t&&(q.set(t,e),D.set(e,t)),e}const C=t=>D.get(t);const E=["get","getKey","getAll","getAllKeys","count"],N=["put","add","delete","clear"],O=new Map;function B(t,e){if(!(t instanceof IDBDatabase)||e in t||"string"!=typeof e)return;if(O.get(e))return O.get(e);const s=e.replace(/FromIndex$/,""),n=e!==s,i=N.includes(s);if(!(s in(n?IDBIndex:IDBObjectStore).prototype)||!i&&!E.includes(s))return;const r=async function(t,...e){const r=this.transaction(t,i?"readwrite":"readonly");let a=r.store;return n&&(a=a.index(e.shift())),(await Promise.all([a[s](...e),i&&r.done]))[0]};return O.set(e,r),r}U=(t=>y({},t,{get:(e,s,n)=>B(e,s)||t.get(e,s,n),has:(e,s)=>!!B(e,s)||t.has(e,s)}))(U);try{self["workbox:expiration:7.3.0"]&&_()}catch(t){}const k="cache-entries",M=t=>{const e=new URL(t,location.href);return e.hash="",e.href};class T{constructor(t){this.h=null,this.u=t}l(t){const e=t.createObjectStore(k,{keyPath:"id"});e.createIndex("cacheName","cacheName",{unique:!1}),e.createIndex("timestamp","timestamp",{unique:!1})}p(t){this.l(t),this.u&&function(t,{blocked:e}={}){const s=indexedDB.deleteDatabase(t);e&&s.addEventListener("blocked",t=>e(t.oldVersion,t)),I(s).then(()=>{})}(this.u)}async setTimestamp(t,e){const s={url:t=M(t),timestamp:e,cacheName:this.u,id:this.m(t)},n=(await this.getDb()).transaction(k,"readwrite",{durability:"relaxed"});await n.store.put(s),await n.done}async getTimestamp(t){const e=await this.getDb(),s=await e.get(k,this.m(t));return null==s?void 0:s.timestamp}async expireEntries(t,e){const s=await this.getDb();let n=await s.transaction(k).store.index("timestamp").openCursor(null,"prev");const i=[];let r=0;for(;n;){const s=n.value;s.cacheName===this.u&&(t&&s.timestamp<t||e&&r>=e?i.push(n.value):r++),n=await n.continue()}const a=[];for(const t of i)await s.delete(k,t.id),a.push(t.url);return a}m(t){return this.u+"|"+M(t)}async getDb(){return this.h||(this.h=await function(t,e,{blocked:s,upgrade:n,blocking:i,terminated:r}={}){const a=indexedDB.open(t,e),o=I(a);return n&&a.addEventListener("upgradeneeded",t=>{n(I(a.result),t.oldVersion,t.newVersion,I(a.transaction),t)}),s&&a.addEventListener("blocked",t=>s(t.oldVersion,t.newVersion,t)),o.then(t=>{r&&t.addEventListener("close",()=>r()),i&&t.addEventListener("versionchange",t=>i(t.oldVersion,t.newVersion,t))}).catch(()=>{}),o}("workbox-expiration",1,{upgrade:this.p.bind(this)})),this.h}}class j{constructor(t,e={}){this.R=!1,this.v=!1,this.q=e.maxEntries,this.D=e.maxAgeSeconds,this.U=e.matchOptions,this.u=t,this._=new T(t)}async expireEntries(){if(this.R)return void(this.v=!0);this.R=!0;const t=this.D?Date.now()-1e3*this.D:0,e=await this._.expireEntries(t,this.q),s=await self.caches.open(this.u);for(const t of e)await s.delete(t,this.U);this.R=!1,this.v&&(this.v=!1,d(this.expireEntries()))}async updateTimestamp(t){await this._.setTimestamp(t,Date.now())}async isURLExpired(t){if(this.D){const e=await this._.getTimestamp(t),s=Date.now()-1e3*this.D;return void 0===e||e<s}return!1}async delete(){this.v=!1,await this._.expireEntries(1/0)}}try{self["workbox:cacheable-response:7.3.0"]&&_()}catch(t){}class W{constructor(t={}){this.L=t.statuses,this.I=t.headers}isResponseCacheable(t){let e=!0;return this.L&&(e=this.L.includes(t.status)),this.I&&e&&(e=Object.keys(this.I).some(e=>t.headers.get(e)===this.I[e])),e}}try{self["workbox:strategies:7.3.0"]&&_()}catch(t){}const P={cacheWillUpdate:async({response:t})=>200===t.status||0===t.status?t:null};function S(t,e){const s=new URL(t);for(const t of e)s.searchParams.delete(t);return s.href}class K{constructor(){this.promise=new Promise((t,e)=>{this.resolve=t,this.reject=e})}}function A(t){return"string"==typeof t?new Request(t):t}class F{constructor(t,e){this.C={},Object.assign(this,e),this.event=e.event,this.N=t,this.O=new K,this.B=[],this.k=[...t.plugins],this.M=new Map;for(const t of this.k)this.M.set(t,{});this.event.waitUntil(this.O.promise)}async fetch(t){const{event:e}=this;let n=A(t);if("navigate"===n.mode&&e instanceof FetchEvent&&e.preloadResponse){const t=await e.preloadResponse;if(t)return t}const i=this.hasCallback("fetchDidFail")?n.clone():null;try{for(const t of this.iterateCallbacks("requestWillFetch"))n=await t({request:n.clone(),event:e})}catch(t){if(t instanceof Error)throw new s("plugin-error-request-will-fetch",{thrownErrorMessage:t.message})}const r=n.clone();try{let t;t=await fetch(n,"navigate"===n.mode?void 0:this.N.fetchOptions);for(const s of this.iterateCallbacks("fetchDidSucceed"))t=await s({event:e,request:r,response:t});return t}catch(t){throw i&&await this.runCallbacks("fetchDidFail",{error:t,event:e,originalRequest:i.clone(),request:r.clone()}),t}}async fetchAndCachePut(t){const e=await this.fetch(t),s=e.clone();return this.waitUntil(this.cachePut(t,s)),e}async cacheMatch(t){const e=A(t);let s;const{cacheName:n,matchOptions:i}=this.N,r=await this.getCacheKey(e,"read"),a=Object.assign(Object.assign({},i),{cacheName:n});s=await caches.match(r,a);for(const t of this.iterateCallbacks("cachedResponseWillBeUsed"))s=await t({cacheName:n,matchOptions:i,cachedResponse:s,request:r,event:this.event})||void 0;return s}async cachePut(t,e){const n=A(t);var i;await(i=0,new Promise(t=>setTimeout(t,i)));const r=await this.getCacheKey(n,"write");if(!e)throw new s("cache-put-with-no-response",{url:(a=r.url,new URL(String(a),location.href).href.replace(new RegExp(`^${location.origin}`),""))});var a;const o=await this.T(e);if(!o)return!1;const{cacheName:c,matchOptions:h}=this.N,u=await self.caches.open(c),l=this.hasCallback("cacheDidUpdate"),f=l?await async function(t,e,s,n){const i=S(e.url,s);if(e.url===i)return t.match(e,n);const r=Object.assign(Object.assign({},n),{ignoreSearch:!0}),a=await t.keys(e,r);for(const e of a)if(i===S(e.url,s))return t.match(e,n)}(u,r.clone(),["__WB_REVISION__"],h):null;try{await u.put(r,l?o.clone():o)}catch(t){if(t instanceof Error)throw"QuotaExceededError"===t.name&&await async function(){for(const t of p)await t()}(),t}for(const t of this.iterateCallbacks("cacheDidUpdate"))await t({cacheName:c,oldResponse:f,newResponse:o.clone(),request:r,event:this.event});return!0}async getCacheKey(t,e){const s=`${t.url} | ${e}`;if(!this.C[s]){let n=t;for(const t of this.iterateCallbacks("cacheKeyWillBeUsed"))n=A(await t({mode:e,request:n,event:this.event,params:this.params}));this.C[s]=n}return this.C[s]}hasCallback(t){for(const e of this.N.plugins)if(t in e)return!0;return!1}async runCallbacks(t,e){for(const s of this.iterateCallbacks(t))await s(e)}*iterateCallbacks(t){for(const e of this.N.plugins)if("function"==typeof e[t]){const s=this.M.get(e),n=n=>{const i=Object.assign(Object.assign({},n),{state:s});return e[t](i)};yield n}}waitUntil(t){return this.B.push(t),t}async doneWaiting(){for(;this.B.length;){const t=this.B.splice(0),e=(await Promise.allSettled(t)).find(t=>"rejected"===t.status);if(e)throw e.reason}}destroy(){this.O.resolve(null)}async T(t){let e=t,s=!1;for(const t of this.iterateCallbacks("cacheWillUpdate"))if(e=await t({request:this.request,response:e,event:this.event})||void 0,s=!0,!e)break;return s||e&&200!==e.status&&(e=void 0),e}}class H{constructor(t={}){this.cacheName=w(t.cacheName),this.plugins=t.plugins||[],this.fetchOptions=t.fetchOptions,this.matchOptions=t.matchOptions}handle(t){const[e]=this.handleAll(t);return e}handleAll(t){t instanceof FetchEvent&&(t={event:t,request:t.request});const e=t.event,s="string"==typeof t.request?new Request(t.request):t.request,n="params"in t?t.params:void 0,i=new F(this,{event:e,request:s,params:n}),r=this.j(i,s,e);return[r,this.W(r,i,s,e)]}async j(t,e,n){let i;await t.runCallbacks("handlerWillStart",{event:n,request:e});try{if(i=await this.P(e,t),!i||"error"===i.type)throw new s("no-response",{url:e.url})}catch(s){if(s instanceof Error)for(const r of t.iterateCallbacks("handlerDidError"))if(i=await r({error:s,event:n,request:e}),i)break;if(!i)throw s}for(const s of t.iterateCallbacks("handlerWillRespond"))i=await s({event:n,request:e,response:i});return i}async W(t,e,s,n){let i,r;try{i=await t}catch(r){}try{await e.runCallbacks("handlerDidRespond",{event:n,request:s,response:i}),await e.doneWaiting()}catch(t){t instanceof Error&&(r=t)}if(await e.runCallbacks("handlerDidComplete",{event:n,request:s,response:i,error:r}),e.destroy(),r)throw r}}function $(t,e){const s=e();return t.waitUntil(s),s}try{self["workbox:precaching:7.3.0"]&&_()}catch(t){}function G(t){if(!t)throw new s("add-to-cache-list-unexpected-type",{entry:t});if("string"==typeof t){const e=new URL(t,location.href);return{cacheKey:e.href,url:e.href}}const{revision:e,url:n}=t;if(!n)throw new s("add-to-cache-list-unexpected-type",{entry:t});if(!e){const t=new URL(n,location.href);return{cacheKey:t.href,url:t.href}}const i=new URL(n,location.href),r=new URL(n,location.href);return i.searchParams.set("__WB_REVISION__",e),{cacheKey:i.href,url:r.href}}class V{constructor(){this.updatedURLs=[],this.notUpdatedURLs=[],this.handlerWillStart=async({request:t,state:e})=>{e&&(e.originalRequest=t)},this.cachedResponseWillBeUsed=async({event:t,state:e,cachedResponse:s})=>{if("install"===t.type&&e&&e.originalRequest&&e.originalRequest instanceof Request){const t=e.originalRequest.url;s?this.notUpdatedURLs.push(t):this.updatedURLs.push(t)}return s}}}class J{constructor({precacheController:t}){this.cacheKeyWillBeUsed=async({request:t,params:e})=>{const s=(null==e?void 0:e.cacheKey)||this.S.getCacheKeyForURL(t.url);return s?new Request(s,{headers:t.headers}):t},this.S=t}}let Q,z;async function X(t,e){let n=null;if(t.url){n=new URL(t.url).origin}if(n!==self.location.origin)throw new s("cross-origin-copy-response",{origin:n});const i=t.clone(),r={headers:new Headers(i.headers),status:i.status,statusText:i.statusText},a=e?e(r):r,o=function(){if(void 0===Q){const t=new Response("");if("body"in t)try{new Response(t.body),Q=!0}catch(t){Q=!1}Q=!1}return Q}()?i.body:await i.blob();return new Response(o,a)}class Y extends H{constructor(t={}){t.cacheName=f(t.cacheName),super(t),this.K=!1!==t.fallbackToNetwork,this.plugins.push(Y.copyRedirectedCacheableResponsesPlugin)}async P(t,e){const s=await e.cacheMatch(t);return s||(e.event&&"install"===e.event.type?await this.A(t,e):await this.F(t,e))}async F(t,e){let n;const i=e.params||{};if(!this.K)throw new s("missing-precache-entry",{cacheName:this.cacheName,url:t.url});{const s=i.integrity,r=t.integrity,a=!r||r===s;n=await e.fetch(new Request(t,{integrity:"no-cors"!==t.mode?r||s:void 0})),s&&a&&"no-cors"!==t.mode&&(this.H(),await e.cachePut(t,n.clone()))}return n}async A(t,e){this.H();const n=await e.fetch(t);if(!await e.cachePut(t,n.clone()))throw new s("bad-precaching-response",{url:t.url,status:n.status});return n}H(){let t=null,e=0;for(const[s,n]of this.plugins.entries())n!==Y.copyRedirectedCacheableResponsesPlugin&&(n===Y.defaultPrecacheCacheabilityPlugin&&(t=s),n.cacheWillUpdate&&e++);0===e?this.plugins.push(Y.defaultPrecacheCacheabilityPlugin):e>1&&null!==t&&this.plugins.splice(t,1)}}Y.defaultPrecacheCacheabilityPlugin={cacheWillUpdate:async({response:t})=>!t||t.status>=400?null:t},Y.copyRedirectedCacheableResponsesPlugin={cacheWillUpdate:async({response:t})=>t.redirected?await X(t):t};class Z{constructor({cacheName:t,plugins:e=[],fallbackToNetwork:s=!0}={}){this.$=new Map,this.G=new Map,this.V=new Map,this.N=new Y({cacheName:f(t),plugins:[...e,new J({precacheController:this})],fallbackToNetwork:s}),this.install=this.install.bind(this),this.activate=this.activate.bind(this)}get strategy(){return this.N}precache(t){this.addToCacheList(t),this.J||(self.addEventListener("install",this.install),self.addEventListener("activate",this.activate),this.J=!0)}addToCacheList(t){const e=[];for(const n of t){"string"==typeof n?e.push(n):n&&void 0===n.revision&&e.push(n.url);const{cacheKey:t,url:i}=G(n),r="string"!=typeof n&&n.revision?"reload":"default";if(this.$.has(i)&&this.$.get(i)!==t)throw new s("add-to-cache-list-conflicting-entries",{firstEntry:this.$.get(i),secondEntry:t});if("string"!=typeof n&&n.integrity){if(this.V.has(t)&&this.V.get(t)!==n.integrity)throw new s("add-to-cache-list-conflicting-integrities",{url:i});this.V.set(t,n.integrity)}if(this.$.set(i,t),this.G.set(i,r),e.length>0){const t=`Workbox is precaching URLs without revision info: ${e.join(", ")}\nThis is generally NOT safe. Learn more at https://bit.ly/wb-precache`;console.warn(t)}}}install(t){return $(t,async()=>{const e=new V;this.strategy.plugins.push(e);for(const[e,s]of this.$){const n=this.V.get(s),i=this.G.get(e),r=new Request(e,{integrity:n,cache:i,credentials:"same-origin"});await Promise.all(this.strategy.handleAll({params:{cacheKey:s},request:r,event:t}))}const{updatedURLs:s,notUpdatedURLs:n}=e;return{updatedURLs:s,notUpdatedURLs:n}})}activate(t){return $(t,async()=>{const t=await self.caches.open(this.strategy.cacheName),e=await t.keys(),s=new Set(this.$.values()),n=[];for(const i of e)s.has(i.url)||(await t.delete(i),n.push(i.url));return{deletedURLs:n}})}getURLsToCacheKeys(){return this.$}getCachedURLs(){return[...this.$.keys()]}getCacheKeyForURL(t){const e=new URL(t,location.href);return this.$.get(e.href)}getIntegrityForCacheKey(t){return this.V.get(t)}async matchPrecache(t){const e=t instanceof Request?t.url:t,s=this.getCacheKeyForURL(e);if(s){return(await self.caches.open(this.strategy.cacheName)).match(s)}}createHandlerBoundToURL(t){const e=this.getCacheKeyForURL(t);if(!e)throw new s("non-precached-url",{url:t});return s=>(s.request=new Request(t),s.params=Object.assign({cacheKey:e},s.params),this.strategy.handle(s))}}const tt=()=>(z||(z=new Z),z);class et extends i{constructor(t,e){super(({request:s})=>{const n=t.getURLsToCacheKeys();for(const i of function*(t,{ignoreURLParametersMatching:e=[/^utm_/,/^fbclid$/],directoryIndex:s="index.html",cleanURLs:n=!0,urlManipulation:i}={}){const r=new URL(t,location.href);r.hash="",yield r.href;const a=function(t,e=[]){for(const s of[...t.searchParams.keys()])e.some(t=>t.test(s))&&t.searchParams.delete(s);return t}(r,e);if(yield a.href,s&&a.pathname.endsWith("/")){const t=new URL(a.href);t.pathname+=s,yield t.href}if(n){const t=new URL(a.href);t.pathname+=".html",yield t.href}if(i){const t=i({url:r});for(const e of t)yield e.href}}(s.url,e)){const e=n.get(i);if(e){return{cacheKey:e,integrity:t.getIntegrityForCacheKey(e)}}}},t.strategy)}}t.CacheableResponsePlugin=class{constructor(t){this.cacheWillUpdate=async({response:t})=>this.X.isResponseCacheable(t)?t:null,this.X=new W(t)}},t.ExpirationPlugin=class{constructor(t={}){this.cachedResponseWillBeUsed=async({event:t,request:e,cacheName:s,cachedResponse:n})=>{if(!n)return null;const i=this.Y(n),r=this.Z(s);d(r.expireEntries());const a=r.updateTimestamp(e.url);if(t)try{t.waitUntil(a)}catch(t){}return i?n:null},this.cacheDidUpdate=async({cacheName:t,request:e})=>{const s=this.Z(t);await s.updateTimestamp(e.url),await s.expireEntries()},this.tt=t,this.D=t.maxAgeSeconds,this.et=new Map,t.purgeOnQuotaError&&function(t){p.add(t)}(()=>this.deleteCacheAndMetadata())}Z(t){if(t===w())throw new s("expire-custom-caches-only");let e=this.et.get(t);return e||(e=new j(t,this.tt),this.et.set(t,e)),e}Y(t){if(!this.D)return!0;const e=this.st(t);if(null===e)return!0;return e>=Date.now()-1e3*this.D}st(t){if(!t.headers.has("date"))return null;const e=t.headers.get("date"),s=new Date(e).getTime();return isNaN(s)?null:s}async deleteCacheAndMetadata(){for(const[t,e]of this.et)await self.caches.delete(t),await e.delete();this.et=new Map}},t.NavigationRoute=class extends i{constructor(t,{allowlist:e=[/./],denylist:s=[]}={}){super(t=>this.nt(t),t),this.it=e,this.rt=s}nt({url:t,request:e}){if(e&&"navigate"!==e.mode)return!1;const s=t.pathname+t.search;for(const t of this.rt)if(t.test(s))return!1;return!!this.it.some(t=>t.test(s))}},t.StaleWhileRevalidate=class extends H{constructor(t={}){super(t),this.plugins.some(t=>"cacheWillUpdate"in t)||this.plugins.unshift(P)}async P(t,e){const n=e.fetchAndCachePut(t).catch(()=>{});e.waitUntil(n);let i,r=await e.cacheMatch(t);if(r);else try{r=await n}catch(t){t instanceof Error&&(i=t)}if(!r)throw new s("no-response",{url:t.url,error:i});return r}},t.cleanupOutdatedCaches=function(){self.addEventListener("activate",t=>{const e=f();t.waitUntil((async(t,e="-precache-")=>{const s=(await self.caches.keys()).filter(s=>s.includes(e)&&s.includes(self.registration.scope)&&s!==t);return await Promise.all(s.map(t=>self.caches.delete(t))),s})(e).then(t=>{}))})},t.createHandlerBoundToURL=function(t){return tt().createHandlerBoundToURL(t)},t.precacheAndRoute=function(t,e){!function(t){tt().precache(t)}(t),function(t){const e=tt();h(new et(e,t))}(e)},t.registerRoute=h}); |
Sorry, the diff of this file is not supported yet
Deprecated
MaintenanceThe maintainer of the package marked it as deprecated. This could indicate that a single version should not be used, or that the package is no longer maintained and any new vulnerabilities will not be fixed.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Minified code
QualityThis package contains minified code. This may be harmless in some cases where minified code is included in packaged libraries, however packages on npm should not minify code.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Minified code
QualityThis package contains minified code. This may be harmless in some cases where minified code is included in packaged libraries, however packages on npm should not minify code.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
1739087
3.16%0
-100%1
-95.24%39
5.41%6422
0.3%107
33.75%1
Infinity%29
11.54%- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed