Skip to content

Commit bc54ebb

Browse files
authored
Merge branch 'master' into mpopov/fix/input-group/filte-type-layout
2 parents 1155509 + 2484c2c commit bc54ebb

File tree

97 files changed

+7915
-649
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

97 files changed

+7915
-649
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@ All notable changes to this project will be documented in this file.
44
The format is based on [Keep a Changelog](http://keepachangelog.com/)
55
and this project adheres to [Semantic Versioning](http://semver.org/).
66

7+
## [Unreleased]
8+
### Fixed
9+
- #### Calendar & Date picker
10+
- Incorrect date rollover for in certain scenarios [#1710](https://github.com/IgniteUI/igniteui-webcomponents/issues/1710)
11+
712
## [6.0.1] - 2025-05-28
813
### Added
914
- #### Radio group

package-lock.json

Lines changed: 123 additions & 124 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,9 @@
2525
"build:meta": "node scripts/build-stories.mjs",
2626
"watch-meta": "node scripts/stories-watcher.js ",
2727
"watch-scss": "node scripts/styles-watcher.mjs",
28-
"check": "madge --circular --warning --no-spinner --ts-config ./tsconfig.json --extensions ts src/index.ts",
28+
"check-imports": "madge --circular --warning --no-spinner --ts-config ./tsconfig.json --extensions ts src/index.ts",
29+
"check-types": "tsc -p scripts/tsconfig-ci.json",
30+
"check": "npm run check-imports && npm run check-types",
2931
"clean": "npm run clean:dist && npm run clean:styles && npm run clean:docs",
3032
"clean:dist": "rimraf ./dist",
3133
"clean:styles": "rimraf --glob \"src/**/*.css.ts\"",
@@ -50,7 +52,7 @@
5052
"prepare": "husky"
5153
},
5254
"dependencies": {
53-
"@floating-ui/dom": "^1.7.0",
55+
"@floating-ui/dom": "^1.7.1",
5456
"@lit-labs/virtualizer": "^2.1.0",
5557
"@lit/context": "^1.1.5",
5658
"lit": "^3.3.0"
@@ -60,10 +62,10 @@
6062
"@custom-elements-manifest/analyzer": "^0.10.4",
6163
"@igniteui/material-icons-extended": "^3.1.0",
6264
"@open-wc/testing": "^4.0.0",
63-
"@storybook/addon-a11y": "^9.0.0-rc.4",
64-
"@storybook/addon-docs": "^9.0.0-rc.4",
65-
"@storybook/addon-links": "^9.0.0-rc.4",
66-
"@storybook/web-components-vite": "^9.0.0-rc.4",
65+
"@storybook/addon-a11y": "^9.0.4",
66+
"@storybook/addon-docs": "^9.0.4",
67+
"@storybook/addon-links": "^9.0.4",
68+
"@storybook/web-components-vite": "^9.0.4",
6769
"@types/mocha": "^10.0.10",
6870
"@web/dev-server-esbuild": "^1.0.4",
6971
"@web/test-runner": "^0.20.2",
@@ -76,21 +78,21 @@
7678
"custom-element-vs-code-integration": "^1.5.0",
7779
"globby": "^14.1.0",
7880
"husky": "^9.1.7",
79-
"ig-typedoc-theme": "^6.0.0",
80-
"igniteui-theming": "^18.0.2",
81+
"ig-typedoc-theme": "^6.1.0",
82+
"igniteui-theming": "^18.1.0",
8183
"keep-a-changelog": "^2.6.2",
82-
"lint-staged": "^16.0.0",
84+
"lint-staged": "^16.1.0",
8385
"lit-analyzer": "^2.0.3",
8486
"madge": "^8.0.0",
8587
"node-watch": "^0.7.4",
8688
"playwright": "^1.52.0",
87-
"postcss": "^8.5.3",
89+
"postcss": "^8.5.4",
8890
"prettier": "^3.5.3",
8991
"rimraf": "^6.0.1",
9092
"sass-embedded": "~1.78.0",
9193
"sinon": "^20.0.0",
92-
"storybook": "^9.0.0-rc.4",
93-
"stylelint": "^16.19.1",
94+
"storybook": "^9.0.4",
95+
"stylelint": "^16.20.0",
9496
"stylelint-config-standard-scss": "^15.0.1",
9597
"stylelint-prettier": "^5.0.3",
9698
"stylelint-scss": "^6.12.0",
@@ -117,8 +119,5 @@
117119
}
118120
}
119121
},
120-
"customElements": "custom-elements.json",
121-
"overrides": {
122-
"storybook": "$storybook"
123-
}
122+
"customElements": "custom-elements.json"
124123
}

scripts/tsconfig-ci.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"extends": "../tsconfig.json",
3+
"compilerOptions": {
4+
"noEmit": true
5+
}
6+
}

src/components/button-group/toggle-button.ts

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,14 @@ export default class IgcToggleButtonComponent extends LitElement {
3030
};
3131

3232
/* blazorSuppress */
33-
public static register() {
33+
public static register(): void {
3434
registerComponent(IgcToggleButtonComponent);
3535
}
3636

37-
private _kbFocus = addKeyboardFocusRing(this);
37+
private readonly _focusRingManager = addKeyboardFocusRing(this);
3838

3939
@query('[part="toggle"]', true)
40-
private _nativeButton!: HTMLButtonElement;
40+
private readonly _nativeButton!: HTMLButtonElement;
4141

4242
/**
4343
* The value attribute of the control.
@@ -62,32 +62,33 @@ export default class IgcToggleButtonComponent extends LitElement {
6262

6363
/* alternateName: focusComponent */
6464
/** Sets focus on the button. */
65-
public override focus(options?: FocusOptions) {
65+
public override focus(options?: FocusOptions): void {
6666
this._nativeButton.focus(options);
6767
}
6868

6969
/* alternateName: blurComponent */
7070
/** Removes focus from the button. */
71-
public override blur() {
71+
public override blur(): void {
7272
this._nativeButton.blur();
7373
}
7474

7575
/** Simulates a mouse click on the element. */
76-
public override click() {
76+
public override click(): void {
7777
this._nativeButton.click();
7878
}
7979

8080
protected override render() {
8181
return html`
8282
<button
83-
part=${partMap({ toggle: true, focused: this._kbFocus.focused })}
83+
part=${partMap({
84+
toggle: true,
85+
focused: this._focusRingManager.focused,
86+
})}
8487
type="button"
8588
?disabled=${this.disabled}
8689
.ariaLabel=${this.ariaLabel}
8790
aria-pressed=${this.selected}
8891
aria-disabled=${this.disabled}
89-
@click=${this._kbFocus.reset}
90-
@blur=${this._kbFocus.reset}
9192
>
9293
<slot></slot>
9394
</button>

src/components/button/button-base.ts

Lines changed: 21 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,14 @@ export abstract class IgcButtonBaseComponent extends EventEmitterMixin<
2828
delegatesFocus: true,
2929
};
3030

31-
private _kbFocus = addKeyboardFocusRing(this);
31+
protected readonly __internals: ElementInternals;
32+
33+
private readonly _focusRingManager = addKeyboardFocusRing(this);
3234

33-
protected __internals: ElementInternals;
3435
protected _disabled = false;
3536

3637
@query('[part="base"]', true)
37-
private _nativeButton!: HTMLButtonElement;
38+
private readonly _nativeButton!: HTMLButtonElement;
3839

3940
/* alternateName: displayType */
4041
/**
@@ -78,19 +79,19 @@ export abstract class IgcButtonBaseComponent extends EventEmitterMixin<
7879
* @attr [disabled=false]
7980
*/
8081
@property({ type: Boolean, reflect: true })
81-
public get disabled(): boolean {
82-
return this._disabled;
83-
}
84-
8582
public set disabled(value: boolean) {
8683
this._disabled = value;
8784
this.toggleAttribute('disabled', Boolean(this._disabled));
8885
}
8986

87+
public get disabled(): boolean {
88+
return this._disabled;
89+
}
90+
9091
/* blazorCSSuppress */
9192
/* alternateType: object */
9293
/** Returns the HTMLFormElement associated with this element. */
93-
public get form() {
94+
public get form(): HTMLFormElement | null {
9495
return this.__internals.form;
9596
}
9697

@@ -101,51 +102,42 @@ export abstract class IgcButtonBaseComponent extends EventEmitterMixin<
101102

102103
/* alternateName: focusComponent */
103104
/** Sets focus in the button. */
104-
public override focus(options?: FocusOptions) {
105+
public override focus(options?: FocusOptions): void {
105106
this._nativeButton.focus(options);
106107
}
107108

108109
/** Simulates a mouse click on the element */
109-
public override click() {
110+
public override click(): void {
110111
this._nativeButton.click();
111112
}
112113

113114
/* alternateName: blurComponent */
114115
/** Removes focus from the button. */
115-
public override blur() {
116+
public override blur(): void {
116117
this._nativeButton.blur();
117118
}
118119

119-
protected handleBlur() {
120-
this._kbFocus.reset();
121-
}
122-
123-
protected handleClick() {
124-
this._kbFocus.reset();
125-
switch (this.type) {
126-
case 'submit':
127-
return this.form?.requestSubmit();
128-
case 'reset':
129-
return this.form?.reset();
130-
default:
131-
return;
120+
protected _handleClick(): void {
121+
if (this.type === 'submit') {
122+
this.form?.requestSubmit();
123+
} else if (this.type === 'reset') {
124+
this.form?.reset();
132125
}
133126
}
134127

135-
protected formDisabledCallback(state: boolean) {
128+
protected formDisabledCallback(state: boolean): void {
136129
this._disabled = state;
137130
this.requestUpdate();
138131
}
139132

140133
private renderButton() {
141134
return html`
142135
<button
143-
part=${partMap({ base: true, focused: this._kbFocus.focused })}
136+
part=${partMap({ base: true, focused: this._focusRingManager.focused })}
144137
aria-label=${ifDefined(this.ariaLabel ?? nothing)}
145138
?disabled=${this.disabled}
146139
type=${ifDefined(this.type)}
147-
@click=${this.handleClick}
148-
@blur=${this.handleBlur}
140+
@click=${this._handleClick}
149141
>
150142
${this.renderContent()}
151143
</button>
@@ -155,15 +147,14 @@ export abstract class IgcButtonBaseComponent extends EventEmitterMixin<
155147
private renderLinkButton() {
156148
return html`
157149
<a
158-
part=${partMap({ base: true, focused: this._kbFocus.focused })}
150+
part=${partMap({ base: true, focused: this._focusRingManager.focused })}
159151
role="button"
160152
aria-label=${ifDefined(this.ariaLabel ?? nothing)}
161153
aria-disabled=${this.disabled}
162154
href=${ifDefined(this.href)}
163155
target=${ifDefined(this.target)}
164156
download=${ifDefined(this.download)}
165157
rel=${ifDefined(this.rel)}
166-
@blur=${this.disabled ? nothing : this.handleBlur}
167158
>
168159
${this.renderContent()}
169160
</a>

src/components/calendar/calendar.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ import IgcYearsViewComponent from './years-view/years-view.js';
5656

5757
export const focusActiveDate = Symbol();
5858

59+
/* blazorIndirectRender */
60+
/* blazorSupportsVisualChildren */
5961
/**
6062
* Represents a calendar that lets users
6163
* to select a date value in a variety of different ways.

src/components/calendar/helpers.ts

Lines changed: 58 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
last,
77
modulo,
88
} from '../common/util.js';
9+
import type { DateRangeValue } from '../date-range-picker/date-range-picker.js';
910
import {
1011
CalendarDay,
1112
type CalendarRangeParams,
@@ -71,6 +72,33 @@ export function convertToDate(value?: Date | string | null): Date | null {
7172
return isString(value) ? parseISODate(value) : isValidDate(value);
7273
}
7374

75+
/**
76+
* Converts the given value to a DateRangeValue object.
77+
*
78+
* If the value is already a valid DateRangeValue object, it is returned directly.
79+
* If the value is a string, it is parsed to object and returned if it fields are valid dates.
80+
* If the value is null or undefined, null is returned.
81+
* If the parsing fails, null is returned.
82+
*/
83+
export function convertToDateRange(
84+
value?: DateRangeValue | string | null
85+
): DateRangeValue | null {
86+
if (!value) {
87+
return null;
88+
}
89+
90+
if (isString(value)) {
91+
const obj = JSON.parse(value);
92+
const start = convertToDate(obj.start);
93+
const end = convertToDate(obj.end);
94+
return {
95+
start: start ? CalendarDay.from(start).native : null,
96+
end: end ? CalendarDay.from(end).native : null,
97+
};
98+
}
99+
return value;
100+
}
101+
74102
/**
75103
* Converts a Date object to an ISO 8601 string.
76104
*
@@ -136,26 +164,41 @@ export function isPreviousMonth(target: DayParameter, origin: DayParameter) {
136164
}
137165

138166
/**
139-
* Returns a generator yielding day values between `start` and `end` (non-inclusive)
167+
* Returns a generator yielding day values between `start` and `end` (non-inclusive by default)
140168
* by a given `unit` as a step.
169+
* To include the end date set the `inclusive` option to true.
141170
*
142171
* @remarks
143172
* By default, `unit` is set to 'day'.
144173
*/
145-
export function* calendarRange(options: CalendarRangeParams) {
146-
let low = toCalendarDay(options.start);
147-
const unit = options.unit ?? 'day';
148-
const high =
149-
typeof options.end === 'number'
150-
? low.add(unit, options.end)
151-
: toCalendarDay(options.end);
152-
153-
const reverse = high.lessThan(low);
154-
const step = reverse ? -1 : 1;
155-
156-
while (!reverse ? low.lessThan(high) : low.greaterThan(high)) {
157-
yield low;
158-
low = low.add(unit, step);
174+
export function* calendarRange(
175+
options: CalendarRangeParams
176+
): Generator<CalendarDay, void, unknown> {
177+
const { start, end, unit = 'day', inclusive = false } = options;
178+
179+
let currentDate = toCalendarDay(start);
180+
const endDate =
181+
typeof end === 'number'
182+
? toCalendarDay(start).add(unit, end)
183+
: toCalendarDay(end);
184+
185+
const isReversed = endDate.lessThan(currentDate);
186+
const step = isReversed ? -1 : 1;
187+
188+
const shouldContinue = () => {
189+
if (inclusive) {
190+
return isReversed
191+
? currentDate.greaterThanOrEqual(endDate)
192+
: currentDate.lessThanOrEqual(endDate);
193+
}
194+
return isReversed
195+
? currentDate.greaterThan(endDate)
196+
: currentDate.lessThan(endDate);
197+
};
198+
199+
while (shouldContinue()) {
200+
yield currentDate;
201+
currentDate = currentDate.add(unit, step);
159202
}
160203
}
161204

0 commit comments

Comments
 (0)