Skip to content

Commit 87a1a5f

Browse files
authored
merge release-8.6.2 (#30500)
Release v8.6.2
2 parents d52b253 + bc36d44 commit 87a1a5f

30 files changed

+506
-91
lines changed

CHANGELOG.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,18 @@
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.6.2](https://github.com/ionic-team/ionic-framework/compare/v8.6.1...v8.6.2) (2025-06-18)
7+
8+
9+
### Bug Fixes
10+
11+
* **picker-column:** fallback to elementFromPoint for iOS 16 Shadow DOM bug ([#30479](https://github.com/ionic-team/ionic-framework/issues/30479)) ([6ae2907](https://github.com/ionic-team/ionic-framework/commit/6ae29077424434f3523d75426f3328765a4797f4)), closes [#29672](https://github.com/ionic-team/ionic-framework/issues/29672)
12+
* **range:** improve focus and blur handling for dual knobs ([#30482](https://github.com/ionic-team/ionic-framework/issues/30482)) ([6811fe5](https://github.com/ionic-team/ionic-framework/commit/6811fe5cc88f132f998476a3f4b956ce21122631))
13+
14+
15+
16+
17+
618
## [8.6.1](https://github.com/ionic-team/ionic-framework/compare/v8.6.0...v8.6.1) (2025-06-11)
719

820

core/CHANGELOG.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,18 @@
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.6.2](https://github.com/ionic-team/ionic-framework/compare/v8.6.1...v8.6.2) (2025-06-18)
7+
8+
9+
### Bug Fixes
10+
11+
* **picker-column:** fallback to elementFromPoint for iOS 16 Shadow DOM bug ([#30479](https://github.com/ionic-team/ionic-framework/issues/30479)) ([6ae2907](https://github.com/ionic-team/ionic-framework/commit/6ae29077424434f3523d75426f3328765a4797f4)), closes [#29672](https://github.com/ionic-team/ionic-framework/issues/29672)
12+
* **range:** improve focus and blur handling for dual knobs ([#30482](https://github.com/ionic-team/ionic-framework/issues/30482)) ([6811fe5](https://github.com/ionic-team/ionic-framework/commit/6811fe5cc88f132f998476a3f4b956ce21122631))
13+
14+
15+
16+
17+
618
## [8.6.1](https://github.com/ionic-team/ionic-framework/compare/v8.6.0...v8.6.1) (2025-06-11)
719

820

core/package-lock.json

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

core/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@ionic/core",
3-
"version": "8.6.1",
3+
"version": "8.6.2",
44
"description": "Base components for Ionic",
55
"keywords": [
66
"ionic",

core/src/components/picker-column/picker-column.tsx

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -376,7 +376,27 @@ export class PickerColumn implements ComponentInterface {
376376
* elementsFromPoint can returns multiple elements
377377
* so find the relevant picker column option if one exists.
378378
*/
379-
const newActiveElement = elementsAtPoint.find((el) => el.tagName === 'ION-PICKER-COLUMN-OPTION');
379+
let newActiveElement = elementsAtPoint.find((el) => el.tagName === 'ION-PICKER-COLUMN-OPTION');
380+
381+
/**
382+
* TODO(FW-6594): Remove this workaround when iOS 16 is no longer
383+
* supported.
384+
*
385+
* If `elementsFromPoint` failed to find the active element (a known
386+
* issue on iOS 16 when elements are in a Shadow DOM and the
387+
* referenceNode is the document), a fallback to `elementFromPoint`
388+
* is used. While `elementsFromPoint` returns all elements,
389+
* `elementFromPoint` returns only the top-most, which is sufficient
390+
* for this use case and appears to handle Shadow DOM retargeting
391+
* more reliably in this specific iOS bug.
392+
*/
393+
if (newActiveElement === undefined) {
394+
const fallbackActiveElement = referenceNode.elementFromPoint(centerX, centerY);
395+
396+
if (fallbackActiveElement?.tagName === 'ION-PICKER-COLUMN-OPTION') {
397+
newActiveElement = fallbackActiveElement as HTMLIonPickerColumnOptionElement;
398+
}
399+
}
380400

381401
if (activeEl !== undefined) {
382402
this.setPickerItemActiveState(activeEl, false);

core/src/components/range/range.tsx

Lines changed: 68 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -639,6 +639,51 @@ export class Range implements ComponentInterface {
639639
}
640640
};
641641

642+
private onKnobFocus = (knob: KnobName) => {
643+
if (!this.hasFocus) {
644+
this.hasFocus = true;
645+
this.ionFocus.emit();
646+
}
647+
648+
// Manually manage ion-focused class for dual knobs
649+
if (this.dualKnobs && this.el.shadowRoot) {
650+
const knobA = this.el.shadowRoot.querySelector('.range-knob-a');
651+
const knobB = this.el.shadowRoot.querySelector('.range-knob-b');
652+
653+
// Remove ion-focused from both knobs first
654+
knobA?.classList.remove('ion-focused');
655+
knobB?.classList.remove('ion-focused');
656+
657+
// Add ion-focused only to the focused knob
658+
const focusedKnobEl = knob === 'A' ? knobA : knobB;
659+
focusedKnobEl?.classList.add('ion-focused');
660+
}
661+
};
662+
663+
private onKnobBlur = () => {
664+
// Check if focus is moving to another knob within the same range
665+
// by delaying the reset to allow the new focus to register
666+
setTimeout(() => {
667+
const activeElement = this.el.shadowRoot?.activeElement;
668+
const isStillFocusedOnKnob = activeElement && activeElement.classList.contains('range-knob-handle');
669+
670+
if (!isStillFocusedOnKnob) {
671+
if (this.hasFocus) {
672+
this.hasFocus = false;
673+
this.ionBlur.emit();
674+
}
675+
676+
// Remove ion-focused from both knobs when focus leaves the range
677+
if (this.dualKnobs && this.el.shadowRoot) {
678+
const knobA = this.el.shadowRoot.querySelector('.range-knob-a');
679+
const knobB = this.el.shadowRoot.querySelector('.range-knob-b');
680+
knobA?.classList.remove('ion-focused');
681+
knobB?.classList.remove('ion-focused');
682+
}
683+
}
684+
}, 0);
685+
};
686+
642687
/**
643688
* Returns true if content was passed to the "start" slot
644689
*/
@@ -813,6 +858,8 @@ export class Range implements ComponentInterface {
813858
min,
814859
max,
815860
inheritedAttributes,
861+
onKnobFocus: this.onKnobFocus,
862+
onKnobBlur: this.onKnobBlur,
816863
})}
817864

818865
{this.dualKnobs &&
@@ -828,6 +875,8 @@ export class Range implements ComponentInterface {
828875
min,
829876
max,
830877
inheritedAttributes,
878+
onKnobFocus: this.onKnobFocus,
879+
onKnobBlur: this.onKnobBlur,
831880
})}
832881
</div>
833882
);
@@ -908,11 +957,27 @@ interface RangeKnob {
908957
pinFormatter: PinFormatter;
909958
inheritedAttributes: Attributes;
910959
handleKeyboard: (name: KnobName, isIncrease: boolean) => void;
960+
onKnobFocus: (knob: KnobName) => void;
961+
onKnobBlur: () => void;
911962
}
912963

913964
const renderKnob = (
914965
rtl: boolean,
915-
{ knob, value, ratio, min, max, disabled, pressed, pin, handleKeyboard, pinFormatter, inheritedAttributes }: RangeKnob
966+
{
967+
knob,
968+
value,
969+
ratio,
970+
min,
971+
max,
972+
disabled,
973+
pressed,
974+
pin,
975+
handleKeyboard,
976+
pinFormatter,
977+
inheritedAttributes,
978+
onKnobFocus,
979+
onKnobBlur,
980+
}: RangeKnob
916981
) => {
917982
const start = rtl ? 'right' : 'left';
918983

@@ -941,6 +1006,8 @@ const renderKnob = (
9411006
ev.stopPropagation();
9421007
}
9431008
}}
1009+
onFocus={() => onKnobFocus(knob)}
1010+
onBlur={onKnobBlur}
9441011
class={{
9451012
'range-knob-handle': true,
9461013
'range-knob-a': knob === 'A',

core/src/components/range/test/basic/index.html

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,10 @@ <h2>Pin</h2>
8080
lower: '10',
8181
upper: '90',
8282
};
83+
84+
dualKnobs.addEventListener('ionFocus', () => {
85+
console.log('Dual Knob ionFocus', dualKnobs.value);
86+
});
8387
</script>
8488
</body>
8589
</html>

0 commit comments

Comments
 (0)