tecnualng 21.1.2 → 21.1.5
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.
- package/fesm2022/tecnualng.mjs +141 -21
- package/fesm2022/tecnualng.mjs.map +1 -1
- package/package.json +1 -1
- package/types/tecnualng.d.ts +10 -5
package/fesm2022/tecnualng.mjs
CHANGED
|
@@ -382,6 +382,8 @@ class TecnualDatepickerComponent {
|
|
|
382
382
|
maxDate = input(null, ...(ngDevMode ? [{ debugName: "maxDate" }] : []));
|
|
383
383
|
disabled = model(false, ...(ngDevMode ? [{ debugName: "disabled" }] : []));
|
|
384
384
|
id = input(`tng-datepicker-${Math.random().toString(36).substr(2, 9)}`, ...(ngDevMode ? [{ debugName: "id" }] : []));
|
|
385
|
+
locale = input((typeof navigator !== 'undefined' ? navigator.language : 'en-US'), ...(ngDevMode ? [{ debugName: "locale" }] : []));
|
|
386
|
+
firstDayOfWeek = input(null, ...(ngDevMode ? [{ debugName: "firstDayOfWeek" }] : [])); // 0 = Sunday, 1 = Monday, etc.
|
|
385
387
|
isOpen = signal(false, ...(ngDevMode ? [{ debugName: "isOpen" }] : []));
|
|
386
388
|
currentViewDate = signal(new Date(), ...(ngDevMode ? [{ debugName: "currentViewDate" }] : [])); // The month we are looking at
|
|
387
389
|
viewMode = signal('day', ...(ngDevMode ? [{ debugName: "viewMode" }] : []));
|
|
@@ -393,29 +395,79 @@ class TecnualDatepickerComponent {
|
|
|
393
395
|
constructor(elementRef) {
|
|
394
396
|
this.elementRef = elementRef;
|
|
395
397
|
}
|
|
398
|
+
getEffectiveFirstDayOfWeek() {
|
|
399
|
+
const definedDay = this.firstDayOfWeek();
|
|
400
|
+
if (definedDay !== null)
|
|
401
|
+
return definedDay;
|
|
402
|
+
// Try to determine from locale
|
|
403
|
+
try {
|
|
404
|
+
// @ts-ignore: weekInfo is a newer API, might need a shim or ignore
|
|
405
|
+
const weekInfo = new Intl.Locale(this.locale()).weekInfo;
|
|
406
|
+
if (weekInfo && typeof weekInfo.firstDay === 'number') {
|
|
407
|
+
return weekInfo.firstDay;
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
catch (e) {
|
|
411
|
+
// Fallback
|
|
412
|
+
}
|
|
413
|
+
// Default fallback: US=0 (Sun), others usually 1 (Mon). Simplified logic:
|
|
414
|
+
const l = this.locale().toLowerCase();
|
|
415
|
+
if (l.includes('us') || l.includes('en-ca') || l.includes('zh'))
|
|
416
|
+
return 0;
|
|
417
|
+
return 1;
|
|
418
|
+
}
|
|
396
419
|
// Calendar Logic
|
|
397
|
-
daysOfWeek =
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
420
|
+
daysOfWeek = computed(() => {
|
|
421
|
+
const firstDay = this.getEffectiveFirstDayOfWeek();
|
|
422
|
+
const days = [];
|
|
423
|
+
// Create a date that is definitely a valid day index to start iterating.
|
|
424
|
+
// 2024-01-07 is a Sunday.
|
|
425
|
+
// We want to generate names: Sun, Mon, etc.
|
|
426
|
+
// Let's iterate 7 days starting from a known Sunday + offset
|
|
427
|
+
const baseDate = new Date(2024, 0, 7); // Jan 7, 2024 is Sunday
|
|
428
|
+
const formatter = new Intl.DateTimeFormat(this.locale(), { weekday: 'short' });
|
|
429
|
+
for (let i = 0; i < 7; i++) {
|
|
430
|
+
const d = new Date(baseDate);
|
|
431
|
+
d.setDate(baseDate.getDate() + (firstDay + i));
|
|
432
|
+
// Remove dot usually found in some locales (e.g. es-ES "lun.") if desired or keep it.
|
|
433
|
+
// Let's keep it clean
|
|
434
|
+
days.push(formatter.format(d).replace('.', ''));
|
|
435
|
+
}
|
|
436
|
+
return days;
|
|
437
|
+
}, ...(ngDevMode ? [{ debugName: "daysOfWeek" }] : []));
|
|
438
|
+
monthNames = computed(() => {
|
|
439
|
+
const formatter = new Intl.DateTimeFormat(this.locale(), { month: 'long' });
|
|
440
|
+
const months = [];
|
|
441
|
+
for (let i = 0; i < 12; i++) {
|
|
442
|
+
const d = new Date(2024, i, 1);
|
|
443
|
+
months.push(formatter.format(d));
|
|
444
|
+
}
|
|
445
|
+
return months;
|
|
446
|
+
}, ...(ngDevMode ? [{ debugName: "monthNames" }] : []));
|
|
402
447
|
calendarDays = computed(() => {
|
|
403
448
|
const year = this.currentViewDate().getFullYear();
|
|
404
449
|
const month = this.currentViewDate().getMonth();
|
|
450
|
+
const firstDayIndex = this.getEffectiveFirstDayOfWeek();
|
|
405
451
|
const firstDayOfMonth = new Date(year, month, 1);
|
|
406
452
|
const lastDayOfMonth = new Date(year, month + 1, 0);
|
|
407
453
|
const days = [];
|
|
408
454
|
// Padding days from previous month
|
|
409
|
-
|
|
410
|
-
|
|
455
|
+
// Calculate how many days to fallback:
|
|
456
|
+
// current day of week (0-6) - firstDayIndex
|
|
457
|
+
// if result < 0, add 7
|
|
458
|
+
let startDayOfWeek = firstDayOfMonth.getDay();
|
|
459
|
+
let daysToBacktrack = startDayOfWeek - firstDayIndex;
|
|
460
|
+
if (daysToBacktrack < 0)
|
|
461
|
+
daysToBacktrack += 7;
|
|
462
|
+
for (let i = daysToBacktrack - 1; i >= 0; i--) {
|
|
411
463
|
days.push(new Date(year, month, -i));
|
|
412
464
|
}
|
|
413
465
|
// Days of current month
|
|
414
466
|
for (let i = 1; i <= lastDayOfMonth.getDate(); i++) {
|
|
415
467
|
days.push(new Date(year, month, i));
|
|
416
468
|
}
|
|
417
|
-
// Padding days for next month
|
|
418
|
-
const remaining = 42 - days.length;
|
|
469
|
+
// Padding days for next month to fill complete rows (usually 6 rows total 42 days)
|
|
470
|
+
const remaining = 42 - days.length;
|
|
419
471
|
for (let i = 1; i <= remaining; i++) {
|
|
420
472
|
days.push(new Date(year, month + 1, i));
|
|
421
473
|
}
|
|
@@ -432,15 +484,16 @@ class TecnualDatepickerComponent {
|
|
|
432
484
|
return years;
|
|
433
485
|
}, ...(ngDevMode ? [{ debugName: "yearsList" }] : []));
|
|
434
486
|
get formattedValue() {
|
|
487
|
+
const locale = this.locale();
|
|
435
488
|
if (this.mode() === 'single') {
|
|
436
|
-
return this.singleValue ? this.singleValue.toLocaleDateString() : '';
|
|
489
|
+
return this.singleValue ? this.singleValue.toLocaleDateString(locale) : '';
|
|
437
490
|
}
|
|
438
491
|
else {
|
|
439
492
|
if (this.rangeValue.start && this.rangeValue.end) {
|
|
440
|
-
return `${this.rangeValue.start.toLocaleDateString()} - ${this.rangeValue.end.toLocaleDateString()}`;
|
|
493
|
+
return `${this.rangeValue.start.toLocaleDateString(locale)} - ${this.rangeValue.end.toLocaleDateString(locale)}`;
|
|
441
494
|
}
|
|
442
495
|
else if (this.rangeValue.start) {
|
|
443
|
-
return `${this.rangeValue.start.toLocaleDateString()} - ...`;
|
|
496
|
+
return `${this.rangeValue.start.toLocaleDateString(locale)} - ...`;
|
|
444
497
|
}
|
|
445
498
|
return '';
|
|
446
499
|
}
|
|
@@ -448,7 +501,7 @@ class TecnualDatepickerComponent {
|
|
|
448
501
|
get headerLabel() {
|
|
449
502
|
const d = this.currentViewDate();
|
|
450
503
|
if (this.viewMode() === 'day') {
|
|
451
|
-
return d.toLocaleString(
|
|
504
|
+
return d.toLocaleString(this.locale(), { month: 'long', year: 'numeric' });
|
|
452
505
|
}
|
|
453
506
|
else if (this.viewMode() === 'month') {
|
|
454
507
|
return d.getFullYear().toString();
|
|
@@ -459,9 +512,17 @@ class TecnualDatepickerComponent {
|
|
|
459
512
|
return `${years[0]} - ${years[years.length - 1]}`;
|
|
460
513
|
}
|
|
461
514
|
}
|
|
462
|
-
toggleCalendar() {
|
|
515
|
+
toggleCalendar(event) {
|
|
463
516
|
if (this.disabled())
|
|
464
517
|
return;
|
|
518
|
+
// If clicking the input itself, ensure we don't close if already open
|
|
519
|
+
if (event && event.target.tagName === 'INPUT') {
|
|
520
|
+
if (!this.isOpen()) {
|
|
521
|
+
this.isOpen.set(true);
|
|
522
|
+
this.viewMode.set('day');
|
|
523
|
+
}
|
|
524
|
+
return;
|
|
525
|
+
}
|
|
465
526
|
if (!this.isOpen()) {
|
|
466
527
|
// Reset to day view when opening
|
|
467
528
|
this.viewMode.set('day');
|
|
@@ -516,19 +577,22 @@ class TecnualDatepickerComponent {
|
|
|
516
577
|
this.currentViewDate.set(new Date(year, d.getMonth(), 1));
|
|
517
578
|
this.viewMode.set('month');
|
|
518
579
|
}
|
|
519
|
-
selectDate(date) {
|
|
580
|
+
selectDate(date, closeCalendar = true) {
|
|
520
581
|
if (this.isDisabled(date))
|
|
521
582
|
return;
|
|
522
583
|
if (this.mode() === 'single') {
|
|
523
584
|
this.singleValue = date;
|
|
585
|
+
this.currentViewDate.set(new Date(date)); // Sync view
|
|
524
586
|
this.onChange(date);
|
|
525
|
-
|
|
587
|
+
if (closeCalendar)
|
|
588
|
+
this.isOpen.set(false);
|
|
526
589
|
}
|
|
527
590
|
else {
|
|
528
591
|
// Range logic
|
|
529
592
|
if (!this.rangeValue.start || (this.rangeValue.start && this.rangeValue.end)) {
|
|
530
593
|
// Start new range
|
|
531
594
|
this.rangeValue = { start: date, end: null };
|
|
595
|
+
this.currentViewDate.set(new Date(date)); // Sync view
|
|
532
596
|
}
|
|
533
597
|
else {
|
|
534
598
|
// Complete range
|
|
@@ -539,10 +603,66 @@ class TecnualDatepickerComponent {
|
|
|
539
603
|
this.rangeValue = { ...this.rangeValue, end: date };
|
|
540
604
|
}
|
|
541
605
|
this.onChange(this.rangeValue);
|
|
542
|
-
|
|
606
|
+
if (closeCalendar)
|
|
607
|
+
this.isOpen.set(false);
|
|
543
608
|
}
|
|
544
609
|
}
|
|
545
610
|
}
|
|
611
|
+
parseDate(value) {
|
|
612
|
+
if (!value)
|
|
613
|
+
return null;
|
|
614
|
+
const locale = this.locale();
|
|
615
|
+
// Use Intl to determine the order of parts
|
|
616
|
+
const parts = new Intl.DateTimeFormat(locale).formatToParts(new Date(2000, 10, 25)); // Nov 25, 2000
|
|
617
|
+
// Parts will contain type: 'day', 'month', 'year', 'literal'
|
|
618
|
+
const formatOrder = [];
|
|
619
|
+
parts.forEach(p => {
|
|
620
|
+
if (p.type === 'day' || p.type === 'month' || p.type === 'year') {
|
|
621
|
+
formatOrder.push(p.type);
|
|
622
|
+
}
|
|
623
|
+
});
|
|
624
|
+
// Split input by non-digit characters
|
|
625
|
+
const dateParts = value.split(/\D+/).filter(part => part.trim() !== '').map(p => parseInt(p, 10));
|
|
626
|
+
if (dateParts.length !== 3) {
|
|
627
|
+
// Fallback to standard parse if structure doesn't match
|
|
628
|
+
const d = new Date(value);
|
|
629
|
+
return isNaN(d.getTime()) ? null : d;
|
|
630
|
+
}
|
|
631
|
+
let day;
|
|
632
|
+
let month;
|
|
633
|
+
let year;
|
|
634
|
+
// Map input parts to Day/Month/Year based on locale order
|
|
635
|
+
for (let i = 0; i < 3; i++) {
|
|
636
|
+
const type = formatOrder[i];
|
|
637
|
+
const val = dateParts[i];
|
|
638
|
+
if (type === 'day')
|
|
639
|
+
day = val;
|
|
640
|
+
if (type === 'month')
|
|
641
|
+
month = val - 1; // JS months are 0-indexed
|
|
642
|
+
if (type === 'year')
|
|
643
|
+
year = val;
|
|
644
|
+
}
|
|
645
|
+
if (day === undefined || month === undefined || year === undefined)
|
|
646
|
+
return null;
|
|
647
|
+
// Validate year length (handle 2-digit years if needed, but let's stick to 4 for now or simple logic)
|
|
648
|
+
if (year < 100)
|
|
649
|
+
year += 2000; // Very basic 2-digit handling
|
|
650
|
+
const d = new Date(year, month, day);
|
|
651
|
+
if (d.getFullYear() === year && d.getMonth() === month && d.getDate() === day) {
|
|
652
|
+
return d;
|
|
653
|
+
}
|
|
654
|
+
return null;
|
|
655
|
+
}
|
|
656
|
+
onManualInput(event) {
|
|
657
|
+
const value = event.target.value;
|
|
658
|
+
if (!value)
|
|
659
|
+
return;
|
|
660
|
+
// Try localized parse first
|
|
661
|
+
let date = this.parseDate(value);
|
|
662
|
+
if (date) {
|
|
663
|
+
this.selectDate(date, false);
|
|
664
|
+
}
|
|
665
|
+
}
|
|
546
666
|
// Helper checks
|
|
547
667
|
isSelected(date) {
|
|
548
668
|
if (this.mode() === 'single') {
|
|
@@ -616,13 +736,13 @@ class TecnualDatepickerComponent {
|
|
|
616
736
|
}
|
|
617
737
|
}
|
|
618
738
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: TecnualDatepickerComponent, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
|
|
619
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.0", type: TecnualDatepickerComponent, isStandalone: true, selector: "tng-datepicker", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, mode: { classPropertyName: "mode", publicName: "mode", 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 }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { disabled: "disabledChange" }, host: { listeners: { "document:click": "onClickOutside($event)" } }, providers: [
|
|
739
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.0", type: TecnualDatepickerComponent, isStandalone: true, selector: "tng-datepicker", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, mode: { classPropertyName: "mode", publicName: "mode", 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 }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, locale: { classPropertyName: "locale", publicName: "locale", isSignal: true, isRequired: false, transformFunction: null }, firstDayOfWeek: { classPropertyName: "firstDayOfWeek", publicName: "firstDayOfWeek", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { disabled: "disabledChange" }, host: { listeners: { "document:click": "onClickOutside($event)" } }, providers: [
|
|
620
740
|
{
|
|
621
741
|
provide: NG_VALUE_ACCESSOR,
|
|
622
742
|
useExisting: forwardRef(() => TecnualDatepickerComponent),
|
|
623
743
|
multi: true
|
|
624
744
|
}
|
|
625
|
-
], ngImport: i0, template: "<div class=\"tng-datepicker-container\" [class.focused]=\"isOpen()\" [class.has-value]=\"formattedValue\" [class.disabled]=\"disabled()\">\n <!-- Trigger Field (Reusing Input Style) -->\n <div class=\"tng-input-trigger\" (click)=\"toggleCalendar()\">\n <fieldset class=\"tng-fieldset\" aria-hidden=\"true\">\n <legend class=\"tng-legend\"><span>{{ label() }}</span></legend>\n </fieldset>\n <label class=\"tng-label\">{{ label() }}</label>\n <
|
|
745
|
+
], ngImport: i0, template: "<div class=\"tng-datepicker-container\" [class.focused]=\"isOpen()\" [class.has-value]=\"formattedValue\" [class.disabled]=\"disabled()\">\n <!-- Trigger Field (Reusing Input Style) -->\n <div class=\"tng-input-trigger\" (click)=\"toggleCalendar($event)\">\n <fieldset class=\"tng-fieldset\" aria-hidden=\"true\">\n <legend class=\"tng-legend\"><span>{{ label() }}</span></legend>\n </fieldset>\n <label class=\"tng-label\">{{ label() }}</label>\n <input\n type=\"text\"\n class=\"tng-input-display\"\n [value]=\"formattedValue || (isOpen() ? '' : '')\"\n [placeholder]=\"isOpen() ? placeholder() : ''\"\n [disabled]=\"disabled()\"\n (input)=\"onManualInput($event)\"\n (click)=\"toggleCalendar($event)\"\n />\n <i class=\"fa-solid fa-calendar tng-icon\"></i>\n </div>\n\n <!-- Calendar Popup -->\n @if (isOpen()) {\n <div class=\"tng-calendar-popup\">\n <div class=\"tng-calendar-header\">\n <button type=\"button\" class=\"nav-btn\" (click)=\"prev($event)\">\n <i class=\"fa-solid fa-chevron-left\"></i>\n </button>\n <button type=\"button\" class=\"header-label-btn\" (click)=\"onHeaderClick()\">\n {{ headerLabel }}\n </button>\n <button type=\"button\" class=\"nav-btn\" (click)=\"next($event)\">\n <i class=\"fa-solid fa-chevron-right\"></i>\n </button>\n </div>\n\n @switch (viewMode()) {\n @case ('day') {\n <div class=\"tng-calendar-grid\">\n @for (day of daysOfWeek(); track day) {\n <div class=\"day-name\">{{ day }}</div>\n }\n @for (date of calendarDays(); track date.getTime()) {\n <div\n class=\"day-cell\"\n [class.not-current-month]=\"!isCurrentMonth(date)\"\n [class.today]=\"isToday(date)\"\n [class.selected]=\"isSelected(date)\"\n [class.in-range]=\"isInRange(date)\"\n [class.range-start]=\"mode() === 'range' && isSameDay(date, rangeValue.start)\"\n [class.range-end]=\"mode() === 'range' && isSameDay(date, rangeValue.end)\"\n [class.disabled]=\"isDisabled(date)\"\n (click)=\"selectDate(date)\"\n >\n {{ date.getDate() }}\n </div>\n }\n </div>\n }\n @case ('month') {\n <div class=\"tng-month-grid\">\n @for (month of monthNames(); track $index) {\n <div \n class=\"month-cell\"\n [class.current]=\"currentViewDate().getMonth() === $index\"\n (click)=\"selectMonth($index)\"\n >\n {{ month.substring(0, 3) }}\n </div>\n }\n </div>\n }\n @case ('year') {\n <div class=\"tng-year-grid\">\n @for (year of yearsList(); track year) {\n <div \n class=\"year-cell\"\n [class.current]=\"currentViewDate().getFullYear() === year\"\n (click)=\"selectYear(year)\"\n >\n {{ year }}\n </div>\n }\n </div>\n }\n }\n </div>\n }\n</div>\n", styles: [":host{display:block;margin-bottom:1.5rem;font-family:var(--tng-font-family, \"Inter\", sans-serif);position:relative}.tng-datepicker-container{position:relative}.tng-datepicker-container.disabled{opacity:.6;pointer-events:none}.tng-datepicker-container.disabled .tng-fieldset{border-color:var(--tng-border, #e0e0e0);background-color:var(--tng-background, #fafafa)}.tng-input-trigger{position:relative;padding:0 16px;height:48px;display:flex;align-items:center;cursor:pointer}.tng-input-trigger:hover .tng-fieldset{border-color:var(--tng-text-secondary, #757575)}.tng-fieldset{position:absolute;inset:0 0 5px;margin:0;padding:0 12px;border:1px solid var(--tng-border, #999);border-radius:var(--tng-border-radius, 4px);background-color:var(--tng-surface);backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px);pointer-events:none;transition:border-color .2s ease,border-width .1s ease;z-index:0}.tng-legend{width:auto;max-width:0;height:11px;font-size:.75em;visibility:hidden;white-space:nowrap;padding-inline:0px;transition:max-width .1s cubic-bezier(.4,0,.2,1)}.tng-legend span{padding:0 2px;visibility:visible;opacity:0}.tng-label{position:absolute;top:50%;left:16px;transform:translateY(-50%);color:var(--tng-text-secondary, #666);font-size:16px;font-weight:400;pointer-events:none;transform-origin:left top;transition:transform .2s cubic-bezier(.4,0,.2,1),color .2s ease;z-index:1}.tng-input-display{flex:1;font-size:16px;color:var(--tng-text, #333);height:100%;border:none;background:transparent;outline:none;padding:0 0 5px;margin:0;width:100%;font-family:inherit;pointer-events:auto;z-index:1}.tng-icon{color:var(--tng-text-secondary, #666);font-size:16px;margin-left:8px;z-index:1;padding-bottom:5px}.tng-datepicker-container.focused .tng-fieldset,.tng-datepicker-container.has-value .tng-fieldset{border-color:var(--tng-primary, #6200ee);border-width:2px}.tng-datepicker-container.focused .tng-label,.tng-datepicker-container.has-value .tng-label{transform:translateY(-24px) scale(.75)}.tng-datepicker-container.focused .tng-legend,.tng-datepicker-container.has-value .tng-legend{max-width:100%}.tng-datepicker-container.focused .tng-label{color:var(--tng-primary, #6200ee)}.tng-calendar-popup{position:absolute;top:100%;left:0;z-index:1000;margin-top:4px;background:var(--tng-surface, #fff);backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);border-radius:var(--tng-border-radius, 4px);box-shadow:var(--tng-shadow-md, 0 4px 20px rgba(0, 0, 0, .15));padding:16px;width:320px;animation:fadeIn .2s ease;border:1px solid var(--tng-border, #eee);color:var(--tng-text, #333)}@media(max-width:768px){.tng-calendar-popup{position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);width:90vw;max-width:350px;margin-top:0;box-shadow:0 10px 40px #0000004d,0 0 0 100vmax #0006;z-index:10000;animation:fadeInMobile .3s cubic-bezier(.16,1,.3,1)}}@keyframes fadeIn{0%{opacity:0;transform:translateY(-10px)}to{opacity:1;transform:translateY(0)}}@keyframes fadeInMobile{0%{opacity:0;transform:translate(-50%,-40%) scale(.95)}to{opacity:1;transform:translate(-50%,-50%) scale(1)}}.tng-calendar-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:16px}.tng-calendar-header .header-label-btn{background:none;border:none;font-weight:600;font-size:16px;color:var(--tng-text, #333);text-transform:capitalize;cursor:pointer;padding:4px 8px;border-radius:var(--tng-border-radius, 4px);transition:background-color .2s ease}.tng-calendar-header .header-label-btn:hover{background-color:var(--tng-background, #f5f5f5);color:var(--tng-primary, #6200ee)}.tng-calendar-header .nav-btn{background:none;border:none;cursor:pointer;padding:8px;border-radius:50%;display:flex;align-items:center;justify-content:center;color:var(--tng-text-secondary, #666);transition:background-color .2s ease}.tng-calendar-header .nav-btn:hover{background-color:var(--tng-background, #f5f5f5);color:var(--tng-primary, #6200ee)}.tng-calendar-header .nav-btn i{font-size:14px}.tng-calendar-grid{display:grid;grid-template-columns:repeat(7,1fr);gap:2px;text-align:center}.day-name{font-size:12px;color:var(--tng-text-secondary, #666);font-weight:500;margin-bottom:8px}.day-cell{aspect-ratio:1;display:flex;align-items:center;justify-content:center;font-size:14px;cursor:pointer;border-radius:50%;transition:all .2s ease;position:relative;color:var(--tng-text, #333)}.day-cell:hover:not(.disabled):not(.selected):not(.range-start):not(.range-end){background-color:var(--tng-background, #f5f5f5)}.day-cell.not-current-month{color:var(--tng-text-secondary, #ccc);opacity:.5}.day-cell.today{font-weight:600;color:var(--tng-primary, #6200ee)}.day-cell.selected,.day-cell.range-start,.day-cell.range-end{background-color:var(--tng-primary, #6200ee);color:var(--tng-primary-contrast, #fff)}.day-cell.selected.today,.day-cell.range-start.today,.day-cell.range-end.today{border-color:transparent}.day-cell.in-range{background-color:color-mix(in srgb,var(--tng-primary, #6200ee),var(--tng-surface));border-radius:0;color:var(--tng-primary, #6200ee)}.day-cell.in-range.range-start{border-top-right-radius:0;border-bottom-right-radius:0}.day-cell.in-range.range-end{border-top-left-radius:0;border-bottom-left-radius:0}.day-cell.range-start{border-radius:50% 0 0 50%;position:relative}.day-cell.range-start:after{content:\"\";position:absolute;inset:0 0 0 50%;background-color:color-mix(in srgb,var(--tng-primary, #6200ee),var(--tng-surface));z-index:-1}.day-cell.range-end{border-radius:0 50% 50% 0;position:relative}.day-cell.range-end:after{content:\"\";position:absolute;inset:0 50% 0 0;background-color:color-mix(in srgb,var(--tng-primary, #6200ee),var(--tng-surface));z-index:-1}.day-cell.selected{border-radius:50%}.day-cell.disabled{opacity:.3;pointer-events:none;cursor:not-allowed}.tng-month-grid,.tng-year-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:8px;padding:8px 0}.month-cell,.year-cell{height:48px;display:flex;align-items:center;justify-content:center;font-size:14px;cursor:pointer;border-radius:var(--tng-border-radius, 4px);transition:all .2s ease;color:var(--tng-text, #333)}.month-cell:hover,.year-cell:hover{background-color:var(--tng-background, #f5f5f5);color:var(--tng-primary, #6200ee)}.month-cell.current,.year-cell.current{font-weight:600;color:var(--tng-primary, #6200ee);border:1px solid var(--tng-primary, #6200ee)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
626
746
|
}
|
|
627
747
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.0", ngImport: i0, type: TecnualDatepickerComponent, decorators: [{
|
|
628
748
|
type: Component,
|
|
@@ -632,8 +752,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.0", ngImpor
|
|
|
632
752
|
useExisting: forwardRef(() => TecnualDatepickerComponent),
|
|
633
753
|
multi: true
|
|
634
754
|
}
|
|
635
|
-
], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"tng-datepicker-container\" [class.focused]=\"isOpen()\" [class.has-value]=\"formattedValue\" [class.disabled]=\"disabled()\">\n <!-- Trigger Field (Reusing Input Style) -->\n <div class=\"tng-input-trigger\" (click)=\"toggleCalendar()\">\n <fieldset class=\"tng-fieldset\" aria-hidden=\"true\">\n <legend class=\"tng-legend\"><span>{{ label() }}</span></legend>\n </fieldset>\n <label class=\"tng-label\">{{ label() }}</label>\n <
|
|
636
|
-
}], ctorParameters: () => [{ type: i0.ElementRef }], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], mode: [{ type: i0.Input, args: [{ isSignal: true, alias: "mode", required: false }] }], minDate: [{ type: i0.Input, args: [{ isSignal: true, alias: "minDate", required: false }] }], maxDate: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxDate", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }, { type: i0.Output, args: ["disabledChange"] }], id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], onClickOutside: [{
|
|
755
|
+
], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"tng-datepicker-container\" [class.focused]=\"isOpen()\" [class.has-value]=\"formattedValue\" [class.disabled]=\"disabled()\">\n <!-- Trigger Field (Reusing Input Style) -->\n <div class=\"tng-input-trigger\" (click)=\"toggleCalendar($event)\">\n <fieldset class=\"tng-fieldset\" aria-hidden=\"true\">\n <legend class=\"tng-legend\"><span>{{ label() }}</span></legend>\n </fieldset>\n <label class=\"tng-label\">{{ label() }}</label>\n <input\n type=\"text\"\n class=\"tng-input-display\"\n [value]=\"formattedValue || (isOpen() ? '' : '')\"\n [placeholder]=\"isOpen() ? placeholder() : ''\"\n [disabled]=\"disabled()\"\n (input)=\"onManualInput($event)\"\n (click)=\"toggleCalendar($event)\"\n />\n <i class=\"fa-solid fa-calendar tng-icon\"></i>\n </div>\n\n <!-- Calendar Popup -->\n @if (isOpen()) {\n <div class=\"tng-calendar-popup\">\n <div class=\"tng-calendar-header\">\n <button type=\"button\" class=\"nav-btn\" (click)=\"prev($event)\">\n <i class=\"fa-solid fa-chevron-left\"></i>\n </button>\n <button type=\"button\" class=\"header-label-btn\" (click)=\"onHeaderClick()\">\n {{ headerLabel }}\n </button>\n <button type=\"button\" class=\"nav-btn\" (click)=\"next($event)\">\n <i class=\"fa-solid fa-chevron-right\"></i>\n </button>\n </div>\n\n @switch (viewMode()) {\n @case ('day') {\n <div class=\"tng-calendar-grid\">\n @for (day of daysOfWeek(); track day) {\n <div class=\"day-name\">{{ day }}</div>\n }\n @for (date of calendarDays(); track date.getTime()) {\n <div\n class=\"day-cell\"\n [class.not-current-month]=\"!isCurrentMonth(date)\"\n [class.today]=\"isToday(date)\"\n [class.selected]=\"isSelected(date)\"\n [class.in-range]=\"isInRange(date)\"\n [class.range-start]=\"mode() === 'range' && isSameDay(date, rangeValue.start)\"\n [class.range-end]=\"mode() === 'range' && isSameDay(date, rangeValue.end)\"\n [class.disabled]=\"isDisabled(date)\"\n (click)=\"selectDate(date)\"\n >\n {{ date.getDate() }}\n </div>\n }\n </div>\n }\n @case ('month') {\n <div class=\"tng-month-grid\">\n @for (month of monthNames(); track $index) {\n <div \n class=\"month-cell\"\n [class.current]=\"currentViewDate().getMonth() === $index\"\n (click)=\"selectMonth($index)\"\n >\n {{ month.substring(0, 3) }}\n </div>\n }\n </div>\n }\n @case ('year') {\n <div class=\"tng-year-grid\">\n @for (year of yearsList(); track year) {\n <div \n class=\"year-cell\"\n [class.current]=\"currentViewDate().getFullYear() === year\"\n (click)=\"selectYear(year)\"\n >\n {{ year }}\n </div>\n }\n </div>\n }\n }\n </div>\n }\n</div>\n", styles: [":host{display:block;margin-bottom:1.5rem;font-family:var(--tng-font-family, \"Inter\", sans-serif);position:relative}.tng-datepicker-container{position:relative}.tng-datepicker-container.disabled{opacity:.6;pointer-events:none}.tng-datepicker-container.disabled .tng-fieldset{border-color:var(--tng-border, #e0e0e0);background-color:var(--tng-background, #fafafa)}.tng-input-trigger{position:relative;padding:0 16px;height:48px;display:flex;align-items:center;cursor:pointer}.tng-input-trigger:hover .tng-fieldset{border-color:var(--tng-text-secondary, #757575)}.tng-fieldset{position:absolute;inset:0 0 5px;margin:0;padding:0 12px;border:1px solid var(--tng-border, #999);border-radius:var(--tng-border-radius, 4px);background-color:var(--tng-surface);backdrop-filter:blur(8px);-webkit-backdrop-filter:blur(8px);pointer-events:none;transition:border-color .2s ease,border-width .1s ease;z-index:0}.tng-legend{width:auto;max-width:0;height:11px;font-size:.75em;visibility:hidden;white-space:nowrap;padding-inline:0px;transition:max-width .1s cubic-bezier(.4,0,.2,1)}.tng-legend span{padding:0 2px;visibility:visible;opacity:0}.tng-label{position:absolute;top:50%;left:16px;transform:translateY(-50%);color:var(--tng-text-secondary, #666);font-size:16px;font-weight:400;pointer-events:none;transform-origin:left top;transition:transform .2s cubic-bezier(.4,0,.2,1),color .2s ease;z-index:1}.tng-input-display{flex:1;font-size:16px;color:var(--tng-text, #333);height:100%;border:none;background:transparent;outline:none;padding:0 0 5px;margin:0;width:100%;font-family:inherit;pointer-events:auto;z-index:1}.tng-icon{color:var(--tng-text-secondary, #666);font-size:16px;margin-left:8px;z-index:1;padding-bottom:5px}.tng-datepicker-container.focused .tng-fieldset,.tng-datepicker-container.has-value .tng-fieldset{border-color:var(--tng-primary, #6200ee);border-width:2px}.tng-datepicker-container.focused .tng-label,.tng-datepicker-container.has-value .tng-label{transform:translateY(-24px) scale(.75)}.tng-datepicker-container.focused .tng-legend,.tng-datepicker-container.has-value .tng-legend{max-width:100%}.tng-datepicker-container.focused .tng-label{color:var(--tng-primary, #6200ee)}.tng-calendar-popup{position:absolute;top:100%;left:0;z-index:1000;margin-top:4px;background:var(--tng-surface, #fff);backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);border-radius:var(--tng-border-radius, 4px);box-shadow:var(--tng-shadow-md, 0 4px 20px rgba(0, 0, 0, .15));padding:16px;width:320px;animation:fadeIn .2s ease;border:1px solid var(--tng-border, #eee);color:var(--tng-text, #333)}@media(max-width:768px){.tng-calendar-popup{position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);width:90vw;max-width:350px;margin-top:0;box-shadow:0 10px 40px #0000004d,0 0 0 100vmax #0006;z-index:10000;animation:fadeInMobile .3s cubic-bezier(.16,1,.3,1)}}@keyframes fadeIn{0%{opacity:0;transform:translateY(-10px)}to{opacity:1;transform:translateY(0)}}@keyframes fadeInMobile{0%{opacity:0;transform:translate(-50%,-40%) scale(.95)}to{opacity:1;transform:translate(-50%,-50%) scale(1)}}.tng-calendar-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:16px}.tng-calendar-header .header-label-btn{background:none;border:none;font-weight:600;font-size:16px;color:var(--tng-text, #333);text-transform:capitalize;cursor:pointer;padding:4px 8px;border-radius:var(--tng-border-radius, 4px);transition:background-color .2s ease}.tng-calendar-header .header-label-btn:hover{background-color:var(--tng-background, #f5f5f5);color:var(--tng-primary, #6200ee)}.tng-calendar-header .nav-btn{background:none;border:none;cursor:pointer;padding:8px;border-radius:50%;display:flex;align-items:center;justify-content:center;color:var(--tng-text-secondary, #666);transition:background-color .2s ease}.tng-calendar-header .nav-btn:hover{background-color:var(--tng-background, #f5f5f5);color:var(--tng-primary, #6200ee)}.tng-calendar-header .nav-btn i{font-size:14px}.tng-calendar-grid{display:grid;grid-template-columns:repeat(7,1fr);gap:2px;text-align:center}.day-name{font-size:12px;color:var(--tng-text-secondary, #666);font-weight:500;margin-bottom:8px}.day-cell{aspect-ratio:1;display:flex;align-items:center;justify-content:center;font-size:14px;cursor:pointer;border-radius:50%;transition:all .2s ease;position:relative;color:var(--tng-text, #333)}.day-cell:hover:not(.disabled):not(.selected):not(.range-start):not(.range-end){background-color:var(--tng-background, #f5f5f5)}.day-cell.not-current-month{color:var(--tng-text-secondary, #ccc);opacity:.5}.day-cell.today{font-weight:600;color:var(--tng-primary, #6200ee)}.day-cell.selected,.day-cell.range-start,.day-cell.range-end{background-color:var(--tng-primary, #6200ee);color:var(--tng-primary-contrast, #fff)}.day-cell.selected.today,.day-cell.range-start.today,.day-cell.range-end.today{border-color:transparent}.day-cell.in-range{background-color:color-mix(in srgb,var(--tng-primary, #6200ee),var(--tng-surface));border-radius:0;color:var(--tng-primary, #6200ee)}.day-cell.in-range.range-start{border-top-right-radius:0;border-bottom-right-radius:0}.day-cell.in-range.range-end{border-top-left-radius:0;border-bottom-left-radius:0}.day-cell.range-start{border-radius:50% 0 0 50%;position:relative}.day-cell.range-start:after{content:\"\";position:absolute;inset:0 0 0 50%;background-color:color-mix(in srgb,var(--tng-primary, #6200ee),var(--tng-surface));z-index:-1}.day-cell.range-end{border-radius:0 50% 50% 0;position:relative}.day-cell.range-end:after{content:\"\";position:absolute;inset:0 50% 0 0;background-color:color-mix(in srgb,var(--tng-primary, #6200ee),var(--tng-surface));z-index:-1}.day-cell.selected{border-radius:50%}.day-cell.disabled{opacity:.3;pointer-events:none;cursor:not-allowed}.tng-month-grid,.tng-year-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:8px;padding:8px 0}.month-cell,.year-cell{height:48px;display:flex;align-items:center;justify-content:center;font-size:14px;cursor:pointer;border-radius:var(--tng-border-radius, 4px);transition:all .2s ease;color:var(--tng-text, #333)}.month-cell:hover,.year-cell:hover{background-color:var(--tng-background, #f5f5f5);color:var(--tng-primary, #6200ee)}.month-cell.current,.year-cell.current{font-weight:600;color:var(--tng-primary, #6200ee);border:1px solid var(--tng-primary, #6200ee)}\n"] }]
|
|
756
|
+
}], ctorParameters: () => [{ type: i0.ElementRef }], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], mode: [{ type: i0.Input, args: [{ isSignal: true, alias: "mode", required: false }] }], minDate: [{ type: i0.Input, args: [{ isSignal: true, alias: "minDate", required: false }] }], maxDate: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxDate", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }, { type: i0.Output, args: ["disabledChange"] }], id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], locale: [{ type: i0.Input, args: [{ isSignal: true, alias: "locale", required: false }] }], firstDayOfWeek: [{ type: i0.Input, args: [{ isSignal: true, alias: "firstDayOfWeek", required: false }] }], onClickOutside: [{
|
|
637
757
|
type: HostListener,
|
|
638
758
|
args: ['document:click', ['$event']]
|
|
639
759
|
}] } });
|