@moonpay/platform-sdk-react-native 1.0.3 → 1.1.0
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.cjs +183 -52
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +194 -52
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -370,8 +370,8 @@ var connectionResetSpec = {
|
|
|
370
370
|
};
|
|
371
371
|
|
|
372
372
|
// src/frame-view.tsx
|
|
373
|
-
import { useEffect as
|
|
374
|
-
import { View as
|
|
373
|
+
import { useEffect as useEffect3, useRef as useRef4, useState as useState3 } from "react";
|
|
374
|
+
import { View as View3 } from "react-native";
|
|
375
375
|
|
|
376
376
|
// src/frame-component.tsx
|
|
377
377
|
import { useEffect, useRef } from "react";
|
|
@@ -577,13 +577,12 @@ function createFrameSession(spec, ctx, props, overrides = {}) {
|
|
|
577
577
|
import { createClientCore } from "@moonpay/platform-sdk-core";
|
|
578
578
|
import {
|
|
579
579
|
createContext,
|
|
580
|
-
useCallback,
|
|
580
|
+
useCallback as useCallback2,
|
|
581
581
|
useContext,
|
|
582
582
|
useMemo,
|
|
583
|
-
useRef as
|
|
584
|
-
useState
|
|
583
|
+
useRef as useRef3,
|
|
584
|
+
useState as useState2
|
|
585
585
|
} from "react";
|
|
586
|
-
import { Modal } from "react-native";
|
|
587
586
|
|
|
588
587
|
// src/methods/add-card.ts
|
|
589
588
|
import { err, ok } from "@moonpay/platform-protocol/result";
|
|
@@ -872,8 +871,153 @@ function createMountSession(specCtx, host) {
|
|
|
872
871
|
};
|
|
873
872
|
}
|
|
874
873
|
|
|
875
|
-
// src/
|
|
874
|
+
// src/VisibleFrameSlotSheet.tsx
|
|
875
|
+
import { useCallback, useEffect as useEffect2, useRef as useRef2, useState } from "react";
|
|
876
|
+
import {
|
|
877
|
+
ActivityIndicator,
|
|
878
|
+
Animated,
|
|
879
|
+
Easing,
|
|
880
|
+
Modal,
|
|
881
|
+
Platform,
|
|
882
|
+
Pressable,
|
|
883
|
+
StyleSheet,
|
|
884
|
+
Text,
|
|
885
|
+
useWindowDimensions,
|
|
886
|
+
View as View2
|
|
887
|
+
} from "react-native";
|
|
876
888
|
import { jsx as jsx2, jsxs } from "react/jsx-runtime";
|
|
889
|
+
function animateSheet(value, toValue, onDone) {
|
|
890
|
+
const animation = Platform.OS === "android" ? Animated.timing(value, {
|
|
891
|
+
toValue,
|
|
892
|
+
duration: 250,
|
|
893
|
+
easing: Easing.out(Easing.exp),
|
|
894
|
+
useNativeDriver: true
|
|
895
|
+
}) : Animated.spring(value, {
|
|
896
|
+
toValue,
|
|
897
|
+
damping: 500,
|
|
898
|
+
stiffness: 1e3,
|
|
899
|
+
mass: 3,
|
|
900
|
+
overshootClamping: true,
|
|
901
|
+
restDisplacementThreshold: 10,
|
|
902
|
+
restSpeedThreshold: 10,
|
|
903
|
+
useNativeDriver: true
|
|
904
|
+
});
|
|
905
|
+
animation.start(onDone);
|
|
906
|
+
}
|
|
907
|
+
function VisibleFrameSlotSheet({
|
|
908
|
+
slot,
|
|
909
|
+
onClose
|
|
910
|
+
}) {
|
|
911
|
+
const { height } = useWindowDimensions();
|
|
912
|
+
const sheetHeight = Math.round(height * 0.9);
|
|
913
|
+
const translateY = useRef2(new Animated.Value(sheetHeight)).current;
|
|
914
|
+
const [frameReady, setFrameReady] = useState(false);
|
|
915
|
+
const onCloseRef = useRef2(onClose);
|
|
916
|
+
onCloseRef.current = onClose;
|
|
917
|
+
const closingRef = useRef2(false);
|
|
918
|
+
const close = useCallback(() => {
|
|
919
|
+
if (closingRef.current)
|
|
920
|
+
return;
|
|
921
|
+
closingRef.current = true;
|
|
922
|
+
animateSheet(translateY, sheetHeight, ({ finished }) => {
|
|
923
|
+
if (finished)
|
|
924
|
+
onCloseRef.current();
|
|
925
|
+
});
|
|
926
|
+
}, [translateY, sheetHeight]);
|
|
927
|
+
useEffect2(() => {
|
|
928
|
+
animateSheet(translateY, 0);
|
|
929
|
+
}, [translateY]);
|
|
930
|
+
useEffect2(() => {
|
|
931
|
+
const unsubscribe = slot.transport.onMessage((msg) => {
|
|
932
|
+
if (msg.kind === "ready")
|
|
933
|
+
setFrameReady(true);
|
|
934
|
+
else if (msg.kind === "complete" || msg.kind === "error")
|
|
935
|
+
close();
|
|
936
|
+
});
|
|
937
|
+
return unsubscribe;
|
|
938
|
+
}, [slot.transport, close]);
|
|
939
|
+
const backdropOpacity = translateY.interpolate({
|
|
940
|
+
inputRange: [0, sheetHeight],
|
|
941
|
+
outputRange: [1, 0],
|
|
942
|
+
extrapolate: "clamp"
|
|
943
|
+
});
|
|
944
|
+
return /* @__PURE__ */ jsx2(Modal, { visible: true, transparent: true, animationType: "none", onRequestClose: close, children: /* @__PURE__ */ jsxs(View2, { style: styles.root, children: [
|
|
945
|
+
/* @__PURE__ */ jsx2(Animated.View, { style: [styles.backdrop, { opacity: backdropOpacity }], children: /* @__PURE__ */ jsx2(
|
|
946
|
+
Pressable,
|
|
947
|
+
{
|
|
948
|
+
style: StyleSheet.absoluteFill,
|
|
949
|
+
accessibilityRole: "button",
|
|
950
|
+
accessibilityLabel: "Close",
|
|
951
|
+
onPress: close
|
|
952
|
+
}
|
|
953
|
+
) }),
|
|
954
|
+
/* @__PURE__ */ jsxs(Animated.View, { style: [styles.sheet, { height: sheetHeight, transform: [{ translateY }] }], children: [
|
|
955
|
+
/* @__PURE__ */ jsx2(MoonPayFrame, { transport: slot.transport }),
|
|
956
|
+
!frameReady && /* @__PURE__ */ jsx2(View2, { style: styles.loading, children: /* @__PURE__ */ jsx2(ActivityIndicator, { size: "large", color: "#000" }) }),
|
|
957
|
+
/* @__PURE__ */ jsx2(
|
|
958
|
+
Pressable,
|
|
959
|
+
{
|
|
960
|
+
onPress: close,
|
|
961
|
+
accessibilityRole: "button",
|
|
962
|
+
accessibilityLabel: "Close",
|
|
963
|
+
hitSlop: 8,
|
|
964
|
+
style: styles.closeButton,
|
|
965
|
+
children: /* @__PURE__ */ jsx2(Text, { style: styles.closeButtonText, children: "\u2715" })
|
|
966
|
+
}
|
|
967
|
+
)
|
|
968
|
+
] })
|
|
969
|
+
] }) });
|
|
970
|
+
}
|
|
971
|
+
var styles = StyleSheet.create({
|
|
972
|
+
root: {
|
|
973
|
+
flex: 1,
|
|
974
|
+
justifyContent: "flex-end"
|
|
975
|
+
},
|
|
976
|
+
// Dimmed backdrop covering the whole screen; fades with the sheet position.
|
|
977
|
+
backdrop: {
|
|
978
|
+
...StyleSheet.absoluteFillObject,
|
|
979
|
+
backgroundColor: "rgba(0, 0, 0, 0.5)"
|
|
980
|
+
},
|
|
981
|
+
// Bottom sheet: ~90% of the screen (height applied inline), rounded top
|
|
982
|
+
// corners. The 10% gap keeps the frame clear of the status bar / notch
|
|
983
|
+
// without depending on react-native-safe-area-context.
|
|
984
|
+
sheet: {
|
|
985
|
+
backgroundColor: "#fff",
|
|
986
|
+
borderTopLeftRadius: 24,
|
|
987
|
+
borderTopRightRadius: 24,
|
|
988
|
+
overflow: "hidden"
|
|
989
|
+
},
|
|
990
|
+
// Opaque cover with a centered spinner, shown until the frame is ready.
|
|
991
|
+
loading: {
|
|
992
|
+
...StyleSheet.absoluteFillObject,
|
|
993
|
+
backgroundColor: "#fff",
|
|
994
|
+
alignItems: "center",
|
|
995
|
+
justifyContent: "center"
|
|
996
|
+
},
|
|
997
|
+
// Floating X in the top-right corner, over the frame.
|
|
998
|
+
closeButton: {
|
|
999
|
+
position: "absolute",
|
|
1000
|
+
top: 12,
|
|
1001
|
+
right: 12,
|
|
1002
|
+
width: 32,
|
|
1003
|
+
height: 32,
|
|
1004
|
+
borderRadius: 16,
|
|
1005
|
+
backgroundColor: "rgba(0, 0, 0, 0.06)",
|
|
1006
|
+
alignItems: "center",
|
|
1007
|
+
justifyContent: "center",
|
|
1008
|
+
zIndex: 1,
|
|
1009
|
+
elevation: 2
|
|
1010
|
+
},
|
|
1011
|
+
closeButtonText: {
|
|
1012
|
+
fontSize: 17,
|
|
1013
|
+
lineHeight: 20,
|
|
1014
|
+
color: "#000",
|
|
1015
|
+
fontWeight: "500"
|
|
1016
|
+
}
|
|
1017
|
+
});
|
|
1018
|
+
|
|
1019
|
+
// src/provider.tsx
|
|
1020
|
+
import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
877
1021
|
var MoonPayContext = createContext(null);
|
|
878
1022
|
function MoonPayProvider({
|
|
879
1023
|
sessionToken,
|
|
@@ -881,14 +1025,14 @@ function MoonPayProvider({
|
|
|
881
1025
|
frameBaseUrl,
|
|
882
1026
|
children
|
|
883
1027
|
}) {
|
|
884
|
-
const [frameSlots, setFrameSlots] =
|
|
885
|
-
const addSlot =
|
|
1028
|
+
const [frameSlots, setFrameSlots] = useState2([]);
|
|
1029
|
+
const addSlot = useCallback2((slot) => {
|
|
886
1030
|
setFrameSlots((prev) => [...prev, slot]);
|
|
887
1031
|
}, []);
|
|
888
|
-
const removeSlot =
|
|
1032
|
+
const removeSlot = useCallback2((id) => {
|
|
889
1033
|
setFrameSlots((prev) => prev.filter((s) => s.id !== id));
|
|
890
1034
|
}, []);
|
|
891
|
-
const coreRef =
|
|
1035
|
+
const coreRef = useRef3(null);
|
|
892
1036
|
if (!coreRef.current) {
|
|
893
1037
|
coreRef.current = createClientCore({
|
|
894
1038
|
apiBaseUrl,
|
|
@@ -904,19 +1048,17 @@ function MoonPayProvider({
|
|
|
904
1048
|
core
|
|
905
1049
|
});
|
|
906
1050
|
}, [sessionToken, frameBaseUrl, core, addSlot, removeSlot]);
|
|
907
|
-
return /* @__PURE__ */
|
|
1051
|
+
return /* @__PURE__ */ jsxs2(MoonPayContext.Provider, { value: { client, sessionToken, core, frameBaseUrl }, children: [
|
|
908
1052
|
children,
|
|
909
|
-
frameSlots.filter((slot) => slot.hidden).map((slot) => /* @__PURE__ */
|
|
910
|
-
frameSlots.filter((slot) => !slot.hidden).map((slot) => /* @__PURE__ */
|
|
911
|
-
|
|
1053
|
+
frameSlots.filter((slot) => slot.hidden).map((slot) => /* @__PURE__ */ jsx3(MoonPayFrame, { transport: slot.transport, hidden: true }, slot.id)),
|
|
1054
|
+
frameSlots.filter((slot) => !slot.hidden).map((slot) => /* @__PURE__ */ jsx3(
|
|
1055
|
+
VisibleFrameSlotSheet,
|
|
912
1056
|
{
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
onRequestClose: () => {
|
|
1057
|
+
slot,
|
|
1058
|
+
onClose: () => {
|
|
916
1059
|
slot.dispose();
|
|
917
1060
|
removeSlot(slot.id);
|
|
918
|
-
}
|
|
919
|
-
children: /* @__PURE__ */ jsx2(MoonPayFrame, { transport: slot.transport })
|
|
1061
|
+
}
|
|
920
1062
|
},
|
|
921
1063
|
slot.id
|
|
922
1064
|
))
|
|
@@ -934,7 +1076,7 @@ function useMoonPay() {
|
|
|
934
1076
|
}
|
|
935
1077
|
|
|
936
1078
|
// src/frame-view.tsx
|
|
937
|
-
import { jsx as
|
|
1079
|
+
import { jsx as jsx4 } from "react/jsx-runtime";
|
|
938
1080
|
function applyReactiveProps(spec, keys, props, applied, handle) {
|
|
939
1081
|
for (const key of keys) {
|
|
940
1082
|
const next = props[key];
|
|
@@ -952,11 +1094,11 @@ function MoonPayFrameView({
|
|
|
952
1094
|
onEvent
|
|
953
1095
|
}) {
|
|
954
1096
|
const { sessionToken, core, frameBaseUrl } = useMoonPayContext();
|
|
955
|
-
const [transport, setTransport] =
|
|
956
|
-
const handleRef =
|
|
957
|
-
const onEventRef =
|
|
1097
|
+
const [transport, setTransport] = useState3(null);
|
|
1098
|
+
const handleRef = useRef4(null);
|
|
1099
|
+
const onEventRef = useRef4(onEvent);
|
|
958
1100
|
onEventRef.current = onEvent;
|
|
959
|
-
const propsRef =
|
|
1101
|
+
const propsRef = useRef4(props);
|
|
960
1102
|
propsRef.current = props;
|
|
961
1103
|
const reactiveKeys = Object.keys(spec.reactiveProps ?? {});
|
|
962
1104
|
const mountProps = {};
|
|
@@ -967,8 +1109,8 @@ function MoonPayFrameView({
|
|
|
967
1109
|
}
|
|
968
1110
|
const mountKey = JSON.stringify(mountProps);
|
|
969
1111
|
const liveKey = JSON.stringify(liveProps);
|
|
970
|
-
const appliedRef =
|
|
971
|
-
|
|
1112
|
+
const appliedRef = useRef4({});
|
|
1113
|
+
useEffect3(() => {
|
|
972
1114
|
let disposed = false;
|
|
973
1115
|
let session;
|
|
974
1116
|
const applied = {};
|
|
@@ -1007,23 +1149,23 @@ function MoonPayFrameView({
|
|
|
1007
1149
|
setTransport(null);
|
|
1008
1150
|
};
|
|
1009
1151
|
}, [mountKey, spec, sessionToken, core, frameBaseUrl]);
|
|
1010
|
-
|
|
1152
|
+
useEffect3(() => {
|
|
1011
1153
|
const handle = handleRef.current;
|
|
1012
1154
|
if (!handle)
|
|
1013
1155
|
return;
|
|
1014
1156
|
applyReactiveProps(spec, reactiveKeys, propsRef.current, appliedRef.current, handle);
|
|
1015
1157
|
}, [liveKey]);
|
|
1016
1158
|
if (spec.hidden) {
|
|
1017
|
-
return transport ? /* @__PURE__ */
|
|
1159
|
+
return transport ? /* @__PURE__ */ jsx4(MoonPayFrame, { transport, hidden: true }) : null;
|
|
1018
1160
|
}
|
|
1019
1161
|
const resolvedStyle = { ...defaultStyle, ...style };
|
|
1020
|
-
return /* @__PURE__ */
|
|
1162
|
+
return /* @__PURE__ */ jsx4(View3, { style: resolvedStyle, children: transport ? /* @__PURE__ */ jsx4(MoonPayFrame, { transport }) : null });
|
|
1021
1163
|
}
|
|
1022
1164
|
|
|
1023
1165
|
// src/components/add-card.tsx
|
|
1024
|
-
import { jsx as
|
|
1166
|
+
import { jsx as jsx5 } from "react/jsx-runtime";
|
|
1025
1167
|
function MoonPayAddCard({ onEvent, style }) {
|
|
1026
|
-
return /* @__PURE__ */
|
|
1168
|
+
return /* @__PURE__ */ jsx5(
|
|
1027
1169
|
MoonPayFrameView,
|
|
1028
1170
|
{
|
|
1029
1171
|
spec: addCardSpec,
|
|
@@ -1036,13 +1178,13 @@ function MoonPayAddCard({ onEvent, style }) {
|
|
|
1036
1178
|
}
|
|
1037
1179
|
|
|
1038
1180
|
// src/components/apple-pay-button.tsx
|
|
1039
|
-
import { jsx as
|
|
1181
|
+
import { jsx as jsx6 } from "react/jsx-runtime";
|
|
1040
1182
|
function MoonPayApplePayButton({
|
|
1041
1183
|
quote,
|
|
1042
1184
|
onEvent,
|
|
1043
1185
|
style
|
|
1044
1186
|
}) {
|
|
1045
|
-
return /* @__PURE__ */
|
|
1187
|
+
return /* @__PURE__ */ jsx6(
|
|
1046
1188
|
MoonPayFrameView,
|
|
1047
1189
|
{
|
|
1048
1190
|
spec: applePaySpec,
|
|
@@ -1055,9 +1197,9 @@ function MoonPayApplePayButton({
|
|
|
1055
1197
|
}
|
|
1056
1198
|
|
|
1057
1199
|
// src/components/auth.tsx
|
|
1058
|
-
import { jsx as
|
|
1200
|
+
import { jsx as jsx7 } from "react/jsx-runtime";
|
|
1059
1201
|
function MoonPayAuth({ onEvent, style }) {
|
|
1060
|
-
return /* @__PURE__ */
|
|
1202
|
+
return /* @__PURE__ */ jsx7(
|
|
1061
1203
|
MoonPayFrameView,
|
|
1062
1204
|
{
|
|
1063
1205
|
spec: authSpec,
|
|
@@ -1070,9 +1212,9 @@ function MoonPayAuth({ onEvent, style }) {
|
|
|
1070
1212
|
}
|
|
1071
1213
|
|
|
1072
1214
|
// src/components/buy-button.tsx
|
|
1073
|
-
import { jsx as
|
|
1215
|
+
import { jsx as jsx8 } from "react/jsx-runtime";
|
|
1074
1216
|
function MoonPayBuyButton({ quote, onEvent, style }) {
|
|
1075
|
-
return /* @__PURE__ */
|
|
1217
|
+
return /* @__PURE__ */ jsx8(
|
|
1076
1218
|
MoonPayFrameView,
|
|
1077
1219
|
{
|
|
1078
1220
|
spec: buyButtonSpec,
|
|
@@ -1085,13 +1227,13 @@ function MoonPayBuyButton({ quote, onEvent, style }) {
|
|
|
1085
1227
|
}
|
|
1086
1228
|
|
|
1087
1229
|
// src/components/buy-frame.tsx
|
|
1088
|
-
import { jsx as
|
|
1230
|
+
import { jsx as jsx9 } from "react/jsx-runtime";
|
|
1089
1231
|
function MoonPayBuyFrame({
|
|
1090
1232
|
quote,
|
|
1091
1233
|
externalTransactionId,
|
|
1092
1234
|
onEvent
|
|
1093
1235
|
}) {
|
|
1094
|
-
return /* @__PURE__ */
|
|
1236
|
+
return /* @__PURE__ */ jsx9(
|
|
1095
1237
|
MoonPayFrameView,
|
|
1096
1238
|
{
|
|
1097
1239
|
spec: buySpec,
|
|
@@ -1103,9 +1245,9 @@ function MoonPayBuyFrame({
|
|
|
1103
1245
|
}
|
|
1104
1246
|
|
|
1105
1247
|
// src/components/challenge.tsx
|
|
1106
|
-
import { jsx as
|
|
1248
|
+
import { jsx as jsx10 } from "react/jsx-runtime";
|
|
1107
1249
|
function MoonPayChallenge({ url, onEvent, style }) {
|
|
1108
|
-
return /* @__PURE__ */
|
|
1250
|
+
return /* @__PURE__ */ jsx10(
|
|
1109
1251
|
MoonPayFrameView,
|
|
1110
1252
|
{
|
|
1111
1253
|
spec: challengeSpec,
|
|
@@ -1118,9 +1260,9 @@ function MoonPayChallenge({ url, onEvent, style }) {
|
|
|
1118
1260
|
}
|
|
1119
1261
|
|
|
1120
1262
|
// src/components/connect.tsx
|
|
1121
|
-
import { jsx as
|
|
1263
|
+
import { jsx as jsx11 } from "react/jsx-runtime";
|
|
1122
1264
|
function MoonPayConnect({ theme, onEvent, style }) {
|
|
1123
|
-
return /* @__PURE__ */
|
|
1265
|
+
return /* @__PURE__ */ jsx11(
|
|
1124
1266
|
MoonPayFrameView,
|
|
1125
1267
|
{
|
|
1126
1268
|
spec: connectSpec,
|
|
@@ -1133,12 +1275,12 @@ function MoonPayConnect({ theme, onEvent, style }) {
|
|
|
1133
1275
|
}
|
|
1134
1276
|
|
|
1135
1277
|
// src/components/connection-check.tsx
|
|
1136
|
-
import { jsx as
|
|
1278
|
+
import { jsx as jsx12 } from "react/jsx-runtime";
|
|
1137
1279
|
function MoonPayConnectionCheck({
|
|
1138
1280
|
skipKyc,
|
|
1139
1281
|
onEvent
|
|
1140
1282
|
}) {
|
|
1141
|
-
return /* @__PURE__ */
|
|
1283
|
+
return /* @__PURE__ */ jsx12(
|
|
1142
1284
|
MoonPayFrameView,
|
|
1143
1285
|
{
|
|
1144
1286
|
spec: connectionCheckSpec,
|
|
@@ -1150,20 +1292,20 @@ function MoonPayConnectionCheck({
|
|
|
1150
1292
|
}
|
|
1151
1293
|
|
|
1152
1294
|
// src/components/connection-reset.tsx
|
|
1153
|
-
import { jsx as
|
|
1295
|
+
import { jsx as jsx13 } from "react/jsx-runtime";
|
|
1154
1296
|
function MoonPayConnectionReset({ onEvent }) {
|
|
1155
|
-
return /* @__PURE__ */
|
|
1297
|
+
return /* @__PURE__ */ jsx13(MoonPayFrameView, { spec: connectionResetSpec, props: {}, defaultStyle: {}, onEvent });
|
|
1156
1298
|
}
|
|
1157
1299
|
|
|
1158
1300
|
// src/components/google-pay-button.tsx
|
|
1159
|
-
import { jsx as
|
|
1301
|
+
import { jsx as jsx14 } from "react/jsx-runtime";
|
|
1160
1302
|
function MoonPayGooglePayButton({
|
|
1161
1303
|
quote,
|
|
1162
1304
|
externalTransactionId,
|
|
1163
1305
|
onEvent,
|
|
1164
1306
|
style
|
|
1165
1307
|
}) {
|
|
1166
|
-
return /* @__PURE__ */
|
|
1308
|
+
return /* @__PURE__ */ jsx14(
|
|
1167
1309
|
MoonPayFrameView,
|
|
1168
1310
|
{
|
|
1169
1311
|
spec: googlePaySpec,
|
|
@@ -1176,9 +1318,9 @@ function MoonPayGooglePayButton({
|
|
|
1176
1318
|
}
|
|
1177
1319
|
|
|
1178
1320
|
// src/components/widget.tsx
|
|
1179
|
-
import { jsx as
|
|
1321
|
+
import { jsx as jsx15 } from "react/jsx-runtime";
|
|
1180
1322
|
function MoonPayWidget({ quote, onEvent, style }) {
|
|
1181
|
-
return /* @__PURE__ */
|
|
1323
|
+
return /* @__PURE__ */ jsx15(
|
|
1182
1324
|
MoonPayFrameView,
|
|
1183
1325
|
{
|
|
1184
1326
|
spec: widgetSpec,
|