@mrck-labs/vanaheim-shared 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/atoms/index.ts","../../src/atoms/focus.ts","../../src/utils/formatters.ts"],"sourcesContent":["/**\n * Atoms Index\n *\n * Re-exports all shared Jotai atoms.\n */\n\nexport * from './focus'\n\n","/**\n * Focus Timer Atoms\n *\n * Shared Jotai atoms for focus timer state management.\n * Used by both desktop and mobile apps.\n *\n * These atoms manage in-memory timer state that syncs with\n * the database via TanStack Query.\n *\n * @example\n * import { timerStatusAtom, targetSecondsAtom } from '@mrck-labs/vanaheim-shared/atoms'\n * import { useAtom, useAtomValue } from 'jotai'\n *\n * const [status, setStatus] = useAtom(timerStatusAtom)\n * const remaining = useAtomValue(remainingSecondsAtom)\n */\n\nimport { atom } from 'jotai'\nimport { formatTime } from '../utils/formatters'\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Timer status values\n */\nexport type TimerStatus = 'idle' | 'running' | 'paused' | 'completed'\n\n/**\n * Active focus session info (in-memory during timer run)\n * This is separate from the database FocusSession type\n */\nexport interface ActiveSession {\n id: string\n title: string\n categoryId: string | null\n targetMinutes: number\n startedAt?: string // Optional - used by mobile for elapsed calculation\n}\n\n// ============================================================================\n// Core Timer Atoms\n// ============================================================================\n\n/**\n * Current timer status\n * - idle: No timer running\n * - running: Timer actively counting\n * - paused: Timer paused\n * - completed: Timer finished (target reached)\n */\nexport const timerStatusAtom = atom<TimerStatus>('idle')\n\n/**\n * Target duration in seconds\n * Default: 25 minutes (Pomodoro)\n */\nexport const targetSecondsAtom = atom<number>(25 * 60)\n\n/**\n * Elapsed seconds since timer started\n */\nexport const elapsedSecondsAtom = atom<number>(0)\n\n/**\n * Currently active session info (in-memory during timer run)\n */\nexport const activeSessionAtom = atom<ActiveSession | null>(null)\n\n// ============================================================================\n// Derived Timer Atoms (computed, read-only)\n// ============================================================================\n\n/**\n * Remaining seconds (target - elapsed)\n * Always returns 0 or positive\n */\nexport const remainingSecondsAtom = atom((get) => {\n const target = get(targetSecondsAtom)\n const elapsed = get(elapsedSecondsAtom)\n return Math.max(0, target - elapsed)\n})\n\n/**\n * Progress as a ratio (0 to 1)\n * 0 = just started, 1 = completed\n *\n * Note: Desktop previously used 0-100 (percentage).\n * If you need percentage, multiply by 100.\n */\nexport const progressAtom = atom((get) => {\n const target = get(targetSecondsAtom)\n const elapsed = get(elapsedSecondsAtom)\n if (target === 0) return 0\n return Math.min(1, elapsed / target)\n})\n\n/**\n * Formatted remaining time (MM:SS)\n * @example \"24:59\", \"00:30\"\n */\nexport const formattedRemainingAtom = atom((get) => {\n return formatTime(get(remainingSecondsAtom))\n})\n\n/**\n * Formatted elapsed time (MM:SS)\n * @example \"00:01\", \"25:00\"\n */\nexport const formattedElapsedAtom = atom((get) => {\n return formatTime(get(elapsedSecondsAtom))\n})\n\n/**\n * Progress as percentage (0 to 100)\n * Convenience atom for desktop compatibility\n */\nexport const progressPercentAtom = atom((get) => {\n return get(progressAtom) * 100\n})\n\n","/**\n * Formatting Utilities\n *\n * Pure functions for formatting data.\n */\n\n/**\n * Format seconds into MM:SS format\n * @example formatTime(125) => \"02:05\"\n */\nexport function formatTime(seconds: number): string {\n const mins = Math.floor(seconds / 60)\n const secs = seconds % 60\n return `${mins.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`\n}\n\n/**\n * Format seconds into human-readable total time\n * @example formatTotalTime(3700) => \"1h 1m\"\n * @example formatTotalTime(1800) => \"30m\"\n */\nexport function formatTotalTime(seconds: number): string {\n const hours = Math.floor(seconds / 3600)\n const mins = Math.floor((seconds % 3600) / 60)\n if (hours > 0) {\n return `${hours}h ${mins}m`\n }\n return `${mins}m`\n}\n\n/**\n * Format a number as currency\n * Uses Swiss German locale for authentic Swiss formatting (apostrophe as thousands separator)\n * @example formatCurrency(1234.56, 'CHF') => \"CHF 1'234.56\"\n */\nexport function formatCurrency(\n amount: number,\n currency: string,\n locale: string = 'de-CH'\n): string {\n return new Intl.NumberFormat(locale, {\n style: 'currency',\n currency,\n minimumFractionDigits: 2,\n maximumFractionDigits: 2,\n }).format(amount)\n}\n\n/**\n * Format a date as relative time (e.g., \"2h ago\", \"3d ago\")\n */\nexport function formatRelativeTime(dateStr: string): string {\n const date = new Date(dateStr)\n const now = new Date()\n const diffMs = now.getTime() - date.getTime()\n const diffMins = Math.floor(diffMs / 60000)\n const diffHours = Math.floor(diffMins / 60)\n const diffDays = Math.floor(diffHours / 24)\n\n if (diffMins < 1) return 'Just now'\n if (diffMins < 60) return `${diffMins}m ago`\n if (diffHours < 24) return `${diffHours}h ago`\n if (diffDays < 7) return `${diffDays}d ago`\n return date.toLocaleDateString()\n}\n\n/**\n * Format a date string to a readable format\n * @example formatDate('2024-01-15') => \"Jan 15, 2024\"\n */\nexport function formatDate(\n dateStr: string,\n options: Intl.DateTimeFormatOptions = {\n month: 'short',\n day: 'numeric',\n year: 'numeric',\n }\n): string {\n return new Date(dateStr).toLocaleDateString('en-US', options)\n}\n\n/**\n * Format a due date with context (Today, Tomorrow, Overdue, etc.)\n */\nexport function formatDueDate(dueDate: string | null): {\n text: string\n isOverdue: boolean\n} {\n if (!dueDate) return { text: '', isOverdue: false }\n\n const due = new Date(dueDate)\n const today = new Date()\n today.setHours(0, 0, 0, 0)\n\n const tomorrow = new Date(today)\n tomorrow.setDate(tomorrow.getDate() + 1)\n\n const dueDay = new Date(due)\n dueDay.setHours(0, 0, 0, 0)\n\n const isOverdue = dueDay < today\n\n if (dueDay.getTime() === today.getTime()) {\n return { text: 'Today', isOverdue: false }\n } else if (dueDay.getTime() === tomorrow.getTime()) {\n return { text: 'Tomorrow', isOverdue: false }\n } else if (isOverdue) {\n const daysAgo = Math.ceil(\n (today.getTime() - dueDay.getTime()) / (1000 * 60 * 60 * 24)\n )\n return { text: `${daysAgo}d overdue`, isOverdue: true }\n } else {\n return {\n text: due.toLocaleDateString('en-US', { month: 'short', day: 'numeric' }),\n isOverdue: false,\n }\n }\n}\n\n/**\n * Truncate a string with ellipsis\n * @example truncate(\"Hello World\", 5) => \"Hello...\"\n */\nexport function truncate(str: string, maxLength: number): string {\n if (str.length <= maxLength) return str\n return str.slice(0, maxLength) + '...'\n}\n\n/**\n * Extract repo name from GitHub URL\n * @example getRepoName(\"https://github.com/owner/repo\") => \"owner/repo\"\n */\nexport function getRepoName(url: string): string {\n const match = url.match(/github\\.com\\/(.+)$/)\n return match ? match[1] : url\n}\n\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACiBA,mBAAqB;;;ACPd,SAAS,WAAW,SAAyB;AAClD,QAAM,OAAO,KAAK,MAAM,UAAU,EAAE;AACpC,QAAM,OAAO,UAAU;AACvB,SAAO,GAAG,KAAK,SAAS,EAAE,SAAS,GAAG,GAAG,CAAC,IAAI,KAAK,SAAS,EAAE,SAAS,GAAG,GAAG,CAAC;AAChF;;;ADsCO,IAAM,sBAAkB,mBAAkB,MAAM;AAMhD,IAAM,wBAAoB,mBAAa,KAAK,EAAE;AAK9C,IAAM,yBAAqB,mBAAa,CAAC;AAKzC,IAAM,wBAAoB,mBAA2B,IAAI;AAUzD,IAAM,2BAAuB,mBAAK,CAAC,QAAQ;AAChD,QAAM,SAAS,IAAI,iBAAiB;AACpC,QAAM,UAAU,IAAI,kBAAkB;AACtC,SAAO,KAAK,IAAI,GAAG,SAAS,OAAO;AACrC,CAAC;AASM,IAAM,mBAAe,mBAAK,CAAC,QAAQ;AACxC,QAAM,SAAS,IAAI,iBAAiB;AACpC,QAAM,UAAU,IAAI,kBAAkB;AACtC,MAAI,WAAW,EAAG,QAAO;AACzB,SAAO,KAAK,IAAI,GAAG,UAAU,MAAM;AACrC,CAAC;AAMM,IAAM,6BAAyB,mBAAK,CAAC,QAAQ;AAClD,SAAO,WAAW,IAAI,oBAAoB,CAAC;AAC7C,CAAC;AAMM,IAAM,2BAAuB,mBAAK,CAAC,QAAQ;AAChD,SAAO,WAAW,IAAI,kBAAkB,CAAC;AAC3C,CAAC;AAMM,IAAM,0BAAsB,mBAAK,CAAC,QAAQ;AAC/C,SAAO,IAAI,YAAY,IAAI;AAC7B,CAAC;","names":[]}
1
+ {"version":3,"sources":["../../src/atoms/index.ts","../../src/atoms/focus.ts","../../src/utils/formatters.ts"],"sourcesContent":["/**\n * Atoms Index\n *\n * Re-exports all shared Jotai atoms.\n */\n\nexport * from './focus'\n\n","/**\n * Focus Timer Atoms\n *\n * Shared Jotai atoms for focus timer state management.\n * Used by both desktop and mobile apps.\n *\n * These atoms manage in-memory timer state that syncs with\n * the database via TanStack Query.\n *\n * @example\n * import { timerStatusAtom, targetSecondsAtom } from '@mrck-labs/vanaheim-shared/atoms'\n * import { useAtom, useAtomValue } from 'jotai'\n *\n * const [status, setStatus] = useAtom(timerStatusAtom)\n * const remaining = useAtomValue(remainingSecondsAtom)\n */\n\nimport { atom } from 'jotai'\nimport { formatTime } from '../utils/formatters'\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Timer status values\n */\nexport type TimerStatus = 'idle' | 'running' | 'paused' | 'completed'\n\n/**\n * Active focus session info (in-memory during timer run)\n * This is separate from the database FocusSession type\n */\nexport interface ActiveSession {\n id: string\n title: string\n categoryId: string | null\n targetMinutes: number\n startedAt?: string // Optional - used by mobile for elapsed calculation\n}\n\n// ============================================================================\n// Core Timer Atoms\n// ============================================================================\n\n/**\n * Current timer status\n * - idle: No timer running\n * - running: Timer actively counting\n * - paused: Timer paused\n * - completed: Timer finished (target reached)\n */\nexport const timerStatusAtom = atom<TimerStatus>('idle')\n\n/**\n * Target duration in seconds\n * Default: 25 minutes (Pomodoro)\n */\nexport const targetSecondsAtom = atom<number>(25 * 60)\n\n/**\n * Elapsed seconds since timer started\n */\nexport const elapsedSecondsAtom = atom<number>(0)\n\n/**\n * Currently active session info (in-memory during timer run)\n */\nexport const activeSessionAtom = atom<ActiveSession | null>(null)\n\n// ============================================================================\n// Derived Timer Atoms (computed, read-only)\n// ============================================================================\n\n/**\n * Remaining seconds (target - elapsed)\n * Always returns 0 or positive\n */\nexport const remainingSecondsAtom = atom((get) => {\n const target = get(targetSecondsAtom)\n const elapsed = get(elapsedSecondsAtom)\n return Math.max(0, target - elapsed)\n})\n\n/**\n * Progress as a ratio (0 to 1)\n * 0 = just started, 1 = completed\n *\n * Note: Desktop previously used 0-100 (percentage).\n * If you need percentage, multiply by 100.\n */\nexport const progressAtom = atom((get) => {\n const target = get(targetSecondsAtom)\n const elapsed = get(elapsedSecondsAtom)\n if (target === 0) return 0\n return Math.min(1, elapsed / target)\n})\n\n/**\n * Formatted remaining time (MM:SS)\n * @example \"24:59\", \"00:30\"\n */\nexport const formattedRemainingAtom = atom((get) => {\n return formatTime(get(remainingSecondsAtom))\n})\n\n/**\n * Formatted elapsed time (MM:SS)\n * @example \"00:01\", \"25:00\"\n */\nexport const formattedElapsedAtom = atom((get) => {\n return formatTime(get(elapsedSecondsAtom))\n})\n\n/**\n * Progress as percentage (0 to 100)\n * Convenience atom for desktop compatibility\n */\nexport const progressPercentAtom = atom((get) => {\n return get(progressAtom) * 100\n})\n\n","/**\n * Formatting Utilities\n *\n * Pure functions for formatting data.\n */\n\n/**\n * Format seconds into MM:SS format\n * @example formatTime(125) => \"02:05\"\n */\nexport function formatTime(seconds: number): string {\n const mins = Math.floor(seconds / 60)\n const secs = seconds % 60\n return `${mins.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`\n}\n\n/**\n * Format seconds into human-readable total time\n * @example formatTotalTime(3700) => \"1h 1m\"\n * @example formatTotalTime(1800) => \"30m\"\n */\nexport function formatTotalTime(seconds: number): string {\n const hours = Math.floor(seconds / 3600)\n const mins = Math.floor((seconds % 3600) / 60)\n if (hours > 0) {\n return `${hours}h ${mins}m`\n }\n return `${mins}m`\n}\n\n/**\n * Format duration in seconds to human-readable format (includes seconds)\n * @example formatDuration(3661) => \"1h 1m\"\n * @example formatDuration(125) => \"2m 5s\"\n * @example formatDuration(45) => \"45s\"\n */\nexport function formatDuration(seconds: number): string {\n const hours = Math.floor(seconds / 3600)\n const minutes = Math.floor((seconds % 3600) / 60)\n const secs = seconds % 60\n\n if (hours > 0) {\n return `${hours}h ${minutes}m`\n } else if (minutes > 0) {\n return `${minutes}m${secs > 0 ? ` ${secs}s` : ''}`\n } else {\n return `${secs}s`\n }\n}\n\n/**\n * Format a number as currency\n * Uses Swiss German locale for authentic Swiss formatting (apostrophe as thousands separator)\n * @example formatCurrency(1234.56, 'CHF') => \"CHF 1'234.56\"\n * @example formatCurrency(1234.56) => \"CHF 1'234.56\" (defaults to CHF)\n */\nexport function formatCurrency(\n amount: number,\n currency: string = 'CHF',\n locale: string = 'de-CH'\n): string {\n return new Intl.NumberFormat(locale, {\n style: 'currency',\n currency,\n minimumFractionDigits: 2,\n maximumFractionDigits: 2,\n }).format(amount)\n}\n\n/**\n * Format a date as relative time (e.g., \"2h ago\", \"3d ago\")\n */\nexport function formatRelativeTime(dateStr: string): string {\n const date = new Date(dateStr)\n const now = new Date()\n const diffMs = now.getTime() - date.getTime()\n const diffMins = Math.floor(diffMs / 60000)\n const diffHours = Math.floor(diffMins / 60)\n const diffDays = Math.floor(diffHours / 24)\n\n if (diffMins < 1) return 'Just now'\n if (diffMins < 60) return `${diffMins}m ago`\n if (diffHours < 24) return `${diffHours}h ago`\n if (diffDays < 7) return `${diffDays}d ago`\n return date.toLocaleDateString()\n}\n\n/**\n * Format a date string to a readable format\n * @example formatDate('2024-01-15') => \"Jan 15, 2024\"\n */\nexport function formatDate(\n dateStr: string,\n options: Intl.DateTimeFormatOptions = {\n month: 'short',\n day: 'numeric',\n year: 'numeric',\n }\n): string {\n return new Date(dateStr).toLocaleDateString('en-US', options)\n}\n\n/**\n * Format a due date with context (Today, Tomorrow, Overdue, etc.)\n */\nexport function formatDueDate(dueDate: string | null): {\n text: string\n isOverdue: boolean\n} {\n if (!dueDate) return { text: '', isOverdue: false }\n\n const due = new Date(dueDate)\n const today = new Date()\n today.setHours(0, 0, 0, 0)\n\n const tomorrow = new Date(today)\n tomorrow.setDate(tomorrow.getDate() + 1)\n\n const dueDay = new Date(due)\n dueDay.setHours(0, 0, 0, 0)\n\n const isOverdue = dueDay < today\n\n if (dueDay.getTime() === today.getTime()) {\n return { text: 'Today', isOverdue: false }\n } else if (dueDay.getTime() === tomorrow.getTime()) {\n return { text: 'Tomorrow', isOverdue: false }\n } else if (isOverdue) {\n const daysAgo = Math.ceil(\n (today.getTime() - dueDay.getTime()) / (1000 * 60 * 60 * 24)\n )\n return { text: `${daysAgo}d overdue`, isOverdue: true }\n } else {\n return {\n text: due.toLocaleDateString('en-US', { month: 'short', day: 'numeric' }),\n isOverdue: false,\n }\n }\n}\n\n/**\n * Truncate a string with ellipsis\n * @example truncate(\"Hello World\", 5) => \"Hello...\"\n */\nexport function truncate(str: string, maxLength: number): string {\n if (str.length <= maxLength) return str\n return str.slice(0, maxLength) + '...'\n}\n\n/**\n * Extract repo name from GitHub URL\n * @example getRepoName(\"https://github.com/owner/repo\") => \"owner/repo\"\n */\nexport function getRepoName(url: string): string {\n const match = url.match(/github\\.com\\/(.+)$/)\n return match ? match[1] : url\n}\n\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACiBA,mBAAqB;;;ACPd,SAAS,WAAW,SAAyB;AAClD,QAAM,OAAO,KAAK,MAAM,UAAU,EAAE;AACpC,QAAM,OAAO,UAAU;AACvB,SAAO,GAAG,KAAK,SAAS,EAAE,SAAS,GAAG,GAAG,CAAC,IAAI,KAAK,SAAS,EAAE,SAAS,GAAG,GAAG,CAAC;AAChF;;;ADsCO,IAAM,sBAAkB,mBAAkB,MAAM;AAMhD,IAAM,wBAAoB,mBAAa,KAAK,EAAE;AAK9C,IAAM,yBAAqB,mBAAa,CAAC;AAKzC,IAAM,wBAAoB,mBAA2B,IAAI;AAUzD,IAAM,2BAAuB,mBAAK,CAAC,QAAQ;AAChD,QAAM,SAAS,IAAI,iBAAiB;AACpC,QAAM,UAAU,IAAI,kBAAkB;AACtC,SAAO,KAAK,IAAI,GAAG,SAAS,OAAO;AACrC,CAAC;AASM,IAAM,mBAAe,mBAAK,CAAC,QAAQ;AACxC,QAAM,SAAS,IAAI,iBAAiB;AACpC,QAAM,UAAU,IAAI,kBAAkB;AACtC,MAAI,WAAW,EAAG,QAAO;AACzB,SAAO,KAAK,IAAI,GAAG,UAAU,MAAM;AACrC,CAAC;AAMM,IAAM,6BAAyB,mBAAK,CAAC,QAAQ;AAClD,SAAO,WAAW,IAAI,oBAAoB,CAAC;AAC7C,CAAC;AAMM,IAAM,2BAAuB,mBAAK,CAAC,QAAQ;AAChD,SAAO,WAAW,IAAI,kBAAkB,CAAC;AAC3C,CAAC;AAMM,IAAM,0BAAsB,mBAAK,CAAC,QAAQ;AAC/C,SAAO,IAAI,YAAY,IAAI;AAC7B,CAAC;","names":[]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/atoms/focus.ts","../../src/utils/formatters.ts"],"sourcesContent":["/**\n * Focus Timer Atoms\n *\n * Shared Jotai atoms for focus timer state management.\n * Used by both desktop and mobile apps.\n *\n * These atoms manage in-memory timer state that syncs with\n * the database via TanStack Query.\n *\n * @example\n * import { timerStatusAtom, targetSecondsAtom } from '@mrck-labs/vanaheim-shared/atoms'\n * import { useAtom, useAtomValue } from 'jotai'\n *\n * const [status, setStatus] = useAtom(timerStatusAtom)\n * const remaining = useAtomValue(remainingSecondsAtom)\n */\n\nimport { atom } from 'jotai'\nimport { formatTime } from '../utils/formatters'\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Timer status values\n */\nexport type TimerStatus = 'idle' | 'running' | 'paused' | 'completed'\n\n/**\n * Active focus session info (in-memory during timer run)\n * This is separate from the database FocusSession type\n */\nexport interface ActiveSession {\n id: string\n title: string\n categoryId: string | null\n targetMinutes: number\n startedAt?: string // Optional - used by mobile for elapsed calculation\n}\n\n// ============================================================================\n// Core Timer Atoms\n// ============================================================================\n\n/**\n * Current timer status\n * - idle: No timer running\n * - running: Timer actively counting\n * - paused: Timer paused\n * - completed: Timer finished (target reached)\n */\nexport const timerStatusAtom = atom<TimerStatus>('idle')\n\n/**\n * Target duration in seconds\n * Default: 25 minutes (Pomodoro)\n */\nexport const targetSecondsAtom = atom<number>(25 * 60)\n\n/**\n * Elapsed seconds since timer started\n */\nexport const elapsedSecondsAtom = atom<number>(0)\n\n/**\n * Currently active session info (in-memory during timer run)\n */\nexport const activeSessionAtom = atom<ActiveSession | null>(null)\n\n// ============================================================================\n// Derived Timer Atoms (computed, read-only)\n// ============================================================================\n\n/**\n * Remaining seconds (target - elapsed)\n * Always returns 0 or positive\n */\nexport const remainingSecondsAtom = atom((get) => {\n const target = get(targetSecondsAtom)\n const elapsed = get(elapsedSecondsAtom)\n return Math.max(0, target - elapsed)\n})\n\n/**\n * Progress as a ratio (0 to 1)\n * 0 = just started, 1 = completed\n *\n * Note: Desktop previously used 0-100 (percentage).\n * If you need percentage, multiply by 100.\n */\nexport const progressAtom = atom((get) => {\n const target = get(targetSecondsAtom)\n const elapsed = get(elapsedSecondsAtom)\n if (target === 0) return 0\n return Math.min(1, elapsed / target)\n})\n\n/**\n * Formatted remaining time (MM:SS)\n * @example \"24:59\", \"00:30\"\n */\nexport const formattedRemainingAtom = atom((get) => {\n return formatTime(get(remainingSecondsAtom))\n})\n\n/**\n * Formatted elapsed time (MM:SS)\n * @example \"00:01\", \"25:00\"\n */\nexport const formattedElapsedAtom = atom((get) => {\n return formatTime(get(elapsedSecondsAtom))\n})\n\n/**\n * Progress as percentage (0 to 100)\n * Convenience atom for desktop compatibility\n */\nexport const progressPercentAtom = atom((get) => {\n return get(progressAtom) * 100\n})\n\n","/**\n * Formatting Utilities\n *\n * Pure functions for formatting data.\n */\n\n/**\n * Format seconds into MM:SS format\n * @example formatTime(125) => \"02:05\"\n */\nexport function formatTime(seconds: number): string {\n const mins = Math.floor(seconds / 60)\n const secs = seconds % 60\n return `${mins.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`\n}\n\n/**\n * Format seconds into human-readable total time\n * @example formatTotalTime(3700) => \"1h 1m\"\n * @example formatTotalTime(1800) => \"30m\"\n */\nexport function formatTotalTime(seconds: number): string {\n const hours = Math.floor(seconds / 3600)\n const mins = Math.floor((seconds % 3600) / 60)\n if (hours > 0) {\n return `${hours}h ${mins}m`\n }\n return `${mins}m`\n}\n\n/**\n * Format a number as currency\n * Uses Swiss German locale for authentic Swiss formatting (apostrophe as thousands separator)\n * @example formatCurrency(1234.56, 'CHF') => \"CHF 1'234.56\"\n */\nexport function formatCurrency(\n amount: number,\n currency: string,\n locale: string = 'de-CH'\n): string {\n return new Intl.NumberFormat(locale, {\n style: 'currency',\n currency,\n minimumFractionDigits: 2,\n maximumFractionDigits: 2,\n }).format(amount)\n}\n\n/**\n * Format a date as relative time (e.g., \"2h ago\", \"3d ago\")\n */\nexport function formatRelativeTime(dateStr: string): string {\n const date = new Date(dateStr)\n const now = new Date()\n const diffMs = now.getTime() - date.getTime()\n const diffMins = Math.floor(diffMs / 60000)\n const diffHours = Math.floor(diffMins / 60)\n const diffDays = Math.floor(diffHours / 24)\n\n if (diffMins < 1) return 'Just now'\n if (diffMins < 60) return `${diffMins}m ago`\n if (diffHours < 24) return `${diffHours}h ago`\n if (diffDays < 7) return `${diffDays}d ago`\n return date.toLocaleDateString()\n}\n\n/**\n * Format a date string to a readable format\n * @example formatDate('2024-01-15') => \"Jan 15, 2024\"\n */\nexport function formatDate(\n dateStr: string,\n options: Intl.DateTimeFormatOptions = {\n month: 'short',\n day: 'numeric',\n year: 'numeric',\n }\n): string {\n return new Date(dateStr).toLocaleDateString('en-US', options)\n}\n\n/**\n * Format a due date with context (Today, Tomorrow, Overdue, etc.)\n */\nexport function formatDueDate(dueDate: string | null): {\n text: string\n isOverdue: boolean\n} {\n if (!dueDate) return { text: '', isOverdue: false }\n\n const due = new Date(dueDate)\n const today = new Date()\n today.setHours(0, 0, 0, 0)\n\n const tomorrow = new Date(today)\n tomorrow.setDate(tomorrow.getDate() + 1)\n\n const dueDay = new Date(due)\n dueDay.setHours(0, 0, 0, 0)\n\n const isOverdue = dueDay < today\n\n if (dueDay.getTime() === today.getTime()) {\n return { text: 'Today', isOverdue: false }\n } else if (dueDay.getTime() === tomorrow.getTime()) {\n return { text: 'Tomorrow', isOverdue: false }\n } else if (isOverdue) {\n const daysAgo = Math.ceil(\n (today.getTime() - dueDay.getTime()) / (1000 * 60 * 60 * 24)\n )\n return { text: `${daysAgo}d overdue`, isOverdue: true }\n } else {\n return {\n text: due.toLocaleDateString('en-US', { month: 'short', day: 'numeric' }),\n isOverdue: false,\n }\n }\n}\n\n/**\n * Truncate a string with ellipsis\n * @example truncate(\"Hello World\", 5) => \"Hello...\"\n */\nexport function truncate(str: string, maxLength: number): string {\n if (str.length <= maxLength) return str\n return str.slice(0, maxLength) + '...'\n}\n\n/**\n * Extract repo name from GitHub URL\n * @example getRepoName(\"https://github.com/owner/repo\") => \"owner/repo\"\n */\nexport function getRepoName(url: string): string {\n const match = url.match(/github\\.com\\/(.+)$/)\n return match ? match[1] : url\n}\n\n"],"mappings":";AAiBA,SAAS,YAAY;;;ACPd,SAAS,WAAW,SAAyB;AAClD,QAAM,OAAO,KAAK,MAAM,UAAU,EAAE;AACpC,QAAM,OAAO,UAAU;AACvB,SAAO,GAAG,KAAK,SAAS,EAAE,SAAS,GAAG,GAAG,CAAC,IAAI,KAAK,SAAS,EAAE,SAAS,GAAG,GAAG,CAAC;AAChF;;;ADsCO,IAAM,kBAAkB,KAAkB,MAAM;AAMhD,IAAM,oBAAoB,KAAa,KAAK,EAAE;AAK9C,IAAM,qBAAqB,KAAa,CAAC;AAKzC,IAAM,oBAAoB,KAA2B,IAAI;AAUzD,IAAM,uBAAuB,KAAK,CAAC,QAAQ;AAChD,QAAM,SAAS,IAAI,iBAAiB;AACpC,QAAM,UAAU,IAAI,kBAAkB;AACtC,SAAO,KAAK,IAAI,GAAG,SAAS,OAAO;AACrC,CAAC;AASM,IAAM,eAAe,KAAK,CAAC,QAAQ;AACxC,QAAM,SAAS,IAAI,iBAAiB;AACpC,QAAM,UAAU,IAAI,kBAAkB;AACtC,MAAI,WAAW,EAAG,QAAO;AACzB,SAAO,KAAK,IAAI,GAAG,UAAU,MAAM;AACrC,CAAC;AAMM,IAAM,yBAAyB,KAAK,CAAC,QAAQ;AAClD,SAAO,WAAW,IAAI,oBAAoB,CAAC;AAC7C,CAAC;AAMM,IAAM,uBAAuB,KAAK,CAAC,QAAQ;AAChD,SAAO,WAAW,IAAI,kBAAkB,CAAC;AAC3C,CAAC;AAMM,IAAM,sBAAsB,KAAK,CAAC,QAAQ;AAC/C,SAAO,IAAI,YAAY,IAAI;AAC7B,CAAC;","names":[]}
1
+ {"version":3,"sources":["../../src/atoms/focus.ts","../../src/utils/formatters.ts"],"sourcesContent":["/**\n * Focus Timer Atoms\n *\n * Shared Jotai atoms for focus timer state management.\n * Used by both desktop and mobile apps.\n *\n * These atoms manage in-memory timer state that syncs with\n * the database via TanStack Query.\n *\n * @example\n * import { timerStatusAtom, targetSecondsAtom } from '@mrck-labs/vanaheim-shared/atoms'\n * import { useAtom, useAtomValue } from 'jotai'\n *\n * const [status, setStatus] = useAtom(timerStatusAtom)\n * const remaining = useAtomValue(remainingSecondsAtom)\n */\n\nimport { atom } from 'jotai'\nimport { formatTime } from '../utils/formatters'\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Timer status values\n */\nexport type TimerStatus = 'idle' | 'running' | 'paused' | 'completed'\n\n/**\n * Active focus session info (in-memory during timer run)\n * This is separate from the database FocusSession type\n */\nexport interface ActiveSession {\n id: string\n title: string\n categoryId: string | null\n targetMinutes: number\n startedAt?: string // Optional - used by mobile for elapsed calculation\n}\n\n// ============================================================================\n// Core Timer Atoms\n// ============================================================================\n\n/**\n * Current timer status\n * - idle: No timer running\n * - running: Timer actively counting\n * - paused: Timer paused\n * - completed: Timer finished (target reached)\n */\nexport const timerStatusAtom = atom<TimerStatus>('idle')\n\n/**\n * Target duration in seconds\n * Default: 25 minutes (Pomodoro)\n */\nexport const targetSecondsAtom = atom<number>(25 * 60)\n\n/**\n * Elapsed seconds since timer started\n */\nexport const elapsedSecondsAtom = atom<number>(0)\n\n/**\n * Currently active session info (in-memory during timer run)\n */\nexport const activeSessionAtom = atom<ActiveSession | null>(null)\n\n// ============================================================================\n// Derived Timer Atoms (computed, read-only)\n// ============================================================================\n\n/**\n * Remaining seconds (target - elapsed)\n * Always returns 0 or positive\n */\nexport const remainingSecondsAtom = atom((get) => {\n const target = get(targetSecondsAtom)\n const elapsed = get(elapsedSecondsAtom)\n return Math.max(0, target - elapsed)\n})\n\n/**\n * Progress as a ratio (0 to 1)\n * 0 = just started, 1 = completed\n *\n * Note: Desktop previously used 0-100 (percentage).\n * If you need percentage, multiply by 100.\n */\nexport const progressAtom = atom((get) => {\n const target = get(targetSecondsAtom)\n const elapsed = get(elapsedSecondsAtom)\n if (target === 0) return 0\n return Math.min(1, elapsed / target)\n})\n\n/**\n * Formatted remaining time (MM:SS)\n * @example \"24:59\", \"00:30\"\n */\nexport const formattedRemainingAtom = atom((get) => {\n return formatTime(get(remainingSecondsAtom))\n})\n\n/**\n * Formatted elapsed time (MM:SS)\n * @example \"00:01\", \"25:00\"\n */\nexport const formattedElapsedAtom = atom((get) => {\n return formatTime(get(elapsedSecondsAtom))\n})\n\n/**\n * Progress as percentage (0 to 100)\n * Convenience atom for desktop compatibility\n */\nexport const progressPercentAtom = atom((get) => {\n return get(progressAtom) * 100\n})\n\n","/**\n * Formatting Utilities\n *\n * Pure functions for formatting data.\n */\n\n/**\n * Format seconds into MM:SS format\n * @example formatTime(125) => \"02:05\"\n */\nexport function formatTime(seconds: number): string {\n const mins = Math.floor(seconds / 60)\n const secs = seconds % 60\n return `${mins.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`\n}\n\n/**\n * Format seconds into human-readable total time\n * @example formatTotalTime(3700) => \"1h 1m\"\n * @example formatTotalTime(1800) => \"30m\"\n */\nexport function formatTotalTime(seconds: number): string {\n const hours = Math.floor(seconds / 3600)\n const mins = Math.floor((seconds % 3600) / 60)\n if (hours > 0) {\n return `${hours}h ${mins}m`\n }\n return `${mins}m`\n}\n\n/**\n * Format duration in seconds to human-readable format (includes seconds)\n * @example formatDuration(3661) => \"1h 1m\"\n * @example formatDuration(125) => \"2m 5s\"\n * @example formatDuration(45) => \"45s\"\n */\nexport function formatDuration(seconds: number): string {\n const hours = Math.floor(seconds / 3600)\n const minutes = Math.floor((seconds % 3600) / 60)\n const secs = seconds % 60\n\n if (hours > 0) {\n return `${hours}h ${minutes}m`\n } else if (minutes > 0) {\n return `${minutes}m${secs > 0 ? ` ${secs}s` : ''}`\n } else {\n return `${secs}s`\n }\n}\n\n/**\n * Format a number as currency\n * Uses Swiss German locale for authentic Swiss formatting (apostrophe as thousands separator)\n * @example formatCurrency(1234.56, 'CHF') => \"CHF 1'234.56\"\n * @example formatCurrency(1234.56) => \"CHF 1'234.56\" (defaults to CHF)\n */\nexport function formatCurrency(\n amount: number,\n currency: string = 'CHF',\n locale: string = 'de-CH'\n): string {\n return new Intl.NumberFormat(locale, {\n style: 'currency',\n currency,\n minimumFractionDigits: 2,\n maximumFractionDigits: 2,\n }).format(amount)\n}\n\n/**\n * Format a date as relative time (e.g., \"2h ago\", \"3d ago\")\n */\nexport function formatRelativeTime(dateStr: string): string {\n const date = new Date(dateStr)\n const now = new Date()\n const diffMs = now.getTime() - date.getTime()\n const diffMins = Math.floor(diffMs / 60000)\n const diffHours = Math.floor(diffMins / 60)\n const diffDays = Math.floor(diffHours / 24)\n\n if (diffMins < 1) return 'Just now'\n if (diffMins < 60) return `${diffMins}m ago`\n if (diffHours < 24) return `${diffHours}h ago`\n if (diffDays < 7) return `${diffDays}d ago`\n return date.toLocaleDateString()\n}\n\n/**\n * Format a date string to a readable format\n * @example formatDate('2024-01-15') => \"Jan 15, 2024\"\n */\nexport function formatDate(\n dateStr: string,\n options: Intl.DateTimeFormatOptions = {\n month: 'short',\n day: 'numeric',\n year: 'numeric',\n }\n): string {\n return new Date(dateStr).toLocaleDateString('en-US', options)\n}\n\n/**\n * Format a due date with context (Today, Tomorrow, Overdue, etc.)\n */\nexport function formatDueDate(dueDate: string | null): {\n text: string\n isOverdue: boolean\n} {\n if (!dueDate) return { text: '', isOverdue: false }\n\n const due = new Date(dueDate)\n const today = new Date()\n today.setHours(0, 0, 0, 0)\n\n const tomorrow = new Date(today)\n tomorrow.setDate(tomorrow.getDate() + 1)\n\n const dueDay = new Date(due)\n dueDay.setHours(0, 0, 0, 0)\n\n const isOverdue = dueDay < today\n\n if (dueDay.getTime() === today.getTime()) {\n return { text: 'Today', isOverdue: false }\n } else if (dueDay.getTime() === tomorrow.getTime()) {\n return { text: 'Tomorrow', isOverdue: false }\n } else if (isOverdue) {\n const daysAgo = Math.ceil(\n (today.getTime() - dueDay.getTime()) / (1000 * 60 * 60 * 24)\n )\n return { text: `${daysAgo}d overdue`, isOverdue: true }\n } else {\n return {\n text: due.toLocaleDateString('en-US', { month: 'short', day: 'numeric' }),\n isOverdue: false,\n }\n }\n}\n\n/**\n * Truncate a string with ellipsis\n * @example truncate(\"Hello World\", 5) => \"Hello...\"\n */\nexport function truncate(str: string, maxLength: number): string {\n if (str.length <= maxLength) return str\n return str.slice(0, maxLength) + '...'\n}\n\n/**\n * Extract repo name from GitHub URL\n * @example getRepoName(\"https://github.com/owner/repo\") => \"owner/repo\"\n */\nexport function getRepoName(url: string): string {\n const match = url.match(/github\\.com\\/(.+)$/)\n return match ? match[1] : url\n}\n\n"],"mappings":";AAiBA,SAAS,YAAY;;;ACPd,SAAS,WAAW,SAAyB;AAClD,QAAM,OAAO,KAAK,MAAM,UAAU,EAAE;AACpC,QAAM,OAAO,UAAU;AACvB,SAAO,GAAG,KAAK,SAAS,EAAE,SAAS,GAAG,GAAG,CAAC,IAAI,KAAK,SAAS,EAAE,SAAS,GAAG,GAAG,CAAC;AAChF;;;ADsCO,IAAM,kBAAkB,KAAkB,MAAM;AAMhD,IAAM,oBAAoB,KAAa,KAAK,EAAE;AAK9C,IAAM,qBAAqB,KAAa,CAAC;AAKzC,IAAM,oBAAoB,KAA2B,IAAI;AAUzD,IAAM,uBAAuB,KAAK,CAAC,QAAQ;AAChD,QAAM,SAAS,IAAI,iBAAiB;AACpC,QAAM,UAAU,IAAI,kBAAkB;AACtC,SAAO,KAAK,IAAI,GAAG,SAAS,OAAO;AACrC,CAAC;AASM,IAAM,eAAe,KAAK,CAAC,QAAQ;AACxC,QAAM,SAAS,IAAI,iBAAiB;AACpC,QAAM,UAAU,IAAI,kBAAkB;AACtC,MAAI,WAAW,EAAG,QAAO;AACzB,SAAO,KAAK,IAAI,GAAG,UAAU,MAAM;AACrC,CAAC;AAMM,IAAM,yBAAyB,KAAK,CAAC,QAAQ;AAClD,SAAO,WAAW,IAAI,oBAAoB,CAAC;AAC7C,CAAC;AAMM,IAAM,uBAAuB,KAAK,CAAC,QAAQ;AAChD,SAAO,WAAW,IAAI,kBAAkB,CAAC;AAC3C,CAAC;AAMM,IAAM,sBAAsB,KAAK,CAAC,QAAQ;AAC/C,SAAO,IAAI,YAAY,IAAI;AAC7B,CAAC;","names":[]}
@@ -11,10 +11,62 @@ declare const FREQUENCIES: readonly ["monthly", "yearly", "6-monthly", "weekly",
11
11
  type Frequency = (typeof FREQUENCIES)[number];
12
12
  declare const FREQUENCY_LABELS: Record<Frequency, string>;
13
13
  declare const FREQUENCY_MULTIPLIERS: Record<Frequency, number>;
14
+ /**
15
+ * Frequency options for dropdowns/toggle groups
16
+ * Format: { value: Frequency, label: string }
17
+ */
18
+ declare const FREQUENCY_OPTIONS: ({
19
+ value: "monthly";
20
+ label: string;
21
+ } | {
22
+ value: "yearly";
23
+ label: string;
24
+ } | {
25
+ value: "6-monthly";
26
+ label: string;
27
+ } | {
28
+ value: "weekly";
29
+ label: string;
30
+ } | {
31
+ value: "one-time";
32
+ label: string;
33
+ })[];
14
34
  declare const DEFAULT_FOCUS_DURATIONS: readonly [15, 25, 30, 45, 60, 90];
15
35
  type FocusDuration = (typeof DEFAULT_FOCUS_DURATIONS)[number];
16
36
  declare const FOCUS_STATUS: readonly ["active", "completed", "abandoned"];
17
37
  type FocusStatus = (typeof FOCUS_STATUS)[number];
38
+ declare const HEALTH_FREQUENCY_TYPES: readonly ["daily", "specific_days", "times_per_week", "times_per_month"];
39
+ declare const HEALTH_FREQUENCY_LABELS: Record<string, string>;
40
+ declare const DAY_OPTIONS: readonly [{
41
+ readonly value: 0;
42
+ readonly label: "Sun";
43
+ }, {
44
+ readonly value: 1;
45
+ readonly label: "Mon";
46
+ }, {
47
+ readonly value: 2;
48
+ readonly label: "Tue";
49
+ }, {
50
+ readonly value: 3;
51
+ readonly label: "Wed";
52
+ }, {
53
+ readonly value: 4;
54
+ readonly label: "Thu";
55
+ }, {
56
+ readonly value: 5;
57
+ readonly label: "Fri";
58
+ }, {
59
+ readonly value: 6;
60
+ readonly label: "Sat";
61
+ }];
62
+ /**
63
+ * Preset colors for categories, labels, and other UI elements
64
+ */
65
+ declare const PRESET_COLORS: string[];
66
+ /**
67
+ * Preset icons/emojis for categories and UI elements
68
+ */
69
+ declare const PRESET_ICONS: string[];
18
70
  declare const LINEAR_PRIORITIES: readonly [0, 1, 2, 3, 4];
19
71
  type LinearPriorityValue = (typeof LINEAR_PRIORITIES)[number];
20
72
  declare const LINEAR_PRIORITY_COLORS: Record<LinearPriorityValue, string>;
@@ -39,4 +91,4 @@ declare const SETTING_KEYS: {
39
91
  };
40
92
  type SettingKey = (typeof SETTING_KEYS)[keyof typeof SETTING_KEYS];
41
93
 
42
- export { API_URLS, CLOUD_AGENT_STATUSES, CLOUD_AGENT_STATUS_COLORS, CLOUD_AGENT_STATUS_EMOJI, CURRENCIES, CURRENCY_NAMES, CURRENCY_SYMBOLS, type Currency, DEFAULT_FOCUS_DURATIONS, FOCUS_STATUS, FREQUENCIES, FREQUENCY_LABELS, FREQUENCY_MULTIPLIERS, type FocusDuration, type FocusStatus, type Frequency, LINEAR_PRIORITIES, LINEAR_PRIORITY_COLORS, type LinearPriorityValue, SETTING_KEYS, type SettingKey };
94
+ export { API_URLS, CLOUD_AGENT_STATUSES, CLOUD_AGENT_STATUS_COLORS, CLOUD_AGENT_STATUS_EMOJI, CURRENCIES, CURRENCY_NAMES, CURRENCY_SYMBOLS, type Currency, DAY_OPTIONS, DEFAULT_FOCUS_DURATIONS, FOCUS_STATUS, FREQUENCIES, FREQUENCY_LABELS, FREQUENCY_MULTIPLIERS, FREQUENCY_OPTIONS, type FocusDuration, type FocusStatus, type Frequency, HEALTH_FREQUENCY_LABELS, HEALTH_FREQUENCY_TYPES, LINEAR_PRIORITIES, LINEAR_PRIORITY_COLORS, type LinearPriorityValue, PRESET_COLORS, PRESET_ICONS, SETTING_KEYS, type SettingKey };
@@ -11,10 +11,62 @@ declare const FREQUENCIES: readonly ["monthly", "yearly", "6-monthly", "weekly",
11
11
  type Frequency = (typeof FREQUENCIES)[number];
12
12
  declare const FREQUENCY_LABELS: Record<Frequency, string>;
13
13
  declare const FREQUENCY_MULTIPLIERS: Record<Frequency, number>;
14
+ /**
15
+ * Frequency options for dropdowns/toggle groups
16
+ * Format: { value: Frequency, label: string }
17
+ */
18
+ declare const FREQUENCY_OPTIONS: ({
19
+ value: "monthly";
20
+ label: string;
21
+ } | {
22
+ value: "yearly";
23
+ label: string;
24
+ } | {
25
+ value: "6-monthly";
26
+ label: string;
27
+ } | {
28
+ value: "weekly";
29
+ label: string;
30
+ } | {
31
+ value: "one-time";
32
+ label: string;
33
+ })[];
14
34
  declare const DEFAULT_FOCUS_DURATIONS: readonly [15, 25, 30, 45, 60, 90];
15
35
  type FocusDuration = (typeof DEFAULT_FOCUS_DURATIONS)[number];
16
36
  declare const FOCUS_STATUS: readonly ["active", "completed", "abandoned"];
17
37
  type FocusStatus = (typeof FOCUS_STATUS)[number];
38
+ declare const HEALTH_FREQUENCY_TYPES: readonly ["daily", "specific_days", "times_per_week", "times_per_month"];
39
+ declare const HEALTH_FREQUENCY_LABELS: Record<string, string>;
40
+ declare const DAY_OPTIONS: readonly [{
41
+ readonly value: 0;
42
+ readonly label: "Sun";
43
+ }, {
44
+ readonly value: 1;
45
+ readonly label: "Mon";
46
+ }, {
47
+ readonly value: 2;
48
+ readonly label: "Tue";
49
+ }, {
50
+ readonly value: 3;
51
+ readonly label: "Wed";
52
+ }, {
53
+ readonly value: 4;
54
+ readonly label: "Thu";
55
+ }, {
56
+ readonly value: 5;
57
+ readonly label: "Fri";
58
+ }, {
59
+ readonly value: 6;
60
+ readonly label: "Sat";
61
+ }];
62
+ /**
63
+ * Preset colors for categories, labels, and other UI elements
64
+ */
65
+ declare const PRESET_COLORS: string[];
66
+ /**
67
+ * Preset icons/emojis for categories and UI elements
68
+ */
69
+ declare const PRESET_ICONS: string[];
18
70
  declare const LINEAR_PRIORITIES: readonly [0, 1, 2, 3, 4];
19
71
  type LinearPriorityValue = (typeof LINEAR_PRIORITIES)[number];
20
72
  declare const LINEAR_PRIORITY_COLORS: Record<LinearPriorityValue, string>;
@@ -39,4 +91,4 @@ declare const SETTING_KEYS: {
39
91
  };
40
92
  type SettingKey = (typeof SETTING_KEYS)[keyof typeof SETTING_KEYS];
41
93
 
42
- export { API_URLS, CLOUD_AGENT_STATUSES, CLOUD_AGENT_STATUS_COLORS, CLOUD_AGENT_STATUS_EMOJI, CURRENCIES, CURRENCY_NAMES, CURRENCY_SYMBOLS, type Currency, DEFAULT_FOCUS_DURATIONS, FOCUS_STATUS, FREQUENCIES, FREQUENCY_LABELS, FREQUENCY_MULTIPLIERS, type FocusDuration, type FocusStatus, type Frequency, LINEAR_PRIORITIES, LINEAR_PRIORITY_COLORS, type LinearPriorityValue, SETTING_KEYS, type SettingKey };
94
+ export { API_URLS, CLOUD_AGENT_STATUSES, CLOUD_AGENT_STATUS_COLORS, CLOUD_AGENT_STATUS_EMOJI, CURRENCIES, CURRENCY_NAMES, CURRENCY_SYMBOLS, type Currency, DAY_OPTIONS, DEFAULT_FOCUS_DURATIONS, FOCUS_STATUS, FREQUENCIES, FREQUENCY_LABELS, FREQUENCY_MULTIPLIERS, FREQUENCY_OPTIONS, type FocusDuration, type FocusStatus, type Frequency, HEALTH_FREQUENCY_LABELS, HEALTH_FREQUENCY_TYPES, LINEAR_PRIORITIES, LINEAR_PRIORITY_COLORS, type LinearPriorityValue, PRESET_COLORS, PRESET_ICONS, SETTING_KEYS, type SettingKey };
@@ -27,13 +27,19 @@ __export(constants_exports, {
27
27
  CURRENCIES: () => CURRENCIES,
28
28
  CURRENCY_NAMES: () => CURRENCY_NAMES,
29
29
  CURRENCY_SYMBOLS: () => CURRENCY_SYMBOLS,
30
+ DAY_OPTIONS: () => DAY_OPTIONS,
30
31
  DEFAULT_FOCUS_DURATIONS: () => DEFAULT_FOCUS_DURATIONS,
31
32
  FOCUS_STATUS: () => FOCUS_STATUS,
32
33
  FREQUENCIES: () => FREQUENCIES,
33
34
  FREQUENCY_LABELS: () => FREQUENCY_LABELS,
34
35
  FREQUENCY_MULTIPLIERS: () => FREQUENCY_MULTIPLIERS,
36
+ FREQUENCY_OPTIONS: () => FREQUENCY_OPTIONS,
37
+ HEALTH_FREQUENCY_LABELS: () => HEALTH_FREQUENCY_LABELS,
38
+ HEALTH_FREQUENCY_TYPES: () => HEALTH_FREQUENCY_TYPES,
35
39
  LINEAR_PRIORITIES: () => LINEAR_PRIORITIES,
36
40
  LINEAR_PRIORITY_COLORS: () => LINEAR_PRIORITY_COLORS,
41
+ PRESET_COLORS: () => PRESET_COLORS,
42
+ PRESET_ICONS: () => PRESET_ICONS,
37
43
  SETTING_KEYS: () => SETTING_KEYS
38
44
  });
39
45
  module.exports = __toCommonJS(constants_exports);
@@ -71,8 +77,98 @@ var FREQUENCY_MULTIPLIERS = {
71
77
  weekly: 52,
72
78
  "one-time": 1
73
79
  };
80
+ var FREQUENCY_OPTIONS = [
81
+ { value: "monthly", label: "Monthly" },
82
+ { value: "yearly", label: "Yearly" },
83
+ { value: "6-monthly", label: "Every 6 Months" },
84
+ { value: "weekly", label: "Weekly" },
85
+ { value: "one-time", label: "One Time" }
86
+ ];
74
87
  var DEFAULT_FOCUS_DURATIONS = [15, 25, 30, 45, 60, 90];
75
88
  var FOCUS_STATUS = ["active", "completed", "abandoned"];
89
+ var HEALTH_FREQUENCY_TYPES = [
90
+ "daily",
91
+ "specific_days",
92
+ "times_per_week",
93
+ "times_per_month"
94
+ ];
95
+ var HEALTH_FREQUENCY_LABELS = {
96
+ daily: "Daily",
97
+ specific_days: "Specific Days",
98
+ times_per_week: "Times per Week",
99
+ times_per_month: "Times per Month"
100
+ };
101
+ var DAY_OPTIONS = [
102
+ { value: 0, label: "Sun" },
103
+ { value: 1, label: "Mon" },
104
+ { value: 2, label: "Tue" },
105
+ { value: 3, label: "Wed" },
106
+ { value: 4, label: "Thu" },
107
+ { value: 5, label: "Fri" },
108
+ { value: 6, label: "Sat" }
109
+ ];
110
+ var PRESET_COLORS = [
111
+ "#10B981",
112
+ // Emerald
113
+ "#3B82F6",
114
+ // Blue
115
+ "#F59E0B",
116
+ // Amber
117
+ "#EF4444",
118
+ // Red
119
+ "#8B5CF6",
120
+ // Purple
121
+ "#EC4899",
122
+ // Pink
123
+ "#14B8A6",
124
+ // Teal
125
+ "#F97316",
126
+ // Orange
127
+ "#6366F1",
128
+ // Indigo
129
+ "#84CC16"
130
+ // Lime
131
+ ];
132
+ var PRESET_ICONS = [
133
+ "\u{1F4DD}",
134
+ // Writing/Notes
135
+ "\u{1F4BB}",
136
+ // Coding/Tech
137
+ "\u{1F3A8}",
138
+ // Design/Art
139
+ "\u{1F4CA}",
140
+ // Analytics/Data
141
+ "\u{1F527}",
142
+ // Tools/Settings
143
+ "\u{1F4DA}",
144
+ // Learning/Docs
145
+ "\u{1F4A1}",
146
+ // Ideas/Lightbulb
147
+ "\u{1F680}",
148
+ // Launch/Start
149
+ "\u26A1",
150
+ // Fast/Energy
151
+ "\u{1F3AF}",
152
+ // Target/Goal
153
+ "\u{1F48A}",
154
+ // Health/Medicine
155
+ "\u{1F957}",
156
+ // Food/Diet
157
+ "\u{1F4A7}",
158
+ // Water/Hydration
159
+ "\u{1F3C3}",
160
+ // Exercise/Running
161
+ "\u{1F634}",
162
+ // Sleep/Rest
163
+ "\u{1F9D8}",
164
+ // Meditation/Mindfulness
165
+ "\u{1F4AA}",
166
+ // Strength/Fitness
167
+ "\u{1F34E}",
168
+ // Health/Food
169
+ "\u{1F517}"
170
+ // Links/Connections
171
+ ];
76
172
  var LINEAR_PRIORITIES = [0, 1, 2, 3, 4];
77
173
  var LINEAR_PRIORITY_COLORS = {
78
174
  0: "#6b7280",
@@ -135,13 +231,19 @@ var SETTING_KEYS = {
135
231
  CURRENCIES,
136
232
  CURRENCY_NAMES,
137
233
  CURRENCY_SYMBOLS,
234
+ DAY_OPTIONS,
138
235
  DEFAULT_FOCUS_DURATIONS,
139
236
  FOCUS_STATUS,
140
237
  FREQUENCIES,
141
238
  FREQUENCY_LABELS,
142
239
  FREQUENCY_MULTIPLIERS,
240
+ FREQUENCY_OPTIONS,
241
+ HEALTH_FREQUENCY_LABELS,
242
+ HEALTH_FREQUENCY_TYPES,
143
243
  LINEAR_PRIORITIES,
144
244
  LINEAR_PRIORITY_COLORS,
245
+ PRESET_COLORS,
246
+ PRESET_ICONS,
145
247
  SETTING_KEYS
146
248
  });
147
249
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/constants/index.ts"],"sourcesContent":["/**\n * Shared Constants\n *\n * Common constants used across Vanaheim apps.\n */\n\n// ============================================================================\n// Currency\n// ============================================================================\n\nexport const CURRENCIES = ['CHF', 'USD', 'EUR', 'PLN'] as const\nexport type Currency = (typeof CURRENCIES)[number]\n\nexport const CURRENCY_SYMBOLS: Record<Currency, string> = {\n CHF: 'CHF',\n USD: '$',\n EUR: '€',\n PLN: 'zł',\n}\n\nexport const CURRENCY_NAMES: Record<Currency, string> = {\n CHF: 'Swiss Franc',\n USD: 'US Dollar',\n EUR: 'Euro',\n PLN: 'Polish Złoty',\n}\n\n// ============================================================================\n// Frequency\n// ============================================================================\n\nexport const FREQUENCIES = [\n 'monthly',\n 'yearly',\n '6-monthly',\n 'weekly',\n 'one-time',\n] as const\nexport type Frequency = (typeof FREQUENCIES)[number]\n\nexport const FREQUENCY_LABELS: Record<Frequency, string> = {\n monthly: 'Monthly',\n yearly: 'Yearly',\n '6-monthly': 'Every 6 Months',\n weekly: 'Weekly',\n 'one-time': 'One Time',\n}\n\nexport const FREQUENCY_MULTIPLIERS: Record<Frequency, number> = {\n monthly: 12,\n yearly: 1,\n '6-monthly': 2,\n weekly: 52,\n 'one-time': 1,\n}\n\n// ============================================================================\n// Focus\n// ============================================================================\n\nexport const DEFAULT_FOCUS_DURATIONS = [15, 25, 30, 45, 60, 90] as const\nexport type FocusDuration = (typeof DEFAULT_FOCUS_DURATIONS)[number]\n\nexport const FOCUS_STATUS = ['active', 'completed', 'abandoned'] as const\nexport type FocusStatus = (typeof FOCUS_STATUS)[number]\n\n// ============================================================================\n// Linear\n// ============================================================================\n\nexport const LINEAR_PRIORITIES = [0, 1, 2, 3, 4] as const\nexport type LinearPriorityValue = (typeof LINEAR_PRIORITIES)[number]\n\nexport const LINEAR_PRIORITY_COLORS: Record<LinearPriorityValue, string> = {\n 0: '#6b7280', // No priority - gray\n 1: '#ef4444', // Urgent - red\n 2: '#f97316', // High - orange\n 3: '#eab308', // Medium - yellow\n 4: '#3b82f6', // Low - blue\n}\n\n// ============================================================================\n// Cloud Agents\n// ============================================================================\n\nexport const CLOUD_AGENT_STATUSES = [\n 'CREATING',\n 'RUNNING',\n 'FINISHED',\n 'FAILED',\n 'CANCELLED',\n] as const\n\nexport const CLOUD_AGENT_STATUS_EMOJI: Record<string, string> = {\n CREATING: '🔨',\n RUNNING: '⏳',\n FINISHED: '✅',\n FAILED: '❌',\n CANCELLED: '🚫',\n}\n\nexport const CLOUD_AGENT_STATUS_COLORS: Record<string, string> = {\n CREATING: '#3b82f6',\n RUNNING: '#3b82f6',\n FINISHED: '#10b981',\n FAILED: '#ef4444',\n CANCELLED: '#6b7280',\n}\n\n// ============================================================================\n// API URLs\n// ============================================================================\n\nexport const API_URLS = {\n CURSOR_CLOUD: 'https://api.cursor.com',\n LINEAR_GRAPHQL: 'https://api.linear.app/graphql',\n} as const\n\n// ============================================================================\n// Settings Keys\n// ============================================================================\n\nexport const SETTING_KEYS = {\n // AI\n AI_MODEL: 'ai_model',\n AI_REASONING_ENABLED: 'ai_reasoning_enabled',\n\n // API Keys\n OPENAI_API_KEY: 'openai_api_key',\n ANTHROPIC_API_KEY: 'anthropic_api_key',\n CURSOR_API_KEY: 'cursor_api_key',\n LINEAR_API_KEY: 'linear_api_key',\n\n // Google\n GOOGLE_CLIENT_ID: 'google_client_id',\n GOOGLE_CLIENT_SECRET: 'google_client_secret',\n GOOGLE_CALENDAR_TOKENS: 'google_calendar_tokens',\n SELECTED_CALENDAR_IDS: 'selected_calendar_ids',\n} as const\n\nexport type SettingKey = (typeof SETTING_KEYS)[keyof typeof SETTING_KEYS]\n\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAUO,IAAM,aAAa,CAAC,OAAO,OAAO,OAAO,KAAK;AAG9C,IAAM,mBAA6C;AAAA,EACxD,KAAK;AAAA,EACL,KAAK;AAAA,EACL,KAAK;AAAA,EACL,KAAK;AACP;AAEO,IAAM,iBAA2C;AAAA,EACtD,KAAK;AAAA,EACL,KAAK;AAAA,EACL,KAAK;AAAA,EACL,KAAK;AACP;AAMO,IAAM,cAAc;AAAA,EACzB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAGO,IAAM,mBAA8C;AAAA,EACzD,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,aAAa;AAAA,EACb,QAAQ;AAAA,EACR,YAAY;AACd;AAEO,IAAM,wBAAmD;AAAA,EAC9D,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,aAAa;AAAA,EACb,QAAQ;AAAA,EACR,YAAY;AACd;AAMO,IAAM,0BAA0B,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE;AAGvD,IAAM,eAAe,CAAC,UAAU,aAAa,WAAW;AAOxD,IAAM,oBAAoB,CAAC,GAAG,GAAG,GAAG,GAAG,CAAC;AAGxC,IAAM,yBAA8D;AAAA,EACzE,GAAG;AAAA;AAAA,EACH,GAAG;AAAA;AAAA,EACH,GAAG;AAAA;AAAA,EACH,GAAG;AAAA;AAAA,EACH,GAAG;AAAA;AACL;AAMO,IAAM,uBAAuB;AAAA,EAClC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEO,IAAM,2BAAmD;AAAA,EAC9D,UAAU;AAAA,EACV,SAAS;AAAA,EACT,UAAU;AAAA,EACV,QAAQ;AAAA,EACR,WAAW;AACb;AAEO,IAAM,4BAAoD;AAAA,EAC/D,UAAU;AAAA,EACV,SAAS;AAAA,EACT,UAAU;AAAA,EACV,QAAQ;AAAA,EACR,WAAW;AACb;AAMO,IAAM,WAAW;AAAA,EACtB,cAAc;AAAA,EACd,gBAAgB;AAClB;AAMO,IAAM,eAAe;AAAA;AAAA,EAE1B,UAAU;AAAA,EACV,sBAAsB;AAAA;AAAA,EAGtB,gBAAgB;AAAA,EAChB,mBAAmB;AAAA,EACnB,gBAAgB;AAAA,EAChB,gBAAgB;AAAA;AAAA,EAGhB,kBAAkB;AAAA,EAClB,sBAAsB;AAAA,EACtB,wBAAwB;AAAA,EACxB,uBAAuB;AACzB;","names":[]}
1
+ {"version":3,"sources":["../../src/constants/index.ts"],"sourcesContent":["/**\n * Shared Constants\n *\n * Common constants used across Vanaheim apps.\n */\n\n// ============================================================================\n// Currency\n// ============================================================================\n\nexport const CURRENCIES = [\"CHF\", \"USD\", \"EUR\", \"PLN\"] as const;\nexport type Currency = (typeof CURRENCIES)[number];\n\nexport const CURRENCY_SYMBOLS: Record<Currency, string> = {\n CHF: \"CHF\",\n USD: \"$\",\n EUR: \"€\",\n PLN: \"zł\",\n};\n\nexport const CURRENCY_NAMES: Record<Currency, string> = {\n CHF: \"Swiss Franc\",\n USD: \"US Dollar\",\n EUR: \"Euro\",\n PLN: \"Polish Złoty\",\n};\n\n// ============================================================================\n// Frequency\n// ============================================================================\n\nexport const FREQUENCIES = [\n \"monthly\",\n \"yearly\",\n \"6-monthly\",\n \"weekly\",\n \"one-time\",\n] as const;\nexport type Frequency = (typeof FREQUENCIES)[number];\n\nexport const FREQUENCY_LABELS: Record<Frequency, string> = {\n monthly: \"Monthly\",\n yearly: \"Yearly\",\n \"6-monthly\": \"Every 6 Months\",\n weekly: \"Weekly\",\n \"one-time\": \"One Time\",\n};\n\nexport const FREQUENCY_MULTIPLIERS: Record<Frequency, number> = {\n monthly: 12,\n yearly: 1,\n \"6-monthly\": 2,\n weekly: 52,\n \"one-time\": 1,\n};\n\n/**\n * Frequency options for dropdowns/toggle groups\n * Format: { value: Frequency, label: string }\n */\nexport const FREQUENCY_OPTIONS = [\n { value: \"monthly\" as const, label: \"Monthly\" },\n { value: \"yearly\" as const, label: \"Yearly\" },\n { value: \"6-monthly\" as const, label: \"Every 6 Months\" },\n { value: \"weekly\" as const, label: \"Weekly\" },\n { value: \"one-time\" as const, label: \"One Time\" },\n];\n\n// ============================================================================\n// Focus\n// ============================================================================\n\nexport const DEFAULT_FOCUS_DURATIONS = [15, 25, 30, 45, 60, 90] as const;\nexport type FocusDuration = (typeof DEFAULT_FOCUS_DURATIONS)[number];\n\nexport const FOCUS_STATUS = [\"active\", \"completed\", \"abandoned\"] as const;\nexport type FocusStatus = (typeof FOCUS_STATUS)[number];\n\n// ============================================================================\n// Health & Habits\n// ============================================================================\n\nexport const HEALTH_FREQUENCY_TYPES = [\n \"daily\",\n \"specific_days\",\n \"times_per_week\",\n \"times_per_month\",\n] as const;\n\nexport const HEALTH_FREQUENCY_LABELS: Record<string, string> = {\n daily: \"Daily\",\n specific_days: \"Specific Days\",\n times_per_week: \"Times per Week\",\n times_per_month: \"Times per Month\",\n};\n\nexport const DAY_OPTIONS = [\n { value: 0, label: \"Sun\" },\n { value: 1, label: \"Mon\" },\n { value: 2, label: \"Tue\" },\n { value: 3, label: \"Wed\" },\n { value: 4, label: \"Thu\" },\n { value: 5, label: \"Fri\" },\n { value: 6, label: \"Sat\" },\n] as const;\n\n/**\n * Preset colors for categories, labels, and other UI elements\n */\nexport const PRESET_COLORS = [\n \"#10B981\", // Emerald\n \"#3B82F6\", // Blue\n \"#F59E0B\", // Amber\n \"#EF4444\", // Red\n \"#8B5CF6\", // Purple\n \"#EC4899\", // Pink\n \"#14B8A6\", // Teal\n \"#F97316\", // Orange\n \"#6366F1\", // Indigo\n \"#84CC16\", // Lime\n];\n\n/**\n * Preset icons/emojis for categories and UI elements\n */\nexport const PRESET_ICONS = [\n \"📝\", // Writing/Notes\n \"💻\", // Coding/Tech\n \"🎨\", // Design/Art\n \"📊\", // Analytics/Data\n \"🔧\", // Tools/Settings\n \"📚\", // Learning/Docs\n \"💡\", // Ideas/Lightbulb\n \"🚀\", // Launch/Start\n \"⚡\", // Fast/Energy\n \"🎯\", // Target/Goal\n \"💊\", // Health/Medicine\n \"🥗\", // Food/Diet\n \"💧\", // Water/Hydration\n \"🏃\", // Exercise/Running\n \"😴\", // Sleep/Rest\n \"🧘\", // Meditation/Mindfulness\n \"💪\", // Strength/Fitness\n \"🍎\", // Health/Food\n \"🔗\", // Links/Connections\n];\n\n// ============================================================================\n// Linear\n// ============================================================================\n\nexport const LINEAR_PRIORITIES = [0, 1, 2, 3, 4] as const;\nexport type LinearPriorityValue = (typeof LINEAR_PRIORITIES)[number];\n\nexport const LINEAR_PRIORITY_COLORS: Record<LinearPriorityValue, string> = {\n 0: \"#6b7280\", // No priority - gray\n 1: \"#ef4444\", // Urgent - red\n 2: \"#f97316\", // High - orange\n 3: \"#eab308\", // Medium - yellow\n 4: \"#3b82f6\", // Low - blue\n};\n\n// ============================================================================\n// Cloud Agents\n// ============================================================================\n\nexport const CLOUD_AGENT_STATUSES = [\n \"CREATING\",\n \"RUNNING\",\n \"FINISHED\",\n \"FAILED\",\n \"CANCELLED\",\n] as const;\n\nexport const CLOUD_AGENT_STATUS_EMOJI: Record<string, string> = {\n CREATING: \"🔨\",\n RUNNING: \"⏳\",\n FINISHED: \"✅\",\n FAILED: \"❌\",\n CANCELLED: \"🚫\",\n};\n\nexport const CLOUD_AGENT_STATUS_COLORS: Record<string, string> = {\n CREATING: \"#3b82f6\",\n RUNNING: \"#3b82f6\",\n FINISHED: \"#10b981\",\n FAILED: \"#ef4444\",\n CANCELLED: \"#6b7280\",\n};\n\n// ============================================================================\n// API URLs\n// ============================================================================\n\nexport const API_URLS = {\n CURSOR_CLOUD: \"https://api.cursor.com\",\n LINEAR_GRAPHQL: \"https://api.linear.app/graphql\",\n} as const;\n\n// ============================================================================\n// Settings Keys\n// ============================================================================\n\nexport const SETTING_KEYS = {\n // AI\n AI_MODEL: \"ai_model\",\n AI_REASONING_ENABLED: \"ai_reasoning_enabled\",\n\n // API Keys\n OPENAI_API_KEY: \"openai_api_key\",\n ANTHROPIC_API_KEY: \"anthropic_api_key\",\n CURSOR_API_KEY: \"cursor_api_key\",\n LINEAR_API_KEY: \"linear_api_key\",\n\n // Google\n GOOGLE_CLIENT_ID: \"google_client_id\",\n GOOGLE_CLIENT_SECRET: \"google_client_secret\",\n GOOGLE_CALENDAR_TOKENS: \"google_calendar_tokens\",\n SELECTED_CALENDAR_IDS: \"selected_calendar_ids\",\n} as const;\n\nexport type SettingKey = (typeof SETTING_KEYS)[keyof typeof SETTING_KEYS];\n"],"mappings":"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","names":[]}
@@ -33,8 +33,98 @@ var FREQUENCY_MULTIPLIERS = {
33
33
  weekly: 52,
34
34
  "one-time": 1
35
35
  };
36
+ var FREQUENCY_OPTIONS = [
37
+ { value: "monthly", label: "Monthly" },
38
+ { value: "yearly", label: "Yearly" },
39
+ { value: "6-monthly", label: "Every 6 Months" },
40
+ { value: "weekly", label: "Weekly" },
41
+ { value: "one-time", label: "One Time" }
42
+ ];
36
43
  var DEFAULT_FOCUS_DURATIONS = [15, 25, 30, 45, 60, 90];
37
44
  var FOCUS_STATUS = ["active", "completed", "abandoned"];
45
+ var HEALTH_FREQUENCY_TYPES = [
46
+ "daily",
47
+ "specific_days",
48
+ "times_per_week",
49
+ "times_per_month"
50
+ ];
51
+ var HEALTH_FREQUENCY_LABELS = {
52
+ daily: "Daily",
53
+ specific_days: "Specific Days",
54
+ times_per_week: "Times per Week",
55
+ times_per_month: "Times per Month"
56
+ };
57
+ var DAY_OPTIONS = [
58
+ { value: 0, label: "Sun" },
59
+ { value: 1, label: "Mon" },
60
+ { value: 2, label: "Tue" },
61
+ { value: 3, label: "Wed" },
62
+ { value: 4, label: "Thu" },
63
+ { value: 5, label: "Fri" },
64
+ { value: 6, label: "Sat" }
65
+ ];
66
+ var PRESET_COLORS = [
67
+ "#10B981",
68
+ // Emerald
69
+ "#3B82F6",
70
+ // Blue
71
+ "#F59E0B",
72
+ // Amber
73
+ "#EF4444",
74
+ // Red
75
+ "#8B5CF6",
76
+ // Purple
77
+ "#EC4899",
78
+ // Pink
79
+ "#14B8A6",
80
+ // Teal
81
+ "#F97316",
82
+ // Orange
83
+ "#6366F1",
84
+ // Indigo
85
+ "#84CC16"
86
+ // Lime
87
+ ];
88
+ var PRESET_ICONS = [
89
+ "\u{1F4DD}",
90
+ // Writing/Notes
91
+ "\u{1F4BB}",
92
+ // Coding/Tech
93
+ "\u{1F3A8}",
94
+ // Design/Art
95
+ "\u{1F4CA}",
96
+ // Analytics/Data
97
+ "\u{1F527}",
98
+ // Tools/Settings
99
+ "\u{1F4DA}",
100
+ // Learning/Docs
101
+ "\u{1F4A1}",
102
+ // Ideas/Lightbulb
103
+ "\u{1F680}",
104
+ // Launch/Start
105
+ "\u26A1",
106
+ // Fast/Energy
107
+ "\u{1F3AF}",
108
+ // Target/Goal
109
+ "\u{1F48A}",
110
+ // Health/Medicine
111
+ "\u{1F957}",
112
+ // Food/Diet
113
+ "\u{1F4A7}",
114
+ // Water/Hydration
115
+ "\u{1F3C3}",
116
+ // Exercise/Running
117
+ "\u{1F634}",
118
+ // Sleep/Rest
119
+ "\u{1F9D8}",
120
+ // Meditation/Mindfulness
121
+ "\u{1F4AA}",
122
+ // Strength/Fitness
123
+ "\u{1F34E}",
124
+ // Health/Food
125
+ "\u{1F517}"
126
+ // Links/Connections
127
+ ];
38
128
  var LINEAR_PRIORITIES = [0, 1, 2, 3, 4];
39
129
  var LINEAR_PRIORITY_COLORS = {
40
130
  0: "#6b7280",
@@ -96,13 +186,19 @@ export {
96
186
  CURRENCIES,
97
187
  CURRENCY_NAMES,
98
188
  CURRENCY_SYMBOLS,
189
+ DAY_OPTIONS,
99
190
  DEFAULT_FOCUS_DURATIONS,
100
191
  FOCUS_STATUS,
101
192
  FREQUENCIES,
102
193
  FREQUENCY_LABELS,
103
194
  FREQUENCY_MULTIPLIERS,
195
+ FREQUENCY_OPTIONS,
196
+ HEALTH_FREQUENCY_LABELS,
197
+ HEALTH_FREQUENCY_TYPES,
104
198
  LINEAR_PRIORITIES,
105
199
  LINEAR_PRIORITY_COLORS,
200
+ PRESET_COLORS,
201
+ PRESET_ICONS,
106
202
  SETTING_KEYS
107
203
  };
108
204
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/constants/index.ts"],"sourcesContent":["/**\n * Shared Constants\n *\n * Common constants used across Vanaheim apps.\n */\n\n// ============================================================================\n// Currency\n// ============================================================================\n\nexport const CURRENCIES = ['CHF', 'USD', 'EUR', 'PLN'] as const\nexport type Currency = (typeof CURRENCIES)[number]\n\nexport const CURRENCY_SYMBOLS: Record<Currency, string> = {\n CHF: 'CHF',\n USD: '$',\n EUR: '€',\n PLN: 'zł',\n}\n\nexport const CURRENCY_NAMES: Record<Currency, string> = {\n CHF: 'Swiss Franc',\n USD: 'US Dollar',\n EUR: 'Euro',\n PLN: 'Polish Złoty',\n}\n\n// ============================================================================\n// Frequency\n// ============================================================================\n\nexport const FREQUENCIES = [\n 'monthly',\n 'yearly',\n '6-monthly',\n 'weekly',\n 'one-time',\n] as const\nexport type Frequency = (typeof FREQUENCIES)[number]\n\nexport const FREQUENCY_LABELS: Record<Frequency, string> = {\n monthly: 'Monthly',\n yearly: 'Yearly',\n '6-monthly': 'Every 6 Months',\n weekly: 'Weekly',\n 'one-time': 'One Time',\n}\n\nexport const FREQUENCY_MULTIPLIERS: Record<Frequency, number> = {\n monthly: 12,\n yearly: 1,\n '6-monthly': 2,\n weekly: 52,\n 'one-time': 1,\n}\n\n// ============================================================================\n// Focus\n// ============================================================================\n\nexport const DEFAULT_FOCUS_DURATIONS = [15, 25, 30, 45, 60, 90] as const\nexport type FocusDuration = (typeof DEFAULT_FOCUS_DURATIONS)[number]\n\nexport const FOCUS_STATUS = ['active', 'completed', 'abandoned'] as const\nexport type FocusStatus = (typeof FOCUS_STATUS)[number]\n\n// ============================================================================\n// Linear\n// ============================================================================\n\nexport const LINEAR_PRIORITIES = [0, 1, 2, 3, 4] as const\nexport type LinearPriorityValue = (typeof LINEAR_PRIORITIES)[number]\n\nexport const LINEAR_PRIORITY_COLORS: Record<LinearPriorityValue, string> = {\n 0: '#6b7280', // No priority - gray\n 1: '#ef4444', // Urgent - red\n 2: '#f97316', // High - orange\n 3: '#eab308', // Medium - yellow\n 4: '#3b82f6', // Low - blue\n}\n\n// ============================================================================\n// Cloud Agents\n// ============================================================================\n\nexport const CLOUD_AGENT_STATUSES = [\n 'CREATING',\n 'RUNNING',\n 'FINISHED',\n 'FAILED',\n 'CANCELLED',\n] as const\n\nexport const CLOUD_AGENT_STATUS_EMOJI: Record<string, string> = {\n CREATING: '🔨',\n RUNNING: '⏳',\n FINISHED: '✅',\n FAILED: '❌',\n CANCELLED: '🚫',\n}\n\nexport const CLOUD_AGENT_STATUS_COLORS: Record<string, string> = {\n CREATING: '#3b82f6',\n RUNNING: '#3b82f6',\n FINISHED: '#10b981',\n FAILED: '#ef4444',\n CANCELLED: '#6b7280',\n}\n\n// ============================================================================\n// API URLs\n// ============================================================================\n\nexport const API_URLS = {\n CURSOR_CLOUD: 'https://api.cursor.com',\n LINEAR_GRAPHQL: 'https://api.linear.app/graphql',\n} as const\n\n// ============================================================================\n// Settings Keys\n// ============================================================================\n\nexport const SETTING_KEYS = {\n // AI\n AI_MODEL: 'ai_model',\n AI_REASONING_ENABLED: 'ai_reasoning_enabled',\n\n // API Keys\n OPENAI_API_KEY: 'openai_api_key',\n ANTHROPIC_API_KEY: 'anthropic_api_key',\n CURSOR_API_KEY: 'cursor_api_key',\n LINEAR_API_KEY: 'linear_api_key',\n\n // Google\n GOOGLE_CLIENT_ID: 'google_client_id',\n GOOGLE_CLIENT_SECRET: 'google_client_secret',\n GOOGLE_CALENDAR_TOKENS: 'google_calendar_tokens',\n SELECTED_CALENDAR_IDS: 'selected_calendar_ids',\n} as const\n\nexport type SettingKey = (typeof SETTING_KEYS)[keyof typeof SETTING_KEYS]\n\n"],"mappings":";AAUO,IAAM,aAAa,CAAC,OAAO,OAAO,OAAO,KAAK;AAG9C,IAAM,mBAA6C;AAAA,EACxD,KAAK;AAAA,EACL,KAAK;AAAA,EACL,KAAK;AAAA,EACL,KAAK;AACP;AAEO,IAAM,iBAA2C;AAAA,EACtD,KAAK;AAAA,EACL,KAAK;AAAA,EACL,KAAK;AAAA,EACL,KAAK;AACP;AAMO,IAAM,cAAc;AAAA,EACzB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAGO,IAAM,mBAA8C;AAAA,EACzD,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,aAAa;AAAA,EACb,QAAQ;AAAA,EACR,YAAY;AACd;AAEO,IAAM,wBAAmD;AAAA,EAC9D,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,aAAa;AAAA,EACb,QAAQ;AAAA,EACR,YAAY;AACd;AAMO,IAAM,0BAA0B,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,EAAE;AAGvD,IAAM,eAAe,CAAC,UAAU,aAAa,WAAW;AAOxD,IAAM,oBAAoB,CAAC,GAAG,GAAG,GAAG,GAAG,CAAC;AAGxC,IAAM,yBAA8D;AAAA,EACzE,GAAG;AAAA;AAAA,EACH,GAAG;AAAA;AAAA,EACH,GAAG;AAAA;AAAA,EACH,GAAG;AAAA;AAAA,EACH,GAAG;AAAA;AACL;AAMO,IAAM,uBAAuB;AAAA,EAClC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEO,IAAM,2BAAmD;AAAA,EAC9D,UAAU;AAAA,EACV,SAAS;AAAA,EACT,UAAU;AAAA,EACV,QAAQ;AAAA,EACR,WAAW;AACb;AAEO,IAAM,4BAAoD;AAAA,EAC/D,UAAU;AAAA,EACV,SAAS;AAAA,EACT,UAAU;AAAA,EACV,QAAQ;AAAA,EACR,WAAW;AACb;AAMO,IAAM,WAAW;AAAA,EACtB,cAAc;AAAA,EACd,gBAAgB;AAClB;AAMO,IAAM,eAAe;AAAA;AAAA,EAE1B,UAAU;AAAA,EACV,sBAAsB;AAAA;AAAA,EAGtB,gBAAgB;AAAA,EAChB,mBAAmB;AAAA,EACnB,gBAAgB;AAAA,EAChB,gBAAgB;AAAA;AAAA,EAGhB,kBAAkB;AAAA,EAClB,sBAAsB;AAAA,EACtB,wBAAwB;AAAA,EACxB,uBAAuB;AACzB;","names":[]}
1
+ {"version":3,"sources":["../../src/constants/index.ts"],"sourcesContent":["/**\n * Shared Constants\n *\n * Common constants used across Vanaheim apps.\n */\n\n// ============================================================================\n// Currency\n// ============================================================================\n\nexport const CURRENCIES = [\"CHF\", \"USD\", \"EUR\", \"PLN\"] as const;\nexport type Currency = (typeof CURRENCIES)[number];\n\nexport const CURRENCY_SYMBOLS: Record<Currency, string> = {\n CHF: \"CHF\",\n USD: \"$\",\n EUR: \"€\",\n PLN: \"zł\",\n};\n\nexport const CURRENCY_NAMES: Record<Currency, string> = {\n CHF: \"Swiss Franc\",\n USD: \"US Dollar\",\n EUR: \"Euro\",\n PLN: \"Polish Złoty\",\n};\n\n// ============================================================================\n// Frequency\n// ============================================================================\n\nexport const FREQUENCIES = [\n \"monthly\",\n \"yearly\",\n \"6-monthly\",\n \"weekly\",\n \"one-time\",\n] as const;\nexport type Frequency = (typeof FREQUENCIES)[number];\n\nexport const FREQUENCY_LABELS: Record<Frequency, string> = {\n monthly: \"Monthly\",\n yearly: \"Yearly\",\n \"6-monthly\": \"Every 6 Months\",\n weekly: \"Weekly\",\n \"one-time\": \"One Time\",\n};\n\nexport const FREQUENCY_MULTIPLIERS: Record<Frequency, number> = {\n monthly: 12,\n yearly: 1,\n \"6-monthly\": 2,\n weekly: 52,\n \"one-time\": 1,\n};\n\n/**\n * Frequency options for dropdowns/toggle groups\n * Format: { value: Frequency, label: string }\n */\nexport const FREQUENCY_OPTIONS = [\n { value: \"monthly\" as const, label: \"Monthly\" },\n { value: \"yearly\" as const, label: \"Yearly\" },\n { value: \"6-monthly\" as const, label: \"Every 6 Months\" },\n { value: \"weekly\" as const, label: \"Weekly\" },\n { value: \"one-time\" as const, label: \"One Time\" },\n];\n\n// ============================================================================\n// Focus\n// ============================================================================\n\nexport const DEFAULT_FOCUS_DURATIONS = [15, 25, 30, 45, 60, 90] as const;\nexport type FocusDuration = (typeof DEFAULT_FOCUS_DURATIONS)[number];\n\nexport const FOCUS_STATUS = [\"active\", \"completed\", \"abandoned\"] as const;\nexport type FocusStatus = (typeof FOCUS_STATUS)[number];\n\n// ============================================================================\n// Health & Habits\n// ============================================================================\n\nexport const HEALTH_FREQUENCY_TYPES = [\n \"daily\",\n \"specific_days\",\n \"times_per_week\",\n \"times_per_month\",\n] as const;\n\nexport const HEALTH_FREQUENCY_LABELS: Record<string, string> = {\n daily: \"Daily\",\n specific_days: \"Specific Days\",\n times_per_week: \"Times per Week\",\n times_per_month: \"Times per Month\",\n};\n\nexport const DAY_OPTIONS = [\n { value: 0, label: \"Sun\" },\n { value: 1, label: \"Mon\" },\n { value: 2, label: \"Tue\" },\n { value: 3, label: \"Wed\" },\n { value: 4, label: \"Thu\" },\n { value: 5, label: \"Fri\" },\n { value: 6, label: \"Sat\" },\n] as const;\n\n/**\n * Preset colors for categories, labels, and other UI elements\n */\nexport const PRESET_COLORS = [\n \"#10B981\", // Emerald\n \"#3B82F6\", // Blue\n \"#F59E0B\", // Amber\n \"#EF4444\", // Red\n \"#8B5CF6\", // Purple\n \"#EC4899\", // Pink\n \"#14B8A6\", // Teal\n \"#F97316\", // Orange\n \"#6366F1\", // Indigo\n \"#84CC16\", // Lime\n];\n\n/**\n * Preset icons/emojis for categories and UI elements\n */\nexport const PRESET_ICONS = [\n \"📝\", // Writing/Notes\n \"💻\", // Coding/Tech\n \"🎨\", // Design/Art\n \"📊\", // Analytics/Data\n \"🔧\", // Tools/Settings\n \"📚\", // Learning/Docs\n \"💡\", // Ideas/Lightbulb\n \"🚀\", // Launch/Start\n \"⚡\", // Fast/Energy\n \"🎯\", // Target/Goal\n \"💊\", // Health/Medicine\n \"🥗\", // Food/Diet\n \"💧\", // Water/Hydration\n \"🏃\", // Exercise/Running\n \"😴\", // Sleep/Rest\n \"🧘\", // Meditation/Mindfulness\n \"💪\", // Strength/Fitness\n \"🍎\", // Health/Food\n \"🔗\", // Links/Connections\n];\n\n// ============================================================================\n// Linear\n// ============================================================================\n\nexport const LINEAR_PRIORITIES = [0, 1, 2, 3, 4] as const;\nexport type LinearPriorityValue = (typeof LINEAR_PRIORITIES)[number];\n\nexport const LINEAR_PRIORITY_COLORS: Record<LinearPriorityValue, string> = {\n 0: \"#6b7280\", // No priority - gray\n 1: \"#ef4444\", // Urgent - red\n 2: \"#f97316\", // High - orange\n 3: \"#eab308\", // Medium - yellow\n 4: \"#3b82f6\", // Low - blue\n};\n\n// ============================================================================\n// Cloud Agents\n// ============================================================================\n\nexport const CLOUD_AGENT_STATUSES = [\n \"CREATING\",\n \"RUNNING\",\n \"FINISHED\",\n \"FAILED\",\n \"CANCELLED\",\n] as const;\n\nexport const CLOUD_AGENT_STATUS_EMOJI: Record<string, string> = {\n CREATING: \"🔨\",\n RUNNING: \"⏳\",\n FINISHED: \"✅\",\n FAILED: \"❌\",\n CANCELLED: \"🚫\",\n};\n\nexport const CLOUD_AGENT_STATUS_COLORS: Record<string, string> = {\n CREATING: \"#3b82f6\",\n RUNNING: \"#3b82f6\",\n FINISHED: \"#10b981\",\n FAILED: \"#ef4444\",\n CANCELLED: \"#6b7280\",\n};\n\n// ============================================================================\n// API URLs\n// ============================================================================\n\nexport const API_URLS = {\n CURSOR_CLOUD: \"https://api.cursor.com\",\n LINEAR_GRAPHQL: \"https://api.linear.app/graphql\",\n} as const;\n\n// ============================================================================\n// Settings Keys\n// ============================================================================\n\nexport const SETTING_KEYS = {\n // AI\n AI_MODEL: \"ai_model\",\n AI_REASONING_ENABLED: \"ai_reasoning_enabled\",\n\n // API Keys\n OPENAI_API_KEY: \"openai_api_key\",\n ANTHROPIC_API_KEY: \"anthropic_api_key\",\n CURSOR_API_KEY: \"cursor_api_key\",\n LINEAR_API_KEY: \"linear_api_key\",\n\n // Google\n GOOGLE_CLIENT_ID: \"google_client_id\",\n GOOGLE_CLIENT_SECRET: \"google_client_secret\",\n GOOGLE_CALENDAR_TOKENS: \"google_calendar_tokens\",\n SELECTED_CALENDAR_IDS: \"selected_calendar_ids\",\n} as const;\n\nexport type SettingKey = (typeof SETTING_KEYS)[keyof typeof SETTING_KEYS];\n"],"mappings":"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","names":[]}