/** * Universal markwhen projection types for rSpace. * * Any rApp can expose date-bearing Automerge records as a MwSource. * The renderer unions sources into a single `.mw` document that feeds * timeline / calendar / gantt views. * * Storage model: `.mw` is NEVER the source of truth. It is a pure * projection over canonical CRDT state. Do not round-trip edits through it. */ /** Hex color or markwhen named color (e.g. "blue"). */ export type MwColor = string; /** A single event in markwhen's mental model. */ export interface MwEvent { /** UTC epoch ms. For all-day events, the renderer normalizes to date-only. */ start: number; /** UTC epoch ms. Omit for a point event. */ end?: number; /** Single-line headline (truncated at ~90 chars when serialized). */ title: string; /** Optional body — becomes indented description under the event. */ description?: string; /** Freeform tags. Prefixed with `#` on serialize. Used for coloring + filtering. */ tags?: string[]; /** Optional deep-link back into the canonical module (e.g. rspace:/cal/ev/123). */ href?: string; /** Treat date as wall-clock in the named IANA zone, not UTC. */ timezone?: string; /** Stable ID for dedup across projections (e.g. module:collection:recordId). */ sourceId: string; } /** A module's contribution to a composite timeline. */ export interface MwSource { /** Short section slug, e.g. "rcal", "rnotes", "rvote". */ id: string; /** Display label for the markwhen `section` header. */ label: string; /** Section-level tag; applied to every event from this source. */ tag: string; /** Optional color for the tag in frontmatter. */ color?: MwColor; /** The events themselves. */ events: MwEvent[]; } /** Result of projecting + rendering. */ export interface MwProjection { /** Serialized `.mw` text. */ text: string; /** Flat list of all events across sources (post-dedup). */ events: MwEvent[]; /** Total event count. */ count: number; } /** * A module registers a factory that builds its MwSource on demand. * The composite rApp (rSaga) calls these at projection time. */ export interface MarkwhenSourceFactory { /** Module id, e.g. "rcal". */ module: string; /** Human label for picker UI. */ label: string; /** Emoji for picker UI. */ icon: string; /** * Build the source. Receives the current space slug and an optional * date window — implementations should filter events to the window * to keep DOM render sizes bounded (~5k event ceiling for smooth UX). */ build(ctx: { space: string; from?: number; to?: number }): Promise; }