@ionic/core 8.8.7-dev.11779385275.161a641b → 8.8.7-dev.11779467048.1641d05e
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/components/index.js +1 -1
- package/components/ion-action-sheet.js +1 -1
- package/components/ion-alert.js +1 -1
- package/components/ion-datetime.js +1 -1
- package/components/ion-gallery.js +1 -1
- package/components/ion-loading.js +1 -1
- package/components/ion-menu.js +1 -1
- package/components/ion-modal.js +1 -1
- package/components/ion-picker-legacy.js +1 -1
- package/components/ion-popover.js +1 -1
- package/components/ion-select-modal.js +1 -1
- package/components/ion-select-popover.js +1 -1
- package/components/ion-select.js +1 -1
- package/components/ion-toast.js +1 -1
- package/components/{p-B2rpt1JV.js → p-C38HUpU5.js} +1 -1
- package/components/{p-Dmuy6xyk.js → p-C4G6C9fP.js} +1 -1
- package/components/{p-B6zr9RZN.js → p-CVRxImH6.js} +1 -1
- package/components/{p-B71c6yUH.js → p-CoFDGTFO.js} +1 -1
- package/components/{p-DAv9P_LE.js → p-CykCvfXQ.js} +1 -1
- package/components/p-DHTe6lDL.js +4 -0
- package/components/{p-Di5rHO3q.js → p-qZr7hBPz.js} +1 -1
- package/dist/cjs/index.cjs.js +1 -1
- package/dist/cjs/ion-action-sheet.cjs.entry.js +1 -1
- package/dist/cjs/ion-alert.cjs.entry.js +1 -1
- package/dist/cjs/ion-datetime_3.cjs.entry.js +1 -1
- package/dist/cjs/ion-gallery.cjs.entry.js +7 -28
- package/dist/cjs/ion-loading.cjs.entry.js +1 -1
- package/dist/cjs/ion-menu_3.cjs.entry.js +1 -1
- package/dist/cjs/ion-modal.cjs.entry.js +1 -1
- package/dist/cjs/ion-popover.cjs.entry.js +1 -1
- package/dist/cjs/ion-select-modal.cjs.entry.js +1 -1
- package/dist/cjs/ion-select_3.cjs.entry.js +1 -1
- package/dist/cjs/ion-toast.cjs.entry.js +1 -1
- package/dist/cjs/{overlays-Hci_7vw_.js → overlays-C54DhaTC.js} +187 -10
- package/dist/collection/components/gallery/gallery.js +7 -28
- package/dist/collection/utils/overlays.js +187 -10
- package/dist/docs.json +1 -1
- package/dist/esm/index.js +1 -1
- package/dist/esm/ion-action-sheet.entry.js +1 -1
- package/dist/esm/ion-alert.entry.js +1 -1
- package/dist/esm/ion-datetime_3.entry.js +1 -1
- package/dist/esm/ion-gallery.entry.js +7 -28
- package/dist/esm/ion-loading.entry.js +1 -1
- package/dist/esm/ion-menu_3.entry.js +1 -1
- package/dist/esm/ion-modal.entry.js +1 -1
- package/dist/esm/ion-popover.entry.js +1 -1
- package/dist/esm/ion-select-modal.entry.js +1 -1
- package/dist/esm/ion-select_3.entry.js +1 -1
- package/dist/esm/ion-toast.entry.js +1 -1
- package/dist/esm/{overlays-rwDDzEs4.js → overlays-ttYCMKRp.js} +187 -10
- package/dist/ionic/index.esm.js +1 -1
- package/dist/ionic/ionic.esm.js +1 -1
- package/dist/ionic/p-06bd033b.entry.js +4 -0
- package/dist/ionic/{p-c10fa162.entry.js → p-1f74b8d4.entry.js} +1 -1
- package/dist/ionic/{p-a9fb086b.entry.js → p-2f8aa0ac.entry.js} +1 -1
- package/dist/ionic/{p-2f0073af.entry.js → p-3331cfa9.entry.js} +1 -1
- package/dist/ionic/{p-35b144f5.entry.js → p-33c34361.entry.js} +1 -1
- package/dist/ionic/{p-15e3e8f5.entry.js → p-5061a8d4.entry.js} +1 -1
- package/dist/ionic/{p-4a0260e6.entry.js → p-8f04bd89.entry.js} +1 -1
- package/dist/ionic/{p-bf972309.entry.js → p-967576f8.entry.js} +1 -1
- package/dist/ionic/p-DdyNaGpi.js +4 -0
- package/dist/ionic/{p-71b6014c.entry.js → p-bb898d47.entry.js} +1 -1
- package/dist/ionic/p-dea52cb3.entry.js +4 -0
- package/dist/ionic/{p-432c5888.entry.js → p-fc796d48.entry.js} +1 -1
- package/dist/types/components/gallery/gallery.d.ts +2 -5
- package/hydrate/index.js +194 -38
- package/hydrate/index.mjs +194 -38
- package/package.json +1 -1
- package/components/p-CtiqM786.js +0 -4
- package/dist/ionic/p-0f3b4262.entry.js +0 -4
- package/dist/ionic/p-4079cee3.entry.js +0 -4
- package/dist/ionic/p-C4uUM9DM.js +0 -4
|
@@ -54,7 +54,6 @@ const BREAKPOINT_ORDER = ['xs', 'sm', 'md', 'lg', 'xl', 'xxl'];
|
|
|
54
54
|
const Gallery = class {
|
|
55
55
|
constructor(hostRef) {
|
|
56
56
|
registerInstance(this, hostRef);
|
|
57
|
-
this.itemWrapperSelector = '[data-gallery-group]';
|
|
58
57
|
// Keep track of whether we've warned about invalid columns, invalid gap,
|
|
59
58
|
// and unused order properties to avoid duplicate warnings on screen resize.
|
|
60
59
|
this.hasWarnedInvalidColumns = false;
|
|
@@ -109,9 +108,8 @@ const Gallery = class {
|
|
|
109
108
|
const styles = getComputedStyle(this.el);
|
|
110
109
|
const rowHeight = parseFloat(styles.getPropertyValue('grid-auto-rows')) || 0;
|
|
111
110
|
const rowGap = parseFloat(styles.getPropertyValue('row-gap')) || parseFloat(styles.getPropertyValue('gap')) || 0;
|
|
112
|
-
const itemGap = parseFloat(styles.getPropertyValue('column-gap')) || parseFloat(styles.getPropertyValue('gap')) || 0;
|
|
113
111
|
const items = this.getItems();
|
|
114
|
-
this.layoutMasonry(items, rowHeight, rowGap,
|
|
112
|
+
this.layoutMasonry(items, rowHeight, rowGap, columns);
|
|
115
113
|
};
|
|
116
114
|
}
|
|
117
115
|
onColumnsOrGapChanged() {
|
|
@@ -368,28 +366,12 @@ const Gallery = class {
|
|
|
368
366
|
const gap = this.getGapForWidth(width);
|
|
369
367
|
this.el.style.setProperty('--internal-gallery-gap', `${gap}`);
|
|
370
368
|
}
|
|
371
|
-
isGalleryItemElement(element) {
|
|
372
|
-
var _a;
|
|
373
|
-
return typeof ((_a = element.style) === null || _a === void 0 ? void 0 : _a.setProperty) === 'function';
|
|
374
|
-
}
|
|
375
369
|
/**
|
|
376
|
-
* Return all gallery
|
|
377
|
-
*
|
|
378
|
-
* with their element children.
|
|
370
|
+
* Return all directly slotted children of the gallery that can be grid items
|
|
371
|
+
* with inline placement styles (HTML elements and SVG elements).
|
|
379
372
|
*/
|
|
380
373
|
getItems() {
|
|
381
|
-
|
|
382
|
-
const flattenedItems = [];
|
|
383
|
-
items.forEach((itemEl) => {
|
|
384
|
-
if (!itemEl.matches(this.itemWrapperSelector)) {
|
|
385
|
-
flattenedItems.push(itemEl);
|
|
386
|
-
return;
|
|
387
|
-
}
|
|
388
|
-
itemEl.style.display = 'contents';
|
|
389
|
-
const wrappedItems = Array.from(itemEl.children).filter((child) => this.isGalleryItemElement(child));
|
|
390
|
-
flattenedItems.push(...wrappedItems);
|
|
391
|
-
});
|
|
392
|
-
return flattenedItems;
|
|
374
|
+
return Array.from(this.el.children).filter((child) => { var _a; return typeof ((_a = child.style) === null || _a === void 0 ? void 0 : _a.setProperty) === 'function'; });
|
|
393
375
|
}
|
|
394
376
|
/**
|
|
395
377
|
* Clear the item styles for the given item element.
|
|
@@ -446,14 +428,11 @@ const Gallery = class {
|
|
|
446
428
|
/**
|
|
447
429
|
* Apply masonry placement by assigning each item a column and row span.
|
|
448
430
|
*/
|
|
449
|
-
layoutMasonry(items, rowHeight, rowGap,
|
|
431
|
+
layoutMasonry(items, rowHeight, rowGap, columns) {
|
|
450
432
|
const columnHeights = new Array(columns).fill(0);
|
|
451
433
|
const lastItemsByColumn = new Array(columns).fill(undefined);
|
|
452
434
|
items.forEach((itemEl, i) => {
|
|
453
435
|
itemEl.style.marginBottom = '';
|
|
454
|
-
if (itemEl.parentElement !== this.el) {
|
|
455
|
-
itemEl.style.marginBottom = `${itemGap}px`;
|
|
456
|
-
}
|
|
457
436
|
const span = this.calculateRowSpan(itemEl, rowHeight, rowGap);
|
|
458
437
|
if (span === undefined) {
|
|
459
438
|
this.clearItemStyles(itemEl);
|
|
@@ -502,11 +481,11 @@ const Gallery = class {
|
|
|
502
481
|
const { layout } = this;
|
|
503
482
|
const order = this.getOrder();
|
|
504
483
|
const theme = getIonTheme(this);
|
|
505
|
-
return (h(Host, { key: '
|
|
484
|
+
return (h(Host, { key: '1bf2973d22835c0dbddf3214b602f8c08b95e421', class: {
|
|
506
485
|
[theme]: true,
|
|
507
486
|
[`gallery-layout-${layout}`]: true,
|
|
508
487
|
[`gallery-order-${order}`]: layout === 'masonry' && order !== undefined,
|
|
509
|
-
} }, h("slot", { key: '
|
|
488
|
+
} }, h("slot", { key: '0dea31f609f6afdb1d73ecb2d873909ffe49203f', onSlotchange: this.onSlotChange })));
|
|
510
489
|
}
|
|
511
490
|
get el() { return getElement(this); }
|
|
512
491
|
static get watchers() { return {
|
|
@@ -5,7 +5,7 @@ import { r as registerInstance, c as createEvent, e as config, h, d as Host, g a
|
|
|
5
5
|
import { E as ENABLE_HTML_CONTENT_DEFAULT } from './config-BwKpO3Is.js';
|
|
6
6
|
import { r as raf } from './helpers-Do7zwvM1.js';
|
|
7
7
|
import { c as createLockController } from './lock-controller-B-hirT0v.js';
|
|
8
|
-
import { d as createDelegateController, e as createTriggerController, B as BACKDROP, j as prepareOverlay, k as setOverlayId, f as present, g as dismiss, h as eventMethod } from './overlays-
|
|
8
|
+
import { d as createDelegateController, e as createTriggerController, B as BACKDROP, j as prepareOverlay, k as setOverlayId, f as present, g as dismiss, h as eventMethod } from './overlays-ttYCMKRp.js';
|
|
9
9
|
import { s as sanitizeDOMString } from './index-D4ugF_sT.js';
|
|
10
10
|
import { g as getClassMap } from './theme-DaJxRxSQ.js';
|
|
11
11
|
import { c as getIonTheme } from './ionic-global-CAZb-5i-.js';
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import { r as registerInstance, c as createEvent, e as config, j as printIonError, h, d as Host, g as getElement } from './index-Omi_TcwW.js';
|
|
5
5
|
import { g as getTimeGivenProgression } from './cubic-bezier-hHmYLOfE.js';
|
|
6
|
-
import { o as getPresentedOverlay, B as BACKDROP, n as focusFirstDescendant, q as focusLastDescendant, G as GESTURE } from './overlays-
|
|
6
|
+
import { o as getPresentedOverlay, B as BACKDROP, n as focusFirstDescendant, q as focusLastDescendant, G as GESTURE } from './overlays-ttYCMKRp.js';
|
|
7
7
|
import { G as GESTURE_CONTROLLER } from './gesture-controller-BTEOs1at.js';
|
|
8
8
|
import { b as getIonMode, a as isPlatform, c as getIonTheme, s as shouldUseCloseWatcher } from './ionic-global-CAZb-5i-.js';
|
|
9
9
|
import { p as isEndSide, i as inheritAriaAttributes, l as assert, e as clamp } from './helpers-Do7zwvM1.js';
|
|
@@ -7,7 +7,7 @@ import { C as CoreDelegate, a as attachComponent, d as detachComponent } from '.
|
|
|
7
7
|
import { g as getElementRoot, e as clamp, r as raf, b as inheritAttributes, h as hasLazyBuild } from './helpers-Do7zwvM1.js';
|
|
8
8
|
import { c as createLockController } from './lock-controller-B-hirT0v.js';
|
|
9
9
|
import { g as getCapacitor } from './capacitor-C4lYa1nV.js';
|
|
10
|
-
import { G as GESTURE, O as OVERLAY_GESTURE_PRIORITY, F as FOCUS_TRAP_DISABLE_CLASS, e as createTriggerController, B as BACKDROP, j as prepareOverlay, k as setOverlayId, f as present, g as dismiss, h as eventMethod } from './overlays-
|
|
10
|
+
import { G as GESTURE, O as OVERLAY_GESTURE_PRIORITY, F as FOCUS_TRAP_DISABLE_CLASS, e as createTriggerController, B as BACKDROP, j as prepareOverlay, k as setOverlayId, f as present, g as dismiss, h as eventMethod } from './overlays-ttYCMKRp.js';
|
|
11
11
|
import { g as getClassMap } from './theme-DaJxRxSQ.js';
|
|
12
12
|
import { e as deepReady, w as waitForMount } from './index-CGthURny.js';
|
|
13
13
|
import { w as win, b as getIonMode, c as getIonTheme } from './ionic-global-CAZb-5i-.js';
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* (C) Ionic http://ionicframework.com - MIT License
|
|
3
3
|
*/
|
|
4
4
|
import { r as registerInstance, c as createEvent, f as printIonWarning, h, d as Host, g as getElement } from './index-Omi_TcwW.js';
|
|
5
|
-
import { B as BACKDROP, j as prepareOverlay, k as setOverlayId, f as present, n as focusFirstDescendant, g as dismiss, h as eventMethod, F as FOCUS_TRAP_DISABLE_CLASS } from './overlays-
|
|
5
|
+
import { B as BACKDROP, j as prepareOverlay, k as setOverlayId, f as present, n as focusFirstDescendant, g as dismiss, h as eventMethod, F as FOCUS_TRAP_DISABLE_CLASS } from './overlays-ttYCMKRp.js';
|
|
6
6
|
import { C as CoreDelegate, a as attachComponent, d as detachComponent } from './framework-delegate-CjVwn_KZ.js';
|
|
7
7
|
import { g as getElementRoot, r as raf, f as addEventListener, h as hasLazyBuild } from './helpers-Do7zwvM1.js';
|
|
8
8
|
import { c as createLockController } from './lock-controller-B-hirT0v.js';
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
import { r as registerInstance, h, i as forceUpdate, d as Host, g as getElement } from './index-Omi_TcwW.js';
|
|
5
5
|
import { c as getIonTheme, b as getIonMode } from './ionic-global-CAZb-5i-.js';
|
|
6
6
|
import { x as xSvg } from './x-BDqjX7Z_.js';
|
|
7
|
-
import { s as safeCall } from './overlays-
|
|
7
|
+
import { s as safeCall } from './overlays-ttYCMKRp.js';
|
|
8
8
|
import { r as renderOptionLabel } from './select-option-render-B2qc5ZP7.js';
|
|
9
9
|
import { h as hostContext, g as getClassMap } from './theme-DaJxRxSQ.js';
|
|
10
10
|
import { b as closeSharp, z as closeOutline } from './index-D2tu5BUg.js';
|
|
@@ -8,7 +8,7 @@ import { c as createNotchController } from './notch-controller-DiBq57w8.js';
|
|
|
8
8
|
import { i as isOptionSelected, c as compareOptions } from './compare-with-utils-sObYyvOy.js';
|
|
9
9
|
import { c as checkInvalidState } from './validity-BjW8SOqw.js';
|
|
10
10
|
import { b as inheritAttributes, a as renderHiddenInput, o as focusVisibleElement } from './helpers-Do7zwvM1.js';
|
|
11
|
-
import { c as popoverController, b as actionSheetController, a as alertController, m as modalController, s as safeCall } from './overlays-
|
|
11
|
+
import { c as popoverController, b as actionSheetController, a as alertController, m as modalController, s as safeCall } from './overlays-ttYCMKRp.js';
|
|
12
12
|
import { i as isRTL } from './dir-C53feagD.js';
|
|
13
13
|
import { s as sanitizeDOMString } from './index-D4ugF_sT.js';
|
|
14
14
|
import { h as hostContext, c as createColorClasses, g as getClassMap } from './theme-DaJxRxSQ.js';
|
|
@@ -5,7 +5,7 @@ import { f as printIonWarning, r as registerInstance, c as createEvent, e as con
|
|
|
5
5
|
import { E as ENABLE_HTML_CONTENT_DEFAULT } from './config-BwKpO3Is.js';
|
|
6
6
|
import { g as getElementRoot, r as raf } from './helpers-Do7zwvM1.js';
|
|
7
7
|
import { c as createLockController } from './lock-controller-B-hirT0v.js';
|
|
8
|
-
import { O as OVERLAY_GESTURE_PRIORITY, d as createDelegateController, e as createTriggerController, i as isCancel, j as prepareOverlay, k as setOverlayId, f as present, g as dismiss, h as eventMethod, s as safeCall, G as GESTURE } from './overlays-
|
|
8
|
+
import { O as OVERLAY_GESTURE_PRIORITY, d as createDelegateController, e as createTriggerController, i as isCancel, j as prepareOverlay, k as setOverlayId, f as present, g as dismiss, h as eventMethod, s as safeCall, G as GESTURE } from './overlays-ttYCMKRp.js';
|
|
9
9
|
import { s as sanitizeDOMString } from './index-D4ugF_sT.js';
|
|
10
10
|
import { c as createColorClasses, g as getClassMap } from './theme-DaJxRxSQ.js';
|
|
11
11
|
import { w as win, b as getIonMode, c as getIonTheme } from './ionic-global-CAZb-5i-.js';
|
|
@@ -102,8 +102,101 @@ const focusElementInContext = (hostToFocus, fallbackElement) => {
|
|
|
102
102
|
let lastOverlayIndex = 0;
|
|
103
103
|
let lastId = 0;
|
|
104
104
|
const activeAnimations = new WeakMap();
|
|
105
|
+
const OVERLAY_FOCUS_TRAP_SELECTOR = 'ion-alert,ion-action-sheet,ion-loading,ion-modal,ion-picker-legacy,ion-popover';
|
|
106
|
+
const ION_SELECT_MODAL_SELECTOR = 'ion-select-modal';
|
|
107
|
+
const isSelectModalOptionControl = (el) => el.tagName === 'ION-RADIO' || el.tagName === 'ION-CHECKBOX';
|
|
105
108
|
/**
|
|
106
|
-
*
|
|
109
|
+
* Returns the currently focused element for keyboard focus checks.
|
|
110
|
+
*
|
|
111
|
+
* Starts from `document.activeElement` (non-shadow / light DOM focus).
|
|
112
|
+
* If focus is inside one or more open shadow roots
|
|
113
|
+
* (e.g. native control inside `ion-radio`), walks through nested
|
|
114
|
+
* `shadowRoot.activeElement` values until the innermost focused node is reached.
|
|
115
|
+
*/
|
|
116
|
+
const getActiveElement = (ownerDoc) => {
|
|
117
|
+
var _a;
|
|
118
|
+
let active = ownerDoc.activeElement;
|
|
119
|
+
if (!active) {
|
|
120
|
+
return null;
|
|
121
|
+
}
|
|
122
|
+
while ((_a = active.shadowRoot) === null || _a === void 0 ? void 0 : _a.activeElement) {
|
|
123
|
+
active = active.shadowRoot.activeElement;
|
|
124
|
+
}
|
|
125
|
+
return active;
|
|
126
|
+
};
|
|
127
|
+
/**
|
|
128
|
+
* Walks from a focused node (possibly deep inside shadow roots)
|
|
129
|
+
* up to the nearest `ion-radio` / `ion-checkbox` host.
|
|
130
|
+
*/
|
|
131
|
+
const getOptionControlHost = (active) => {
|
|
132
|
+
let n = active;
|
|
133
|
+
while (n) {
|
|
134
|
+
if (isSelectModalOptionControl(n)) {
|
|
135
|
+
return n;
|
|
136
|
+
}
|
|
137
|
+
const root = n.getRootNode();
|
|
138
|
+
if (root instanceof ShadowRoot && root.host instanceof HTMLElement) {
|
|
139
|
+
n = root.host;
|
|
140
|
+
}
|
|
141
|
+
else {
|
|
142
|
+
return null;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
return null;
|
|
146
|
+
};
|
|
147
|
+
/**
|
|
148
|
+
* Sheet modals can have visual order that differs from DOM order.
|
|
149
|
+
* Without sorting, Tab can skip the handle after option traversal.
|
|
150
|
+
*
|
|
151
|
+
* Order: option controls (radio/checkbox) → sheet handle → end-slot
|
|
152
|
+
* header button. Any other focusables are appended after.
|
|
153
|
+
*/
|
|
154
|
+
const sortSheetModalFocusables = (overlay, elements) => {
|
|
155
|
+
const optionControls = elements.filter((el) => {
|
|
156
|
+
return overlay.contains(el) && isSelectModalOptionControl(el) && el.tabIndex >= 0;
|
|
157
|
+
});
|
|
158
|
+
const cancelControl = elements.find((el) => overlay.contains(el) &&
|
|
159
|
+
el.tagName === 'ION-BUTTON' &&
|
|
160
|
+
el.closest('ion-header ion-buttons[slot="end"]') !== null);
|
|
161
|
+
const handleControl = elements.find((el) => el.classList.contains('modal-handle'));
|
|
162
|
+
const sortByGeometry = (els) => [...els].sort((a, b) => {
|
|
163
|
+
const ra = a.getBoundingClientRect();
|
|
164
|
+
const rb = b.getBoundingClientRect();
|
|
165
|
+
const topDiff = ra.top - rb.top;
|
|
166
|
+
if (Math.abs(topDiff) > 1) {
|
|
167
|
+
return topDiff;
|
|
168
|
+
}
|
|
169
|
+
return ra.left - rb.left;
|
|
170
|
+
});
|
|
171
|
+
const ordered = [];
|
|
172
|
+
ordered.push(...sortByGeometry(optionControls));
|
|
173
|
+
if (handleControl) {
|
|
174
|
+
ordered.push(handleControl);
|
|
175
|
+
}
|
|
176
|
+
if (cancelControl) {
|
|
177
|
+
ordered.push(cancelControl);
|
|
178
|
+
}
|
|
179
|
+
const used = new Set(ordered);
|
|
180
|
+
for (const el of elements) {
|
|
181
|
+
if (!used.has(el)) {
|
|
182
|
+
ordered.push(el);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
return ordered;
|
|
186
|
+
};
|
|
187
|
+
/**
|
|
188
|
+
* Option controls in groups use a tabindex pattern where only one
|
|
189
|
+
* option is tabbable (`tabIndex="0"`) while the others are `-1`.
|
|
190
|
+
* This returns the index of that current tabbable option.
|
|
191
|
+
*/
|
|
192
|
+
const getTabbableOptionControlIndex = (elements, overlay) => {
|
|
193
|
+
return elements.findIndex((el) => {
|
|
194
|
+
return overlay.contains(el) && isSelectModalOptionControl(el) && el.tabIndex >= 0;
|
|
195
|
+
});
|
|
196
|
+
};
|
|
197
|
+
/**
|
|
198
|
+
* Determines if the overlay's backdrop is always blocking
|
|
199
|
+
* (no background interaction).
|
|
107
200
|
* Returns false if showBackdrop=false or backdropBreakpoint > 0.
|
|
108
201
|
*/
|
|
109
202
|
const isBackdropAlwaysBlocking = (el) => {
|
|
@@ -224,7 +317,7 @@ const focusElementInOverlay = (hostToFocus, overlay) => {
|
|
|
224
317
|
* Should NOT include: Toast
|
|
225
318
|
*/
|
|
226
319
|
const trapKeyboardFocus = (ev, doc) => {
|
|
227
|
-
const lastOverlay = getPresentedOverlay(doc,
|
|
320
|
+
const lastOverlay = getPresentedOverlay(doc, OVERLAY_FOCUS_TRAP_SELECTOR);
|
|
228
321
|
const target = ev.target;
|
|
229
322
|
/**
|
|
230
323
|
* If no active overlay, ignore this event.
|
|
@@ -407,6 +500,30 @@ const connectListeners = (doc) => {
|
|
|
407
500
|
doc.addEventListener('focus', (ev) => {
|
|
408
501
|
trapKeyboardFocus(ev, doc);
|
|
409
502
|
}, true);
|
|
503
|
+
/**
|
|
504
|
+
* Remember which option control last received focus
|
|
505
|
+
* (arrows, click, or Tab). This pattern keeps `tabIndex=0` on the
|
|
506
|
+
* checked/first radio, so the Tab trap uses this when wrapping back
|
|
507
|
+
* into the list or focusing the option-group slot.
|
|
508
|
+
*/
|
|
509
|
+
doc.addEventListener('focusin', (ev) => {
|
|
510
|
+
const lastOverlay = getPresentedOverlay(doc, OVERLAY_FOCUS_TRAP_SELECTOR);
|
|
511
|
+
if (!lastOverlay || lastOverlay.classList.contains(FOCUS_TRAP_DISABLE_CLASS)) {
|
|
512
|
+
return;
|
|
513
|
+
}
|
|
514
|
+
const isSheetModal = lastOverlay.classList.contains('modal-sheet');
|
|
515
|
+
if (!isSheetModal) {
|
|
516
|
+
return;
|
|
517
|
+
}
|
|
518
|
+
const target = ev.target;
|
|
519
|
+
if (!(target instanceof HTMLElement)) {
|
|
520
|
+
return;
|
|
521
|
+
}
|
|
522
|
+
const optionHost = getOptionControlHost(target);
|
|
523
|
+
if (optionHost && lastOverlay.contains(optionHost)) {
|
|
524
|
+
lastOverlay.trapLastSheetOptionControl = optionHost;
|
|
525
|
+
}
|
|
526
|
+
}, true);
|
|
410
527
|
// Listen for keydown events to intercept Tab navigation.
|
|
411
528
|
// This is needed for Safari and Firefox which may skip focusable
|
|
412
529
|
// elements or allow focus to escape the overlay.
|
|
@@ -416,10 +533,10 @@ const connectListeners = (doc) => {
|
|
|
416
533
|
var _a, _b, _c;
|
|
417
534
|
if (ev.key !== 'Tab' && ev.key !== 'Alt+Tab')
|
|
418
535
|
return;
|
|
419
|
-
const lastOverlay = getPresentedOverlay(doc,
|
|
536
|
+
const lastOverlay = getPresentedOverlay(doc, OVERLAY_FOCUS_TRAP_SELECTOR);
|
|
420
537
|
if (!lastOverlay || lastOverlay.classList.contains(FOCUS_TRAP_DISABLE_CLASS))
|
|
421
538
|
return;
|
|
422
|
-
const activeElement = doc
|
|
539
|
+
const activeElement = getActiveElement(doc);
|
|
423
540
|
if (activeElement === lastOverlay) {
|
|
424
541
|
ev.preventDefault();
|
|
425
542
|
focusFirstDescendant(lastOverlay);
|
|
@@ -435,16 +552,32 @@ const connectListeners = (doc) => {
|
|
|
435
552
|
if (!isInsideOverlay)
|
|
436
553
|
return;
|
|
437
554
|
// Get all focusable elements from both light and shadow DOM
|
|
438
|
-
|
|
555
|
+
let allFocusable = [
|
|
439
556
|
...lastOverlay.querySelectorAll(focusableQueryString),
|
|
440
557
|
...(((_c = lastOverlay.shadowRoot) === null || _c === void 0 ? void 0 : _c.querySelectorAll(focusableQueryString)) || []),
|
|
441
558
|
];
|
|
559
|
+
const selectModalEl = lastOverlay.querySelector(ION_SELECT_MODAL_SELECTOR);
|
|
560
|
+
const isSheetModal = lastOverlay.classList.contains('modal-sheet');
|
|
561
|
+
/**
|
|
562
|
+
* Some sheet modal content, including ion-select-modal,
|
|
563
|
+
* renders option containers as `ion-item.select-interface-option`.
|
|
564
|
+
* These can match focusable selectors in some builds but
|
|
565
|
+
* are not intended tab stops. Keep only true interactive
|
|
566
|
+
* controls so Tab can move from options to header
|
|
567
|
+
* controls/handle.
|
|
568
|
+
*/
|
|
569
|
+
if (selectModalEl) {
|
|
570
|
+
allFocusable = allFocusable.filter((el) => !el.matches('ion-item.select-interface-option'));
|
|
571
|
+
}
|
|
572
|
+
if (isSheetModal) {
|
|
573
|
+
allFocusable = sortSheetModalFocusables(lastOverlay, allFocusable);
|
|
574
|
+
}
|
|
442
575
|
if (allFocusable.length === 0) {
|
|
443
576
|
ev.preventDefault();
|
|
444
577
|
return;
|
|
445
578
|
}
|
|
446
579
|
// Find current element's index (accounting for shadow DOM)
|
|
447
|
-
|
|
580
|
+
let currentIndex = activeElement
|
|
448
581
|
? allFocusable.findIndex((el) => {
|
|
449
582
|
var _a;
|
|
450
583
|
if (el === activeElement)
|
|
@@ -455,6 +588,31 @@ const connectListeners = (doc) => {
|
|
|
455
588
|
return rootNode instanceof ShadowRoot && rootNode.host === el;
|
|
456
589
|
})
|
|
457
590
|
: -1;
|
|
591
|
+
/**
|
|
592
|
+
* Radio/checkbox groups can move focus onto an option with
|
|
593
|
+
* `tabIndex=-1`, while another option still has `tabIndex=0`
|
|
594
|
+
* in the list. `findIndex` then yields -1 and Tab incorrectly
|
|
595
|
+
* wraps to `allFocusable[0]`.
|
|
596
|
+
* Treat focus on any option control inside the sheet modal
|
|
597
|
+
* as the same trap slot as the listed tabbable option
|
|
598
|
+
* (`tabIndex >= 0`) so Tab goes handle → Cancel, not back
|
|
599
|
+
* to the first radio.
|
|
600
|
+
*/
|
|
601
|
+
if (currentIndex < 0 && isSheetModal && activeElement) {
|
|
602
|
+
const optionHost = getOptionControlHost(activeElement);
|
|
603
|
+
if (optionHost && lastOverlay.contains(optionHost)) {
|
|
604
|
+
const directIndex = allFocusable.indexOf(optionHost);
|
|
605
|
+
if (directIndex >= 0) {
|
|
606
|
+
currentIndex = directIndex;
|
|
607
|
+
}
|
|
608
|
+
else {
|
|
609
|
+
const tabbableOptionIndex = getTabbableOptionControlIndex(allFocusable, lastOverlay);
|
|
610
|
+
if (tabbableOptionIndex >= 0) {
|
|
611
|
+
currentIndex = tabbableOptionIndex;
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
}
|
|
458
616
|
ev.preventDefault();
|
|
459
617
|
// Helper to focus an element, handling shadow DOM properly
|
|
460
618
|
const focusElement = (element) => {
|
|
@@ -468,24 +626,43 @@ const connectListeners = (doc) => {
|
|
|
468
626
|
}
|
|
469
627
|
focusVisibleElement(element);
|
|
470
628
|
};
|
|
629
|
+
let nextIndex;
|
|
471
630
|
if (ev.shiftKey) {
|
|
472
631
|
// Shift+Tab: previous element, wrap to last if at first
|
|
473
632
|
if (currentIndex <= 0) {
|
|
474
|
-
|
|
633
|
+
nextIndex = allFocusable.length - 1;
|
|
475
634
|
}
|
|
476
635
|
else {
|
|
477
|
-
|
|
636
|
+
nextIndex = currentIndex - 1;
|
|
478
637
|
}
|
|
479
638
|
}
|
|
480
639
|
else {
|
|
481
640
|
// Tab: next element, wrap to first if at last
|
|
482
641
|
if (currentIndex < 0 || currentIndex >= allFocusable.length - 1) {
|
|
483
|
-
|
|
642
|
+
nextIndex = 0;
|
|
484
643
|
}
|
|
485
644
|
else {
|
|
486
|
-
|
|
645
|
+
nextIndex = currentIndex + 1;
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
const nextEl = allFocusable[nextIndex];
|
|
649
|
+
const overlayTrap = lastOverlay;
|
|
650
|
+
const tabbableOptionIndex = isSheetModal ? getTabbableOptionControlIndex(allFocusable, lastOverlay) : -1;
|
|
651
|
+
/**
|
|
652
|
+
* The trap list only includes one tabbable option host
|
|
653
|
+
* (`tabIndex >= 0`), usually the checked/first radio.
|
|
654
|
+
* `focusin` tracks the real last-focused option; use it
|
|
655
|
+
* whenever Tab would focus that slot (wrap from Cancel,
|
|
656
|
+
* Shift+Tab from handle, etc.).
|
|
657
|
+
*/
|
|
658
|
+
let focusTarget = nextEl;
|
|
659
|
+
if (isSheetModal && tabbableOptionIndex >= 0 && nextIndex === tabbableOptionIndex) {
|
|
660
|
+
const saved = overlayTrap.trapLastSheetOptionControl;
|
|
661
|
+
if ((saved === null || saved === void 0 ? void 0 : saved.isConnected) && lastOverlay.contains(saved) && saved !== nextEl) {
|
|
662
|
+
focusTarget = saved;
|
|
487
663
|
}
|
|
488
664
|
}
|
|
665
|
+
focusElement(focusTarget);
|
|
489
666
|
}, true);
|
|
490
667
|
// handle back-button click
|
|
491
668
|
doc.addEventListener('ionBackButton', (ev) => {
|
package/dist/ionic/index.esm.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
/*!
|
|
2
2
|
* (C) Ionic http://ionicframework.com - MIT License
|
|
3
3
|
*/
|
|
4
|
-
export{c as createAnimation}from"./p-Cb-0O4h8.js";export{a as LIFECYCLE_DID_ENTER,c as LIFECYCLE_DID_LEAVE,L as LIFECYCLE_WILL_ENTER,b as LIFECYCLE_WILL_LEAVE,d as LIFECYCLE_WILL_UNLOAD,g as getIonPageElement}from"./p-BsfuYVMP.js";export{iosTransitionAnimation}from"./p-8uDL7fql.js";export{mdTransitionAnimation}from"./p-CIk5QtPm.js";export{g as getTimeGivenProgression}from"./p-hHmYLOfE.js";export{createGesture}from"./p-Cl0B-RWe.js";export{g as getPlatforms,i as initialize,a as isPlatform}from"./p-CBV-BGvD.js";export{c as componentOnReady}from"./p-CHE1xWbg.js";export{L as LogLevel}from"./p-Omi_TcwW.js";export{I as IonicSafeString}from"./p-CWJdc8f_.js";export{g as getMode,s as setupConfig}from"./p-BwKpO3Is.js";export{o as openURL}from"./p-DaJxRxSQ.js";export{m as menuController}from"./p-C5zxLmJ_.js";export{b as actionSheetController,a as alertController,l as loadingController,m as modalController,p as pickerController,c as popoverController,t as toastController}from"./p-
|
|
4
|
+
export{c as createAnimation}from"./p-Cb-0O4h8.js";export{a as LIFECYCLE_DID_ENTER,c as LIFECYCLE_DID_LEAVE,L as LIFECYCLE_WILL_ENTER,b as LIFECYCLE_WILL_LEAVE,d as LIFECYCLE_WILL_UNLOAD,g as getIonPageElement}from"./p-BsfuYVMP.js";export{iosTransitionAnimation}from"./p-8uDL7fql.js";export{mdTransitionAnimation}from"./p-CIk5QtPm.js";export{g as getTimeGivenProgression}from"./p-hHmYLOfE.js";export{createGesture}from"./p-Cl0B-RWe.js";export{g as getPlatforms,i as initialize,a as isPlatform}from"./p-CBV-BGvD.js";export{c as componentOnReady}from"./p-CHE1xWbg.js";export{L as LogLevel}from"./p-Omi_TcwW.js";export{I as IonicSafeString}from"./p-CWJdc8f_.js";export{g as getMode,s as setupConfig}from"./p-BwKpO3Is.js";export{o as openURL}from"./p-DaJxRxSQ.js";export{m as menuController}from"./p-C5zxLmJ_.js";export{b as actionSheetController,a as alertController,l as loadingController,m as modalController,p as pickerController,c as popoverController,t as toastController}from"./p-DdyNaGpi.js";import"./p-BTEOs1at.js";import"./p-vXpMhGrs.js";import"./p-FvDKM4Ax.js";const e=e=>{const{swiper:o,extendParams:s}=e,t={effect:void 0,direction:"horizontal",initialSlide:0,loop:!1,parallax:!1,slidesPerView:1,spaceBetween:0,speed:300,slidesPerColumn:1,slidesPerColumnFill:"column",slidesPerGroup:1,centeredSlides:!1,slidesOffsetBefore:0,slidesOffsetAfter:0,touchEventsTarget:"container",freeMode:!1,freeModeMomentum:!0,freeModeMomentumRatio:1,freeModeMomentumBounce:!0,freeModeMomentumBounceRatio:1,freeModeMomentumVelocityRatio:1,freeModeSticky:!1,freeModeMinimumVelocity:.02,autoHeight:!1,setWrapperSize:!1,zoom:{maxRatio:3,minRatio:1,toggle:!1},touchRatio:1,touchAngle:45,simulateTouch:!0,touchStartPreventDefault:!1,shortSwipes:!0,longSwipes:!0,longSwipesRatio:.5,longSwipesMs:300,followFinger:!0,threshold:0,touchMoveStopPropagation:!0,touchReleaseOnEdges:!1,iOSEdgeSwipeDetection:!1,iOSEdgeSwipeThreshold:20,resistance:!0,resistanceRatio:.85,watchSlidesProgress:!1,watchSlidesVisibility:!1,preventClicks:!0,preventClicksPropagation:!0,slideToClickedSlide:!1,loopAdditionalSlides:0,noSwiping:!0,runCallbacksOnInit:!0,coverflowEffect:{rotate:50,stretch:0,depth:100,modifier:1,slideShadows:!0},flipEffect:{slideShadows:!0,limitRotation:!0},cubeEffect:{slideShadows:!0,shadow:!0,shadowOffset:20,shadowScale:.94},fadeEffect:{crossFade:!1},a11y:{prevSlideMessage:"Previous slide",nextSlideMessage:"Next slide",firstSlideMessage:"This is the first slide",lastSlideMessage:"This is the last slide"}};o.pagination&&(t.pagination={type:"bullets",clickable:!1,hideOnClick:!1}),o.scrollbar&&(t.scrollbar={hide:!0}),s(t)};export{e as IonicSlides}
|