UNPKG

v-calendar

Version:

A calendar and date picker plugin for Vue.js.

136 lines (118 loc) 3.81 kB
import { isArray, isObject, isString, isFunction } from '../helpers'; import Locale from '../locale'; import type { DayOfWeek, DayInMonth, WeekInMonth, MonthInYear, DayParts, DateParts, } from './helpers'; import { type Rule, type RuleType, type SingleOrArray, ComponentRule, ComponentRuleType, FunctionRule, GroupRuleType, IntervalRule, IntervalRuleType, OrdinalComponentRuleType, OrdinalComponentRule, } from './rules'; export type RepeatIntervalShort = 'day' | 'week' | 'month' | 'year'; export type RepeatInterval = 'days' | 'weeks' | 'months' | 'years'; export interface DateRepeatConfig { every: RepeatIntervalShort | [number, RepeatInterval]; from: Date; until: Date; weekdays: SingleOrArray<DayOfWeek>; days: SingleOrArray<DayInMonth>; weeks: SingleOrArray<WeekInMonth>; months: SingleOrArray<MonthInYear>; years: SingleOrArray<number>; ordinalWeekdays: SingleOrArray<number[]>; on: SingleOrArray<DateRepeatFn | Partial<DateRepeatConfig>>; } export type DateRepeatFn = (dayParts: DayParts) => boolean; export interface DateRepeatOptions { locale: Locale; } export class DateRepeat implements Rule<GroupRuleType> { validated = true; config: Partial<DateRepeatConfig> | DateRepeatFn; type = GroupRuleType.Any; from: DateParts | undefined; until: DateParts | undefined; rules: Rule<RuleType>[] = []; locale = new Locale(); constructor( config: Partial<DateRepeatConfig> | DateRepeatFn, options: Partial<DateRepeatOptions> = {}, private parent?: DateRepeat, ) { if (options.locale) this.locale = options.locale; this.config = config; if (isFunction(config)) { this.type = GroupRuleType.All; this.rules = [new FunctionRule(config)]; } else if (isArray(config)) { this.type = GroupRuleType.Any; this.rules = config.map(c => new DateRepeat(c, options, this)); } else if (isObject(config)) { this.type = GroupRuleType.All; // Assign bounding dates this.from = config.from ? this.locale.getDateParts(config.from) : parent?.from; this.until = config.until ? this.locale.getDateParts(config.until) : parent?.until; this.rules = this.getObjectRules(config); } else { console.error('Rule group configuration must be an object or an array.'); this.validated = false; } } getObjectRules(config: any) { const rules: Rule<RuleType>[] = []; // Add interval rule if (config.every) { if (isString(config.every)) { config.every = [1, `${config.every}s`]; } if (isArray(config.every)) { const [interval = 1, type = IntervalRuleType.Days] = config.every; rules.push(new IntervalRule(type, interval, this.from!)); } } // Add component rules Object.values(ComponentRuleType).forEach(type => { if (!(type in config)) return; rules.push(ComponentRule.create(type, config[type])); }); // Add ordinal component rules Object.values(OrdinalComponentRuleType).forEach(type => { if (!(type in config)) return; rules.push(new OrdinalComponentRule(type, config[type])); }); // Add group rules if (config.on != null) { if (!isArray(config.on)) config.on = [config.on]; rules.push( new DateRepeat(config.on, { locale: this.locale }, this.parent), ); } return rules; } passes(dayParts: DayParts) { if (!this.validated) return true; if (this.from && dayParts.dayIndex <= this.from.dayIndex) return false; if (this.until && dayParts.dayIndex >= this.until.dayIndex) return false; if (this.type === GroupRuleType.Any) { return this.rules.some(r => r.passes(dayParts)); } return this.rules.every(r => r.passes(dayParts)); } }