@getuserfeedback/react-native 3.0.49 → 3.0.56
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/dist/index.js +2 -2
- package/dist/native-runtime-root.d.ts +9 -1
- package/dist/native-runtime-root.js +39 -13
- package/dist/provider-widget-border-radius.d.ts +11 -0
- package/dist/provider-widget-border-radius.js +115 -0
- package/dist/provider-widget-frame-appearance.d.ts +35 -7
- package/dist/provider-widget-frame-appearance.js +56 -24
- package/dist/provider-widget-host-overlay.d.ts +19 -4
- package/dist/provider-widget-host-overlay.js +204 -63
- package/dist/version.js +1 -1
- package/dist/view-webview-bridge-adapter.js +2 -0
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -650,8 +650,7 @@ export function GetUserFeedbackProvider({ autoInit = true, children, commandTime
|
|
|
650
650
|
(previousSheetHostLayoutUpdate === null || previousSheetHostLayoutUpdate === void 0 ? void 0 : previousSheetHostLayoutUpdate.transition.kind) === "timed" &&
|
|
651
651
|
previousSheetHostLayoutUpdate.size.height ===
|
|
652
652
|
sheetHostLayoutPlan.size.height
|
|
653
|
-
? previousSheetHostLayoutUpdate
|
|
654
|
-
: sheetHostLayoutPlan.update;
|
|
653
|
+
? Object.assign(Object.assign({}, previousSheetHostLayoutUpdate), { size: sheetHostLayoutPlan.size }) : sheetHostLayoutPlan.update;
|
|
655
654
|
break;
|
|
656
655
|
}
|
|
657
656
|
case "timed":
|
|
@@ -699,6 +698,7 @@ export function GetUserFeedbackProvider({ autoInit = true, children, commandTime
|
|
|
699
698
|
nativeView: NativeView,
|
|
700
699
|
onRequestDismiss: handleWidgetHostDismiss,
|
|
701
700
|
sheetHostLayoutUpdate,
|
|
701
|
+
transitionSequence: transitionPolicySequence,
|
|
702
702
|
}, widgetHost));
|
|
703
703
|
}
|
|
704
704
|
export function useGetUserFeedbackNative() {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { CoreCommandEnvelope } from "@getuserfeedback/protocol";
|
|
1
2
|
import { type ReactElement } from "react";
|
|
2
3
|
import { type CoreWebViewHostProps } from "./core-webview-host.js";
|
|
3
4
|
import { type NativeCoreCommandChannel } from "./native-core-command-channel.js";
|
|
@@ -6,10 +7,17 @@ export type NativeRuntimeRootProps = {
|
|
|
6
7
|
coreUrl: string;
|
|
7
8
|
coreWebViewComponent?: CoreWebViewHostProps["webViewComponent"];
|
|
8
9
|
coreWebViewProps?: CoreWebViewHostProps["webViewProps"];
|
|
10
|
+
instanceRegistrationEnvelope?: NativeRuntimeInstanceRegistrationEnvelope;
|
|
9
11
|
onCommandChannelChange?: (channel: NativeCoreCommandChannel | null) => void;
|
|
10
12
|
onError?: (error: Error) => void;
|
|
11
13
|
onInvalidMessage?: (error: Error, value: unknown) => void;
|
|
12
14
|
viewWebViewComponent?: NativeViewHostProjectionProps["webViewComponent"];
|
|
13
15
|
viewWebViewProps?: NativeViewHostProjectionProps["webViewProps"];
|
|
14
16
|
};
|
|
15
|
-
|
|
17
|
+
type NativeRuntimeInstanceRegistrationEnvelope = Omit<CoreCommandEnvelope, "command"> & {
|
|
18
|
+
command: Extract<CoreCommandEnvelope["command"], {
|
|
19
|
+
kind: "init";
|
|
20
|
+
}>;
|
|
21
|
+
};
|
|
22
|
+
export declare function NativeRuntimeRoot({ coreUrl, coreWebViewComponent, coreWebViewProps, instanceRegistrationEnvelope, onCommandChannelChange, onError, onInvalidMessage, viewWebViewComponent, viewWebViewProps, }: NativeRuntimeRootProps): ReactElement;
|
|
23
|
+
export {};
|
|
@@ -3,43 +3,51 @@ import { CoreWebViewHost, } from "./core-webview-host.js";
|
|
|
3
3
|
import { createNativeCoreCommandChannel, } from "./native-core-command-channel.js";
|
|
4
4
|
import { NativeViewHostProjection, } from "./native-view-host-projection.js";
|
|
5
5
|
import { createNativeViewRecordController, } from "./native-view-record-controller.js";
|
|
6
|
-
// TODO(architecture):
|
|
7
|
-
// [from=
|
|
8
|
-
export function NativeRuntimeRoot({ coreUrl, coreWebViewComponent, coreWebViewProps, onCommandChannelChange, onError, onInvalidMessage, viewWebViewComponent, viewWebViewProps, }) {
|
|
6
|
+
// TODO(architecture): Compose provider-owned startup state with the private native runtime without changing the default loader-backed path.
|
|
7
|
+
// [from=protocol-owned-native-command-bootstrap-routing] [to=provider-owned-native-registration-composition] [scope=slice] [principle=preserve-provider-runtime] [priority=high] [impact=high] [risk=high] [epic=runtime-neutral-view-host-orchestration] [epic_order=80]
|
|
8
|
+
export function NativeRuntimeRoot({ coreUrl, coreWebViewComponent, coreWebViewProps, instanceRegistrationEnvelope, onCommandChannelChange, onError, onInvalidMessage, viewWebViewComponent, viewWebViewProps, }) {
|
|
9
|
+
const [coreHostRevision, setCoreHostRevision] = useState(0);
|
|
9
10
|
const [session, setSession] = useState(null);
|
|
10
11
|
const sessionRef = useRef(null);
|
|
11
12
|
const nextSessionKeyRef = useRef(0);
|
|
13
|
+
const registrationRetryAttemptedRef = useRef(false);
|
|
12
14
|
const onErrorRef = useRef(onError);
|
|
13
15
|
onErrorRef.current = onError;
|
|
14
16
|
const onCommandChannelChangeRef = useRef(onCommandChannelChange);
|
|
15
17
|
onCommandChannelChangeRef.current = onCommandChannelChange;
|
|
16
18
|
const onInvalidMessageRef = useRef(onInvalidMessage);
|
|
17
19
|
onInvalidMessageRef.current = onInvalidMessage;
|
|
18
|
-
const
|
|
20
|
+
const instanceRegistrationEnvelopeRef = useRef(instanceRegistrationEnvelope);
|
|
21
|
+
instanceRegistrationEnvelopeRef.current = instanceRegistrationEnvelope;
|
|
22
|
+
const reportError = useCallback((error) => {
|
|
19
23
|
var _a;
|
|
24
|
+
try {
|
|
25
|
+
(_a = onErrorRef.current) === null || _a === void 0 ? void 0 : _a.call(onErrorRef, error instanceof Error ? error : new Error(String(error)));
|
|
26
|
+
}
|
|
27
|
+
catch (_b) {
|
|
28
|
+
// Error observers cannot change native runtime settlement.
|
|
29
|
+
}
|
|
30
|
+
}, []);
|
|
31
|
+
const notifyCommandChannelObserver = useCallback((observer, channel) => {
|
|
20
32
|
try {
|
|
21
33
|
observer === null || observer === void 0 ? void 0 : observer(channel);
|
|
22
34
|
}
|
|
23
35
|
catch (error) {
|
|
24
|
-
|
|
25
|
-
(_a = onErrorRef.current) === null || _a === void 0 ? void 0 : _a.call(onErrorRef, error instanceof Error ? error : new Error(String(error)));
|
|
26
|
-
}
|
|
27
|
-
catch (_b) {
|
|
28
|
-
// Observer failures must not interrupt connection settlement.
|
|
29
|
-
}
|
|
36
|
+
reportError(error);
|
|
30
37
|
}
|
|
31
|
-
}, []);
|
|
38
|
+
}, [reportError]);
|
|
32
39
|
const handleConnected = useCallback((coreConnection) => {
|
|
33
40
|
const previousSession = sessionRef.current;
|
|
34
41
|
if (previousSession) {
|
|
35
42
|
sessionRef.current = null;
|
|
36
43
|
previousSession.commandChannelOwner.dispose();
|
|
37
44
|
previousSession.controller.dispose();
|
|
45
|
+
setSession(null);
|
|
38
46
|
notifyCommandChannelObserver(previousSession.observer, null);
|
|
39
47
|
}
|
|
40
48
|
const controller = createNativeViewRecordController({
|
|
41
49
|
coreConnection,
|
|
42
|
-
onError:
|
|
50
|
+
onError: reportError,
|
|
43
51
|
});
|
|
44
52
|
const commandChannelOwner = createNativeCoreCommandChannel({
|
|
45
53
|
coreConnection,
|
|
@@ -51,11 +59,28 @@ export function NativeRuntimeRoot({ coreUrl, coreWebViewComponent, coreWebViewPr
|
|
|
51
59
|
key: nextSessionKeyRef.current + 1,
|
|
52
60
|
observer: onCommandChannelChangeRef.current,
|
|
53
61
|
};
|
|
62
|
+
const registrationEnvelope = instanceRegistrationEnvelopeRef.current;
|
|
63
|
+
if (registrationEnvelope) {
|
|
64
|
+
try {
|
|
65
|
+
commandChannelOwner.channel.post(registrationEnvelope);
|
|
66
|
+
}
|
|
67
|
+
catch (error) {
|
|
68
|
+
commandChannelOwner.dispose();
|
|
69
|
+
controller.dispose();
|
|
70
|
+
if (!registrationRetryAttemptedRef.current) {
|
|
71
|
+
registrationRetryAttemptedRef.current = true;
|
|
72
|
+
setCoreHostRevision((revision) => revision + 1);
|
|
73
|
+
}
|
|
74
|
+
reportError(error);
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
registrationRetryAttemptedRef.current = false;
|
|
54
79
|
nextSessionKeyRef.current = nextSession.key;
|
|
55
80
|
sessionRef.current = nextSession;
|
|
56
81
|
setSession(nextSession);
|
|
57
82
|
notifyCommandChannelObserver(nextSession.observer, commandChannelOwner.channel);
|
|
58
|
-
}, [notifyCommandChannelObserver]);
|
|
83
|
+
}, [notifyCommandChannelObserver, reportError]);
|
|
59
84
|
const handleDisconnected = useCallback(() => {
|
|
60
85
|
const currentSession = sessionRef.current;
|
|
61
86
|
if (!currentSession) {
|
|
@@ -88,6 +113,7 @@ export function NativeRuntimeRoot({ coreUrl, coreWebViewComponent, coreWebViewPr
|
|
|
88
113
|
}, [notifyCommandChannelObserver]);
|
|
89
114
|
return createElement(Fragment, null, createElement(CoreWebViewHost, {
|
|
90
115
|
coreUrl,
|
|
116
|
+
key: `${coreUrl}:${coreHostRevision}`,
|
|
91
117
|
onConnected: handleConnected,
|
|
92
118
|
onDisconnected: handleDisconnected,
|
|
93
119
|
onInvalidMessage,
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { WidgetFrameResolvedBorderRadius } from "@getuserfeedback/protocol/host";
|
|
2
|
+
type ProviderWidgetFrameSize = {
|
|
3
|
+
height: number;
|
|
4
|
+
width: number;
|
|
5
|
+
};
|
|
6
|
+
export declare function safeParseProviderWidgetCanonicalTopRadii(value: string): {
|
|
7
|
+
topLeft: number;
|
|
8
|
+
topRight: number;
|
|
9
|
+
} | undefined;
|
|
10
|
+
export declare function resolveProviderWidgetCanonicalBorderRadius(value: string, frameSize: ProviderWidgetFrameSize): WidgetFrameResolvedBorderRadius | undefined;
|
|
11
|
+
export {};
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
const CANONICAL_PX_PATTERN = /^(?:0|[1-9]\d*)(?:\.\d+)?px$/;
|
|
2
|
+
const CANONICAL_RADIUS_COMPONENT_PATTERN = /^((?:\d+(?:\.\d+)?|\.\d+))(px|%)$/;
|
|
3
|
+
const safeParseCanonicalPx = (value) => {
|
|
4
|
+
if (!CANONICAL_PX_PATTERN.test(value)) {
|
|
5
|
+
return undefined;
|
|
6
|
+
}
|
|
7
|
+
const parsed = Number.parseFloat(value);
|
|
8
|
+
return Number.isFinite(parsed) ? parsed : undefined;
|
|
9
|
+
};
|
|
10
|
+
export function safeParseProviderWidgetCanonicalTopRadii(value) {
|
|
11
|
+
if (value.includes("/")) {
|
|
12
|
+
return undefined;
|
|
13
|
+
}
|
|
14
|
+
const radii = value.split(/\s+/).map(safeParseCanonicalPx);
|
|
15
|
+
if (radii.length === 0 ||
|
|
16
|
+
radii.length > 4 ||
|
|
17
|
+
radii.some((radius) => radius === undefined)) {
|
|
18
|
+
return undefined;
|
|
19
|
+
}
|
|
20
|
+
const [topLeft, topRight = topLeft] = radii;
|
|
21
|
+
return topLeft === undefined || topRight === undefined
|
|
22
|
+
? undefined
|
|
23
|
+
: { topLeft, topRight };
|
|
24
|
+
}
|
|
25
|
+
const parseCanonicalRadiusComponent = (value) => {
|
|
26
|
+
var _a;
|
|
27
|
+
const match = CANONICAL_RADIUS_COMPONENT_PATTERN.exec(value);
|
|
28
|
+
if (match === null) {
|
|
29
|
+
return undefined;
|
|
30
|
+
}
|
|
31
|
+
const parsed = Number.parseFloat((_a = match[1]) !== null && _a !== void 0 ? _a : "");
|
|
32
|
+
const unit = match[2];
|
|
33
|
+
return Number.isFinite(parsed) && (unit === "px" || unit === "%")
|
|
34
|
+
? { unit, value: parsed }
|
|
35
|
+
: undefined;
|
|
36
|
+
};
|
|
37
|
+
const expandRadiusComponents = (values) => {
|
|
38
|
+
const [topLeft, topRight, bottomRight, bottomLeft] = values;
|
|
39
|
+
if (topLeft === undefined || values.length > 4) {
|
|
40
|
+
return undefined;
|
|
41
|
+
}
|
|
42
|
+
if (values.length === 1) {
|
|
43
|
+
return [topLeft, topLeft, topLeft, topLeft];
|
|
44
|
+
}
|
|
45
|
+
if (topRight === undefined) {
|
|
46
|
+
return undefined;
|
|
47
|
+
}
|
|
48
|
+
if (values.length === 2) {
|
|
49
|
+
return [topLeft, topRight, topLeft, topRight];
|
|
50
|
+
}
|
|
51
|
+
if (bottomRight === undefined) {
|
|
52
|
+
return undefined;
|
|
53
|
+
}
|
|
54
|
+
if (values.length === 3) {
|
|
55
|
+
return [topLeft, topRight, bottomRight, topRight];
|
|
56
|
+
}
|
|
57
|
+
return bottomLeft === undefined
|
|
58
|
+
? undefined
|
|
59
|
+
: [topLeft, topRight, bottomRight, bottomLeft];
|
|
60
|
+
};
|
|
61
|
+
const parseCanonicalRadiusComponents = (value) => {
|
|
62
|
+
const components = value
|
|
63
|
+
.trim()
|
|
64
|
+
.split(/\s+/)
|
|
65
|
+
.map(parseCanonicalRadiusComponent);
|
|
66
|
+
return components.some((component) => component === undefined)
|
|
67
|
+
? undefined
|
|
68
|
+
: expandRadiusComponents(components);
|
|
69
|
+
};
|
|
70
|
+
const resolveCanonicalRadiusComponent = (component, basis) => component.unit === "%" ? (component.value / 100) * basis : component.value;
|
|
71
|
+
const toRadiusOverlapRatio = (limit, first, second) => {
|
|
72
|
+
const max = Math.max(first, second);
|
|
73
|
+
return max === 0 ? 1 : limit / max / (first / max + second / max);
|
|
74
|
+
};
|
|
75
|
+
export function resolveProviderWidgetCanonicalBorderRadius(value, frameSize) {
|
|
76
|
+
var _a, _b, _c;
|
|
77
|
+
if (!Number.isFinite(frameSize.width) ||
|
|
78
|
+
frameSize.width < 0 ||
|
|
79
|
+
!Number.isFinite(frameSize.height) ||
|
|
80
|
+
frameSize.height < 0) {
|
|
81
|
+
return undefined;
|
|
82
|
+
}
|
|
83
|
+
const axes = value.split("/");
|
|
84
|
+
if (axes.length > 2) {
|
|
85
|
+
return undefined;
|
|
86
|
+
}
|
|
87
|
+
const horizontal = parseCanonicalRadiusComponents((_a = axes[0]) !== null && _a !== void 0 ? _a : "");
|
|
88
|
+
const vertical = parseCanonicalRadiusComponents((_c = (_b = axes[1]) !== null && _b !== void 0 ? _b : axes[0]) !== null && _c !== void 0 ? _c : "");
|
|
89
|
+
if (horizontal === undefined || vertical === undefined) {
|
|
90
|
+
return undefined;
|
|
91
|
+
}
|
|
92
|
+
const resolveCorner = (index) => ({
|
|
93
|
+
horizontalPx: resolveCanonicalRadiusComponent(horizontal[index], frameSize.width),
|
|
94
|
+
verticalPx: resolveCanonicalRadiusComponent(vertical[index], frameSize.height),
|
|
95
|
+
});
|
|
96
|
+
const topLeft = resolveCorner(0);
|
|
97
|
+
const topRight = resolveCorner(1);
|
|
98
|
+
const bottomRight = resolveCorner(2);
|
|
99
|
+
const bottomLeft = resolveCorner(3);
|
|
100
|
+
if ([topLeft, topRight, bottomRight, bottomLeft].some((corner) => !Number.isFinite(corner.horizontalPx) ||
|
|
101
|
+
!Number.isFinite(corner.verticalPx))) {
|
|
102
|
+
return undefined;
|
|
103
|
+
}
|
|
104
|
+
const overlapScale = Math.min(1, toRadiusOverlapRatio(frameSize.width, topLeft.horizontalPx, topRight.horizontalPx), toRadiusOverlapRatio(frameSize.width, bottomLeft.horizontalPx, bottomRight.horizontalPx), toRadiusOverlapRatio(frameSize.height, topLeft.verticalPx, bottomLeft.verticalPx), toRadiusOverlapRatio(frameSize.height, topRight.verticalPx, bottomRight.verticalPx));
|
|
105
|
+
const scaleCorner = (corner) => ({
|
|
106
|
+
horizontalPx: corner.horizontalPx * overlapScale,
|
|
107
|
+
verticalPx: corner.verticalPx * overlapScale,
|
|
108
|
+
});
|
|
109
|
+
return {
|
|
110
|
+
topLeft: scaleCorner(topLeft),
|
|
111
|
+
topRight: scaleCorner(topRight),
|
|
112
|
+
bottomRight: scaleCorner(bottomRight),
|
|
113
|
+
bottomLeft: scaleCorner(bottomLeft),
|
|
114
|
+
};
|
|
115
|
+
}
|
|
@@ -1,18 +1,46 @@
|
|
|
1
|
-
import type { WidgetFrameAppearance, WidgetFrameResolvedBorder } from "@getuserfeedback/protocol/host";
|
|
1
|
+
import type { WidgetFrameAppearance, WidgetFrameResolvedBorder, WidgetFrameResolvedBoxShadowLayer } from "@getuserfeedback/protocol/host";
|
|
2
2
|
export type ProviderWidgetFrameBorderStyle = {
|
|
3
3
|
borderColor: string;
|
|
4
4
|
borderStyle: "dashed" | "dotted" | "solid";
|
|
5
5
|
borderWidth: number;
|
|
6
6
|
};
|
|
7
|
+
type ProviderWidgetFrameBoxShadowValue = {
|
|
8
|
+
blurRadius: number;
|
|
9
|
+
color: string;
|
|
10
|
+
inset: boolean;
|
|
11
|
+
offsetX: number;
|
|
12
|
+
offsetY: number;
|
|
13
|
+
spreadDistance: number;
|
|
14
|
+
};
|
|
15
|
+
type ProviderWidgetFrameLegacyShadowStyle = {
|
|
16
|
+
elevation: number;
|
|
17
|
+
shadowColor: string;
|
|
18
|
+
shadowOffset: {
|
|
19
|
+
height: number;
|
|
20
|
+
width: number;
|
|
21
|
+
};
|
|
22
|
+
shadowOpacity: number;
|
|
23
|
+
shadowRadius: number;
|
|
24
|
+
};
|
|
25
|
+
export type ProviderWidgetFrameShadowProjection = {
|
|
26
|
+
kind: "clear";
|
|
27
|
+
} | {
|
|
28
|
+
kind: "legacy";
|
|
29
|
+
} | {
|
|
30
|
+
boxShadow: ProviderWidgetFrameBoxShadowValue[];
|
|
31
|
+
fallbackStyle: ProviderWidgetFrameLegacyShadowStyle;
|
|
32
|
+
kind: "resolved";
|
|
33
|
+
};
|
|
7
34
|
export type ProviderWidgetFrameAppearanceProjection = {
|
|
8
35
|
borderStyle?: ProviderWidgetFrameBorderStyle;
|
|
9
|
-
|
|
36
|
+
shadow: ProviderWidgetFrameShadowProjection;
|
|
10
37
|
topLeftRadius: number;
|
|
11
38
|
topRightRadius: number;
|
|
12
39
|
};
|
|
13
|
-
export declare function
|
|
14
|
-
topLeft: number;
|
|
15
|
-
topRight: number;
|
|
16
|
-
} | undefined;
|
|
40
|
+
export declare function toProviderWidgetFrameShadow(layers?: WidgetFrameResolvedBoxShadowLayer[]): ProviderWidgetFrameShadowProjection;
|
|
17
41
|
export declare function toProviderWidgetFrameBorderStyle(border?: WidgetFrameResolvedBorder): ProviderWidgetFrameBorderStyle;
|
|
18
|
-
export declare function toProviderWidgetFrameAppearance(appearance?: WidgetFrameAppearance
|
|
42
|
+
export declare function toProviderWidgetFrameAppearance(appearance?: WidgetFrameAppearance, nativeSheetSize?: {
|
|
43
|
+
height: number;
|
|
44
|
+
width: number;
|
|
45
|
+
}): ProviderWidgetFrameAppearanceProjection;
|
|
46
|
+
export {};
|
|
@@ -1,32 +1,55 @@
|
|
|
1
|
+
import { resolveProviderWidgetCanonicalBorderRadius, safeParseProviderWidgetCanonicalTopRadii, } from "./provider-widget-border-radius.js";
|
|
1
2
|
const LEGACY_WIDGET_SHEET_RADIUS = 24;
|
|
2
|
-
const CANONICAL_PX_PATTERN = /^(?:0|[1-9]\d*)(?:\.\d+)?px$/;
|
|
3
3
|
const CLEARED_WIDGET_FRAME_BORDER_STYLE = {
|
|
4
4
|
borderColor: "transparent",
|
|
5
5
|
borderStyle: "solid",
|
|
6
6
|
borderWidth: 0,
|
|
7
7
|
};
|
|
8
|
-
const
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
|
|
8
|
+
const CLEARED_WIDGET_FRAME_SHADOW_STYLE = {
|
|
9
|
+
elevation: 0,
|
|
10
|
+
shadowColor: "transparent",
|
|
11
|
+
shadowOffset: { height: 0, width: 0 },
|
|
12
|
+
shadowOpacity: 0,
|
|
13
|
+
shadowRadius: 0,
|
|
14
14
|
};
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
const toProviderWidgetFrameColor = (color) => `rgba(${color.red}, ${color.green}, ${color.blue}, ${color.alpha})`;
|
|
16
|
+
const toProviderWidgetFrameBoxShadow = (layers) => layers.map((layer) => ({
|
|
17
|
+
blurRadius: layer.blurRadiusPx,
|
|
18
|
+
color: toProviderWidgetFrameColor(layer.color),
|
|
19
|
+
inset: layer.inset,
|
|
20
|
+
offsetX: layer.offsetXPx,
|
|
21
|
+
offsetY: layer.offsetYPx,
|
|
22
|
+
spreadDistance: layer.spreadRadiusPx,
|
|
23
|
+
}));
|
|
24
|
+
const toProviderWidgetFrameLegacyShadow = (layers) => {
|
|
25
|
+
const layer = layers.find((candidate) => !candidate.inset && candidate.color.alpha > 0);
|
|
26
|
+
if (layer === undefined) {
|
|
27
|
+
return Object.assign({}, CLEARED_WIDGET_FRAME_SHADOW_STYLE);
|
|
18
28
|
}
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
29
|
+
return {
|
|
30
|
+
elevation: Math.max(1, Math.ceil(layer.blurRadiusPx + Math.max(0, layer.spreadRadiusPx))),
|
|
31
|
+
shadowColor: `rgb(${layer.color.red}, ${layer.color.green}, ${layer.color.blue})`,
|
|
32
|
+
shadowOffset: { height: layer.offsetYPx, width: layer.offsetXPx },
|
|
33
|
+
shadowOpacity: layer.color.alpha,
|
|
34
|
+
shadowRadius: layer.blurRadiusPx,
|
|
35
|
+
};
|
|
36
|
+
};
|
|
37
|
+
export function toProviderWidgetFrameShadow(layers) {
|
|
38
|
+
if (layers === undefined) {
|
|
39
|
+
return { kind: "clear" };
|
|
24
40
|
}
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
:
|
|
41
|
+
return {
|
|
42
|
+
boxShadow: toProviderWidgetFrameBoxShadow(layers),
|
|
43
|
+
fallbackStyle: toProviderWidgetFrameLegacyShadow(layers),
|
|
44
|
+
kind: "resolved",
|
|
45
|
+
};
|
|
29
46
|
}
|
|
47
|
+
const toProviderWidgetConservativeResolvedTopRadii = (radius) => ({
|
|
48
|
+
// React Native exposes one scalar per corner, so use a deliberately smaller
|
|
49
|
+
// circle that does not exceed the authored ellipse on either axis.
|
|
50
|
+
topLeft: Math.min(radius.topLeft.horizontalPx, radius.topLeft.verticalPx),
|
|
51
|
+
topRight: Math.min(radius.topRight.horizontalPx, radius.topRight.verticalPx),
|
|
52
|
+
});
|
|
30
53
|
export function toProviderWidgetFrameBorderStyle(border) {
|
|
31
54
|
if (border === undefined ||
|
|
32
55
|
border.widthPx === 0 ||
|
|
@@ -43,11 +66,11 @@ export function toProviderWidgetFrameBorderStyle(border) {
|
|
|
43
66
|
borderWidth: border.widthPx,
|
|
44
67
|
};
|
|
45
68
|
}
|
|
46
|
-
export function toProviderWidgetFrameAppearance(appearance) {
|
|
69
|
+
export function toProviderWidgetFrameAppearance(appearance, nativeSheetSize) {
|
|
47
70
|
var _a, _b;
|
|
48
71
|
if (appearance === undefined) {
|
|
49
72
|
return {
|
|
50
|
-
|
|
73
|
+
shadow: { kind: "legacy" },
|
|
51
74
|
topLeftRadius: LEGACY_WIDGET_SHEET_RADIUS,
|
|
52
75
|
topRightRadius: LEGACY_WIDGET_SHEET_RADIUS,
|
|
53
76
|
};
|
|
@@ -55,15 +78,24 @@ export function toProviderWidgetFrameAppearance(appearance) {
|
|
|
55
78
|
if (appearance.kind === "none") {
|
|
56
79
|
return {
|
|
57
80
|
borderStyle: toProviderWidgetFrameBorderStyle(),
|
|
58
|
-
|
|
81
|
+
shadow: { kind: "clear" },
|
|
59
82
|
topLeftRadius: 0,
|
|
60
83
|
topRightRadius: 0,
|
|
61
84
|
};
|
|
62
85
|
}
|
|
63
|
-
|
|
86
|
+
// Percentage radii depend on the host-owned sheet box, which can differ from
|
|
87
|
+
// the view's reported plan. Browser-only expressions keep the structured fallback.
|
|
88
|
+
const nativeResolvedRadius = nativeSheetSize === undefined || !appearance.borderRadius.includes("%")
|
|
89
|
+
? undefined
|
|
90
|
+
: resolveProviderWidgetCanonicalBorderRadius(appearance.borderRadius, nativeSheetSize);
|
|
91
|
+
const radius = nativeResolvedRadius !== undefined
|
|
92
|
+
? toProviderWidgetConservativeResolvedTopRadii(nativeResolvedRadius)
|
|
93
|
+
: appearance.resolvedBorderRadius === undefined
|
|
94
|
+
? safeParseProviderWidgetCanonicalTopRadii(appearance.borderRadius)
|
|
95
|
+
: toProviderWidgetConservativeResolvedTopRadii(appearance.resolvedBorderRadius);
|
|
64
96
|
return {
|
|
65
97
|
borderStyle: toProviderWidgetFrameBorderStyle(appearance.resolvedBorder),
|
|
66
|
-
|
|
98
|
+
shadow: toProviderWidgetFrameShadow(appearance.resolvedBoxShadow),
|
|
67
99
|
topLeftRadius: (_a = radius === null || radius === void 0 ? void 0 : radius.topLeft) !== null && _a !== void 0 ? _a : 0,
|
|
68
100
|
topRightRadius: (_b = radius === null || radius === void 0 ? void 0 : radius.topRight) !== null && _b !== void 0 ? _b : 0,
|
|
69
101
|
};
|
|
@@ -2,6 +2,19 @@ import { type WidgetFrameAppearance, type WidgetLayoutComparableSizeUpdate, type
|
|
|
2
2
|
import { type ComponentType, type ReactElement, type ReactNode } from "react";
|
|
3
3
|
import type { WidgetHostProps } from "./widget-host.js";
|
|
4
4
|
type NativeViewComponent = ComponentType<Record<string, unknown>>;
|
|
5
|
+
type NativeReactVersion = {
|
|
6
|
+
major?: unknown;
|
|
7
|
+
minor?: unknown;
|
|
8
|
+
};
|
|
9
|
+
export type ProviderWidgetNativeBoxShadowSupport = "all" | "none" | "outset";
|
|
10
|
+
export declare function toProviderWidgetNativeBoxShadowSupport(input: {
|
|
11
|
+
hasFabricUIManager: boolean;
|
|
12
|
+
platform: {
|
|
13
|
+
os?: unknown;
|
|
14
|
+
version?: unknown;
|
|
15
|
+
};
|
|
16
|
+
reactNativeVersion?: NativeReactVersion;
|
|
17
|
+
}): ProviderWidgetNativeBoxShadowSupport;
|
|
5
18
|
export declare function toProviderWidgetSheetHostViewport(viewport: WidgetHostProps["hostViewport"], flowSize?: {
|
|
6
19
|
height?: number;
|
|
7
20
|
}): WidgetHostProps["hostViewport"];
|
|
@@ -28,17 +41,19 @@ export declare function toProviderWidgetSheetSurfaceStyles(input: {
|
|
|
28
41
|
frameAppearance?: WidgetFrameAppearance;
|
|
29
42
|
isVisible: boolean;
|
|
30
43
|
sheetHostLayoutUpdate: WidgetLayoutComparableSizeUpdate | undefined;
|
|
44
|
+
nativeBoxShadowSupport?: ProviderWidgetNativeBoxShadowSupport;
|
|
31
45
|
}): {
|
|
32
|
-
contentStyle: unknown
|
|
33
|
-
frameStyle: unknown
|
|
34
|
-
sheetStyle: unknown
|
|
46
|
+
contentStyle: Record<string, unknown>;
|
|
47
|
+
frameStyle: Record<string, unknown>;
|
|
48
|
+
sheetStyle: Record<string, unknown>;
|
|
35
49
|
};
|
|
36
|
-
export declare function ProviderWidgetHostOverlay({ children, frameAppearance, isVisible, nativeView, onRequestDismiss, sheetHostLayoutUpdate, }: {
|
|
50
|
+
export declare function ProviderWidgetHostOverlay({ children, frameAppearance, isVisible, nativeView, onRequestDismiss, sheetHostLayoutUpdate, transitionSequence, }: {
|
|
37
51
|
children?: ReactNode;
|
|
38
52
|
frameAppearance?: WidgetFrameAppearance;
|
|
39
53
|
isVisible: boolean;
|
|
40
54
|
nativeView: NativeViewComponent;
|
|
41
55
|
onRequestDismiss: () => void;
|
|
42
56
|
sheetHostLayoutUpdate: WidgetLayoutComparableSizeUpdate | undefined;
|
|
57
|
+
transitionSequence?: number;
|
|
43
58
|
}): ReactElement;
|
|
44
59
|
export {};
|
|
@@ -134,6 +134,60 @@ function resolveNativeAnimationRuntime() {
|
|
|
134
134
|
return null;
|
|
135
135
|
}
|
|
136
136
|
}
|
|
137
|
+
export function toProviderWidgetNativeBoxShadowSupport(input) {
|
|
138
|
+
var _a, _b;
|
|
139
|
+
if (!input.hasFabricUIManager) {
|
|
140
|
+
return "none";
|
|
141
|
+
}
|
|
142
|
+
const major = (_a = input.reactNativeVersion) === null || _a === void 0 ? void 0 : _a.major;
|
|
143
|
+
const minor = (_b = input.reactNativeVersion) === null || _b === void 0 ? void 0 : _b.minor;
|
|
144
|
+
const supportsBoxShadow = typeof major === "number" &&
|
|
145
|
+
Number.isInteger(major) &&
|
|
146
|
+
(major > 0 ||
|
|
147
|
+
(major === 0 &&
|
|
148
|
+
typeof minor === "number" &&
|
|
149
|
+
Number.isInteger(minor) &&
|
|
150
|
+
minor >= 76));
|
|
151
|
+
if (!supportsBoxShadow) {
|
|
152
|
+
return "none";
|
|
153
|
+
}
|
|
154
|
+
if (input.platform.os === "ios") {
|
|
155
|
+
return "all";
|
|
156
|
+
}
|
|
157
|
+
if (input.platform.os !== "android") {
|
|
158
|
+
return "none";
|
|
159
|
+
}
|
|
160
|
+
const androidApiLevel = input.platform.version;
|
|
161
|
+
if (typeof androidApiLevel !== "number" ||
|
|
162
|
+
!Number.isInteger(androidApiLevel)) {
|
|
163
|
+
return "none";
|
|
164
|
+
}
|
|
165
|
+
return androidApiLevel >= 29
|
|
166
|
+
? "all"
|
|
167
|
+
: androidApiLevel >= 28
|
|
168
|
+
? "outset"
|
|
169
|
+
: "none";
|
|
170
|
+
}
|
|
171
|
+
function resolveNativeBoxShadowSupport() {
|
|
172
|
+
var _a, _b, _c, _d;
|
|
173
|
+
try {
|
|
174
|
+
const reactNativeModule = require("react-native");
|
|
175
|
+
// React Native exposes renderer capability to JavaScript process-wide.
|
|
176
|
+
// There is no stable public API for querying the renderer of this View.
|
|
177
|
+
const fabricUIManager = Reflect.get(globalThis, "nativeFabricUIManager");
|
|
178
|
+
return toProviderWidgetNativeBoxShadowSupport({
|
|
179
|
+
hasFabricUIManager: fabricUIManager !== undefined && fabricUIManager !== null,
|
|
180
|
+
platform: {
|
|
181
|
+
os: (_a = reactNativeModule.Platform) === null || _a === void 0 ? void 0 : _a.OS,
|
|
182
|
+
version: (_b = reactNativeModule.Platform) === null || _b === void 0 ? void 0 : _b.Version,
|
|
183
|
+
},
|
|
184
|
+
reactNativeVersion: (_d = (_c = reactNativeModule.Platform) === null || _c === void 0 ? void 0 : _c.constants) === null || _d === void 0 ? void 0 : _d.reactNativeVersion,
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
catch (_e) {
|
|
188
|
+
return "none";
|
|
189
|
+
}
|
|
190
|
+
}
|
|
137
191
|
function toResponderPageY(event) {
|
|
138
192
|
var _a, _b, _c;
|
|
139
193
|
const nativeEvent = event === null || event === void 0 ? void 0 : event.nativeEvent;
|
|
@@ -212,100 +266,184 @@ export function toProviderWidgetHostStyle({ isVisible, webViewStyle, }) {
|
|
|
212
266
|
export function toProviderWidgetSheetSurfaceStyles(input) {
|
|
213
267
|
var _a;
|
|
214
268
|
const sheetHostViewport = (_a = input.sheetHostLayoutUpdate) === null || _a === void 0 ? void 0 : _a.size;
|
|
215
|
-
const appearance = toProviderWidgetFrameAppearance(input.frameAppearance);
|
|
269
|
+
const appearance = toProviderWidgetFrameAppearance(input.frameAppearance, sheetHostViewport);
|
|
216
270
|
const radiusStyle = {
|
|
217
271
|
borderTopLeftRadius: appearance.topLeftRadius,
|
|
218
272
|
borderTopRightRadius: appearance.topRightRadius,
|
|
219
273
|
};
|
|
220
|
-
const
|
|
274
|
+
const nativeBoxShadow = appearance.shadow.kind !== "resolved" ||
|
|
275
|
+
input.nativeBoxShadowSupport === undefined ||
|
|
276
|
+
input.nativeBoxShadowSupport === "none"
|
|
277
|
+
? undefined
|
|
278
|
+
: input.nativeBoxShadowSupport === "all"
|
|
279
|
+
? appearance.shadow.boxShadow
|
|
280
|
+
: appearance.shadow.boxShadow.filter((shadow) => !shadow.inset);
|
|
281
|
+
const usesNativeBoxShadow = nativeBoxShadow !== undefined;
|
|
282
|
+
const sheetShadowStyle = appearance.shadow.kind === "legacy"
|
|
221
283
|
? WIDGET_SHEET_LEGACY_FRAME_STYLE
|
|
222
|
-
:
|
|
284
|
+
: appearance.shadow.kind === "resolved" && !usesNativeBoxShadow
|
|
285
|
+
? appearance.shadow.fallbackStyle
|
|
286
|
+
: WIDGET_SHEET_CLEARED_FRAME_STYLE;
|
|
287
|
+
const frameShadowStyle = nativeBoxShadow === undefined ? {} : { boxShadow: nativeBoxShadow };
|
|
223
288
|
return {
|
|
224
289
|
contentStyle: Object.assign(Object.assign({}, WIDGET_SHEET_CONTENT_BASE_STYLE), radiusStyle),
|
|
225
290
|
frameStyle: input.isVisible && sheetHostViewport !== undefined
|
|
226
|
-
? Object.assign(Object.assign(Object.assign({}, WIDGET_SHEET_FRAME_OVERLAY_STYLE), radiusStyle), appearance.borderStyle) : HIDDEN_WIDGET_HOST_STYLE,
|
|
291
|
+
? Object.assign(Object.assign(Object.assign(Object.assign({}, WIDGET_SHEET_FRAME_OVERLAY_STYLE), radiusStyle), appearance.borderStyle), frameShadowStyle) : HIDDEN_WIDGET_HOST_STYLE,
|
|
227
292
|
sheetStyle: input.isVisible && sheetHostViewport !== undefined
|
|
228
|
-
? Object.assign(Object.assign(Object.assign(Object.assign({}, WIDGET_SHEET_LAYOUT_STYLE), radiusStyle),
|
|
293
|
+
? Object.assign(Object.assign(Object.assign(Object.assign({}, WIDGET_SHEET_LAYOUT_STYLE), radiusStyle), sheetShadowStyle), { height: sheetHostViewport.height }) : HIDDEN_WIDGET_HOST_STYLE,
|
|
229
294
|
};
|
|
230
295
|
}
|
|
231
296
|
function useProviderWidgetSheetPresentation(input) {
|
|
232
|
-
var _a, _b, _c
|
|
297
|
+
var _a, _b, _c;
|
|
233
298
|
const animationRuntime = useMemo(resolveNativeAnimationRuntime, []);
|
|
234
|
-
const
|
|
235
|
-
const animationRef = useRef(
|
|
236
|
-
const
|
|
237
|
-
const
|
|
299
|
+
const animatedValuesRef = useRef(null);
|
|
300
|
+
const animationRef = useRef([]);
|
|
301
|
+
const consumedTransitionSequenceRef = useRef(undefined);
|
|
302
|
+
const previousFrameRef = useRef(undefined);
|
|
303
|
+
const animatedSurfaceView = useMemo(() => animationRuntime
|
|
238
304
|
? animationRuntime.Animated.createAnimatedComponent(input.nativeView)
|
|
239
305
|
: input.nativeView, [animationRuntime, input.nativeView]);
|
|
240
306
|
const sheetHostViewport = (_a = input.sheetHostLayoutUpdate) === null || _a === void 0 ? void 0 : _a.size;
|
|
241
307
|
const height = sheetHostViewport === null || sheetHostViewport === void 0 ? void 0 : sheetHostViewport.height;
|
|
308
|
+
const topLeftRadius = input.surfaceStyles.sheetStyle.borderTopLeftRadius;
|
|
309
|
+
const topRightRadius = input.surfaceStyles.sheetStyle.borderTopRightRadius;
|
|
310
|
+
const frame = useMemo(() => height !== undefined &&
|
|
311
|
+
typeof topLeftRadius === "number" &&
|
|
312
|
+
typeof topRightRadius === "number"
|
|
313
|
+
? { height, topLeftRadius, topRightRadius }
|
|
314
|
+
: undefined, [height, topLeftRadius, topRightRadius]);
|
|
242
315
|
const shouldUseAnimatedStyle = animationRuntime !== null &&
|
|
243
316
|
input.isVisible &&
|
|
244
|
-
|
|
317
|
+
frame !== undefined &&
|
|
318
|
+
previousFrameRef.current !== undefined &&
|
|
245
319
|
((_b = input.sheetHostLayoutUpdate) === null || _b === void 0 ? void 0 : _b.transition.kind) === "timed";
|
|
246
|
-
const
|
|
247
|
-
if (animationRuntime &&
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
320
|
+
const surfaceView = animationRuntime ? animatedSurfaceView : input.nativeView;
|
|
321
|
+
if (animationRuntime && frame && animatedValuesRef.current === null) {
|
|
322
|
+
animatedValuesRef.current = {
|
|
323
|
+
height: new animationRuntime.Animated.Value(frame.height),
|
|
324
|
+
topLeftRadius: new animationRuntime.Animated.Value(frame.topLeftRadius),
|
|
325
|
+
topRightRadius: new animationRuntime.Animated.Value(frame.topRightRadius),
|
|
326
|
+
};
|
|
251
327
|
}
|
|
252
328
|
useEffect(() => {
|
|
253
|
-
var _a, _b, _c
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
329
|
+
var _a, _b, _c;
|
|
330
|
+
const stopAnimations = (property) => {
|
|
331
|
+
var _a, _b;
|
|
332
|
+
const retained = [];
|
|
333
|
+
for (const animation of animationRef.current) {
|
|
334
|
+
if (property === undefined || animation.property === property) {
|
|
335
|
+
(_b = (_a = animation.handle).stop) === null || _b === void 0 ? void 0 : _b.call(_a);
|
|
336
|
+
}
|
|
337
|
+
else {
|
|
338
|
+
retained.push(animation);
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
animationRef.current = retained;
|
|
342
|
+
};
|
|
343
|
+
if (!animationRuntime || !frame || !input.isVisible) {
|
|
344
|
+
stopAnimations();
|
|
345
|
+
previousFrameRef.current = undefined;
|
|
258
346
|
return;
|
|
259
347
|
}
|
|
260
|
-
const
|
|
261
|
-
if (!
|
|
348
|
+
const animatedValues = animatedValuesRef.current;
|
|
349
|
+
if (!animatedValues) {
|
|
262
350
|
return;
|
|
263
351
|
}
|
|
264
|
-
const
|
|
265
|
-
|
|
266
|
-
const transition = (
|
|
267
|
-
const
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
if (
|
|
271
|
-
|
|
352
|
+
const previousFrame = previousFrameRef.current;
|
|
353
|
+
previousFrameRef.current = frame;
|
|
354
|
+
const transition = (_a = input.sheetHostLayoutUpdate) === null || _a === void 0 ? void 0 : _a.transition;
|
|
355
|
+
const hasNewTransitionPolicy = input.transitionSequence !== undefined &&
|
|
356
|
+
consumedTransitionSequenceRef.current !== input.transitionSequence;
|
|
357
|
+
const shouldAnimate = (transition === null || transition === void 0 ? void 0 : transition.kind) === "timed" && hasNewTransitionPolicy;
|
|
358
|
+
if (hasNewTransitionPolicy) {
|
|
359
|
+
consumedTransitionSequenceRef.current = input.transitionSequence;
|
|
360
|
+
}
|
|
361
|
+
if (previousFrame === undefined || (transition === null || transition === void 0 ? void 0 : transition.kind) === "instant") {
|
|
362
|
+
stopAnimations();
|
|
363
|
+
animatedValues.height.setValue(frame.height);
|
|
364
|
+
animatedValues.topLeftRadius.setValue(frame.topLeftRadius);
|
|
365
|
+
animatedValues.topRightRadius.setValue(frame.topRightRadius);
|
|
272
366
|
return;
|
|
273
367
|
}
|
|
274
|
-
|
|
275
|
-
|
|
368
|
+
const values = {
|
|
369
|
+
height: animatedValues.height,
|
|
370
|
+
topLeftRadius: animatedValues.topLeftRadius,
|
|
371
|
+
topRightRadius: animatedValues.topRightRadius,
|
|
372
|
+
};
|
|
373
|
+
if (!shouldAnimate) {
|
|
374
|
+
for (const property of [
|
|
375
|
+
"height",
|
|
376
|
+
"topLeftRadius",
|
|
377
|
+
"topRightRadius",
|
|
378
|
+
]) {
|
|
379
|
+
if (previousFrame[property] !== frame[property]) {
|
|
380
|
+
stopAnimations(property);
|
|
381
|
+
values[property].setValue(frame[property]);
|
|
382
|
+
}
|
|
383
|
+
}
|
|
276
384
|
return;
|
|
277
385
|
}
|
|
278
386
|
const easing = transition.easing.kind === "cubic-bezier"
|
|
279
|
-
? (
|
|
387
|
+
? (_c = (_b = animationRuntime.Easing) === null || _b === void 0 ? void 0 : _b.bezier) === null || _c === void 0 ? void 0 : _c.call(_b, ...transition.easing.points)
|
|
280
388
|
: undefined;
|
|
281
|
-
const
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
389
|
+
const animate = (property, value, toValue) => ({
|
|
390
|
+
handle: animationRuntime.Animated.timing(value, {
|
|
391
|
+
toValue,
|
|
392
|
+
duration: transition.durationMs,
|
|
393
|
+
easing,
|
|
394
|
+
useNativeDriver: false,
|
|
395
|
+
}),
|
|
396
|
+
property,
|
|
286
397
|
});
|
|
287
|
-
animationRef.current
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
398
|
+
const activeProperties = new Set(animationRef.current.map((animation) => animation.property));
|
|
399
|
+
const animations = [];
|
|
400
|
+
for (const property of [
|
|
401
|
+
"height",
|
|
402
|
+
"topLeftRadius",
|
|
403
|
+
"topRightRadius",
|
|
404
|
+
]) {
|
|
405
|
+
if (previousFrame[property] !== frame[property] ||
|
|
406
|
+
activeProperties.has(property)) {
|
|
407
|
+
stopAnimations(property);
|
|
408
|
+
animations.push(animate(property, values[property], frame[property]));
|
|
294
409
|
}
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
}
|
|
410
|
+
}
|
|
411
|
+
animationRef.current.push(...animations);
|
|
412
|
+
for (const animation of animations) {
|
|
413
|
+
animation.handle.start(() => {
|
|
414
|
+
animationRef.current = animationRef.current.filter((candidate) => candidate !== animation);
|
|
415
|
+
});
|
|
416
|
+
}
|
|
417
|
+
}, [
|
|
418
|
+
animationRuntime,
|
|
419
|
+
frame,
|
|
420
|
+
input.isVisible,
|
|
421
|
+
(_c = input.sheetHostLayoutUpdate) === null || _c === void 0 ? void 0 : _c.transition,
|
|
422
|
+
input.transitionSequence,
|
|
423
|
+
]);
|
|
424
|
+
useEffect(() => () => {
|
|
425
|
+
var _a, _b;
|
|
426
|
+
for (const animation of animationRef.current) {
|
|
427
|
+
(_b = (_a = animation.handle).stop) === null || _b === void 0 ? void 0 : _b.call(_a);
|
|
428
|
+
}
|
|
429
|
+
animationRef.current = [];
|
|
430
|
+
}, []);
|
|
431
|
+
const animatedValues = animatedValuesRef.current;
|
|
432
|
+
if (!shouldUseAnimatedStyle || animatedValues === null) {
|
|
433
|
+
return Object.assign(Object.assign({}, input.surfaceStyles), { surfaceView });
|
|
302
434
|
}
|
|
435
|
+
const animatedRadiusStyle = {
|
|
436
|
+
borderTopLeftRadius: animatedValues.topLeftRadius,
|
|
437
|
+
borderTopRightRadius: animatedValues.topRightRadius,
|
|
438
|
+
};
|
|
303
439
|
return {
|
|
304
|
-
|
|
305
|
-
|
|
440
|
+
contentStyle: Object.assign(Object.assign({}, input.surfaceStyles.contentStyle), animatedRadiusStyle),
|
|
441
|
+
frameStyle: Object.assign(Object.assign({}, input.surfaceStyles.frameStyle), animatedRadiusStyle),
|
|
442
|
+
sheetStyle: Object.assign(Object.assign(Object.assign({}, input.surfaceStyles.sheetStyle), animatedRadiusStyle), { height: animatedValues.height }),
|
|
443
|
+
surfaceView,
|
|
306
444
|
};
|
|
307
445
|
}
|
|
308
|
-
export function ProviderWidgetHostOverlay({ children, frameAppearance, isVisible, nativeView, onRequestDismiss, sheetHostLayoutUpdate, }) {
|
|
446
|
+
export function ProviderWidgetHostOverlay({ children, frameAppearance, isVisible, nativeView, onRequestDismiss, sheetHostLayoutUpdate, transitionSequence, }) {
|
|
309
447
|
const dragStartYRef = useRef(undefined);
|
|
310
448
|
const handleDragGrant = useCallback((event) => {
|
|
311
449
|
dragStartYRef.current = toResponderPageY(event);
|
|
@@ -359,16 +497,19 @@ export function ProviderWidgetHostOverlay({ children, frameAppearance, isVisible
|
|
|
359
497
|
const sheetHostViewport = sheetHostLayoutUpdate === null || sheetHostLayoutUpdate === void 0 ? void 0 : sheetHostLayoutUpdate.size;
|
|
360
498
|
const isSheetVisible = isVisible && sheetHostViewport !== undefined;
|
|
361
499
|
const pointerEvents = isSheetVisible ? "auto" : "none";
|
|
500
|
+
const nativeBoxShadowSupport = useMemo(resolveNativeBoxShadowSupport, []);
|
|
362
501
|
const surfaceStyles = toProviderWidgetSheetSurfaceStyles({
|
|
363
502
|
frameAppearance,
|
|
364
503
|
isVisible,
|
|
365
504
|
sheetHostLayoutUpdate,
|
|
505
|
+
nativeBoxShadowSupport,
|
|
366
506
|
});
|
|
367
507
|
const sheetPresentation = useProviderWidgetSheetPresentation({
|
|
368
508
|
isVisible,
|
|
369
509
|
nativeView,
|
|
370
510
|
sheetHostLayoutUpdate,
|
|
371
|
-
|
|
511
|
+
surfaceStyles,
|
|
512
|
+
transitionSequence,
|
|
372
513
|
});
|
|
373
514
|
return createElement(nativeView, {
|
|
374
515
|
pointerEvents,
|
|
@@ -382,22 +523,22 @@ export function ProviderWidgetHostOverlay({ children, frameAppearance, isVisible
|
|
|
382
523
|
? WIDGET_SHEET_BACKDROP_STYLE
|
|
383
524
|
: HIDDEN_WIDGET_HOST_STYLE,
|
|
384
525
|
testID: "gx-widget-host-backdrop",
|
|
385
|
-
}), createElement(sheetPresentation.
|
|
526
|
+
}), createElement(sheetPresentation.surfaceView, {
|
|
386
527
|
pointerEvents,
|
|
387
|
-
style: sheetPresentation.
|
|
528
|
+
style: sheetPresentation.sheetStyle,
|
|
388
529
|
testID: "gx-widget-host-sheet",
|
|
389
|
-
}, createElement(
|
|
530
|
+
}, createElement(sheetPresentation.surfaceView, {
|
|
390
531
|
pointerEvents,
|
|
391
|
-
style:
|
|
532
|
+
style: sheetPresentation.contentStyle,
|
|
392
533
|
testID: "gx-widget-host-sheet-content",
|
|
393
534
|
}, children, isSheetVisible
|
|
394
535
|
? createElement(nativeView, Object.assign(Object.assign({}, dragHandleGestureProps), { style: WIDGET_SHEET_DRAG_HANDLE_TOUCH_STYLE, testID: "gx-widget-host-drag-handle" }), createElement(nativeView, {
|
|
395
536
|
style: WIDGET_SHEET_DRAG_HANDLE_INDICATOR_STYLE,
|
|
396
537
|
testID: "gx-widget-host-drag-handle-indicator",
|
|
397
538
|
}))
|
|
398
|
-
: null), createElement(
|
|
539
|
+
: null), createElement(sheetPresentation.surfaceView, {
|
|
399
540
|
pointerEvents: "none",
|
|
400
|
-
style:
|
|
541
|
+
style: sheetPresentation.frameStyle,
|
|
401
542
|
testID: "gx-widget-host-sheet-frame",
|
|
402
543
|
})));
|
|
403
544
|
}
|
package/dist/version.js
CHANGED
|
@@ -3,4 +3,4 @@ const reactNativeSdkVersion = typeof __GX_REACT_NATIVE_SDK_VERSION__ === "string
|
|
|
3
3
|
: "";
|
|
4
4
|
// Build scripts patch this fallback to the package version for published artifacts.
|
|
5
5
|
// Source-linked workspace usage keeps the local fallback.
|
|
6
|
-
export const REACT_NATIVE_SDK_VERSION = reactNativeSdkVersion.length > 0 ? reactNativeSdkVersion : "3.0.
|
|
6
|
+
export const REACT_NATIVE_SDK_VERSION = reactNativeSdkVersion.length > 0 ? reactNativeSdkVersion : "3.0.56";
|
|
@@ -23,6 +23,8 @@ const buildViewHostBootstrapScript = () => {
|
|
|
23
23
|
const bootstrapProtocolVersion = serializeForJavaScript(VIEW_HOST_BOOTSTRAP_PROTOCOL_VERSION);
|
|
24
24
|
const bootstrapCapabilities = serializeForJavaScript([
|
|
25
25
|
VIEW_HOST_BOOTSTRAP_CAPABILITIES.RESOLVED_FRAME_BORDER,
|
|
26
|
+
VIEW_HOST_BOOTSTRAP_CAPABILITIES.RESOLVED_FRAME_BORDER_RADIUS,
|
|
27
|
+
VIEW_HOST_BOOTSTRAP_CAPABILITIES.RESOLVED_FRAME_BOX_SHADOW,
|
|
26
28
|
]);
|
|
27
29
|
const bootstrapReadyEventName = serializeForJavaScript(VIEW_HOST_BOOTSTRAP_READY_EVENT_NAME);
|
|
28
30
|
const inactiveConnectionMessage = serializeForJavaScript(VIEW_WEBVIEW_BRIDGE_CONFIG.inactiveConnectionMessage);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@getuserfeedback/react-native",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.56",
|
|
4
4
|
"description": "getuserfeedback React Native SDK",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"getuserfeedback",
|
|
@@ -44,8 +44,8 @@
|
|
|
44
44
|
"lint": "biome check ."
|
|
45
45
|
},
|
|
46
46
|
"dependencies": {
|
|
47
|
-
"@getuserfeedback/protocol": "^3.
|
|
48
|
-
"@getuserfeedback/sdk": "^0.10.
|
|
47
|
+
"@getuserfeedback/protocol": "^3.15.0",
|
|
48
|
+
"@getuserfeedback/sdk": "^0.10.18",
|
|
49
49
|
"robot3": "^1.2.0"
|
|
50
50
|
},
|
|
51
51
|
"peerDependencies": {
|