@sixbell-telco/sdk
Version:
A collection of reusable components designed for use in Sixbell Telco Angular projects
213 lines (208 loc) • 17.5 kB
JavaScript
import * as i0 from '@angular/core';
import { Pipe, input, computed, model, output, effect, Component } from '@angular/core';
import 'dayjs/locale/es';
import 'dayjs/locale/pt';
import * as i1 from '@angular/common';
import { CommonModule } from '@angular/common';
import { FormsModule, NG_VALUE_ACCESSOR } from '@angular/forms';
import { InputComponent } from '@sixbell-telco/sdk/components/forms/input';
import { IconComponent } from '@sixbell-telco/sdk/components/icon';
import { matKeyboardArrowLeftOutline, matKeyboardArrowRightOutline } from '@sixbell-telco/sdk/components/icon/material/outline';
import dayjs from 'dayjs';
import customParseFormat from 'dayjs/plugin/customParseFormat';
import isBetween from 'dayjs/plugin/isBetween';
import isoWeek from 'dayjs/plugin/isoWeek';
class DatepickerFormatMonthPipe {
transform(value, language = 'es') {
// capitalize the first letter of the month
return value.locale(language).format('MMMM').charAt(0).toUpperCase() + value.format('MMMM YYYY').slice(1);
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.0", ngImport: i0, type: DatepickerFormatMonthPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "19.2.0", ngImport: i0, type: DatepickerFormatMonthPipe, isStandalone: true, name: "datepickerFormatMonth" });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.0", ngImport: i0, type: DatepickerFormatMonthPipe, decorators: [{
type: Pipe,
args: [{
name: 'datepickerFormatMonth',
standalone: true,
}]
}] });
/* eslint-disable @typescript-eslint/no-explicit-any */
class DatepickerComponent {
iconArrowLeft = matKeyboardArrowLeftOutline;
iconArrowRight = matKeyboardArrowRightOutline;
format = input('DD/MM/YYYY');
language = input('es');
weekFromLanguage = computed(() => {
if (this.language() === 'en') {
return ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'];
}
else if (this.language() === 'pt') {
return ['Seg', 'Ter', 'Qua', 'Qui', 'Sex', 'Sáb', 'Dom'];
}
else {
return ['Lun', 'Mar', 'Mié', 'Jue', 'Vie', 'Sáb', 'Dom'];
}
});
label = input('');
range = input(null); // example: [1, 'month']
minDate = input(null);
maxDate = input(null);
disableUntil = input('');
disableFrom = input('');
current = model(dayjs().locale(this.language()).format(this.format()));
dateUpdated = output();
synchronizedPickersEffect = effect(() => {
if (this.minDate() || this.maxDate()) {
this.refresh();
}
});
daysOfMonth = [];
monthAndYearLabel = dayjs().locale(this.language());
isOpen = false;
// Form control properties
parentForm = input(null);
formControlName = input('');
get formField() {
if (!this.parentForm())
return null;
return this.parentForm()?.get(this.formControlName());
}
// ControlValueAccessor attributes
onControlChange = () => { };
onControlTouch = () => { };
disabled = model(false);
// ControlValueAccessor methods
writeValue(obj) {
this.current.set(obj);
}
registerOnChange(fn) {
this.onControlChange = fn;
}
registerOnTouched(fn) {
this.onControlTouch = fn;
}
setDisabledState(isDisabled) {
this.disabled.set(isDisabled);
}
constructor() {
dayjs.extend(isoWeek);
dayjs.extend(customParseFormat);
dayjs.extend(isBetween);
}
ngOnInit() {
if (this.current()) {
this.getDaysFromDate(dayjs(this.current(), this.format()).locale(this.language()).month() + 1, dayjs(this.current(), this.format()).locale(this.language()).year());
}
else {
const d = new Date();
this.getDaysFromDate(d.getMonth() + 1, d.getFullYear());
}
}
toggleDatepicker() {
if (this.range()) {
this.refresh();
}
this.isOpen = !this.isOpen;
this.onControlTouch();
}
getDaysFromDate(month, year) {
const startDate = dayjs(`${year}/${month}/01`).locale(this.language());
const endDate = startDate.clone().endOf('month');
this.monthAndYearLabel = startDate;
const diffDays = endDate.diff(startDate, 'days', true);
const numberDays = Math.round(diffDays);
const days = Object.keys([...Array(numberDays)]).map((a) => {
const d = parseInt(a) + 1;
const day = dayjs(`${year}-${month}-${d}`).locale(this.language());
const range = this.range();
const dateRange = this.minDate() ?? this.maxDate() ?? '';
return {
name: day.format('dddd'),
value: d, // Change the value to a number
indexWeek: day.isoWeekday(),
disabled: range ? this.shouldDisableDayByRange(day, dateRange, range[0], range[1]) : this.shouldDisableDay(day),
date: day.format(this.format()),
};
});
this.daysOfMonth = days;
}
shouldDisableDayByRange(day, from, quantity, unit) {
if (!from) {
return false;
}
if (this.maxDate()) {
// If maxDate is true, disables all dates AFTER 'from' date
return !day.isBetween(dayjs(from, this.format()).locale(this.language()).subtract(quantity, unit), dayjs(from, this.format()).locale(this.language()), null, '[]');
}
if (this.minDate()) {
// If minDate is true, disables all dates BEFORE 'from' date
return !day.isBetween(dayjs(from, this.format()).locale(this.language()), dayjs(from, this.format()).locale(this.language()).add(quantity, unit), null, '[]');
}
// Disables all dates BEFORE and AFTER 'from' date
return !day.isBetween(dayjs(from, this.format()).locale(this.language()).subtract(quantity, unit), dayjs(from, this.format()).locale(this.language()).add(quantity, unit), null, '[]');
}
shouldDisableDay(day) {
if (this.disableUntil() && this.disableFrom()) {
return !day.isBetween(dayjs(this.disableUntil(), this.format()).locale(this.language()).subtract(1, 'day'), dayjs(this.disableFrom(), this.format()).locale(this.language()).add(1, 'day'));
}
if (this.disableUntil() && !this.disableFrom()) {
return day.isBefore(dayjs(this.disableUntil(), this.format()).locale(this.language()));
}
if (this.disableFrom() && !this.disableUntil()) {
return day.isAfter(dayjs(this.disableFrom(), this.format()).locale(this.language()));
}
return false;
}
refresh() {
// Used to force a refresh on the calendar
this.changeMonth(true);
this.changeMonth(false);
}
changeMonth(flag) {
if (flag) {
const prevDate = this.monthAndYearLabel.clone().subtract(1, 'month');
this.getDaysFromDate(prevDate.format('MM'), prevDate.format('YYYY'));
}
else {
const nextDate = this.monthAndYearLabel.clone().add(1, 'month');
this.getDaysFromDate(nextDate.format('MM'), nextDate.format('YYYY'));
}
}
handleSelectDay(day) {
if (day.disabled)
return;
const monthYear = this.monthAndYearLabel.format('YYYY-MM');
const parsedDay = `${monthYear}-${day.value}`;
const date = dayjs(parsedDay).locale(this.language()).format(this.format());
this.current.set(date);
this.dateUpdated.emit(date);
this.onControlChange(date);
if (!this.range()) {
this.toggleDatepicker();
}
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.0", ngImport: i0, type: DatepickerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.0", type: DatepickerComponent, isStandalone: true, selector: "st-datepicker", inputs: { format: { classPropertyName: "format", publicName: "format", isSignal: true, isRequired: false, transformFunction: null }, language: { classPropertyName: "language", publicName: "language", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, range: { classPropertyName: "range", publicName: "range", isSignal: true, isRequired: false, transformFunction: null }, minDate: { classPropertyName: "minDate", publicName: "minDate", isSignal: true, isRequired: false, transformFunction: null }, maxDate: { classPropertyName: "maxDate", publicName: "maxDate", isSignal: true, isRequired: false, transformFunction: null }, disableUntil: { classPropertyName: "disableUntil", publicName: "disableUntil", isSignal: true, isRequired: false, transformFunction: null }, disableFrom: { classPropertyName: "disableFrom", publicName: "disableFrom", isSignal: true, isRequired: false, transformFunction: null }, current: { classPropertyName: "current", publicName: "current", isSignal: true, isRequired: false, transformFunction: null }, parentForm: { classPropertyName: "parentForm", publicName: "parentForm", isSignal: true, isRequired: false, transformFunction: null }, formControlName: { classPropertyName: "formControlName", publicName: "formControlName", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { current: "currentChange", dateUpdated: "dateUpdated", disabled: "disabledChange" }, providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: DatepickerComponent,
multi: true,
},
], ngImport: i0, template: "<!-- eslint-disable @angular-eslint/template/click-events-have-key-events -->\n<!-- eslint-disable @angular-eslint/template/interactive-supports-focus -->\n<st-input (click)=\"toggleDatepicker()\" [(value)]=\"current\" [readonly]=\"true\" [label]=\"label()\" />\n<div class=\"datepicker-container\">\n\t<div [class]=\"isOpen ? 'calendar-wrapper active' : 'calendar-wrapper inactive'\">\n\t\t<div class=\"calendar-header\">\n\t\t\t<button (click)=\"changeMonth(true)\" class=\"btn-prev\">\n\t\t\t\t<!-- <img src=\"assets/icons/calendar/left.svg\" /> -->\n\t\t\t\t<st-icon class=\"text-secondary-content\" [icon]=\"iconArrowLeft\" color=\"inherit\">></st-icon>\n\t\t\t</button>\n\t\t\t<h1>{{ monthAndYearLabel | datepickerFormatMonth: language() }}</h1>\n\t\t\t<button (click)=\"changeMonth(false)\" class=\"btn-next\">\n\t\t\t\t<!-- <img src=\"assets/icons/calendar/right.svg\" /> -->\n\t\t\t\t<st-icon class=\"text-secondary-content\" [icon]=\"iconArrowRight\" color=\"inherit\"></st-icon>\n\t\t\t</button>\n\t\t</div>\n\t\t<ol class=\"days\">\n\t\t\t@for (day of weekFromLanguage(); track day) {\n\t\t\t\t<li class=\"day-name\">{{ day | slice: 0 : 1 }}</li>\n\t\t\t}\n\n\t\t\t@for (day of daysOfMonth; track day.value) {\n\t\t\t\t<li\n\t\t\t\t\tclass=\"day\"\n\t\t\t\t\t(click)=\"handleSelectDay(day)\"\n\t\t\t\t\t[ngClass]=\"{ active: day.date === current(), disabled: day.disabled }\"\n\t\t\t\t\t[style.gridColumnStart]=\"$first ? day.indexWeek : 'auto'\"\n\t\t\t\t>\n\t\t\t\t\t<span>{{ day.value }}</span>\n\t\t\t\t</li>\n\t\t\t}\n\t\t</ol>\n\t</div>\n</div>\n", styles: [".datepicker-container{position:relative}.calendar-wrapper{padding:20px;border:solid 1px #eaeaea;background:#fff;box-shadow:0 4px 15px #0000001a;border-radius:15px;position:absolute;top:5px;left:0;z-index:9999;max-width:280px}.calendar-wrapper.active{display:block}.calendar-wrapper.inactive{display:none}.calendar-header{display:flex;width:100%;justify-content:space-between;align-items:center;align-content:center;padding:10px 0 0;margin-bottom:10px}.calendar-header h1{width:100%;font-style:normal;font-weight:500;font-size:15px;line-height:18px;color:#777675;text-align:center;font-family:Roboto,sans-serif}.calendar-header button{cursor:pointer;background-color:transparent;border:0;width:40px;display:flex;justify-content:center;align-items:center}.days{list-style:none;display:grid;grid-template-columns:repeat(7,34px);margin:0;padding:0;gap:0}.days .day-name{font-weight:700;margin-bottom:2px;padding:4px;text-align:center;font-style:normal;font-size:15px;color:#4dd6ed;margin-top:10px}.days .day{display:flex;justify-content:center;align-items:center;width:100%;height:34px;padding:.25rem;font-size:15px;cursor:pointer;color:#636363}.days .day:hover{font-weight:600;background:#4dd6ed;border-radius:50%;color:#fff}.days .day.disabled{color:#ccc}.days .day.active{font-weight:600;background:#4dd6ed;border-radius:50%;color:#fff}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "pipe", type: i1.SlicePipe, name: "slice" }, { kind: "ngmodule", type: FormsModule }, { kind: "component", type: InputComponent, selector: "st-input", inputs: ["variant", "size", "label", "type", "name", "placeholder", "readonly", "focus", "onlyNumbers", "ghost", "value", "parentForm", "formControlName", "disabled", "debounceTime"], outputs: ["valueChange", "disabledChange", "enterPressed", "blurred", "valueDebounced"] }, { kind: "pipe", type: DatepickerFormatMonthPipe, name: "datepickerFormatMonth" }, { kind: "component", type: IconComponent, selector: "st-icon", inputs: ["color", "size", "icon"] }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.0", ngImport: i0, type: DatepickerComponent, decorators: [{
type: Component,
args: [{ selector: 'st-datepicker', imports: [CommonModule, FormsModule, InputComponent, DatepickerFormatMonthPipe, IconComponent], providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: DatepickerComponent,
multi: true,
},
], template: "<!-- eslint-disable @angular-eslint/template/click-events-have-key-events -->\n<!-- eslint-disable @angular-eslint/template/interactive-supports-focus -->\n<st-input (click)=\"toggleDatepicker()\" [(value)]=\"current\" [readonly]=\"true\" [label]=\"label()\" />\n<div class=\"datepicker-container\">\n\t<div [class]=\"isOpen ? 'calendar-wrapper active' : 'calendar-wrapper inactive'\">\n\t\t<div class=\"calendar-header\">\n\t\t\t<button (click)=\"changeMonth(true)\" class=\"btn-prev\">\n\t\t\t\t<!-- <img src=\"assets/icons/calendar/left.svg\" /> -->\n\t\t\t\t<st-icon class=\"text-secondary-content\" [icon]=\"iconArrowLeft\" color=\"inherit\">></st-icon>\n\t\t\t</button>\n\t\t\t<h1>{{ monthAndYearLabel | datepickerFormatMonth: language() }}</h1>\n\t\t\t<button (click)=\"changeMonth(false)\" class=\"btn-next\">\n\t\t\t\t<!-- <img src=\"assets/icons/calendar/right.svg\" /> -->\n\t\t\t\t<st-icon class=\"text-secondary-content\" [icon]=\"iconArrowRight\" color=\"inherit\"></st-icon>\n\t\t\t</button>\n\t\t</div>\n\t\t<ol class=\"days\">\n\t\t\t@for (day of weekFromLanguage(); track day) {\n\t\t\t\t<li class=\"day-name\">{{ day | slice: 0 : 1 }}</li>\n\t\t\t}\n\n\t\t\t@for (day of daysOfMonth; track day.value) {\n\t\t\t\t<li\n\t\t\t\t\tclass=\"day\"\n\t\t\t\t\t(click)=\"handleSelectDay(day)\"\n\t\t\t\t\t[ngClass]=\"{ active: day.date === current(), disabled: day.disabled }\"\n\t\t\t\t\t[style.gridColumnStart]=\"$first ? day.indexWeek : 'auto'\"\n\t\t\t\t>\n\t\t\t\t\t<span>{{ day.value }}</span>\n\t\t\t\t</li>\n\t\t\t}\n\t\t</ol>\n\t</div>\n</div>\n", styles: [".datepicker-container{position:relative}.calendar-wrapper{padding:20px;border:solid 1px #eaeaea;background:#fff;box-shadow:0 4px 15px #0000001a;border-radius:15px;position:absolute;top:5px;left:0;z-index:9999;max-width:280px}.calendar-wrapper.active{display:block}.calendar-wrapper.inactive{display:none}.calendar-header{display:flex;width:100%;justify-content:space-between;align-items:center;align-content:center;padding:10px 0 0;margin-bottom:10px}.calendar-header h1{width:100%;font-style:normal;font-weight:500;font-size:15px;line-height:18px;color:#777675;text-align:center;font-family:Roboto,sans-serif}.calendar-header button{cursor:pointer;background-color:transparent;border:0;width:40px;display:flex;justify-content:center;align-items:center}.days{list-style:none;display:grid;grid-template-columns:repeat(7,34px);margin:0;padding:0;gap:0}.days .day-name{font-weight:700;margin-bottom:2px;padding:4px;text-align:center;font-style:normal;font-size:15px;color:#4dd6ed;margin-top:10px}.days .day{display:flex;justify-content:center;align-items:center;width:100%;height:34px;padding:.25rem;font-size:15px;cursor:pointer;color:#636363}.days .day:hover{font-weight:600;background:#4dd6ed;border-radius:50%;color:#fff}.days .day.disabled{color:#ccc}.days .day.active{font-weight:600;background:#4dd6ed;border-radius:50%;color:#fff}\n"] }]
}], ctorParameters: () => [] });
/**
* Generated bundle index. Do not edit.
*/
export { DatepickerComponent, DatepickerFormatMonthPipe };
//# sourceMappingURL=sixbell-telco-sdk-components-forms-datepicker.mjs.map