diff --git a/packages/components/core/locales/en-US.ts b/packages/components/core/locales/en-US.ts index bad707dba2..855ad776b9 100644 --- a/packages/components/core/locales/en-US.ts +++ b/packages/components/core/locales/en-US.ts @@ -135,10 +135,13 @@ export const enUSLocaleData = { to: 'to', apply: 'Apply', cancel: 'Cancel', - rangeLabel: 'for period', + rangeLabel: 'Period', allTime: 'for all time', currentQuarter: 'for the current quarter', - currentYear: 'for the current year' + currentYear: 'for the current year', + allTimeOption: 'All time', + currentQuarterOption: 'Current quarter', + currentYearOption: 'Current year' }, durationTemplate: { title: { @@ -180,31 +183,31 @@ export const enUSLocaleData = { LAST_PART_SEPARATOR: '', YEARS: `{years, plural, one {# year} - other {last # years} + other {Last # years} }`, MONTHS: `{months, plural, - one {last month} - other {last # months} + one {Last month} + other {Last # months} }`, WEEKS: `{weeks, plural, - one {last week} - other {last # weeks} + one {Last week} + other {Last # weeks} }`, DAYS: `{days, plural, - one {last day} - other {last # days} + one {Last day} + other {Last # days} }`, HOURS: `{hours, plural, - one {last hour} - other {last # hours} + one {Last hour} + other {Last # hours} }`, MINUTES: `{minutes, plural, - one {last minute} - other {last # minutes} + one {Last minute} + other {Last # minutes} }`, SECONDS: `{seconds, plural, - one {last second} - other {last # seconds} + one {Last second} + other {Last # seconds} }`, YEARS_FRACTION: `{years} years`, MONTHS_FRACTION: `{months} months` diff --git a/packages/components/core/locales/es-LA.ts b/packages/components/core/locales/es-LA.ts index 94471ba698..f134f66d60 100644 --- a/packages/components/core/locales/es-LA.ts +++ b/packages/components/core/locales/es-LA.ts @@ -134,10 +134,13 @@ export const esLALocaleData = { to: 'a', apply: 'Aplicar', cancel: 'Cancelar', - rangeLabel: 'para el período', + rangeLabel: 'Período', allTime: 'por todo el tiempo', currentQuarter: 'por el trimestre actual', - currentYear: 'por el año actual' + currentYear: 'por el año actual', + allTimeOption: 'Todo el tiempo', + currentQuarterOption: 'Trimestre actual', + currentYearOption: 'Año actual' }, durationTemplate: { title: { @@ -179,31 +182,31 @@ export const esLALocaleData = { LAST_PART_SEPARATOR: '', YEARS: `{years, plural, one {# año} - other {últimos # años} + other {Últimos # años} }`, MONTHS: `{months, plural, - one {último mes} - other {últimos # meses} + one {Último mes} + other {Últimos # meses} }`, WEEKS: `{weeks, plural, - one {última semana} - other {últimas # semanas} + one {Última semana} + other {Últimas # semanas} }`, DAYS: `{days, plural, - one {último día} - other {últimos # días} + one {Último día} + other {Últimos # días} }`, HOURS: `{hours, plural, - one {última hora} - other {últimas # horas} + one {Última hora} + other {Últimas # horas} }`, MINUTES: `{minutes, plural, - one {último minuto} - other {últimos # minutos} + one {Último minuto} + other {Últimos # minutos} }`, SECONDS: `{seconds, plural, - one {último segundo} - other {últimos # segundos} + one {Último segundo} + other {Últimos # segundos} }`, YEARS_FRACTION: `{years} años`, MONTHS_FRACTION: `{months} meses` diff --git a/packages/components/core/locales/pt-BR.ts b/packages/components/core/locales/pt-BR.ts index 45368cfcd1..7882cb4e24 100644 --- a/packages/components/core/locales/pt-BR.ts +++ b/packages/components/core/locales/pt-BR.ts @@ -134,10 +134,13 @@ export const ptBRLocaleData = { to: 'até', apply: 'Aplicar', cancel: 'Cancelar', - rangeLabel: 'para o período', + rangeLabel: 'Período', allTime: 'por todo o tempo', currentQuarter: 'pelo trimestre atual', - currentYear: 'pelo ano atual' + currentYear: 'pelo ano atual', + allTimeOption: 'Todo o tempo', + currentQuarterOption: 'Trimestre atual', + currentYearOption: 'Ano atual' }, durationTemplate: { title: { @@ -179,31 +182,31 @@ export const ptBRLocaleData = { LAST_PART_SEPARATOR: '', YEARS: `{years, plural, one {# ano} - other {últimos # anos} + other {Últimos # anos} }`, MONTHS: `{months, plural, - one {último mês} - other {últimos # meses} + one {Último mês} + other {Últimos # meses} }`, WEEKS: `{weeks, plural, - one {última semana} - other {últimas # semanas} + one {Última semana} + other {Últimas # semanas} }`, DAYS: `{days, plural, - one {último dia} - other {últimos # dias} + one {Último dia} + other {Últimos # dias} }`, HOURS: `{hours, plural, - one {última hora} - other {últimas # horas} + one {Última hora} + other {Últimas # horas} }`, MINUTES: `{minutes, plural, - one {último minuto} - other {últimos # minutos} + one {Último minuto} + other {Últimos # minutos} }`, SECONDS: `{seconds, plural, - one {último segundo} - other {últimos # segundos} + one {Último segundo} + other {Últimos # segundos} }`, YEARS_FRACTION: `{years} anos`, MONTHS_FRACTION: `{months} meses` diff --git a/packages/components/core/locales/ru-RU.ts b/packages/components/core/locales/ru-RU.ts index d9755d3054..6761d0724b 100644 --- a/packages/components/core/locales/ru-RU.ts +++ b/packages/components/core/locales/ru-RU.ts @@ -135,10 +135,13 @@ export const ruRULocaleData = { to: 'по', apply: 'Применить', cancel: 'Отмена', - rangeLabel: 'за период', + rangeLabel: 'Период', allTime: 'за все время', currentQuarter: 'за текущий квартал', - currentYear: 'за текущий год' + currentYear: 'за текущий год', + allTimeOption: 'Все время', + currentQuarterOption: 'Текущий квартал', + currentYearOption: 'Текущий год' }, durationTemplate: { title: { @@ -146,7 +149,7 @@ export const ruRULocaleData = { LAST_PART_SEPARATOR: 'и', YEARS: `{years, plural, one {# год} - few {последние # лет} + few {последние # года} other {последние # лет} }`, MONTHS: `{months, plural, @@ -186,39 +189,39 @@ export const ruRULocaleData = { SEPARATOR: ' ', LAST_PART_SEPARATOR: 'и', YEARS: `{years, plural, - one {последний год} - few {последние # лет} - other {последние # лет} + one {Последний год} + few {Последние # года} + other {Последние # лет} }`, MONTHS: `{months, plural, - one {последний месяц} - few {последние # месяца} - other {последние # месяцев} + one {Последний месяц} + few {Последние # месяца} + other {Последние # месяцев} }`, WEEKS: `{weeks, plural, - one {последняя неделя} - few {последние # недели} - other {последние # недель} + one {Последняя неделя} + few {Последние # недели} + other {Последние # недель} }`, DAYS: `{days, plural, - one {последний день} - few {последние # дня} - other {последние # дней} + one {Последний день} + few {Последние # дня} + other {Последние # дней} }`, HOURS: `{hours, plural, - one {последний час} - few {последние # часа} - other {последние # часов} + one {Последний час} + few {Последние # часа} + other {Последние # часов} }`, MINUTES: `{minutes, plural, - one {последняя минута} - few {последние # минуты} - other {последние # минут} + one {Последняя минута} + few {Последние # минуты} + other {Последние # минут} }`, SECONDS: `{seconds, plural, - one {последняя секунда} - few {последние # секунды} - other {последние # секунд} + one {Последняя секунда} + few {Последние # секунды} + other {Последние # секунд} }`, YEARS_FRACTION: `{years} лет`, MONTHS_FRACTION: `{months} месяцев` diff --git a/packages/components/core/locales/tk-TM.ts b/packages/components/core/locales/tk-TM.ts index e335bfe187..1aff94826d 100644 --- a/packages/components/core/locales/tk-TM.ts +++ b/packages/components/core/locales/tk-TM.ts @@ -135,10 +135,13 @@ export const tkTMLocaleData = { to: 'şuňa', apply: 'Ulanmak', cancel: 'Ýatyrmak', - rangeLabel: 'şu döwürde', + rangeLabel: 'Döwür', allTime: 'hemme döwür üçin', currentQuarter: 'şu çärýek üçin', - currentYear: 'şu ýyl üçin' + currentYear: 'şu ýyl üçin', + allTimeOption: 'Hemme döwür', + currentQuarterOption: 'Şu çärýek', + currentYearOption: 'Şu ýyl' }, durationTemplate: { title: { @@ -183,27 +186,27 @@ export const tkTMLocaleData = { other {# ýyl} }`, MONTHS: `{months, plural, - one {aý} + one {Aý} other {# aý} }`, WEEKS: `{weeks, plural, - one {hepde} + one {Hepde} other {# hepde} }`, DAYS: `{days, plural, - one {gün} + one {Gün} other {# gün} }`, HOURS: `{hours, plural, - one {sagat} + one {Sagat} other {# sagat} }`, MINUTES: `{minutes, plural, - one {minut} + one {Minut} other {# minut} }`, SECONDS: `{seconds, plural, - one {sekunt} + one {Sekunt} other {# sekunt} }`, YEARS_FRACTION: `{years} ýyl`, diff --git a/packages/components/core/locales/types.ts b/packages/components/core/locales/types.ts index 489cd8c251..25510db2e9 100644 --- a/packages/components/core/locales/types.ts +++ b/packages/components/core/locales/types.ts @@ -62,6 +62,12 @@ export type KbqTimeRangeLocaleConfig = { allTime: string; currentQuarter: string; currentYear: string; + /** Label for the `allTime` option in the presets list, as opposed to the trigger label in `allTime` */ + allTimeOption?: string; + /** Label for the `currentQuarter` option in the presets list, as opposed to the trigger label in `currentQuarter` */ + currentQuarterOption?: string; + /** Label for the `currentYear` option in the presets list, as opposed to the trigger label in `currentYear` */ + currentYearOption?: string; }; durationTemplate: { title: FormatterDurationTemplate; diff --git a/packages/components/time-range/__snapshots__/time-range.spec.ts.snap b/packages/components/time-range/__snapshots__/time-range.spec.ts.snap index f253e1a62e..02efc9c512 100644 --- a/packages/components/time-range/__snapshots__/time-range.spec.ts.snap +++ b/packages/components/time-range/__snapshots__/time-range.spec.ts.snap @@ -10,7 +10,7 @@ exports[`KbqTimeRange Component initialization should apply custom option templa " Currentquarter ", " Currentyear ", " Alltime ", - "за период", + "Период", ] `; @@ -25,7 +25,7 @@ exports[`KbqTimeRange Component initialization should check range as default if exports[`KbqTimeRange Component initialization should check selected radio if external value provided 1`] = ` { - "checkedRadio": " за текущий год ", + "checkedRadio": " Текущий год ", "trigger": "за текущий год", } `; diff --git a/packages/components/time-range/time-range-editor.html b/packages/components/time-range/time-range-editor.html index 4b233e4826..f4c719e7b3 100644 --- a/packages/components/time-range/time-range-editor.html +++ b/packages/components/time-range/time-range-editor.html @@ -80,13 +80,13 @@ @case ('other') { @switch (context.type) { @case ('allTime') { - {{ localeConfig.editor.allTime }} + {{ localeConfig.editor.allTimeOption ?? localeConfig.editor.allTime }} } @case ('currentQuarter') { - {{ localeConfig.editor.currentQuarter }} + {{ localeConfig.editor.currentQuarterOption ?? localeConfig.editor.currentQuarter }} } @case ('currentYear') { - {{ localeConfig.editor.currentYear }} + {{ localeConfig.editor.currentYearOption ?? localeConfig.editor.currentYear }} } } } diff --git a/packages/components/time-range/time-range.en.md b/packages/components/time-range/time-range.en.md index fa8699fba3..80556ec1b3 100644 --- a/packages/components/time-range/time-range.en.md +++ b/packages/components/time-range/time-range.en.md @@ -1,27 +1,27 @@ -Time range selection menu. The user can choose one of the preset values or specify the range manually. +Time range selection menu. The user can choose one of the preset values or specify the time range manually. ### Trigger element -The menu can drop down from different trigger elements, and the window can have a pointer. +The component allows you to customize the trigger element. For example, it can be a button, a field, or a pseudo-link. ### Custom presets -When there are no preset values, only the From and To fields remain in the dialog: +When there are no preset values, only the start and end of the period remain in the window. ### Selection restriction -It is possible to configure the minimum and maximum date: +You can configure the minimum and maximum date. For example, a range from 2015 to 2017. ### Custom time ranges -The option to configure interval selection is available: +The component allows you to set custom time range options. diff --git a/packages/components/time-range/time-range.ru.md b/packages/components/time-range/time-range.ru.md index 7dccca577a..c011bbbb7a 100644 --- a/packages/components/time-range/time-range.ru.md +++ b/packages/components/time-range/time-range.ru.md @@ -1,27 +1,27 @@ -Меню выбора периода времени. Пользователь может выбрать одно из предустановленных значений или самостоятельно указать период. +Меню выбора периода. Пользователь может выбрать одно из предустановленных значений или самостоятельно указать временной диапазон. ### Триггерный элемент -Меню может выпадать из разных триггерных элементов, а окно может не иметь стрелку-указатель. +Компонент позволяет настроить триггерный элемент. Это может быть, например, кнопка, поле или псевдоссылка. ### Пользовательские предустановки -Когда нет предустановленных значений, в диалоге остаются только поля **С** и **По**: +Когда нет предустановленных значений, в окне остается только начало и конец периода. ### Ограничение выбора -Доступна настройка минимальной и максимальной даты: +Доступна настройка минимальной и максимальной даты. Например, диапазон с 2015 по 2017 год. ### Настройка промежутков -Доступна настройка выбора промежутков: +Компонент позволяет задать варианты промежутков времени. diff --git a/packages/docs-examples/components/time-range/time-range-as-form-field/time-range-as-form-field-example.ts b/packages/docs-examples/components/time-range/time-range-as-form-field/time-range-as-form-field-example.ts index bcd1ef2f7e..273d558936 100644 --- a/packages/docs-examples/components/time-range/time-range-as-form-field/time-range-as-form-field-example.ts +++ b/packages/docs-examples/components/time-range/time-range-as-form-field/time-range-as-form-field-example.ts @@ -1,11 +1,20 @@ import { TitleCasePipe } from '@angular/common'; -import { ChangeDetectionStrategy, Component } from '@angular/core'; +import { ChangeDetectionStrategy, Component, computed, inject, InjectionToken } from '@angular/core'; +import { toSignal } from '@angular/core/rxjs-interop'; import { ReactiveFormsModule } from '@angular/forms'; import { LuxonDateModule } from '@koobiq/angular-luxon-adapter/adapter'; -import { DateAdapter, DateFormatter, KBQ_DATE_LOCALE } from '@koobiq/components/core'; +import { DateAdapter, DateFormatter, KBQ_DATE_LOCALE, KBQ_LOCALE_SERVICE } from '@koobiq/components/core'; import { KbqFormFieldModule } from '@koobiq/components/form-field'; import { KbqIconModule } from '@koobiq/components/icon'; import { KbqTimeRangeModule } from '@koobiq/components/time-range'; +import { of } from 'rxjs'; + +const ExampleLocalizedData = new InjectionToken>('ExampleLocalizedData', { + factory: () => ({ + 'ru-RU': 'Период', + default: 'Period' + }) +}); /** * @title Time range as form field @@ -25,7 +34,7 @@ import { KbqTimeRangeModule } from '@koobiq/components/time-range'; @if (!context.type) { - {{ context.formattedDate }} + {{ placeholder() }} } @else { {{ context.formattedDate[0] | titlecase }}{{ context.formattedDate.slice(1) }} } @@ -44,4 +53,9 @@ import { KbqTimeRangeModule } from '@koobiq/components/time-range'; class: 'layout-flex layout-row layout-align-center-center layout-gap-3xl' } }) -export class TimeRangeAsFormFieldExample {} +export class TimeRangeAsFormFieldExample { + private readonly data = inject(ExampleLocalizedData); + private readonly localeId = toSignal(inject(KBQ_LOCALE_SERVICE, { optional: true })?.changes || of('')); + + protected readonly placeholder = computed(() => this.data[this.localeId() || 'default'] ?? this.data.default); +} diff --git a/packages/docs-examples/components/time-range/time-range-custom-option/time-range-custom-option-example.ts b/packages/docs-examples/components/time-range/time-range-custom-option/time-range-custom-option-example.ts index 9cefc3d66d..8a009fbf4c 100644 --- a/packages/docs-examples/components/time-range/time-range-custom-option/time-range-custom-option-example.ts +++ b/packages/docs-examples/components/time-range/time-range-custom-option/time-range-custom-option-example.ts @@ -1,8 +1,9 @@ import { TitleCasePipe } from '@angular/common'; -import { ChangeDetectionStrategy, Component } from '@angular/core'; +import { ChangeDetectionStrategy, Component, computed, inject, InjectionToken } from '@angular/core'; +import { toSignal } from '@angular/core/rxjs-interop'; import { ReactiveFormsModule } from '@angular/forms'; import { LuxonDateModule } from '@koobiq/angular-luxon-adapter/adapter'; -import { DateAdapter, DateFormatter, KBQ_DATE_LOCALE } from '@koobiq/components/core'; +import { DateAdapter, DateFormatter, KBQ_DATE_LOCALE, KBQ_LOCALE_SERVICE } from '@koobiq/components/core'; import { KbqFormFieldModule } from '@koobiq/components/form-field'; import { KbqIconModule } from '@koobiq/components/icon'; import { @@ -11,6 +12,14 @@ import { KbqCustomTimeRangeType, KbqTimeRangeModule } from '@koobiq/components/time-range'; +import { of } from 'rxjs'; + +const ExampleLocalizedData = new InjectionToken>('ExampleLocalizedData', { + factory: () => ({ + 'ru-RU': 'Период', + default: 'Period' + }) +}); export function customTypesFactory(adapter: DateAdapter): KbqCustomTimeRangeType[] { const currentYear = adapter.startOf(adapter.today(), 'year'); @@ -77,7 +86,7 @@ export function customTypesFactory(adapter: DateAdapter): KbqCustomTimeRan @if (!context.type) { - {{ context.formattedDate }} + {{ placeholder() }} } @else { {{ context.type | titlecase }} } @@ -107,4 +116,9 @@ export function customTypesFactory(adapter: DateAdapter): KbqCustomTimeRan class: 'layout-flex layout-row layout-align-center-center layout-gap-3xl' } }) -export class TimeRangeCustomOptionExample {} +export class TimeRangeCustomOptionExample { + private readonly data = inject(ExampleLocalizedData); + private readonly localeId = toSignal(inject(KBQ_LOCALE_SERVICE, { optional: true })?.changes || of('')); + + protected readonly placeholder = computed(() => this.data[this.localeId() || 'default'] ?? this.data.default); +} diff --git a/packages/docs-examples/components/time-range/time-range-custom-range-types/time-range-custom-range-types-example.ts b/packages/docs-examples/components/time-range/time-range-custom-range-types/time-range-custom-range-types-example.ts index 2564f7d856..4aa531622b 100644 --- a/packages/docs-examples/components/time-range/time-range-custom-range-types/time-range-custom-range-types-example.ts +++ b/packages/docs-examples/components/time-range/time-range-custom-range-types/time-range-custom-range-types-example.ts @@ -1,24 +1,43 @@ -import { TitleCasePipe } from '@angular/common'; -import { ChangeDetectionStrategy, Component } from '@angular/core'; +import { ChangeDetectionStrategy, Component, computed, inject, InjectionToken } from '@angular/core'; +import { toSignal } from '@angular/core/rxjs-interop'; import { ReactiveFormsModule } from '@angular/forms'; import { LuxonDateModule } from '@koobiq/angular-luxon-adapter/adapter'; -import { DateAdapter, DateFormatter, KBQ_DATE_LOCALE } from '@koobiq/components/core'; +import { DateAdapter, DateFormatter, KBQ_DATE_LOCALE, KBQ_LOCALE_SERVICE } from '@koobiq/components/core'; import { KbqFormFieldModule } from '@koobiq/components/form-field'; import { KbqIconModule } from '@koobiq/components/icon'; import { KBQ_CUSTOM_TIME_RANGE_TYPES, KBQ_DEFAULT_TIME_RANGE_TYPES, KbqCustomTimeRangeType, - KbqTimeRangeModule + KbqTimeRangeModule, + KbqTimeRangeTranslationType, + KbqTimeRangeType, + KbqTimeRangeUnits } from '@koobiq/components/time-range'; +import { of } from 'rxjs'; const customTypes: KbqCustomTimeRangeType[] = [ { type: 'last3Minutes', units: { minutes: -3 }, translationType: 'minutes' }, { type: 'last3Weeks', units: { weeks: -3 }, translationType: 'weeks' }, - { type: 'last3Years', units: { years: -3 }, translationType: 'months' } + { type: 'last3Years', units: { years: -3 }, translationType: 'years' } ]; -const customDefaultTypes = customTypes.map(({ type }) => type); +const customDefaultTypes = [...customTypes.map(({ type }) => type), 'range'] as KbqTimeRangeType[]; + +const customTypeUnits: Record = Object.fromEntries( + customTypes.map(({ type, units }) => [type, units]) +); + +const customTypeTranslation: Record = Object.fromEntries( + customTypes.map(({ type, translationType }) => [type, translationType]) +); + +const ExampleLocalizedData = new InjectionToken>('ExampleLocalizedData', { + factory: () => ({ + 'ru-RU': 'Период', + default: 'Period' + }) +}); /** * @title Time range custom range types @@ -30,28 +49,39 @@ const customDefaultTypes = customTypes.map(({ type }) => type); KbqTimeRangeModule, LuxonDateModule, KbqIconModule, - KbqFormFieldModule, - TitleCasePipe + KbqFormFieldModule ], template: ` - {{ context.type | titlecase }} + {{ optionLabel(context.type) }} @if (!context.type) { - {{ context.formattedDate }} + {{ placeholder() }} + } @else if (context.type === 'range') { + {{ + dateFormatter.rangeShortDateTime( + dateAdapter.deserialize(context.startDateTime), + dateAdapter.deserialize(context.endDateTime) + ) + }} } @else { - {{ context.type | titlecase }} + {{ optionLabel(context.type) }} } - + `, providers: [ { provide: DateFormatter, deps: [DateAdapter, KBQ_DATE_LOCALE] }, @@ -63,4 +93,37 @@ const customDefaultTypes = customTypes.map(({ type }) => type); class: 'layout-flex layout-row layout-align-center-center layout-gap-3xl' } }) -export class TimeRangeCustomRangeTypesExample {} +export class TimeRangeCustomRangeTypesExample { + protected readonly dateAdapter = inject(DateAdapter); + protected readonly dateFormatter = inject(DateFormatter); + + private readonly localeService = inject(KBQ_LOCALE_SERVICE, { optional: true }); + private readonly localeId = toSignal(this.localeService?.changes || of('')); + + private readonly localeConfig = computed(() => { + this.localeId(); + + return this.localeService?.getParams('timeRange'); + }); + + private readonly data = inject(ExampleLocalizedData); + protected readonly placeholder = computed(() => this.data[this.localeId() || 'default'] ?? this.data.default); + + protected optionLabel(type: string): string { + const localeConfig = this.localeConfig(); + + if (!localeConfig) return type; + + const units = customTypeUnits[type]; + const translationType = customTypeTranslation[type]; + const startDate = this.dateAdapter.addCalendarUnits(this.dateAdapter.today(), units); + + return this.dateFormatter.duration( + startDate, + this.dateAdapter.today(), + [translationType as Exclude], + false, + localeConfig.durationTemplate.option + ); + } +} diff --git a/packages/docs-examples/components/time-range/time-range-empty-type-list/time-range-empty-type-list-example.ts b/packages/docs-examples/components/time-range/time-range-empty-type-list/time-range-empty-type-list-example.ts index ceddfcb3c5..1067f209b2 100644 --- a/packages/docs-examples/components/time-range/time-range-empty-type-list/time-range-empty-type-list-example.ts +++ b/packages/docs-examples/components/time-range/time-range-empty-type-list/time-range-empty-type-list-example.ts @@ -1,7 +1,9 @@ -import { ChangeDetectionStrategy, Component } from '@angular/core'; +import { ChangeDetectionStrategy, Component, inject } from '@angular/core'; import { ReactiveFormsModule } from '@angular/forms'; import { LuxonDateModule } from '@koobiq/angular-luxon-adapter/adapter'; import { DateAdapter, DateFormatter, KBQ_DATE_LOCALE } from '@koobiq/components/core'; +import { KbqIconModule } from '@koobiq/components/icon'; +import { KbqLinkModule } from '@koobiq/components/link'; import { KbqTimeRange, KbqTimeRangeType } from '@koobiq/components/time-range'; /** @@ -12,10 +14,31 @@ import { KbqTimeRange, KbqTimeRangeType } from '@koobiq/components/time-range'; imports: [ ReactiveFormsModule, KbqTimeRange, - LuxonDateModule + LuxonDateModule, + KbqLinkModule, + KbqIconModule ], template: ` - + + + + @if (context.startDateTime && context.endDateTime) { + {{ + dateFormatter.rangeLongDate( + dateAdapter.deserialize(context.startDateTime), + dateAdapter.deserialize(context.endDateTime) + ) + }} + } @else { + {{ context.formattedDate }} + } + + + + + + + `, providers: [ { provide: DateFormatter, deps: [DateAdapter, KBQ_DATE_LOCALE] } @@ -26,5 +49,8 @@ import { KbqTimeRange, KbqTimeRangeType } from '@koobiq/components/time-range'; } }) export class TimeRangeEmptyTypeListExample { + protected readonly dateAdapter = inject(DateAdapter); + protected readonly dateFormatter = inject(DateFormatter); + protected readonly availableTimeRangeTypes: KbqTimeRangeType[] = []; } diff --git a/packages/docs-examples/components/time-range/time-range-min-max/time-range-min-max-example.ts b/packages/docs-examples/components/time-range/time-range-min-max/time-range-min-max-example.ts index d7a745379c..5c66e6d8ed 100644 --- a/packages/docs-examples/components/time-range/time-range-min-max/time-range-min-max-example.ts +++ b/packages/docs-examples/components/time-range/time-range-min-max/time-range-min-max-example.ts @@ -1,9 +1,20 @@ -import { ChangeDetectionStrategy, Component, inject } from '@angular/core'; +import { ChangeDetectionStrategy, Component, computed, inject, InjectionToken } from '@angular/core'; +import { toSignal } from '@angular/core/rxjs-interop'; import { ReactiveFormsModule } from '@angular/forms'; import { LuxonDateModule } from '@koobiq/angular-luxon-adapter/adapter'; -import { DateAdapter, DateFormatter, KBQ_DATE_LOCALE } from '@koobiq/components/core'; +import { DateAdapter, DateFormatter, KBQ_DATE_LOCALE, KBQ_LOCALE_SERVICE } from '@koobiq/components/core'; +import { KbqIconModule } from '@koobiq/components/icon'; +import { KbqLinkModule } from '@koobiq/components/link'; import { KbqTimeRange } from '@koobiq/components/time-range'; import { DateTime } from 'luxon'; +import { of } from 'rxjs'; + +const ExampleLocalizedData = new InjectionToken>('ExampleLocalizedData', { + factory: () => ({ + 'ru-RU': 'Выбрать период', + default: 'Select period' + }) +}); /** * @title Time range min max @@ -13,13 +24,33 @@ import { DateTime } from 'luxon'; imports: [ ReactiveFormsModule, KbqTimeRange, - LuxonDateModule + LuxonDateModule, + KbqLinkModule, + KbqIconModule ], template: ` -
-
From 2017 to 2025
- -
+ + + + @if (!context.type) { + {{ placeholder() }} + } @else if (context.type === 'range') { + {{ + dateFormatter.rangeLongDate( + dateAdapter.deserialize(context.startDateTime), + dateAdapter.deserialize(context.endDateTime) + ) + }} + } @else { + {{ capitalize(context.formattedDate) }} + } + + + + + + + `, providers: [ { provide: DateFormatter, deps: [DateAdapter, KBQ_DATE_LOCALE] } @@ -30,8 +61,18 @@ import { DateTime } from 'luxon'; } }) export class TimeRangeMinMaxExample { - protected readonly adapter = inject>(DateAdapter); + protected readonly dateAdapter = inject>(DateAdapter); + protected readonly dateFormatter = inject(DateFormatter); + + protected readonly minDate = this.dateAdapter.createDate(2015, 0, 1); + protected readonly maxDate = this.dateAdapter.createDate(2017, 11, 31); - protected readonly minDate = this.adapter.createDate(2017, 0, 1); - protected readonly maxDate = this.adapter.today(); + private readonly data = inject(ExampleLocalizedData); + private readonly localeId = toSignal(inject(KBQ_LOCALE_SERVICE, { optional: true })?.changes || of('')); + + protected readonly placeholder = computed(() => this.data[this.localeId() || 'default'] ?? this.data.default); + + protected capitalize(text: string): string { + return text.charAt(0).toUpperCase() + text.slice(1); + } } diff --git a/packages/docs-examples/components/time-range/time-range-overview/time-range-overview-example.ts b/packages/docs-examples/components/time-range/time-range-overview/time-range-overview-example.ts index 8ed3e1f12e..ecd80917ef 100644 --- a/packages/docs-examples/components/time-range/time-range-overview/time-range-overview-example.ts +++ b/packages/docs-examples/components/time-range/time-range-overview/time-range-overview-example.ts @@ -1,8 +1,17 @@ -import { ChangeDetectionStrategy, Component } from '@angular/core'; +import { ChangeDetectionStrategy, Component, computed, inject, InjectionToken } from '@angular/core'; +import { toSignal } from '@angular/core/rxjs-interop'; import { FormControl, ReactiveFormsModule } from '@angular/forms'; import { LuxonDateModule } from '@koobiq/angular-luxon-adapter/adapter'; -import { DateAdapter, DateFormatter, KBQ_DATE_LOCALE } from '@koobiq/components/core'; +import { DateAdapter, DateFormatter, KBQ_DATE_LOCALE, KBQ_LOCALE_SERVICE } from '@koobiq/components/core'; import { KbqTimeRange, KbqTimeRangeRange, KbqTimeRangeType } from '@koobiq/components/time-range'; +import { of } from 'rxjs'; + +const ExampleLocalizedData = new InjectionToken>('ExampleLocalizedData', { + factory: () => ({ + 'ru-RU': 'События', + default: 'Events' + }) +}); /** * @title Time range overview @@ -15,6 +24,7 @@ import { KbqTimeRange, KbqTimeRangeRange, KbqTimeRangeType } from '@koobiq/compo LuxonDateModule ], template: ` + {{ caption() }} `, providers: [ @@ -22,10 +32,15 @@ import { KbqTimeRange, KbqTimeRangeRange, KbqTimeRangeType } from '@koobiq/compo ], changeDetection: ChangeDetectionStrategy.OnPush, host: { - class: 'layout-flex layout-row layout-align-center-center layout-gap-3xl' + class: 'layout-flex layout-row layout-align-center-center layout-gap-xxs' } }) export class TimeRangeOverviewExample { + private readonly data = inject(ExampleLocalizedData); + private readonly localeId = toSignal(inject(KBQ_LOCALE_SERVICE, { optional: true })?.changes || of('')); + + protected readonly caption = computed(() => this.data[this.localeId() || 'default'] ?? this.data.default); + protected readonly control = new FormControl( { type: 'last5Minutes' @@ -46,9 +61,9 @@ export class TimeRangeOverviewExample { 'last30Days', 'last3Months', 'last12Months', - 'allTime', 'currentQuarter', 'currentYear', + 'allTime', 'range' ]; } diff --git a/tools/public_api_guard/components/core.api.md b/tools/public_api_guard/components/core.api.md index e8018147e6..b2206b4396 100644 --- a/tools/public_api_guard/components/core.api.md +++ b/tools/public_api_guard/components/core.api.md @@ -512,6 +512,9 @@ export const enUSLocaleData: { allTime: string; currentQuarter: string; currentYear: string; + allTimeOption: string; + currentQuarterOption: string; + currentYearOption: string; }; durationTemplate: { title: { @@ -750,6 +753,9 @@ export const esLALocaleData: { allTime: string; currentQuarter: string; currentYear: string; + allTimeOption: string; + currentQuarterOption: string; + currentYearOption: string; }; durationTemplate: { title: { @@ -1211,6 +1217,9 @@ export function KBQ_DEFAULT_LOCALE_DATA_FACTORY(): { allTime: string; currentQuarter: string; currentYear: string; + allTimeOption: string; + currentQuarterOption: string; + currentYearOption: string; }; durationTemplate: { title: { @@ -1424,6 +1433,9 @@ export function KBQ_DEFAULT_LOCALE_DATA_FACTORY(): { allTime: string; currentQuarter: string; currentYear: string; + allTimeOption: string; + currentQuarterOption: string; + currentYearOption: string; }; durationTemplate: { title: { @@ -1633,6 +1645,9 @@ export function KBQ_DEFAULT_LOCALE_DATA_FACTORY(): { allTime: string; currentQuarter: string; currentYear: string; + allTimeOption: string; + currentQuarterOption: string; + currentYearOption: string; }; durationTemplate: { title: { @@ -1848,6 +1863,9 @@ export function KBQ_DEFAULT_LOCALE_DATA_FACTORY(): { allTime: string; currentQuarter: string; currentYear: string; + allTimeOption: string; + currentQuarterOption: string; + currentYearOption: string; }; durationTemplate: { title: { @@ -2059,6 +2077,9 @@ export function KBQ_DEFAULT_LOCALE_DATA_FACTORY(): { allTime: string; currentQuarter: string; currentYear: string; + allTimeOption: string; + currentQuarterOption: string; + currentYearOption: string; }; durationTemplate: { title: { @@ -3421,6 +3442,9 @@ export type KbqTimeRangeLocaleConfig = { allTime: string; currentQuarter: string; currentYear: string; + allTimeOption?: string; + currentQuarterOption?: string; + currentYearOption?: string; }; durationTemplate: { title: FormatterDurationTemplate; @@ -3984,6 +4008,9 @@ export const ptBRLocaleData: { allTime: string; currentQuarter: string; currentYear: string; + allTimeOption: string; + currentQuarterOption: string; + currentYearOption: string; }; durationTemplate: { title: { @@ -4409,6 +4436,9 @@ export const ruRULocaleData: { allTime: string; currentQuarter: string; currentYear: string; + allTimeOption: string; + currentQuarterOption: string; + currentYearOption: string; }; durationTemplate: { title: { @@ -4755,6 +4785,9 @@ export const tkTMLocaleData: { allTime: string; currentQuarter: string; currentYear: string; + allTimeOption: string; + currentQuarterOption: string; + currentYearOption: string; }; durationTemplate: { title: {