From 48b5002f2ff0d792954ac8c0879b350425655246 Mon Sep 17 00:00:00 2001 From: Guillermo Pages Date: Sun, 10 Aug 2025 22:30:12 +0200 Subject: [PATCH] feat: working --- README.md | 6 +- USAGE_GUIDE.md | 58 ++++++---- package.json | 2 +- src/components/calendar/Day/Day.module.scss | 5 - src/components/calendar/Day/index.tsx | 1 - src/examples/InteractiveDateRange.tsx | 112 +++++++++++--------- src/index.ts | 4 +- src/types/calendar.ts | 16 +-- src/utils/colorUtils.ts | 93 ++++++++++++---- src/utils/dateUtils.ts | 8 +- 10 files changed, 197 insertions(+), 108 deletions(-) diff --git a/README.md b/README.md index b0decda..60b2380 100644 --- a/README.md +++ b/README.md @@ -2,12 +2,12 @@ A modern, flexible, and highly customizable calendar component library for React with TypeScript support. -## 🆕 Version 1.3.0 Features +## 🆕 Version 1.4.0 Features -- 📅 **Today State in Color Schemes**: Define custom colors for today's date through color schemes +- 📅 **Today in Any State**: Define custom colors for today's date in any state (default, active, rangeStart, etc.) - ✏️ **Header Text Transform**: Custom function to transform day name display (e.g., `dayName => dayName.slice(0, 2)`) - 🌍 **International Locale Support**: Full internationalization with 50+ languages via date-fns -- 🎨 **Comprehensive Color Schemes**: Complete control over colors for every state (default, today, selecting, selected, range start/end/mid, active) and day type (weekday/weekend) +- 🎨 **Three-Dimensional Color Schemes**: Control colors by week split (weekday/weekend), relative (today/anyday), and state - 🎯 **Enhanced Weekend Support**: Distinct colors for weekends in all selection states 📖 **[View the complete Usage Guide](./USAGE_GUIDE.md)** for detailed examples of the new features! diff --git a/USAGE_GUIDE.md b/USAGE_GUIDE.md index 7ad9ce7..af08f31 100644 --- a/USAGE_GUIDE.md +++ b/USAGE_GUIDE.md @@ -71,26 +71,37 @@ Full control over colors for every state and day type: import { Year, ColorScheme } from 'react-calendario'; const colorScheme: ColorScheme = [ - // Today's date colors (highest priority) + // Today's date colors for different states { - type: 'weekday', - state: 'today', // Today if it's a weekday + weekSplit: 'weekday', + relative: 'today', + state: 'default', // Today when it's a normal weekday colors: { header: { backgroundColor: '#ffd700', color: '#000000' }, content: { backgroundColor: '#fff9e6', color: '#000000' } } }, { - type: 'weekend', - state: 'today', // Today if it's a weekend + weekSplit: 'weekday', + relative: 'today', + state: 'active', // Today when it's active/clicked colors: { - header: { backgroundColor: '#ffb347', color: '#000000' }, - content: { backgroundColor: '#fff5e6', color: '#000000' } + header: { backgroundColor: '#ffed4e', color: '#000000' }, + content: { backgroundColor: '#fff59d', color: '#000000' } } }, - // Weekday colors { - type: 'weekday', + weekSplit: 'weekday', + relative: 'today', + state: 'rangeStart', // Today when it starts a range + colors: { + header: { backgroundColor: '#ffc107', color: '#000000' }, + content: { backgroundColor: '#ffeb3b', color: '#000000' } + } + }, + // Regular weekday colors (anyday is default when relative is omitted) + { + weekSplit: 'weekday', state: 'default', // Normal weekday colors: { header: { backgroundColor: '#2c3e50', color: '#ffffff' }, @@ -98,7 +109,7 @@ const colorScheme: ColorScheme = [ } }, { - type: 'weekday', + weekSplit: 'weekday', state: 'rangeStart', // First day of selected range colors: { header: { backgroundColor: '#2980b9', color: '#ffffff' }, @@ -106,7 +117,7 @@ const colorScheme: ColorScheme = [ } }, { - type: 'weekday', + weekSplit: 'weekday', state: 'rangeMid', // Middle days of selected range colors: { header: { backgroundColor: '#5dade2', color: '#ffffff' }, @@ -116,7 +127,7 @@ const colorScheme: ColorScheme = [ // Weekend colors { - type: 'weekend', + weekSplit: 'weekend', state: 'default', // Normal weekend colors: { header: { backgroundColor: '#7f8c8d', color: '#ffffff' }, @@ -124,7 +135,7 @@ const colorScheme: ColorScheme = [ } }, { - type: 'weekend', + weekSplit: 'weekend', state: 'rangeStart', // Weekend that starts a range colors: { header: { backgroundColor: '#2980b9', color: '#ffffff' }, @@ -140,19 +151,26 @@ const colorScheme: ColorScheme = [ /> ``` -#### Available States: +#### Color Scheme Dimensions: + +**Week Split** (`weekSplit`): +- `weekday` - Monday through Friday +- `weekend` - Saturday and Sunday (or custom weekend days) + +**Relative** (`relative`, optional): +- `today` - Today's date (automatically detected) +- `anyday` - Any other date (default when omitted) + +**State** (`state`): - `default` - Normal day appearance -- `today` - Today's date (automatically detected, highest priority) -- `selected` - Day is part of a completed selection (deprecated, use `rangeMid`) -- `selecting` - Day is being hovered during selection (important for weekends!) +- `selecting` - Day is being hovered during selection - `rangeStart` - First day of a range - `rangeEnd` - Last day of a range - `rangeMid` - Middle days of a selected range - `active` - Special highlighted days (holidays, events) -#### Day Types: -- `weekday` - Monday through Friday -- `weekend` - Saturday and Sunday (or custom weekend days) +#### Backwards Compatibility: +- `type` is still supported but deprecated (use `weekSplit` instead) ## 🌍 Locale Support diff --git a/package.json b/package.json index e8617cc..6ccda12 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-calendario", - "version": "1.3.1", + "version": "1.4.1", "description": "A modern, flexible calendar component for React with TypeScript support", "type": "module", "main": "dist/index.umd.js", diff --git a/src/components/calendar/Day/Day.module.scss b/src/components/calendar/Day/Day.module.scss index 207d1cf..072d0e2 100644 --- a/src/components/calendar/Day/Day.module.scss +++ b/src/components/calendar/Day/Day.module.scss @@ -190,11 +190,6 @@ } // end implicit (midrange) { - // today state - no default styling, handled by color scheme - &.Day__Container--today { - // Today state can combine with other states - // Styling is handled through the color scheme - } // active state - inverted colors &.Day__Container--active { diff --git a/src/components/calendar/Day/index.tsx b/src/components/calendar/Day/index.tsx index be15ff9..3f5fdfa 100644 --- a/src/components/calendar/Day/index.tsx +++ b/src/components/calendar/Day/index.tsx @@ -46,7 +46,6 @@ export const Day: React.FC = ({ [styles['Day__Container--rowStart']]: variations.includes('rowStart'), [styles['Day__Container--rowEnd']]: variations.includes('rowEnd'), [styles['Day__Container--active']]: variations.includes('active'), - [styles['Day__Container--today']]: variations.includes('today'), [styles['magnify']]: magnify && (variations.includes('selected') || variations.includes('selecting')) }, styles[`Day--${headerStyle}`], diff --git a/src/examples/InteractiveDateRange.tsx b/src/examples/InteractiveDateRange.tsx index 85fc3dd..2446498 100644 --- a/src/examples/InteractiveDateRange.tsx +++ b/src/examples/InteractiveDateRange.tsx @@ -39,184 +39,200 @@ export const InteractiveDateRange: React.FC = () => { // Color schemes with proper weekend and today support const colorSchemes: Record = { ocean: [ - // Today state (highest priority) - { type: 'weekday', state: 'today', colors: { + // Today's date colors (any state) + { weekSplit: 'weekday', relative: 'today', state: 'default', colors: { header: { backgroundColor: '#ffd700', color: '#000000' }, content: { backgroundColor: '#fff9e6', color: '#000000' } }}, - { type: 'weekend', state: 'today', colors: { + { weekSplit: 'weekend', relative: 'today', state: 'default', colors: { header: { backgroundColor: '#ffb347', color: '#000000' }, content: { backgroundColor: '#fff5e6', color: '#000000' } }}, - // Weekday states - { type: 'weekday', state: 'default', colors: { + { weekSplit: 'weekday', relative: 'today', state: 'active', colors: { + header: { backgroundColor: '#ffed4e', color: '#000000' }, + content: { backgroundColor: '#fff59d', color: '#000000' } + }}, + { weekSplit: 'weekday', relative: 'today', state: 'rangeStart', colors: { + header: { backgroundColor: '#ffc107', color: '#000000' }, + content: { backgroundColor: '#ffeb3b', color: '#000000' } + }}, + // Weekday states (anyday - default when relative is omitted) + { weekSplit: 'weekday', state: 'default', colors: { header: { backgroundColor: '#006994', color: '#ffffff' }, content: { backgroundColor: '#ffffff', color: '#006994' } }}, - { type: 'weekday', state: 'selecting', colors: { + { weekSplit: 'weekday', state: 'selecting', colors: { header: { backgroundColor: '#4a90a4', color: '#ffffff' }, content: { backgroundColor: '#e8f4f8', color: '#006994' } }}, - { type: 'weekday', state: 'rangeStart', colors: { + { weekSplit: 'weekday', state: 'rangeStart', colors: { header: { backgroundColor: '#004d6f', color: '#ffffff' }, content: { backgroundColor: '#0084b4', color: '#ffffff' } }}, - { type: 'weekday', state: 'rangeEnd', colors: { + { weekSplit: 'weekday', state: 'rangeEnd', colors: { header: { backgroundColor: '#004d6f', color: '#ffffff' }, content: { backgroundColor: '#0084b4', color: '#ffffff' } }}, - { type: 'weekday', state: 'rangeMid', colors: { + { weekSplit: 'weekday', state: 'rangeMid', colors: { header: { backgroundColor: '#3ca0c8', color: '#ffffff' }, content: { backgroundColor: '#b3d9ea', color: '#004d6f' } }}, - { type: 'weekday', state: 'active', colors: { + { weekSplit: 'weekday', state: 'active', colors: { header: { backgroundColor: '#00a8e8', color: '#ffffff' }, content: { backgroundColor: '#007ea7', color: '#ffffff' } }}, // Weekend states - with subtle differentiation - { type: 'weekend', state: 'default', colors: { + { weekSplit: 'weekend', state: 'default', colors: { header: { backgroundColor: '#5c8ca3', color: '#ffffff' }, content: { backgroundColor: '#f0f6f9', color: '#3d5a6c' } }}, - { type: 'weekend', state: 'selecting', colors: { + { weekSplit: 'weekend', state: 'selecting', colors: { header: { backgroundColor: '#7aa3b8', color: '#ffffff' }, content: { backgroundColor: '#dde9f0', color: '#4a6b7c' } }}, - { type: 'weekend', state: 'rangeStart', colors: { + { weekSplit: 'weekend', state: 'rangeStart', colors: { header: { backgroundColor: '#003f5c', color: '#ffffff' }, content: { backgroundColor: '#006d94', color: '#ffffff' } }}, - { type: 'weekend', state: 'rangeEnd', colors: { + { weekSplit: 'weekend', state: 'rangeEnd', colors: { header: { backgroundColor: '#003f5c', color: '#ffffff' }, content: { backgroundColor: '#006d94', color: '#ffffff' } }}, - { type: 'weekend', state: 'rangeMid', colors: { + { weekSplit: 'weekend', state: 'rangeMid', colors: { header: { backgroundColor: '#6eb5d0', color: '#ffffff' }, content: { backgroundColor: '#cce5f0', color: '#003f5c' } }}, - { type: 'weekend', state: 'active', colors: { + { weekSplit: 'weekend', state: 'active', colors: { header: { backgroundColor: '#0096c7', color: '#ffffff' }, content: { backgroundColor: '#0077b6', color: '#ffffff' } }} ], sunset: [ - // Today state - { type: 'weekday', state: 'today', colors: { + // Today's date colors + { weekSplit: 'weekday', relative: 'today', state: 'default', colors: { header: { backgroundColor: '#ff1744', color: '#ffffff' }, content: { backgroundColor: '#ffebee', color: '#c62828' } }}, - { type: 'weekend', state: 'today', colors: { + { weekSplit: 'weekend', relative: 'today', state: 'default', colors: { header: { backgroundColor: '#ff6b6b', color: '#ffffff' }, content: { backgroundColor: '#ffe0e0', color: '#d32f2f' } }}, + { weekSplit: 'weekday', relative: 'today', state: 'active', colors: { + header: { backgroundColor: '#ff5252', color: '#ffffff' }, + content: { backgroundColor: '#ffcdd2', color: '#b71c1c' } + }}, // Weekday states - { type: 'weekday', state: 'default', colors: { + { weekSplit: 'weekday', state: 'default', colors: { header: { backgroundColor: '#ff6b35', color: '#ffffff' }, content: { backgroundColor: '#ffffff', color: '#ff6b35' } }}, - { type: 'weekday', state: 'selecting', colors: { + { weekSplit: 'weekday', state: 'selecting', colors: { header: { backgroundColor: '#ff8c5a', color: '#ffffff' }, content: { backgroundColor: '#ffe8df', color: '#c94820' } }}, - { type: 'weekday', state: 'rangeStart', colors: { + { weekSplit: 'weekday', state: 'rangeStart', colors: { header: { backgroundColor: '#d84315', color: '#ffffff' }, content: { backgroundColor: '#ff5722', color: '#ffffff' } }}, - { type: 'weekday', state: 'rangeEnd', colors: { + { weekSplit: 'weekday', state: 'rangeEnd', colors: { header: { backgroundColor: '#d84315', color: '#ffffff' }, content: { backgroundColor: '#ff5722', color: '#ffffff' } }}, - { type: 'weekday', state: 'rangeMid', colors: { + { weekSplit: 'weekday', state: 'rangeMid', colors: { header: { backgroundColor: '#ff8a65', color: '#ffffff' }, content: { backgroundColor: '#ffccbc', color: '#bf360c' } }}, - { type: 'weekday', state: 'active', colors: { + { weekSplit: 'weekday', state: 'active', colors: { header: { backgroundColor: '#f4511e', color: '#ffffff' }, content: { backgroundColor: '#e64a19', color: '#ffffff' } }}, // Weekend states - { type: 'weekend', state: 'default', colors: { + { weekSplit: 'weekend', state: 'default', colors: { header: { backgroundColor: '#ff9671', color: '#ffffff' }, content: { backgroundColor: '#fff4f0', color: '#cc5030' } }}, - { type: 'weekend', state: 'selecting', colors: { + { weekSplit: 'weekend', state: 'selecting', colors: { header: { backgroundColor: '#ffab8f', color: '#ffffff' }, content: { backgroundColor: '#ffe0d6', color: '#b84020' } }}, - { type: 'weekend', state: 'rangeStart', colors: { + { weekSplit: 'weekend', state: 'rangeStart', colors: { header: { backgroundColor: '#bf360c', color: '#ffffff' }, content: { backgroundColor: '#ff6e40', color: '#ffffff' } }}, - { type: 'weekend', state: 'rangeEnd', colors: { + { weekSplit: 'weekend', state: 'rangeEnd', colors: { header: { backgroundColor: '#bf360c', color: '#ffffff' }, content: { backgroundColor: '#ff6e40', color: '#ffffff' } }}, - { type: 'weekend', state: 'rangeMid', colors: { + { weekSplit: 'weekend', state: 'rangeMid', colors: { header: { backgroundColor: '#ffab91', color: '#ffffff' }, content: { backgroundColor: '#ffddd2', color: '#a73010' } }}, - { type: 'weekend', state: 'active', colors: { + { weekSplit: 'weekend', state: 'active', colors: { header: { backgroundColor: '#ff3d00', color: '#ffffff' }, content: { backgroundColor: '#ff6e40', color: '#ffffff' } }} ], forest: [ - // Today state - { type: 'weekday', state: 'today', colors: { + // Today's date colors + { weekSplit: 'weekday', relative: 'today', state: 'default', colors: { header: { backgroundColor: '#66bb6a', color: '#ffffff' }, content: { backgroundColor: '#e8f5e9', color: '#2e7d32' } }}, - { type: 'weekend', state: 'today', colors: { + { weekSplit: 'weekend', relative: 'today', state: 'default', colors: { header: { backgroundColor: '#81c784', color: '#ffffff' }, content: { backgroundColor: '#f1f8e9', color: '#33691e' } }}, + { weekSplit: 'weekday', relative: 'today', state: 'rangeStart', colors: { + header: { backgroundColor: '#4caf50', color: '#ffffff' }, + content: { backgroundColor: '#c8e6c9', color: '#1b5e20' } + }}, // Weekday states - { type: 'weekday', state: 'default', colors: { + { weekSplit: 'weekday', state: 'default', colors: { header: { backgroundColor: '#2d6a4f', color: '#ffffff' }, content: { backgroundColor: '#ffffff', color: '#2d6a4f' } }}, - { type: 'weekday', state: 'selecting', colors: { + { weekSplit: 'weekday', state: 'selecting', colors: { header: { backgroundColor: '#52b788', color: '#ffffff' }, content: { backgroundColor: '#d8f3dc', color: '#1b5e3f' } }}, - { type: 'weekday', state: 'rangeStart', colors: { + { weekSplit: 'weekday', state: 'rangeStart', colors: { header: { backgroundColor: '#1b5e3f', color: '#ffffff' }, content: { backgroundColor: '#40916c', color: '#ffffff' } }}, - { type: 'weekday', state: 'rangeEnd', colors: { + { weekSplit: 'weekday', state: 'rangeEnd', colors: { header: { backgroundColor: '#1b5e3f', color: '#ffffff' }, content: { backgroundColor: '#40916c', color: '#ffffff' } }}, - { type: 'weekday', state: 'rangeMid', colors: { + { weekSplit: 'weekday', state: 'rangeMid', colors: { header: { backgroundColor: '#74c69d', color: '#ffffff' }, content: { backgroundColor: '#b7e4c7', color: '#1b5e3f' } }}, - { type: 'weekday', state: 'active', colors: { + { weekSplit: 'weekday', state: 'active', colors: { header: { backgroundColor: '#388e3c', color: '#ffffff' }, content: { backgroundColor: '#2e7d32', color: '#ffffff' } }}, // Weekend states - { type: 'weekend', state: 'default', colors: { + { weekSplit: 'weekend', state: 'default', colors: { header: { backgroundColor: '#6a994e', color: '#ffffff' }, content: { backgroundColor: '#f1f8f4', color: '#386641' } }}, - { type: 'weekend', state: 'selecting', colors: { + { weekSplit: 'weekend', state: 'selecting', colors: { header: { backgroundColor: '#95d5b2', color: '#ffffff' }, content: { backgroundColor: '#e5f5eb', color: '#2d6a4f' } }}, - { type: 'weekend', state: 'rangeStart', colors: { + { weekSplit: 'weekend', state: 'rangeStart', colors: { header: { backgroundColor: '#155d3f', color: '#ffffff' }, content: { backgroundColor: '#52b788', color: '#ffffff' } }}, - { type: 'weekend', state: 'rangeEnd', colors: { + { weekSplit: 'weekend', state: 'rangeEnd', colors: { header: { backgroundColor: '#155d3f', color: '#ffffff' }, content: { backgroundColor: '#52b788', color: '#ffffff' } }}, - { type: 'weekend', state: 'rangeMid', colors: { + { weekSplit: 'weekend', state: 'rangeMid', colors: { header: { backgroundColor: '#95d5b2', color: '#ffffff' }, content: { backgroundColor: '#d8f3dc', color: '#155d3f' } }}, - { type: 'weekend', state: 'active', colors: { + { weekSplit: 'weekend', state: 'active', colors: { header: { backgroundColor: '#2e7d32', color: '#ffffff' }, content: { backgroundColor: '#4caf50', color: '#ffffff' } }} @@ -381,14 +397,14 @@ export const InteractiveDateRange: React.FC = () => {

🎨 Color Scheme Features:

    -
  • 📅 Today's Date: Automatically highlighted with special colors (gold/red/green based on theme)
  • +
  • 📅 Today's Date: Can have special colors for any state (default, active, rangeStart, etc.)
  • Weekdays vs Weekends: Notice the subtle color differences
  • Selecting State: Hover while range is selected to see the selecting colors
  • Range States: Start/End dates have stronger colors than middle dates
  • Active Dates: Click to toggle - active dates get special highlighting

- 💡 Today's date has its own distinct styling that works with all themes! + 💡 Today can be in any state and still have its special styling!

)} diff --git a/src/index.ts b/src/index.ts index e55af0b..bed32ed 100644 --- a/src/index.ts +++ b/src/index.ts @@ -23,7 +23,9 @@ export type { ColorStyle, StateColors, DayState, - DayType + WeekSplit, + DayRelative, + DayType // Deprecated, kept for backwards compatibility } from './types/calendar'; // Re-export Locale type from date-fns for convenience diff --git a/src/types/calendar.ts b/src/types/calendar.ts index 45ce20f..d6e2285 100644 --- a/src/types/calendar.ts +++ b/src/types/calendar.ts @@ -32,13 +32,18 @@ export type DayState = | 'rangeStart' | 'rangeEnd' | 'rangeMid' - | 'active' - | 'today'; + | 'active'; -export type DayType = 'weekday' | 'weekend'; +export type WeekSplit = 'weekday' | 'weekend'; +export type DayRelative = 'today' | 'anyday'; + +// Keep DayType for backwards compatibility (deprecated) +export type DayType = WeekSplit; export type ColorSchemeEntry = { - type: DayType; + weekSplit?: WeekSplit; // Optional for backwards compatibility + type?: DayType; // Deprecated, use weekSplit + relative?: DayRelative; // Default is 'anyday' state: DayState; colors: StateColors; }; @@ -56,8 +61,7 @@ export type DayVariation = | 'selecting' | 'rowStart' | 'rowEnd' - | 'active' - | 'today'; + | 'active'; export type DaySize = 'xl' | 'l' | 'm' | 's' | 'xs' | 'xxs'; export interface YearProps { diff --git a/src/utils/colorUtils.ts b/src/utils/colorUtils.ts index dd5d8b2..4958fb4 100644 --- a/src/utils/colorUtils.ts +++ b/src/utils/colorUtils.ts @@ -1,10 +1,11 @@ -import { ColorScheme, DayState, DayType, StateColors, DayVariation } from '../types/calendar'; +import { ColorScheme, DayState, WeekSplit, DayRelative, StateColors, DayVariation } from '../types/calendar'; +import { isToday } from './dateUtils'; /** - * Determines the day type based on variations (greyed indicates weekend) + * Determines the week split based on variations (greyed indicates weekend) * or by checking the day of week */ -export const getDayType = (date: Date, variations: DayVariation[], weekendDays: number[] = [6, 0]): DayType => { +export const getWeekSplit = (date: Date, variations: DayVariation[], weekendDays: number[] = [6, 0]): WeekSplit => { // If variations include 'greyed', it's a weekend if (variations.includes('greyed')) { return 'weekend'; @@ -17,8 +18,7 @@ export const getDayType = (date: Date, variations: DayVariation[], weekendDays: * Maps variations to a DayState for color lookup */ export const getDayState = (variations: DayVariation[]): DayState => { - // Priority order for states (today has highest priority for visibility) - if (variations.includes('today')) return 'today'; + // Priority order for states if (variations.includes('rangeStart') || variations.includes('rangeEnd')) { if (variations.includes('rangeStart') && !variations.includes('rangeEnd')) { return 'rangeStart'; @@ -40,34 +40,87 @@ export const getDayState = (variations: DayVariation[]): DayState => { */ export const findColorInScheme = ( colorScheme: ColorScheme | undefined, - dayType: DayType, - dayState: DayState + weekSplit: WeekSplit, + dayState: DayState, + relative: DayRelative ): StateColors | undefined => { if (!colorScheme) return undefined; - // First try to find exact match + // First try to find exact match with all three dimensions const exactMatch = colorScheme.find( - entry => entry.type === dayType && entry.state === dayState + entry => { + const entryWeekSplit = entry.weekSplit || entry.type || 'weekday'; + const entryRelative = entry.relative || 'anyday'; + return entryWeekSplit === weekSplit && entry.state === dayState && entryRelative === relative; + } ); if (exactMatch) return exactMatch.colors; + // If today, fallback to anyday with same weekSplit and state + if (relative === 'today') { + const anydayMatch = colorScheme.find( + entry => { + const entryWeekSplit = entry.weekSplit || entry.type || 'weekday'; + const entryRelative = entry.relative || 'anyday'; + return entryWeekSplit === weekSplit && entry.state === dayState && entryRelative === 'anyday'; + } + ); + if (anydayMatch) return anydayMatch.colors; + } + // Fallback to weekday colors for weekend if not specified - if (dayType === 'weekend') { + if (weekSplit === 'weekend') { const weekdayMatch = colorScheme.find( - entry => entry.type === 'weekday' && entry.state === dayState + entry => { + const entryWeekSplit = entry.weekSplit || entry.type || 'weekday'; + const entryRelative = entry.relative || 'anyday'; + return entryWeekSplit === 'weekday' && entry.state === dayState && entryRelative === relative; + } ); if (weekdayMatch) return weekdayMatch.colors; + + // Try weekday anyday if today weekend doesn't exist + if (relative === 'today') { + const weekdayAnydayMatch = colorScheme.find( + entry => { + const entryWeekSplit = entry.weekSplit || entry.type || 'weekday'; + const entryRelative = entry.relative || 'anyday'; + return entryWeekSplit === 'weekday' && entry.state === dayState && entryRelative === 'anyday'; + } + ); + if (weekdayAnydayMatch) return weekdayAnydayMatch.colors; + } } - // Fallback to default state for the day type + // Fallback to default state for the same weekSplit and relative const defaultMatch = colorScheme.find( - entry => entry.type === dayType && entry.state === 'default' + entry => { + const entryWeekSplit = entry.weekSplit || entry.type || 'weekday'; + const entryRelative = entry.relative || 'anyday'; + return entryWeekSplit === weekSplit && entry.state === 'default' && entryRelative === relative; + } ); if (defaultMatch) return defaultMatch.colors; - // Final fallback to weekday default + // Fallback to default anyday for the same weekSplit + if (relative === 'today') { + const defaultAnydayMatch = colorScheme.find( + entry => { + const entryWeekSplit = entry.weekSplit || entry.type || 'weekday'; + const entryRelative = entry.relative || 'anyday'; + return entryWeekSplit === weekSplit && entry.state === 'default' && entryRelative === 'anyday'; + } + ); + if (defaultAnydayMatch) return defaultAnydayMatch.colors; + } + + // Final fallback to weekday default anyday const weekdayDefault = colorScheme.find( - entry => entry.type === 'weekday' && entry.state === 'default' + entry => { + const entryWeekSplit = entry.weekSplit || entry.type || 'weekday'; + const entryRelative = entry.relative || 'anyday'; + return entryWeekSplit === 'weekday' && entry.state === 'default' && entryRelative === 'anyday'; + } ); return weekdayDefault?.colors; }; @@ -83,8 +136,12 @@ export const getCustomColors = ( ): StateColors | undefined => { if (!colorScheme) return undefined; - const dayType = getDayType(date, variations, weekendDays); + const weekSplit = getWeekSplit(date, variations, weekendDays); const dayState = getDayState(variations); + const relative: DayRelative = isToday(date) ? 'today' : 'anyday'; - return findColorInScheme(colorScheme, dayType, dayState); -}; \ No newline at end of file + return findColorInScheme(colorScheme, weekSplit, dayState, relative); +}; + +// Keep old exports for backwards compatibility (deprecated) +export const getDayType = getWeekSplit; \ No newline at end of file diff --git a/src/utils/dateUtils.ts b/src/utils/dateUtils.ts index 07645be..7aff781 100644 --- a/src/utils/dateUtils.ts +++ b/src/utils/dateUtils.ts @@ -1,4 +1,7 @@ import { isSameDay, isWithinInterval, startOfDay, isToday } from 'date-fns'; + +// Re-export isToday for use in color utils +export { isToday }; import { DateRange, DayVariation } from '../types/calendar'; export const getDateVariations = ( @@ -9,11 +12,6 @@ export const getDateVariations = ( ): DayVariation[] => { const variations: DayVariation[] = []; - // Check if it's today - if (isToday(date)) { - variations.push('today'); - } - // Check if it's a weekend if (weekendDays.includes(date.getDay())) { variations.push('greyed');