Skip to content

Commit a9a5e9c

Browse files
committed
Merge branch 'main' of github.com:ionic-team/ionic-framework into FW-6259
2 parents 4d636a5 + 1cfa915 commit a9a5e9c

34 files changed

+515
-324
lines changed

CHANGELOG.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,34 @@
33
All notable changes to this project will be documented in this file.
44
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
55

6+
## [8.5.1](https://github.com/ionic-team/ionic-framework/compare/v8.5.0...v8.5.1) (2025-03-19)
7+
8+
9+
### Bug Fixes
10+
11+
* **modal:** consider scrollable content while dragging when expandToScroll is false ([#30257](https://github.com/ionic-team/ionic-framework/issues/30257)) ([68be8e9](https://github.com/ionic-team/ionic-framework/commit/68be8e915ce5637b20591bb0acfb3653c2184ff6))
12+
* **vue:** update output target and fix incorrect types ([#30259](https://github.com/ionic-team/ionic-framework/issues/30259)) ([f4186c6](https://github.com/ionic-team/ionic-framework/commit/f4186c6761c46bf386f8effecf90d88831c34726)), closes [#30254](https://github.com/ionic-team/ionic-framework/issues/30254)
13+
14+
15+
### Performance Improvements
16+
17+
* **modal:** fixing performance regression on modal sheets when expandToScroll is false ([#30267](https://github.com/ionic-team/ionic-framework/issues/30267)) ([c4b9212](https://github.com/ionic-team/ionic-framework/commit/c4b92126405ae5b7160ce03f40557563e755a8a5))
18+
19+
20+
21+
22+
23+
## [8.4.6](https://github.com/ionic-team/ionic-framework/compare/v8.4.5...v8.4.6) (2025-03-19)
24+
25+
26+
### Bug Fixes
27+
28+
* **vue:** update output target and fix incorrect types ([#30259](https://github.com/ionic-team/ionic-framework/issues/30259)) ([0eaee78](https://github.com/ionic-team/ionic-framework/commit/0eaee78fe1cae8f8a6cb04a01abad8c05dec0723)), closes [#30254](https://github.com/ionic-team/ionic-framework/issues/30254)
29+
30+
31+
32+
33+
634
# [8.5.0](https://github.com/ionic-team/ionic-framework/compare/v8.4.5...v8.5.0) (2025-03-13)
735

836

core/CHANGELOG.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,34 @@
33
All notable changes to this project will be documented in this file.
44
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
55

6+
## [8.5.1](https://github.com/ionic-team/ionic-framework/compare/v8.5.0...v8.5.1) (2025-03-19)
7+
8+
9+
### Bug Fixes
10+
11+
* **modal:** consider scrollable content while dragging when expandToScroll is false ([#30257](https://github.com/ionic-team/ionic-framework/issues/30257)) ([68be8e9](https://github.com/ionic-team/ionic-framework/commit/68be8e915ce5637b20591bb0acfb3653c2184ff6))
12+
* **vue:** update output target and fix incorrect types ([#30259](https://github.com/ionic-team/ionic-framework/issues/30259)) ([f4186c6](https://github.com/ionic-team/ionic-framework/commit/f4186c6761c46bf386f8effecf90d88831c34726)), closes [#30254](https://github.com/ionic-team/ionic-framework/issues/30254)
13+
14+
15+
### Performance Improvements
16+
17+
* **modal:** fixing performance regression on modal sheets when expandToScroll is false ([#30267](https://github.com/ionic-team/ionic-framework/issues/30267)) ([c4b9212](https://github.com/ionic-team/ionic-framework/commit/c4b92126405ae5b7160ce03f40557563e755a8a5))
18+
19+
20+
21+
22+
23+
## [8.4.6](https://github.com/ionic-team/ionic-framework/compare/v8.4.5...v8.4.6) (2025-03-19)
24+
25+
26+
### Bug Fixes
27+
28+
* **vue:** update output target and fix incorrect types ([#30259](https://github.com/ionic-team/ionic-framework/issues/30259)) ([0eaee78](https://github.com/ionic-team/ionic-framework/commit/0eaee78fe1cae8f8a6cb04a01abad8c05dec0723)), closes [#30254](https://github.com/ionic-team/ionic-framework/issues/30254)
29+
30+
31+
32+
33+
634
# [8.5.0](https://github.com/ionic-team/ionic-framework/compare/v8.4.5...v8.5.0) (2025-03-13)
735

836

core/package-lock.json

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

core/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@ionic/core",
3-
"version": "8.5.0",
3+
"version": "8.5.1",
44
"description": "Base components for Ionic",
55
"keywords": [
66
"ionic",
@@ -44,7 +44,7 @@
4444
"@clack/prompts": "^0.10.0",
4545
"@ionic/eslint-config": "^0.3.0",
4646
"@ionic/prettier-config": "^2.0.0",
47-
"@playwright/test": "^1.51.0",
47+
"@playwright/test": "^1.51.1",
4848
"@rollup/plugin-node-resolve": "^8.4.0",
4949
"@rollup/plugin-virtual": "^2.0.3",
5050
"@stencil/angular-output-target": "^0.10.0",

core/src/components/modal/gestures/sheet.ts

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
import { isIonContent, findClosestIonContent } from '@utils/content';
1+
import { findClosestIonContent, isIonContent } from '@utils/content';
22
import { createGesture } from '@utils/gesture';
3-
import { clamp, raf, getElementRoot } from '@utils/helpers';
3+
import { clamp, getElementRoot, raf } from '@utils/helpers';
44
import { FOCUS_TRAP_DISABLE_CLASS } from '@utils/overlays';
55

66
import type { Animation } from '../../../interface';
@@ -83,6 +83,7 @@ export const createSheetGesture = (
8383
let currentBreakpoint = initialBreakpoint;
8484
let offset = 0;
8585
let canDismissBlocksGesture = false;
86+
let cachedScrollEl: HTMLElement | null = null;
8687
const canDismissMaxStep = 0.95;
8788
const maxBreakpoint = breakpoints[breakpoints.length - 1];
8889
const minBreakpoint = breakpoints[0];
@@ -233,6 +234,17 @@ export const createSheetGesture = (
233234
*/
234235
canDismissBlocksGesture = baseEl.canDismiss !== undefined && baseEl.canDismiss !== true && minBreakpoint === 0;
235236

237+
/**
238+
* Cache the scroll element reference when the gesture starts,
239+
* this allows us to avoid querying the DOM for the target in onMove,
240+
* which would impact performance significantly.
241+
*/
242+
if (!expandToScroll) {
243+
const targetEl = findClosestIonContent(detail.event.target! as HTMLElement);
244+
cachedScrollEl =
245+
targetEl && isIonContent(targetEl) ? getElementRoot(targetEl).querySelector('.inner-scroll') : targetEl;
246+
}
247+
236248
/**
237249
* If expandToScroll is disabled, we need to swap
238250
* the footer visibility to the original, so if the modal
@@ -267,13 +279,8 @@ export const createSheetGesture = (
267279
* If `expandToScroll` is disabled, and an upwards swipe gesture is done within
268280
* the scrollable content, we should not allow the swipe gesture to continue.
269281
*/
270-
if (!expandToScroll && detail.deltaY <= 0) {
271-
const contentEl = findClosestIonContent(detail.event.target! as HTMLElement);
272-
const scrollEl =
273-
contentEl && isIonContent(contentEl) ? getElementRoot(contentEl).querySelector('.inner-scroll') : contentEl;
274-
if (scrollEl) {
275-
return;
276-
}
282+
if (!expandToScroll && detail.deltaY <= 0 && cachedScrollEl) {
283+
return;
277284
}
278285

279286
/**
@@ -334,12 +341,8 @@ export const createSheetGesture = (
334341
* function to be called if the user is trying to swipe content upwards and the content
335342
* is not scrolled to the top.
336343
*/
337-
if (!expandToScroll && detail.deltaY <= 0 && findClosestIonContent(detail.event.target! as HTMLElement)) {
338-
const contentEl = findClosestIonContent(detail.event.target! as HTMLElement)!;
339-
const scrollEl = isIonContent(contentEl) ? getElementRoot(contentEl).querySelector('.inner-scroll') : contentEl;
340-
if (scrollEl!.scrollTop > 0) {
341-
return;
342-
}
344+
if (!expandToScroll && detail.deltaY <= 0 && cachedScrollEl && cachedScrollEl.scrollTop > 0) {
345+
return;
343346
}
344347

345348
/**

core/src/components/range/range.tsx

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -213,12 +213,32 @@ export class Range implements ComponentInterface {
213213
*/
214214
@Prop({ mutable: true }) value: RangeValue = 0;
215215
@Watch('value')
216-
protected valueChanged() {
216+
protected valueChanged(newValue: RangeValue, oldValue: RangeValue) {
217+
const valuesChanged = this.compareValues(newValue, oldValue);
218+
if (valuesChanged) {
219+
this.ionInput.emit({ value: this.value });
220+
}
221+
217222
if (!this.noUpdate) {
218223
this.updateRatio();
219224
}
220225
}
221226

227+
/**
228+
* Compares two RangeValue inputs to determine if they are different.
229+
*
230+
* @param newVal - The new value.
231+
* @param oldVal - The old value.
232+
* @returns `true` if the values are different, `false` otherwise.
233+
*/
234+
private compareValues = (newVal: RangeValue, oldVal: RangeValue) => {
235+
if (typeof newVal === 'object' && typeof oldVal === 'object') {
236+
return newVal.lower !== oldVal.lower || newVal.upper !== oldVal.upper;
237+
}
238+
239+
return newVal !== oldVal;
240+
};
241+
222242
private clampBounds = (value: any): number => {
223243
return clamp(this.min, value, this.max);
224244
};
@@ -591,8 +611,6 @@ export class Range implements ComponentInterface {
591611
upper: Math.max(valA, valB),
592612
};
593613

594-
this.ionInput.emit({ value: this.value });
595-
596614
this.noUpdate = false;
597615
}
598616

core/src/components/range/test/range-events.e2e.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,42 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) =>
217217
expect(ionInputSpy).toHaveReceivedEvent();
218218
});
219219

220+
test('should not emit when the value does not change', async ({ page }, testInfo) => {
221+
testInfo.annotations.push({
222+
type: 'issue',
223+
description: 'https://github.com/ionic-team/ionic-framework/issues/29619',
224+
});
225+
226+
/**
227+
* Requires padding to prevent the knob from being clipped.
228+
* If it's clipped, then the value might be one off.
229+
* For example, if the knob is clipped on the right, then the value
230+
* will be 99 instead of 100.
231+
*/
232+
await page.setContent(
233+
`
234+
<div style="padding: 0 20px">
235+
<ion-range aria-label="range"></ion-range>
236+
</div>
237+
`,
238+
config
239+
);
240+
241+
const rangeHandle = page.locator('ion-range .range-knob-handle');
242+
const ionInputSpy = await page.spyOnEvent('ionInput');
243+
244+
const rangeHandleBoundingBox = await rangeHandle.boundingBox();
245+
const x = rangeHandleBoundingBox!.width / 2;
246+
const y = rangeHandleBoundingBox!.height / 2;
247+
248+
// Click in the middle of the knob to prevent the knob from moving.
249+
await rangeHandle.click({
250+
position: { x, y },
251+
});
252+
253+
expect(ionInputSpy).not.toHaveReceivedEvent();
254+
});
255+
220256
test('should emit when the knob is moved with the keyboard', async ({ page }) => {
221257
await page.setContent(`<ion-range aria-label="range" value="50"></ion-range>`, config);
222258

0 commit comments

Comments
 (0)