react-native-nitro-modal 0.1.5 → 0.3.0-rc
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 +65 -11
- package/android/src/main/java/com/margelo/nitro/nitromodal/BottomSheetPresenter.kt +335 -34
- package/android/src/main/java/com/margelo/nitro/nitromodal/HybridNitroModal.kt +63 -22
- package/android/src/main/java/com/margelo/nitro/nitromodal/ModalConfig.kt +31 -1
- package/android/src/main/java/com/margelo/nitro/nitromodal/ModalContentRoot.kt +48 -5
- package/android/src/main/java/com/margelo/nitro/nitromodal/ModalPresenter.kt +63 -4
- package/android/src/main/java/com/margelo/nitro/nitromodal/NitroModalHostView.kt +68 -8
- package/ios/HybridNitroModal.swift +111 -20
- package/ios/ModalConfig.swift +44 -2
- package/ios/NitroModalHostView.swift +73 -8
- package/ios/SheetView.swift +575 -0
- package/ios/SheetViewController.swift +19 -450
- package/lib/module/NitroModal.js +39 -7
- package/lib/module/NitroModal.js.map +1 -1
- package/lib/module/NitroModalView.js +4 -3
- package/lib/module/NitroModalView.js.map +1 -1
- package/lib/module/NitroModalView.native.js +3 -0
- package/lib/module/NitroModalView.native.js.map +1 -1
- package/lib/module/NitroModalView.web.js +159 -0
- package/lib/module/NitroModalView.web.js.map +1 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/web/AnimatedValue.js +126 -0
- package/lib/module/web/AnimatedValue.js.map +1 -0
- package/lib/module/web/ModalConfig.js +30 -0
- package/lib/module/web/ModalConfig.js.map +1 -0
- package/lib/module/web/ModalController.js +306 -0
- package/lib/module/web/ModalController.js.map +1 -0
- package/lib/module/web/ModalPresenter.js +280 -0
- package/lib/module/web/ModalPresenter.js.map +1 -0
- package/lib/module/web/PopupPresenter.js +117 -0
- package/lib/module/web/PopupPresenter.js.map +1 -0
- package/lib/module/web/SheetPresenter.js +494 -0
- package/lib/module/web/SheetPresenter.js.map +1 -0
- package/lib/module/web/dom.js +138 -0
- package/lib/module/web/dom.js.map +1 -0
- package/lib/typescript/src/NitroModal.d.ts +35 -4
- package/lib/typescript/src/NitroModal.d.ts.map +1 -1
- package/lib/typescript/src/NitroModal.nitro.d.ts +29 -2
- package/lib/typescript/src/NitroModal.nitro.d.ts.map +1 -1
- package/lib/typescript/src/NitroModalView.d.ts +2 -1
- package/lib/typescript/src/NitroModalView.d.ts.map +1 -1
- package/lib/typescript/src/NitroModalView.native.d.ts +1 -0
- package/lib/typescript/src/NitroModalView.native.d.ts.map +1 -1
- package/lib/typescript/src/NitroModalView.web.d.ts +6 -0
- package/lib/typescript/src/NitroModalView.web.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +2 -2
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/web/AnimatedValue.d.ts +49 -0
- package/lib/typescript/src/web/AnimatedValue.d.ts.map +1 -0
- package/lib/typescript/src/web/ModalConfig.d.ts +30 -0
- package/lib/typescript/src/web/ModalConfig.d.ts.map +1 -0
- package/lib/typescript/src/web/ModalController.d.ts +70 -0
- package/lib/typescript/src/web/ModalController.d.ts.map +1 -0
- package/lib/typescript/src/web/ModalPresenter.d.ts +107 -0
- package/lib/typescript/src/web/ModalPresenter.d.ts.map +1 -0
- package/lib/typescript/src/web/PopupPresenter.d.ts +20 -0
- package/lib/typescript/src/web/PopupPresenter.d.ts.map +1 -0
- package/lib/typescript/src/web/SheetPresenter.d.ts +65 -0
- package/lib/typescript/src/web/SheetPresenter.d.ts.map +1 -0
- package/lib/typescript/src/web/dom.d.ts +42 -0
- package/lib/typescript/src/web/dom.d.ts.map +1 -0
- package/nitrogen/generated/android/c++/JHybridNitroModalSpec.cpp +60 -6
- package/nitrogen/generated/android/c++/JHybridNitroModalSpec.hpp +10 -2
- package/nitrogen/generated/android/c++/JNamedSheetDetent.hpp +64 -0
- package/nitrogen/generated/android/c++/JSheetDetent.cpp +26 -0
- package/nitrogen/generated/android/c++/JSheetDetent.hpp +42 -37
- package/nitrogen/generated/android/c++/views/JHybridNitroModalStateUpdater.cpp +20 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromodal/HybridNitroModalSpec.kt +40 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromodal/NamedSheetDetent.kt +25 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitromodal/SheetDetent.kt +47 -10
- package/nitrogen/generated/android/nitromodal+autolinking.cmake +1 -0
- package/nitrogen/generated/ios/NitroModal-Swift-Cxx-Bridge.hpp +53 -8
- package/nitrogen/generated/ios/NitroModal-Swift-Cxx-Umbrella.hpp +4 -3
- package/nitrogen/generated/ios/c++/HybridNitroModalSpecSwift.hpp +32 -5
- package/nitrogen/generated/ios/c++/views/HybridNitroModalComponent.mm +24 -0
- package/nitrogen/generated/ios/swift/HybridNitroModalSpec.swift +4 -0
- package/nitrogen/generated/ios/swift/HybridNitroModalSpec_cxx.swift +110 -5
- package/nitrogen/generated/ios/swift/NamedSheetDetent.swift +48 -0
- package/nitrogen/generated/ios/swift/SheetDetent.swift +15 -33
- package/nitrogen/generated/shared/c++/HybridNitroModalSpec.cpp +8 -0
- package/nitrogen/generated/shared/c++/HybridNitroModalSpec.hpp +14 -5
- package/nitrogen/generated/shared/c++/{SheetDetent.hpp → NamedSheetDetent.hpp} +17 -17
- package/nitrogen/generated/shared/c++/views/HybridNitroModalComponent.cpp +9 -1
- package/nitrogen/generated/shared/c++/views/HybridNitroModalComponent.hpp +15 -2
- package/nitrogen/generated/shared/json/NitroModalConfig.json +4 -0
- package/package.json +3 -2
- package/src/NitroModal.nitro.ts +30 -2
- package/src/NitroModal.tsx +71 -8
- package/src/NitroModalView.native.tsx +4 -0
- package/src/NitroModalView.tsx +9 -4
- package/src/NitroModalView.web.tsx +180 -0
- package/src/index.tsx +2 -0
- package/src/web/AnimatedValue.ts +193 -0
- package/src/web/ModalConfig.ts +67 -0
- package/src/web/ModalController.ts +338 -0
- package/src/web/ModalPresenter.ts +333 -0
- package/src/web/PopupPresenter.ts +129 -0
- package/src/web/SheetPresenter.ts +647 -0
- package/src/web/dom.ts +171 -0
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/// <reference lib="dom" />
|
|
2
|
+
|
|
3
|
+
import { AnimatedValue, INSTANT, type Motion } from './AnimatedValue';
|
|
4
|
+
import { prefersReducedMotion, type Insets, type Size } from './dom';
|
|
5
|
+
import { ModalPresenter } from './ModalPresenter';
|
|
6
|
+
|
|
7
|
+
const MARGIN = 16;
|
|
8
|
+
const DEFAULT_CORNER_RADIUS = 16;
|
|
9
|
+
const ENTER_SCALE = 0.9;
|
|
10
|
+
|
|
11
|
+
const ENTER: Motion = { type: 'spring', response: 0.3, dampingRatio: 0.82 };
|
|
12
|
+
const EXIT: Motion = { type: 'timing', duration: 200, easing: (t) => t * t };
|
|
13
|
+
|
|
14
|
+
interface Rect extends Size {
|
|
15
|
+
x: number;
|
|
16
|
+
y: number;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/** Area a card may occupy, clear of the safe area and the part of the keyboard above it. */
|
|
20
|
+
function availableRect(
|
|
21
|
+
viewport: Size,
|
|
22
|
+
insets: Insets,
|
|
23
|
+
keyboardHeight: number
|
|
24
|
+
): Rect {
|
|
25
|
+
const covered = Math.max(0, keyboardHeight - insets.bottom);
|
|
26
|
+
return {
|
|
27
|
+
x: insets.left + MARGIN,
|
|
28
|
+
y: insets.top + MARGIN,
|
|
29
|
+
width: Math.max(
|
|
30
|
+
0,
|
|
31
|
+
viewport.width - insets.left - insets.right - 2 * MARGIN
|
|
32
|
+
),
|
|
33
|
+
height: Math.max(
|
|
34
|
+
0,
|
|
35
|
+
viewport.height - insets.top - insets.bottom - 2 * MARGIN - covered
|
|
36
|
+
),
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/** Best guess of the content area before the popup is on screen. */
|
|
41
|
+
export function popupContentArea(viewport: Size, insets: Insets): Size {
|
|
42
|
+
const { width, height } = availableRect(viewport, insets, 0);
|
|
43
|
+
return { width, height };
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** `popup` mode: a centered card over the backdrop with a fade/scale transition. */
|
|
47
|
+
export class PopupPresenter extends ModalPresenter {
|
|
48
|
+
/** 0 hidden, 1 presented. */
|
|
49
|
+
private readonly progress = new AnimatedValue(0, 0.001, (value) =>
|
|
50
|
+
this.render(value)
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
protected didShow() {
|
|
54
|
+
this.layout();
|
|
55
|
+
this.progress.set(0);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
protected animateIn() {
|
|
59
|
+
this.progress.animateTo(1, this.isAnimated ? ENTER : INSTANT, {
|
|
60
|
+
onEnd: () => this.notifyPresented(),
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
protected animateOut(onEnd: () => void) {
|
|
65
|
+
this.progress.animateTo(0, this.isAnimated ? EXIT : INSTANT, { onEnd });
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
protected configDidChange() {
|
|
69
|
+
this.layout();
|
|
70
|
+
this.render(this.progress.value);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
protected viewportDidChange() {
|
|
74
|
+
this.layout();
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
protected contentSizeDidChange() {
|
|
78
|
+
this.layout();
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
protected stopAnimations() {
|
|
82
|
+
this.progress.stop();
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
private get isAnimated(): boolean {
|
|
86
|
+
return this.config.popupAnimation !== 'none' && !prefersReducedMotion();
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
private layout() {
|
|
90
|
+
const { surface, content, grabber } = this.elements!;
|
|
91
|
+
const behavior = this.config.keyboardBehavior;
|
|
92
|
+
const available = availableRect(
|
|
93
|
+
this.viewport,
|
|
94
|
+
this.insets,
|
|
95
|
+
behavior === 'none' ? 0 : this.keyboardHeight
|
|
96
|
+
);
|
|
97
|
+
const width = Math.min(this.contentSize.width, available.width);
|
|
98
|
+
const height = Math.min(this.contentSize.height, available.height);
|
|
99
|
+
Object.assign(surface.style, {
|
|
100
|
+
left: `${available.x + (available.width - width) / 2}px`,
|
|
101
|
+
top: `${available.y + (available.height - height) / 2}px`,
|
|
102
|
+
width: `${width}px`,
|
|
103
|
+
height: `${height}px`,
|
|
104
|
+
borderRadius: `${this.config.cornerRadius ?? DEFAULT_CORNER_RADIUS}px`,
|
|
105
|
+
});
|
|
106
|
+
grabber.style.display = 'none';
|
|
107
|
+
|
|
108
|
+
// The content host also bounds the content's own (shrink-to-fit) width.
|
|
109
|
+
const area =
|
|
110
|
+
behavior === 'resize'
|
|
111
|
+
? available
|
|
112
|
+
: availableRect(this.viewport, this.insets, 0);
|
|
113
|
+
content.style.width = `${area.width}px`;
|
|
114
|
+
content.style.height = `${area.height}px`;
|
|
115
|
+
this.reportContentArea(area.width, area.height);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
private render(progress: number) {
|
|
119
|
+
if (!this.elements) return;
|
|
120
|
+
const { surface, backdrop } = this.elements;
|
|
121
|
+
const visible = Math.min(Math.max(progress, 0), 1);
|
|
122
|
+
const animation = this.config.popupAnimation;
|
|
123
|
+
backdrop.style.opacity = String(visible);
|
|
124
|
+
surface.style.opacity = animation === 'none' ? '1' : String(visible);
|
|
125
|
+
const scale =
|
|
126
|
+
animation === 'scale' ? ENTER_SCALE + (1 - ENTER_SCALE) * progress : 1;
|
|
127
|
+
surface.style.transform = `scale(${scale})`;
|
|
128
|
+
}
|
|
129
|
+
}
|