@farcaster/snap 1.5.1 → 1.6.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.
- package/dist/constants.d.ts +0 -107
- package/dist/constants.js +0 -148
- package/dist/dataStore.d.ts +12 -0
- package/dist/dataStore.js +35 -0
- package/dist/index.d.ts +6 -3
- package/dist/index.js +5 -3
- package/dist/middleware.d.ts +3 -0
- package/dist/middleware.js +3 -0
- package/dist/react/accent-context.d.ts +6 -0
- package/dist/react/accent-context.js +10 -0
- package/dist/react/catalog-renderer.d.ts +5 -0
- package/dist/react/catalog-renderer.js +37 -0
- package/dist/react/components/action-button.d.ts +6 -0
- package/dist/react/components/action-button.js +22 -0
- package/dist/react/components/badge.d.ts +5 -0
- package/dist/react/components/badge.js +18 -0
- package/dist/react/components/icon.d.ts +7 -0
- package/dist/react/components/icon.js +60 -0
- package/dist/react/components/image.d.ts +5 -0
- package/dist/react/components/image.js +15 -0
- package/dist/react/components/input.d.ts +5 -0
- package/dist/react/components/input.js +18 -0
- package/dist/react/components/item-group.d.ts +7 -0
- package/dist/react/components/item-group.js +17 -0
- package/dist/react/components/item.d.ts +7 -0
- package/dist/react/components/item.js +9 -0
- package/dist/react/components/progress.d.ts +5 -0
- package/dist/react/components/progress.js +11 -0
- package/dist/react/components/separator.d.ts +5 -0
- package/dist/react/components/separator.js +7 -0
- package/dist/react/components/slider.d.ts +5 -0
- package/dist/react/components/slider.js +21 -0
- package/dist/react/components/stack.d.ts +7 -0
- package/dist/react/components/stack.js +32 -0
- package/dist/react/components/switch.d.ts +5 -0
- package/dist/react/components/switch.js +23 -0
- package/dist/react/components/text.d.ts +5 -0
- package/dist/react/components/text.js +25 -0
- package/dist/react/components/toggle-group.d.ts +5 -0
- package/dist/react/components/toggle-group.js +52 -0
- package/dist/react/hooks/use-snap-accent.d.ts +13 -0
- package/dist/react/hooks/use-snap-accent.js +32 -0
- package/dist/react/index.d.ts +47 -0
- package/dist/react/index.js +191 -0
- package/dist/react/lib/preview-primary-css.d.ts +6 -0
- package/dist/react/lib/preview-primary-css.js +43 -0
- package/dist/react/lib/resolve-palette-hex.d.ts +2 -0
- package/dist/react/lib/resolve-palette-hex.js +10 -0
- package/dist/schemas.d.ts +14 -1629
- package/dist/schemas.js +14 -526
- package/dist/ui/badge.d.ts +52 -0
- package/dist/ui/badge.js +9 -0
- package/dist/ui/button.d.ts +42 -28
- package/dist/ui/button.js +7 -9
- package/dist/ui/catalog.d.ts +280 -155
- package/dist/ui/catalog.js +102 -83
- package/dist/ui/icon.d.ts +56 -0
- package/dist/ui/icon.js +51 -0
- package/dist/ui/image.d.ts +1 -0
- package/dist/ui/image.js +2 -2
- package/dist/ui/index.d.ts +20 -22
- package/dist/ui/index.js +10 -11
- package/dist/ui/input.d.ts +17 -0
- package/dist/ui/input.js +13 -0
- package/dist/ui/item-group.d.ts +12 -0
- package/dist/ui/item-group.js +7 -0
- package/dist/ui/item.d.ts +14 -0
- package/dist/ui/item.js +9 -0
- package/dist/ui/progress.d.ts +1 -11
- package/dist/ui/progress.js +21 -4
- package/dist/ui/schema.js +3 -3
- package/dist/ui/separator.d.ts +9 -0
- package/dist/ui/separator.js +5 -0
- package/dist/ui/slider.d.ts +4 -3
- package/dist/ui/slider.js +34 -5
- package/dist/ui/stack.d.ts +22 -1
- package/dist/ui/stack.js +8 -1
- package/dist/ui/switch.d.ts +8 -0
- package/dist/ui/switch.js +7 -0
- package/dist/ui/text.d.ts +15 -7
- package/dist/ui/text.js +8 -4
- package/dist/ui/toggle-group.d.ts +23 -0
- package/dist/ui/toggle-group.js +19 -0
- package/dist/validator.d.ts +5 -1
- package/dist/validator.js +6 -136
- package/package.json +72 -52
- package/src/constants.ts +0 -179
- package/src/dataStore.ts +62 -0
- package/src/index.ts +11 -20
- package/src/middleware.ts +7 -0
- package/src/react/accent-context.tsx +29 -0
- package/src/react/catalog-renderer.tsx +39 -0
- package/src/react/components/action-button.tsx +48 -0
- package/src/react/components/badge.tsx +37 -0
- package/src/react/components/icon.tsx +115 -0
- package/src/react/components/image.tsx +33 -0
- package/src/react/components/input.tsx +36 -0
- package/src/react/components/item-group.tsx +43 -0
- package/src/react/components/item.tsx +33 -0
- package/src/react/components/progress.tsx +29 -0
- package/src/react/components/separator.tsx +14 -0
- package/src/react/components/slider.tsx +43 -0
- package/src/react/components/stack.tsx +55 -0
- package/src/react/components/switch.tsx +46 -0
- package/src/react/components/text.tsx +43 -0
- package/src/react/components/toggle-group.tsx +85 -0
- package/src/react/hooks/use-snap-accent.ts +45 -0
- package/src/react/index.tsx +321 -0
- package/src/react/lib/preview-primary-css.ts +57 -0
- package/src/react/lib/resolve-palette-hex.ts +20 -0
- package/src/schemas.ts +18 -644
- package/src/ui/badge.ts +13 -0
- package/src/ui/button.ts +9 -12
- package/src/ui/catalog.ts +106 -86
- package/src/ui/icon.ts +56 -0
- package/src/ui/image.ts +3 -2
- package/src/ui/index.ts +26 -29
- package/src/ui/input.ts +17 -0
- package/src/ui/item-group.ts +11 -0
- package/src/ui/item.ts +13 -0
- package/src/ui/progress.ts +25 -7
- package/src/ui/schema.ts +3 -3
- package/src/ui/separator.ts +9 -0
- package/src/ui/slider.ts +40 -10
- package/src/ui/stack.ts +9 -1
- package/src/ui/switch.ts +11 -0
- package/src/ui/text.ts +9 -4
- package/src/ui/toggle-group.ts +23 -0
- package/src/validator.ts +6 -176
- package/dist/ui/bar-chart.d.ts +0 -30
- package/dist/ui/bar-chart.js +0 -15
- package/dist/ui/button-group.d.ts +0 -19
- package/dist/ui/button-group.js +0 -18
- package/dist/ui/divider.d.ts +0 -3
- package/dist/ui/divider.js +0 -2
- package/dist/ui/grid.d.ts +0 -22
- package/dist/ui/grid.js +0 -16
- package/dist/ui/group.d.ts +0 -7
- package/dist/ui/group.js +0 -5
- package/dist/ui/list.d.ts +0 -13
- package/dist/ui/list.js +0 -13
- package/dist/ui/spacer.d.ts +0 -9
- package/dist/ui/spacer.js +0 -5
- package/dist/ui/text-input.d.ts +0 -7
- package/dist/ui/text-input.js +0 -12
- package/dist/ui/toggle.d.ts +0 -7
- package/dist/ui/toggle.js +0 -6
- package/src/ui/bar-chart.ts +0 -20
- package/src/ui/button-group.ts +0 -26
- package/src/ui/divider.ts +0 -5
- package/src/ui/grid.ts +0 -25
- package/src/ui/group.ts +0 -8
- package/src/ui/list.ts +0 -17
- package/src/ui/spacer.ts +0 -8
- package/src/ui/text-input.ts +0 -15
- package/src/ui/toggle.ts +0 -9
package/src/ui/badge.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { PROGRESS_COLOR_VALUES } from "../colors.js";
|
|
3
|
+
import { ICON_NAMES } from "./icon.js";
|
|
4
|
+
|
|
5
|
+
export const BADGE_MAX_LABEL_CHARS = 30;
|
|
6
|
+
|
|
7
|
+
export const badgeProps = z.object({
|
|
8
|
+
label: z.string().min(1).max(BADGE_MAX_LABEL_CHARS),
|
|
9
|
+
color: z.enum(PROGRESS_COLOR_VALUES).optional(),
|
|
10
|
+
icon: z.enum(ICON_NAMES).optional(),
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
export type BadgeProps = z.infer<typeof badgeProps>;
|
package/src/ui/button.ts
CHANGED
|
@@ -1,16 +1,13 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
import {
|
|
2
|
+
import { ICON_NAMES } from "./icon.js";
|
|
3
3
|
|
|
4
|
-
export const
|
|
5
|
-
|
|
6
|
-
action: z.enum(BUTTON_ACTION_VALUES),
|
|
7
|
-
target: z.string().optional(),
|
|
8
|
-
client_action: z.record(z.string(), z.unknown()).optional(),
|
|
9
|
-
style: z.enum(BUTTON_STYLE_VALUES).optional(),
|
|
10
|
-
});
|
|
4
|
+
export const BUTTON_VARIANTS = ["default", "secondary", "outline", "ghost"] as const;
|
|
5
|
+
export const BUTTON_MAX_LABEL_CHARS = 30;
|
|
11
6
|
|
|
12
|
-
export
|
|
7
|
+
export const buttonProps = z.object({
|
|
8
|
+
label: z.string().min(1).max(BUTTON_MAX_LABEL_CHARS),
|
|
9
|
+
variant: z.enum(BUTTON_VARIANTS).optional(),
|
|
10
|
+
icon: z.enum(ICON_NAMES).optional(),
|
|
11
|
+
});
|
|
13
12
|
|
|
14
|
-
|
|
15
|
-
export const buttonProps = actionButtonProps;
|
|
16
|
-
export type ButtonProps = ActionButtonProps;
|
|
13
|
+
export type ButtonProps = z.infer<typeof buttonProps>;
|
package/src/ui/catalog.ts
CHANGED
|
@@ -1,132 +1,152 @@
|
|
|
1
1
|
import { defineCatalog } from "@json-render/core";
|
|
2
2
|
import { z } from "zod";
|
|
3
|
-
import { BUTTON_STYLE_VALUES } from "../constants.js";
|
|
4
3
|
import { snapJsonRenderSchema } from "./schema.js";
|
|
5
|
-
import {
|
|
4
|
+
import { badgeProps } from "./badge.js";
|
|
5
|
+
import { buttonProps } from "./button.js";
|
|
6
|
+
import { switchProps } from "./switch.js";
|
|
7
|
+
import { toggleGroupProps } from "./toggle-group.js";
|
|
8
|
+
import { iconProps } from "./icon.js";
|
|
9
|
+
import { inputProps } from "./input.js";
|
|
10
|
+
import { itemProps } from "./item.js";
|
|
11
|
+
import { itemGroupProps } from "./item-group.js";
|
|
6
12
|
import { imageProps } from "./image.js";
|
|
7
|
-
import { dividerProps } from "./divider.js";
|
|
8
|
-
import { spacerProps } from "./spacer.js";
|
|
9
13
|
import { progressProps } from "./progress.js";
|
|
10
|
-
import {
|
|
11
|
-
import { gridProps } from "./grid.js";
|
|
12
|
-
import { textInputProps } from "./text-input.js";
|
|
14
|
+
import { separatorProps } from "./separator.js";
|
|
13
15
|
import { sliderProps } from "./slider.js";
|
|
14
|
-
import { buttonGroupProps } from "./button-group.js";
|
|
15
|
-
import { toggleProps } from "./toggle.js";
|
|
16
|
-
import { barChartProps } from "./bar-chart.js";
|
|
17
|
-
import { groupProps } from "./group.js";
|
|
18
16
|
import { stackProps } from "./stack.js";
|
|
19
|
-
import {
|
|
20
|
-
|
|
21
|
-
const snapPostParams = z.object({
|
|
22
|
-
button_index: z.number().int().nonnegative(),
|
|
23
|
-
target: z.string(),
|
|
24
|
-
label: z.string().optional(),
|
|
25
|
-
style: z.enum(BUTTON_STYLE_VALUES).optional(),
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
const snapTargetParams = z.object({
|
|
29
|
-
target: z.string(),
|
|
30
|
-
});
|
|
17
|
+
import { textProps } from "./text.js";
|
|
31
18
|
|
|
32
19
|
const snapClientParams = z.object({
|
|
33
20
|
client_action: z.record(z.string(), z.unknown()),
|
|
34
21
|
});
|
|
35
22
|
|
|
36
23
|
/**
|
|
37
|
-
*
|
|
38
|
-
*
|
|
24
|
+
* json-render catalog for snap elements.
|
|
25
|
+
*
|
|
26
|
+
* Component keys match the snap wire-format `type` strings.
|
|
27
|
+
* Action names are used directly in `on.press` bindings.
|
|
39
28
|
*/
|
|
40
29
|
export const snapJsonRenderCatalog = defineCatalog(snapJsonRenderSchema, {
|
|
41
30
|
components: {
|
|
42
|
-
|
|
43
|
-
props:
|
|
31
|
+
badge: {
|
|
32
|
+
props: badgeProps,
|
|
44
33
|
description:
|
|
45
|
-
"
|
|
34
|
+
"Inline label — variant: default | secondary | destructive | outline.",
|
|
46
35
|
},
|
|
47
|
-
|
|
48
|
-
props:
|
|
49
|
-
description:
|
|
36
|
+
button: {
|
|
37
|
+
props: buttonProps,
|
|
38
|
+
description:
|
|
39
|
+
"Action button — use with on.press to bind snap or client actions.",
|
|
50
40
|
},
|
|
51
|
-
|
|
52
|
-
props:
|
|
53
|
-
description:
|
|
41
|
+
switch: {
|
|
42
|
+
props: switchProps,
|
|
43
|
+
description:
|
|
44
|
+
"Boolean toggle; `name` becomes POST inputs key. Optional label.",
|
|
54
45
|
},
|
|
55
|
-
|
|
56
|
-
props:
|
|
57
|
-
description:
|
|
46
|
+
toggle_group: {
|
|
47
|
+
props: toggleGroupProps,
|
|
48
|
+
description:
|
|
49
|
+
"Single or multi-select choice group; `name` becomes POST inputs key. mode: single (default) | multiple. Optional label.",
|
|
58
50
|
},
|
|
59
|
-
|
|
60
|
-
props:
|
|
51
|
+
input: {
|
|
52
|
+
props: inputProps,
|
|
61
53
|
description:
|
|
62
|
-
"
|
|
54
|
+
"Text input; `name` becomes POST inputs key. Optional label and placeholder.",
|
|
63
55
|
},
|
|
64
|
-
|
|
65
|
-
props:
|
|
56
|
+
item: {
|
|
57
|
+
props: itemProps,
|
|
66
58
|
description:
|
|
67
|
-
"
|
|
59
|
+
"Content row with title and optional description. Children render in the actions slot (right side) — use badge, button, or text elements.",
|
|
68
60
|
},
|
|
69
|
-
|
|
70
|
-
props:
|
|
61
|
+
item_group: {
|
|
62
|
+
props: itemGroupProps,
|
|
71
63
|
description:
|
|
72
|
-
"
|
|
64
|
+
"Groups item children into a styled list. Optional border around the group and separator lines between items.",
|
|
73
65
|
},
|
|
74
|
-
|
|
75
|
-
props:
|
|
76
|
-
description:
|
|
66
|
+
icon: {
|
|
67
|
+
props: iconProps,
|
|
68
|
+
description:
|
|
69
|
+
"Inline icon from the curated set. Optional color (palette) and size (sm | md).",
|
|
77
70
|
},
|
|
78
|
-
|
|
79
|
-
props:
|
|
80
|
-
description: "
|
|
71
|
+
image: {
|
|
72
|
+
props: imageProps,
|
|
73
|
+
description: "HTTPS image with fixed aspect ratio.",
|
|
81
74
|
},
|
|
82
|
-
|
|
83
|
-
props:
|
|
75
|
+
progress: {
|
|
76
|
+
props: progressProps,
|
|
84
77
|
description:
|
|
85
|
-
"
|
|
86
|
-
},
|
|
87
|
-
Toggle: {
|
|
88
|
-
props: toggleProps,
|
|
89
|
-
description: "Boolean toggle; `name` becomes POST inputs key.",
|
|
78
|
+
"Horizontal progress bar (value/max, optional label and color).",
|
|
90
79
|
},
|
|
91
|
-
|
|
92
|
-
props:
|
|
80
|
+
separator: {
|
|
81
|
+
props: separatorProps,
|
|
93
82
|
description:
|
|
94
|
-
"
|
|
83
|
+
"Visual divider — orientation: horizontal (default) | vertical.",
|
|
95
84
|
},
|
|
96
|
-
|
|
97
|
-
props:
|
|
85
|
+
slider: {
|
|
86
|
+
props: sliderProps,
|
|
98
87
|
description:
|
|
99
|
-
"
|
|
88
|
+
"Numeric slider; `name` becomes POST inputs key. Optional label.",
|
|
100
89
|
},
|
|
101
|
-
|
|
90
|
+
stack: {
|
|
102
91
|
props: stackProps,
|
|
103
92
|
description:
|
|
104
|
-
"
|
|
93
|
+
"Layout container — direction: vertical (default) | horizontal. Children are element ids in order.",
|
|
105
94
|
},
|
|
106
|
-
|
|
107
|
-
props:
|
|
95
|
+
text: {
|
|
96
|
+
props: textProps,
|
|
108
97
|
description:
|
|
109
|
-
"
|
|
98
|
+
"Text block — size: lg (heading), md (body, default), sm (caption). Optional weight and align.",
|
|
110
99
|
},
|
|
111
100
|
},
|
|
112
101
|
actions: {
|
|
113
|
-
|
|
114
|
-
description:
|
|
115
|
-
"POST to snap `target` with signed body (fid, inputs, button_index, timestamp, signature); response is next snap page JSON.",
|
|
116
|
-
params: snapPostParams,
|
|
117
|
-
},
|
|
118
|
-
snap_link: {
|
|
119
|
-
description: "Open `target` in the system browser; no server round-trip.",
|
|
120
|
-
params: snapTargetParams,
|
|
121
|
-
},
|
|
122
|
-
snap_mini_app: {
|
|
123
|
-
description: "Open `target` as an in-app Farcaster mini app.",
|
|
124
|
-
params: snapTargetParams,
|
|
125
|
-
},
|
|
126
|
-
snap_client: {
|
|
102
|
+
submit: {
|
|
127
103
|
description:
|
|
128
|
-
"
|
|
129
|
-
params:
|
|
104
|
+
"POST to snap server with signed body (fid, inputs, timestamp, signature); response is next snap page.",
|
|
105
|
+
params: z.object({ target: z.string() }),
|
|
106
|
+
},
|
|
107
|
+
open_url: {
|
|
108
|
+
description: "Open target URL in the system browser.",
|
|
109
|
+
params: z.object({ target: z.string() }),
|
|
110
|
+
},
|
|
111
|
+
open_mini_app: {
|
|
112
|
+
description: "Open target URL as a Farcaster mini app.",
|
|
113
|
+
params: z.object({ target: z.string() }),
|
|
114
|
+
},
|
|
115
|
+
view_cast: {
|
|
116
|
+
description: "Navigate to a cast by hash.",
|
|
117
|
+
params: z.object({ hash: z.string() }),
|
|
118
|
+
},
|
|
119
|
+
view_profile: {
|
|
120
|
+
description: "Navigate to a user profile by FID.",
|
|
121
|
+
params: z.object({ fid: z.number() }),
|
|
122
|
+
},
|
|
123
|
+
compose_cast: {
|
|
124
|
+
description: "Open the cast composer with optional pre-filled content.",
|
|
125
|
+
params: z.object({
|
|
126
|
+
text: z.string().optional(),
|
|
127
|
+
channelKey: z.string().optional(),
|
|
128
|
+
embeds: z.array(z.string()).optional(),
|
|
129
|
+
}),
|
|
130
|
+
},
|
|
131
|
+
view_token: {
|
|
132
|
+
description: "View a token in the wallet. Token is a CAIP-19 identifier.",
|
|
133
|
+
params: z.object({ token: z.string() }),
|
|
134
|
+
},
|
|
135
|
+
send_token: {
|
|
136
|
+
description: "Open send flow for a token. Token is CAIP-19.",
|
|
137
|
+
params: z.object({
|
|
138
|
+
token: z.string(),
|
|
139
|
+
amount: z.string().optional(),
|
|
140
|
+
recipientFid: z.number().optional(),
|
|
141
|
+
recipientAddress: z.string().optional(),
|
|
142
|
+
}),
|
|
143
|
+
},
|
|
144
|
+
swap_token: {
|
|
145
|
+
description: "Open swap flow between two tokens. Tokens are CAIP-19.",
|
|
146
|
+
params: z.object({
|
|
147
|
+
sellToken: z.string().optional(),
|
|
148
|
+
buyToken: z.string().optional(),
|
|
149
|
+
}),
|
|
130
150
|
},
|
|
131
151
|
},
|
|
132
152
|
});
|
package/src/ui/icon.ts
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { PROGRESS_COLOR_VALUES } from "../colors.js";
|
|
3
|
+
|
|
4
|
+
export const ICON_NAMES = [
|
|
5
|
+
// Navigation/Actions
|
|
6
|
+
"arrow-right",
|
|
7
|
+
"arrow-left",
|
|
8
|
+
"external-link",
|
|
9
|
+
"chevron-right",
|
|
10
|
+
// Status
|
|
11
|
+
"check",
|
|
12
|
+
"x",
|
|
13
|
+
"alert-triangle",
|
|
14
|
+
"info",
|
|
15
|
+
"clock",
|
|
16
|
+
// Social
|
|
17
|
+
"heart",
|
|
18
|
+
"message-circle",
|
|
19
|
+
"repeat",
|
|
20
|
+
"share",
|
|
21
|
+
"user",
|
|
22
|
+
"users",
|
|
23
|
+
// Content
|
|
24
|
+
"star",
|
|
25
|
+
"trophy",
|
|
26
|
+
"zap",
|
|
27
|
+
"flame",
|
|
28
|
+
"gift",
|
|
29
|
+
// Media
|
|
30
|
+
"image",
|
|
31
|
+
"play",
|
|
32
|
+
"pause",
|
|
33
|
+
// Commerce
|
|
34
|
+
"wallet",
|
|
35
|
+
"coins",
|
|
36
|
+
// Common actions
|
|
37
|
+
"plus",
|
|
38
|
+
"minus",
|
|
39
|
+
"refresh-cw",
|
|
40
|
+
"bookmark",
|
|
41
|
+
// Feedback/data
|
|
42
|
+
"thumbs-up",
|
|
43
|
+
"thumbs-down",
|
|
44
|
+
"trending-up",
|
|
45
|
+
"trending-down",
|
|
46
|
+
] as const;
|
|
47
|
+
|
|
48
|
+
export const ICON_SIZES = ["sm", "md"] as const;
|
|
49
|
+
|
|
50
|
+
export const iconProps = z.object({
|
|
51
|
+
name: z.enum(ICON_NAMES),
|
|
52
|
+
color: z.enum(PROGRESS_COLOR_VALUES).optional(),
|
|
53
|
+
size: z.enum(ICON_SIZES).optional(),
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
export type IconProps = z.infer<typeof iconProps>;
|
package/src/ui/image.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
|
|
2
|
+
|
|
3
|
+
export const IMAGE_ASPECTS = ["1:1", "16:9", "4:3", "3:4", "9:16"] as const;
|
|
3
4
|
|
|
4
5
|
export const imageProps = z.object({
|
|
5
6
|
url: z.string(),
|
|
6
|
-
aspect: z.enum(
|
|
7
|
+
aspect: z.enum(IMAGE_ASPECTS),
|
|
7
8
|
alt: z.string().optional(),
|
|
8
9
|
});
|
|
9
10
|
|
package/src/ui/index.ts
CHANGED
|
@@ -1,47 +1,44 @@
|
|
|
1
1
|
export { snapJsonRenderSchema } from "./schema.js";
|
|
2
2
|
export { snapJsonRenderCatalog } from "./catalog.js";
|
|
3
3
|
|
|
4
|
-
export {
|
|
5
|
-
export type {
|
|
4
|
+
export { badgeProps } from "./badge.js";
|
|
5
|
+
export type { BadgeProps } from "./badge.js";
|
|
6
6
|
|
|
7
|
-
export {
|
|
8
|
-
export type {
|
|
7
|
+
export { buttonProps } from "./button.js";
|
|
8
|
+
export type { ButtonProps } from "./button.js";
|
|
9
9
|
|
|
10
|
-
export {
|
|
11
|
-
export type {
|
|
10
|
+
export { switchProps } from "./switch.js";
|
|
11
|
+
export type { SwitchProps } from "./switch.js";
|
|
12
12
|
|
|
13
|
-
export {
|
|
14
|
-
export type {
|
|
13
|
+
export { toggleGroupProps } from "./toggle-group.js";
|
|
14
|
+
export type { ToggleGroupProps } from "./toggle-group.js";
|
|
15
15
|
|
|
16
|
-
export {
|
|
17
|
-
export type {
|
|
18
|
-
|
|
19
|
-
export { listProps } from "./list.js";
|
|
20
|
-
export type { ListProps } from "./list.js";
|
|
16
|
+
export { inputProps } from "./input.js";
|
|
17
|
+
export type { InputProps } from "./input.js";
|
|
21
18
|
|
|
22
|
-
export {
|
|
23
|
-
export type {
|
|
19
|
+
export { itemProps } from "./item.js";
|
|
20
|
+
export type { ItemProps } from "./item.js";
|
|
24
21
|
|
|
25
|
-
export {
|
|
26
|
-
export type {
|
|
22
|
+
export { itemGroupProps } from "./item-group.js";
|
|
23
|
+
export type { ItemGroupProps } from "./item-group.js";
|
|
27
24
|
|
|
28
|
-
export {
|
|
29
|
-
export type {
|
|
25
|
+
export { iconProps, ICON_NAMES } from "./icon.js";
|
|
26
|
+
export type { IconProps } from "./icon.js";
|
|
30
27
|
|
|
31
|
-
export {
|
|
32
|
-
export type {
|
|
28
|
+
export { imageProps } from "./image.js";
|
|
29
|
+
export type { ImageProps } from "./image.js";
|
|
33
30
|
|
|
34
|
-
export {
|
|
35
|
-
export type {
|
|
31
|
+
export { progressProps } from "./progress.js";
|
|
32
|
+
export type { ProgressProps } from "./progress.js";
|
|
36
33
|
|
|
37
|
-
export {
|
|
38
|
-
export type {
|
|
34
|
+
export { separatorProps } from "./separator.js";
|
|
35
|
+
export type { SeparatorProps } from "./separator.js";
|
|
39
36
|
|
|
40
|
-
export {
|
|
41
|
-
export type {
|
|
37
|
+
export { sliderProps } from "./slider.js";
|
|
38
|
+
export type { SliderProps } from "./slider.js";
|
|
42
39
|
|
|
43
40
|
export { stackProps } from "./stack.js";
|
|
44
41
|
export type { StackProps } from "./stack.js";
|
|
45
42
|
|
|
46
|
-
export {
|
|
47
|
-
export type {
|
|
43
|
+
export { textProps } from "./text.js";
|
|
44
|
+
export type { TextProps } from "./text.js";
|
package/src/ui/input.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
|
|
3
|
+
export const INPUT_TYPES = ["text", "number"] as const;
|
|
4
|
+
export const INPUT_MAX_CHARS = 280;
|
|
5
|
+
export const INPUT_MAX_LABEL_CHARS = 60;
|
|
6
|
+
export const INPUT_MAX_PLACEHOLDER_CHARS = 60;
|
|
7
|
+
|
|
8
|
+
export const inputProps = z.object({
|
|
9
|
+
name: z.string().min(1),
|
|
10
|
+
type: z.enum(INPUT_TYPES).optional(),
|
|
11
|
+
label: z.string().max(INPUT_MAX_LABEL_CHARS).optional(),
|
|
12
|
+
placeholder: z.string().max(INPUT_MAX_PLACEHOLDER_CHARS).optional(),
|
|
13
|
+
defaultValue: z.string().optional(),
|
|
14
|
+
maxLength: z.number().int().min(1).max(INPUT_MAX_CHARS).optional(),
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
export type InputProps = z.infer<typeof inputProps>;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
|
|
3
|
+
import { STACK_GAPS } from "./stack.js";
|
|
4
|
+
|
|
5
|
+
export const itemGroupProps = z.object({
|
|
6
|
+
border: z.boolean().optional(),
|
|
7
|
+
separator: z.boolean().optional(),
|
|
8
|
+
gap: z.enum(STACK_GAPS).optional(),
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
export type ItemGroupProps = z.infer<typeof itemGroupProps>;
|
package/src/ui/item.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
|
|
3
|
+
export const ITEM_VARIANTS = ["default", "outline", "muted"] as const;
|
|
4
|
+
export const ITEM_MAX_TITLE_CHARS = 100;
|
|
5
|
+
export const ITEM_MAX_DESCRIPTION_CHARS = 160;
|
|
6
|
+
|
|
7
|
+
export const itemProps = z.object({
|
|
8
|
+
title: z.string().min(1).max(ITEM_MAX_TITLE_CHARS),
|
|
9
|
+
description: z.string().max(ITEM_MAX_DESCRIPTION_CHARS).optional(),
|
|
10
|
+
variant: z.enum(ITEM_VARIANTS).optional(),
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
export type ItemProps = z.infer<typeof itemProps>;
|
package/src/ui/progress.ts
CHANGED
|
@@ -1,11 +1,29 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
import { PROGRESS_COLOR_VALUES } from "../colors.js";
|
|
3
2
|
|
|
4
|
-
export const
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
3
|
+
export const PROGRESS_MAX_LABEL_CHARS = 60;
|
|
4
|
+
|
|
5
|
+
export const progressProps = z
|
|
6
|
+
.object({
|
|
7
|
+
value: z.number(),
|
|
8
|
+
max: z.number(),
|
|
9
|
+
label: z.string().max(PROGRESS_MAX_LABEL_CHARS).optional(),
|
|
10
|
+
})
|
|
11
|
+
.superRefine((val, ctx) => {
|
|
12
|
+
if (!Number.isFinite(val.max) || val.max <= 0) {
|
|
13
|
+
ctx.addIssue({
|
|
14
|
+
code: "custom",
|
|
15
|
+
message: `progress max must be a finite number > 0 (got ${val.max})`,
|
|
16
|
+
path: ["max"],
|
|
17
|
+
});
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
if (!Number.isFinite(val.value) || val.value < 0 || val.value > val.max) {
|
|
21
|
+
ctx.addIssue({
|
|
22
|
+
code: "custom",
|
|
23
|
+
message: `progress value (${val.value}) must be between 0 and max (${val.max})`,
|
|
24
|
+
path: ["value"],
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
});
|
|
10
28
|
|
|
11
29
|
export type ProgressProps = z.infer<typeof progressProps>;
|
package/src/ui/schema.ts
CHANGED
|
@@ -29,9 +29,9 @@ export const snapJsonRenderSchema = defineSchema(
|
|
|
29
29
|
}),
|
|
30
30
|
{
|
|
31
31
|
defaultRules: [
|
|
32
|
-
"You are generating auxiliary UI for a Farcaster Snap. Prefer components matching snap element types (
|
|
33
|
-
"Snap pages use a Stack root with at most
|
|
34
|
-
"Bottom-of-card snap buttons are
|
|
32
|
+
"You are generating auxiliary UI for a Farcaster Snap. Prefer components matching snap element types (Item, Badge, ButtonGroup, Input, Switch, ToggleGroup, Slider, Progress, Image, Separator).",
|
|
33
|
+
"Snap pages use a Stack root with at most 6 body children and 1 media element (Image); keep generated trees small.",
|
|
34
|
+
"Bottom-of-card snap buttons are Button components; use actions post / link / mini_app / sdk per SPEC.md.",
|
|
35
35
|
],
|
|
36
36
|
},
|
|
37
37
|
);
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
|
|
3
|
+
export const SEPARATOR_ORIENTATIONS = ["horizontal", "vertical"] as const;
|
|
4
|
+
|
|
5
|
+
export const separatorProps = z.object({
|
|
6
|
+
orientation: z.enum(SEPARATOR_ORIENTATIONS).optional(),
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
export type SeparatorProps = z.infer<typeof separatorProps>;
|
package/src/ui/slider.ts
CHANGED
|
@@ -1,14 +1,44 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
|
|
3
|
-
export const
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
3
|
+
export const SLIDER_MAX_LABEL_CHARS = 60;
|
|
4
|
+
export const SLIDER_DEFAULT_STEP = 1;
|
|
5
|
+
export const SLIDER_STEP_ALIGN_EPS = 1e-6;
|
|
6
|
+
|
|
7
|
+
export const sliderProps = z
|
|
8
|
+
.object({
|
|
9
|
+
name: z.string().min(1),
|
|
10
|
+
min: z.number(),
|
|
11
|
+
max: z.number(),
|
|
12
|
+
step: z.number().optional(),
|
|
13
|
+
defaultValue: z.number().optional(),
|
|
14
|
+
label: z.string().max(SLIDER_MAX_LABEL_CHARS).optional(),
|
|
15
|
+
})
|
|
16
|
+
.superRefine((val, ctx) => {
|
|
17
|
+
if (val.min > val.max) {
|
|
18
|
+
ctx.addIssue({
|
|
19
|
+
code: "custom",
|
|
20
|
+
message: `slider min (${val.min}) must be <= max (${val.max})`,
|
|
21
|
+
path: ["min"],
|
|
22
|
+
});
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
if (val.step !== undefined && (val.step <= 0 || !Number.isFinite(val.step))) {
|
|
26
|
+
ctx.addIssue({
|
|
27
|
+
code: "custom",
|
|
28
|
+
message: "slider step must be a finite number > 0",
|
|
29
|
+
path: ["step"],
|
|
30
|
+
});
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
if (val.defaultValue !== undefined) {
|
|
34
|
+
if (val.defaultValue < val.min || val.defaultValue > val.max) {
|
|
35
|
+
ctx.addIssue({
|
|
36
|
+
code: "custom",
|
|
37
|
+
message: `slider defaultValue (${val.defaultValue}) must be between min (${val.min}) and max (${val.max})`,
|
|
38
|
+
path: ["defaultValue"],
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
});
|
|
13
43
|
|
|
14
44
|
export type SliderProps = z.infer<typeof sliderProps>;
|
package/src/ui/stack.ts
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
|
|
3
|
-
export const
|
|
3
|
+
export const STACK_DIRECTIONS = ["vertical", "horizontal"] as const;
|
|
4
|
+
export const STACK_GAPS = ["none", "sm", "md", "lg"] as const;
|
|
5
|
+
export const STACK_JUSTIFY = ["start", "center", "end", "between", "around"] as const;
|
|
6
|
+
|
|
7
|
+
export const stackProps = z.object({
|
|
8
|
+
direction: z.enum(STACK_DIRECTIONS).optional(),
|
|
9
|
+
gap: z.enum(STACK_GAPS).optional(),
|
|
10
|
+
justify: z.enum(STACK_JUSTIFY).optional(),
|
|
11
|
+
});
|
|
4
12
|
|
|
5
13
|
export type StackProps = z.infer<typeof stackProps>;
|
package/src/ui/switch.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
|
|
3
|
+
export const SWITCH_MAX_LABEL_CHARS = 60;
|
|
4
|
+
|
|
5
|
+
export const switchProps = z.object({
|
|
6
|
+
name: z.string().min(1),
|
|
7
|
+
label: z.string().max(SWITCH_MAX_LABEL_CHARS).optional(),
|
|
8
|
+
defaultChecked: z.boolean().optional(),
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
export type SwitchProps = z.infer<typeof switchProps>;
|
package/src/ui/text.ts
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
|
|
2
|
+
|
|
3
|
+
export const TEXT_SIZES = ["lg", "md", "sm"] as const;
|
|
4
|
+
export const TEXT_WEIGHTS = ["bold", "medium", "normal"] as const;
|
|
5
|
+
export const TEXT_ALIGNS = ["left", "center", "right"] as const;
|
|
6
|
+
export const TEXT_MAX_CONTENT_CHARS = 320;
|
|
3
7
|
|
|
4
8
|
export const textProps = z.object({
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
9
|
+
content: z.string().min(1).max(TEXT_MAX_CONTENT_CHARS),
|
|
10
|
+
size: z.enum(TEXT_SIZES).optional(),
|
|
11
|
+
weight: z.enum(TEXT_WEIGHTS).optional(),
|
|
12
|
+
align: z.enum(TEXT_ALIGNS).optional(),
|
|
8
13
|
});
|
|
9
14
|
|
|
10
15
|
export type TextProps = z.infer<typeof textProps>;
|