From 358deac191464c5ea16aca2cc284a3e7dc0b1260 Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Mon, 4 May 2026 17:30:09 +0000 Subject: [PATCH 1/2] feat: add sunsama-web workspace with task management UI Port the Sunsama Clone UI (https://github.com/Hamsa-code-ui/sunsamaClone) as a new @workspace/sunsama-web package in the monorepo. - Dark-themed task planner with sidebar, day columns, and calendar pane - Task cards with subtasks, progress bars, and time estimates - Task editor dialog with date picker and tag selection - Horizontal scrollable day grid with auto-scroll to today - Uses local state (no Convex dependency) with sample data - Follows existing monorepo conventions (Vite, React, catalog deps) - Lucide icons replace image-based icons for better DX - date-fns replaces dayjs for consistency with admin-web Co-Authored-By: adamer --- artifacts/sunsama-web/index.html | 15 + artifacts/sunsama-web/package.json | 29 + artifacts/sunsama-web/src/App.tsx | 5 + artifacts/sunsama-web/src/index.css | 15 + artifacts/sunsama-web/src/main.tsx | 10 + .../src/pages/home/BoardHeader.tsx | 12 + .../src/pages/home/CalendarPane.tsx | 29 + .../src/pages/home/CalendarSelect.tsx | 49 + .../sunsama-web/src/pages/home/DayColumn.tsx | 39 + .../sunsama-web/src/pages/home/Homepage.tsx | 131 ++ .../src/pages/home/ProgressBar.tsx | 18 + .../sunsama-web/src/pages/home/Sidebar.tsx | 25 + .../src/pages/home/SubtaskItem.tsx | 38 + .../sunsama-web/src/pages/home/TaskCard.tsx | 90 ++ .../sunsama-web/src/pages/home/TaskEditor.tsx | 119 ++ .../src/pages/home/generateDays.ts | 24 + .../sunsama-web/src/pages/home/homepage.css | 579 +++++++ .../sunsama-web/src/pages/home/sampleData.ts | 65 + artifacts/sunsama-web/src/pages/home/types.ts | 20 + artifacts/sunsama-web/tsconfig.json | 16 + artifacts/sunsama-web/vite.config.ts | 37 + pnpm-lock.yaml | 1349 +++++++++++++++-- 22 files changed, 2620 insertions(+), 94 deletions(-) create mode 100644 artifacts/sunsama-web/index.html create mode 100644 artifacts/sunsama-web/package.json create mode 100644 artifacts/sunsama-web/src/App.tsx create mode 100644 artifacts/sunsama-web/src/index.css create mode 100644 artifacts/sunsama-web/src/main.tsx create mode 100644 artifacts/sunsama-web/src/pages/home/BoardHeader.tsx create mode 100644 artifacts/sunsama-web/src/pages/home/CalendarPane.tsx create mode 100644 artifacts/sunsama-web/src/pages/home/CalendarSelect.tsx create mode 100644 artifacts/sunsama-web/src/pages/home/DayColumn.tsx create mode 100644 artifacts/sunsama-web/src/pages/home/Homepage.tsx create mode 100644 artifacts/sunsama-web/src/pages/home/ProgressBar.tsx create mode 100644 artifacts/sunsama-web/src/pages/home/Sidebar.tsx create mode 100644 artifacts/sunsama-web/src/pages/home/SubtaskItem.tsx create mode 100644 artifacts/sunsama-web/src/pages/home/TaskCard.tsx create mode 100644 artifacts/sunsama-web/src/pages/home/TaskEditor.tsx create mode 100644 artifacts/sunsama-web/src/pages/home/generateDays.ts create mode 100644 artifacts/sunsama-web/src/pages/home/homepage.css create mode 100644 artifacts/sunsama-web/src/pages/home/sampleData.ts create mode 100644 artifacts/sunsama-web/src/pages/home/types.ts create mode 100644 artifacts/sunsama-web/tsconfig.json create mode 100644 artifacts/sunsama-web/vite.config.ts diff --git a/artifacts/sunsama-web/index.html b/artifacts/sunsama-web/index.html new file mode 100644 index 0000000..1995b2b --- /dev/null +++ b/artifacts/sunsama-web/index.html @@ -0,0 +1,15 @@ + + + + + + Sunsama + + + + + +
+ + + diff --git a/artifacts/sunsama-web/package.json b/artifacts/sunsama-web/package.json new file mode 100644 index 0000000..687eb05 --- /dev/null +++ b/artifacts/sunsama-web/package.json @@ -0,0 +1,29 @@ +{ + "name": "@workspace/sunsama-web", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite --host 0.0.0.0", + "build": "vite build", + "preview": "vite preview --host 0.0.0.0", + "typecheck": "tsc -p tsconfig.json --noEmit" + }, + "devDependencies": { + "@radix-ui/react-popover": "^1.1.15", + "@tailwindcss/vite": "catalog:", + "@types/node": "catalog:", + "@types/react": "catalog:", + "@types/react-dom": "catalog:", + "@vitejs/plugin-react": "catalog:", + "@replit/vite-plugin-runtime-error-modal": "catalog:", + "date-fns": "^3.6.0", + "lucide-react": "catalog:", + "react": "catalog:", + "react-day-picker": "^9.11.1", + "react-dom": "catalog:", + "tailwind-merge": "catalog:", + "tailwindcss": "catalog:", + "vite": "catalog:" + } +} diff --git a/artifacts/sunsama-web/src/App.tsx b/artifacts/sunsama-web/src/App.tsx new file mode 100644 index 0000000..4feb104 --- /dev/null +++ b/artifacts/sunsama-web/src/App.tsx @@ -0,0 +1,5 @@ +import { HomePage } from "./pages/home/Homepage"; + +export default function App() { + return ; +} diff --git a/artifacts/sunsama-web/src/index.css b/artifacts/sunsama-web/src/index.css new file mode 100644 index 0000000..0ca1172 --- /dev/null +++ b/artifacts/sunsama-web/src/index.css @@ -0,0 +1,15 @@ +@import "tailwindcss"; + +*, +*::before, +*::after { + box-sizing: border-box; +} + +html, +body { + height: 100%; + margin: 0; + font-family: Inter, ui-sans-serif, system-ui, -apple-system, "Segoe UI", + Roboto, "Helvetica Neue", Arial, sans-serif; +} diff --git a/artifacts/sunsama-web/src/main.tsx b/artifacts/sunsama-web/src/main.tsx new file mode 100644 index 0000000..c2a145c --- /dev/null +++ b/artifacts/sunsama-web/src/main.tsx @@ -0,0 +1,10 @@ +import { StrictMode } from "react"; +import { createRoot } from "react-dom/client"; +import App from "./App"; +import "./index.css"; + +createRoot(document.getElementById("root")!).render( + + + , +); diff --git a/artifacts/sunsama-web/src/pages/home/BoardHeader.tsx b/artifacts/sunsama-web/src/pages/home/BoardHeader.tsx new file mode 100644 index 0000000..ae92a6d --- /dev/null +++ b/artifacts/sunsama-web/src/pages/home/BoardHeader.tsx @@ -0,0 +1,12 @@ +import "./homepage.css"; + +export default function BoardHeader() { + return ( +
+
+ + +
+
+ ); +} diff --git a/artifacts/sunsama-web/src/pages/home/CalendarPane.tsx b/artifacts/sunsama-web/src/pages/home/CalendarPane.tsx new file mode 100644 index 0000000..4c13706 --- /dev/null +++ b/artifacts/sunsama-web/src/pages/home/CalendarPane.tsx @@ -0,0 +1,29 @@ +import "./homepage.css"; + +export default function CalendarPane() { + const now = new Date(); + const dayAbbr = now + .toLocaleDateString("en-US", { weekday: "short" }) + .toUpperCase(); + const dayNum = now.getDate(); + + return ( + + ); +} diff --git a/artifacts/sunsama-web/src/pages/home/CalendarSelect.tsx b/artifacts/sunsama-web/src/pages/home/CalendarSelect.tsx new file mode 100644 index 0000000..4883f2f --- /dev/null +++ b/artifacts/sunsama-web/src/pages/home/CalendarSelect.tsx @@ -0,0 +1,49 @@ +import { useState } from "react"; +import * as Popover from "@radix-ui/react-popover"; +import { CalendarIcon } from "lucide-react"; +import { DayPicker } from "react-day-picker"; +import { format, isToday } from "date-fns"; +import "react-day-picker/style.css"; + +interface Props { + value?: string; + onSelect?: (dateString: string) => void; +} + +export default function CalendarSelect({ value, onSelect }: Props) { + const initial = value ? new Date(value) : new Date(); + const [date, setDate] = useState(initial); + const [open, setOpen] = useState(false); + + function handleSelect(d: Date | undefined) { + if (!d) return; + setDate(d); + const iso = format(d, "yyyy-MM-dd"); + if (onSelect) onSelect(iso); + setOpen(false); + } + + return ( + + + + + + +
+ Schedule exact start date +
+ +
+
+ ); +} diff --git a/artifacts/sunsama-web/src/pages/home/DayColumn.tsx b/artifacts/sunsama-web/src/pages/home/DayColumn.tsx new file mode 100644 index 0000000..eb91dcd --- /dev/null +++ b/artifacts/sunsama-web/src/pages/home/DayColumn.tsx @@ -0,0 +1,39 @@ +import type { DayItem, Project } from "./types"; +import "./homepage.css"; +import TaskCard from "./TaskCard"; + +interface Props { + day: DayItem; + projects: Project[]; + openEditor: (dayId: string) => void; + pendingToggles: Record; + onToggleSubtask: (projectId: string, subtaskTitle: string) => void; +} + +export default function DayColumn({ + day, + projects, + openEditor, + pendingToggles, + onToggleSubtask, +}: Props) { + return ( +
+
+
{day.name}
+
{day.date}
+
+ + {projects.map((p) => ( + + ))} +
+ ); +} diff --git a/artifacts/sunsama-web/src/pages/home/Homepage.tsx b/artifacts/sunsama-web/src/pages/home/Homepage.tsx new file mode 100644 index 0000000..9ccb981 --- /dev/null +++ b/artifacts/sunsama-web/src/pages/home/Homepage.tsx @@ -0,0 +1,131 @@ +import "./homepage.css"; +import { useRef, useEffect, useState, useMemo } from "react"; +import type { Project } from "./types"; +import { generateDays } from "./generateDays"; +import { sampleProjects } from "./sampleData"; +import Sidebar from "./Sidebar"; +import BoardHeader from "./BoardHeader"; +import DayColumn from "./DayColumn"; +import TaskEditor from "./TaskEditor"; +import CalendarPane from "./CalendarPane"; + +export function HomePage() { + const days = useMemo(() => generateDays(), []); + const todayIndex = 29; + const daysRef = useRef(null); + + const [localProjects, setLocalProjects] = + useState(sampleProjects); + const [pendingToggles, setPendingToggles] = useState< + Record + >({}); + + const [editor, setEditor] = useState<{ + open: boolean; + dayId?: string; + title?: string; + tag?: string; + timeEstimate?: number; + }>({ open: false }); + + function openEditor(dayId: string) { + setEditor({ open: true, dayId, title: "", tag: "# work", timeEstimate: 30 }); + } + + function closeEditor() { + setEditor({ open: false }); + } + + function saveEditor() { + if (!editor.dayId) return closeEditor(); + const newTask: Project = { + _id: `local-${Date.now()}`, + title: editor.title || "New task", + date: editor.dayId, + plannedTime: editor.timeEstimate ?? 0, + subtasks: [], + tag: editor.tag, + }; + + setLocalProjects((prev) => [newTask, ...prev]); + closeEditor(); + } + + function handleWheel(e: React.WheelEvent) { + const el = daysRef.current; + if (!el) return; + if (Math.abs(e.deltaY) > Math.abs(e.deltaX)) { + el.scrollLeft += e.deltaY; + e.preventDefault(); + } + } + + useEffect(() => { + const container = daysRef.current; + const todayEl = container?.children[todayIndex - 1] as + | HTMLElement + | undefined; + if (!container || !todayEl) return; + container.scrollTo({ left: todayEl.offsetLeft, behavior: "instant" }); + }, [todayIndex]); + + function handleToggleSubtask(projectId: string, subtaskTitle: string) { + const toggleKey = `${projectId}::${subtaskTitle}`; + if (pendingToggles[toggleKey]) return; + + setLocalProjects((prev) => + prev.map((p) => { + if (p._id !== projectId) return p; + return { + ...p, + subtasks: p.subtasks.map((s) => + s.title === subtaskTitle ? { ...s, isDone: !s.isDone } : s, + ), + }; + }), + ); + + setPendingToggles((prev) => ({ ...prev, [toggleKey]: true })); + setTimeout(() => { + setPendingToggles((prev) => { + const copy = { ...prev }; + delete copy[toggleKey]; + return copy; + }); + }, 300); + } + + return ( +
+ + +
+ + +
+ {days.map((day) => ( + p.date === day.id)} + openEditor={openEditor} + pendingToggles={pendingToggles} + onToggleSubtask={handleToggleSubtask} + /> + ))} +
+ + {editor.open && ( + + )} +
+ + +
+ ); +} diff --git a/artifacts/sunsama-web/src/pages/home/ProgressBar.tsx b/artifacts/sunsama-web/src/pages/home/ProgressBar.tsx new file mode 100644 index 0000000..43b185c --- /dev/null +++ b/artifacts/sunsama-web/src/pages/home/ProgressBar.tsx @@ -0,0 +1,18 @@ +import "./homepage.css"; + +interface ProgressBarProps { + progress: number; +} + +export default function ProgressBar({ progress }: ProgressBarProps) { + const clampProgress = Math.min(Math.max(progress, 0), 100); + + return ( +
+
+
+ ); +} diff --git a/artifacts/sunsama-web/src/pages/home/Sidebar.tsx b/artifacts/sunsama-web/src/pages/home/Sidebar.tsx new file mode 100644 index 0000000..b8e8d8b --- /dev/null +++ b/artifacts/sunsama-web/src/pages/home/Sidebar.tsx @@ -0,0 +1,25 @@ +import "./homepage.css"; + +export default function Sidebar() { + return ( + + ); +} diff --git a/artifacts/sunsama-web/src/pages/home/SubtaskItem.tsx b/artifacts/sunsama-web/src/pages/home/SubtaskItem.tsx new file mode 100644 index 0000000..6902743 --- /dev/null +++ b/artifacts/sunsama-web/src/pages/home/SubtaskItem.tsx @@ -0,0 +1,38 @@ +import type { Subtask } from "./types"; +import "./homepage.css"; +import { Circle, CheckCircle2 } from "lucide-react"; + +interface Props { + projectId: string; + subtask: Subtask; + inFlight: boolean; + onToggle: (projectId: string, subtaskTitle: string) => void; +} + +export default function SubtaskItem({ + projectId, + subtask, + inFlight, + onToggle, +}: Props) { + return ( +
+ { + if (!inFlight) onToggle(projectId, subtask.title); + }} + > + {subtask.isDone ? ( + + ) : ( + + )} + +
+ {subtask.title} +
+
+ ); +} diff --git a/artifacts/sunsama-web/src/pages/home/TaskCard.tsx b/artifacts/sunsama-web/src/pages/home/TaskCard.tsx new file mode 100644 index 0000000..c419eb7 --- /dev/null +++ b/artifacts/sunsama-web/src/pages/home/TaskCard.tsx @@ -0,0 +1,90 @@ +import "./homepage.css"; +import ProgressBar from "./ProgressBar"; +import type { Project, Subtask } from "./types"; +import SubtaskItem from "./SubtaskItem"; + +interface Props { + project: Project; + pendingToggles: Record; + onToggleSubtask: (projectId: string, subtaskTitle: string) => void; +} + +export default function TaskCard({ + project, + pendingToggles, + onToggleSubtask, +}: Props) { + const total = project.subtasks?.length || 0; + const done = + project.subtasks?.filter((s: Subtask) => s.isDone).length || 0; + const progress = total > 0 ? Math.round((done / total) * 100) : 0; + + return ( +
+
+
+
{project.title}
+
{project.plannedTime ?? 0}m
+
+ +
+ {project.subtasks?.map((subtask: Subtask, idx: number) => { + const toggleKey = `${project._id}::${subtask.title}`; + const inFlight = !!pendingToggles[toggleKey]; + return ( + + ); + })} +
+
+
+ + + + + + + +
+
{project.tag ?? "# work"}
+
+
+
+ ); +} diff --git a/artifacts/sunsama-web/src/pages/home/TaskEditor.tsx b/artifacts/sunsama-web/src/pages/home/TaskEditor.tsx new file mode 100644 index 0000000..d968cde --- /dev/null +++ b/artifacts/sunsama-web/src/pages/home/TaskEditor.tsx @@ -0,0 +1,119 @@ +import "./homepage.css"; +import type { Dispatch, SetStateAction } from "react"; +import { + format, + isToday, + isTomorrow, + isYesterday, +} from "date-fns"; +import CalendarSelect from "./CalendarSelect"; +import { Clock } from "lucide-react"; + +interface EditorState { + open: boolean; + dayId?: string; + title?: string; + tag?: string; + timeEstimate?: number; +} + +interface Props { + editor: EditorState; + setEditor: Dispatch>; + closeEditor: () => void; + saveEditor: () => void; +} + +export default function TaskEditor({ + editor, + setEditor, + closeEditor, + saveEditor, +}: Props) { + let displayDate: string; + if (editor.dayId) { + const parsed = new Date(editor.dayId + "T00:00:00"); + if (isToday(parsed)) { + displayDate = "Today"; + } else if (isTomorrow(parsed)) { + displayDate = "Tomorrow"; + } else if (isYesterday(parsed)) { + displayDate = "Yesterday"; + } else { + displayDate = format(parsed, "EEEE, MMM d"); + } + } else { + displayDate = format(new Date(), "EEEE, MMM d"); + } + + void displayDate; + + return ( + <> +
+
+ + setEditor((s) => ({ ...s, title: e.target.value })) + } + onKeyDown={(e) => { + if (e.key === "Escape") { + closeEditor(); + } else if (e.key === "Enter") { + e.preventDefault(); + saveEditor(); + } + }} + /> + +
+
+ + + +
+
+
+ + ); +} diff --git a/artifacts/sunsama-web/src/pages/home/generateDays.ts b/artifacts/sunsama-web/src/pages/home/generateDays.ts new file mode 100644 index 0000000..65a78c9 --- /dev/null +++ b/artifacts/sunsama-web/src/pages/home/generateDays.ts @@ -0,0 +1,24 @@ +import type { DayItem } from "./types"; + +export function generateDays( + center = new Date(), + daysBefore = 30, + daysAfter = 30, +): DayItem[] { + const result: DayItem[] = []; + const start = new Date(center); + start.setDate(start.getDate() - daysBefore); + + for (let i = 0; i <= daysBefore + daysAfter; i++) { + const d = new Date(start); + d.setDate(start.getDate() + i); + result.push({ + id: d.toISOString().split("T")[0], + name: d.toLocaleDateString("en-US", { weekday: "long" }), + date: d.toLocaleDateString("en-US", { day: "2-digit", month: "long" }), + fullDate: d, + }); + } + + return result; +} diff --git a/artifacts/sunsama-web/src/pages/home/homepage.css b/artifacts/sunsama-web/src/pages/home/homepage.css new file mode 100644 index 0000000..3b50451 --- /dev/null +++ b/artifacts/sunsama-web/src/pages/home/homepage.css @@ -0,0 +1,579 @@ +:root { + --bg: #0b0b0c; + --panel: #121213; + --muted: #9b9b9b; + --accent: #ff6b6b; + --card: #181819; + --soft: #262626; + --text: #e9e9e9; + --radius: 8px; +} + +* { + box-sizing: border-box; +} + +html, +body { + height: 100%; +} + +body { + margin: 0; + font-family: Inter, ui-sans-serif, system-ui, -apple-system, "Segoe UI", + Roboto, "Helvetica Neue", Arial; + background: var(--bg); + color: var(--text); +} + +.app { + display: flex; + height: 100vh; + align-items: stretch; +} + +/* ── Sidebar ─────────────────────────────────────────── */ +.sidebar { + width: 300px; + background: linear-gradient(180deg, var(--panel), #0c0c0c); + padding: 32px 20px; + display: flex; + flex-direction: column; + gap: 18px; + border-right: 1px solid #31363f; +} + +.logo { + font-weight: 700; + font-size: 18px; + margin-bottom: 8px; +} + +.main-nav { + display: flex; + flex-direction: column; + gap: 10px; +} + +.nav-item { + color: var(--muted); + padding: 10px 8px; + border-radius: 8px; + display: flex; + align-items: center; + gap: 10px; + cursor: pointer; + text-decoration: none; +} + +.nav-item.active { + color: var(--text); + background: #31363f; +} + +.nav-item:hover { + color: var(--text); +} + +.section { + margin-top: 14px; + color: var(--muted); + font-size: 12px; + text-transform: uppercase; +} + +.invite { + margin-top: auto; + color: var(--muted); + font-size: 13px; + cursor: pointer; +} + +/* ── Board ───────────────────────────────────────────── */ +.board { + flex: 1; + padding: 22px 28px 28px 32px; + display: flex; + flex-direction: column; + gap: 16px; + min-width: 0; + position: relative; +} + +.board-header { + display: flex; + align-items: center; + justify-content: space-between; +} + +.btn { + background: var(--card); + border: 1px solid rgba(255, 255, 255, 0.04); + color: var(--text); + padding: 10px 14px; + border-radius: 8px; + cursor: pointer; +} + +.btn.ghost { + background: transparent; +} + +.btn.small { + font-size: 13px; + padding: 8px 12px; +} + +.controls-left { + display: flex; + gap: 10px; + align-items: center; +} + +/* ── Days grid ───────────────────────────────────────── */ +.days { + display: flex; + gap: 22px; + align-items: flex-start; + overflow-x: auto; + padding-bottom: 12px; + scroll-behavior: smooth; +} + +.days::-webkit-scrollbar { + height: 10px; +} + +.days::-webkit-scrollbar-track { + background: transparent; +} + +.days::-webkit-scrollbar-thumb { + background: rgba(255, 255, 255, 0.05); + border-radius: 6px; +} + +.day-col { + background: transparent; + flex: 0 0 360px; + min-width: 300px; + display: flex; + flex-direction: column; + height: 78vh; + max-height: 100%; +} + +.day-head { + margin-bottom: 14px; +} + +.day-name { + font-weight: 700; + font-size: 28px; + line-height: 1; +} + +.day-date { + color: var(--muted); + font-size: 14px; + margin-top: 6px; +} + +.add-task { + background: var(--card); + padding: 12px; + border-radius: 8px; + color: var(--muted); + margin-bottom: 14px; + box-shadow: 0 1px 0 rgba(255, 255, 255, 0.02); + display: flex; + align-items: center; + justify-content: flex-start; + border: none; + cursor: pointer; + font-size: 14px; +} + +.add-task:hover { + background: #2a2a2b; +} + +/* ── Task card ───────────────────────────────────────── */ +.task { + background: #1f1f20; + border-radius: 10px; + padding: 16px; + margin-bottom: 14px; + color: var(--text); + box-shadow: 0 8px 22px rgba(0, 0, 0, 0.6); + border: 1px solid rgba(255, 255, 255, 0.02); +} + +.task-project { + display: flex; + flex-direction: column; + gap: 8px; +} + +.task-name { + font-weight: 600; + font-size: 17px; +} + +.task-header { + display: flex; + justify-content: space-between; + align-items: center; + gap: 12px; + margin-bottom: 8px; +} + +.time-badge { + background: #141415; + border-radius: 10px; + padding: 6px 10px; + color: var(--muted); + font-size: 12px; + border: 1px solid rgba(255, 255, 255, 0.02); +} + +.task-middlesection { + display: flex; + flex-direction: column; + gap: 8px; + padding-right: 8px; +} + +/* ── Subtask ─────────────────────────────────────────── */ +.subtask { + display: flex; + align-items: center; + gap: 12px; + color: var(--muted); + font-size: 14px; +} + +.subtask-icon-wrapper { + display: flex; + align-items: center; + cursor: pointer; + opacity: 0.95; +} + +.subtask-check-icon { + color: var(--muted); +} + +.subtask-check-icon.done { + color: #76abae; +} + +.subtask-title { + color: var(--muted); + margin-left: 4px; +} + +.subtask-title.done { + text-decoration: line-through; + opacity: 0.6; +} + +/* ── Task footer ─────────────────────────────────────── */ +.task-footer { + display: flex; + justify-content: space-between; + align-items: center; + margin-top: 12px; +} + +.footer-icons { + display: flex; + gap: 10px; + align-items: center; +} + +.footer-icon { + width: 20px; + height: 20px; + border-radius: 6px; + color: var(--muted); + opacity: 0.95; +} + +.footer-icon path { + stroke: rgba(255, 255, 255, 0.7); +} + +.tag { + color: #ffb86b; + background: transparent; + font-weight: 700; + font-size: 13px; +} + +/* ── Progress bar ────────────────────────────────────── */ +.progress-container { + position: relative; + width: 100%; + height: 12px; + background-color: #262626; + border-radius: 6px; + overflow: hidden; +} + +.progress-fill { + height: 100%; + background-color: #76abae; + transition: width 0.3s ease; +} + +/* ── Calendar pane ───────────────────────────────────── */ +.calendar-pane { + width: 340px; + background: #0f0f10; + border-left: 1px solid rgba(255, 255, 255, 0.03); + display: flex; + flex-direction: column; + position: relative; + padding: 14px; + height: 100vh; + box-sizing: border-box; +} + +.calendar-top { + padding-bottom: 12px; + border-bottom: 1px solid rgba(255, 255, 255, 0.02); + margin-bottom: 10px; +} + +.month { + background: #222831; + padding: 14px; + border-radius: 8px; + text-align: center; + color: var(--text); + font-weight: 700; + font-size: 18px; +} + +.calendar-hours { + flex: 1; + overflow: hidden; + min-height: 0; + display: flex; + flex-direction: column; +} + +.hours-grid { + flex: 1; + min-height: 0; + height: 100%; + background: linear-gradient(180deg, transparent, transparent); + position: relative; +} + +.hours-grid::before { + content: ""; + position: absolute; + left: 52px; + right: 18px; + top: 0; + bottom: 0; + background-image: repeating-linear-gradient( + to bottom, + transparent 0 56px, + rgba(255, 255, 255, 0.02) 57px + ); + opacity: 0.9; +} + +.hours-grid::after { + content: ""; + position: absolute; + left: 0; + right: 0; + bottom: 0; + height: 1px; + background: linear-gradient( + 90deg, + transparent, + rgba(255, 255, 255, 0.02), + transparent + ); +} + +.chat-btn { + position: absolute; + right: 18px; + bottom: 18px; + background: linear-gradient(180deg, #ff7b7b, #ff5a5a); + width: 64px; + height: 64px; + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + color: white; + font-size: 22px; + box-shadow: 0 10px 30px rgba(0, 0, 0, 0.6); + cursor: pointer; +} + +/* ── Task editor dialog ──────────────────────────────── */ +.editor-backdrop { + position: fixed; + inset: 0; + background: rgba(0, 0, 0, 0.6); + z-index: 160; +} + +.task-editor { + position: fixed; + left: 50%; + top: 12vh; + transform: translateX(-50%); + width: min(900px, calc(100% - 48px)); + background: #1e1e20; + border-radius: 12px; + padding: 22px 22px 18px; + box-shadow: 0 28px 90px rgba(0, 0, 0, 0.75); + z-index: 170; + border: 1px solid rgba(255, 255, 255, 0.04); +} + +.editor-title { + width: 100%; + padding: 14px; + border-radius: 10px; + border: 1px solid rgba(255, 255, 255, 0.03); + background: transparent; + color: var(--text); + font-size: 18px; + margin-bottom: 12px; + outline: none; +} + +.editor-footer { + display: flex; + justify-content: space-between; + align-items: center; + margin-top: 14px; +} + +.editor-left { + display: flex; + gap: 14px; + align-items: center; +} + +.editor-label { + display: flex; + align-items: center; + gap: 8px; + color: var(--muted); + font-size: 14px; +} + +.clock-icon { + opacity: 0.95; + color: var(--muted); +} + +.editor-select { + background: #161616; + color: var(--muted); + border-radius: 8px; + padding: 8px 10px; + border: 1px solid rgba(255, 255, 255, 0.02); +} + +/* ── Calendar select popover ─────────────────────────── */ +.calendar-popover { + background: #0f0f10; + color: var(--text); + padding: 12px; + border-radius: 10px; + box-shadow: 0 18px 60px rgba(0, 0, 0, 0.6); + border: 1px solid rgba(255, 255, 255, 0.03); + min-width: 260px; +} + +.calendar-popover-header { + font-size: 13px; + color: var(--muted); + padding: 6px 8px 10px; +} + +.calendar-trigger { + display: inline-flex; + align-items: center; + gap: 8px; + padding: 6px 10px; + border-radius: 8px; + background: transparent; + border: 1px solid rgba(255, 255, 255, 0.02); + color: var(--muted); + cursor: pointer; +} + +.calendar-trigger .calendar-icon { + width: 16px; + height: 16px; + opacity: 0.9; + color: #948979; +} + +/* react-day-picker dark theme */ +.rdp { + color: var(--text); +} + +.rdp-day { + background: transparent; + border-radius: 6px; +} + +.rdp-day_selected, +.rdp-day_selected:focus { + color: #2b6cb0; + background: white; +} + +.rdp-nav { + display: flex; + align-items: center; + justify-content: space-between; + padding: 6px 8px; +} + +.rdp-caption { + font-weight: 700; +} + +.rdp-head_cell { + color: var(--muted); +} + +.rdp-day:hover { + background: rgba(255, 255, 255, 0.03); +} + +/* ── Responsive ──────────────────────────────────────── */ +@media (max-width: 1000px) { + .calendar-pane { + display: none; + } +} + +@media (max-width: 768px) { + .sidebar { + width: 200px; + padding: 20px 12px; + } +} + +@media (max-width: 600px) { + .sidebar { + display: none; + } +} diff --git a/artifacts/sunsama-web/src/pages/home/sampleData.ts b/artifacts/sunsama-web/src/pages/home/sampleData.ts new file mode 100644 index 0000000..73b5295 --- /dev/null +++ b/artifacts/sunsama-web/src/pages/home/sampleData.ts @@ -0,0 +1,65 @@ +import { format, addDays } from "date-fns"; +import type { Project } from "./types"; + +const today = format(new Date(), "yyyy-MM-dd"); +const tomorrow = format(addDays(new Date(), 1), "yyyy-MM-dd"); + +export const sampleProjects: Project[] = [ + { + _id: "sample-1", + title: "Design landing page", + date: today, + plannedTime: 60, + tag: "# work", + subtasks: [ + { title: "Create wireframe", isDone: true }, + { title: "Choose color palette", isDone: true }, + { title: "Build in Figma", isDone: false }, + ], + }, + { + _id: "sample-2", + title: "Review pull requests", + date: today, + plannedTime: 30, + tag: "# work", + subtasks: [ + { title: "Check API changes", isDone: false }, + { title: "Test frontend build", isDone: false }, + ], + }, + { + _id: "sample-3", + title: "Weekly team sync", + date: today, + plannedTime: 45, + tag: "# work", + subtasks: [ + { title: "Prepare agenda", isDone: true }, + { title: "Share meeting notes", isDone: false }, + ], + }, + { + _id: "sample-4", + title: "Write blog post", + date: tomorrow, + plannedTime: 90, + tag: "# personal", + subtasks: [ + { title: "Draft outline", isDone: false }, + { title: "Write first section", isDone: false }, + { title: "Add images", isDone: false }, + ], + }, + { + _id: "sample-5", + title: "Grocery shopping", + date: tomorrow, + plannedTime: 30, + tag: "# errands", + subtasks: [ + { title: "Check fridge inventory", isDone: true }, + { title: "Make shopping list", isDone: false }, + ], + }, +]; diff --git a/artifacts/sunsama-web/src/pages/home/types.ts b/artifacts/sunsama-web/src/pages/home/types.ts new file mode 100644 index 0000000..51600ba --- /dev/null +++ b/artifacts/sunsama-web/src/pages/home/types.ts @@ -0,0 +1,20 @@ +export interface Subtask { + title: string; + isDone: boolean; +} + +export interface Project { + _id: string; + title: string; + date: string; + plannedTime: number; + subtasks: Subtask[]; + tag?: string; +} + +export interface DayItem { + id: string; + name: string; + date: string; + fullDate: Date; +} diff --git a/artifacts/sunsama-web/tsconfig.json b/artifacts/sunsama-web/tsconfig.json new file mode 100644 index 0000000..78bd2d1 --- /dev/null +++ b/artifacts/sunsama-web/tsconfig.json @@ -0,0 +1,16 @@ +{ + "extends": "../../tsconfig.base.json", + "include": ["src/**/*"], + "exclude": ["node_modules", "build", "dist", "**/*.test.ts"], + "compilerOptions": { + "noEmit": true, + "jsx": "preserve", + "lib": ["es2022", "dom", "dom.iterable"], + "resolveJsonModule": true, + "allowImportingTsExtensions": true, + "types": ["node", "vite/client"], + "paths": { + "@/*": ["./src/*"] + } + } +} diff --git a/artifacts/sunsama-web/vite.config.ts b/artifacts/sunsama-web/vite.config.ts new file mode 100644 index 0000000..aaa8e91 --- /dev/null +++ b/artifacts/sunsama-web/vite.config.ts @@ -0,0 +1,37 @@ +import { defineConfig } from "vite"; +import react from "@vitejs/plugin-react"; +import tailwindcss from "@tailwindcss/vite"; +import path from "path"; +import runtimeErrorOverlay from "@replit/vite-plugin-runtime-error-modal"; + +const rawPort = process.env.PORT ?? "5180"; +const port = Number(rawPort) || 5180; + +export default defineConfig({ + plugins: [react(), tailwindcss(), runtimeErrorOverlay()], + resolve: { + alias: { + "@": path.resolve(import.meta.dirname, "src"), + }, + dedupe: ["react", "react-dom"], + }, + root: path.resolve(import.meta.dirname), + build: { + outDir: path.resolve(import.meta.dirname, "dist"), + emptyOutDir: true, + }, + server: { + port, + host: "0.0.0.0", + allowedHosts: true, + fs: { + strict: true, + deny: ["**/.*"], + }, + }, + preview: { + port, + host: "0.0.0.0", + allowedHosts: true, + }, +}); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4ed2a08..19037bf 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -70,89 +70,6 @@ catalogs: specifier: 3.25.76 version: 3.25.76 -overrides: - esbuild>@esbuild/darwin-arm64: '-' - esbuild>@esbuild/darwin-x64: '-' - esbuild>@esbuild/freebsd-arm64: '-' - esbuild>@esbuild/freebsd-x64: '-' - esbuild>@esbuild/linux-arm: '-' - esbuild>@esbuild/linux-arm64: '-' - esbuild>@esbuild/linux-ia32: '-' - esbuild>@esbuild/linux-loong64: '-' - esbuild>@esbuild/linux-mips64el: '-' - esbuild>@esbuild/linux-ppc64: '-' - esbuild>@esbuild/linux-riscv64: '-' - esbuild>@esbuild/linux-s390x: '-' - esbuild>@esbuild/netbsd-arm64: '-' - esbuild>@esbuild/netbsd-x64: '-' - esbuild>@esbuild/openbsd-arm64: '-' - esbuild>@esbuild/openbsd-x64: '-' - esbuild>@esbuild/sunos-x64: '-' - esbuild>@esbuild/win32-arm64: '-' - esbuild>@esbuild/win32-ia32: '-' - esbuild>@esbuild/win32-x64: '-' - esbuild>@esbuild/aix-ppc64: '-' - esbuild>@esbuild/android-arm: '-' - esbuild>@esbuild/android-arm64: '-' - esbuild>@esbuild/android-x64: '-' - esbuild>@esbuild/openharmony-arm64: '-' - lightningcss>lightningcss-android-arm64: '-' - lightningcss>lightningcss-darwin-arm64: '-' - lightningcss>lightningcss-darwin-x64: '-' - lightningcss>lightningcss-freebsd-x64: '-' - lightningcss>lightningcss-linux-arm-gnueabihf: '-' - lightningcss>lightningcss-linux-arm64-gnu: '-' - lightningcss>lightningcss-linux-arm64-musl: '-' - lightningcss>lightningcss-linux-x64-musl: '-' - lightningcss>lightningcss-win32-arm64-msvc: '-' - lightningcss>lightningcss-win32-x64-msvc: '-' - '@tailwindcss/oxide>@tailwindcss/oxide-android-arm64': '-' - '@tailwindcss/oxide>@tailwindcss/oxide-darwin-arm64': '-' - '@tailwindcss/oxide>@tailwindcss/oxide-darwin-x64': '-' - '@tailwindcss/oxide>@tailwindcss/oxide-freebsd-x64': '-' - '@tailwindcss/oxide>@tailwindcss/oxide-linux-arm-gnueabihf': '-' - '@tailwindcss/oxide>@tailwindcss/oxide-linux-arm64-gnu': '-' - '@tailwindcss/oxide>@tailwindcss/oxide-linux-arm64-musl': '-' - '@tailwindcss/oxide>@tailwindcss/oxide-win32-arm64-msvc': '-' - '@tailwindcss/oxide>@tailwindcss/oxide-win32-x64-msvc': '-' - '@tailwindcss/oxide>@tailwindcss/oxide-linux-x64-musl': '-' - rollup>@rollup/rollup-android-arm-eabi: '-' - rollup>@rollup/rollup-android-arm64: '-' - rollup>@rollup/rollup-darwin-arm64: '-' - rollup>@rollup/rollup-darwin-x64: '-' - rollup>@rollup/rollup-freebsd-arm64: '-' - rollup>@rollup/rollup-freebsd-x64: '-' - rollup>@rollup/rollup-linux-arm-gnueabihf: '-' - rollup>@rollup/rollup-linux-arm-musleabihf: '-' - rollup>@rollup/rollup-linux-arm64-gnu: '-' - rollup>@rollup/rollup-linux-arm64-musl: '-' - rollup>@rollup/rollup-linux-loong64-gnu: '-' - rollup>@rollup/rollup-linux-loong64-musl: '-' - rollup>@rollup/rollup-linux-ppc64-gnu: '-' - rollup>@rollup/rollup-linux-ppc64-musl: '-' - rollup>@rollup/rollup-linux-riscv64-gnu: '-' - rollup>@rollup/rollup-linux-riscv64-musl: '-' - rollup>@rollup/rollup-linux-s390x-gnu: '-' - rollup>@rollup/rollup-linux-x64-musl: '-' - rollup>@rollup/rollup-openbsd-x64: '-' - rollup>@rollup/rollup-openharmony-arm64: '-' - rollup>@rollup/rollup-win32-arm64-msvc: '-' - rollup>@rollup/rollup-win32-ia32-msvc: '-' - rollup>@rollup/rollup-win32-x64-gnu: '-' - rollup>@rollup/rollup-win32-x64-msvc: '-' - '@expo/ngrok-bin>@expo/ngrok-bin-darwin-arm64': '-' - '@expo/ngrok-bin>@expo/ngrok-bin-darwin-x64': '-' - '@expo/ngrok-bin>@expo/ngrok-bin-freebsd-ia32': '-' - '@expo/ngrok-bin>@expo/ngrok-bin-freebsd-x64': '-' - '@expo/ngrok-bin>@expo/ngrok-bin-linux-arm64': '-' - '@expo/ngrok-bin>@expo/ngrok-bin-linux-arm': '-' - '@expo/ngrok-bin>@expo/ngrok-bin-linux-ia32': '-' - '@expo/ngrok-bin>@expo/ngrok-bin-sunos-x64': '-' - '@expo/ngrok-bin>@expo/ngrok-bin-win32-ia32': '-' - '@expo/ngrok-bin>@expo/ngrok-bin-win32-x64': '-' - '@esbuild-kit/esm-loader': npm:tsx@^4.21.0 - esbuild: 0.27.3 - importers: .: @@ -411,7 +328,7 @@ importers: specifier: 'catalog:' version: 25.3.5 esbuild: - specifier: 0.27.3 + specifier: ^0.27.3 version: 0.27.3 esbuild-plugin-pino: specifier: ^2.3.3 @@ -606,6 +523,54 @@ importers: specifier: 'catalog:' version: 3.25.76 + artifacts/sunsama-web: + devDependencies: + '@radix-ui/react-popover': + specifier: ^1.1.15 + version: 1.1.15(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@replit/vite-plugin-runtime-error-modal': + specifier: 'catalog:' + version: 0.0.6 + '@tailwindcss/vite': + specifier: 'catalog:' + version: 4.2.1(vite@7.3.1(@types/node@25.3.5)(jiti@2.6.1)(lightningcss@1.31.1)(tsx@4.21.0)(yaml@2.8.2)) + '@types/node': + specifier: 'catalog:' + version: 25.3.5 + '@types/react': + specifier: 'catalog:' + version: 19.2.14 + '@types/react-dom': + specifier: 'catalog:' + version: 19.2.3(@types/react@19.2.14) + '@vitejs/plugin-react': + specifier: 'catalog:' + version: 5.1.4(vite@7.3.1(@types/node@25.3.5)(jiti@2.6.1)(lightningcss@1.31.1)(tsx@4.21.0)(yaml@2.8.2)) + date-fns: + specifier: ^3.6.0 + version: 3.6.0 + lucide-react: + specifier: 'catalog:' + version: 0.545.0(react@19.1.0) + react: + specifier: 'catalog:' + version: 19.1.0 + react-day-picker: + specifier: ^9.11.1 + version: 9.14.0(react@19.1.0) + react-dom: + specifier: 'catalog:' + version: 19.1.0(react@19.1.0) + tailwind-merge: + specifier: 'catalog:' + version: 3.5.0 + tailwindcss: + specifier: 'catalog:' + version: 4.2.1 + vite: + specifier: 'catalog:' + version: 7.3.1(@types/node@25.3.5)(jiti@2.6.1)(lightningcss@1.31.1)(tsx@4.21.0)(yaml@2.8.2) + lib/api-client-react: dependencies: '@tanstack/react-query': @@ -758,12 +723,458 @@ packages: '@drizzle-team/brocli@0.10.2': resolution: {integrity: sha512-z33Il7l5dKjUgGULTqBsQBQwckHh5AbIuxhdsIxDDiZAzBOrZO6q9ogcWC65kU382AfynTfgNumVcNIjuIua6w==} + '@esbuild-kit/core-utils@3.3.2': + resolution: {integrity: sha512-sPRAnw9CdSsRmEtnsl2WXWdyquogVpB3yZ3dgwJfe8zrOzTsV7cJvmwrKVa+0ma5BoiGJ+BoqkMvawbayKUsqQ==} + deprecated: 'Merged into tsx: https://tsx.is' + + '@esbuild-kit/esm-loader@2.6.5': + resolution: {integrity: sha512-FxEMIkJKnodyA1OaCUoEvbYRkoZlLZ4d/eXFu9Fh8CbBBgP5EmZxrfTRyN0qpXZ4vOvqnE5YdRdcrmUUXuU+dA==} + deprecated: 'Merged into tsx: https://tsx.is' + + '@esbuild/aix-ppc64@0.25.12': + resolution: {integrity: sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + + '@esbuild/aix-ppc64@0.27.3': + resolution: {integrity: sha512-9fJMTNFTWZMh5qwrBItuziu834eOCUcEqymSH7pY+zoMVEZg3gcPuBNxH1EvfVYe9h0x/Ptw8KBzv7qxb7l8dg==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + + '@esbuild/android-arm64@0.18.20': + resolution: {integrity: sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm64@0.25.12': + resolution: {integrity: sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm64@0.27.3': + resolution: {integrity: sha512-YdghPYUmj/FX2SYKJ0OZxf+iaKgMsKHVPF1MAq/P8WirnSpCStzKJFjOjzsW0QQ7oIAiccHdcqjbHmJxRb/dmg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm@0.18.20': + resolution: {integrity: sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==} + engines: {node: '>=12'} + cpu: [arm] + os: [android] + + '@esbuild/android-arm@0.25.12': + resolution: {integrity: sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + + '@esbuild/android-arm@0.27.3': + resolution: {integrity: sha512-i5D1hPY7GIQmXlXhs2w8AWHhenb00+GxjxRncS2ZM7YNVGNfaMxgzSGuO8o8SJzRc/oZwU2bcScvVERk03QhzA==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + + '@esbuild/android-x64@0.18.20': + resolution: {integrity: sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] + + '@esbuild/android-x64@0.25.12': + resolution: {integrity: sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + + '@esbuild/android-x64@0.27.3': + resolution: {integrity: sha512-IN/0BNTkHtk8lkOM8JWAYFg4ORxBkZQf9zXiEOfERX/CzxW3Vg1ewAhU7QSWQpVIzTW+b8Xy+lGzdYXV6UZObQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + + '@esbuild/darwin-arm64@0.18.20': + resolution: {integrity: sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-arm64@0.25.12': + resolution: {integrity: sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-arm64@0.27.3': + resolution: {integrity: sha512-Re491k7ByTVRy0t3EKWajdLIr0gz2kKKfzafkth4Q8A5n1xTHrkqZgLLjFEHVD+AXdUGgQMq+Godfq45mGpCKg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-x64@0.18.20': + resolution: {integrity: sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + + '@esbuild/darwin-x64@0.25.12': + resolution: {integrity: sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + + '@esbuild/darwin-x64@0.27.3': + resolution: {integrity: sha512-vHk/hA7/1AckjGzRqi6wbo+jaShzRowYip6rt6q7VYEDX4LEy1pZfDpdxCBnGtl+A5zq8iXDcyuxwtv3hNtHFg==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + + '@esbuild/freebsd-arm64@0.18.20': + resolution: {integrity: sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-arm64@0.25.12': + resolution: {integrity: sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-arm64@0.27.3': + resolution: {integrity: sha512-ipTYM2fjt3kQAYOvo6vcxJx3nBYAzPjgTCk7QEgZG8AUO3ydUhvelmhrbOheMnGOlaSFUoHXB6un+A7q4ygY9w==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.18.20': + resolution: {integrity: sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.25.12': + resolution: {integrity: sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.27.3': + resolution: {integrity: sha512-dDk0X87T7mI6U3K9VjWtHOXqwAMJBNN2r7bejDsc+j03SEjtD9HrOl8gVFByeM0aJksoUuUVU9TBaZa2rgj0oA==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + + '@esbuild/linux-arm64@0.18.20': + resolution: {integrity: sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm64@0.25.12': + resolution: {integrity: sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm64@0.27.3': + resolution: {integrity: sha512-sZOuFz/xWnZ4KH3YfFrKCf1WyPZHakVzTiqji3WDc0BCl2kBwiJLCXpzLzUBLgmp4veFZdvN5ChW4Eq/8Fc2Fg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm@0.18.20': + resolution: {integrity: sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-arm@0.25.12': + resolution: {integrity: sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-arm@0.27.3': + resolution: {integrity: sha512-s6nPv2QkSupJwLYyfS+gwdirm0ukyTFNl3KTgZEAiJDd+iHZcbTPPcWCcRYH+WlNbwChgH2QkE9NSlNrMT8Gfw==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-ia32@0.18.20': + resolution: {integrity: sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-ia32@0.25.12': + resolution: {integrity: sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-ia32@0.27.3': + resolution: {integrity: sha512-yGlQYjdxtLdh0a3jHjuwOrxQjOZYD/C9PfdbgJJF3TIZWnm/tMd/RcNiLngiu4iwcBAOezdnSLAwQDPqTmtTYg==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-loong64@0.18.20': + resolution: {integrity: sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==} + engines: {node: '>=12'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-loong64@0.25.12': + resolution: {integrity: sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-loong64@0.27.3': + resolution: {integrity: sha512-WO60Sn8ly3gtzhyjATDgieJNet/KqsDlX5nRC5Y3oTFcS1l0KWba+SEa9Ja1GfDqSF1z6hif/SkpQJbL63cgOA==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-mips64el@0.18.20': + resolution: {integrity: sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-mips64el@0.25.12': + resolution: {integrity: sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-mips64el@0.27.3': + resolution: {integrity: sha512-APsymYA6sGcZ4pD6k+UxbDjOFSvPWyZhjaiPyl/f79xKxwTnrn5QUnXR5prvetuaSMsb4jgeHewIDCIWljrSxw==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-ppc64@0.18.20': + resolution: {integrity: sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-ppc64@0.25.12': + resolution: {integrity: sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-ppc64@0.27.3': + resolution: {integrity: sha512-eizBnTeBefojtDb9nSh4vvVQ3V9Qf9Df01PfawPcRzJH4gFSgrObw+LveUyDoKU3kxi5+9RJTCWlj4FjYXVPEA==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-riscv64@0.18.20': + resolution: {integrity: sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==} + engines: {node: '>=12'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-riscv64@0.25.12': + resolution: {integrity: sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-riscv64@0.27.3': + resolution: {integrity: sha512-3Emwh0r5wmfm3ssTWRQSyVhbOHvqegUDRd0WhmXKX2mkHJe1SFCMJhagUleMq+Uci34wLSipf8Lagt4LlpRFWQ==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-s390x@0.18.20': + resolution: {integrity: sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==} + engines: {node: '>=12'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-s390x@0.25.12': + resolution: {integrity: sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-s390x@0.27.3': + resolution: {integrity: sha512-pBHUx9LzXWBc7MFIEEL0yD/ZVtNgLytvx60gES28GcWMqil8ElCYR4kvbV2BDqsHOvVDRrOxGySBM9Fcv744hw==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-x64@0.18.20': + resolution: {integrity: sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==} + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + + '@esbuild/linux-x64@0.25.12': + resolution: {integrity: sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + '@esbuild/linux-x64@0.27.3': resolution: {integrity: sha512-Czi8yzXUWIQYAtL/2y6vogER8pvcsOsk5cpwL4Gk5nJqH5UZiVByIY8Eorm5R13gq+DQKYg0+JyQoytLQas4dA==} engines: {node: '>=18'} cpu: [x64] os: [linux] + '@esbuild/netbsd-arm64@0.25.12': + resolution: {integrity: sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [netbsd] + + '@esbuild/netbsd-arm64@0.27.3': + resolution: {integrity: sha512-sDpk0RgmTCR/5HguIZa9n9u+HVKf40fbEUt+iTzSnCaGvY9kFP0YKBWZtJaraonFnqef5SlJ8/TiPAxzyS+UoA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [netbsd] + + '@esbuild/netbsd-x64@0.18.20': + resolution: {integrity: sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + + '@esbuild/netbsd-x64@0.25.12': + resolution: {integrity: sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + + '@esbuild/netbsd-x64@0.27.3': + resolution: {integrity: sha512-P14lFKJl/DdaE00LItAukUdZO5iqNH7+PjoBm+fLQjtxfcfFE20Xf5CrLsmZdq5LFFZzb5JMZ9grUwvtVYzjiA==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + + '@esbuild/openbsd-arm64@0.25.12': + resolution: {integrity: sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + + '@esbuild/openbsd-arm64@0.27.3': + resolution: {integrity: sha512-AIcMP77AvirGbRl/UZFTq5hjXK+2wC7qFRGoHSDrZ5v5b8DK/GYpXW3CPRL53NkvDqb9D+alBiC/dV0Fb7eJcw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + + '@esbuild/openbsd-x64@0.18.20': + resolution: {integrity: sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + + '@esbuild/openbsd-x64@0.25.12': + resolution: {integrity: sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + + '@esbuild/openbsd-x64@0.27.3': + resolution: {integrity: sha512-DnW2sRrBzA+YnE70LKqnM3P+z8vehfJWHXECbwBmH/CU51z6FiqTQTHFenPlHmo3a8UgpLyH3PT+87OViOh1AQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + + '@esbuild/openharmony-arm64@0.25.12': + resolution: {integrity: sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openharmony] + + '@esbuild/openharmony-arm64@0.27.3': + resolution: {integrity: sha512-NinAEgr/etERPTsZJ7aEZQvvg/A6IsZG/LgZy+81wON2huV7SrK3e63dU0XhyZP4RKGyTm7aOgmQk0bGp0fy2g==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openharmony] + + '@esbuild/sunos-x64@0.18.20': + resolution: {integrity: sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + + '@esbuild/sunos-x64@0.25.12': + resolution: {integrity: sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + + '@esbuild/sunos-x64@0.27.3': + resolution: {integrity: sha512-PanZ+nEz+eWoBJ8/f8HKxTTD172SKwdXebZ0ndd953gt1HRBbhMsaNqjTyYLGLPdoWHy4zLU7bDVJztF5f3BHA==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + + '@esbuild/win32-arm64@0.18.20': + resolution: {integrity: sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-arm64@0.25.12': + resolution: {integrity: sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-arm64@0.27.3': + resolution: {integrity: sha512-B2t59lWWYrbRDw/tjiWOuzSsFh1Y/E95ofKz7rIVYSQkUYBjfSgf6oeYPNWHToFRr2zx52JKApIcAS/D5TUBnA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-ia32@0.18.20': + resolution: {integrity: sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==} + engines: {node: '>=12'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-ia32@0.25.12': + resolution: {integrity: sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-ia32@0.27.3': + resolution: {integrity: sha512-QLKSFeXNS8+tHW7tZpMtjlNb7HKau0QDpwm49u0vUp9y1WOF+PEzkU84y9GqYaAVW8aH8f3GcBck26jh54cX4Q==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-x64@0.18.20': + resolution: {integrity: sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] + + '@esbuild/win32-x64@0.25.12': + resolution: {integrity: sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + + '@esbuild/win32-x64@0.27.3': + resolution: {integrity: sha512-4uJGhsxuptu3OcpVAzli+/gWusVGwZZHTlS63hh++ehExkVT8SgiEf7/uC/PclrPPkLhZqGgCTjd0VWLo6xMqA==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + '@floating-ui/core@1.7.5': resolution: {integrity: sha512-1Ih4WTWyw0+lKyFMcBHGbb5U5FtuHJuujoyyr5zTaWS5EYMeT6Jb2AuDeftsCsEuchO+mM2ij5+q9crhydzLhQ==} @@ -1524,11 +1935,130 @@ packages: '@rolldown/pluginutils@1.0.0-rc.3': resolution: {integrity: sha512-eybk3TjzzzV97Dlj5c+XrBFW57eTNhzod66y9HrBlzJ6NsCrWCp/2kaPS3K9wJmurBC0Tdw4yPjXKZqlznim3Q==} + '@rollup/rollup-android-arm-eabi@4.59.0': + resolution: {integrity: sha512-upnNBkA6ZH2VKGcBj9Fyl9IGNPULcjXRlg0LLeaioQWueH30p6IXtJEbKAgvyv+mJaMxSm1l6xwDXYjpEMiLMg==} + cpu: [arm] + os: [android] + + '@rollup/rollup-android-arm64@4.59.0': + resolution: {integrity: sha512-hZ+Zxj3SySm4A/DylsDKZAeVg0mvi++0PYVceVyX7hemkw7OreKdCvW2oQ3T1FMZvCaQXqOTHb8qmBShoqk69Q==} + cpu: [arm64] + os: [android] + + '@rollup/rollup-darwin-arm64@4.59.0': + resolution: {integrity: sha512-W2Psnbh1J8ZJw0xKAd8zdNgF9HRLkdWwwdWqubSVk0pUuQkoHnv7rx4GiF9rT4t5DIZGAsConRE3AxCdJ4m8rg==} + cpu: [arm64] + os: [darwin] + + '@rollup/rollup-darwin-x64@4.59.0': + resolution: {integrity: sha512-ZW2KkwlS4lwTv7ZVsYDiARfFCnSGhzYPdiOU4IM2fDbL+QGlyAbjgSFuqNRbSthybLbIJ915UtZBtmuLrQAT/w==} + cpu: [x64] + os: [darwin] + + '@rollup/rollup-freebsd-arm64@4.59.0': + resolution: {integrity: sha512-EsKaJ5ytAu9jI3lonzn3BgG8iRBjV4LxZexygcQbpiU0wU0ATxhNVEpXKfUa0pS05gTcSDMKpn3Sx+QB9RlTTA==} + cpu: [arm64] + os: [freebsd] + + '@rollup/rollup-freebsd-x64@4.59.0': + resolution: {integrity: sha512-d3DuZi2KzTMjImrxoHIAODUZYoUUMsuUiY4SRRcJy6NJoZ6iIqWnJu9IScV9jXysyGMVuW+KNzZvBLOcpdl3Vg==} + cpu: [x64] + os: [freebsd] + + '@rollup/rollup-linux-arm-gnueabihf@4.59.0': + resolution: {integrity: sha512-t4ONHboXi/3E0rT6OZl1pKbl2Vgxf9vJfWgmUoCEVQVxhW6Cw/c8I6hbbu7DAvgp82RKiH7TpLwxnJeKv2pbsw==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm-musleabihf@4.59.0': + resolution: {integrity: sha512-CikFT7aYPA2ufMD086cVORBYGHffBo4K8MQ4uPS/ZnY54GKj36i196u8U+aDVT2LX4eSMbyHtyOh7D7Zvk2VvA==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm64-gnu@4.59.0': + resolution: {integrity: sha512-jYgUGk5aLd1nUb1CtQ8E+t5JhLc9x5WdBKew9ZgAXg7DBk0ZHErLHdXM24rfX+bKrFe+Xp5YuJo54I5HFjGDAA==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-arm64-musl@4.59.0': + resolution: {integrity: sha512-peZRVEdnFWZ5Bh2KeumKG9ty7aCXzzEsHShOZEFiCQlDEepP1dpUl/SrUNXNg13UmZl+gzVDPsiCwnV1uI0RUA==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-loong64-gnu@4.59.0': + resolution: {integrity: sha512-gbUSW/97f7+r4gHy3Jlup8zDG190AuodsWnNiXErp9mT90iCy9NKKU0Xwx5k8VlRAIV2uU9CsMnEFg/xXaOfXg==} + cpu: [loong64] + os: [linux] + + '@rollup/rollup-linux-loong64-musl@4.59.0': + resolution: {integrity: sha512-yTRONe79E+o0FWFijasoTjtzG9EBedFXJMl888NBEDCDV9I2wGbFFfJQQe63OijbFCUZqxpHz1GzpbtSFikJ4Q==} + cpu: [loong64] + os: [linux] + + '@rollup/rollup-linux-ppc64-gnu@4.59.0': + resolution: {integrity: sha512-sw1o3tfyk12k3OEpRddF68a1unZ5VCN7zoTNtSn2KndUE+ea3m3ROOKRCZxEpmT9nsGnogpFP9x6mnLTCaoLkA==} + cpu: [ppc64] + os: [linux] + + '@rollup/rollup-linux-ppc64-musl@4.59.0': + resolution: {integrity: sha512-+2kLtQ4xT3AiIxkzFVFXfsmlZiG5FXYW7ZyIIvGA7Bdeuh9Z0aN4hVyXS/G1E9bTP/vqszNIN/pUKCk/BTHsKA==} + cpu: [ppc64] + os: [linux] + + '@rollup/rollup-linux-riscv64-gnu@4.59.0': + resolution: {integrity: sha512-NDYMpsXYJJaj+I7UdwIuHHNxXZ/b/N2hR15NyH3m2qAtb/hHPA4g4SuuvrdxetTdndfj9b1WOmy73kcPRoERUg==} + cpu: [riscv64] + os: [linux] + + '@rollup/rollup-linux-riscv64-musl@4.59.0': + resolution: {integrity: sha512-nLckB8WOqHIf1bhymk+oHxvM9D3tyPndZH8i8+35p/1YiVoVswPid2yLzgX7ZJP0KQvnkhM4H6QZ5m0LzbyIAg==} + cpu: [riscv64] + os: [linux] + + '@rollup/rollup-linux-s390x-gnu@4.59.0': + resolution: {integrity: sha512-oF87Ie3uAIvORFBpwnCvUzdeYUqi2wY6jRFWJAy1qus/udHFYIkplYRW+wo+GRUP4sKzYdmE1Y3+rY5Gc4ZO+w==} + cpu: [s390x] + os: [linux] + '@rollup/rollup-linux-x64-gnu@4.59.0': resolution: {integrity: sha512-3AHmtQq/ppNuUspKAlvA8HtLybkDflkMuLK4DPo77DfthRb71V84/c4MlWJXixZz4uruIH4uaa07IqoAkG64fg==} cpu: [x64] os: [linux] - libc: [glibc] + + '@rollup/rollup-linux-x64-musl@4.59.0': + resolution: {integrity: sha512-2UdiwS/9cTAx7qIUZB/fWtToJwvt0Vbo0zmnYt7ED35KPg13Q0ym1g442THLC7VyI6JfYTP4PiSOWyoMdV2/xg==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-openbsd-x64@4.59.0': + resolution: {integrity: sha512-M3bLRAVk6GOwFlPTIxVBSYKUaqfLrn8l0psKinkCFxl4lQvOSz8ZrKDz2gxcBwHFpci0B6rttydI4IpS4IS/jQ==} + cpu: [x64] + os: [openbsd] + + '@rollup/rollup-openharmony-arm64@4.59.0': + resolution: {integrity: sha512-tt9KBJqaqp5i5HUZzoafHZX8b5Q2Fe7UjYERADll83O4fGqJ49O1FsL6LpdzVFQcpwvnyd0i+K/VSwu/o/nWlA==} + cpu: [arm64] + os: [openharmony] + + '@rollup/rollup-win32-arm64-msvc@4.59.0': + resolution: {integrity: sha512-V5B6mG7OrGTwnxaNUzZTDTjDS7F75PO1ae6MJYdiMu60sq0CqN5CVeVsbhPxalupvTX8gXVSU9gq+Rx1/hvu6A==} + cpu: [arm64] + os: [win32] + + '@rollup/rollup-win32-ia32-msvc@4.59.0': + resolution: {integrity: sha512-UKFMHPuM9R0iBegwzKF4y0C4J9u8C6MEJgFuXTBerMk7EJ92GFVFYBfOZaSGLu6COf7FxpQNqhNS4c4icUPqxA==} + cpu: [ia32] + os: [win32] + + '@rollup/rollup-win32-x64-gnu@4.59.0': + resolution: {integrity: sha512-laBkYlSS1n2L8fSo1thDNGrCTQMmxjYY5G0WFWjFFYZkKPjsMBsgJfGf4TLxXrF6RyhI60L8TMOjBMvXiTcxeA==} + cpu: [x64] + os: [win32] + + '@rollup/rollup-win32-x64-msvc@4.59.0': + resolution: {integrity: sha512-2HRCml6OztYXyJXAvdDXPKcawukWY2GpR5/nxKp4iBgiO3wcoEGkAaqctIbZcNB6KlUQBIqt8VYkNSj2397EfA==} + cpu: [x64] + os: [win32] '@scalar/helpers@0.2.18': resolution: {integrity: sha512-w1d4tpNEVZ293oB2BAgLrS0kVPUtG3eByNmOCJA5eK9vcT4D3cmsGtWjUaaqit0BQCsBFHK51rasGvSWnApYTw==} @@ -1583,12 +2113,59 @@ packages: '@tailwindcss/node@4.2.1': resolution: {integrity: sha512-jlx6sLk4EOwO6hHe1oCGm1Q4AN/s0rSrTTPBGPM0/RQ6Uylwq17FuU8IeJJKEjtc6K6O07zsvP+gDO6MMWo7pg==} + '@tailwindcss/oxide-android-arm64@4.2.1': + resolution: {integrity: sha512-eZ7G1Zm5EC8OOKaesIKuw77jw++QJ2lL9N+dDpdQiAB/c/B2wDh0QPFHbkBVrXnwNugvrbJFk1gK2SsVjwWReg==} + engines: {node: '>= 20'} + cpu: [arm64] + os: [android] + + '@tailwindcss/oxide-darwin-arm64@4.2.1': + resolution: {integrity: sha512-q/LHkOstoJ7pI1J0q6djesLzRvQSIfEto148ppAd+BVQK0JYjQIFSK3JgYZJa+Yzi0DDa52ZsQx2rqytBnf8Hw==} + engines: {node: '>= 20'} + cpu: [arm64] + os: [darwin] + + '@tailwindcss/oxide-darwin-x64@4.2.1': + resolution: {integrity: sha512-/f/ozlaXGY6QLbpvd/kFTro2l18f7dHKpB+ieXz+Cijl4Mt9AI2rTrpq7V+t04nK+j9XBQHnSMdeQRhbGyt6fw==} + engines: {node: '>= 20'} + cpu: [x64] + os: [darwin] + + '@tailwindcss/oxide-freebsd-x64@4.2.1': + resolution: {integrity: sha512-5e/AkgYJT/cpbkys/OU2Ei2jdETCLlifwm7ogMC7/hksI2fC3iiq6OcXwjibcIjPung0kRtR3TxEITkqgn0TcA==} + engines: {node: '>= 20'} + cpu: [x64] + os: [freebsd] + + '@tailwindcss/oxide-linux-arm-gnueabihf@4.2.1': + resolution: {integrity: sha512-Uny1EcVTTmerCKt/1ZuKTkb0x8ZaiuYucg2/kImO5A5Y/kBz41/+j0gxUZl+hTF3xkWpDmHX+TaWhOtba2Fyuw==} + engines: {node: '>= 20'} + cpu: [arm] + os: [linux] + + '@tailwindcss/oxide-linux-arm64-gnu@4.2.1': + resolution: {integrity: sha512-CTrwomI+c7n6aSSQlsPL0roRiNMDQ/YzMD9EjcR+H4f0I1SQ8QqIuPnsVp7QgMkC1Qi8rtkekLkOFjo7OlEFRQ==} + engines: {node: '>= 20'} + cpu: [arm64] + os: [linux] + + '@tailwindcss/oxide-linux-arm64-musl@4.2.1': + resolution: {integrity: sha512-WZA0CHRL/SP1TRbA5mp9htsppSEkWuQ4KsSUumYQnyl8ZdT39ntwqmz4IUHGN6p4XdSlYfJwM4rRzZLShHsGAQ==} + engines: {node: '>= 20'} + cpu: [arm64] + os: [linux] + '@tailwindcss/oxide-linux-x64-gnu@4.2.1': resolution: {integrity: sha512-qMFzxI2YlBOLW5PhblzuSWlWfwLHaneBE0xHzLrBgNtqN6mWfs+qYbhryGSXQjFYB1Dzf5w+LN5qbUTPhW7Y5g==} engines: {node: '>= 20'} cpu: [x64] os: [linux] - libc: [glibc] + + '@tailwindcss/oxide-linux-x64-musl@4.2.1': + resolution: {integrity: sha512-5r1X2FKnCMUPlXTWRYpHdPYUY6a1Ar/t7P24OuiEdEOmms5lyqjDRvVY1yy9Rmioh+AunQ0rWiOTPE8F9A3v5g==} + engines: {node: '>= 20'} + cpu: [x64] + os: [linux] '@tailwindcss/oxide-wasm32-wasi@4.2.1': resolution: {integrity: sha512-MGFB5cVPvshR85MTJkEvqDUnuNoysrsRxd6vnk1Lf2tbiqNlXpHYZqkqOQalydienEWOHHFyyuTSYRsLfxFJ2Q==} @@ -1602,6 +2179,18 @@ packages: - '@emnapi/wasi-threads' - tslib + '@tailwindcss/oxide-win32-arm64-msvc@4.2.1': + resolution: {integrity: sha512-YlUEHRHBGnCMh4Nj4GnqQyBtsshUPdiNroZj8VPkvTZSoHsilRCwXcVKnG9kyi0ZFAS/3u+qKHBdDc81SADTRA==} + engines: {node: '>= 20'} + cpu: [arm64] + os: [win32] + + '@tailwindcss/oxide-win32-x64-msvc@4.2.1': + resolution: {integrity: sha512-rbO34G5sMWWyrN/idLeVxAZgAKWrn5LiR3/I90Q9MkA67s6T1oB0xtTe+0heoBvHSpbU9Mk7i6uwJnpo4u21XQ==} + engines: {node: '>= 20'} + cpu: [x64] + os: [win32] + '@tailwindcss/oxide@4.2.1': resolution: {integrity: sha512-yv9jeEFWnjKCI6/T3Oq50yQEOqmpmpfzG1hcZsAOaXFQPfzWprWrlHSdGPEF3WQTi8zu8ohC9Mh9J470nT5pUw==} engines: {node: '>= 20'} @@ -1803,6 +2392,9 @@ packages: engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true + buffer-from@1.1.2: + resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} + bytes@3.1.2: resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} engines: {node: '>= 0.8'} @@ -2143,7 +2735,7 @@ packages: esbuild-plugin-pino@2.3.3: resolution: {integrity: sha512-5RIsILwgqy8wIV5pVg2gb13gJlH3EKKg613Js8q25p3tFsKA8ftsgWQFdgGbIkUe77Ttjl8lctuGkchRAvXGfw==} peerDependencies: - esbuild: 0.27.3 + esbuild: '>=0.25.0 <=0.25.8' pino: '>=7.0.0' pino-pretty: '*' thread-stream: '*' @@ -2156,7 +2748,17 @@ packages: esbuild-register@3.6.0: resolution: {integrity: sha512-H2/S7Pm8a9CL1uhp9OvjwrBh5Pvx0H8qVOxNu8Wed9Y7qv56MPtq+GGM8RJpq6glYJn9Wspr8uw7l55uyinNeg==} peerDependencies: - esbuild: 0.27.3 + esbuild: '>=0.12 <1' + + esbuild@0.18.20: + resolution: {integrity: sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==} + engines: {node: '>=12'} + hasBin: true + + esbuild@0.25.12: + resolution: {integrity: sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==} + engines: {node: '>=18'} + hasBin: true esbuild@0.27.3: resolution: {integrity: sha512-8VwMnyGCONIs6cWue2IdpHxHnAjzxnw2Zr7MkVxB2vjmQ2ivqGFb4LEG3SMnv0Gb2F/G/2yA8zUaiL1gywDCCg==} @@ -2434,12 +3036,71 @@ packages: resolution: {integrity: sha512-KZ9W9nWDT7rF7Dazg8xyLHGLrmpgq2nVNFUckhqdW3szVP6YhCpp/RAnpmVExA9JvrMynjwSLVrEj3AepHR6ew==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + lightningcss-android-arm64@1.31.1: + resolution: {integrity: sha512-HXJF3x8w9nQ4jbXRiNppBCqeZPIAfUo8zE/kOEGbW5NZvGc/K7nMxbhIr+YlFlHW5mpbg/YFPdbnCh1wAXCKFg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [android] + + lightningcss-darwin-arm64@1.31.1: + resolution: {integrity: sha512-02uTEqf3vIfNMq3h/z2cJfcOXnQ0GRwQrkmPafhueLb2h7mqEidiCzkE4gBMEH65abHRiQvhdcQ+aP0D0g67sg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [darwin] + + lightningcss-darwin-x64@1.31.1: + resolution: {integrity: sha512-1ObhyoCY+tGxtsz1lSx5NXCj3nirk0Y0kB/g8B8DT+sSx4G9djitg9ejFnjb3gJNWo7qXH4DIy2SUHvpoFwfTA==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [darwin] + + lightningcss-freebsd-x64@1.31.1: + resolution: {integrity: sha512-1RINmQKAItO6ISxYgPwszQE1BrsVU5aB45ho6O42mu96UiZBxEXsuQ7cJW4zs4CEodPUioj/QrXW1r9pLUM74A==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [freebsd] + + lightningcss-linux-arm-gnueabihf@1.31.1: + resolution: {integrity: sha512-OOCm2//MZJ87CdDK62rZIu+aw9gBv4azMJuA8/KB74wmfS3lnC4yoPHm0uXZ/dvNNHmnZnB8XLAZzObeG0nS1g==} + engines: {node: '>= 12.0.0'} + cpu: [arm] + os: [linux] + + lightningcss-linux-arm64-gnu@1.31.1: + resolution: {integrity: sha512-WKyLWztD71rTnou4xAD5kQT+982wvca7E6QoLpoawZ1gP9JM0GJj4Tp5jMUh9B3AitHbRZ2/H3W5xQmdEOUlLg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + + lightningcss-linux-arm64-musl@1.31.1: + resolution: {integrity: sha512-mVZ7Pg2zIbe3XlNbZJdjs86YViQFoJSpc41CbVmKBPiGmC4YrfeOyz65ms2qpAobVd7WQsbW4PdsSJEMymyIMg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + lightningcss-linux-x64-gnu@1.31.1: resolution: {integrity: sha512-xGlFWRMl+0KvUhgySdIaReQdB4FNudfUTARn7q0hh/V67PVGCs3ADFjw+6++kG1RNd0zdGRlEKa+T13/tQjPMA==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [linux] - libc: [glibc] + + lightningcss-linux-x64-musl@1.31.1: + resolution: {integrity: sha512-eowF8PrKHw9LpoZii5tdZwnBcYDxRw2rRCyvAXLi34iyeYfqCQNA9rmUM0ce62NlPhCvof1+9ivRaTY6pSKDaA==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + + lightningcss-win32-arm64-msvc@1.31.1: + resolution: {integrity: sha512-aJReEbSEQzx1uBlQizAOBSjcmr9dCdL3XuC/6HLXAxmtErsj2ICo5yYggg1qOODQMtnjNQv2UHb9NpOuFtYe4w==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [win32] + + lightningcss-win32-x64-msvc@1.31.1: + resolution: {integrity: sha512-I9aiFrbd7oYHwlnQDqr1Roz+fTz61oDDJX7n9tYF9FJymH1cIN1DtKw3iYt6b8WZgEjoNwVSncwF4wx/ZedMhw==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [win32] lightningcss@1.31.1: resolution: {integrity: sha512-l51N2r93WmGUye3WuFoN5k10zyvrVs0qfKBhyC5ogUQ6Ew6JUSswh78mbSO+IU3nTWsyOArqPCcShdQSadghBQ==} @@ -2975,6 +3636,13 @@ packages: resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} engines: {node: '>=0.10.0'} + source-map-support@0.5.21: + resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} + + source-map@0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + split2@4.2.0: resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==} engines: {node: '>= 10.x'} @@ -3357,9 +4025,238 @@ snapshots: '@drizzle-team/brocli@0.10.2': {} + '@esbuild-kit/core-utils@3.3.2': + dependencies: + esbuild: 0.18.20 + source-map-support: 0.5.21 + + '@esbuild-kit/esm-loader@2.6.5': + dependencies: + '@esbuild-kit/core-utils': 3.3.2 + get-tsconfig: 4.13.6 + + '@esbuild/aix-ppc64@0.25.12': + optional: true + + '@esbuild/aix-ppc64@0.27.3': + optional: true + + '@esbuild/android-arm64@0.18.20': + optional: true + + '@esbuild/android-arm64@0.25.12': + optional: true + + '@esbuild/android-arm64@0.27.3': + optional: true + + '@esbuild/android-arm@0.18.20': + optional: true + + '@esbuild/android-arm@0.25.12': + optional: true + + '@esbuild/android-arm@0.27.3': + optional: true + + '@esbuild/android-x64@0.18.20': + optional: true + + '@esbuild/android-x64@0.25.12': + optional: true + + '@esbuild/android-x64@0.27.3': + optional: true + + '@esbuild/darwin-arm64@0.18.20': + optional: true + + '@esbuild/darwin-arm64@0.25.12': + optional: true + + '@esbuild/darwin-arm64@0.27.3': + optional: true + + '@esbuild/darwin-x64@0.18.20': + optional: true + + '@esbuild/darwin-x64@0.25.12': + optional: true + + '@esbuild/darwin-x64@0.27.3': + optional: true + + '@esbuild/freebsd-arm64@0.18.20': + optional: true + + '@esbuild/freebsd-arm64@0.25.12': + optional: true + + '@esbuild/freebsd-arm64@0.27.3': + optional: true + + '@esbuild/freebsd-x64@0.18.20': + optional: true + + '@esbuild/freebsd-x64@0.25.12': + optional: true + + '@esbuild/freebsd-x64@0.27.3': + optional: true + + '@esbuild/linux-arm64@0.18.20': + optional: true + + '@esbuild/linux-arm64@0.25.12': + optional: true + + '@esbuild/linux-arm64@0.27.3': + optional: true + + '@esbuild/linux-arm@0.18.20': + optional: true + + '@esbuild/linux-arm@0.25.12': + optional: true + + '@esbuild/linux-arm@0.27.3': + optional: true + + '@esbuild/linux-ia32@0.18.20': + optional: true + + '@esbuild/linux-ia32@0.25.12': + optional: true + + '@esbuild/linux-ia32@0.27.3': + optional: true + + '@esbuild/linux-loong64@0.18.20': + optional: true + + '@esbuild/linux-loong64@0.25.12': + optional: true + + '@esbuild/linux-loong64@0.27.3': + optional: true + + '@esbuild/linux-mips64el@0.18.20': + optional: true + + '@esbuild/linux-mips64el@0.25.12': + optional: true + + '@esbuild/linux-mips64el@0.27.3': + optional: true + + '@esbuild/linux-ppc64@0.18.20': + optional: true + + '@esbuild/linux-ppc64@0.25.12': + optional: true + + '@esbuild/linux-ppc64@0.27.3': + optional: true + + '@esbuild/linux-riscv64@0.18.20': + optional: true + + '@esbuild/linux-riscv64@0.25.12': + optional: true + + '@esbuild/linux-riscv64@0.27.3': + optional: true + + '@esbuild/linux-s390x@0.18.20': + optional: true + + '@esbuild/linux-s390x@0.25.12': + optional: true + + '@esbuild/linux-s390x@0.27.3': + optional: true + + '@esbuild/linux-x64@0.18.20': + optional: true + + '@esbuild/linux-x64@0.25.12': + optional: true + '@esbuild/linux-x64@0.27.3': optional: true + '@esbuild/netbsd-arm64@0.25.12': + optional: true + + '@esbuild/netbsd-arm64@0.27.3': + optional: true + + '@esbuild/netbsd-x64@0.18.20': + optional: true + + '@esbuild/netbsd-x64@0.25.12': + optional: true + + '@esbuild/netbsd-x64@0.27.3': + optional: true + + '@esbuild/openbsd-arm64@0.25.12': + optional: true + + '@esbuild/openbsd-arm64@0.27.3': + optional: true + + '@esbuild/openbsd-x64@0.18.20': + optional: true + + '@esbuild/openbsd-x64@0.25.12': + optional: true + + '@esbuild/openbsd-x64@0.27.3': + optional: true + + '@esbuild/openharmony-arm64@0.25.12': + optional: true + + '@esbuild/openharmony-arm64@0.27.3': + optional: true + + '@esbuild/sunos-x64@0.18.20': + optional: true + + '@esbuild/sunos-x64@0.25.12': + optional: true + + '@esbuild/sunos-x64@0.27.3': + optional: true + + '@esbuild/win32-arm64@0.18.20': + optional: true + + '@esbuild/win32-arm64@0.25.12': + optional: true + + '@esbuild/win32-arm64@0.27.3': + optional: true + + '@esbuild/win32-ia32@0.18.20': + optional: true + + '@esbuild/win32-ia32@0.25.12': + optional: true + + '@esbuild/win32-ia32@0.27.3': + optional: true + + '@esbuild/win32-x64@0.18.20': + optional: true + + '@esbuild/win32-x64@0.25.12': + optional: true + + '@esbuild/win32-x64@0.27.3': + optional: true + '@floating-ui/core@1.7.5': dependencies: '@floating-ui/utils': 0.2.11 @@ -4243,9 +5140,81 @@ snapshots: '@rolldown/pluginutils@1.0.0-rc.3': {} + '@rollup/rollup-android-arm-eabi@4.59.0': + optional: true + + '@rollup/rollup-android-arm64@4.59.0': + optional: true + + '@rollup/rollup-darwin-arm64@4.59.0': + optional: true + + '@rollup/rollup-darwin-x64@4.59.0': + optional: true + + '@rollup/rollup-freebsd-arm64@4.59.0': + optional: true + + '@rollup/rollup-freebsd-x64@4.59.0': + optional: true + + '@rollup/rollup-linux-arm-gnueabihf@4.59.0': + optional: true + + '@rollup/rollup-linux-arm-musleabihf@4.59.0': + optional: true + + '@rollup/rollup-linux-arm64-gnu@4.59.0': + optional: true + + '@rollup/rollup-linux-arm64-musl@4.59.0': + optional: true + + '@rollup/rollup-linux-loong64-gnu@4.59.0': + optional: true + + '@rollup/rollup-linux-loong64-musl@4.59.0': + optional: true + + '@rollup/rollup-linux-ppc64-gnu@4.59.0': + optional: true + + '@rollup/rollup-linux-ppc64-musl@4.59.0': + optional: true + + '@rollup/rollup-linux-riscv64-gnu@4.59.0': + optional: true + + '@rollup/rollup-linux-riscv64-musl@4.59.0': + optional: true + + '@rollup/rollup-linux-s390x-gnu@4.59.0': + optional: true + '@rollup/rollup-linux-x64-gnu@4.59.0': optional: true + '@rollup/rollup-linux-x64-musl@4.59.0': + optional: true + + '@rollup/rollup-openbsd-x64@4.59.0': + optional: true + + '@rollup/rollup-openharmony-arm64@4.59.0': + optional: true + + '@rollup/rollup-win32-arm64-msvc@4.59.0': + optional: true + + '@rollup/rollup-win32-ia32-msvc@4.59.0': + optional: true + + '@rollup/rollup-win32-x64-gnu@4.59.0': + optional: true + + '@rollup/rollup-win32-x64-msvc@4.59.0': + optional: true + '@scalar/helpers@0.2.18': {} '@scalar/json-magic@0.11.7': @@ -4315,16 +5284,56 @@ snapshots: source-map-js: 1.2.1 tailwindcss: 4.2.1 + '@tailwindcss/oxide-android-arm64@4.2.1': + optional: true + + '@tailwindcss/oxide-darwin-arm64@4.2.1': + optional: true + + '@tailwindcss/oxide-darwin-x64@4.2.1': + optional: true + + '@tailwindcss/oxide-freebsd-x64@4.2.1': + optional: true + + '@tailwindcss/oxide-linux-arm-gnueabihf@4.2.1': + optional: true + + '@tailwindcss/oxide-linux-arm64-gnu@4.2.1': + optional: true + + '@tailwindcss/oxide-linux-arm64-musl@4.2.1': + optional: true + '@tailwindcss/oxide-linux-x64-gnu@4.2.1': optional: true + '@tailwindcss/oxide-linux-x64-musl@4.2.1': + optional: true + '@tailwindcss/oxide-wasm32-wasi@4.2.1': optional: true + '@tailwindcss/oxide-win32-arm64-msvc@4.2.1': + optional: true + + '@tailwindcss/oxide-win32-x64-msvc@4.2.1': + optional: true + '@tailwindcss/oxide@4.2.1': optionalDependencies: + '@tailwindcss/oxide-android-arm64': 4.2.1 + '@tailwindcss/oxide-darwin-arm64': 4.2.1 + '@tailwindcss/oxide-darwin-x64': 4.2.1 + '@tailwindcss/oxide-freebsd-x64': 4.2.1 + '@tailwindcss/oxide-linux-arm-gnueabihf': 4.2.1 + '@tailwindcss/oxide-linux-arm64-gnu': 4.2.1 + '@tailwindcss/oxide-linux-arm64-musl': 4.2.1 '@tailwindcss/oxide-linux-x64-gnu': 4.2.1 + '@tailwindcss/oxide-linux-x64-musl': 4.2.1 '@tailwindcss/oxide-wasm32-wasi': 4.2.1 + '@tailwindcss/oxide-win32-arm64-msvc': 4.2.1 + '@tailwindcss/oxide-win32-x64-msvc': 4.2.1 '@tailwindcss/typography@0.5.19(tailwindcss@4.2.1)': dependencies: @@ -4554,6 +5563,8 @@ snapshots: node-releases: 2.0.36 update-browserslist-db: 1.2.3(browserslist@4.28.1) + buffer-from@1.1.2: {} + bytes@3.1.2: {} call-bind-apply-helpers@1.0.2: @@ -4704,9 +5715,9 @@ snapshots: drizzle-kit@0.31.9: dependencies: '@drizzle-team/brocli': 0.10.2 - '@esbuild-kit/esm-loader': tsx@4.21.0 - esbuild: 0.27.3 - esbuild-register: 3.6.0(esbuild@0.27.3) + '@esbuild-kit/esm-loader': 2.6.5 + esbuild: 0.25.12 + esbuild-register: 3.6.0(esbuild@0.25.12) transitivePeerDependencies: - supports-color @@ -4776,16 +5787,95 @@ snapshots: pino-pretty: 13.1.3 thread-stream: 3.1.0 - esbuild-register@3.6.0(esbuild@0.27.3): + esbuild-register@3.6.0(esbuild@0.25.12): dependencies: debug: 4.4.3 - esbuild: 0.27.3 + esbuild: 0.25.12 transitivePeerDependencies: - supports-color + esbuild@0.18.20: + optionalDependencies: + '@esbuild/android-arm': 0.18.20 + '@esbuild/android-arm64': 0.18.20 + '@esbuild/android-x64': 0.18.20 + '@esbuild/darwin-arm64': 0.18.20 + '@esbuild/darwin-x64': 0.18.20 + '@esbuild/freebsd-arm64': 0.18.20 + '@esbuild/freebsd-x64': 0.18.20 + '@esbuild/linux-arm': 0.18.20 + '@esbuild/linux-arm64': 0.18.20 + '@esbuild/linux-ia32': 0.18.20 + '@esbuild/linux-loong64': 0.18.20 + '@esbuild/linux-mips64el': 0.18.20 + '@esbuild/linux-ppc64': 0.18.20 + '@esbuild/linux-riscv64': 0.18.20 + '@esbuild/linux-s390x': 0.18.20 + '@esbuild/linux-x64': 0.18.20 + '@esbuild/netbsd-x64': 0.18.20 + '@esbuild/openbsd-x64': 0.18.20 + '@esbuild/sunos-x64': 0.18.20 + '@esbuild/win32-arm64': 0.18.20 + '@esbuild/win32-ia32': 0.18.20 + '@esbuild/win32-x64': 0.18.20 + + esbuild@0.25.12: + optionalDependencies: + '@esbuild/aix-ppc64': 0.25.12 + '@esbuild/android-arm': 0.25.12 + '@esbuild/android-arm64': 0.25.12 + '@esbuild/android-x64': 0.25.12 + '@esbuild/darwin-arm64': 0.25.12 + '@esbuild/darwin-x64': 0.25.12 + '@esbuild/freebsd-arm64': 0.25.12 + '@esbuild/freebsd-x64': 0.25.12 + '@esbuild/linux-arm': 0.25.12 + '@esbuild/linux-arm64': 0.25.12 + '@esbuild/linux-ia32': 0.25.12 + '@esbuild/linux-loong64': 0.25.12 + '@esbuild/linux-mips64el': 0.25.12 + '@esbuild/linux-ppc64': 0.25.12 + '@esbuild/linux-riscv64': 0.25.12 + '@esbuild/linux-s390x': 0.25.12 + '@esbuild/linux-x64': 0.25.12 + '@esbuild/netbsd-arm64': 0.25.12 + '@esbuild/netbsd-x64': 0.25.12 + '@esbuild/openbsd-arm64': 0.25.12 + '@esbuild/openbsd-x64': 0.25.12 + '@esbuild/openharmony-arm64': 0.25.12 + '@esbuild/sunos-x64': 0.25.12 + '@esbuild/win32-arm64': 0.25.12 + '@esbuild/win32-ia32': 0.25.12 + '@esbuild/win32-x64': 0.25.12 + esbuild@0.27.3: optionalDependencies: + '@esbuild/aix-ppc64': 0.27.3 + '@esbuild/android-arm': 0.27.3 + '@esbuild/android-arm64': 0.27.3 + '@esbuild/android-x64': 0.27.3 + '@esbuild/darwin-arm64': 0.27.3 + '@esbuild/darwin-x64': 0.27.3 + '@esbuild/freebsd-arm64': 0.27.3 + '@esbuild/freebsd-x64': 0.27.3 + '@esbuild/linux-arm': 0.27.3 + '@esbuild/linux-arm64': 0.27.3 + '@esbuild/linux-ia32': 0.27.3 + '@esbuild/linux-loong64': 0.27.3 + '@esbuild/linux-mips64el': 0.27.3 + '@esbuild/linux-ppc64': 0.27.3 + '@esbuild/linux-riscv64': 0.27.3 + '@esbuild/linux-s390x': 0.27.3 '@esbuild/linux-x64': 0.27.3 + '@esbuild/netbsd-arm64': 0.27.3 + '@esbuild/netbsd-x64': 0.27.3 + '@esbuild/openbsd-arm64': 0.27.3 + '@esbuild/openbsd-x64': 0.27.3 + '@esbuild/openharmony-arm64': 0.27.3 + '@esbuild/sunos-x64': 0.27.3 + '@esbuild/win32-arm64': 0.27.3 + '@esbuild/win32-ia32': 0.27.3 + '@esbuild/win32-x64': 0.27.3 escalade@3.2.0: {} @@ -5063,14 +6153,54 @@ snapshots: leven@4.1.0: {} + lightningcss-android-arm64@1.31.1: + optional: true + + lightningcss-darwin-arm64@1.31.1: + optional: true + + lightningcss-darwin-x64@1.31.1: + optional: true + + lightningcss-freebsd-x64@1.31.1: + optional: true + + lightningcss-linux-arm-gnueabihf@1.31.1: + optional: true + + lightningcss-linux-arm64-gnu@1.31.1: + optional: true + + lightningcss-linux-arm64-musl@1.31.1: + optional: true + lightningcss-linux-x64-gnu@1.31.1: optional: true + lightningcss-linux-x64-musl@1.31.1: + optional: true + + lightningcss-win32-arm64-msvc@1.31.1: + optional: true + + lightningcss-win32-x64-msvc@1.31.1: + optional: true + lightningcss@1.31.1: dependencies: detect-libc: 2.1.2 optionalDependencies: + lightningcss-android-arm64: 1.31.1 + lightningcss-darwin-arm64: 1.31.1 + lightningcss-darwin-x64: 1.31.1 + lightningcss-freebsd-x64: 1.31.1 + lightningcss-linux-arm-gnueabihf: 1.31.1 + lightningcss-linux-arm64-gnu: 1.31.1 + lightningcss-linux-arm64-musl: 1.31.1 lightningcss-linux-x64-gnu: 1.31.1 + lightningcss-linux-x64-musl: 1.31.1 + lightningcss-win32-arm64-msvc: 1.31.1 + lightningcss-win32-x64-msvc: 1.31.1 linkify-it@5.0.0: dependencies: @@ -5513,7 +6643,31 @@ snapshots: dependencies: '@types/estree': 1.0.8 optionalDependencies: + '@rollup/rollup-android-arm-eabi': 4.59.0 + '@rollup/rollup-android-arm64': 4.59.0 + '@rollup/rollup-darwin-arm64': 4.59.0 + '@rollup/rollup-darwin-x64': 4.59.0 + '@rollup/rollup-freebsd-arm64': 4.59.0 + '@rollup/rollup-freebsd-x64': 4.59.0 + '@rollup/rollup-linux-arm-gnueabihf': 4.59.0 + '@rollup/rollup-linux-arm-musleabihf': 4.59.0 + '@rollup/rollup-linux-arm64-gnu': 4.59.0 + '@rollup/rollup-linux-arm64-musl': 4.59.0 + '@rollup/rollup-linux-loong64-gnu': 4.59.0 + '@rollup/rollup-linux-loong64-musl': 4.59.0 + '@rollup/rollup-linux-ppc64-gnu': 4.59.0 + '@rollup/rollup-linux-ppc64-musl': 4.59.0 + '@rollup/rollup-linux-riscv64-gnu': 4.59.0 + '@rollup/rollup-linux-riscv64-musl': 4.59.0 + '@rollup/rollup-linux-s390x-gnu': 4.59.0 '@rollup/rollup-linux-x64-gnu': 4.59.0 + '@rollup/rollup-linux-x64-musl': 4.59.0 + '@rollup/rollup-openbsd-x64': 4.59.0 + '@rollup/rollup-openharmony-arm64': 4.59.0 + '@rollup/rollup-win32-arm64-msvc': 4.59.0 + '@rollup/rollup-win32-ia32-msvc': 4.59.0 + '@rollup/rollup-win32-x64-gnu': 4.59.0 + '@rollup/rollup-win32-x64-msvc': 4.59.0 fsevents: 2.3.3 router@2.2.0: @@ -5618,6 +6772,13 @@ snapshots: source-map-js@1.2.1: {} + source-map-support@0.5.21: + dependencies: + buffer-from: 1.1.2 + source-map: 0.6.1 + + source-map@0.6.1: {} + split2@4.2.0: {} statuses@2.0.2: {} From a9ad5df71ea4e83fa69e2191ac4f00360667b453 Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Tue, 5 May 2026 02:17:50 +0000 Subject: [PATCH 2/2] feat: implement full Sunsama UI features - sidebar icons with collapse toggle, board header with Board/Calendars buttons, calendar pane with hour labels and current-time line, task editor with description textarea, h:mm time format, archive/backlog panel Co-Authored-By: adamer --- .../src/pages/home/BacklogPanel.tsx | 85 ++++ .../src/pages/home/BoardHeader.tsx | 26 +- .../src/pages/home/CalendarPane.tsx | 77 ++- .../sunsama-web/src/pages/home/DayColumn.tsx | 3 + .../sunsama-web/src/pages/home/Homepage.tsx | 45 +- .../sunsama-web/src/pages/home/Sidebar.tsx | 80 ++- .../sunsama-web/src/pages/home/TaskCard.tsx | 52 +- .../sunsama-web/src/pages/home/TaskEditor.tsx | 45 +- .../sunsama-web/src/pages/home/homepage.css | 463 ++++++++++++++++-- artifacts/sunsama-web/src/pages/home/types.ts | 1 + 10 files changed, 754 insertions(+), 123 deletions(-) create mode 100644 artifacts/sunsama-web/src/pages/home/BacklogPanel.tsx diff --git a/artifacts/sunsama-web/src/pages/home/BacklogPanel.tsx b/artifacts/sunsama-web/src/pages/home/BacklogPanel.tsx new file mode 100644 index 0000000..29d0327 --- /dev/null +++ b/artifacts/sunsama-web/src/pages/home/BacklogPanel.tsx @@ -0,0 +1,85 @@ +import "./homepage.css"; +import { useState } from "react"; +import type { Project } from "./types"; +import { X, Search, RotateCcw } from "lucide-react"; + +interface Props { + archivedProjects: Project[]; + onRestore: (projectId: string) => void; + onClose: () => void; +} + +export default function BacklogPanel({ + archivedProjects, + onRestore, + onClose, +}: Props) { + const [search, setSearch] = useState(""); + const [filterTag, setFilterTag] = useState("all"); + + const filtered = archivedProjects.filter((p) => { + const matchesSearch = + !search || p.title.toLowerCase().includes(search.toLowerCase()); + const matchesTag = filterTag === "all" || p.tag === filterTag; + return matchesSearch && matchesTag; + }); + + return ( + + ); +} diff --git a/artifacts/sunsama-web/src/pages/home/BoardHeader.tsx b/artifacts/sunsama-web/src/pages/home/BoardHeader.tsx index ae92a6d..f91dbd9 100644 --- a/artifacts/sunsama-web/src/pages/home/BoardHeader.tsx +++ b/artifacts/sunsama-web/src/pages/home/BoardHeader.tsx @@ -1,11 +1,33 @@ import "./homepage.css"; +import { + Calendar, + SlidersHorizontal, + LayoutGrid, + CalendarDays, +} from "lucide-react"; export default function BoardHeader() { return (
- - + + +
+
+ +
); diff --git a/artifacts/sunsama-web/src/pages/home/CalendarPane.tsx b/artifacts/sunsama-web/src/pages/home/CalendarPane.tsx index 4c13706..4150291 100644 --- a/artifacts/sunsama-web/src/pages/home/CalendarPane.tsx +++ b/artifacts/sunsama-web/src/pages/home/CalendarPane.tsx @@ -1,16 +1,59 @@ import "./homepage.css"; +import { useState, useEffect, useMemo } from "react"; +import { + Calendar, + BarChart2, + Settings, + ClipboardList, + Moon, + Search, + Zap, + Plus, +} from "lucide-react"; -export default function CalendarPane() { +const HOURS = Array.from({ length: 12 }, (_, i) => i + 12); +const HOUR_HEIGHT = 56; + +function currentMinuteOffset(): number { + const now = new Date(); + const h = now.getHours(); + const m = now.getMinutes(); + const minutesSinceNoon = (h - 12) * 60 + m; + return (minutesSinceNoon / 60) * HOUR_HEIGHT; +} + +interface Props { + onOpenBacklog: () => void; +} + +export default function CalendarPane({ onOpenBacklog }: Props) { const now = new Date(); const dayAbbr = now .toLocaleDateString("en-US", { weekday: "short" }) .toUpperCase(); const dayNum = now.getDate(); + const [timeOffset, setTimeOffset] = useState(currentMinuteOffset); + + useEffect(() => { + const id = setInterval(() => setTimeOffset(currentMinuteOffset()), 60_000); + return () => clearInterval(id); + }, []); + + const showTimeLine = useMemo(() => { + const h = now.getHours(); + return h >= 12 && h < 24; + }, [now]); + return (