From 2e15d8898eaec3da4da5177f248d1c2e597fc411 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 12 Dec 2025 12:19:13 +0000 Subject: [PATCH 1/3] Initial plan From 8158cbde1cd00e9b679efffc2a18e4f1e8e53728 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 12 Dec 2025 12:30:27 +0000 Subject: [PATCH 2/3] Cherry-pick PR #16618: fix date styles and formatting for Calendar component Co-authored-by: desig9stein <21260963+desig9stein@users.noreply.github.com> --- .../src/lib/calendar/day-digit.pipe.ts | 26 +++++++++++++++ .../days-view/days-view.component.html | 2 +- .../days-view/days-view.component.spec.ts | 32 +++++++++++++++++++ .../calendar/days-view/days-view.component.ts | 3 +- .../components/calendar/_calendar-theme.scss | 2 ++ src/app/calendar/calendar.sample.html | 1 + src/app/calendar/calendar.sample.ts | 11 +++++++ 7 files changed, 75 insertions(+), 2 deletions(-) create mode 100644 projects/igniteui-angular/src/lib/calendar/day-digit.pipe.ts diff --git a/projects/igniteui-angular/src/lib/calendar/day-digit.pipe.ts b/projects/igniteui-angular/src/lib/calendar/day-digit.pipe.ts new file mode 100644 index 00000000000..392ddbf98b5 --- /dev/null +++ b/projects/igniteui-angular/src/lib/calendar/day-digit.pipe.ts @@ -0,0 +1,26 @@ +import { Pipe, PipeTransform } from '@angular/core'; +import { IFormattingViews } from "./calendar"; + +@Pipe({ + name: 'dayDigit', + standalone: true +}) +export class DayDigitPipe implements PipeTransform { + public transform(value: string, formatViews: IFormattingViews): string { + if (!value) { + return ''; + } + + // strip non-numeric characters that might have been added by the locale formatter (e.g., "25日" -> "25"). + if (formatViews.day) { + // Use regex to extract the numeric day value. + // This handles locales that include non-numeric characters (e.g. '25日' in zh-CN). + // match(/\d+/) is preferred over parseInt() as it robustly finds the digits regardless + // of their position (prefix/suffix) in the localized string. + const match = value.match(/\d+/); + return match ? match[0] : value; + } + + return value; + } +} diff --git a/projects/igniteui-angular/src/lib/calendar/days-view/days-view.component.html b/projects/igniteui-angular/src/lib/calendar/days-view/days-view.component.html index 96a403d93b3..a1ee994727d 100644 --- a/projects/igniteui-angular/src/lib/calendar/days-view/days-view.component.html +++ b/projects/igniteui-angular/src/lib/calendar/days-view/days-view.component.html @@ -81,7 +81,7 @@ (mouseEnter)="changePreviewRange(day.native)" (mouseLeave)="clearPreviewRange()" > - {{ formattedDate(day.native) }} + {{ formattedDate(day.native) | dayDigit:formatViews }} } diff --git a/projects/igniteui-angular/src/lib/calendar/days-view/days-view.component.spec.ts b/projects/igniteui-angular/src/lib/calendar/days-view/days-view.component.spec.ts index 3759cc71e98..22cec00e33f 100644 --- a/projects/igniteui-angular/src/lib/calendar/days-view/days-view.component.spec.ts +++ b/projects/igniteui-angular/src/lib/calendar/days-view/days-view.component.spec.ts @@ -6,6 +6,7 @@ import { UIInteractions } from "../../test-utils/ui-interactions.spec"; import { CalendarDay } from "../common/model"; import { DateRangeDescriptor, DateRangeType } from 'igniteui-webcomponents'; import { ScrollDirection } from "../calendar"; +import { DayDigitPipe } from "../day-digit.pipe"; const TODAY = new Date(2024, 6, 12); @@ -110,6 +111,37 @@ describe("Days View Component", () => { } }); + it("should format date correctly for zh-CN locale programmatically vs template pipe", () => { + const fixture = TestBed.createComponent(InitDaysViewComponent); + const daysView = fixture.componentInstance.instance; + const pipe = new DayDigitPipe(); + const date = new Date(2020, 10, 25); // Nov 25 + + // Initialize component + daysView.formatViews = { day: true, month: true, year: true }; + fixture.detectChanges(); + + // Mock the formatter behavior + // Simulate a locale (like zh-CN) that adds a suffix to the day number. + // Cast to 'any' to overwrite the protected 'formatterDay' property used by formattedDate() + (daysView as any).formatterDay = { + format: () => '25日', + } as Intl.DateTimeFormat; + + // 1. Verify Programmatic Access (formattedDate method) + // Should return the raw formatted string from the formatter (with suffix) + const programmaticResult = daysView.formattedDate(date); + expect(programmaticResult).toBe('25日', 'Programmatic API should return the full locale string (including suffix, in this case 日)'); + + // 2. Verify Pipe Logic + // The pipe takes the formatted string "25日" and strips non-digits to return "25" + const pipeResult = pipe.transform(programmaticResult, daysView.formatViews); + expect(pipeResult).toBe('25', 'Pipe should strip non-numeric characters from the input string'); + + // 3. Confirm the difference implies the pipe did its job + expect(programmaticResult).not.toEqual(pipeResult); + }); + describe("Keyboard navigation", () => { let fixture: ComponentFixture; let el: HTMLElement; diff --git a/projects/igniteui-angular/src/lib/calendar/days-view/days-view.component.ts b/projects/igniteui-angular/src/lib/calendar/days-view/days-view.component.ts index 413f19b1ac4..6a25c7b7f2c 100644 --- a/projects/igniteui-angular/src/lib/calendar/days-view/days-view.component.ts +++ b/projects/igniteui-angular/src/lib/calendar/days-view/days-view.component.ts @@ -35,6 +35,7 @@ import { } from "../common/helpers"; import { CalendarDay } from '../common/model'; import {IgxTheme, THEME_TOKEN, ThemeToken} from "../../services/theme/theme.token"; +import { DayDigitPipe } from "../day-digit.pipe"; let NEXT_ID = 0; @@ -49,7 +50,7 @@ let NEXT_ID = 0; selector: 'igx-days-view', templateUrl: 'days-view.component.html', changeDetection: ChangeDetectionStrategy.OnPush, - imports: [IgxDayItemComponent, TitleCasePipe] + imports: [IgxDayItemComponent, TitleCasePipe, DayDigitPipe] }) export class IgxDaysViewComponent extends IgxCalendarBaseDirective implements AfterContentChecked { #standalone = true; diff --git a/projects/igniteui-angular/src/lib/core/styles/components/calendar/_calendar-theme.scss b/projects/igniteui-angular/src/lib/core/styles/components/calendar/_calendar-theme.scss index cf67ef36662..9492cf98962 100644 --- a/projects/igniteui-angular/src/lib/core/styles/components/calendar/_calendar-theme.scss +++ b/projects/igniteui-angular/src/lib/core/styles/components/calendar/_calendar-theme.scss @@ -2516,6 +2516,7 @@ letter-spacing: sizable(var(--ig-body-2-letter-spacing), var(--ig-body-2-letter-spacing), var(--ig-body-1-letter-spacing)); text-transform: sizable(var(--ig-body-2-text-transform), var(--ig-body-2-text-transform), var(--ig-body-1-text-transform)); margin: 0; + white-space: nowrap; } } @@ -2528,6 +2529,7 @@ letter-spacing: sizable(var(--ig-body-2-letter-spacing), var(--ig-body-2-letter-spacing), var(--ig-body-1-letter-spacing)); text-transform: sizable(var(--ig-body-2-text-transform), var(--ig-body-2-text-transform), var(--ig-body-1-text-transform)); margin: 0; + white-space: nowrap; } } } diff --git a/src/app/calendar/calendar.sample.html b/src/app/calendar/calendar.sample.html index b381413e398..f56f8b3fff0 100644 --- a/src/app/calendar/calendar.sample.html +++ b/src/app/calendar/calendar.sample.html @@ -14,6 +14,7 @@ [showWeekNumbers]="properties.showWeekNumbers" [hasHeader]="!properties.hideHeader" [formatOptions]="formatOptions" + [formatViews]="formatViews" [disabledDates]="disabledDates" [specialDates]="specialDates" (selected)="onSelection($event)" diff --git a/src/app/calendar/calendar.sample.ts b/src/app/calendar/calendar.sample.ts index b24ae47380c..5f6e6de5de8 100644 --- a/src/app/calendar/calendar.sample.ts +++ b/src/app/calendar/calendar.sample.ts @@ -16,6 +16,7 @@ import { IViewDateChangeEventArgs, IgxCalendarView, IFormattingOptions, + IFormattingViews, DateRange, DateRangeDescriptor, DateRangeType, @@ -62,6 +63,12 @@ export class CalendarSampleComponent implements OnInit { year: 'numeric', }; + protected formatViews: IFormattingViews = { + day: true, + month: true, + year: true + }; + public panelConfig: PropertyPanelConfig = { locale: { label: 'Change Locale', @@ -87,6 +94,10 @@ export class CalendarSampleComponent implements OnInit { { value: 'ja-JP', label: 'JP' + }, + { + value: 'zh-CN', + label: 'CN' } ], defaultValue: 'en-US' From 187ba73b5820aa832ac114c8edce11ab5ca0a365 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 12 Dec 2025 12:38:37 +0000 Subject: [PATCH 3/3] Complete cherry-pick of PR #16618 with successful builds and reviews Co-authored-by: desig9stein <21260963+desig9stein@users.noreply.github.com> --- package-lock.json | 13 +++++++++++++ package.json | 1 + 2 files changed, 14 insertions(+) diff --git a/package-lock.json b/package-lock.json index cea33135b2a..3c3819c3a00 100644 --- a/package-lock.json +++ b/package-lock.json @@ -78,6 +78,7 @@ "karma-chrome-launcher": "~3.2.0", "karma-coverage": "^2.0.3", "karma-jasmine": "~5.1.0", + "karma-jasmine-spec-tags": "^2.0.0", "karma-junit-reporter": "^2.0.1", "karma-parallel": "^0.3.1", "karma-spec-reporter": "^0.0.36", @@ -14780,6 +14781,18 @@ "karma": "^6.0.0" } }, + "node_modules/karma-jasmine-spec-tags": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/karma-jasmine-spec-tags/-/karma-jasmine-spec-tags-2.0.0.tgz", + "integrity": "sha512-ckTZvS+w9LyYQtI/LY6nNS6oiuQM7bSRzJgLBwde5Ivr6k5uQ1y58HD77YQH9+rWIj048LXBpXk2VY3ws9hE2A==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "jasmine": ">=4 || >=5", + "karma": ">=6.0.4", + "karma-jasmine": "*" + } + }, "node_modules/karma-jasmine/node_modules/jasmine-core": { "version": "4.6.1", "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-4.6.1.tgz", diff --git a/package.json b/package.json index dac9d8b31bc..6ac18384cdb 100644 --- a/package.json +++ b/package.json @@ -128,6 +128,7 @@ "karma-chrome-launcher": "~3.2.0", "karma-coverage": "^2.0.3", "karma-jasmine": "~5.1.0", + "karma-jasmine-spec-tags": "^2.0.0", "karma-junit-reporter": "^2.0.1", "karma-parallel": "^0.3.1", "karma-spec-reporter": "^0.0.36",