### Install Reka.js Core and Types packages
Source: https://github.com/prevwong/reka.js/blob/main/docs/guides/getting-started.md
Installs the necessary `@rekajs/types` and `@rekajs/core` packages using npm. These packages provide APIs for creating Reka data types (AST nodes) and for instantiating the Reka engine.
```npm
npm install @rekajs/types @rekajs/core
```
--------------------------------
### Run Next.js Development Server
Source: https://github.com/prevwong/reka.js/blob/main/examples/02-collab/README.md
Start the local development server for the Next.js application. This allows you to access the application in your browser at `http://localhost:3000` and enables hot-reloading for development.
```bash
npm run dev
# or
yarn dev
# or
pnpm dev
```
--------------------------------
### Run Next.js Development Server
Source: https://github.com/prevwong/reka.js/blob/main/examples/01-react/README.md
Commands to start the Next.js development server using npm, yarn, or pnpm. The server will typically run on http://localhost:3000, and pages will auto-update upon file edits.
```bash
npm run dev
# or
yarn dev
# or
pnpm dev
```
--------------------------------
### React equivalent of Reka.js App component
Source: https://github.com/prevwong/reka.js/blob/main/docs/guides/getting-started.md
Shows the equivalent React component for the 'App' component defined in the Reka.js State. This illustrates how the Reka AST translates to a standard React functional component.
```tsx
const App = () => {
return
Hello World
;
};
```
--------------------------------
### Create a Reka.js Frame to evaluate a component instance
Source: https://github.com/prevwong/reka.js/blob/main/docs/guides/getting-started.md
Demonstrates how to create a new `Frame` instance from a Reka instance. The `Frame` evaluates a specific component, in this case, the 'App' component, to produce a renderable `View`.
```tsx
const reka = Reka.create(...);
const frame = await reka.createFrame({
id: 'my-app-component',
component: {
name: 'App',
props: {}
}
});
```
--------------------------------
### Install Reka Collaboration Package and Dependencies
Source: https://github.com/prevwong/reka.js/blob/main/docs/guides/realtime.md
Command to install the @rekajs/collaboration package along with yjs and y-webrtc. y-webrtc is used as a WebRTC connector example, but other Yjs connectors can be used.
```shell
npm install @rekajs/collaboration yjs y-webrtc
```
--------------------------------
### Define initial Reka.js State with an App component
Source: https://github.com/prevwong/reka.js/blob/main/docs/guides/getting-started.md
Initializes a new Reka instance and loads an initial `State` data type. This State includes a basic 'App' component with a 'Hello World!' text, defining the application's initial structure using Reka's type system.
```tsx
import { Reka } from '@rekajs/core';
import * as t from '@rekajs/types';
const reka = Reka.create();
reka.load(
t.state({
program: t.program({
globals: [],
components: [
t.rekaComponent({
name: 'App',
props: [],
state: [],
template: t.tagTemplate({
tag: 'div',
props: {},
children: [
t.tagTemplate({
tag: 'text',
props: {
value: t.literal({
value: 'Hello World!',
}),
},
children: [],
}),
],
}),
}),
],
}),
})
);
```
--------------------------------
### Watch and Change Reka Component Template Tag
Source: https://github.com/prevwong/reka.js/blob/main/docs/guides/getting-started.md
Demonstrates how to subscribe to changes in a Reka `State` or `View` data structure using `reka.watch` and how to trigger changes using `reka.change`. It specifically shows modifying and observing the tag of an `appComponent.template`.
```tsx
reka.watch(() => {
if (appComponent.template instanceof t.TagTemplate) {
console.log('appComponent =>', appComponent.template.tag);
}
});
reka.change(() => {
// Since we know the type of appComponent.template, we can use t.assert to assert the type
t.assert(appComponent.template, t.TagTemplate).tag = 'section';
});
// 1)
// console:
// appComponent => section
reka.change(() => {
t.assert(appComponent.template, t.TagTemplate).tag = 'div';
});
// 2)
// console:
// appComponent => div
```
--------------------------------
### Install @rekajs/types Package
Source: https://github.com/prevwong/reka.js/blob/main/packages/types/README.md
Instructions to install the @rekajs/types package using npm.
```shell
npm install @rekajs/types
```
--------------------------------
### Watch and Change Reka View Root Tag
Source: https://github.com/prevwong/reka.js/blob/main/docs/guides/getting-started.md
Illustrates how to watch for changes made to a resulting `View` and observe the root tag of the `frame.view`. It uses `reka.watch` to log the tag and `reka.change` to modify the `appComponent.template` which in turn affects the `View`.
```tsx
reka.watch(() => {
if (frame.view) {
console.log(
'frame root tag =>',
t.assert(frame.view.render[0], t.TagView).tag
);
}
});
reka.change(() => {
t.assert(appComponent.template, t.TagTemplate).tag = 'section';
});
// console:
// frame root tag => section
```
--------------------------------
### Start Reka.js Development Server and Watch Packages
Source: https://github.com/prevwong/reka.js/blob/main/CONTRIBUTING.md
This command initiates the development workflow for Reka.js. It watches for changes and rebuilds all packages within the monorepo, and simultaneously starts the main `/site` application in development mode, enabling live development.
```Bash
pnpm dev
```
--------------------------------
### Mutate Reka.js State by adding a new element
Source: https://github.com/prevwong/reka.js/blob/main/docs/guides/getting-started.md
Demonstrates how to modify the Reka `State` by adding a new `` element to the 'App' component's template. All state changes must be wrapped within the `.change()` method to ensure proper tracking and updates.
```tsx
const appComponent = reka.program.components[0];
reka.change(() => {
appComponent.template.children.push(
t.tagTemplate({
tag: 'button',
props: {},
children: [
t.tagTemplate({
tag: 'text',
props: {
value: t.literal({ value: 'Click me!' }),
},
children: [],
}),
],
})
);
});
console.log(appComponent.template.children[1]);
// console:
{ type: "TagTemplate", tag: "button", props: {}, children: [...] }
```
--------------------------------
### Install Reka.js Project Dependencies
Source: https://github.com/prevwong/reka.js/blob/main/CONTRIBUTING.md
This command installs all required dependencies for the Reka.js monorepo. It should be executed in the root directory of the project to ensure all packages and applications have their necessary components.
```Bash
pnpm install
```
--------------------------------
### Observe automatic View updates after Reka.js State mutation
Source: https://github.com/prevwong/reka.js/blob/main/docs/guides/getting-started.md
Shows that `Frame` instances automatically update their `View` property to reflect changes made to the Reka `State`. This example demonstrates the `Frame.view` reflecting the newly added button element after a state mutation, highlighting Reka's reactive nature.
```tsx
// from previous example
const frame = await reka.createFrame(...)
reka.change(() => {});
console.log(appComponent.template.children[1]);
console.log(frame.view);
// console:
{
type: "RekaComponentView",
render: [{
type: 'TagView',
tag: 'div',
props: {},
children: [
{
type: 'TagView',
tag: 'text',
props: {
value: 'Hello World!',
},
children: []
},
// View has been updated to contain the following child View
// as a result of the mutation to add a new TagTemplate in the State
{
type: 'TagView',
tag: 'button',
props: {},
children: [
{
type: 'TagView',
tag: 'text',
props: { value: 'Click me!' },
children: []
}
]
}
]
}]
}
```
--------------------------------
### Install @rekajs/parser Package
Source: https://github.com/prevwong/reka.js/blob/main/docs/guides/react.md
This command installs the `@rekajs/parser` package, which is essential for parsing user inputs into an Abstract Syntax Tree (AST) Node. This allows dynamic text values to be correctly interpreted as Reka expressions.
```shell
npm install @rekajs/parser
```
--------------------------------
### Basic Reka Realtime Collaboration Setup with Yjs and WebRTC
Source: https://github.com/prevwong/reka.js/blob/main/docs/guides/realtime.md
Demonstrates the fundamental steps to integrate Reka with Yjs for real-time collaboration using y-webrtc. This includes creating a Yjs Doc and Y.Map, initializing Reka with the CollabExtension, loading the initial state, and binding the WebRTC provider.
```tsx
// app.tsx
import { Reka } from '@rekajs/core';
import * as t from '@rekajs/types';
import { createCollabExtension } from '@rekajs/collaboration';
import * as Y from 'yjs';
import { WebrtcProvider } from 'y-webrtc';
// 1. Create a new Yjs Doc
const doc = new Y.Doc();
// 2. Create a new Y.Map type
// This map will be used to store the flattened Reka state
// Initially, this will be empty; see the section below on how to correctly set the initial state locally
const type = doc.getMap('my-collaborative-editor');)
const CollabExtension = createCollabExtension(type);
// 3. Create a Reka.create instance with an initial State
const reka = Reka.create({
extensions: [CollabExtension],
});
// 4. Get flattend state from Yjs
const document = type.get('document');
// 5. Restore the Reka state
const state = t.unflatten(document.toJSON());
reka.load(state);
// 6. Bind connector
const provider = new WebrtcProvider('collab-room', doc);
```
--------------------------------
### Install @rekajs/collaboration package
Source: https://github.com/prevwong/reka.js/blob/main/packages/collaboration/README.md
Installs the @rekajs/collaboration package, which provides multiplayer capabilities for Reka via Yjs CRDT, using the npm package manager.
```bash
npm install @rekajs/collaboration
```
--------------------------------
### Install Reka React Integration Packages
Source: https://github.com/prevwong/reka.js/blob/main/docs/guides/react.md
Installs the necessary npm packages, including `next` for the React application scaffold and `@rekajs/core`, `@rekajs/types`, `@rekajs/react` for Reka integration. These packages are essential dependencies for building a Reka-powered React application.
```bash
npm install next @rekajs/core @rekajs/types @rekajs/react
```
--------------------------------
### Inspect the Reka.js Frame's computed View
Source: https://github.com/prevwong/reka.js/blob/main/docs/guides/getting-started.md
Illustrates the structure of the `View` object computed by a Reka `Frame`. This `View` represents the hierarchical render output of the evaluated component instance, showing tags, props, and children, similar to a virtual DOM.
```tsx
const view = frame.view;
// view =
{
type: "RekaComponentView",
render: [{
type: 'TagView',
tag: 'div',
props: {},
children: [
{
type: 'TagView',
tag: 'text',
props: {
value: 'Hello World!',
},
children: []
}
]
}]
}
```
--------------------------------
### Wrap React editor with RekaProvider
Source: https://github.com/prevwong/reka.js/blob/main/docs/api/react.md
Demonstrates how to wrap a React application with the `RekaProvider` component to make the Reka instance available throughout the component tree. It shows the basic setup including importing `Reka` and `RekaProvider`, creating a Reka instance, loading data, and rendering the provider.
```tsx
import { Reka } from '@rekajs/core';
import { RekaProvider } from '@rekajs/react';
import * as React from 'react';
const reka = Reka.create();
reka.load(...);
export const App = () => {
return (
...
)
}
```
--------------------------------
### Initialize Reka Instance and React Application Structure
Source: https://github.com/prevwong/reka.js/blob/main/docs/guides/react.md
This TypeScript React snippet demonstrates the basic setup for integrating Reka into a Next.js application. It initializes a Reka instance, loads it with a predefined program containing `App` and `Button` components, and exposes the instance via `RekaProvider`. The `Home` component then renders `Editor` and `Preview` components within the Reka context, showcasing a typical Reka development environment.
```tsx
// src/pages/index.tsx
import { Reka } from '@rekajs/core';
import { RekaProvider } from '@rekajs/react';
import * as t from '@rekajs/types';
import * as React from 'react';
import { Editor } from '@/components/Editor';
import { Preview } from '@/components/Preview';
const reka = Reka.create();
reka.load(
t.state({
extensions: {},
program: t.program({
globals: [
t.val({
name: 'globalText',
init: t.literal({ value: 'Global Text!' })
})
],
components: [
t.rekaComponent({
name: 'App',
props: [],
state: [],
template: t.tagTemplate({
tag: 'div',
props: {
className: t.literal({
value: 'bg-neutral-100 px-3 py-4 w-full h-full'
})
},
children: [
t.tagTemplate({
tag: 'h4',
props: {
className: t.literal({ value: 'text-lg w-full' })
},
children: [
t.tagTemplate({
tag: 'text',
props: {
value: t.literal({ value: 'Hello World' })
},
children: []
})
]
}),
t.componentTemplate({
component: t.identifier({ name: 'Button' }),
props: {},
children: []
})
]
})
}),
t.rekaComponent({
name: 'Button',
props: [
t.componentProp({
name: 'text',
init: t.literal({ value: 'Click me!' })
})
],
state: [t.val({ name: 'counter', init: t.literal({ value: 0 }) })],
template: t.tagTemplate({
tag: 'button',
props: {
className: t.literal({ value: 'rounded border-2 px-3 py-2' }),
onClick: t.func({
params: [],
body: t.block({
statements: [
t.assignment({
left: t.identifier({ name: 'counter' }),
operator: '+=',
right: t.literal({ value: 1 })
})
]
})
})
},
children: [
t.tagTemplate({
tag: 'text',
props: {
value: t.identifier({ name: 'text' })
},
children: []
}),
t.tagTemplate({
tag: 'text',
props: {
value: t.binaryExpression({
left: t.literal({ value: ' -> ' }),
operator: '+',
right: t.identifier({ name: 'counter' })
})
},
children: []
})
]
})
})
]
})
})
);
export default function Home() {
return (
);
}
```
--------------------------------
### Install @rekajs/react-code-editor Package
Source: https://github.com/prevwong/reka.js/blob/main/docs/guides/react.md
This command installs the `@rekajs/react-code-editor` package. This package provides a pre-built, ready-to-use code editor component that can be easily integrated into a React application to directly manipulate Reka state.
```shell
npm install @rekajs/react-code-editor
```
--------------------------------
### Generate Initial Yjs State for Reka.js Editor
Source: https://github.com/prevwong/reka.js/blob/main/examples/02-collab/README.md
To correctly set the initial state for Reka.js when using WebRTC, modify the `/src/constants/state.ts` file. Afterwards, run the specified command to generate an encoded Yjs update, which is stored in `/src/generated/encoded-initial-state.ts` and loaded into the Yjs document on page load.
```bash
pnpm encode-initial-state
```
--------------------------------
### Implementing Real-time Collaboration with Reka.js and Yjs
Source: https://github.com/prevwong/reka.js/blob/main/packages/core/README.md
This example illustrates how to set up real-time collaboration in a Reka.js page editor. It leverages the `@rekajs/collaboration` extension, which provides CRDT capabilities backed by Yjs. The code demonstrates initializing a Yjs document, creating a collaborative type, and integrating it with Reka.js, along with setting up a WebRTC provider for peer-to-peer synchronization.
```tsx
import { Reka } from '@rekajs/core';
import * as t from '@rekajs/types';
import { createCollabExtension } from '@rekajs/collaboration';
import * as Y from 'yjs';
import { WebrtcProvider } from 'y-webrtc';
const doc = new Y.Doc();
const type = doc.getMap('my-collaborative-editor');
const reka = Reka.create({
extensions: [createCollabExtension(type)],
});
reka.load(t.unflatten(type.getMap('document')));
new WebrtcProvider('collab-room', doc);
```
--------------------------------
### Integrate a Reka.js Extension into a Reka Instance
Source: https://github.com/prevwong/reka.js/blob/main/docs/guides/extensions.md
This example illustrates how to register a previously defined extension, such as `CommentExtension`, when creating a new `Reka` instance. By including the extension in the `extension` array during `Reka.create()`, its state and logic become part of the Reka application's lifecycle.
```tsx
import { Reka } from '@rekajs/core';
const CommentExtension = createExtension({...});
const reka = Reka.create({
state: {...},
extension: [
CommentExtension
]
})
```
--------------------------------
### Example `View` output for a Reka component
Source: https://github.com/prevwong/reka.js/blob/main/docs/concepts/frame.md
This `tsx` snippet shows the static `View` output generated by a `Frame` for a component instance. The `View` is a serializable JSON structure representing the rendered component, including its tag, props, and children.
```tsx
{
type: "TagView",
tag: "button",
props: {
className: "bg-blue-900",
},
children: [
{
type: "TagView",
tag: "text",
props: {
value: 0
},
},
{
type: "TagView",
tag: "text",
props: {
value: "I'm enabled!"
}
}
]
}
```
--------------------------------
### Stringify Reka AST to DSL Code
Source: https://github.com/prevwong/reka.js/blob/main/docs/api/parser.md
Illustrates how to use `Parser.stringify` to convert a Reka Abstract Syntax Tree (AST) object, constructed using `@rekajs/types`, back into a human-readable Reka DSL code string. The example includes an AST for a simple 'App' component with state and a template, showing the resulting Reka DSL output.
```tsx
import * as t from '@rekajs/types';
import { Parser } from '@rekajs/parser';
Parser.stringify(
t.program({
components: [
t.rekaComponent({
name: 'App',
state: [t.val({ name: 'counter', init: t.literal({ value: 0 }) })],
props: [],
template: t.tagTemplate({
tag: 'div',
props: {},
children: [
t.tagTemplate({
tag: 'text',
props: { value: 'Hello!' },
children: [],
}),
],
}),
}),
],
})
);
```
```Reka DSL
component App() {
val counter = 0;
} => (
)
```
--------------------------------
### Craft.js EditorState Example and React Rendering
Source: https://github.com/prevwong/reka.js/blob/main/docs/motivation.md
This snippet illustrates the structure of Craft.js's `EditorState`, an implicit tree data structure representing a page's current state. It also shows how this state translates into a simple React component rendering, demonstrating the direct relationship between the state and the UI output.
```tsx
{
"ROOT": {
type: "div",
props: {},
nodes: ["node-a"],
},
"node-a": {
type: "Button",
props: {
text: "Hello World!"
}
nodes: []
}
}
// The above state can be rendered in React like so:
```
--------------------------------
### Example React Component Demonstrating Advanced UI Features
Source: https://github.com/prevwong/reka.js/blob/main/docs/motivation.md
This React component showcases capabilities that a complete page builder should support, including rendering HTML based on props, using JavaScript expressions, managing stateful values with `useState`, conditional rendering, and iterating through arrays to render multiple elements. It highlights the features Reka aims to enable within Craft.js.
```tsx
const posts = [...];
const MyComponent = (props) => {
const [counter, setCounter] = useState(0);
return (
Hello World!
{
props.enabled &&
I'm enabled!
}
{
counter > 0 && (
I'm non-negative!
)
}
{
posts.map(post =>
{post.name} )
}
{
setCounter(counter + 1);
}}>
Increment
)
}
```
--------------------------------
### Reference other RekaComponents within a template
Source: https://github.com/prevwong/reka.js/blob/main/docs/concepts/components.md
Illustrates how a TagTemplate can include other RekaComponent instances as children, allowing for component composition and reusability. This example shows embedding a 'Button' component within another template.
```JSON
{
"type": "TagTemplate",
"name": "div",
"children": [
{
"type": "ComponentTemplate",
"component": { "type": "Identifier", "name": "Button" },
"props": {},
"children": []
}
]
}
```
--------------------------------
### Extending Reka State with Custom Data
Source: https://github.com/prevwong/reka.js/blob/main/packages/core/README.md
This example demonstrates Reka's extensibility, allowing developers to store additional, custom data as part of the core State. It shows how to define a 'CommentExtension' to store comments associated with template elements, including its initial state and how to interact with it using `reka.getExtension` within a `reka.change` block.
```tsx
import { createExtension } from '@rekajs/core';
type CommentState = {
comments: Array<{
templateId: string; // Id of the Template element associated with the comment
content: string;
}>;
};
const CommentExtension = createExtension({
key: 'comments',
state: {
// initial state
comments: [],
},
init: (extension) => {
// do whatever your extension may have to do here
// ie: send some data to the backend or listen to some changes made in State
},
});
// Usage
reka.change(() => {
reka.getExtension(CommentExtension).state.comments.push({
templateId: '...',
content: 'This button tag should be larger!!',
});
});
```
--------------------------------
### Apply Changes to Reka State (TypeScript/TSX)
Source: https://github.com/prevwong/reka.js/blob/main/docs/api/core.md
This example illustrates how to modify the Reka state using the `reka.change` method. This method ensures that state mutations are batched and properly tracked, allowing for efficient updates to the Reka program.
```tsx
reka.change(() => {
reka.components.push(t.rekaComponent(...))
})
```
--------------------------------
### Subscribe to Reka State Changes (TypeScript/TSX)
Source: https://github.com/prevwong/reka.js/blob/main/docs/api/core.md
This example shows how to subscribe to specific parts of the Reka state using `reka.subscribe`. It allows you to define a selector function to extract relevant data and a callback function to react only when that collected data changes, optimizing performance.
```tsx
reka.subscribe(
(state) => ({
componentNames: state.program.components.map((component) => component.name),
}),
(collected) => {
console.log('component names', collected.componentNames);
}
);
```
--------------------------------
### Computing a Portable View Tree from Reka State
Source: https://github.com/prevwong/reka.js/blob/main/docs/introduction.md
This example demonstrates Reka's ability to compute a `View` tree from its internal State. The `View` is a simple, serializable JSON structure that can be efficiently recomputed upon state changes. This portability allows developers to render Reka's output in any UI framework like React, Vue, or Svelte by building a custom renderer.
```tsx
// Compute a View for the Counter component
const frame = await reka.createFrame({
id: 'my-basic-counter-instance',
component: {
name: 'Counter',
props: { initialValue: t.literal({ value: 10 }) }
}
});
console.log(frame.view);
// console:
{
type: "RekaComponentView",
component: { type: "RekaComponent", component: "Counter" },
root: {
type: "TagView",
tag: "p",
props: {},
children: [
{ type: "TagView", tag: "text", props: { value: "My counter: " }},
{ type: "TagView", tag: "text", props: { value: 10 }}
]
}
}
```
--------------------------------
### Defining a Button Component in Reka State AST and React
Source: https://github.com/prevwong/reka.js/blob/main/docs/concepts/state.md
Illustrates how a simple Button component is defined within Reka's `Program` as a `RekaComponent` AST, alongside its equivalent implementation in React. The Reka AST shows the component's structure, props, internal state, and template, while the React example provides a familiar code comparison.
```tsx
{
type: "State",
program: {
type: "Program",
components: [
{
type: "RekaComponent",
name: "Button",
props: [
{ type: "ComponentProp", name: "enabled" }
],
state: [
{
type: "Val",
name: "counter",
init: { type: "Literal", value: 0 }
}
],
template: {
type: "TagTemplate",
tag: "button",
props: {
className: { type: "Literal", value: "bg-blue-900" }
},
children: [
{
type: "TagTemplate",
tag: "text",
props: {
value: { type: "Identifier", name: "counter" }
}
},
{
type: "TagTemplate",
tag: "text",
if: { type: "Identifier", name: "enabled" },
props: {
value: { type: "Identifier", name: "counter" }
}
}
]
}
}
]
}
}
```
```tsx
const Button = ({ enabled }) => {
const [counter, _] = useState(0);
return (
{counter}
{enabled && "I'm enabled!"}
);
};
```
--------------------------------
### Collect values from Reka data types using useReka callback
Source: https://github.com/prevwong/reka.js/blob/main/docs/api/react.md
Shows how to use the `useReka` hook with an optional callback function to derive and collect specific values from Reka's internal state. This example extracts and displays component names from the Reka program state.
```tsx
const Editor = () => {
const { componentNames } = useReka((reka) => ({
componentNames: reka.state.program.components.map(
(component) => component.name
),
}));
return (
{componentNames.map((name) => (
{name}
))}
);
}
```
--------------------------------
### Exposing Custom Functions to Reka.js State
Source: https://github.com/prevwong/reka.js/blob/main/packages/core/README.md
This snippet demonstrates how to expose a custom JavaScript function, such as `getDateTime`, to the Reka.js state. Once exposed, this function can be called from within Reka.js templates, allowing end-users of the page builder to utilize custom logic. The example shows defining the function and then calling it in a `callExpression`.
```tsx
// 1) Expose function to return current time
const reka = Reka.create({
externals: {
functions: [
t.externalFunc({
name: 'getDateTime',
func: () => {
return Date.now();
},
}),
],
},
});
// 2) External function is now accessible throughout the State:
reka.load(
t.state({
program: t.program({
components: [
t.rekaComponent({
name: 'App',
states: [],
props: [],
template: t.tagTemplate({
tag: 'text',
props: {
value: t.binaryExpression({
left: t.literal({ value: 'Current date time is: ' }),
operator: '+',
right: t.callExpression({
identifier: {
name: 'getDateTime', // <-- access exposed function to return current time
external: true,
},
params: {}
})
})
}
})
})
]
})
})
);
```
--------------------------------
### Computing a Reka View from State
Source: https://github.com/prevwong/reka.js/blob/main/packages/core/README.md
This code snippet illustrates how Reka processes its internal State to generate a 'View' tree. The 'View' is a simple, serializable JSON structure that represents the computed output, making it portable and easy to render across different UI frameworks. The example shows creating a frame for a 'Counter' component instance and logging its resulting 'View'.
```tsx
// Compute a View for the Counter component
const frame = await reka.createFrame({
id: 'my-basic-counter-instance',
component: {
name: 'Counter',
props: { initialValue: t.literal({ value: 10 }) }
}
});
console.log(frame.view);
// console:
{
type: "RekaComponentView",
component: { type: "RekaComponent", component: "Counter" },
root: {
type: "TagView",
tag: "p",
props: {},
children: [
{ type: "TagView", tag: "text", props: { value: "My counter: " }},
{ type: "TagView", tag: "text", props: { value: 10 }}
]
}
}
```
--------------------------------
### React Renderer for Reka `View`
Source: https://github.com/prevwong/reka.js/blob/main/docs/concepts/frame.md
This `tsx` code provides an example of a React renderer that consumes the serializable `View` output from a `Frame`. It recursively processes different `View` types (e.g., `TagView`, `RekaComponentView`, `ExternalComponentView`) to render them into corresponding React elements, showcasing the flexibility of the `View` structure.
```tsx
const Renderer = ({ view }) => {
if (props.view instanceof t.TagView) {
if (props.view.tag === 'text') {
return {props.view.props.value} ;
}
return React.createElement(
props.view.tag,
props.view.props,
props.view.children.map((child) => (
))
);
}
if (props.view instanceof t.RekaComponentView) {
return props.view.render.map((r) => );
}
if (props.view instanceof t.ExternalComponentView) {
return props.view.component.render(props.view.props);
}
if (props.view instanceof t.SlotView || props.view instanceof t.FragmentView) {
return props.view.children.map((r) => );
}
if (props.view instanceof t.ErrorSystemView) {
return (
Something went wrong.
{props.view.error}
);
}
return null;
};
```
--------------------------------
### Get Parent Node in Reka AST (TypeScript/TSX)
Source: https://github.com/prevwong/reka.js/blob/main/docs/api/core.md
This example demonstrates how to retrieve the parent node of a specific Reka AST node using `reka.getParentNode`. It's useful for navigating the abstract syntax tree and understanding the hierarchical relationships between components and program elements.
```tsx
const state = t.state({
program: t.program({
components: [
t.rekaComponent({
name: "App"
...
})
]
})
})
reka.load(state);
const appComponent = state.program.components[0];
console.log(reka.getParentNode(appComponent) === state.program); // true
```
--------------------------------
### Reka Class API Reference
Source: https://github.com/prevwong/reka.js/blob/main/docs/api/core.md
Detailed API documentation for the `Reka` class, including its static creation method and instance methods for state management, change tracking, and AST navigation.
```APIDOC
Reka:
static create(options: {
externals?: {
states?: Record;
functions?: (reka: Reka) => Record;
components?: Array;
};
}): Reka
options: Configuration options for the Reka instance.
externals: Optional external definitions.
states: Initial global state variables.
functions: Functions accessible within Reka.
components: External React components to integrate.
instance methods:
change(callback: () => void): void
callback: A function containing state mutations to be batched.
listenToChangeset(callback: (payload: {
type: 'add' | 'remove' | 'update';
newValue?: any;
oldValue?: any;
name?: string;
path: string[];
}) => void): () => void
callback: Function to call with changeset payload.
Returns: A function to unsubscribe.
getParentNode(node: t.RekaNode): t.RekaNode | undefined
node: The Reka AST node to find the parent of.
Returns: The parent node or undefined if root.
getNodeLocation(node: t.RekaNode): { parent: t.RekaNode; path: (string | number)[]; } | undefined
node: The Reka AST node to find the location of.
Returns: An object containing the parent node and path, or undefined.
subscribe(selector: (state: RekaState) => T, listener: (collected: T) => void): () => void
selector: A function to select specific data from the Reka state.
listener: A callback function invoked when the selected data changes.
Returns: A function to unsubscribe.
watch(callback: () => void): () => void
callback: A function to execute on any Reka state change.
Returns: A function to unsubscribe.
```
--------------------------------
### Basic Usage of Reka.js Parser
Source: https://github.com/prevwong/reka.js/blob/main/docs/api/parser.md
Demonstrates the fundamental import of the `Parser` class from `@rekajs/parser` and its primary methods, `stringify` and `parse`, for general code transformation tasks within the Reka.js ecosystem.
```tsx
import { Parser } from '@rekajs/parser';
Parser.stringify(...);
Parser.parse(...);
```
--------------------------------
### Reka Program Node Syntax
Source: https://github.com/prevwong/reka.js/blob/main/packages/parser/README.md
Illustrates the overall structure of a Reka Program Node, including global variable declarations, component definitions with default prop values, internal state variables (with various expression types), and the basic template rendering syntax.
```Reka-syntax
val globalVariable1 = "hi";
component ComponentName(prop1="default value") {
val stateVariable1 = 0;
val stateWithBinaryExpression = 1+1;
val stateWithBooleanExpression = false;
} => (
)
component AnotherComponentName() {
} => (
)
```
--------------------------------
### Initialize Reka Instance and Create Frames
Source: https://github.com/prevwong/reka.js/blob/main/docs/guides/react.md
This snippet demonstrates how to initialize a Reka instance and manually create `Frame` objects for different components like 'App' and 'Button' with literal props. These frames represent instances of Reka components that will be rendered.
```tsx
// src/pages/index.tsx
import { Reka } from '@rekajs/core';
import { RekaProvider } from '@rekajs/react';
import * as t from '@rekajs/types';
import * as React from 'react';
import { Editor } from '@/components/Editor';
import { Preview } from '@/components/Preview';
const reka = Reka.create();
reka.load(...);
reka.createFrame({
id: 'Main app',
component: {
name: 'App',
},
});
reka.createFrame({
id: 'Primary button',
component: {
name: 'Button',
props: {
text: t.literal({ value: 'Primary button' }),
},
},
});
export default function Home() {...}
```
--------------------------------
### Get Node Location in Reka AST (TypeScript/TSX)
Source: https://github.com/prevwong/reka.js/blob/main/docs/api/core.md
This snippet illustrates how to obtain the location of a Reka AST node within the program using `reka.getNodeLocation`. The returned location includes the parent node and the path (an array of keys/indices) to the node, facilitating precise navigation and identification.
```tsx
const state = t.state({
program: t.program({
components: [
t.rekaComponent({
name: "App"
...
})
]
})
})
reka.load(state);
const appComponent = state.program.components[0];
const location = reka.getNodeLocation(appComponent);
console.log(location.parent === state.program); // true
console.log(location.path) // ["components", 0]
```
--------------------------------
### Create a New Changeset for Reka.js Contributions
Source: https://github.com/prevwong/reka.js/blob/main/CONTRIBUTING.md
Run this command to generate a new Changeset when submitting changes that impact functionality (e.g., bug fixes or new features) within the packages located in the `/packages/` folder. This is a crucial step for tracking and publishing new releases.
```Bash
pnpm changeset
```
--------------------------------
### Apply Encoded Yjs Update to Initialize Reka.js with Collaboration
Source: https://github.com/prevwong/reka.js/blob/main/docs/guides/realtime.md
This code snippet shows how to initialize a Reka.js application with the CollabExtension and an initial state provided by a pre-encoded Yjs update. It covers creating a Yjs document, applying the update, setting up the Reka instance, and binding a WebRTC provider for real-time collaboration.
```TypeScript
// app.tsx
import { Reka } from '@rekajs/core';
import * as t from '@rekajs/types';
import { createCollabExtension } from '@rekajs/collaboration';
import * as Y from 'yjs';
import { WebrtcProvider } from 'y-webrtc';
import { ENCODED_INITIAL_STATE } from './generated/encoded-initial-state';
// 1. Create a new Yjs Doc
const doc = new Y.Doc();
// 2. Create a new Y.Map type
// This map will be used to store the flattened Reka state
// Initially, this will be empty; see the section below on how to correctly set the initial state locally
const type = doc.getMap('my-collaborative-editor');)
// 2.5: Apply initial update! <---
Y.applyUpdate(doc, Buffer.from(ENCODED_INITIAL_STATE, 'base64'));
const CollabExtension = createCollabExtension(type);
// 3. Create a Reka.create instance with an initial State
const reka = Reka.create({
extensions: [CollabExtension],
});
// 4. Get flattend state from Yjs
const document = type.get('document');
// 5. Restore the Reka state
const state = t.unflatten(document.toJSON());
reka.load(state);
// 6. Bind connector
const provider = new WebrtcProvider('collab-room', doc);
```
--------------------------------
### Generate Yjs Initial State Update for Reka.js
Source: https://github.com/prevwong/reka.js/blob/main/docs/guides/realtime.md
This script demonstrates how to set up a dummy Reka instance to serialize its initial state into a Yjs update. The generated update is then encoded in Base64 and saved to a TypeScript file, which can be imported and used to initialize a collaborative Reka application.
```TypeScript
// scripts/generate-encoded-initial-update.ts
import { jsToYType } from '@rekajs/collaboration';
import { Reka } from '@rekajs/core';
import * as t from '@rekajs/types';
import * as Y from 'yjs';
import fs from 'fs';
const doc = new Y.Doc();
const type = doc.getMap('my-collaborative-editor');
// Note: don't include the CollabExtension here
// We are setting up a dummy Reka instance here purely to serialise its State for Y.js
const reka = Reka.create();
reka.load(
t.state({
program: t.program({
components: [
t.rekaComponent(...)
]
}),
})
);
const flattenState = t.flatten(reka.state);
const { converted } = jsToYType(flattenState);
// Store the state in the "document" key of the Y.Map type:
type.set('document', converted);
const update = Y.encodeStateAsUpdate(doc);
const encoded = Buffer.from(update).toString('base64');
// Finally, save the encoded state value in a separate file:
fs.writeFileSync(
'./generated/encoded-initial-update.ts',
`export const ENCODED_INITIAL_STATE = '${encoded}';`
);
```
--------------------------------
### Defining UI Components with Reka AST and React Equivalent
Source: https://github.com/prevwong/reka.js/blob/main/docs/introduction.md
This snippet illustrates how Reka uses an Abstract Syntax Tree (AST) to define UI components, allowing end-users to build complex UIs with stateful values and templating. It shows a Reka AST representation of 'Counter' and 'App' components, alongside their equivalent implementation in React, highlighting Reka's capability to mirror developer-familiar UI framework features.
```tsx
[
{
type: 'RekaComponent',
name: 'Counter',
props: [
{
type: 'ComponentProp',
name: 'initalValue',
init: { type: 'Literal', value: 0 },
},
],
state: [
{
type: 'Val',
name: 'counter',
init: { type: 'Identifier', name: 'initialValue' },
},
],
template: {
type: 'TagTemplate',
tag: 'p',
props: {},
children: [
{
type: 'TagTemplate',
tag: 'text',
props: { value: { type: 'Literal', value: 'My counter: ' } },
},
{
type: 'TagTemplate',
tag: 'text',
props: { value: { type: 'Identifier', value: 'counter' } },
},
],
},
},
{
type: 'RekaComponent',
name: 'App',
state: [],
template: {
type: 'TagTemplate',
tag: 'div',
props: {},
children: [{ type: 'TagTemplate', component: 'Counter', props: {} }],
},
},
];
// which is the equivalent of the following React code:
const Counter = ({ initialValue = 0 }) => {
const [counter, setCounter] = useState(initialValue);
return My Counter: {counter}
;
};
const App = () => {
return (
);
};
```
--------------------------------
### Setting Up Real-time Collaboration with Reka.js and Yjs
Source: https://github.com/prevwong/reka.js/blob/main/README.md
This code illustrates how to enable real-time, multiplayer collaboration in a Reka.js editor. It utilizes the @rekajs/collaboration extension, integrating with Yjs for CRDT-backed synchronization and y-webrtc for peer-to-peer connectivity.
```tsx
import { Reka } from '@rekajs/core';
import * as t from '@rekajs/types';
import { createCollabExtension } from '@rekajs/collaboration';
import * as Y from 'yjs';
import { WebrtcProvider } from 'y-webrtc';
const doc = new Y.Doc();
const type = doc.getMap('my-collaborative-editor');
const reka = Reka.create({
extensions: [createCollabExtension(type)],
});
reka.load(t.unflatten(type.getMap('document')));
new WebrtcProvider('collab-room', doc);
```
--------------------------------
### Reka.js Types API Reference (Classes & Functions)
Source: https://github.com/prevwong/reka.js/blob/main/docs/api/types.md
This section outlines the API documentation for the `@rekajs/types` package, generated from `types/types.docs.ts`. It details the available classes and utility functions, including their methods, properties, parameters, and return types.
```APIDOC
Classes:
- Type:
- Properties: id (string)
- Methods: toJSON(), fromJSON(obj: object)
- Expression (extends Type):
- Subclasses: Literal, BinaryExpression, Identifier, etc.
- Literal (extends Expression):
- Properties: value (any)
- BinaryExpression (extends Expression):
- Properties: left (Expression), operator (string), right (Expression)
Functions:
- match(type: Type, callbacks: object):
- Description: Traverses a Reka type tree and executes callbacks based on type matching.
- Parameters:
- type: The root Reka type to traverse.
- callbacks: An object mapping type names to callback functions.
- Returns: void
- flatten(type: Type):
- Description: Converts a nested Reka type object into a flattened structure.
- Parameters:
- type: The Reka type to flatten.
- Returns: { root: string, types: { [id: string]: object } }
- merge(target: Type, source: Type):
- Description: Applies changes from a source Reka type onto a target type.
- Parameters:
- target: The Reka type to merge into.
- source: The Reka type to merge from.
- Returns: void (modifies target in place)
- unflatten(flattened: { root: string, types: { [id: string]: object } }):
- Description: Reconstructs a nested Reka type object from a flattened structure.
- Parameters:
- flattened: The flattened Reka type structure.
- Returns: Type
- collect(type: Type):
- Description: Gathers all nested Reka type instances within a given root type.
- Parameters:
- type: The root Reka type to collect from.
- Returns: Type[]
- assert(value: any, expectedType: TypeConstructor, callback?: (value: Type) => any):
- Description: Validates if a value is an instance of an expected Reka type.
- Parameters:
- value: The value to assert.
- expectedType: The constructor of the expected Reka type.
- callback (optional): A function to execute on the asserted type.
- Throws: Error if assertion fails.
- Returns: Type | any (if callback is provided)
- clone(type: Type, options?: { replaceExistingIds?: boolean }):
- Description: Creates a deep copy of a Reka type object.
- Parameters:
- type: The Reka type to clone.
- options (optional): Configuration for cloning.
- replaceExistingIds: If true, generates new IDs for cloned types.
- Returns: Type
```
--------------------------------
### Create New Reka Type Instance with Builder
Source: https://github.com/prevwong/reka.js/blob/main/packages/types/README.md
Demonstrates how to create a new Reka type instance, specifically a literal, using the provided builder function from `@rekajs/types`. It also shows the alternative manual instantiation.
```tsx
import * as t from '@rekajs/types';
// Using the builder function
const literal = t.literal({
value: 0
});
// or manually: new Literal({ value: 0 })
```