Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 22 additions & 22 deletions packages/example-wormhole/package.json
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
{
"name": "@vortexjs/example-wormhole",
"module": "index.ts",
"type": "module",
"license": "MIT-0",
"private": true,
"devDependencies": {
"@types/bun": "catalog:"
},
"dependencies": {
"@vortexjs/core": "workspace:*",
"@vortexjs/dom": "workspace:*",
"@vortexjs/wormhole": "workspace:*",
"tailwindcss": "catalog:",
"valibot": "catalog:"
},
"scripts": {
"dev": "wormhole dev",
"vbuild": "wormhole build vercel"
},
"peerDependencies": {
"typescript": "catalog:"
}
"name": "@vortexjs/example-wormhole",
"module": "index.ts",
"type": "module",
"license": "MIT-0",
"private": true,
"devDependencies": {
"@types/bun": "catalog:"
},
"dependencies": {
"@vortexjs/core": "workspace:*",
"@vortexjs/dom": "workspace:*",
"@vortexjs/wormhole": "workspace:*",
"tailwindcss": "catalog:",
"valibot": "catalog:"
},
"scripts": {
"dev": "wormhole dev",
"vbuild": "wormhole build vercel"
},
"peerDependencies": {
"typescript": "catalog:"
}
}
116 changes: 62 additions & 54 deletions packages/example-wormhole/src/features/home/index.tsx
Original file line number Diff line number Diff line change
@@ -1,67 +1,75 @@
import { useAwait } from "@vortexjs/core";
import { useAction } from "@vortexjs/core/actions";
import { DOMKeyboardActions } from "@vortexjs/dom";
import route, { query } from "@vortexjs/wormhole/route";
import * as v from "valibot";

route("/", {
page() {
const pause = (ms: number) => new Promise(resolve => setTimeout(resolve, ms));
const awaited = useAwait();
page() {
useAction({
name: "Show Alert",
shortcut: "shift+b",
run() {
alert("Action triggered!");
}
})

return (
<>
<h1 class="text-4xl font-bold">
Welcome to Wormhole, {Object.entries(globalThis).length}
</h1>
<p>
This is an example app, go to the{" "}
<a href="/docs/tada">docs</a>
</p>
<button on:click={async () => {
console.log(await add({
a: 1,
b: 2
}))
}}>
add
</button>
</>
);
},
layout({ children }) {
return (
<>
<title>Wormhole Example</title>
{children}
</>
);
},
notFound() {
return (
<>
<h1>404 not found</h1>
</>
)
}
return (
<>
<DOMKeyboardActions />
<h1 class="text-4xl font-bold">
Welcome to Wormhole, {Object.entries(globalThis).length}
</h1>
<p>
This is an example app, go to the{" "}
<a href="/docs/tada">docs</a>
</p>
<button on:click={async () => {
console.log(await add({
a: 1,
b: 2
}))
}}>
add
</button>
</>
);
},
layout({ children }) {
return (
<>
<title>Wormhole Example</title>
{children}
</>
);
},
notFound() {
return (
<>
<h1>404 not found</h1>
</>
)
}
});

route("/docs", {
page({ }) {
const page = "introduction";
return (
<>
<h1>Documentation for {page}</h1>
<p>This is the documentation page for {page}.</p>
</>
);
},
page({ }) {
const page = "introduction";
return (
<>
<h1>Documentation for {page}</h1>
<p>This is the documentation page for {page}.</p>
</>
);
},
});

export const add = query("/api/add", {
schema: v.object({
a: v.number(),
b: v.number()
}),
impl({ a, b }) {
return a + b;
}
schema: v.object({
a: v.number(),
b: v.number()
}),
impl({ a, b }) {
return a + b;
}
})
2 changes: 1 addition & 1 deletion packages/vortex-cli/src/corebind/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { createContext, getImmediateValue, implementIntrinsic, store, type IntrinsicComponent, type Lifetime, type Renderer, type Store } from "@vortexjs/core";
import { createContext, getImmediateValue, store, type IntrinsicComponent, type Lifetime, type Renderer, type Store } from "@vortexjs/core";
import { Box, type TreeNode, Text } from "../tree";
import { fontWeightToPrimitiveBoldness, Frame, Text as TextIntrinsic, type FontWeight } from "@vortexjs/intrinsics";
import { jsx } from "@vortexjs/core/jsx-runtime";
Expand Down
7 changes: 6 additions & 1 deletion packages/vortex-core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"typescript": "catalog:"
},
"scripts": {
"build": "tsdown ./src/index.ts ./src/jsx/jsx-runtime.ts ./src/jsx/jsx-dev-runtime.ts --format esm --dts --out-dir dist"
"build": "tsdown ./src/index.ts ./src/jsx/jsx-runtime.ts ./src/jsx/jsx-dev-runtime.ts ./src/actions/index.tsx --format esm --dts --out-dir dist"
},
"exports": {
".": {
Expand All @@ -31,6 +31,11 @@
"types": "./dist/jsx/jsx-dev-runtime.d.ts",
"import": "./dist/jsx/jsx-dev-runtime.js",
"require": "./dist/jsx/jsx-dev-runtime.cjs"
},
"./actions": {
"types": "./dist/actions/index.d.ts",
"import": "./dist/actions/index.js",
"require": "./dist/actions/index.cjs"
}
},
"version": "2.6.0",
Expand Down
116 changes: 116 additions & 0 deletions packages/vortex-core/src/actions/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
import { getImmediateValue } from "../signal";
import { createContext } from "../context";
import type { JSXChildren, JSXComponent, JSXNode } from "../jsx/jsx-common";
import { useState, type Signal } from "../signal";
import { useHookLifetime, type Lifetime } from "../lifetime";

export type KeyModifier = "ctrl"
| "shift"
| "alt"
| "meta";
export type Key =
| KeyModifier
| "backspace"
| "tab"
| "enter"
| "escape"
| "space"
| "a"
| "b"
| "c"
| "d"
| "e"
| "f"
| "g"
| "h"
| "i"
| "j"
| "k"
| "l"
| "m"
| "n"
| "o"
| "p"
| "q"
| "r"
| "s"
| "t"
| "u"
| "v"
| "w"
| "x"
| "y"
| "z"
| "0"
| "1"
| "2"
| "3"
| "4"
| "5"
| "6"
| "7"
| "8"
| "9";

export type UnionToArray<T, U = T> =
[T] extends [never] ? [] :
T extends any ? [T, ...UnionToArray<Exclude<U, T>>] : [];

export type ModifierList<Modifiers extends KeyModifier[]> =
Modifiers extends [] ? "" :
Modifiers extends [infer First extends KeyModifier, ...infer Rest extends KeyModifier[]] ?
`${First}+${ModifierList<Rest>}` | ModifierList<Rest> :
"";
export type KeyboardShortcut = `${ModifierList<UnionToArray<KeyModifier>>}${Key}`;

export interface Action {
run?(): void | Promise<void>;
shortcut?: KeyboardShortcut
name: string;
icon?: JSXComponent<{}>;
description?: string;
group?: string;
}

export interface ActionContext {
actions: Signal<Action[]>;
addAction(action: Action, lt: Lifetime): void;
}

export const ActionContext = createContext<ActionContext>("ActionContext");

export function ActionProvider(props: {
children: JSXChildren;
}): JSXNode {
const actions = new Set<Action>();
const signal = useState<Action[]>([]);

function update() {
signal.set(Array.from(actions));
}

function addAction(action: Action, lt: Lifetime) {
actions.add(action);
update();
lt.onClosed(() => {
actions.delete(action);
update();
});
}

return <ActionContext value={{ actions: signal, addAction }}>
<>{props.children}</>
</ActionContext>
}

export function useActionContext(): ActionContext {
return getImmediateValue(ActionContext.use());
}

export function useAction(action: Action, lt: Lifetime = useHookLifetime()) {
const ctx = useActionContext();

ctx.addAction(action, lt);

return action;
}
2 changes: 1 addition & 1 deletion packages/vortex-core/src/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ export class StreamingContext {
private updateCallbackImmediate = 0;
private updateCallbacks = new Set<() => void>();
private loadingCounter = 0;
private onDoneLoadingCallback = () => { };
private onDoneLoadingCallback = () => {};
onDoneLoading: Promise<void>;

constructor() {
Expand Down
Loading