Add resizable panes with drag handles, min widths, and persistence

This commit is contained in:
2026-06-05 10:46:07 +03:00
parent 411bfbc6c2
commit c50f141d57
11 changed files with 482 additions and 25 deletions
+14 -7
View File
@@ -18,7 +18,7 @@ src/
│ ├── snippet-store.ts # IndexedDB: snippets (metadata + drafts)
│ ├── dataset-store.ts # IndexedDB: datasets (heavy payloads)
│ ├── settings-store.ts # localStorage: UserSettings
│ └── prefs-store.ts # localStorage: app/UI prefs (sort, layout)
│ └── ux-prefs.ts # localStorage: app/UI prefs (sort, panel layout)
```
### Why this boundary exists
@@ -317,17 +317,24 @@ export function saveSettings(s: UserSettings): void {
}
```
App/UI prefs follow the identical pattern under their own keys, e.g.:
App/UI prefs follow the identical guard+fallback pattern, but live in **one
record under their own key**, `astrolabe:ux-prefs` (the snippet sort and the
panel layout together — the plan's "ux-prefs for sort + panel layout", §09D):
```ts
// src/app/infrastructure/prefs-store.ts
const SORT_KEY = 'astrolabe:snippet-sort';
const LAYOUT_KEY = 'astrolabe:panel-layout';
// src/app/infrastructure/ux-prefs.ts
const KEY = 'astrolabe:ux-prefs'; // { panelLayout: { libraryWidth, previewWidth }, sort: { … } }
const SORT_DEFAULTS = { sortBy: 'modified' as const, sortOrder: 'desc' as const };
// loadSort()/saveSort() and loadLayout()/saveLayout() mirror §5's guard+fallback shape.
// loadPanelLayout()/savePanelLayout() (and sort later) mirror §5's guard+fallback shape,
// merging the changed section so a frequent write (a drag) never clobbers the others.
```
> One nuance vs. the settings record: the panel-layout widths are **validated**
> (positive finite numbers) and surfaced as `undefined` when absent/invalid; the
> **defaults live in the `PanesStore`** (`PANE_DEFAULT`), applied at `hydrate`,
> rather than merged in the adapter. Persistence of the live drag is **debounced**
> in `orchestration/panes.ts` (a drag emits an update per pointer move).
> **Do:** keep a single complete `DEFAULTS` object as the source of truth and merge over it.
> **Don't:** read individual keys with bespoke `?? fallback` at each call site; one stale default and the shapes drift.