@farcaster/snap 1.21.0 → 1.22.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/colors.d.ts CHANGED
@@ -3,12 +3,12 @@
3
3
  * it to a hex value appropriate for its current light/dark mode.
4
4
  *
5
5
  * Light-mode hex values (used by emulator):
6
- * gray=#8F8F8F blue=#006BFF red=#FC0036 amber=#FFAE00
7
- * green=#28A948 teal=#00AC96 purple=#8B5CF6 pink=#F32782
6
+ * gray=#6E6A86 blue=#286983 red=#B4637A amber=#EA9D34
7
+ * green=#3E8F8F teal=#56949F purple=#907AA9 pink=#D7827E
8
8
  *
9
9
  * Dark-mode hex values (for reference; client-owned):
10
- * gray=#8F8F8F blue=#006FFE red=#F13342 amber=#FFAE00
11
- * green=#00AC3A teal=#00AA96 purple=#A78BFA pink=#F12B82
10
+ * gray=#908CAA blue=#9CCFD8 red=#EB6F92 amber=#F6C177
11
+ * green=#56D4A4 teal=#3E8FB0 purple=#C4A7E7 pink=#EBBCBA
12
12
  */
13
13
  export declare const PALETTE_COLOR: {
14
14
  readonly gray: "gray";
package/dist/colors.js CHANGED
@@ -3,12 +3,12 @@
3
3
  * it to a hex value appropriate for its current light/dark mode.
4
4
  *
5
5
  * Light-mode hex values (used by emulator):
6
- * gray=#8F8F8F blue=#006BFF red=#FC0036 amber=#FFAE00
7
- * green=#28A948 teal=#00AC96 purple=#8B5CF6 pink=#F32782
6
+ * gray=#6E6A86 blue=#286983 red=#B4637A amber=#EA9D34
7
+ * green=#3E8F8F teal=#56949F purple=#907AA9 pink=#D7827E
8
8
  *
9
9
  * Dark-mode hex values (for reference; client-owned):
10
- * gray=#8F8F8F blue=#006FFE red=#F13342 amber=#FFAE00
11
- * green=#00AC3A teal=#00AA96 purple=#A78BFA pink=#F12B82
10
+ * gray=#908CAA blue=#9CCFD8 red=#EB6F92 amber=#F6C177
11
+ * green=#56D4A4 teal=#3E8FB0 purple=#C4A7E7 pink=#EBBCBA
12
12
  */
13
13
  export const PALETTE_COLOR = {
14
14
  gray: "gray",
@@ -34,25 +34,25 @@ export const PALETTE_COLOR_VALUES = [
34
34
  ];
35
35
  /** Light-mode hex for each palette color (emulator / reference client). */
36
36
  export const PALETTE_LIGHT_HEX = {
37
- gray: "#8F8F8F",
38
- blue: "#006BFF",
39
- red: "#FC0036",
40
- amber: "#FFAE00",
41
- green: "#28A948",
42
- teal: "#00AC96",
43
- purple: "#8B5CF6",
44
- pink: "#F32782",
37
+ gray: "#6E6A86",
38
+ blue: "#286983",
39
+ red: "#B4637A",
40
+ amber: "#EA9D34",
41
+ green: "#3E8F8F",
42
+ teal: "#56949F",
43
+ purple: "#907AA9",
44
+ pink: "#D7827E",
45
45
  };
46
46
  /** Dark-mode hex for each palette color (reference). */
47
47
  export const PALETTE_DARK_HEX = {
48
- gray: "#8F8F8F",
49
- blue: "#006FFE",
50
- red: "#F13342",
51
- amber: "#FFAE00",
52
- green: "#00AC3A",
53
- teal: "#00AA96",
54
- purple: "#A78BFA",
55
- pink: "#F12B82",
48
+ gray: "#908CAA",
49
+ blue: "#9CCFD8",
50
+ red: "#EB6F92",
51
+ amber: "#F6C177",
52
+ green: "#56D4A4",
53
+ teal: "#3E8FB0",
54
+ purple: "#C4A7E7",
55
+ pink: "#EBBCBA",
56
56
  };
57
57
  export const PROGRESS_COLOR_VALUES = [
58
58
  PALETTE_COLOR_ACCENT,
@@ -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.1",
4
4
  "description": "Farcaster Snaps 🫰",
5
5
  "repository": {
6
6
  "type": "git",
package/src/colors.ts CHANGED
@@ -3,12 +3,12 @@
3
3
  * it to a hex value appropriate for its current light/dark mode.
4
4
  *
5
5
  * Light-mode hex values (used by emulator):
6
- * gray=#8F8F8F blue=#006BFF red=#FC0036 amber=#FFAE00
7
- * green=#28A948 teal=#00AC96 purple=#8B5CF6 pink=#F32782
6
+ * gray=#6E6A86 blue=#286983 red=#B4637A amber=#EA9D34
7
+ * green=#3E8F8F teal=#56949F purple=#907AA9 pink=#D7827E
8
8
  *
9
9
  * Dark-mode hex values (for reference; client-owned):
10
- * gray=#8F8F8F blue=#006FFE red=#F13342 amber=#FFAE00
11
- * green=#00AC3A teal=#00AA96 purple=#A78BFA pink=#F12B82
10
+ * gray=#908CAA blue=#9CCFD8 red=#EB6F92 amber=#F6C177
11
+ * green=#56D4A4 teal=#3E8FB0 purple=#C4A7E7 pink=#EBBCBA
12
12
  */
13
13
  export const PALETTE_COLOR = {
14
14
  gray: "gray",
@@ -40,26 +40,26 @@ export type PaletteColor = (typeof PALETTE_COLOR_VALUES)[number];
40
40
 
41
41
  /** Light-mode hex for each palette color (emulator / reference client). */
42
42
  export const PALETTE_LIGHT_HEX: Record<PaletteColor, string> = {
43
- gray: "#8F8F8F",
44
- blue: "#006BFF",
45
- red: "#FC0036",
46
- amber: "#FFAE00",
47
- green: "#28A948",
48
- teal: "#00AC96",
49
- purple: "#8B5CF6",
50
- pink: "#F32782",
43
+ gray: "#6E6A86",
44
+ blue: "#286983",
45
+ red: "#B4637A",
46
+ amber: "#EA9D34",
47
+ green: "#3E8F8F",
48
+ teal: "#56949F",
49
+ purple: "#907AA9",
50
+ pink: "#D7827E",
51
51
  };
52
52
 
53
53
  /** Dark-mode hex for each palette color (reference). */
54
54
  export const PALETTE_DARK_HEX: Record<PaletteColor, string> = {
55
- gray: "#8F8F8F",
56
- blue: "#006FFE",
57
- red: "#F13342",
58
- amber: "#FFAE00",
59
- green: "#00AC3A",
60
- teal: "#00AA96",
61
- purple: "#A78BFA",
62
- pink: "#F12B82",
55
+ gray: "#908CAA",
56
+ blue: "#9CCFD8",
57
+ red: "#EB6F92",
58
+ amber: "#F6C177",
59
+ green: "#56D4A4",
60
+ teal: "#3E8FB0",
61
+ purple: "#C4A7E7",
62
+ pink: "#EBBCBA",
63
63
  };
64
64
 
65
65
  export const PROGRESS_COLOR_VALUES = [
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>