@capgo/capacitor-sheets 8.1.0 → 8.2.2
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/README.md +16 -3
- package/dist/angular/index.js +253 -46
- package/dist/angular/index.js.map +1 -1
- package/dist/angular/index.mjs +253 -46
- package/dist/angular/index.mjs.map +1 -1
- package/dist/{chunk-75SRJO4V.mjs → chunk-VT3FZ2IC.mjs} +254 -47
- package/dist/chunk-VT3FZ2IC.mjs.map +1 -0
- package/dist/{components-6FNKBOX7.mjs → components-Y762NURC.mjs} +2 -2
- package/dist/index.d.mts +25 -1
- package/dist/index.d.ts +25 -1
- package/dist/index.js +254 -47
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2 -2
- package/dist/react/index.js +253 -46
- package/dist/react/index.js.map +1 -1
- package/dist/react/index.mjs +253 -46
- package/dist/react/index.mjs.map +1 -1
- package/dist/solid/index.js +253 -46
- package/dist/solid/index.js.map +1 -1
- package/dist/solid/index.mjs +253 -46
- package/dist/solid/index.mjs.map +1 -1
- package/dist/svelte/index.js +253 -46
- package/dist/svelte/index.js.map +1 -1
- package/dist/svelte/index.mjs +253 -46
- package/dist/svelte/index.mjs.map +1 -1
- package/dist/vue/index.js +253 -46
- package/dist/vue/index.js.map +1 -1
- package/dist/vue/index.mjs +253 -46
- package/dist/vue/index.mjs.map +1 -1
- package/package.json +20 -20
- package/dist/chunk-75SRJO4V.mjs.map +0 -1
- /package/dist/{components-6FNKBOX7.mjs.map → components-Y762NURC.mjs.map} +0 -0
package/README.md
CHANGED
|
@@ -1,19 +1,32 @@
|
|
|
1
1
|
# @capgo/capacitor-sheets
|
|
2
2
|
|
|
3
|
-
<a href="https://capgo.app
|
|
3
|
+
<a href="https://capgo.app/?ref=plugin_sheets">
|
|
4
4
|
<img
|
|
5
5
|
src="https://capgo.app/readme-banner.svg?repo=Cap-go/capacitor-sheets"
|
|
6
|
-
alt="Capgo -
|
|
6
|
+
alt="Capgo - Build Capacitor apps with AI, ship updates instantly"
|
|
7
7
|
/>
|
|
8
8
|
</a>
|
|
9
9
|
|
|
10
|
+
<div align="center">
|
|
11
|
+
<p>
|
|
12
|
+
<b>Capgo</b>: push fixes to your Capacitor users in minutes, build signed iOS and Android apps without a Mac, and
|
|
13
|
+
roll back in one click.
|
|
14
|
+
</p>
|
|
15
|
+
<h2>
|
|
16
|
+
<a href="https://capgo.app/register/?ref=plugin_sheets">➡️ Get started for free</a>
|
|
17
|
+
</h2>
|
|
18
|
+
<p>14-day unlimited free trial. No credit card required</p>
|
|
19
|
+
</div>
|
|
20
|
+
|
|
21
|
+
> 🤖 **Building with an AI coding agent?** Install [Capgo skills](https://capgo.app/skills/?ref=plugin_sheets) so Claude Code, Codex, Cursor, Copilot, or Gemini CLI know how to install and use `@capgo/capacitor-sheets` in your Capacitor app: `npx skills add Cap-go/capgo-skills`. Then ask your agent: _"Add @capgo/capacitor-sheets to my Capacitor app and wire it up."_ [Agent setup guides](https://capgo.app/agents/?ref=plugin_sheets) · [Hosted MCP](https://capgo.app/docs/ai/mcp/?ref=plugin_sheets)
|
|
22
|
+
|
|
10
23
|
Framework-agnostic sheets, drawers, dialogs, scroll helpers, and overlay primitives for Capacitor apps.
|
|
11
24
|
|
|
12
25
|
This package is inspired by the public Silk feature surface, but it is not a wrapper around Silk and does not include Silk source code. It uses platform web APIs and custom elements so the same primitives work in React, Vue, Angular, Svelte, Solid, or plain TypeScript.
|
|
13
26
|
|
|
14
27
|
## Usecase Demos
|
|
15
28
|
|
|
16
|
-
Each usecase has its own animated WebP demo. These match the public Silk-style example set: long sheets, detents, sidebars, bottom/top sheets, keyboard-aware sheets, toasts, detached sheets, full pages, stacking, depth, parallax, lightboxes, persistent detents, and cards
|
|
29
|
+
Each usecase has its own animated WebP demo. These match the public Silk-style example set: long sheets, detents, sidebars, bottom/top sheets, keyboard-aware sheets, toasts, detached sheets, full pages, stacking, depth, parallax, lightboxes, persistent detents, and cards..
|
|
17
30
|
|
|
18
31
|
<table>
|
|
19
32
|
<tr>
|
package/dist/angular/index.js
CHANGED
|
@@ -529,6 +529,9 @@ function releaseThemeColorDimmer(documentRef) {
|
|
|
529
529
|
}
|
|
530
530
|
|
|
531
531
|
// src/core/sheet-controller.ts
|
|
532
|
+
var inertDepth = /* @__PURE__ */ new WeakMap();
|
|
533
|
+
var inertOriginal = /* @__PURE__ */ new WeakMap();
|
|
534
|
+
var inertHolders = /* @__PURE__ */ new WeakMap();
|
|
532
535
|
var defaultOptions = {
|
|
533
536
|
contentPlacement: "bottom",
|
|
534
537
|
sheetRole: "dialog",
|
|
@@ -713,24 +716,32 @@ var SheetController = class {
|
|
|
713
716
|
pointerTravel = null;
|
|
714
717
|
connected = false;
|
|
715
718
|
lockedScroll = false;
|
|
716
|
-
|
|
719
|
+
inertHeldElements = /* @__PURE__ */ new Set();
|
|
720
|
+
remeasureFrame = null;
|
|
721
|
+
activeMotion = null;
|
|
722
|
+
pendingSettle = null;
|
|
723
|
+
/** Entering completion deferred by a drag that interrupted present(); runs once the sheet settles. */
|
|
724
|
+
deferredEnteringComplete = null;
|
|
725
|
+
/** Resolves the in-flight present() after entering lifecycle completes or is abandoned. */
|
|
726
|
+
settlePresentPromise = null;
|
|
717
727
|
previousFocus = null;
|
|
718
728
|
hasThemeDimmer = false;
|
|
719
729
|
stackId = null;
|
|
720
730
|
documentListenersAttached = false;
|
|
721
731
|
viewListenersElement = null;
|
|
722
732
|
visualViewportListenersAttached = false;
|
|
723
|
-
handleVisualViewportResize = () => {
|
|
733
|
+
handleVisualViewportResize = (event) => {
|
|
724
734
|
const view = this.parts.view;
|
|
725
735
|
const visualViewport = this.root.ownerDocument.defaultView?.visualViewport;
|
|
726
736
|
if (!view) return;
|
|
737
|
+
const viewportChanged = event !== void 0;
|
|
727
738
|
if (!visualViewport || this.options.nativeFocusScrollPrevention === false) {
|
|
728
|
-
this.setKeyboardOffset("0em");
|
|
739
|
+
this.setKeyboardOffset("0em", viewportChanged);
|
|
729
740
|
return;
|
|
730
741
|
}
|
|
731
742
|
const layoutHeight = this.root.ownerDocument.documentElement.clientHeight;
|
|
732
743
|
const keyboardOffset = Math.max(0, layoutHeight - visualViewport.height - visualViewport.offsetTop);
|
|
733
|
-
this.setKeyboardOffset(`${toEm(view, keyboardOffset)}em
|
|
744
|
+
this.setKeyboardOffset(`${toEm(view, keyboardOffset)}em`, viewportChanged);
|
|
734
745
|
};
|
|
735
746
|
handleFocusIn = (event) => {
|
|
736
747
|
if (!this.presented || this.options.nativeFocusScrollPrevention === false) return;
|
|
@@ -761,10 +772,18 @@ var SheetController = class {
|
|
|
761
772
|
if (!this.presented || this.options.swipe === false || this.options.contentPlacement === "center") return;
|
|
762
773
|
if (!(event.target instanceof Element)) return;
|
|
763
774
|
if (!this.parts.content?.contains(event.target) && event.target !== this.parts.backdrop) return;
|
|
775
|
+
if (this.pointerTravel && !event.isPrimary) return;
|
|
764
776
|
if (this.options.nativeEdgeSwipePrevention !== false && this.isNativeEdgePointer(event)) {
|
|
765
777
|
event.preventDefault();
|
|
766
778
|
}
|
|
779
|
+
this.syncOffsetFromRenderedPosition();
|
|
780
|
+
const interruptedMotion = this.activeMotion ? this.pendingSettle : null;
|
|
781
|
+
this.pendingSettle = null;
|
|
782
|
+
this.cancelActiveMotion();
|
|
783
|
+
this.applyOffset(this.currentOffsetPx, this.status);
|
|
767
784
|
this.remeasure();
|
|
785
|
+
const axis = isVerticalTrack(this.activeTrack) ? "y" : "x";
|
|
786
|
+
const startPos = axis === "y" ? event.clientY : event.clientX;
|
|
768
787
|
this.pointerTravel = {
|
|
769
788
|
id: event.pointerId,
|
|
770
789
|
startOffsetPx: this.currentOffsetPx,
|
|
@@ -774,7 +793,9 @@ var SheetController = class {
|
|
|
774
793
|
lastY: event.clientY,
|
|
775
794
|
lastTime: performance.now(),
|
|
776
795
|
velocity: 0,
|
|
777
|
-
dragging: false
|
|
796
|
+
dragging: false,
|
|
797
|
+
samples: [{ t: performance.now(), pos: startPos }],
|
|
798
|
+
interruptedMotion
|
|
778
799
|
};
|
|
779
800
|
};
|
|
780
801
|
handlePointerMove = (event) => {
|
|
@@ -802,6 +823,8 @@ var SheetController = class {
|
|
|
802
823
|
travel.lastX = event.clientX;
|
|
803
824
|
travel.lastY = event.clientY;
|
|
804
825
|
travel.lastTime = now;
|
|
826
|
+
travel.samples.push({ t: now, pos: current });
|
|
827
|
+
if (travel.samples.length > 24) travel.samples.shift();
|
|
805
828
|
const nextOffset = this.limitOffset(travel.startOffsetPx + delta);
|
|
806
829
|
this.applyOffset(nextOffset, "dragging");
|
|
807
830
|
};
|
|
@@ -813,9 +836,17 @@ var SheetController = class {
|
|
|
813
836
|
currentTarget.releasePointerCapture(event.pointerId);
|
|
814
837
|
}
|
|
815
838
|
this.pointerTravel = null;
|
|
816
|
-
if (!travel.dragging)
|
|
817
|
-
|
|
839
|
+
if (!travel.dragging) {
|
|
840
|
+
if (travel.interruptedMotion && this.presented) {
|
|
841
|
+
void this.runSettleMotion(travel.interruptedMotion);
|
|
842
|
+
}
|
|
843
|
+
return;
|
|
844
|
+
}
|
|
845
|
+
const nearest = this.nearestDetentForOffset(this.currentOffsetPx, this.releaseVelocity(travel));
|
|
818
846
|
dispatch(this.root, "cap-sheet-drag-end", this.getTravelEvent());
|
|
847
|
+
if (travel.interruptedMotion?.status === "entering") {
|
|
848
|
+
this.deferredEnteringComplete = travel.interruptedMotion.complete;
|
|
849
|
+
}
|
|
819
850
|
if (nearest === 0 && this.options.swipeDismissal !== false) {
|
|
820
851
|
void this.dismiss({ source: "gesture" });
|
|
821
852
|
return;
|
|
@@ -900,6 +931,8 @@ var SheetController = class {
|
|
|
900
931
|
this.remeasure();
|
|
901
932
|
this.applyOffset(this.detentOffsetsPx[0] || this.hiddenOffsetPx, this.status);
|
|
902
933
|
this.updateDomState(false);
|
|
934
|
+
} else if (this.presented && affectsDismissedOffset(options)) {
|
|
935
|
+
this.scheduleRemeasure();
|
|
903
936
|
}
|
|
904
937
|
this.registerStack();
|
|
905
938
|
}
|
|
@@ -954,6 +987,7 @@ var SheetController = class {
|
|
|
954
987
|
}
|
|
955
988
|
this.previousFocus = this.root.ownerDocument.activeElement;
|
|
956
989
|
this.presented = true;
|
|
990
|
+
this.abandonDeferredEntering();
|
|
957
991
|
this.activeDetent = clamp(options.detent ?? this.resolveInitialDetent(), 1, this.detentOffsetsPx.length - 1);
|
|
958
992
|
this.updateDetentState();
|
|
959
993
|
this.updateDomState(true);
|
|
@@ -962,15 +996,33 @@ var SheetController = class {
|
|
|
962
996
|
this.retainThemeDimmer();
|
|
963
997
|
this.setStatus("entering");
|
|
964
998
|
dispatch(this.root, "cap-sheet-present", this.getTravelEvent());
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
999
|
+
const source = options.source || "programmatic";
|
|
1000
|
+
let resolvePresent;
|
|
1001
|
+
const presentLifecycleSettled = new Promise((resolve) => {
|
|
1002
|
+
resolvePresent = resolve;
|
|
968
1003
|
});
|
|
969
|
-
this.
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
1004
|
+
this.settlePresentPromise = () => {
|
|
1005
|
+
resolvePresent();
|
|
1006
|
+
};
|
|
1007
|
+
const complete = () => {
|
|
1008
|
+
this.setStatus("idle");
|
|
1009
|
+
this.focusInitialElement();
|
|
1010
|
+
this.emitPresentedChange(true, source);
|
|
1011
|
+
this.emitActiveDetentChange(this.activeDetent, 0);
|
|
1012
|
+
this.updateStack();
|
|
1013
|
+
this.releasePresentAwait();
|
|
1014
|
+
};
|
|
1015
|
+
const finished = await this.runSettleMotion({
|
|
1016
|
+
status: "entering",
|
|
1017
|
+
animation: {
|
|
1018
|
+
...this.options.enteringAnimationSettings || {},
|
|
1019
|
+
...options.animation || {}
|
|
1020
|
+
},
|
|
1021
|
+
complete
|
|
1022
|
+
});
|
|
1023
|
+
if (!finished) {
|
|
1024
|
+
await presentLifecycleSettled;
|
|
1025
|
+
}
|
|
974
1026
|
}
|
|
975
1027
|
/** Dismiss the sheet. */
|
|
976
1028
|
async dismiss(options = {}) {
|
|
@@ -979,6 +1031,8 @@ var SheetController = class {
|
|
|
979
1031
|
const previous = this.activeDetent;
|
|
980
1032
|
this.presented = false;
|
|
981
1033
|
this.activeDetent = 0;
|
|
1034
|
+
this.pendingSettle = null;
|
|
1035
|
+
this.abandonDeferredEntering();
|
|
982
1036
|
this.updateDetentState();
|
|
983
1037
|
this.setStatus("exiting");
|
|
984
1038
|
dispatch(this.root, "cap-sheet-dismiss", this.getTravelEvent());
|
|
@@ -1019,15 +1073,49 @@ var SheetController = class {
|
|
|
1019
1073
|
const previous = this.activeDetent;
|
|
1020
1074
|
this.activeDetent = target;
|
|
1021
1075
|
this.updateDetentState();
|
|
1022
|
-
this.
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1076
|
+
await this.runSettleMotion({
|
|
1077
|
+
status: "settling",
|
|
1078
|
+
animation: {
|
|
1079
|
+
...this.options.steppingAnimationSettings || {},
|
|
1080
|
+
...options.animation || {}
|
|
1081
|
+
},
|
|
1082
|
+
complete: () => {
|
|
1083
|
+
const enteringComplete = this.deferredEnteringComplete;
|
|
1084
|
+
if (enteringComplete) {
|
|
1085
|
+
this.deferredEnteringComplete = null;
|
|
1086
|
+
enteringComplete();
|
|
1087
|
+
return;
|
|
1088
|
+
}
|
|
1089
|
+
this.setStatus("idle");
|
|
1090
|
+
if (previous !== target) {
|
|
1091
|
+
this.emitActiveDetentChange(target, previous);
|
|
1092
|
+
}
|
|
1093
|
+
}
|
|
1026
1094
|
});
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1095
|
+
}
|
|
1096
|
+
/**
|
|
1097
|
+
* Animate to the active detent and run the completion once the motion finishes.
|
|
1098
|
+
* When the motion is cancelled by a pointerdown, the settle stays pending so a tap
|
|
1099
|
+
* that never becomes a drag can resume it.
|
|
1100
|
+
*/
|
|
1101
|
+
releasePresentAwait() {
|
|
1102
|
+
if (!this.settlePresentPromise) return;
|
|
1103
|
+
const settle = this.settlePresentPromise;
|
|
1104
|
+
this.settlePresentPromise = null;
|
|
1105
|
+
settle();
|
|
1106
|
+
}
|
|
1107
|
+
abandonDeferredEntering() {
|
|
1108
|
+
this.deferredEnteringComplete = null;
|
|
1109
|
+
this.releasePresentAwait();
|
|
1110
|
+
}
|
|
1111
|
+
async runSettleMotion(motion) {
|
|
1112
|
+
this.setStatus(motion.status);
|
|
1113
|
+
this.pendingSettle = motion;
|
|
1114
|
+
const finished = await this.animateTo(this.detentOffsetsPx[this.activeDetent] || 0, motion.animation);
|
|
1115
|
+
if (!finished) return false;
|
|
1116
|
+
if (this.pendingSettle === motion) this.pendingSettle = null;
|
|
1117
|
+
motion.complete();
|
|
1118
|
+
return true;
|
|
1031
1119
|
}
|
|
1032
1120
|
/** Step up or down one detent. */
|
|
1033
1121
|
async step(direction = "up", options = {}) {
|
|
@@ -1159,7 +1247,7 @@ var SheetController = class {
|
|
|
1159
1247
|
const resolved = resolveAnimation(settings);
|
|
1160
1248
|
if (!content || shouldSkipMotion(resolved.skip)) {
|
|
1161
1249
|
this.applyOffset(targetOffsetPx, "idle");
|
|
1162
|
-
return;
|
|
1250
|
+
return true;
|
|
1163
1251
|
}
|
|
1164
1252
|
const startOffset = this.currentOffsetPx;
|
|
1165
1253
|
const fromProgress = this.getProgressForOffset(startOffset);
|
|
@@ -1184,7 +1272,18 @@ var SheetController = class {
|
|
|
1184
1272
|
);
|
|
1185
1273
|
const started = performance.now();
|
|
1186
1274
|
let frame;
|
|
1275
|
+
let cancelled = false;
|
|
1276
|
+
const cancelMotion = () => {
|
|
1277
|
+
if (cancelled) return;
|
|
1278
|
+
cancelled = true;
|
|
1279
|
+
cancelAnimationFrame(frame);
|
|
1280
|
+
contentAnimation?.cancel();
|
|
1281
|
+
backdropAnimation?.cancel();
|
|
1282
|
+
this.activeMotion = null;
|
|
1283
|
+
};
|
|
1284
|
+
this.activeMotion = { cancel: cancelMotion };
|
|
1187
1285
|
const tick = () => {
|
|
1286
|
+
if (cancelled) return;
|
|
1188
1287
|
const progress = duration === 0 ? 1 : clamp((performance.now() - started) / duration, 0, 1);
|
|
1189
1288
|
const offset = startOffset + (targetOffsetPx - startOffset) * progress;
|
|
1190
1289
|
this.currentOffsetPx = offset;
|
|
@@ -1198,10 +1297,13 @@ var SheetController = class {
|
|
|
1198
1297
|
contentAnimation?.finished,
|
|
1199
1298
|
backdropAnimation ? backdropAnimation.finished : Promise.resolve()
|
|
1200
1299
|
]);
|
|
1300
|
+
if (cancelled) return false;
|
|
1201
1301
|
cancelAnimationFrame(frame);
|
|
1202
1302
|
contentAnimation?.cancel();
|
|
1203
1303
|
backdropAnimation?.cancel();
|
|
1304
|
+
this.activeMotion = null;
|
|
1204
1305
|
this.applyOffset(targetOffsetPx, "idle");
|
|
1306
|
+
return true;
|
|
1205
1307
|
}
|
|
1206
1308
|
getProgressForOffset(offsetPx) {
|
|
1207
1309
|
if (this.options.contentPlacement === "center") {
|
|
@@ -1425,47 +1527,152 @@ var SheetController = class {
|
|
|
1425
1527
|
documentLockSnapshot.delete(doc);
|
|
1426
1528
|
this.lockedScroll = false;
|
|
1427
1529
|
}
|
|
1428
|
-
setKeyboardOffset(value) {
|
|
1530
|
+
setKeyboardOffset(value, viewportChanged = false) {
|
|
1429
1531
|
const view = this.parts.view;
|
|
1430
1532
|
if (!view) return;
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1533
|
+
const changed = view.style.getPropertyValue("--cap-sheet-keyboard-offset") !== value;
|
|
1534
|
+
if (changed) view.style.setProperty("--cap-sheet-keyboard-offset", value);
|
|
1535
|
+
if (changed || viewportChanged) this.scheduleRemeasure();
|
|
1536
|
+
}
|
|
1537
|
+
scheduleRemeasure() {
|
|
1434
1538
|
if (!this.presented) return;
|
|
1435
|
-
|
|
1539
|
+
if (this.remeasureFrame !== null) return;
|
|
1540
|
+
this.remeasureFrame = requestAnimationFrame(() => {
|
|
1541
|
+
this.remeasureFrame = null;
|
|
1436
1542
|
if (!this.presented) return;
|
|
1437
1543
|
this.remeasure();
|
|
1544
|
+
if (this.status === "dragging") return;
|
|
1438
1545
|
this.applyOffset(this.detentOffsetsPx[this.activeDetent] || 0, this.status);
|
|
1439
1546
|
});
|
|
1440
1547
|
}
|
|
1548
|
+
cancelActiveMotion() {
|
|
1549
|
+
this.activeMotion?.cancel();
|
|
1550
|
+
this.activeMotion = null;
|
|
1551
|
+
}
|
|
1552
|
+
syncOffsetFromRenderedPosition() {
|
|
1553
|
+
const content = this.parts.content;
|
|
1554
|
+
if (!content || this.options.contentPlacement === "center") return;
|
|
1555
|
+
const offsetPx = this.readOffsetPxFromTransform(content);
|
|
1556
|
+
if (offsetPx === null) return;
|
|
1557
|
+
this.currentOffsetPx = offsetPx;
|
|
1558
|
+
}
|
|
1559
|
+
readOffsetPxFromTransform(content) {
|
|
1560
|
+
const axis = isVerticalTrack(this.activeTrack) ? "y" : "x";
|
|
1561
|
+
const computed = this.root.ownerDocument.defaultView?.getComputedStyle(content).transform;
|
|
1562
|
+
const inline = content.style.transform;
|
|
1563
|
+
const transform = computed && computed !== "none" ? computed : inline && inline !== "none" ? inline : "";
|
|
1564
|
+
if (!transform) return this.currentOffsetPx;
|
|
1565
|
+
const translateMatch = transform.match(/translate3d\(\s*([^,]+)\s*,\s*([^,]+)\s*,/);
|
|
1566
|
+
if (translateMatch) {
|
|
1567
|
+
const raw = axis === "y" ? translateMatch[2] : translateMatch[1];
|
|
1568
|
+
const emMatch = raw.trim().match(/^(-?[\d.]+)em$/);
|
|
1569
|
+
if (emMatch) return Number.parseFloat(emMatch[1]) * getEmPx(content);
|
|
1570
|
+
const pxMatch = raw.trim().match(/^(-?[\d.]+)px$/);
|
|
1571
|
+
if (pxMatch) return Number.parseFloat(pxMatch[1]);
|
|
1572
|
+
}
|
|
1573
|
+
const matrixMatch = transform.match(/^matrix\(([^)]+)\)$/);
|
|
1574
|
+
if (matrixMatch) {
|
|
1575
|
+
const values = matrixMatch[1].split(",").map((part) => Number.parseFloat(part.trim()));
|
|
1576
|
+
const translation = axis === "y" ? values[5] : values[4];
|
|
1577
|
+
if (Number.isFinite(translation)) return translation;
|
|
1578
|
+
}
|
|
1579
|
+
const matrix3dMatch = transform.match(/^matrix3d\(([^)]+)\)$/);
|
|
1580
|
+
if (matrix3dMatch) {
|
|
1581
|
+
const values = matrix3dMatch[1].split(",").map((part) => Number.parseFloat(part.trim()));
|
|
1582
|
+
const translation = axis === "y" ? values[13] : values[12];
|
|
1583
|
+
if (Number.isFinite(translation)) return translation;
|
|
1584
|
+
}
|
|
1585
|
+
return null;
|
|
1586
|
+
}
|
|
1587
|
+
releaseVelocity(travel) {
|
|
1588
|
+
const windowMs = 100;
|
|
1589
|
+
const now = performance.now();
|
|
1590
|
+
const samples = travel.samples.filter((sample) => now - sample.t <= windowMs);
|
|
1591
|
+
if (samples.length < 2) return 0;
|
|
1592
|
+
const first = samples[0];
|
|
1593
|
+
const last = samples[samples.length - 1];
|
|
1594
|
+
const elapsed = Math.max(last.t - first.t, 1);
|
|
1595
|
+
return (last.pos - first.pos) / elapsed * 1e3;
|
|
1596
|
+
}
|
|
1597
|
+
getAllowedOutsideElements() {
|
|
1598
|
+
const allowed = /* @__PURE__ */ new Set();
|
|
1599
|
+
if (this.parts.view) allowed.add(this.parts.view);
|
|
1600
|
+
for (const element of this.parts.islands) allowed.add(element);
|
|
1601
|
+
for (const element of this.parts.externalOverlays) allowed.add(element);
|
|
1602
|
+
return allowed;
|
|
1603
|
+
}
|
|
1604
|
+
applyInertForElement(element, allowed) {
|
|
1605
|
+
const isAllowed = Array.from(allowed).some((candidate) => element === candidate || element.contains(candidate));
|
|
1606
|
+
if (isAllowed) {
|
|
1607
|
+
element.inert = false;
|
|
1608
|
+
element.removeAttribute("aria-hidden");
|
|
1609
|
+
return;
|
|
1610
|
+
}
|
|
1611
|
+
element.inert = true;
|
|
1612
|
+
element.setAttribute("aria-hidden", "true");
|
|
1613
|
+
}
|
|
1441
1614
|
applyInert() {
|
|
1442
1615
|
if (this.options.inertOutside === false || !this.parts.view) return;
|
|
1443
|
-
const
|
|
1444
|
-
const
|
|
1445
|
-
this.
|
|
1616
|
+
const doc = this.root.ownerDocument;
|
|
1617
|
+
const body = doc.body;
|
|
1618
|
+
const allowed = this.getAllowedOutsideElements();
|
|
1619
|
+
this.releaseInertHold();
|
|
1620
|
+
const holders = inertHolders.get(doc) || /* @__PURE__ */ new Set();
|
|
1621
|
+
holders.add(this);
|
|
1622
|
+
inertHolders.set(doc, holders);
|
|
1446
1623
|
for (const child of Array.from(body.children)) {
|
|
1447
1624
|
if (!(child instanceof HTMLElement)) continue;
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
child.inert = false;
|
|
1452
|
-
child.removeAttribute("aria-hidden");
|
|
1453
|
-
continue;
|
|
1625
|
+
const depth = inertDepth.get(child) ?? 0;
|
|
1626
|
+
if (depth === 0) {
|
|
1627
|
+
inertOriginal.set(child, { inert: child.inert, ariaHidden: child.getAttribute("aria-hidden") });
|
|
1454
1628
|
}
|
|
1455
|
-
child
|
|
1456
|
-
|
|
1629
|
+
inertDepth.set(child, depth + 1);
|
|
1630
|
+
this.inertHeldElements.add(child);
|
|
1631
|
+
this.applyInertForElement(child, allowed);
|
|
1457
1632
|
}
|
|
1458
1633
|
}
|
|
1459
1634
|
clearInert() {
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1635
|
+
this.releaseInertHold();
|
|
1636
|
+
}
|
|
1637
|
+
releaseInertHold() {
|
|
1638
|
+
if (this.inertHeldElements.size === 0) return;
|
|
1639
|
+
const doc = this.root.ownerDocument;
|
|
1640
|
+
const holders = inertHolders.get(doc);
|
|
1641
|
+
holders?.delete(this);
|
|
1642
|
+
if (holders?.size === 0) inertHolders.delete(doc);
|
|
1643
|
+
for (const element of this.inertHeldElements) {
|
|
1644
|
+
const depth = Math.max((inertDepth.get(element) ?? 1) - 1, 0);
|
|
1645
|
+
if (depth === 0) {
|
|
1646
|
+
inertDepth.delete(element);
|
|
1647
|
+
const snapshot = inertOriginal.get(element);
|
|
1648
|
+
if (snapshot) {
|
|
1649
|
+
element.inert = snapshot.inert;
|
|
1650
|
+
if (snapshot.ariaHidden === null) {
|
|
1651
|
+
element.removeAttribute("aria-hidden");
|
|
1652
|
+
} else {
|
|
1653
|
+
element.setAttribute("aria-hidden", snapshot.ariaHidden);
|
|
1654
|
+
}
|
|
1655
|
+
inertOriginal.delete(element);
|
|
1656
|
+
}
|
|
1464
1657
|
} else {
|
|
1465
|
-
|
|
1658
|
+
inertDepth.set(element, depth);
|
|
1466
1659
|
}
|
|
1467
1660
|
}
|
|
1468
|
-
this.
|
|
1661
|
+
this.inertHeldElements.clear();
|
|
1662
|
+
this.reapplyDocumentInert(doc);
|
|
1663
|
+
}
|
|
1664
|
+
reapplyDocumentInert(doc) {
|
|
1665
|
+
const holders = inertHolders.get(doc);
|
|
1666
|
+
if (!holders?.size) return;
|
|
1667
|
+
const top = Array.from(holders).filter((controller) => controller.presented && controller.options.inertOutside !== false).sort((left, right) => right.getStackZIndex() - left.getStackZIndex())[0];
|
|
1668
|
+
if (!top) return;
|
|
1669
|
+
const allowed = top.getAllowedOutsideElements();
|
|
1670
|
+
const body = doc.body;
|
|
1671
|
+
for (const child of Array.from(body.children)) {
|
|
1672
|
+
if (!(child instanceof HTMLElement)) continue;
|
|
1673
|
+
if ((inertDepth.get(child) ?? 0) === 0) continue;
|
|
1674
|
+
top.applyInertForElement(child, allowed);
|
|
1675
|
+
}
|
|
1469
1676
|
}
|
|
1470
1677
|
retainThemeDimmer() {
|
|
1471
1678
|
if (this.hasThemeDimmer || this.options.themeColorDimming !== "auto") return;
|