@farcaster/snap 1.16.3 → 1.17.1
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/react/index.d.ts +3 -1
- package/dist/react/index.js +3 -3
- package/dist/react/v1/snap-view.d.ts +2 -1
- package/dist/react/v1/snap-view.js +9 -3
- package/dist/react/v2/snap-view.d.ts +2 -1
- package/dist/react/v2/snap-view.js +36 -29
- package/dist/react-native/index.d.ts +3 -1
- package/dist/react-native/index.js +3 -3
- package/dist/react-native/v1/snap-view.d.ts +2 -1
- package/dist/react-native/v1/snap-view.js +21 -13
- package/dist/react-native/v2/snap-view.d.ts +2 -1
- package/dist/react-native/v2/snap-view.js +20 -12
- package/package.json +1 -1
- package/src/react/index.tsx +5 -0
- package/src/react/v1/snap-view.tsx +16 -0
- package/src/react/v2/snap-view.tsx +19 -0
- package/src/react-native/index.tsx +5 -0
- package/src/react-native/v1/snap-view.tsx +41 -15
- package/src/react-native/v2/snap-view.tsx +55 -29
package/dist/react/index.d.ts
CHANGED
|
@@ -41,7 +41,7 @@ export type SnapActionHandlers = {
|
|
|
41
41
|
buyToken?: string;
|
|
42
42
|
}) => void;
|
|
43
43
|
};
|
|
44
|
-
export declare function SnapCard({ snap, handlers, loading, appearance, maxWidth, showOverflowWarning, onValidationError, validationErrorFallback, }: {
|
|
44
|
+
export declare function SnapCard({ snap, handlers, loading, appearance, maxWidth, showOverflowWarning, onValidationError, validationErrorFallback, actionError, }: {
|
|
45
45
|
snap: SnapPage;
|
|
46
46
|
handlers: SnapActionHandlers;
|
|
47
47
|
loading?: boolean;
|
|
@@ -51,4 +51,6 @@ export declare function SnapCard({ snap, handlers, loading, appearance, maxWidth
|
|
|
51
51
|
showOverflowWarning?: boolean;
|
|
52
52
|
onValidationError?: (result: ValidationResult) => void;
|
|
53
53
|
validationErrorFallback?: ReactNode;
|
|
54
|
+
/** Server-side action error message to display inline. */
|
|
55
|
+
actionError?: string | null;
|
|
54
56
|
}): import("react/jsx-runtime").JSX.Element;
|
package/dist/react/index.js
CHANGED
|
@@ -4,9 +4,9 @@ import { SPEC_VERSION_2 } from "../constants.js";
|
|
|
4
4
|
import { SnapCardV1 } from "./v1/snap-view.js";
|
|
5
5
|
import { SnapCardV2 } from "./v2/snap-view.js";
|
|
6
6
|
// ─── SnapCard ────────────────────────────────────────
|
|
7
|
-
export function SnapCard({ snap, handlers, loading = false, appearance = "dark", maxWidth = 480, showOverflowWarning = false, onValidationError, validationErrorFallback, }) {
|
|
7
|
+
export function SnapCard({ snap, handlers, loading = false, appearance = "dark", maxWidth = 480, showOverflowWarning = false, onValidationError, validationErrorFallback, actionError, }) {
|
|
8
8
|
if (snap.version === SPEC_VERSION_2) {
|
|
9
|
-
return (_jsx(SnapCardV2, { snap: snap, handlers: handlers, loading: loading, appearance: appearance, maxWidth: maxWidth, showOverflowWarning: showOverflowWarning, onValidationError: onValidationError, validationErrorFallback: validationErrorFallback }));
|
|
9
|
+
return (_jsx(SnapCardV2, { snap: snap, handlers: handlers, loading: loading, appearance: appearance, maxWidth: maxWidth, showOverflowWarning: showOverflowWarning, onValidationError: onValidationError, validationErrorFallback: validationErrorFallback, actionError: actionError }));
|
|
10
10
|
}
|
|
11
|
-
return (_jsx(SnapCardV1, { snap: snap, handlers: handlers, loading: loading, appearance: appearance, maxWidth: maxWidth }));
|
|
11
|
+
return (_jsx(SnapCardV1, { snap: snap, handlers: handlers, loading: loading, appearance: appearance, maxWidth: maxWidth, actionError: actionError }));
|
|
12
12
|
}
|
|
@@ -5,10 +5,11 @@ export declare function SnapViewV1({ snap, handlers, loading, appearance, }: {
|
|
|
5
5
|
loading?: boolean;
|
|
6
6
|
appearance?: "light" | "dark";
|
|
7
7
|
}): import("react/jsx-runtime").JSX.Element;
|
|
8
|
-
export declare function SnapCardV1({ snap, handlers, loading, appearance, maxWidth, }: {
|
|
8
|
+
export declare function SnapCardV1({ snap, handlers, loading, appearance, maxWidth, actionError, }: {
|
|
9
9
|
snap: SnapPage;
|
|
10
10
|
handlers: SnapActionHandlers;
|
|
11
11
|
loading?: boolean;
|
|
12
12
|
appearance?: "light" | "dark";
|
|
13
13
|
maxWidth?: number;
|
|
14
|
+
actionError?: string | null;
|
|
14
15
|
}): import("react/jsx-runtime").JSX.Element;
|
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { SnapViewCore } from "../snap-view-core.js";
|
|
4
4
|
export function SnapViewV1({ snap, handlers, loading = false, appearance = "dark", }) {
|
|
5
5
|
return (_jsx(SnapViewCore, { snap: snap, handlers: handlers, loading: loading, appearance: appearance }));
|
|
6
6
|
}
|
|
7
|
-
export function SnapCardV1({ snap, handlers, loading = false, appearance = "dark", maxWidth = 480, }) {
|
|
8
|
-
return (
|
|
7
|
+
export function SnapCardV1({ snap, handlers, loading = false, appearance = "dark", maxWidth = 480, actionError, }) {
|
|
8
|
+
return (_jsxs("div", { style: { position: "relative", width: "100%", maxWidth }, children: [_jsx(SnapViewV1, { snap: snap, handlers: handlers, loading: loading, appearance: appearance }), actionError && (_jsx("div", { style: {
|
|
9
|
+
padding: "8px 12px",
|
|
10
|
+
fontSize: 13,
|
|
11
|
+
color: appearance === "dark"
|
|
12
|
+
? "rgba(255,100,100,0.9)"
|
|
13
|
+
: "rgba(200,0,0,0.8)",
|
|
14
|
+
}, children: actionError }))] }));
|
|
9
15
|
}
|
|
@@ -9,7 +9,7 @@ export declare function SnapViewV2({ snap, handlers, loading, appearance, onVali
|
|
|
9
9
|
onValidationError?: (result: ValidationResult) => void;
|
|
10
10
|
validationErrorFallback?: ReactNode;
|
|
11
11
|
}): import("react/jsx-runtime").JSX.Element | null;
|
|
12
|
-
export declare function SnapCardV2({ snap, handlers, loading, appearance, maxWidth, showOverflowWarning, onValidationError, validationErrorFallback, }: {
|
|
12
|
+
export declare function SnapCardV2({ snap, handlers, loading, appearance, maxWidth, showOverflowWarning, onValidationError, validationErrorFallback, actionError, }: {
|
|
13
13
|
snap: SnapPage;
|
|
14
14
|
handlers: SnapActionHandlers;
|
|
15
15
|
loading?: boolean;
|
|
@@ -18,4 +18,5 @@ export declare function SnapCardV2({ snap, handlers, loading, appearance, maxWid
|
|
|
18
18
|
showOverflowWarning?: boolean;
|
|
19
19
|
onValidationError?: (result: ValidationResult) => void;
|
|
20
20
|
validationErrorFallback?: ReactNode;
|
|
21
|
+
actionError?: string | null;
|
|
21
22
|
}): import("react/jsx-runtime").JSX.Element;
|
|
@@ -42,35 +42,42 @@ export function SnapViewV2({ snap, handlers, loading = false, appearance = "dark
|
|
|
42
42
|
return (_jsx(SnapViewCore, { snap: snap, handlers: handlers, loading: loading, appearance: appearance }));
|
|
43
43
|
}
|
|
44
44
|
// ─── SnapCardV2 ──────────────────────────────────────
|
|
45
|
-
export function SnapCardV2({ snap, handlers, loading = false, appearance = "dark", maxWidth = 480, showOverflowWarning = false, onValidationError, validationErrorFallback, }) {
|
|
45
|
+
export function SnapCardV2({ snap, handlers, loading = false, appearance = "dark", maxWidth = 480, showOverflowWarning = false, onValidationError, validationErrorFallback, actionError, }) {
|
|
46
46
|
const maxHeight = showOverflowWarning ? SNAP_WARNING_HEIGHT : SNAP_MAX_HEIGHT;
|
|
47
47
|
const bg = appearance === "dark" ? "rgba(0,0,0,0.85)" : "rgba(255,255,255,0.9)";
|
|
48
|
-
return (_jsxs("div", { style: {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
48
|
+
return (_jsxs(_Fragment, { children: [_jsxs("div", { style: {
|
|
49
|
+
position: "relative",
|
|
50
|
+
width: "100%",
|
|
51
|
+
maxWidth,
|
|
52
|
+
maxHeight,
|
|
53
|
+
overflow: "hidden",
|
|
54
|
+
}, children: [_jsx(SnapViewV2, { snap: snap, handlers: handlers, loading: loading, appearance: appearance, onValidationError: onValidationError, validationErrorFallback: validationErrorFallback }), showOverflowWarning && (_jsxs("div", { style: {
|
|
55
|
+
position: "absolute",
|
|
56
|
+
top: SNAP_MAX_HEIGHT,
|
|
57
|
+
left: 0,
|
|
58
|
+
right: 0,
|
|
59
|
+
bottom: 0,
|
|
60
|
+
pointerEvents: "none",
|
|
61
|
+
zIndex: 10,
|
|
62
|
+
}, children: [_jsx("div", { style: { borderTop: "1px dashed rgba(255,100,100,0.6)", position: "relative" }, children: _jsxs("span", { style: {
|
|
63
|
+
position: "absolute",
|
|
64
|
+
top: -10,
|
|
65
|
+
right: 0,
|
|
66
|
+
fontSize: 10,
|
|
67
|
+
fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace",
|
|
68
|
+
color: "rgba(255,100,100,0.7)",
|
|
69
|
+
background: bg,
|
|
70
|
+
padding: "1px 4px",
|
|
71
|
+
borderRadius: 3,
|
|
72
|
+
}, children: [SNAP_MAX_HEIGHT, "px"] }) }), _jsx("div", { style: {
|
|
73
|
+
height: "100%",
|
|
74
|
+
background: "repeating-linear-gradient(-45deg, transparent, transparent 8px, rgba(255,100,100,0.06) 8px, rgba(255,100,100,0.06) 16px)",
|
|
75
|
+
} })] }))] }), actionError && (_jsx("div", { style: {
|
|
76
|
+
maxWidth,
|
|
77
|
+
padding: "8px 12px",
|
|
78
|
+
fontSize: 13,
|
|
79
|
+
color: appearance === "dark"
|
|
80
|
+
? "rgba(255,100,100,0.9)"
|
|
81
|
+
: "rgba(200,0,0,0.8)",
|
|
82
|
+
}, children: actionError }))] }));
|
|
76
83
|
}
|
|
@@ -7,7 +7,7 @@ import { hexToRgba } from "./use-snap-palette.js";
|
|
|
7
7
|
export type { JsonValue, SnapPage, SnapActionHandlers } from "./types.js";
|
|
8
8
|
export { useSnapTheme, hexToRgba };
|
|
9
9
|
export type { SnapNativeColors };
|
|
10
|
-
export declare function SnapCard({ snap, handlers, loading, appearance, colors, borderRadius, showOverflowWarning, onValidationError, validationErrorFallback, }: {
|
|
10
|
+
export declare function SnapCard({ snap, handlers, loading, appearance, colors, borderRadius, showOverflowWarning, onValidationError, validationErrorFallback, actionError, }: {
|
|
11
11
|
snap: SnapPage;
|
|
12
12
|
handlers: SnapActionHandlers;
|
|
13
13
|
loading?: boolean;
|
|
@@ -21,4 +21,6 @@ export declare function SnapCard({ snap, handlers, loading, appearance, colors,
|
|
|
21
21
|
onValidationError?: (result: ValidationResult) => void;
|
|
22
22
|
/** Custom fallback rendered when validation fails (v2 only). */
|
|
23
23
|
validationErrorFallback?: ReactNode;
|
|
24
|
+
/** Server-side action error message to display inline. */
|
|
25
|
+
actionError?: string | null;
|
|
24
26
|
}): import("react").JSX.Element;
|
|
@@ -7,9 +7,9 @@ import { SnapCardV2 } from "./v2/snap-view.js";
|
|
|
7
7
|
// ─── Re-exports ───────────────────────────────────────
|
|
8
8
|
export { useSnapTheme, hexToRgba };
|
|
9
9
|
// ─── SnapCard (version-switching) ─────────────────────
|
|
10
|
-
export function SnapCard({ snap, handlers, loading = false, appearance = "dark", colors, borderRadius = 16, showOverflowWarning = false, onValidationError, validationErrorFallback, }) {
|
|
10
|
+
export function SnapCard({ snap, handlers, loading = false, appearance = "dark", colors, borderRadius = 16, showOverflowWarning = false, onValidationError, validationErrorFallback, actionError, }) {
|
|
11
11
|
if (snap.version === SPEC_VERSION_2) {
|
|
12
|
-
return (_jsx(SnapCardV2, { snap: snap, handlers: handlers, loading: loading, appearance: appearance, colors: colors, borderRadius: borderRadius, showOverflowWarning: showOverflowWarning, onValidationError: onValidationError, validationErrorFallback: validationErrorFallback }));
|
|
12
|
+
return (_jsx(SnapCardV2, { snap: snap, handlers: handlers, loading: loading, appearance: appearance, colors: colors, borderRadius: borderRadius, showOverflowWarning: showOverflowWarning, onValidationError: onValidationError, validationErrorFallback: validationErrorFallback, actionError: actionError }));
|
|
13
13
|
}
|
|
14
|
-
return (_jsx(SnapCardV1, { snap: snap, handlers: handlers, loading: loading, appearance: appearance, colors: colors, borderRadius: borderRadius }));
|
|
14
|
+
return (_jsx(SnapCardV1, { snap: snap, handlers: handlers, loading: loading, appearance: appearance, colors: colors, borderRadius: borderRadius, actionError: actionError }));
|
|
15
15
|
}
|
|
@@ -12,11 +12,12 @@ export declare function SnapViewV1({ snap, handlers, loading, appearance, colors
|
|
|
12
12
|
appearance?: "light" | "dark";
|
|
13
13
|
colors?: Partial<SnapNativeColors>;
|
|
14
14
|
}): import("react").JSX.Element;
|
|
15
|
-
export declare function SnapCardV1({ snap, handlers, loading, appearance, colors, borderRadius, }: {
|
|
15
|
+
export declare function SnapCardV1({ snap, handlers, loading, appearance, colors, borderRadius, actionError, }: {
|
|
16
16
|
snap: SnapPage;
|
|
17
17
|
handlers: SnapActionHandlers;
|
|
18
18
|
loading?: boolean;
|
|
19
19
|
appearance?: "light" | "dark";
|
|
20
20
|
colors?: Partial<SnapNativeColors>;
|
|
21
21
|
borderRadius?: number;
|
|
22
|
+
actionError?: string | null;
|
|
22
23
|
}): import("react").JSX.Element;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import { View, StyleSheet } from "react-native";
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { View, Text, StyleSheet } from "react-native";
|
|
3
3
|
import { SnapThemeProvider, useSnapTheme } from "../theme.js";
|
|
4
4
|
import { SnapViewCoreInner } from "../snap-view-core.js";
|
|
5
5
|
// ─── SnapViewV1 (no validation, no height limits) ────
|
|
@@ -10,22 +10,30 @@ export function SnapViewV1({ snap, handlers, loading = false, appearance = "dark
|
|
|
10
10
|
return (_jsx(SnapThemeProvider, { appearance: appearance, colors: colors, children: _jsx(SnapViewV1Inner, { snap: snap, handlers: handlers, loading: loading }) }));
|
|
11
11
|
}
|
|
12
12
|
// ─── SnapCardV1 (card frame, no height limits) ───────
|
|
13
|
-
function SnapCardV1Inner({ snap, handlers, loading = false, borderRadius, }) {
|
|
13
|
+
function SnapCardV1Inner({ snap, handlers, loading = false, borderRadius, actionError, appearance, }) {
|
|
14
14
|
const { colors } = useSnapTheme();
|
|
15
|
-
return (_jsx(View, { style: cardStyles.frameRing, children: _jsx(View, { style: [
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
15
|
+
return (_jsxs(_Fragment, { children: [_jsx(View, { style: cardStyles.frameRing, children: _jsx(View, { style: [
|
|
16
|
+
cardStyles.card,
|
|
17
|
+
{
|
|
18
|
+
borderRadius,
|
|
19
|
+
borderColor: colors.border,
|
|
20
|
+
backgroundColor: colors.surface,
|
|
21
|
+
},
|
|
22
|
+
], children: _jsx(View, { style: cardStyles.body, children: _jsx(SnapViewV1Inner, { snap: snap, handlers: handlers, loading: loading }) }) }) }), actionError && (_jsx(Text, { style: [
|
|
23
|
+
cardStyles.actionError,
|
|
24
|
+
{
|
|
25
|
+
color: appearance === "dark"
|
|
26
|
+
? "rgba(255,100,100,0.9)"
|
|
27
|
+
: "rgba(200,0,0,0.8)",
|
|
28
|
+
},
|
|
29
|
+
], children: actionError }))] }));
|
|
23
30
|
}
|
|
24
|
-
export function SnapCardV1({ snap, handlers, loading = false, appearance = "dark", colors, borderRadius = 16, }) {
|
|
25
|
-
return (_jsx(SnapThemeProvider, { appearance: appearance, colors: colors, children: _jsx(SnapCardV1Inner, { snap: snap, handlers: handlers, loading: loading, borderRadius: borderRadius }) }));
|
|
31
|
+
export function SnapCardV1({ snap, handlers, loading = false, appearance = "dark", colors, borderRadius = 16, actionError, }) {
|
|
32
|
+
return (_jsx(SnapThemeProvider, { appearance: appearance, colors: colors, children: _jsx(SnapCardV1Inner, { snap: snap, handlers: handlers, loading: loading, borderRadius: borderRadius, actionError: actionError, appearance: appearance }) }));
|
|
26
33
|
}
|
|
27
34
|
const cardStyles = StyleSheet.create({
|
|
28
35
|
frameRing: { alignSelf: "stretch" },
|
|
29
36
|
card: { overflow: "hidden", borderWidth: 1, minHeight: 120 },
|
|
30
37
|
body: { paddingHorizontal: 16, paddingVertical: 16 },
|
|
38
|
+
actionError: { paddingHorizontal: 12, paddingVertical: 8, fontSize: 13 },
|
|
31
39
|
});
|
|
@@ -18,7 +18,7 @@ export declare function SnapViewV2({ snap, handlers, loading, appearance, colors
|
|
|
18
18
|
onValidationError?: (result: ValidationResult) => void;
|
|
19
19
|
validationErrorFallback?: ReactNode;
|
|
20
20
|
}): import("react").JSX.Element;
|
|
21
|
-
export declare function SnapCardV2({ snap, handlers, loading, appearance, colors, borderRadius, showOverflowWarning, onValidationError, validationErrorFallback, }: {
|
|
21
|
+
export declare function SnapCardV2({ snap, handlers, loading, appearance, colors, borderRadius, showOverflowWarning, onValidationError, validationErrorFallback, actionError, }: {
|
|
22
22
|
snap: SnapPage;
|
|
23
23
|
handlers: SnapActionHandlers;
|
|
24
24
|
loading?: boolean;
|
|
@@ -28,4 +28,5 @@ export declare function SnapCardV2({ snap, handlers, loading, appearance, colors
|
|
|
28
28
|
showOverflowWarning?: boolean;
|
|
29
29
|
onValidationError?: (result: ValidationResult) => void;
|
|
30
30
|
validationErrorFallback?: ReactNode;
|
|
31
|
+
actionError?: string | null;
|
|
31
32
|
}): import("react").JSX.Element;
|
|
@@ -50,26 +50,34 @@ export function SnapViewV2({ snap, handlers, loading = false, appearance = "dark
|
|
|
50
50
|
return (_jsx(SnapThemeProvider, { appearance: appearance, colors: colors, children: _jsx(SnapViewV2Inner, { snap: snap, handlers: handlers, loading: loading, onValidationError: onValidationError, validationErrorFallback: validationErrorFallback }) }));
|
|
51
51
|
}
|
|
52
52
|
// ─── SnapCardV2 (card frame + height limits) ─────────
|
|
53
|
-
function SnapCardV2Inner({ snap, handlers, loading, borderRadius, showOverflowWarning, onValidationError, validationErrorFallback, }) {
|
|
53
|
+
function SnapCardV2Inner({ snap, handlers, loading, borderRadius, showOverflowWarning, onValidationError, validationErrorFallback, actionError, appearance, }) {
|
|
54
54
|
const { colors } = useSnapTheme();
|
|
55
55
|
const maxHeight = showOverflowWarning ? SNAP_WARNING_HEIGHT : SNAP_MAX_HEIGHT;
|
|
56
|
-
return (_jsx(View, { style: cardStyles.frameRing, children: _jsxs(View, { style: [
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
56
|
+
return (_jsxs(_Fragment, { children: [_jsx(View, { style: cardStyles.frameRing, children: _jsxs(View, { style: [
|
|
57
|
+
cardStyles.card,
|
|
58
|
+
{
|
|
59
|
+
borderRadius,
|
|
60
|
+
maxHeight,
|
|
61
|
+
borderColor: colors.border,
|
|
62
|
+
backgroundColor: colors.surface,
|
|
63
|
+
},
|
|
64
|
+
], children: [_jsx(View, { style: cardStyles.body, children: _jsx(SnapViewV2Inner, { snap: snap, handlers: handlers, loading: loading, onValidationError: onValidationError, validationErrorFallback: validationErrorFallback }) }), showOverflowWarning && (_jsxs(View, { style: cardStyles.warningOverlay, children: [_jsx(View, { style: cardStyles.warningLine }), _jsx(View, { style: cardStyles.warningLabel, children: _jsxs(Text, { style: cardStyles.warningLabelText, children: [SNAP_MAX_HEIGHT, "px"] }) })] }))] }) }), actionError && (_jsx(Text, { style: [
|
|
65
|
+
cardStyles.actionError,
|
|
66
|
+
{
|
|
67
|
+
color: appearance === "dark"
|
|
68
|
+
? "rgba(255,100,100,0.9)"
|
|
69
|
+
: "rgba(200,0,0,0.8)",
|
|
70
|
+
},
|
|
71
|
+
], children: actionError }))] }));
|
|
65
72
|
}
|
|
66
|
-
export function SnapCardV2({ snap, handlers, loading = false, appearance = "dark", colors, borderRadius = 16, showOverflowWarning = false, onValidationError, validationErrorFallback, }) {
|
|
67
|
-
return (_jsx(SnapThemeProvider, { appearance: appearance, colors: colors, children: _jsx(SnapCardV2Inner, { snap: snap, handlers: handlers, loading: loading, borderRadius: borderRadius, showOverflowWarning: showOverflowWarning, onValidationError: onValidationError, validationErrorFallback: validationErrorFallback }) }));
|
|
73
|
+
export function SnapCardV2({ snap, handlers, loading = false, appearance = "dark", colors, borderRadius = 16, showOverflowWarning = false, onValidationError, validationErrorFallback, actionError, }) {
|
|
74
|
+
return (_jsx(SnapThemeProvider, { appearance: appearance, colors: colors, children: _jsx(SnapCardV2Inner, { snap: snap, handlers: handlers, loading: loading, borderRadius: borderRadius, showOverflowWarning: showOverflowWarning, onValidationError: onValidationError, validationErrorFallback: validationErrorFallback, actionError: actionError, appearance: appearance }) }));
|
|
68
75
|
}
|
|
69
76
|
const cardStyles = StyleSheet.create({
|
|
70
77
|
frameRing: { alignSelf: "stretch" },
|
|
71
78
|
card: { overflow: "hidden", borderWidth: 1, minHeight: 120 },
|
|
72
79
|
body: { paddingHorizontal: 16, paddingVertical: 16 },
|
|
80
|
+
actionError: { paddingHorizontal: 12, paddingVertical: 8, fontSize: 13 },
|
|
73
81
|
warningOverlay: {
|
|
74
82
|
position: "absolute",
|
|
75
83
|
top: SNAP_MAX_HEIGHT,
|
package/package.json
CHANGED
package/src/react/index.tsx
CHANGED
|
@@ -56,6 +56,7 @@ export function SnapCard({
|
|
|
56
56
|
showOverflowWarning = false,
|
|
57
57
|
onValidationError,
|
|
58
58
|
validationErrorFallback,
|
|
59
|
+
actionError,
|
|
59
60
|
}: {
|
|
60
61
|
snap: SnapPage;
|
|
61
62
|
handlers: SnapActionHandlers;
|
|
@@ -66,6 +67,8 @@ export function SnapCard({
|
|
|
66
67
|
showOverflowWarning?: boolean;
|
|
67
68
|
onValidationError?: (result: ValidationResult) => void;
|
|
68
69
|
validationErrorFallback?: ReactNode;
|
|
70
|
+
/** Server-side action error message to display inline. */
|
|
71
|
+
actionError?: string | null;
|
|
69
72
|
}) {
|
|
70
73
|
if (snap.version === SPEC_VERSION_2) {
|
|
71
74
|
return (
|
|
@@ -78,6 +81,7 @@ export function SnapCard({
|
|
|
78
81
|
showOverflowWarning={showOverflowWarning}
|
|
79
82
|
onValidationError={onValidationError}
|
|
80
83
|
validationErrorFallback={validationErrorFallback}
|
|
84
|
+
actionError={actionError}
|
|
81
85
|
/>
|
|
82
86
|
);
|
|
83
87
|
}
|
|
@@ -89,6 +93,7 @@ export function SnapCard({
|
|
|
89
93
|
loading={loading}
|
|
90
94
|
appearance={appearance}
|
|
91
95
|
maxWidth={maxWidth}
|
|
96
|
+
actionError={actionError}
|
|
92
97
|
/>
|
|
93
98
|
);
|
|
94
99
|
}
|
|
@@ -30,12 +30,14 @@ export function SnapCardV1({
|
|
|
30
30
|
loading = false,
|
|
31
31
|
appearance = "dark",
|
|
32
32
|
maxWidth = 480,
|
|
33
|
+
actionError,
|
|
33
34
|
}: {
|
|
34
35
|
snap: SnapPage;
|
|
35
36
|
handlers: SnapActionHandlers;
|
|
36
37
|
loading?: boolean;
|
|
37
38
|
appearance?: "light" | "dark";
|
|
38
39
|
maxWidth?: number;
|
|
40
|
+
actionError?: string | null;
|
|
39
41
|
}) {
|
|
40
42
|
return (
|
|
41
43
|
<div style={{ position: "relative", width: "100%", maxWidth }}>
|
|
@@ -45,6 +47,20 @@ export function SnapCardV1({
|
|
|
45
47
|
loading={loading}
|
|
46
48
|
appearance={appearance}
|
|
47
49
|
/>
|
|
50
|
+
{actionError && (
|
|
51
|
+
<div
|
|
52
|
+
style={{
|
|
53
|
+
padding: "8px 12px",
|
|
54
|
+
fontSize: 13,
|
|
55
|
+
color:
|
|
56
|
+
appearance === "dark"
|
|
57
|
+
? "rgba(255,100,100,0.9)"
|
|
58
|
+
: "rgba(200,0,0,0.8)",
|
|
59
|
+
}}
|
|
60
|
+
>
|
|
61
|
+
{actionError}
|
|
62
|
+
</div>
|
|
63
|
+
)}
|
|
48
64
|
</div>
|
|
49
65
|
);
|
|
50
66
|
}
|
|
@@ -94,6 +94,7 @@ export function SnapCardV2({
|
|
|
94
94
|
showOverflowWarning = false,
|
|
95
95
|
onValidationError,
|
|
96
96
|
validationErrorFallback,
|
|
97
|
+
actionError,
|
|
97
98
|
}: {
|
|
98
99
|
snap: SnapPage;
|
|
99
100
|
handlers: SnapActionHandlers;
|
|
@@ -103,11 +104,13 @@ export function SnapCardV2({
|
|
|
103
104
|
showOverflowWarning?: boolean;
|
|
104
105
|
onValidationError?: (result: ValidationResult) => void;
|
|
105
106
|
validationErrorFallback?: ReactNode;
|
|
107
|
+
actionError?: string | null;
|
|
106
108
|
}) {
|
|
107
109
|
const maxHeight = showOverflowWarning ? SNAP_WARNING_HEIGHT : SNAP_MAX_HEIGHT;
|
|
108
110
|
const bg = appearance === "dark" ? "rgba(0,0,0,0.85)" : "rgba(255,255,255,0.9)";
|
|
109
111
|
|
|
110
112
|
return (
|
|
113
|
+
<>
|
|
111
114
|
<div
|
|
112
115
|
style={{
|
|
113
116
|
position: "relative",
|
|
@@ -164,5 +167,21 @@ export function SnapCardV2({
|
|
|
164
167
|
</div>
|
|
165
168
|
)}
|
|
166
169
|
</div>
|
|
170
|
+
{actionError && (
|
|
171
|
+
<div
|
|
172
|
+
style={{
|
|
173
|
+
maxWidth,
|
|
174
|
+
padding: "8px 12px",
|
|
175
|
+
fontSize: 13,
|
|
176
|
+
color:
|
|
177
|
+
appearance === "dark"
|
|
178
|
+
? "rgba(255,100,100,0.9)"
|
|
179
|
+
: "rgba(200,0,0,0.8)",
|
|
180
|
+
}}
|
|
181
|
+
>
|
|
182
|
+
{actionError}
|
|
183
|
+
</div>
|
|
184
|
+
)}
|
|
185
|
+
</>
|
|
167
186
|
);
|
|
168
187
|
}
|
|
@@ -29,6 +29,7 @@ export function SnapCard({
|
|
|
29
29
|
showOverflowWarning = false,
|
|
30
30
|
onValidationError,
|
|
31
31
|
validationErrorFallback,
|
|
32
|
+
actionError,
|
|
32
33
|
}: {
|
|
33
34
|
snap: SnapPage;
|
|
34
35
|
handlers: SnapActionHandlers;
|
|
@@ -43,6 +44,8 @@ export function SnapCard({
|
|
|
43
44
|
onValidationError?: (result: ValidationResult) => void;
|
|
44
45
|
/** Custom fallback rendered when validation fails (v2 only). */
|
|
45
46
|
validationErrorFallback?: ReactNode;
|
|
47
|
+
/** Server-side action error message to display inline. */
|
|
48
|
+
actionError?: string | null;
|
|
46
49
|
}) {
|
|
47
50
|
if (snap.version === SPEC_VERSION_2) {
|
|
48
51
|
return (
|
|
@@ -56,6 +59,7 @@ export function SnapCard({
|
|
|
56
59
|
showOverflowWarning={showOverflowWarning}
|
|
57
60
|
onValidationError={onValidationError}
|
|
58
61
|
validationErrorFallback={validationErrorFallback}
|
|
62
|
+
actionError={actionError}
|
|
59
63
|
/>
|
|
60
64
|
);
|
|
61
65
|
}
|
|
@@ -68,6 +72,7 @@ export function SnapCard({
|
|
|
68
72
|
appearance={appearance}
|
|
69
73
|
colors={colors}
|
|
70
74
|
borderRadius={borderRadius}
|
|
75
|
+
actionError={actionError}
|
|
71
76
|
/>
|
|
72
77
|
);
|
|
73
78
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { View, StyleSheet } from "react-native";
|
|
1
|
+
import { View, Text, StyleSheet } from "react-native";
|
|
2
2
|
import { SnapThemeProvider, useSnapTheme, type SnapNativeColors } from "../theme";
|
|
3
3
|
import { SnapViewCoreInner } from "../snap-view-core";
|
|
4
4
|
import type { SnapPage, SnapActionHandlers } from "../types";
|
|
@@ -46,31 +46,52 @@ function SnapCardV1Inner({
|
|
|
46
46
|
handlers,
|
|
47
47
|
loading = false,
|
|
48
48
|
borderRadius,
|
|
49
|
+
actionError,
|
|
50
|
+
appearance,
|
|
49
51
|
}: {
|
|
50
52
|
snap: SnapPage;
|
|
51
53
|
handlers: SnapActionHandlers;
|
|
52
54
|
loading?: boolean;
|
|
53
55
|
borderRadius: number;
|
|
56
|
+
actionError?: string | null;
|
|
57
|
+
appearance: "light" | "dark";
|
|
54
58
|
}) {
|
|
55
59
|
const { colors } = useSnapTheme();
|
|
56
60
|
|
|
57
61
|
return (
|
|
58
|
-
|
|
59
|
-
<View
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
<
|
|
62
|
+
<>
|
|
63
|
+
<View style={cardStyles.frameRing}>
|
|
64
|
+
<View
|
|
65
|
+
style={[
|
|
66
|
+
cardStyles.card,
|
|
67
|
+
{
|
|
68
|
+
borderRadius,
|
|
69
|
+
borderColor: colors.border,
|
|
70
|
+
backgroundColor: colors.surface,
|
|
71
|
+
},
|
|
72
|
+
]}
|
|
73
|
+
>
|
|
74
|
+
<View style={cardStyles.body}>
|
|
75
|
+
<SnapViewV1Inner snap={snap} handlers={handlers} loading={loading} />
|
|
76
|
+
</View>
|
|
71
77
|
</View>
|
|
72
78
|
</View>
|
|
73
|
-
|
|
79
|
+
{actionError && (
|
|
80
|
+
<Text
|
|
81
|
+
style={[
|
|
82
|
+
cardStyles.actionError,
|
|
83
|
+
{
|
|
84
|
+
color:
|
|
85
|
+
appearance === "dark"
|
|
86
|
+
? "rgba(255,100,100,0.9)"
|
|
87
|
+
: "rgba(200,0,0,0.8)",
|
|
88
|
+
},
|
|
89
|
+
]}
|
|
90
|
+
>
|
|
91
|
+
{actionError}
|
|
92
|
+
</Text>
|
|
93
|
+
)}
|
|
94
|
+
</>
|
|
74
95
|
);
|
|
75
96
|
}
|
|
76
97
|
|
|
@@ -81,6 +102,7 @@ export function SnapCardV1({
|
|
|
81
102
|
appearance = "dark",
|
|
82
103
|
colors,
|
|
83
104
|
borderRadius = 16,
|
|
105
|
+
actionError,
|
|
84
106
|
}: {
|
|
85
107
|
snap: SnapPage;
|
|
86
108
|
handlers: SnapActionHandlers;
|
|
@@ -88,6 +110,7 @@ export function SnapCardV1({
|
|
|
88
110
|
appearance?: "light" | "dark";
|
|
89
111
|
colors?: Partial<SnapNativeColors>;
|
|
90
112
|
borderRadius?: number;
|
|
113
|
+
actionError?: string | null;
|
|
91
114
|
}) {
|
|
92
115
|
return (
|
|
93
116
|
<SnapThemeProvider appearance={appearance} colors={colors}>
|
|
@@ -96,6 +119,8 @@ export function SnapCardV1({
|
|
|
96
119
|
handlers={handlers}
|
|
97
120
|
loading={loading}
|
|
98
121
|
borderRadius={borderRadius}
|
|
122
|
+
actionError={actionError}
|
|
123
|
+
appearance={appearance}
|
|
99
124
|
/>
|
|
100
125
|
</SnapThemeProvider>
|
|
101
126
|
);
|
|
@@ -105,4 +130,5 @@ const cardStyles = StyleSheet.create({
|
|
|
105
130
|
frameRing: { alignSelf: "stretch" },
|
|
106
131
|
card: { overflow: "hidden", borderWidth: 1, minHeight: 120 },
|
|
107
132
|
body: { paddingHorizontal: 16, paddingVertical: 16 },
|
|
133
|
+
actionError: { paddingHorizontal: 12, paddingVertical: 8, fontSize: 13 },
|
|
108
134
|
});
|
|
@@ -121,6 +121,8 @@ function SnapCardV2Inner({
|
|
|
121
121
|
showOverflowWarning,
|
|
122
122
|
onValidationError,
|
|
123
123
|
validationErrorFallback,
|
|
124
|
+
actionError,
|
|
125
|
+
appearance,
|
|
124
126
|
}: {
|
|
125
127
|
snap: SnapPage;
|
|
126
128
|
handlers: SnapActionHandlers;
|
|
@@ -129,42 +131,61 @@ function SnapCardV2Inner({
|
|
|
129
131
|
showOverflowWarning: boolean;
|
|
130
132
|
onValidationError?: (result: ValidationResult) => void;
|
|
131
133
|
validationErrorFallback?: ReactNode;
|
|
134
|
+
actionError?: string | null;
|
|
135
|
+
appearance: "light" | "dark";
|
|
132
136
|
}) {
|
|
133
137
|
const { colors } = useSnapTheme();
|
|
134
138
|
const maxHeight = showOverflowWarning ? SNAP_WARNING_HEIGHT : SNAP_MAX_HEIGHT;
|
|
135
139
|
|
|
136
140
|
return (
|
|
137
|
-
|
|
138
|
-
<View
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
<
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
{showOverflowWarning && (
|
|
159
|
-
<View style={cardStyles.warningOverlay}>
|
|
160
|
-
<View style={cardStyles.warningLine} />
|
|
161
|
-
<View style={cardStyles.warningLabel}>
|
|
162
|
-
<Text style={cardStyles.warningLabelText}>{SNAP_MAX_HEIGHT}px</Text>
|
|
163
|
-
</View>
|
|
141
|
+
<>
|
|
142
|
+
<View style={cardStyles.frameRing}>
|
|
143
|
+
<View
|
|
144
|
+
style={[
|
|
145
|
+
cardStyles.card,
|
|
146
|
+
{
|
|
147
|
+
borderRadius,
|
|
148
|
+
maxHeight,
|
|
149
|
+
borderColor: colors.border,
|
|
150
|
+
backgroundColor: colors.surface,
|
|
151
|
+
},
|
|
152
|
+
]}
|
|
153
|
+
>
|
|
154
|
+
<View style={cardStyles.body}>
|
|
155
|
+
<SnapViewV2Inner
|
|
156
|
+
snap={snap}
|
|
157
|
+
handlers={handlers}
|
|
158
|
+
loading={loading}
|
|
159
|
+
onValidationError={onValidationError}
|
|
160
|
+
validationErrorFallback={validationErrorFallback}
|
|
161
|
+
/>
|
|
164
162
|
</View>
|
|
165
|
-
|
|
163
|
+
{showOverflowWarning && (
|
|
164
|
+
<View style={cardStyles.warningOverlay}>
|
|
165
|
+
<View style={cardStyles.warningLine} />
|
|
166
|
+
<View style={cardStyles.warningLabel}>
|
|
167
|
+
<Text style={cardStyles.warningLabelText}>{SNAP_MAX_HEIGHT}px</Text>
|
|
168
|
+
</View>
|
|
169
|
+
</View>
|
|
170
|
+
)}
|
|
171
|
+
</View>
|
|
166
172
|
</View>
|
|
167
|
-
|
|
173
|
+
{actionError && (
|
|
174
|
+
<Text
|
|
175
|
+
style={[
|
|
176
|
+
cardStyles.actionError,
|
|
177
|
+
{
|
|
178
|
+
color:
|
|
179
|
+
appearance === "dark"
|
|
180
|
+
? "rgba(255,100,100,0.9)"
|
|
181
|
+
: "rgba(200,0,0,0.8)",
|
|
182
|
+
},
|
|
183
|
+
]}
|
|
184
|
+
>
|
|
185
|
+
{actionError}
|
|
186
|
+
</Text>
|
|
187
|
+
)}
|
|
188
|
+
</>
|
|
168
189
|
);
|
|
169
190
|
}
|
|
170
191
|
|
|
@@ -178,6 +199,7 @@ export function SnapCardV2({
|
|
|
178
199
|
showOverflowWarning = false,
|
|
179
200
|
onValidationError,
|
|
180
201
|
validationErrorFallback,
|
|
202
|
+
actionError,
|
|
181
203
|
}: {
|
|
182
204
|
snap: SnapPage;
|
|
183
205
|
handlers: SnapActionHandlers;
|
|
@@ -188,6 +210,7 @@ export function SnapCardV2({
|
|
|
188
210
|
showOverflowWarning?: boolean;
|
|
189
211
|
onValidationError?: (result: ValidationResult) => void;
|
|
190
212
|
validationErrorFallback?: ReactNode;
|
|
213
|
+
actionError?: string | null;
|
|
191
214
|
}) {
|
|
192
215
|
return (
|
|
193
216
|
<SnapThemeProvider appearance={appearance} colors={colors}>
|
|
@@ -199,6 +222,8 @@ export function SnapCardV2({
|
|
|
199
222
|
showOverflowWarning={showOverflowWarning}
|
|
200
223
|
onValidationError={onValidationError}
|
|
201
224
|
validationErrorFallback={validationErrorFallback}
|
|
225
|
+
actionError={actionError}
|
|
226
|
+
appearance={appearance}
|
|
202
227
|
/>
|
|
203
228
|
</SnapThemeProvider>
|
|
204
229
|
);
|
|
@@ -208,6 +233,7 @@ const cardStyles = StyleSheet.create({
|
|
|
208
233
|
frameRing: { alignSelf: "stretch" },
|
|
209
234
|
card: { overflow: "hidden", borderWidth: 1, minHeight: 120 },
|
|
210
235
|
body: { paddingHorizontal: 16, paddingVertical: 16 },
|
|
236
|
+
actionError: { paddingHorizontal: 12, paddingVertical: 8, fontSize: 13 },
|
|
211
237
|
warningOverlay: {
|
|
212
238
|
position: "absolute",
|
|
213
239
|
top: SNAP_MAX_HEIGHT,
|