@farcaster/snap 1.21.0 → 1.22.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.
@@ -1,6 +1,6 @@
1
1
  export declare const SPEC_VERSION_1: "1.0";
2
2
  export declare const SPEC_VERSION_2: "2.0";
3
- export declare const SPEC_VERSION: "1.0";
3
+ export declare const SPEC_VERSION: "2.0";
4
4
  export declare const SUPPORTED_SPEC_VERSIONS: readonly ["1.0", "2.0"];
5
5
  export type SpecVersion = (typeof SUPPORTED_SPEC_VERSIONS)[number];
6
6
  export declare const MEDIA_TYPE: "application/vnd.farcaster.snap+json";
package/dist/constants.js CHANGED
@@ -1,6 +1,6 @@
1
1
  export const SPEC_VERSION_1 = "1.0";
2
2
  export const SPEC_VERSION_2 = "2.0";
3
- export const SPEC_VERSION = SPEC_VERSION_1;
3
+ export const SPEC_VERSION = SPEC_VERSION_2;
4
4
  export const SUPPORTED_SPEC_VERSIONS = [SPEC_VERSION_1, SPEC_VERSION_2];
5
5
  export const MEDIA_TYPE = "application/vnd.farcaster.snap+json";
6
6
  export const EFFECT_VALUES = ["confetti"];
@@ -11,6 +11,7 @@ export function SnapCellGrid({ element: { props }, }) {
11
11
  const cols = Number(props.cols ?? 2);
12
12
  const rows = Number(props.rows ?? 2);
13
13
  const cells = Array.isArray(props.cells) ? props.cells : [];
14
+ const rowHeight = typeof props.rowHeight === "number" ? props.rowHeight : 28;
14
15
  const gap = String(props.gap ?? "sm");
15
16
  const gapMap = { none: 0, sm: 1, md: 2, lg: 4 };
16
17
  const gapPx = gapMap[gap] ?? 1;
@@ -60,10 +61,10 @@ export function SnapCellGrid({ element: { props }, }) {
60
61
  const bg = cell?.color ? hex(cell.color) : "transparent";
61
62
  const cellContent = cell?.content ? (_jsx(Text, { style: [styles.cellText, { color: colors.textPrimary }], children: cell.content })) : null;
62
63
  // Two-tone ring: outer View with contrasting border, inner View with inverse border
63
- const cellView = selected ? (_jsx(View, { style: [styles.cell, { borderWidth: 1, borderColor: ringOuter, borderRadius: 4 }], children: _jsx(View, { style: [
64
+ const cellView = selected ? (_jsx(View, { style: [styles.cell, { height: rowHeight, borderWidth: 1, borderColor: ringOuter, borderRadius: 4 }], children: _jsx(View, { style: [
64
65
  styles.innerCell,
65
66
  { backgroundColor: bg, borderWidth: 1, borderColor: ringInner, borderRadius: 3 },
66
- ], children: cellContent }) })) : (_jsx(View, { style: [styles.cell, { backgroundColor: bg }], children: cellContent }));
67
+ ], children: cellContent }) })) : (_jsx(View, { style: [styles.cell, { height: rowHeight, backgroundColor: bg }], children: cellContent }));
67
68
  rowCells.push(interactive ? (_jsx(Pressable, { onPress: () => handleTap(r, c), style: styles.cellWrap, children: cellView }, `${r}-${c}`)) : (_jsx(View, { style: styles.cellWrap, children: cellView }, `${r}-${c}`)));
68
69
  }
69
70
  rowEls.push(_jsx(View, { style: [styles.gridRow, { gap: gapPx }], children: rowCells }, r));
@@ -78,16 +79,13 @@ const styles = StyleSheet.create({
78
79
  gridRow: { flexDirection: "row" },
79
80
  cellWrap: { flex: 1 },
80
81
  cell: {
81
- flex: 1,
82
- minHeight: 28,
83
82
  borderRadius: 4,
84
83
  alignItems: "center",
85
84
  justifyContent: "center",
86
85
  },
87
86
  innerCell: {
88
- flex: 1,
89
87
  width: "100%",
90
- minHeight: 26,
88
+ height: "100%",
91
89
  alignItems: "center",
92
90
  justifyContent: "center",
93
91
  },
@@ -1,5 +1,5 @@
1
1
  import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useEffect, useMemo } from "react";
2
+ import { useEffect, useMemo, useState } from "react";
3
3
  import { Platform, StyleSheet, Text, View } from "react-native";
4
4
  import { SnapThemeProvider, useSnapTheme } from "../theme.js";
5
5
  import { SnapViewCoreInner } from "../snap-view-core.js";
@@ -52,20 +52,21 @@ export function SnapViewV2({ snap, handlers, loading = false, appearance = "dark
52
52
  // ─── SnapCardV2 (card frame + height limits) ─────────
53
53
  function SnapCardV2Inner({ snap, handlers, loading, borderRadius, showOverflowWarning, onValidationError, validationErrorFallback, actionError, appearance, plain, }) {
54
54
  const { colors } = useSnapTheme();
55
- const clipHeight = showOverflowWarning ? undefined : SNAP_MAX_HEIGHT;
55
+ const [contentHeight, setContentHeight] = useState(0);
56
56
  const content = (_jsx(SnapViewV2Inner, { snap: snap, handlers: handlers, loading: loading, onValidationError: onValidationError, validationErrorFallback: validationErrorFallback }));
57
57
  if (plain) {
58
58
  return content;
59
59
  }
60
+ const overflowAmount = showOverflowWarning ? contentHeight - SNAP_MAX_HEIGHT : 0;
60
61
  return (_jsxs(_Fragment, { children: [_jsxs(View, { style: {
61
62
  borderRadius,
62
63
  borderWidth: 1,
63
64
  borderColor: colors.border,
64
65
  backgroundColor: colors.surface,
65
- maxHeight: clipHeight,
66
+ maxHeight: showOverflowWarning ? undefined : SNAP_MAX_HEIGHT,
66
67
  overflow: "hidden",
67
68
  minHeight: 120,
68
- }, children: [_jsx(View, { style: { paddingHorizontal: 16, paddingVertical: 16 }, children: content }), showOverflowWarning && (_jsxs(View, { style: { position: "absolute", top: SNAP_MAX_HEIGHT, left: 0, right: 0, bottom: 0, zIndex: 10, pointerEvents: "none" }, children: [_jsx(View, { style: { height: 1, borderTopWidth: 1, borderStyle: "dashed", borderColor: "rgba(255,100,100,0.6)" } }), _jsx(View, { style: { position: "absolute", top: -10, right: 4, backgroundColor: "rgba(0,0,0,0.7)", paddingHorizontal: 4, paddingVertical: 1, borderRadius: 3 }, children: _jsxs(Text, { style: { fontSize: 10, color: "rgba(255,100,100,0.7)", fontFamily: Platform.select({ ios: "Menlo", default: "monospace" }) }, children: [SNAP_MAX_HEIGHT, "px"] }) }), _jsx(View, { style: { flex: 1, backgroundColor: "rgba(255,50,50,0.15)" } })] }))] }), actionError && (_jsx(Text, { style: {
69
+ }, children: [_jsx(View, { collapsable: false, onLayout: (e) => setContentHeight(Math.round(e.nativeEvent.layout.height)), style: { paddingHorizontal: 16, paddingVertical: 16 }, children: content }), showOverflowWarning && contentHeight > SNAP_MAX_HEIGHT && (_jsxs(View, { style: { position: "absolute", top: SNAP_MAX_HEIGHT, left: 0, right: 0, height: overflowAmount, zIndex: 10, pointerEvents: "none" }, children: [_jsx(View, { style: { height: 1, borderTopWidth: 1, borderStyle: "dashed", borderColor: "rgba(255,100,100,0.6)" } }), _jsx(View, { style: { position: "absolute", top: -10, right: 4, backgroundColor: "rgba(0,0,0,0.7)", paddingHorizontal: 4, paddingVertical: 1, borderRadius: 3 }, children: _jsxs(Text, { style: { fontSize: 10, color: "rgba(255,100,100,0.7)", fontFamily: Platform.select({ ios: "Menlo", default: "monospace" }) }, children: [SNAP_MAX_HEIGHT, "px"] }) }), _jsx(View, { style: { flex: 1, backgroundColor: "rgba(255,50,50,0.15)" } })] }))] }), actionError && (_jsx(Text, { style: {
69
70
  paddingHorizontal: 12,
70
71
  paddingVertical: 8,
71
72
  fontSize: 13,
package/llms.txt CHANGED
@@ -8,7 +8,7 @@ Every snap handler returns a `SnapResponse`:
8
8
 
9
9
  ```json
10
10
  {
11
- "version": "1.0",
11
+ "version": "2.0",
12
12
  "theme": { "accent": "purple" },
13
13
  "effects": ["confetti"],
14
14
  "ui": {
@@ -26,7 +26,7 @@ Every snap handler returns a `SnapResponse`:
26
26
  }
27
27
  ```
28
28
 
29
- Top-level fields: `version` (required, `"1.0"`), `theme` (optional, `{ accent: PaletteColor }`), `effects` (optional, `["confetti"]`), `ui` (required).
29
+ Top-level fields: `version` (required, `"1.0"` or `"2.0"`), `theme` (optional, `{ accent: PaletteColor }`), `effects` (optional, `["confetti"]`), `ui` (required).
30
30
 
31
31
  `ui.root` is the ID of the root element. `ui.elements` is a flat map of element ID to element definition.
32
32
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@farcaster/snap",
3
- "version": "1.21.0",
3
+ "version": "1.22.0",
4
4
  "description": "Farcaster Snaps 🫰",
5
5
  "repository": {
6
6
  "type": "git",
package/src/constants.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  export const SPEC_VERSION_1 = "1.0" as const;
2
2
  export const SPEC_VERSION_2 = "2.0" as const;
3
- export const SPEC_VERSION = SPEC_VERSION_1;
3
+ export const SPEC_VERSION = SPEC_VERSION_2;
4
4
  export const SUPPORTED_SPEC_VERSIONS = [SPEC_VERSION_1, SPEC_VERSION_2] as const;
5
5
  export type SpecVersion = (typeof SUPPORTED_SPEC_VERSIONS)[number];
6
6
 
@@ -14,6 +14,7 @@ export function SnapCellGrid({
14
14
  const cols = Number(props.cols ?? 2);
15
15
  const rows = Number(props.rows ?? 2);
16
16
  const cells = Array.isArray(props.cells) ? props.cells : [];
17
+ const rowHeight = typeof props.rowHeight === "number" ? props.rowHeight : 28;
17
18
  const gap = String(props.gap ?? "sm");
18
19
  const gapMap: Record<string, number> = { none: 0, sm: 1, md: 2, lg: 4 };
19
20
  const gapPx = gapMap[gap] ?? 1;
@@ -74,7 +75,7 @@ export function SnapCellGrid({
74
75
 
75
76
  // Two-tone ring: outer View with contrasting border, inner View with inverse border
76
77
  const cellView = selected ? (
77
- <View style={[styles.cell, { borderWidth: 1, borderColor: ringOuter, borderRadius: 4 }]}>
78
+ <View style={[styles.cell, { height: rowHeight, borderWidth: 1, borderColor: ringOuter, borderRadius: 4 }]}>
78
79
  <View
79
80
  style={[
80
81
  styles.innerCell,
@@ -85,7 +86,7 @@ export function SnapCellGrid({
85
86
  </View>
86
87
  </View>
87
88
  ) : (
88
- <View style={[styles.cell, { backgroundColor: bg }]}>
89
+ <View style={[styles.cell, { height: rowHeight, backgroundColor: bg }]}>
89
90
  {cellContent}
90
91
  </View>
91
92
  );
@@ -134,16 +135,13 @@ const styles = StyleSheet.create({
134
135
  gridRow: { flexDirection: "row" },
135
136
  cellWrap: { flex: 1 },
136
137
  cell: {
137
- flex: 1,
138
- minHeight: 28,
139
138
  borderRadius: 4,
140
139
  alignItems: "center",
141
140
  justifyContent: "center",
142
141
  },
143
142
  innerCell: {
144
- flex: 1,
145
143
  width: "100%",
146
- minHeight: 26,
144
+ height: "100%",
147
145
  alignItems: "center",
148
146
  justifyContent: "center",
149
147
  },
@@ -1,5 +1,5 @@
1
1
  import type { ReactNode } from "react";
2
- import { useEffect, useMemo } from "react";
2
+ import { useEffect, useMemo, useState } from "react";
3
3
  import { Platform, StyleSheet, Text, View } from "react-native";
4
4
  import { SnapThemeProvider, useSnapTheme, type SnapNativeColors } from "../theme";
5
5
  import { SnapViewCoreInner } from "../snap-view-core";
@@ -137,7 +137,7 @@ function SnapCardV2Inner({
137
137
  plain: boolean;
138
138
  }) {
139
139
  const { colors } = useSnapTheme();
140
- const clipHeight = showOverflowWarning ? undefined : SNAP_MAX_HEIGHT;
140
+ const [contentHeight, setContentHeight] = useState(0);
141
141
 
142
142
  const content = (
143
143
  <SnapViewV2Inner
@@ -153,6 +153,8 @@ function SnapCardV2Inner({
153
153
  return content;
154
154
  }
155
155
 
156
+ const overflowAmount = showOverflowWarning ? contentHeight - SNAP_MAX_HEIGHT : 0;
157
+
156
158
  return (
157
159
  <>
158
160
  <View
@@ -161,16 +163,20 @@ function SnapCardV2Inner({
161
163
  borderWidth: 1,
162
164
  borderColor: colors.border,
163
165
  backgroundColor: colors.surface,
164
- maxHeight: clipHeight,
166
+ maxHeight: showOverflowWarning ? undefined : SNAP_MAX_HEIGHT,
165
167
  overflow: "hidden",
166
168
  minHeight: 120,
167
169
  }}
168
170
  >
169
- <View style={{ paddingHorizontal: 16, paddingVertical: 16 }}>
171
+ <View
172
+ collapsable={false}
173
+ onLayout={(e) => setContentHeight(Math.round(e.nativeEvent.layout.height))}
174
+ style={{ paddingHorizontal: 16, paddingVertical: 16 }}
175
+ >
170
176
  {content}
171
177
  </View>
172
- {showOverflowWarning && (
173
- <View style={{ position: "absolute", top: SNAP_MAX_HEIGHT, left: 0, right: 0, bottom: 0, zIndex: 10, pointerEvents: "none" }}>
178
+ {showOverflowWarning && contentHeight > SNAP_MAX_HEIGHT && (
179
+ <View style={{ position: "absolute", top: SNAP_MAX_HEIGHT, left: 0, right: 0, height: overflowAmount, zIndex: 10, pointerEvents: "none" }}>
174
180
  <View style={{ height: 1, borderTopWidth: 1, borderStyle: "dashed", borderColor: "rgba(255,100,100,0.6)" }} />
175
181
  <View style={{ position: "absolute", top: -10, right: 4, backgroundColor: "rgba(0,0,0,0.7)", paddingHorizontal: 4, paddingVertical: 1, borderRadius: 3 }}>
176
182
  <Text style={{ fontSize: 10, color: "rgba(255,100,100,0.7)", fontFamily: Platform.select({ ios: "Menlo", default: "monospace" }) }}>{SNAP_MAX_HEIGHT}px</Text>