Skip to content

Commit 6703530

Browse files
authored
Merge pull request #278 from framesjs/dev
Dev
2 parents 55c53e7 + baeb33e commit 6703530

File tree

113 files changed

+1594
-995
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

113 files changed

+1594
-995
lines changed

.changeset/calm-carpets-divide.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@frames.js/render": minor
3+
---
4+
5+
feat: rename types

.changeset/chilly-parrots-sneeze.md

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
"frames.js": patch
3+
"@frames.js/debugger": patch
4+
---
5+
6+
fix: minor bugs and code cleanup

.changeset/clever-impalas-notice.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"create-frames": patch
3+
---
4+
5+
fix: missing basePath in next template

.changeset/curly-badgers-drum.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"docs": patch
3+
---
4+
5+
docs: state management

.changeset/curly-queens-thank.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@frames.js/debugger": patch
3+
---
4+
5+
fix: correctly manipulate url on load and also on change

.changeset/early-turkeys-impress.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@frames.js/render": patch
3+
---
4+
5+
fix: correctly detect image change in order to properly indicate loading state

.changeset/fast-wasps-yawn.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"framesjs-starter": patch
3+
---
4+
5+
fix: state management generic type demo

.changeset/orange-owls-agree.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"create-frames": patch
3+
---
4+
5+
fix: debugger dependency version

.changeset/rotten-taxis-whisper.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"create-frames": patch
3+
---
4+
5+
fix: bump template versions

.changeset/silver-timers-compare.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@frames.js/debugger": patch
3+
---
4+
5+
fix: properly split dev dependencies in debugger

.eslintrc.js

+1-4
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,8 @@
22
/** @type {import("eslint").Linter.Config} */
33
module.exports = {
44
extends: ["@framesjs/eslint-config/library.js"],
5-
parser: "@typescript-eslint/parser",
65
parserOptions: {
76
project: true,
87
},
9-
env: {
10-
jest: true,
11-
},
8+
ignorePatterns: ["**/farcaster/generated/*.ts"],
129
};

.github/workflows/github-actions.yml

+3
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,9 @@ jobs:
5050
- name: Install dependencies
5151
run: yarn --frozen-lockfile
5252

53+
- name: Build
54+
run: yarn build:ci
55+
5356
- name: Lint
5457
run: yarn lint
5558

+72
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
---
2+
title: "Guide: Frames.js State"
3+
description: "Frames.js is the react based framework for making frames. Debugger included."
4+
---
5+
6+
# Guide: State Management in Frames.js
7+
8+
State in Frames.js is a way for you to store data that you want to use in between frames requests. The frames spec allows up to 4kb of data to be stored in the state object.
9+
10+
## Setup
11+
12+
To use state in frames.js, you should declare the initial state in your `createFrames` call. If your state type is not declared explicitly it will be derived from the initial state.
13+
14+
```ts [frames.ts]
15+
import { createFrames } from "@framesjs/next";
16+
17+
export type State = {
18+
count: number;
19+
};
20+
21+
export const frames = createFrames<State>({
22+
initialState: {
23+
count: 0,
24+
},
25+
});
26+
```
27+
28+
## Accessing state
29+
30+
You can access the state object in your frame on the `ctx` parameter. The initial frame will have the state object with the initial values.
31+
32+
```ts [route.tsx]
33+
import { frames } from "./frames";
34+
35+
const handler = frames(async ({ ctx }) => {
36+
return {
37+
image: <div tw="flex">Count: {ctx.state.count}</div>, // [!code focus]
38+
};
39+
});
40+
41+
export const GET = handler;
42+
export const POST = handler;
43+
```
44+
45+
## Updating state
46+
47+
To update the state, you just include the updated state object in your handler's [`FrameDefinition`](/reference/core/createFrames#framedefinition) return value.
48+
49+
```ts [route.tsx]
50+
import { frames, Button } from "./frames";
51+
52+
const handler = frames(async ({ ctx }) => {
53+
const currentState = ctx.state;
54+
55+
// Update the state // [!code focus]
56+
const updatedState = { // [!code focus]
57+
...currentState, // [!code focus]
58+
count: currentState.count + 1, // [!code focus]
59+
}; // [!code focus]
60+
61+
return {
62+
image: <div tw="flex">Count: {updatedState.count}`</div>, // [!code focus],
63+
buttons: [
64+
<Button action="post">Increment</Button>
65+
],
66+
state: updatedState, // [!code focus]
67+
};
68+
});
69+
70+
export const GET = handler;
71+
export const POST = handler;
72+
```

docs/vocs.config.tsx

+7-3
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@ const sidebar = [
2222
text: "Multi-page Frames",
2323
link: "/guides/multiple-frames",
2424
},
25+
{
26+
text: "State Management",
27+
link: "/guides/state-management",
28+
},
2529
{
2630
text: "Deploying your Frame",
2731
link: "/guides/deployment",
@@ -87,9 +91,9 @@ const sidebar = [
8791
link: "/reference/core/remix",
8892
},
8993
{
90-
text: 'Cloudflare Workers',
91-
link: '/reference/core/cloudflare-workers'
92-
}
94+
text: "Cloudflare Workers",
95+
link: "/reference/core/cloudflare-workers",
96+
},
9397
],
9498
},
9599
{
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
import { createFrames } from "frames.js/next";
22

3-
export const frames = createFrames({
3+
type State = {
4+
counter: number;
5+
};
6+
7+
export const frames = createFrames<State>({
48
basePath: "/frames",
59
initialState: { counter: 0 },
610
});

packages/debugger/app/components/frame-debugger.tsx

+26-15
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { getFrameHtmlHead, getFrameFlattened } from "frames.js";
22
import { Dispatch, SetStateAction, useEffect, useMemo, useState } from "react";
33
import React from "react";
4-
import { FrameState, FrameRequest, FrameStackSuccess } from "frames.js/render";
4+
import { FrameState, FrameStackSuccess } from "@frames.js/render";
55
import { Table, TableBody, TableCell, TableRow } from "@/components/table";
66
import {
77
AlertTriangle,
@@ -10,7 +10,6 @@ import {
1010
HomeIcon,
1111
ListIcon,
1212
LoaderIcon,
13-
MessageCircle,
1413
MessageCircleHeart,
1514
RefreshCwIcon,
1615
XCircle,
@@ -190,20 +189,22 @@ export function FrameDebugger({
190189

191190
const [openAccordions, setOpenAccordions] = useState<string[]>([]);
192191

192+
const [latestFrame] = frameState.framesStack;
193+
193194
useEffect(() => {
194195
if (!frameState.isLoading) {
195196
// make sure the first frame is open
196197
if (
197198
!openAccordions.includes(
198-
String(frameState.framesStack[0]?.timestamp.getTime())
199+
String(latestFrame?.timestamp.getTime())
199200
)
200201
)
201202
setOpenAccordions((v) => [
202203
...v,
203-
String(frameState.framesStack[0]?.timestamp.getTime()),
204+
String(latestFrame?.timestamp.getTime()),
204205
]);
205206
}
206-
}, [frameState.isLoading]);
207+
}, [frameState.isLoading, latestFrame?.timestamp, openAccordions]);
207208

208209
return (
209210
<div className="flex flex-row items-start p-4 gap-4 bg-slate-50 max-w-full w-full h-full">
@@ -219,7 +220,6 @@ export function FrameDebugger({
219220
frameState.fetchFrame({
220221
url: frameState?.homeframeUrl,
221222
method: "GET",
222-
request: {},
223223
});
224224
}}
225225
>
@@ -235,7 +235,6 @@ export function FrameDebugger({
235235
frameState.fetchFrame({
236236
url: frameState?.homeframeUrl,
237237
method: "GET",
238-
request: {},
239238
});
240239
}
241240
}}
@@ -246,12 +245,21 @@ export function FrameDebugger({
246245
className="flex flex-row gap-3 items-center shadow-sm border"
247246
variant={"outline"}
248247
onClick={() => {
249-
if (frameState?.framesStack[0]?.request) {
250-
frameState.fetchFrame({
251-
url: frameState?.framesStack[0].url,
252-
method: frameState?.framesStack[0].method,
253-
request: frameState.framesStack[0].request,
254-
} as FrameRequest);
248+
const [latestFrame] = frameState.framesStack;
249+
250+
if (latestFrame) {
251+
frameState.fetchFrame(
252+
latestFrame.method === "GET"
253+
? {
254+
method: "GET",
255+
url: latestFrame.url,
256+
}
257+
: {
258+
method: "POST",
259+
request: latestFrame.request,
260+
url: latestFrame.url,
261+
}
262+
);
255263
}
256264
}}
257265
>
@@ -269,11 +277,14 @@ export function FrameDebugger({
269277
className={`px-4 py-3 flex flex-col gap-2 ${i !== 0 ? "border-t" : "bg-slate-50"} hover:bg-slate-50 w-full`}
270278
key={frameStackItem.timestamp.getTime()}
271279
onClick={() => {
272-
frameState.fetchFrame({
280+
frameState.fetchFrame(frameStackItem.method === 'GET' ? {
281+
method: 'GET',
282+
url: frameStackItem.url,
283+
} : {
273284
url: frameStackItem.url,
274285
method: frameStackItem.method,
275286
request: frameStackItem.request,
276-
} as FrameRequest);
287+
});
277288
}}
278289
>
279290
<span className="flex text-left flex-row w-full">

0 commit comments

Comments
 (0)