@farcaster/snap 2.1.0 → 2.1.2
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/constants.d.ts +2 -1
- package/dist/constants.js +2 -1
- package/dist/react/components/cell-grid.js +13 -14
- package/dist/react/components/image.js +5 -1
- package/dist/react/components/stack.js +53 -3
- package/dist/react/components/text.js +7 -1
- package/dist/react/stack-direction-context.d.ts +7 -0
- package/dist/react/stack-direction-context.js +10 -0
- package/dist/react/v2/snap-view.js +4 -1
- package/dist/react-native/components/snap-cell-grid.js +5 -7
- package/dist/react-native/components/snap-image.js +15 -2
- package/dist/react-native/components/snap-item.js +12 -2
- package/dist/react-native/components/snap-progress.js +8 -2
- package/dist/react-native/components/snap-stack.d.ts +1 -1
- package/dist/react-native/components/snap-stack.js +85 -10
- package/dist/react-native/components/snap-text.js +7 -2
- package/dist/react-native/stack-direction-context.d.ts +7 -0
- package/dist/react-native/stack-direction-context.js +9 -0
- package/dist/react-native/v2/snap-view.js +2 -1
- package/dist/stack-horizontal-utils.d.ts +4 -0
- package/dist/stack-horizontal-utils.js +29 -0
- package/dist/ui/catalog.d.ts +1 -0
- package/dist/ui/catalog.js +1 -1
- package/dist/ui/stack.d.ts +1 -0
- package/dist/ui/stack.js +8 -0
- package/llms.txt +2 -1
- package/package.json +1 -1
- package/src/constants.ts +2 -1
- package/src/react/components/cell-grid.tsx +17 -24
- package/src/react/components/image.tsx +8 -1
- package/src/react/components/stack.tsx +84 -11
- package/src/react/components/text.tsx +8 -1
- package/src/react/stack-direction-context.tsx +27 -0
- package/src/react/v2/snap-view.tsx +8 -2
- package/src/react-native/components/snap-cell-grid.tsx +5 -11
- package/src/react-native/components/snap-image.tsx +17 -2
- package/src/react-native/components/snap-item.tsx +14 -2
- package/src/react-native/components/snap-progress.tsx +8 -2
- package/src/react-native/components/snap-stack.tsx +116 -14
- package/src/react-native/components/snap-text.tsx +7 -2
- package/src/react-native/stack-direction-context.tsx +25 -0
- package/src/react-native/v2/snap-view.tsx +3 -2
- package/src/stack-horizontal-utils.ts +27 -0
- package/src/ui/catalog.ts +1 -1
- package/src/ui/stack.ts +8 -0
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { ComponentRenderProps } from "@json-render/react-native";
|
|
2
2
|
import { StyleSheet, Text, View } from "react-native";
|
|
3
|
+
import { useSnapStackDirection } from "../stack-direction-context";
|
|
3
4
|
import { useSnapTheme } from "../theme";
|
|
4
5
|
|
|
5
6
|
const SIZE_STYLES: Record<string, { fontSize: number; lineHeight?: number; fontWeight?: "400" | "500" | "600" | "700" }> = {
|
|
@@ -24,9 +25,10 @@ export function SnapText({
|
|
|
24
25
|
const sizeStyle = SIZE_STYLES[size] ?? SIZE_STYLES.md;
|
|
25
26
|
const resolvedWeight = weight ? WEIGHT_MAP[weight] : sizeStyle?.fontWeight;
|
|
26
27
|
const textAlign = align === "center" ? "center" : align === "right" ? "right" : "left";
|
|
28
|
+
const inHorizontalStack = useSnapStackDirection() === "horizontal";
|
|
27
29
|
|
|
28
30
|
return (
|
|
29
|
-
<View style={styles.
|
|
31
|
+
<View style={inHorizontalStack ? styles.wrapRow : styles.wrapCol}>
|
|
30
32
|
<Text
|
|
31
33
|
style={[
|
|
32
34
|
styles.base,
|
|
@@ -46,6 +48,9 @@ export function SnapText({
|
|
|
46
48
|
}
|
|
47
49
|
|
|
48
50
|
const styles = StyleSheet.create({
|
|
49
|
-
|
|
51
|
+
/** Full width for vertical stacks (alignment / wrapping). */
|
|
52
|
+
wrapCol: { width: "100%" },
|
|
53
|
+
/** Row peers: hug content; avoid width 100% fighting nowrap horizontal rows. */
|
|
54
|
+
wrapRow: { flexShrink: 1, minWidth: 0 },
|
|
50
55
|
base: {},
|
|
51
56
|
});
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { createContext, useContext, type ReactNode } from "react";
|
|
2
|
+
|
|
3
|
+
export type SnapStackDirection = "vertical" | "horizontal";
|
|
4
|
+
|
|
5
|
+
const SnapStackDirectionContext = createContext<SnapStackDirection | undefined>(
|
|
6
|
+
undefined,
|
|
7
|
+
);
|
|
8
|
+
|
|
9
|
+
export function SnapStackDirectionProvider({
|
|
10
|
+
direction,
|
|
11
|
+
children,
|
|
12
|
+
}: {
|
|
13
|
+
direction: SnapStackDirection;
|
|
14
|
+
children: ReactNode;
|
|
15
|
+
}) {
|
|
16
|
+
return (
|
|
17
|
+
<SnapStackDirectionContext.Provider value={direction}>
|
|
18
|
+
{children}
|
|
19
|
+
</SnapStackDirectionContext.Provider>
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function useSnapStackDirection(): SnapStackDirection | undefined {
|
|
24
|
+
return useContext(SnapStackDirectionContext);
|
|
25
|
+
}
|
|
@@ -17,6 +17,7 @@ import type { SnapPage, SnapActionHandlers } from "../types";
|
|
|
17
17
|
|
|
18
18
|
const SNAP_MAX_HEIGHT = 500;
|
|
19
19
|
const SNAP_WARNING_HEIGHT = 700;
|
|
20
|
+
const SHOW_MORE_OVERHANG = 14;
|
|
20
21
|
|
|
21
22
|
// ─── Validation fallback ─────────────────────────────
|
|
22
23
|
|
|
@@ -229,7 +230,7 @@ function SnapCardV2Inner({
|
|
|
229
230
|
const pillBgPressed = isDark ? "rgba(60,60,60,0.95)" : "rgba(240,240,240,0.95)";
|
|
230
231
|
|
|
231
232
|
return (
|
|
232
|
-
|
|
233
|
+
<View style={{ paddingBottom: isExpandable ? SHOW_MORE_OVERHANG : 0 }}>
|
|
233
234
|
<View style={{ position: "relative" }}>
|
|
234
235
|
<View
|
|
235
236
|
style={{
|
|
@@ -307,7 +308,7 @@ function SnapCardV2Inner({
|
|
|
307
308
|
{actionError}
|
|
308
309
|
</Text>
|
|
309
310
|
)}
|
|
310
|
-
|
|
311
|
+
</View>
|
|
311
312
|
);
|
|
312
313
|
}
|
|
313
314
|
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Children, isValidElement, type ReactNode } from "react";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* True when every rendered child comes from a catalog `button` element.
|
|
5
|
+
* json-render passes `{ element: { type, props, ... } }` into each catalog component.
|
|
6
|
+
*/
|
|
7
|
+
function isRenderableChild(c: ReactNode): boolean {
|
|
8
|
+
if (c == null) return false;
|
|
9
|
+
if (typeof c === "boolean") return false;
|
|
10
|
+
return true;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function horizontalChildrenAreAllButtons(children: ReactNode): boolean {
|
|
14
|
+
const items = Children.toArray(children).filter(isRenderableChild);
|
|
15
|
+
if (items.length === 0) return false;
|
|
16
|
+
for (const child of items) {
|
|
17
|
+
if (!isValidElement(child)) return false;
|
|
18
|
+
const typ = (child.props as { element?: { type?: unknown } }).element?.type;
|
|
19
|
+
if (typ !== "button") return false;
|
|
20
|
+
}
|
|
21
|
+
return true;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/** Direct snap catalog children under a stack (used for all-button grid column count). */
|
|
25
|
+
export function countRenderableChildren(children: ReactNode): number {
|
|
26
|
+
return Children.toArray(children).filter(isRenderableChild).length;
|
|
27
|
+
}
|
package/src/ui/catalog.ts
CHANGED
|
@@ -92,7 +92,7 @@ export const snapJsonRenderCatalog = defineCatalog(snapJsonRenderSchema, {
|
|
|
92
92
|
stack: {
|
|
93
93
|
props: stackProps,
|
|
94
94
|
description:
|
|
95
|
-
"Layout container — direction: vertical (default) | horizontal. Children are element ids in order.",
|
|
95
|
+
"Layout container — direction: vertical (default) | horizontal. Children are element ids in order. Horizontal stacks use a single flex row so peers stay side-by-side and shrink with min-width 0. Nested stacks participate as flexible row peers. All-button horizontal stacks use an equal N-column grid where N is the number of buttons (1–6). Optional `columns` (`2`–`6`) forces an explicit equal grid for mixed children.",
|
|
96
96
|
},
|
|
97
97
|
text: {
|
|
98
98
|
props: textProps,
|
package/src/ui/stack.ts
CHANGED
|
@@ -8,6 +8,14 @@ export const stackProps = z.object({
|
|
|
8
8
|
direction: z.enum(STACK_DIRECTIONS).optional(),
|
|
9
9
|
gap: z.enum(STACK_GAPS).optional(),
|
|
10
10
|
justify: z.enum(STACK_JUSTIFY).optional(),
|
|
11
|
+
/** Horizontal stacks only: fixed column grid (`2`–`6`). Prefer omitting this when children are stacks — they flex as row peers automatically. */
|
|
12
|
+
columns: z.union([
|
|
13
|
+
z.literal(2),
|
|
14
|
+
z.literal(3),
|
|
15
|
+
z.literal(4),
|
|
16
|
+
z.literal(5),
|
|
17
|
+
z.literal(6),
|
|
18
|
+
]).optional(),
|
|
11
19
|
});
|
|
12
20
|
|
|
13
21
|
export type StackProps = z.infer<typeof stackProps>;
|