From 4979c3d80c5df1ba21049dc46bbcdb0dfddcb62b Mon Sep 17 00:00:00 2001 From: Jeff Emmett Date: Sun, 1 Mar 2026 11:49:13 -0800 Subject: [PATCH] feat(rcal): replace static demo with interactive folk-calendar-view The demo page was a frozen July 2026 static HTML grid with no real functionality. Now embeds which provides full month/week/day views, navigation, lunar overlay, source filtering, event modals, keyboard shortcuts, and 37 demo events. Keeps hero, temporal zoom showcase, feature cards, ecosystem integrations, and CTA sections around the interactive component. Co-Authored-By: Claude Opus 4.6 --- modules/rcal/demo.ts | 291 +++++++++---------------------------------- modules/rcal/mod.ts | 8 +- 2 files changed, 62 insertions(+), 237 deletions(-) diff --git a/modules/rcal/demo.ts b/modules/rcal/demo.ts index 67f3736..263dbef 100644 --- a/modules/rcal/demo.ts +++ b/modules/rcal/demo.ts @@ -1,46 +1,12 @@ /** * rCal demo page — server-rendered HTML body. * - * Static July 2026 calendar grid with Alpine Explorer trip events, - * tab switching (Temporal/Spatial/Lunar/Context), zoom panel, - * and feature cards. Entirely local state, no WebSocket. + * Embeds the full component for + * real interactivity (month/week/day views, navigation, lunar overlay, + * source filtering, event modals, keyboard shortcuts) plus showcase + * sections explaining the rCal vision. */ -/* ─── Event Data ──────────────────────────────────────────── */ - -interface CalEvent { - day: number; - emoji: string; - label: string; - color: string; - bg: string; -} - -const TRIP_EVENTS: CalEvent[] = [ - { day: 6, emoji: "\u2708\uFE0F", label: "Arrive Chamonix", color: "#2dd4bf", bg: "rgba(20,184,166,0.15)" }, - { day: 7, emoji: "\u{1F97E}", label: "Lac Blanc Hike", color: "#34d399", bg: "rgba(16,185,129,0.15)" }, - { day: 8, emoji: "\u{1F9D7}", label: "Aiguille du Midi", color: "#fbbf24", bg: "rgba(245,158,11,0.15)" }, - { day: 9, emoji: "\u{1F97E}", label: "Mer de Glace", color: "#34d399", bg: "rgba(16,185,129,0.15)" }, - { day: 10, emoji: "\u{1F682}", label: "Train to Zermatt", color: "#22d3ee", bg: "rgba(6,182,212,0.15)" }, - { day: 11, emoji: "\u{1F97E}", label: "Five Lakes Walk", color: "#34d399", bg: "rgba(16,185,129,0.15)" }, - { day: 12, emoji: "\u26F7", label: "Glacier Paradise", color: "#fbbf24", bg: "rgba(245,158,11,0.15)" }, - { day: 13, emoji: "\u{1F3DB}", label: "Alpine Museum", color: "#a78bfa", bg: "rgba(139,92,246,0.15)" }, - { day: 14, emoji: "\u{1F68C}", label: "Bus to Dolomites", color: "#22d3ee", bg: "rgba(6,182,212,0.15)" }, - { day: 15, emoji: "\u{1F97E}", label: "Tre Cime Circuit", color: "#34d399", bg: "rgba(16,185,129,0.15)" }, - { day: 16, emoji: "\u{1FA82}", label: "Paragliding", color: "#fbbf24", bg: "rgba(245,158,11,0.15)" }, - { day: 17, emoji: "\u{1F6F6}", label: "Lago di Braies", color: "#fbbf24", bg: "rgba(245,158,11,0.15)" }, - { day: 18, emoji: "\u{1F97E}", label: "Seceda Ridge", color: "#34d399", bg: "rgba(16,185,129,0.15)" }, - { day: 19, emoji: "\u{1F4F8}", label: "Rest & Photos", color: "#94a3b8", bg: "rgba(100,116,139,0.15)" }, - { day: 20, emoji: "\u2708\uFE0F", label: "Depart", color: "#2dd4bf", bg: "rgba(20,184,166,0.15)" }, -]; - -const TABS = ["Temporal", "Spatial", "Lunar", "Context"]; - -const ZOOM_LEVELS = [ - "Era", "Century", "Decade", "Year", "Quarter", - "Month", "Week", "Day", "Hour", "Minute", -]; - const FEATURES = [ { icon: "\u{1F50D}", @@ -64,62 +30,21 @@ const FEATURES = [ }, ]; -const LEGEND = [ - { color: "#2dd4bf", label: "Travel" }, - { color: "#34d399", label: "Hike" }, - { color: "#fbbf24", label: "Adventure" }, - { color: "#22d3ee", label: "Transit" }, - { color: "#a78bfa", label: "Culture" }, - { color: "#94a3b8", label: "Rest" }, +const INTEGRATIONS = [ + { icon: "\u{1F5FA}", name: "rTrips", desc: "Travel itineraries surface as calendar events with departure/arrival times and locations." }, + { icon: "\u{1F30D}", name: "rMaps", desc: "Events appear on the map. Zoom the map and the calendar filters to show only visible events." }, + { icon: "\u{1F465}", name: "rNetwork", desc: "See availability across your network. Coordinate meetings without back-and-forth." }, + { icon: "\u{1F4DD}", name: "rNotes", desc: "Link notes to calendar events. Meeting agendas, daily journals, and retrospective logs." }, + { icon: "\u{1F4B0}", name: "rFunds", desc: "Budget reviews, treasury flows, and governance votes appear on the calendar timeline." }, + { icon: "\u2615\uFE0F", name: "rSpace", desc: "Each space has its own calendar layer. Nest calendars across spaces for cross-community coordination." }, ]; -/* ─── Helpers ─────────────────────────────────────────────── */ - -function eventForDay(day: number): CalEvent | undefined { - return TRIP_EVENTS.find((e) => e.day === day); -} - -function isTripDay(day: number): boolean { - return day >= 6 && day <= 20; -} - -/* ─── Render ──────────────────────────────────────────────── */ +const ZOOM_LEVELS = [ + "Era", "Century", "Decade", "Year", "Quarter", + "Month", "Week", "Day", "Hour", "Minute", +]; export function renderDemo(): string { - // July 2026: starts on Wednesday (offset 2 for Mon-based grid), 31 days - const firstDayOffset = 2; // Mon=0, Tue=1, Wed=2 - const totalDays = 31; - const dayNames = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]; - - // Build calendar cells - const calendarCells: string[] = []; - - // Empty offset cells - for (let i = 0; i < firstDayOffset; i++) { - calendarCells.push(`
`); - } - - // Day cells - for (let d = 1; d <= totalDays; d++) { - const ev = eventForDay(d); - const trip = isTripDay(d); - const todayClass = d === 15 ? " rcal-cell--today" : ""; - const tripClass = trip ? " rcal-cell--trip" : ""; - - let pill = ""; - if (ev) { - pill = `
- ${ev.emoji} - ${ev.label} -
`; - } - - calendarCells.push(`
- ${d} - ${pill} -
`); - } - return `
@@ -129,7 +54,7 @@ export function renderDemo(): string { Multi-Dimensional Calendar

rCal Demo

-

Multi-dimensional calendar with temporal zoom

+

Temporal coordination with lunar cycles, spatial context, and multi-scale zoom

\u{1F50D} Temporal Zoom | @@ -141,62 +66,35 @@ export function renderDemo(): string {
- +
- - -
-
-

- \u{1F4C5} July 2026 -

-
- ${TABS.map( - (tab, i) => ``, - ).join("\n ")} -
-
- - -
- ${dayNames.map((d) => `
${d}
`).join("\n ")} -
- - -
- ${calendarCells.join("\n ")} -
- - -
- Legend: - ${LEGEND.map( - (l) => ` - - ${l.label} - `, - ).join("\n ")} -
+
+ +
+
+ 1 + 2 + 3 + Day / Week / Month  \u00B7  + \u2190 + \u2192 + Navigate  \u00B7  + L + Lunar  \u00B7  + T + Today
- +
-

+

\u{1F50D} Temporal Zoom

-

- Navigate across temporal granularities. The calendar grid adapts at each zoom level. +

+ Navigate across 10 temporal granularities. The calendar adapts its grid at each level — + from geological eras to individual minutes.

${ZOOM_LEVELS.map( @@ -218,7 +116,7 @@ export function renderDemo(): string {
- +
${FEATURES.map( @@ -232,6 +130,23 @@ export function renderDemo(): string {
+ +
+

+ r* Ecosystem Integrations +

+
+ ${INTEGRATIONS.map( + (i) => ` +
+
${i.icon}
+

${i.name}

+

${i.desc}

+
`, + ).join("")} +
+
+
@@ -246,99 +161,5 @@ export function renderDemo(): string {
- - -`; +`; } diff --git a/modules/rcal/mod.ts b/modules/rcal/mod.ts index 91c6ed6..e733302 100644 --- a/modules/rcal/mod.ts +++ b/modules/rcal/mod.ts @@ -385,8 +385,8 @@ routes.get("/", (c) => { modules: getModuleInfoList(), theme: "dark", body: renderDemo(), - scripts: ``, - styles: ``, + scripts: ``, + styles: ``, })); } return c.html(renderShell({ @@ -426,4 +426,8 @@ export const calModule: RSpaceModule = { }, ], acceptsFeeds: ["data", "governance"], + outputPaths: [ + { path: "saved-views", name: "Saved Views", icon: "👁️", description: "Custom calendar views and filters" }, + { path: "events", name: "Events", icon: "📅", description: "Calendar events across all systems" }, + ], };