@farcaster/snap 2.5.0 → 2.5.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.
@@ -27,6 +27,7 @@ export function SnapCellGrid({ element: { props, on }, emit, }) {
27
27
  for (const c of cells) {
28
28
  cellMap.set(`${Number(c.row)},${Number(c.col)}`, {
29
29
  color: c.color,
30
+ textColor: c.textColor,
30
31
  content: c.content != null ? String(c.content) : undefined,
31
32
  value: typeof c.value === "string" ? c.value : undefined,
32
33
  });
@@ -74,7 +75,11 @@ export function SnapCellGrid({ element: { props, on }, emit, }) {
74
75
  const selected = interactive && isSelected(r, c);
75
76
  const bgHex = cell?.color ? colors.colorHex(cell.color) : null;
76
77
  const bg = bgHex ?? emptyCellBg;
77
- const textColor = bgHex ? readableTextOnHex(bgHex) : colors.text;
78
+ const textColor = cell?.textColor
79
+ ? colors.colorHex(cell.textColor)
80
+ : bgHex
81
+ ? readableTextOnHex(bgHex)
82
+ : colors.text;
78
83
  cellEls.push(_jsx("div", { role: interactive ? "button" : undefined, tabIndex: interactive ? 0 : undefined, onClick: interactive ? () => handleTap(r, c) : undefined, onKeyDown: interactive
79
84
  ? (e) => {
80
85
  if (e.key === "Enter" || e.key === " ") {
@@ -30,6 +30,7 @@ export function SnapCellGrid({ element, emit, }) {
30
30
  for (const c of cells) {
31
31
  cellMap.set(`${Number(c.row)},${Number(c.col)}`, {
32
32
  color: c.color,
33
+ textColor: c.textColor,
33
34
  content: c.content != null ? String(c.content) : undefined,
34
35
  value: typeof c.value === "string" ? c.value : undefined,
35
36
  });
@@ -78,7 +79,11 @@ export function SnapCellGrid({ element, emit, }) {
78
79
  const selected = interactive && isSelected(r, c);
79
80
  const bgHex = cell?.color ? hex(cell.color) : null;
80
81
  const bg = bgHex ?? emptyCellBg;
81
- const textColor = bgHex ? readableTextOnHex(bgHex) : colors.text;
82
+ const textColor = cell?.textColor
83
+ ? hex(cell.textColor)
84
+ : bgHex
85
+ ? readableTextOnHex(bgHex)
86
+ : colors.text;
82
87
  const cellContent = cell?.content ? (_jsx(Text, { style: [styles.cellText, { color: textColor }], children: cell.content })) : null;
83
88
  // Two-tone ring: outer View with contrasting border, inner View with inverse border
84
89
  const cellView = selected ? (_jsx(View, { style: [
@@ -445,6 +445,16 @@ export declare const snapJsonRenderCatalog: import("@json-render/core").Catalog<
445
445
  purple: "purple";
446
446
  pink: "pink";
447
447
  }>, z.ZodString]>>>;
448
+ textColor: z.ZodOptional<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodUnion<readonly [z.ZodEnum<{
449
+ gray: "gray";
450
+ blue: "blue";
451
+ red: "red";
452
+ amber: "amber";
453
+ green: "green";
454
+ teal: "teal";
455
+ purple: "purple";
456
+ pink: "pink";
457
+ }>, z.ZodString]>>>;
448
458
  content: z.ZodOptional<z.ZodString>;
449
459
  value: z.ZodOptional<z.ZodString>;
450
460
  }, z.core.$strip>>;
@@ -90,7 +90,7 @@ export const snapJsonRenderCatalog = defineCatalog(snapJsonRenderSchema, {
90
90
  },
91
91
  cell_grid: {
92
92
  props: cellGridProps,
93
- description: "Cell grid — sparse colored cells on a rows×cols grid. Cell color is a palette name or literal #rrggbb hex (hex ignores page accent). Two interaction modes: leave select 'off' and bind on.press to fire an action per cell press (inputs[name] is the pressed 'row,col' before the action runs); or set select 'single'/'multiple' for press-to-select with a visual ring (no auto-fire — pair with a separate submit button). on.press is ignored when select is on.",
93
+ description: "Cell grid — sparse colored cells on a rows×cols grid. Cell color and textColor are palette names or literal #rrggbb hex values (hex ignores page accent); textColor overrides the default auto-contrast text color. Two interaction modes: leave select 'off' and bind on.press to fire an action per cell press (inputs[name] is the pressed 'row,col' before the action runs); or set select 'single'/'multiple' for press-to-select with a visual ring (no auto-fire — pair with a separate submit button). on.press is ignored when select is on.",
94
94
  },
95
95
  },
96
96
  actions: {
@@ -16,6 +16,16 @@ export declare const cellGridProps: z.ZodObject<{
16
16
  purple: "purple";
17
17
  pink: "pink";
18
18
  }>, z.ZodString]>>>;
19
+ textColor: z.ZodOptional<z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodUnion<readonly [z.ZodEnum<{
20
+ gray: "gray";
21
+ blue: "blue";
22
+ red: "red";
23
+ amber: "amber";
24
+ green: "green";
25
+ teal: "teal";
26
+ purple: "purple";
27
+ pink: "pink";
28
+ }>, z.ZodString]>>>;
19
29
  content: z.ZodOptional<z.ZodString>;
20
30
  value: z.ZodOptional<z.ZodString>;
21
31
  }, z.core.$strip>>;
@@ -2,16 +2,17 @@ import { z } from "zod";
2
2
  import { isSnapHexColorString, PALETTE_COLOR_VALUES } from "../colors.js";
3
3
  import { GRID_MIN_COLS, GRID_MAX_COLS, GRID_MIN_ROWS, GRID_MAX_ROWS, GRID_GAP_VALUES, GRID_CELL_ASPECT_RATIO_VALUES, } from "../constants.js";
4
4
  /** Palette name or `#rrggbb`; input is trimmed so palette and hex rules match runtime resolvers. */
5
- const cellGridCellColorSchema = z.preprocess((v) => (typeof v === "string" ? v.trim() : v), z.union([
5
+ const cellGridCellColorSchema = (field) => z.preprocess((v) => (typeof v === "string" ? v.trim() : v), z.union([
6
6
  z.enum(PALETTE_COLOR_VALUES),
7
7
  z.string().refine(isSnapHexColorString, {
8
- message: "cell_grid cell hex color must be #rrggbb",
8
+ message: `cell_grid cell ${field} hex must be #rrggbb`,
9
9
  }),
10
10
  ]));
11
11
  const cellGridCellSchema = z.object({
12
12
  row: z.number().int().nonnegative(),
13
13
  col: z.number().int().nonnegative(),
14
- color: cellGridCellColorSchema.optional(),
14
+ color: cellGridCellColorSchema("color").optional(),
15
+ textColor: cellGridCellColorSchema("textColor").optional(),
15
16
  content: z.string().optional(),
16
17
  value: z.string().min(1).max(30).optional(),
17
18
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@farcaster/snap",
3
- "version": "2.5.0",
3
+ "version": "2.5.1",
4
4
  "description": "Farcaster Snaps 🫰",
5
5
  "repository": {
6
6
  "type": "git",
@@ -35,11 +35,12 @@ export function SnapCellGrid({
35
35
 
36
36
  const cellMap = new Map<
37
37
  string,
38
- { color?: string; content?: string; value?: string }
38
+ { color?: string; textColor?: string; content?: string; value?: string }
39
39
  >();
40
40
  for (const c of cells) {
41
41
  cellMap.set(`${Number(c.row)},${Number(c.col)}`, {
42
42
  color: c.color as string | undefined,
43
+ textColor: c.textColor as string | undefined,
43
44
  content: c.content != null ? String(c.content) : undefined,
44
45
  value: typeof c.value === "string" ? c.value : undefined,
45
46
  });
@@ -90,7 +91,11 @@ export function SnapCellGrid({
90
91
  const selected = interactive && isSelected(r, c);
91
92
  const bgHex = cell?.color ? colors.colorHex(cell.color) : null;
92
93
  const bg = bgHex ?? emptyCellBg;
93
- const textColor = bgHex ? readableTextOnHex(bgHex) : colors.text;
94
+ const textColor = cell?.textColor
95
+ ? colors.colorHex(cell.textColor)
96
+ : bgHex
97
+ ? readableTextOnHex(bgHex)
98
+ : colors.text;
94
99
 
95
100
  cellEls.push(
96
101
  <div
@@ -35,11 +35,12 @@ export function SnapCellGrid({
35
35
 
36
36
  const cellMap = new Map<
37
37
  string,
38
- { color?: string; content?: string; value?: string }
38
+ { color?: string; textColor?: string; content?: string; value?: string }
39
39
  >();
40
40
  for (const c of cells) {
41
41
  cellMap.set(`${Number(c.row)},${Number(c.col)}`, {
42
42
  color: c.color as string | undefined,
43
+ textColor: c.textColor as string | undefined,
43
44
  content: c.content != null ? String(c.content) : undefined,
44
45
  value: typeof c.value === "string" ? c.value : undefined,
45
46
  });
@@ -92,7 +93,11 @@ export function SnapCellGrid({
92
93
  const selected = interactive && isSelected(r, c);
93
94
  const bgHex = cell?.color ? hex(cell.color) : null;
94
95
  const bg = bgHex ?? emptyCellBg;
95
- const textColor = bgHex ? readableTextOnHex(bgHex) : colors.text;
96
+ const textColor = cell?.textColor
97
+ ? hex(cell.textColor)
98
+ : bgHex
99
+ ? readableTextOnHex(bgHex)
100
+ : colors.text;
96
101
 
97
102
  const cellContent = cell?.content ? (
98
103
  <Text style={[styles.cellText, { color: textColor }]}>
package/src/ui/README.md CHANGED
@@ -41,7 +41,7 @@ Some elements accept a `color` prop:
41
41
 
42
42
  - `progress` — color name or `"accent"`
43
43
  - `bar_chart` — color name or `"accent"` at chart level; color name only per-bar
44
- - `grid` cells — `#rrggbb` hex
44
+ - `grid` cell fill/text colors — `#rrggbb` hex
45
45
 
46
46
  When `color` is `"accent"` (or omitted), the element uses the accent color. When it is a specific color name or hex value, that color is **explicit** and independent of `page.theme.accent`.
47
47
 
package/src/ui/catalog.ts CHANGED
@@ -107,7 +107,7 @@ export const snapJsonRenderCatalog = defineCatalog(snapJsonRenderSchema, {
107
107
  cell_grid: {
108
108
  props: cellGridProps,
109
109
  description:
110
- "Cell grid — sparse colored cells on a rows×cols grid. Cell color is a palette name or literal #rrggbb hex (hex ignores page accent). Two interaction modes: leave select 'off' and bind on.press to fire an action per cell press (inputs[name] is the pressed 'row,col' before the action runs); or set select 'single'/'multiple' for press-to-select with a visual ring (no auto-fire — pair with a separate submit button). on.press is ignored when select is on.",
110
+ "Cell grid — sparse colored cells on a rows×cols grid. Cell color and textColor are palette names or literal #rrggbb hex values (hex ignores page accent); textColor overrides the default auto-contrast text color. Two interaction modes: leave select 'off' and bind on.press to fire an action per cell press (inputs[name] is the pressed 'row,col' before the action runs); or set select 'single'/'multiple' for press-to-select with a visual ring (no auto-fire — pair with a separate submit button). on.press is ignored when select is on.",
111
111
  },
112
112
  },
113
113
  actions: {
@@ -10,12 +10,12 @@ import {
10
10
  } from "../constants.js";
11
11
 
12
12
  /** Palette name or `#rrggbb`; input is trimmed so palette and hex rules match runtime resolvers. */
13
- const cellGridCellColorSchema = z.preprocess(
13
+ const cellGridCellColorSchema = (field: "color" | "textColor") => z.preprocess(
14
14
  (v) => (typeof v === "string" ? v.trim() : v),
15
15
  z.union([
16
16
  z.enum(PALETTE_COLOR_VALUES),
17
17
  z.string().refine(isSnapHexColorString, {
18
- message: "cell_grid cell hex color must be #rrggbb",
18
+ message: `cell_grid cell ${field} hex must be #rrggbb`,
19
19
  }),
20
20
  ]),
21
21
  );
@@ -23,7 +23,8 @@ const cellGridCellColorSchema = z.preprocess(
23
23
  const cellGridCellSchema = z.object({
24
24
  row: z.number().int().nonnegative(),
25
25
  col: z.number().int().nonnegative(),
26
- color: cellGridCellColorSchema.optional(),
26
+ color: cellGridCellColorSchema("color").optional(),
27
+ textColor: cellGridCellColorSchema("textColor").optional(),
27
28
  content: z.string().optional(),
28
29
  value: z.string().min(1).max(30).optional(),
29
30
  });