web: shared note actions, reminder chips, page header, formatters and settings seam

From the audit (#5179, web half).

- NoteActions: share, pin, archive and trash (restore and delete forever
  when trashed), as both the card and the editor offer them. The editor's
  history toggle goes in its slot, and it closes on `acted`.
- ReminderActions: the Done / 1h / 1d chips on the card and in the editor,
  which are now the same chips.
- PageHeader: the back-to-board header that Settings, Sync and Linked
  devices each wrote out, now with a `back` icon from the shared set.
- notes/datetime: formatShortDateTime (was formatReminder and the editor's
  revLabel) and formatDateTime (the two `fmt` copies).
- notes/colors: labelDotClasses (the sidebar's and the tag manager's
  labelDot).
- Drawer links use exact-active-class instead of route.name ternaries.
- BoardView binds its three grids from one gridBinds object.
- Settings goes through repo.settings (rest, plus a local adapter that
  answers "needs a server") and shows load failures through AsyncState.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-07 20:02:18 -04:00
co-authored by Claude Opus 5.5
parent 05c82c2362
commit e75e3d37d0
17 changed files with 348 additions and 422 deletions
+6
View File
@@ -137,6 +137,12 @@ export function labelChipClasses(label: { name: string; color?: string | null })
return `${LABEL_CHIP_SHELL[color]} ${TAG_TEXT_CLASSES[color]}`;
}
/** The small round swatch for a tag (sidebar, tag manager): the colour it actually
* wears, derived from its name when nobody picked one, as on every chip. */
export function labelDotClasses(label: { name: string; color?: string | null }): string {
return NOTE_SWATCH_CLASSES[resolveLabelColor(label)] ?? NOTE_SWATCH_CLASSES.default;
}
export const NOTE_COLOR_LABELS: Record<NoteColor, string> = {
default: "Default",
red: "Red",
+7 -1
View File
@@ -13,7 +13,8 @@ export function fromLocalInput(local: string): string | null {
return new Date(local).toISOString();
}
export function formatReminder(iso: string | null): string {
// A moment, short: "Oct 7, 4:05 PM". A reminder on a card, a revision in history.
export function formatShortDateTime(iso: string | null): string {
if (!iso) return "";
return new Date(iso).toLocaleString(undefined, {
month: "short",
@@ -23,6 +24,11 @@ export function formatReminder(iso: string | null): string {
});
}
// A moment, in full, or `empty` when there is none ("last synced never").
export function formatDateTime(iso: string | null, empty = "never"): string {
return iso ? new Date(iso).toLocaleString() : empty;
}
export function isOverdue(iso: string | null): boolean {
return !!iso && new Date(iso).getTime() < Date.now();
}