diff --git a/example/src/index.tsx b/example/src/index.tsx index c4e39df2..5f2de44d 100644 --- a/example/src/index.tsx +++ b/example/src/index.tsx @@ -48,7 +48,32 @@ app.frame('/', (context) => { , , , - status === 'response' && , + status === 'response' && Reset, + ], + } +}) + +app.frame('/buttons', ({ buttonValue }) => { + return { + image: ( +
+ {buttonValue ?? ''} +
+ ), + intents: [ + , + Google, + + Mint + , + Reset, ], } }) diff --git a/src/index.tsx b/src/index.tsx index 8950df58..3f8d1c71 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -11,6 +11,7 @@ import { type Context, Hono } from 'hono' import { ImageResponse } from 'hono-og' import { type JSXNode } from 'hono/jsx' import { jsxRenderer } from 'hono/jsx-renderer' +import type { HtmlEscapedString } from 'hono/utils/html' import { Preview, previewStyles } from './preview.js' import { @@ -263,23 +264,84 @@ export class Farc extends Hono { export type ButtonProps = { children: string index?: number | undefined - type?: 'reset' +} + +export type ButtonRootProps = ButtonProps & { + action?: 'post' | 'post_redirect' value?: string | undefined } // TODO: `fc:frame:button:$idx:action` and `fc:frame:button:$idx:target` -Button.__type = 'button' -export function Button({ children, index = 0, type, value }: ButtonProps) { - return ( +ButtonRoot.__type = 'button' +export function ButtonRoot({ + action = 'post', + children, + index = 0, + value, +}: ButtonRootProps) { + return [ , + , + ] as unknown as HtmlEscapedString +} + +export type ButtonLinkProps = ButtonProps & { + href: string +} + +ButtonLink.__type = 'button' +export function ButtonLink({ children, index = 0, href }: ButtonLinkProps) { + return [ + , + , + , + ] as unknown as HtmlEscapedString +} + +export type ButtonMintProps = ButtonProps & { + target: string +} + +ButtonMint.__type = 'button' +export function ButtonMint({ children, index = 0, target }: ButtonMintProps) { + return [ + , + , + , + ] as unknown as HtmlEscapedString +} + +export type ButtonResetProps = ButtonProps + +ButtonReset.__type = 'button' +export function ButtonReset({ children, index = 0 }: ButtonResetProps) { + return ( + ) } +export const Button = Object.assign(ButtonRoot, { + Link: ButtonLink, + Mint: ButtonMint, + Reset: ButtonReset, +}) + export type TextInputProps = { placeholder?: string | undefined } @@ -302,7 +364,7 @@ function getIntentState( if (!intents) return state if (buttonIndex) { const buttonIntents = intents.filter((intent) => - intent?.props.property.includes('fc:frame:button'), + intent?.props.property.match(/fc:frame:button:\d$/), ) const intent = buttonIntents[buttonIndex - 1] state.buttonValue = intent.props['data-value'] @@ -360,7 +422,7 @@ function parseIntents(intents_: Intents) { return parseIntent(nodes, counter) })() - return Array.isArray(intents) ? intents : [intents] + return (Array.isArray(intents) ? intents : [intents]).flat() } function parseIntent(node_: JSXNode, counter: Counter) {