Skip to content

Commit e6050d5

Browse files
committed
Feat: Auto read theme
1 parent 82cefc1 commit e6050d5

File tree

3 files changed

+69
-56
lines changed

3 files changed

+69
-56
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "vue-persian-calendar-datepicker",
3-
"version": "1.2.3",
3+
"version": "1.2.4",
44
"description": "A Vue 3 Persian calendar and datepicker with official Iranian holidays, Jalali, Hijri, and Gregorian date support.",
55
"author": "Mohammad Hossein Pour",
66
"license": "MIT",

src/components/PersianDatePicker.vue

Lines changed: 68 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ interface Props
7171
showTodayButton?: boolean
7272
showCloseButton?: boolean
7373
showOccasions?: boolean
74-
theme?: 'light' | 'dark' | 'auto'
74+
theme?: 'light' | 'dark' | 'auto' | ''
7575
lightColors?: ColorScheme
7676
darkColors?: ColorScheme
7777
}
@@ -171,16 +171,14 @@ const props = withDefaults(defineProps<Props>(),
171171
theme: 'light'
172172
});
173173
174-
const emit = defineEmits<
175-
{
174+
const emit = defineEmits<{
176175
(e: 'update:modelValue', value: number[] | null): void
177176
(e: 'change', value: number[] | null): void
178177
(e: 'open'): void
179178
(e: 'close'): void
180179
}>();
181180
182-
const
183-
{
181+
const {
184182
today,
185183
persianMonthName,
186184
dayCountInMonth,
@@ -206,34 +204,52 @@ const systemTheme = ref<'light' | 'dark'>('light');
206204
207205
const detectSystemTheme = () =>
208206
{
209-
if (typeof window !== 'undefined' && window.matchMedia)
207+
if (typeof window !== 'undefined')
210208
{
211-
systemTheme.value = window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
209+
// Check HTML tag for dark/light class first
210+
const htmlElement = document.documentElement;
211+
212+
if (htmlElement.classList.contains('dark'))
213+
{
214+
systemTheme.value = 'dark';
215+
}
216+
else if (htmlElement.classList.contains('light'))
217+
{
218+
systemTheme.value = 'light';
219+
}
220+
else if (window.matchMedia)
221+
{
222+
// Fallback to prefers-color-scheme if no class is found
223+
systemTheme.value = window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
224+
}
212225
}
213226
}
214227
215228
const currentTheme = computed(() =>
216229
{
217-
if (props.theme === 'auto')
230+
if (!props.theme || props.theme === 'auto')
231+
{
218232
return systemTheme.value;
233+
}
234+
219235
return props.theme;
220236
});
221237
222238
const currentColors = computed((): ColorScheme =>
223239
{
224-
const isLight = currentTheme.value === 'light'
225-
const defaultColors = isLight ? defaultLightColors : defaultDarkColors
226-
const customColors = isLight ? props.lightColors : props.darkColors
240+
const isLight = currentTheme.value === 'light';
241+
const defaultColors = isLight ? defaultLightColors : defaultDarkColors;
242+
const customColors = isLight ? props.lightColors : props.darkColors;
227243
228244
return {
229245
...defaultColors,
230246
...customColors
231-
}
232-
})
247+
};
248+
});
233249
234250
const getCSSVariables = computed(() =>
235251
{
236-
const colors = currentColors.value
252+
const colors = currentColors.value;
237253
return {
238254
'--input-bg': colors.inputBg,
239255
'--input-text': colors.inputText,
@@ -270,8 +286,8 @@ const getCSSVariables = computed(() =>
270286
'--event-dot-color': colors.eventDotColor,
271287
'--footer-border-color': colors.footerBorderColor,
272288
'--footer-text': colors.footerText
273-
}
274-
})
289+
};
290+
});
275291
276292
const initializeDate = () =>
277293
{
@@ -288,6 +304,7 @@ const initializeDate = () =>
288304
else if (typeof value === 'string')
289305
{
290306
const parts = value.split(/[\/\-]/).map(Number);
307+
291308
if (parts.length === 3)
292309
{
293310
selectedDate.value = parts;
@@ -296,17 +313,17 @@ const initializeDate = () =>
296313
}
297314
}
298315
}
299-
}
316+
};
300317
301318
watch(() => props.modelValue, (value) =>
302319
{
303320
if (value)
304321
{
305322
if (Array.isArray(value))
306323
{
307-
selectedDate.value = value
308-
currentYear.value = value[0]
309-
currentMonth.value = value[1]
324+
selectedDate.value = value;
325+
currentYear.value = value[0];
326+
currentMonth.value = value[1];
310327
}
311328
else if (typeof value === 'string')
312329
{
@@ -351,7 +368,7 @@ const displayValue = computed(() =>
351368
}
352369
353370
return `${year}/${month}/${day}`;
354-
})
371+
});
355372
356373
const formattedSelectedDate = computed(() =>
357374
{
@@ -360,7 +377,7 @@ const formattedSelectedDate = computed(() =>
360377
361378
const [year, month, day] = selectedDate.value;
362379
return `${day} ${persianMonthName(month)} ${year}`;
363-
})
380+
});
364381
365382
const calendarDays = computed((): CalendarDay[] =>
366383
{
@@ -420,13 +437,14 @@ const calendarDays = computed((): CalendarDay[] =>
420437
}
421438
422439
return days;
423-
})
440+
});
424441
425442
const checkIfDisabled = (year: number, month: number, day: number): boolean =>
426443
{
427444
if (props.from)
428445
{
429446
const [fromY, fromM, fromD] = props.from;
447+
430448
if (year < fromY || (year === fromY && month < fromM) || (year === fromY && month === fromM && day < fromD))
431449
{
432450
return true;
@@ -436,14 +454,15 @@ const checkIfDisabled = (year: number, month: number, day: number): boolean =>
436454
if (props.to)
437455
{
438456
const [toY, toM, toD] = props.to;
457+
439458
if (year > toY || (year === toY && month > toM) || (year === toY && month === toM && day > toD))
440459
{
441460
return true;
442461
}
443462
}
444463
445464
return false;
446-
}
465+
};
447466
448467
const getDayClasses = (day: CalendarDay) =>
449468
{
@@ -457,7 +476,7 @@ const getDayClasses = (day: CalendarDay) =>
457476
'empty': day.day === 0,
458477
'has-event': day.events && (day.events.persianEvents.length > 0 || day.events.hijriEvents.length > 0)
459478
};
460-
}
479+
};
461480
462481
const getDayTooltip = (day: CalendarDay): string =>
463482
{
@@ -476,15 +495,15 @@ const getDayTooltip = (day: CalendarDay): string =>
476495
}
477496
478497
return events.join('\n');
479-
}
498+
};
480499
481500
const handleInputClick = () =>
482501
{
483502
if (props.disabled)
484503
return;
485504
486505
togglePopup();
487-
}
506+
};
488507
489508
const togglePopup = () =>
490509
{
@@ -499,7 +518,7 @@ const togglePopup = () =>
499518
{
500519
openPopup();
501520
}
502-
}
521+
};
503522
504523
const openPopup = () =>
505524
{
@@ -523,14 +542,14 @@ const openPopup = () =>
523542
nextTick(() =>
524543
{
525544
calculatePopupPosition();
526-
})
527-
}
545+
});
546+
};
528547
529548
const closePopup = () =>
530549
{
531550
isOpen.value = false;
532551
emit('close');
533-
}
552+
};
534553
535554
const calculatePopupPosition = () =>
536555
{
@@ -553,7 +572,7 @@ const calculatePopupPosition = () =>
553572
554573
popupPosition.value = spaceBelow < 400 && spaceAbove > spaceBelow ? 'top' : 'bottom';
555574
}
556-
}
575+
};
557576
558577
const selectDate = (day: CalendarDay) =>
559578
{
@@ -563,9 +582,8 @@ const selectDate = (day: CalendarDay) =>
563582
selectedDate.value = [currentYear.value, currentMonth.value, day.day];
564583
emit('update:modelValue', selectedDate.value);
565584
emit('change', selectedDate.value);
566-
567585
closePopup();
568-
}
586+
};
569587
570588
const selectToday = () =>
571589
{
@@ -575,16 +593,15 @@ const selectToday = () =>
575593
576594
emit('update:modelValue', selectedDate.value);
577595
emit('change', selectedDate.value);
578-
579596
closePopup();
580-
}
597+
};
581598
582599
const clearDate = () =>
583600
{
584601
selectedDate.value = null;
585602
emit('update:modelValue', null);
586603
emit('change', null);
587-
}
604+
};
588605
589606
const handleNextMonth = () =>
590607
{
@@ -597,7 +614,7 @@ const handleNextMonth = () =>
597614
{
598615
currentMonth.value++;
599616
}
600-
}
617+
};
601618
602619
const handlePrevMonth = () =>
603620
{
@@ -610,27 +627,25 @@ const handlePrevMonth = () =>
610627
{
611628
currentMonth.value--;
612629
}
613-
}
630+
};
614631
615632
const handleNextYear = () =>
616633
{
617634
currentYear.value++;
618-
}
635+
};
619636
620637
const handlePrevYear = () =>
621638
{
622639
currentYear.value--;
623-
}
640+
};
624641
625642
const onFocus = () =>
626643
{
627644
if (!props.readonly)
628645
return;
629-
}
646+
};
630647
631-
const onBlur = () =>
632-
{
633-
}
648+
const onBlur = () => {};
634649
635650
const setDate = (date: number[] | string | null) =>
636651
{
@@ -639,15 +654,14 @@ const setDate = (date: number[] | string | null) =>
639654
selectedDate.value = null;
640655
emit('update:modelValue', null);
641656
emit('change', null);
642-
643657
return;
644658
}
645659
646660
if (Array.isArray(date))
647661
{
648-
selectedDate.value = date
649-
currentYear.value = date[0]
650-
currentMonth.value = date[1]
662+
selectedDate.value = date;
663+
currentYear.value = date[0];
664+
currentMonth.value = date[1];
651665
}
652666
else if (typeof date === 'string')
653667
{
@@ -663,7 +677,7 @@ const setDate = (date: number[] | string | null) =>
663677
664678
emit('update:modelValue', selectedDate.value);
665679
emit('change', selectedDate.value);
666-
}
680+
};
667681
668682
const setDateFromGregorian = (gregorianDate: number[] | string) =>
669683
{
@@ -685,12 +699,12 @@ const setDateFromGregorian = (gregorianDate: number[] | string) =>
685699
686700
const jalaliDate = gregorianToJalali(gYear, gMonth, gDay);
687701
setDate(jalaliDate);
688-
}
702+
};
689703
690704
const getSelectedDate = (): number[] | null =>
691705
{
692706
return selectedDate.value;
693-
}
707+
};
694708
695709
defineExpose({
696710
setDate,
@@ -700,15 +714,15 @@ defineExpose({
700714
clearDate,
701715
openPopup,
702716
closePopup
703-
})
717+
});
704718
705719
const handleClickOutside = (event: MouseEvent) =>
706720
{
707721
if (wrapperRef.value && !wrapperRef.value.contains(event.target as Node))
708722
{
709723
closePopup();
710724
}
711-
}
725+
};
712726
713727
onMounted(() =>
714728
{

src/styles/datepicker.css

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@
4141
{
4242
position: relative;
4343
width: 100%;
44-
max-width: 300px;
4544
direction: rtl;
4645
font-size: 0.9rem;
4746
font-family: Tahoma, sans-serif;

0 commit comments

Comments
 (0)