npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@libs-ui/components-datetime-picker

v0.2.357-3

Published

> Component chọn ngày tháng mạnh mẽ, hỗ trợ single date, date range, time picker, quick ranges và validation.

Readme

@libs-ui/components-datetime-picker

Component chọn ngày tháng mạnh mẽ, hỗ trợ single date, date range, time picker, quick ranges và validation.

Giới thiệu

LibsUiComponentsDatetimePickerComponent là một Angular Standalone Component cho phép người dùng chọn ngày tháng với nhiều chế độ linh hoạt: single date, date range, có hoặc không có time picker. Component tích hợp sẵn quick ranges (hôm nay, tuần này, tháng này...), custom ranges mở rộng, min/max date validation, required validation và hỗ trợ two-way binding qua Signal API.

Tính năng

  • ✅ Single Date Picker — chọn một ngày duy nhất
  • ✅ Date Range Picker — chọn khoảng thời gian từ - đến
  • ✅ Time Picker tích hợp — bật/tắt linh hoạt qua [hasTimePicker]
  • ✅ Quick Ranges — hôm nay, hôm qua, 7 ngày, 30 ngày, tháng này, tháng trước, 90 ngày
  • ✅ Custom Ranges — mở rộng danh sách chọn nhanh qua [extendRanges]
  • ✅ Auto Apply — tự động xác nhận khi người dùng chọn xong
  • ✅ Min/Max Date — giới hạn ngày có thể chọn
  • ✅ Required Validation — tích hợp kiểm tra bắt buộc nhập
  • ✅ Function Control API — checkIsValid(), reset(), resetError() qua (outFunctionsControl)
  • ✅ Two-way binding — [(singleDateSelected)], [(dateRangeSelected)] qua Signal model
  • ✅ Label tích hợp — cấu hình label trái/phải qua [labelConfig]
  • ✅ Localization — hỗ trợ đa ngôn ngữ Tiếng Việt / English
  • ✅ Standalone + OnPush — hiệu năng tối ưu

Khi nào sử dụng

  • Khi cần chọn một ngày cụ thể (form đơn, filter)
  • Khi cần chọn khoảng thời gian để lọc dữ liệu (báo cáo, thống kê)
  • Khi cần chọn cả ngày và giờ (đặt lịch, nhập thời gian)
  • Khi cần quick ranges để người dùng chọn nhanh (dashboard filter)
  • Khi cần validation bắt buộc nhập ngày trong form

Cài đặt

npm install @libs-ui/components-datetime-picker

Import

import { LibsUiComponentsDatetimePickerComponent } from '@libs-ui/components-datetime-picker';

// Interfaces & Types
import {
  IEmitSingleDate,
  IEmitDateRange,
  IDateTimeValid,
  IDateTimePickerFunctionControlEvent,
  IDateRange,
  LocalizationConfig,
} from '@libs-ui/components-datetime-picker';

// Define helpers
import {
  getDateOptions,
  getDateOptionsDefault,
  getDateRangeDefault,
  DEFAULT_MIN_YEAR,
  DEFAULT_MAX_YEAR,
} from '@libs-ui/components-datetime-picker';

Ví dụ sử dụng

1. Date Range Picker cơ bản (không có giờ)

import { Component } from '@angular/core';
import { LibsUiComponentsDatetimePickerComponent, IEmitDateRange } from '@libs-ui/components-datetime-picker';

@Component({
  selector: 'app-filter',
  standalone: true,
  imports: [LibsUiComponentsDatetimePickerComponent],
  template: `
    <libs_ui-components-datetime-picker
      [labelConfig]="{ labelLeft: 'Khoảng thời gian' }"
      [widthByLabel]="false"
      [isSingle]="false"
      [hasTimePicker]="false"
      (outSelectDateRange)="handlerSelectDateRange($event)"
    />
  `,
})
export class FilterComponent {
  handlerSelectDateRange(event: IEmitDateRange): void {
    event.stopPropagation();
    console.log('startDate:', event.startDate);
    console.log('endDate:', event.endDate);
    console.log('quickRangeId:', event.quickRangeId);
  }
}

2. Single Date Picker với giờ và giá trị mặc định

import { Component, signal } from '@angular/core';
import {
  LibsUiComponentsDatetimePickerComponent,
  IEmitSingleDate,
} from '@libs-ui/components-datetime-picker';
import { getDayjs } from '@libs-ui/utils';

@Component({
  selector: 'app-date-form',
  standalone: true,
  imports: [LibsUiComponentsDatetimePickerComponent],
  template: `
    <libs_ui-components-datetime-picker
      [labelConfig]="{ labelLeft: 'Ngày thực hiện' }"
      [widthByLabel]="false"
      [isSingle]="true"
      [hasTimePicker]="true"
      [(singleDateSelected)]="selectedDate"
      (outSelectSingleDate)="handlerSelectSingleDate($event)"
    />
  `,
})
export class DateFormComponent {
  readonly selectedDate = signal<IEmitSingleDate>({ date: getDayjs() });

  handlerSelectSingleDate(event: IEmitSingleDate): void {
    event.stopPropagation();
    console.log('date:', event.date);
    console.log('displayLabel:', event.displayLabel);
  }
}

3. Date Range với validation bắt buộc và Function Control

import { Component } from '@angular/core';
import {
  LibsUiComponentsDatetimePickerComponent,
  IEmitDateRange,
  IDateTimePickerFunctionControlEvent,
} from '@libs-ui/components-datetime-picker';

@Component({
  selector: 'app-report-filter',
  standalone: true,
  imports: [LibsUiComponentsDatetimePickerComponent],
  template: `
    <libs_ui-components-datetime-picker
      [labelConfig]="{ labelLeft: 'Kỳ báo cáo' }"
      [widthByLabel]="false"
      [isSingle]="false"
      [hasTimePicker]="false"
      [validRequired]="{ message: 'Vui lòng chọn khoảng thời gian' }"
      (outSelectDateRange)="handlerSelectDateRange($event)"
      (outFunctionsControl)="handlerFunctionsControl($event)"
    />

    <button (click)="handlerSubmit()">Tạo báo cáo</button>
  `,
})
export class ReportFilterComponent {
  private functionControl?: IDateTimePickerFunctionControlEvent;

  handlerSelectDateRange(event: IEmitDateRange): void {
    event.stopPropagation();
    console.log('range:', event.startDate, '-', event.endDate);
  }

  handlerFunctionsControl(control: IDateTimePickerFunctionControlEvent): void {
    this.functionControl = control;
  }

  async handlerSubmit(): Promise<void> {
    const isValid = await this.functionControl?.checkIsValid();
    if (!isValid) return;
    // proceed with report generation
  }
}

4. Date Range với preset giá trị ban đầu (30 ngày qua)

import { Component, signal } from '@angular/core';
import {
  LibsUiComponentsDatetimePickerComponent,
  IEmitDateRange,
} from '@libs-ui/components-datetime-picker';
import { getDayjs } from '@libs-ui/utils';

@Component({
  selector: 'app-dashboard-filter',
  standalone: true,
  imports: [LibsUiComponentsDatetimePickerComponent],
  template: `
    <libs_ui-components-datetime-picker
      [labelConfig]="{ labelLeft: 'Lọc theo ngày' }"
      [widthByLabel]="false"
      [isSingle]="false"
      [hasTimePicker]="false"
      [(dateRangeSelected)]="dateRange"
      (outSelectDateRange)="handlerSelectDateRange($event)"
    />
  `,
})
export class DashboardFilterComponent {
  readonly dateRange = signal<IEmitDateRange>({
    quickRangeId: '_30days_ago',
    startDate: getDayjs().subtract(29, 'days').hour(0).minute(0).second(0).millisecond(0).format('YYYY-MM-DDTHH:mm:ss[Z]'),
    endDate: getDayjs().hour(23).minute(59).second(59).format('YYYY-MM-DDTHH:mm:ss[Z]'),
  });

  handlerSelectDateRange(event: IEmitDateRange): void {
    event.stopPropagation();
    console.log('selected range:', event);
  }
}

5. Date Range với Custom Ranges mở rộng

import { Component } from '@angular/core';
import {
  LibsUiComponentsDatetimePickerComponent,
  IEmitDateRange,
  IDateRange,
} from '@libs-ui/components-datetime-picker';
import { getDayjs } from '@libs-ui/utils';

@Component({
  selector: 'app-custom-range',
  standalone: true,
  imports: [LibsUiComponentsDatetimePickerComponent],
  template: `
    <libs_ui-components-datetime-picker
      [labelConfig]="{ labelLeft: 'Khoảng tùy chỉnh' }"
      [widthByLabel]="false"
      [isSingle]="false"
      [hasTimePicker]="false"
      [extendRanges]="customRanges"
      (outSelectDateRange)="handlerSelectDateRange($event)"
    />
  `,
})
export class CustomRangeComponent {
  readonly customRanges: IDateRange[] = [
    {
      id: 'this_quarter',
      label: 'Quý này',
      values: [getDayjs().startOf('quarter'), getDayjs().endOf('quarter')],
    },
    {
      id: 'last_quarter',
      label: 'Quý trước',
      values: [
        getDayjs().subtract(1, 'quarter').startOf('quarter'),
        getDayjs().subtract(1, 'quarter').endOf('quarter'),
      ],
    },
  ];

  handlerSelectDateRange(event: IEmitDateRange): void {
    event.stopPropagation();
    console.log('selected:', event);
  }
}

6. Single Date với Min/Max Date

import { Component } from '@angular/core';
import {
  LibsUiComponentsDatetimePickerComponent,
  IEmitSingleDate,
} from '@libs-ui/components-datetime-picker';
import { getDayjs } from '@libs-ui/utils';

@Component({
  selector: 'app-birth-date',
  standalone: true,
  imports: [LibsUiComponentsDatetimePickerComponent],
  template: `
    <libs_ui-components-datetime-picker
      [labelConfig]="{ labelLeft: 'Ngày sinh' }"
      [widthByLabel]="false"
      [isSingle]="true"
      [hasTimePicker]="false"
      [minDate]="minDate"
      [maxDate]="maxDate"
      (outSelectSingleDate)="handlerSelectSingleDate($event)"
    />
  `,
})
export class BirthDateComponent {
  readonly minDate = getDayjs('1945-01-01');
  readonly maxDate = getDayjs();

  handlerSelectSingleDate(event: IEmitSingleDate): void {
    event.stopPropagation();
    console.log('birth date:', event.date);
  }
}

7. Auto Apply với reset

import { Component } from '@angular/core';
import {
  LibsUiComponentsDatetimePickerComponent,
  IEmitDateRange,
  IEmitSingleDate,
  IDateTimePickerFunctionControlEvent,
} from '@libs-ui/components-datetime-picker';

@Component({
  selector: 'app-auto-filter',
  standalone: true,
  imports: [LibsUiComponentsDatetimePickerComponent],
  template: `
    <libs_ui-components-datetime-picker
      [labelConfig]="{ labelLeft: 'Ngày tạo' }"
      [widthByLabel]="false"
      [isSingle]="false"
      [hasTimePicker]="true"
      [autoApply]="true"
      [allowReset]="true"
      (outSelectDateRange)="handlerSelectDateRange($event)"
      (outReset)="handlerReset($event)"
      (outFunctionsControl)="handlerFunctionsControl($event)"
    />
  `,
})
export class AutoFilterComponent {
  private functionControl?: IDateTimePickerFunctionControlEvent;

  handlerSelectDateRange(event: IEmitDateRange): void {
    event.stopPropagation();
    console.log('range:', event);
  }

  handlerReset(event: IEmitDateRange | IEmitSingleDate | undefined): void {
    event?.stopPropagation?.();
    console.log('picker reset', event);
  }

  handlerFunctionsControl(control: IDateTimePickerFunctionControlEvent): void {
    this.functionControl = control;
  }

  async handlerClearPicker(): Promise<void> {
    await this.functionControl?.reset(false);
  }
}

@Input()

| Input | Type | Default | Mô tả | Ví dụ | |---|---|---|---|---| | [allowReset] | boolean | true | Hiển thị nút reset để xóa ngày đã chọn | [allowReset]="false" | | [autoApply] | boolean | false | Tự động xác nhận ngay khi người dùng chọn đủ ngày (không cần nhấn Lưu) | [autoApply]="true" | | [classInclude] | string | '' | CSS class thêm vào wrapper ngoài cùng của component | [classInclude]="'mt-4'" | | [classIncludeCustomRanges] | string | '' | CSS class thêm vào vùng danh sách quick ranges | [classIncludeCustomRanges]="'w-[180px]'" | | [classPickerContentInclude] | string | '' | CSS class thêm vào vùng nội dung popover bên trong | [classPickerContentInclude]="'p-2'" | | [classPickerInclude] | string | '' | CSS class thêm vào trigger button hiển thị nhãn ngày | [classPickerInclude]="'w-full'" | | [dateOptions] | LocalizationConfig | getDateOptionsDefault() | Cấu hình localization: tên tháng, ngày, nhãn nút, danh sách quick ranges | [dateOptions]="myConfig" | | [(dateRangeSelected)] | IEmitDateRange | undefined | Two-way binding giá trị khoảng ngày đã chọn (dùng cho date range mode) | [(dateRangeSelected)]="dateRange" | | [defaultWidth] | number | undefined | Ghi đè chiều rộng mặc định của trigger (px). Ưu tiên sau [widthByLabel]="false" | [defaultWidth]="300" | | [directionPopover] | TYPE_POPOVER_DIRECTION | 'bottom' | Hướng mở của popover calendar | [directionPopover]="'top'" | | [disable] | boolean | false | Vô hiệu hoá toàn bộ picker, không cho tương tác | [disable]="true" | | [extendRanges] | Array<IDateRange> | [] | Danh sách quick ranges tuỳ chỉnh thêm vào ngoài danh sách mặc định | [extendRanges]="customRanges" | | [flagMouse] | IFlagMouse (model) | { isMouseEnter: false, isMouseEnterContent: false } | Two-way binding trạng thái hover chuột (dùng khi tích hợp với popover cha) | [(flagMouse)]="flagMouse" | | [hasTimePicker] | boolean | true | Hiển thị bộ chọn giờ/phút bên cạnh calendar | [hasTimePicker]="false" | | [ignoreBorderQuickRange] | boolean | false | Ẩn viền ngăn cách giữa quick ranges và calendar | [ignoreBorderQuickRange]="true" | | [ignoreStopPropagationEvent] | boolean | false | Bỏ qua stopPropagation trên sự kiện click (dùng khi component cha cần nhận event bubble) | [ignoreStopPropagationEvent]="true" | | [isBorderError] | boolean | false | Hiển thị viền đỏ lỗi ngay lập tức mà không cần chạy validation | [isBorderError]="true" | | [isNgContent] | boolean | false | Chế độ dùng ng-content thay thế trigger mặc định | [isNgContent]="true" | | [isSingle] | boolean | false | Chuyển sang chế độ chọn single date (thay vì date range) | [isSingle]="true" | | [labelConfig] | ILabel | undefined | Cấu hình label hiển thị bên trái hoặc bên phải picker | [labelConfig]="{ labelLeft: 'Ngày tạo' }" | | [listYearHiddenInputSearch] | boolean | false | Ẩn ô tìm kiếm năm trong dropdown chọn năm | [listYearHiddenInputSearch]="true" | | [maxDate] | Dayjs \| string | undefined | Ngày tối đa người dùng có thể chọn (ngày sau ngày này bị disabled) | [maxDate]="'2025-12-31'" | | [minDate] | Dayjs \| string | undefined | Ngày tối thiểu người dùng có thể chọn (ngày trước ngày này bị disabled) | [minDate]="'2020-01-01'" | | [placeholder] | string | undefined | Văn bản gợi ý hiển thị khi chưa chọn ngày | [placeholder]="'Chọn ngày'" | | [positionQuickRanges] | 'left' \| 'right' | 'left' | Vị trí hiển thị danh sách quick ranges (trái hay phải so với calendar) | [positionQuickRanges]="'right'" | | [rangesPopoverPosition] | 'start' \| 'center' \| 'end' | 'start' | Căn chỉnh ngang của popover so với trigger | [rangesPopoverPosition]="'end'" | | [rangesPopoverPositionDistance] | number | 0 | Khoảng cách dịch chuyển ngang của popover (px) | [rangesPopoverPositionDistance]="8" | | [readonly] | boolean | false | Chế độ chỉ đọc, không cho phép thay đổi ngày | [readonly]="true" | | [(singleDateSelected)] | IEmitSingleDate | undefined | Two-way binding giá trị ngày đơn đã chọn (dùng cho single mode) | [(singleDateSelected)]="selectedDate" | | [showCustomRangeLabel] | boolean | true | Hiển thị tuỳ chọn "Tuỳ Chỉnh" ở cuối danh sách quick ranges | [showCustomRangeLabel]="false" | | [trackDateRageUpdateLabel] | boolean | false | Theo dõi reactive thay đổi dateRangeSelected để cập nhật label hiển thị | [trackDateRageUpdateLabel]="true" | | [useColorModeExist] | boolean | false | Dùng màu sắc theo color mode hệ thống (dark/light theme) | [useColorModeExist]="true" | | [validRequired] | IDateTimeValid | undefined | Cấu hình validation bắt buộc nhập. Khi không có giá trị và gọi checkIsValid() sẽ hiển thị lỗi | [validRequired]="{ message: 'Bắt buộc' }" | | [widthByLabel] | boolean | true | Khi true: chiều rộng trigger co dãn theo label. Khi false: dùng chiều rộng cố định tự tính theo mode | [widthByLabel]="false" | | [widthByParent] | boolean | false | Chiều rộng trigger theo 100% chiều rộng phần tử cha | [widthByParent]="true" | | [zIndex] | number | 1200 | z-index của popover calendar | [zIndex]="1500" |

@Output()

| Output | Type | Mô tả | Handler TS | Binding HTML | |---|---|---|---|---| | (outChangStageFlagMouse) | IFlagMouse | Phát ra khi trạng thái hover chuột thay đổi (tích hợp với popover cha) | handlerChangStageFlagMouse(e: IFlagMouse): void { e.stopPropagation?.(); ... } | (outChangStageFlagMouse)="handlerChangStageFlagMouse($event)" | | (outFunctionsControl) | IDateTimePickerFunctionControlEvent | Phát ra ngay khi component khởi tạo, cung cấp API kiểm soát: checkIsValid, reset, resetError | handlerFunctionsControl(e: IDateTimePickerFunctionControlEvent): void { this.funcCtrl = e; } | (outFunctionsControl)="handlerFunctionsControl($event)" | | (outReset) | IEmitDateRange \| IEmitSingleDate \| undefined | Phát ra khi người dùng nhấn nút reset | handlerReset(e: IEmitDateRange \| IEmitSingleDate \| undefined): void { e?.stopPropagation?.(); ... } | (outReset)="handlerReset($event)" | | (outSelectDateRange) | IEmitDateRange | Phát ra khi người dùng xác nhận chọn khoảng ngày (date range mode) | handlerSelectDateRange(e: IEmitDateRange): void { e.stopPropagation(); ... } | (outSelectDateRange)="handlerSelectDateRange($event)" | | (outSelectSingleDate) | IEmitSingleDate | Phát ra khi người dùng xác nhận chọn một ngày (single mode) | handlerSelectSingleDate(e: IEmitSingleDate): void { e.stopPropagation(); ... } | (outSelectSingleDate)="handlerSelectSingleDate($event)" |

Function Control API

Nhận qua (outFunctionsControl) khi component khởi tạo. Dùng để tương tác chương trình với picker.

import { IDateTimePickerFunctionControlEvent } from '@libs-ui/components-datetime-picker';

export class MyComponent {
  private functionControl?: IDateTimePickerFunctionControlEvent;

  handlerFunctionsControl(control: IDateTimePickerFunctionControlEvent): void {
    this.functionControl = control;
  }

  // Kiểm tra hợp lệ (hiển thị lỗi nếu validRequired được cấu hình và chưa chọn ngày)
  async handlerValidate(): Promise<void> {
    const isValid = await this.functionControl?.checkIsValid();
    console.log('isValid:', isValid); // true | false
  }

  // Reset picker về trạng thái trống
  async handlerClear(): Promise<void> {
    await this.functionControl?.reset(false);
  }

  // Reset về giá trị cụ thể
  async handlerResetToRange(): Promise<void> {
    await this.functionControl?.reset(false, {
      startDate: '2024-01-01',
      endDate: '2024-01-31',
    });
  }

  // Xóa thông báo lỗi đang hiển thị
  async handlerClearError(): Promise<void> {
    await this.functionControl?.resetError();
  }

  // Đặt thông báo lỗi tuỳ chỉnh
  async handlerSetError(): Promise<void> {
    await this.functionControl?.resetError('Ngày không hợp lệ với kỳ kế toán');
  }
}

| Method | Signature | Mô tả | |---|---|---| | checkIsValid | () => Promise<boolean> | Chạy validation, hiển thị lỗi nếu [validRequired] được cấu hình và chưa chọn ngày. Trả về true nếu hợp lệ | | reset | (checkIsValid?: boolean, dateRangeReset?: IEmitDateRange, singleDateReset?: IEmitSingleDate) => Promise<void> | Reset picker. checkIsValid=true sẽ chạy lại validation sau reset. Có thể truyền giá trị để reset về ngày cụ thể | | resetError | (message?: string, interpolateParams?: TYPE_OBJECT) => Promise<void> | Xóa hoặc đặt lại thông báo lỗi. Gọi không tham số để xóa lỗi |

Types & Interfaces

import {
  IEmitSingleDate,
  IEmitDateRange,
  IDateTimeValid,
  IDateTimePickerFunctionControlEvent,
  IDateRange,
  LocalizationConfig,
  TYPE_RANGE_KEY,
} from '@libs-ui/components-datetime-picker';

IEmitSingleDate

Dữ liệu trả về khi chọn single date.

export interface IEmitSingleDate {
  displayLabel?: string;       // Chuỗi hiển thị trên trigger (VD: "15/06/2024 09:30")
  date: string | Dayjs | undefined;  // Giá trị ngày đã chọn
  values?: {
    month: string | number;
    year: string | number;
    day: string | number;
    hour?: string | number;
    minute?: string | number;
  };
}

IEmitDateRange

Dữ liệu trả về khi chọn date range.

export interface IEmitDateRange {
  quickRangeId?: string;       // ID của quick range đã chọn (VD: 'today', '_7days_ago', 'this_month')
  displayLabel?: string;       // Chuỗi hiển thị (VD: "01/06/2024 - 30/06/2024")
  startDate: string | Dayjs | undefined;
  endDate: string | Dayjs | undefined;
}

IDateTimeValid

Cấu hình validation bắt buộc nhập.

export interface IDateTimeValid {
  message?: string;                        // Thông báo lỗi tuỳ chỉnh (hỗ trợ i18n key)
  interpolateParams?: Record<string, any>; // Tham số nội suy cho i18n
  ignoreMessage?: boolean;                 // Ẩn văn bản lỗi, chỉ hiện viền đỏ
}

IDateTimePickerFunctionControlEvent

API kiểm soát picker từ bên ngoài, nhận qua (outFunctionsControl).

export interface IDateTimePickerFunctionControlEvent {
  checkIsValid: () => Promise<boolean>;
  resetError: (message?: string, interpolateParams?: TYPE_OBJECT) => Promise<void>;
  reset: (
    checkIsValid?: boolean,
    dateRangeSelected?: IEmitDateRange,
    singleDateReset?: IEmitSingleDate
  ) => Promise<void>;
}

IDateRange

Cấu trúc một mục custom range trong [extendRanges].

export interface IDateRange {
  id: string;                // ID duy nhất, sẽ được trả về trong IEmitDateRange.quickRangeId
  label: string;             // Nhãn hiển thị trong danh sách quick ranges
  values?: Array<Dayjs>;     // [startDate, endDate] - nếu không truyền, sẽ hiển thị như "Custom Range"
}

LocalizationConfig

Cấu hình ngôn ngữ và danh sách quick ranges mặc định.

export interface LocalizationConfig {
  monthNames: string[];                    // 12 tên tháng
  ranges: { [key: string]: string };       // Map ID quick range → nhãn hiển thị
  daysOfWeek: string[];                    // 7 tên ngày trong tuần
  applyLabel: string;                      // Nhãn nút xác nhận
  cancelLabel: string;                     // Nhãn nút huỷ
  fromLabel: string;                       // Nhãn "Từ"
  toLabel: string;                         // Nhãn "Đến"
  customRangeLabel: string;                // Nhãn tùy chọn "Tuỳ Chỉnh"
  format?: string;
  direction?: string;
  separator?: string;
  weekLabel?: string;
  clearLabel?: string;
  firstDay?: number;                       // Ngày đầu tuần (0 = CN, 1 = T2)
  displayFormat?: string;
}

TYPE_RANGE_KEY

Danh sách ID quick range mặc định của hệ thống.

export type TYPE_RANGE_KEY =
  | 'today'
  | 'yesterday'
  | '_7days_ago'
  | '_30days_ago'
  | 'this_month'
  | 'last_month'
  | '_3months_ago';

Defines & Helpers

import {
  getDateOptions,
  getDateOptionsDefault,
  getDateRangeDefault,
  defaultLocaleConfig,
  DEFAULT_MIN_YEAR,
  DEFAULT_MAX_YEAR,
} from '@libs-ui/components-datetime-picker';

// Lấy LocalizationConfig theo ngôn ngữ hiện tại (VI/EN)
const config = getDateOptions();

// Lấy LocalizationConfig đầy đủ với defaultLocaleConfig merge vào
const fullConfig = getDateOptionsDefault();

// Lấy object mapping ID quick range → [startDayjs, endDayjs]
const ranges = getDateRangeDefault();
// ranges.today → [startOfDay, endOfDay]
// ranges._7days_ago → [6 ngày trước 00:00, hôm nay 23:59]

// Năm tối thiểu/tối đa mặc định
console.log(DEFAULT_MIN_YEAR); // 1945
console.log(DEFAULT_MAX_YEAR); // năm hiện tại + 5

Lưu ý quan trọng

⚠️ isSingle vs isSingle=false: Khi [isSingle]="true", lắng nghe (outSelectSingleDate) và dùng [(singleDateSelected)]. Khi [isSingle]="false" (mặc định), lắng nghe (outSelectDateRange) và dùng [(dateRangeSelected)]. Trộn lẫn hai mode sẽ không hiển thị giá trị đúng.

⚠️ hasTimePicker mặc định là true: Nếu không cần giờ phút, hãy truyền rõ [hasTimePicker]="false". Khi true, format hiển thị là DD/MM/YYYY HH:mm; khi falseDD/MM/YYYY.

⚠️ outFunctionsControl emit khi ngOnInit: (outFunctionsControl) chỉ phát ra một lần duy nhất khi component khởi tạo. Luôn lưu giá trị nhận được vào biến class để dùng sau.

⚠️ Preset giá trị ban đầu: Khi truyền [dateRangeSelected] hoặc [singleDateSelected] với quickRangeId, đảm bảo quickRangeId trùng khớp với key trong dateOptions.ranges. Nếu không khớp, nhãn hiển thị sẽ tính lại từ startDate/endDate.

⚠️ trackDateRageUpdateLabel: Mặc định false — label chỉ cập nhật khi người dùng tương tác. Đặt [trackDateRageUpdateLabel]="true" nếu cần label cập nhật reactive khi dateRangeSelected thay đổi từ bên ngoài (ví dụ: reset programmatic).

⚠️ Format ngày truyền vào: minDate, maxDate, startDate, endDate chấp nhận cả Dayjs object lẫn string ISO (VD: '2024-06-15', '2024-06-15T00:00:00Z'). Khuyến nghị dùng getDayjs() từ @libs-ui/utils để đảm bảo timezone nhất quán.

⚠️ widthByLabel mặc định là true: Khi true, chiều rộng trigger tự co dãn theo nội dung label ngày. Để có chiều rộng cố định đẹp hơn trong form, đặt [widthByLabel]="false". Chiều rộng tự tính lúc đó: range+time=322px, range=232px, single+time=190px, single=152px.

Demo

npx nx serve core-ui

Truy cập: http://localhost:4500/components/datetime/picker