diff --git a/packages/reacord/library/core/instance-context.tsx b/packages/reacord/library/core/instance-context.tsx new file mode 100644 index 0000000..da1237f --- /dev/null +++ b/packages/reacord/library/core/instance-context.tsx @@ -0,0 +1,20 @@ +import * as React from "react" +import { raise } from "../../helpers/raise" +import type { ReacordInstance } from "./instance" + +const Context = React.createContext(undefined) + +export const InstanceProvider = Context.Provider + +/** + * Get the associated instance for the current component. + * + * @category Core + * @see https://reacord.fly.dev/guides/use-instance + */ +export function useInstance(): ReacordInstance { + return ( + React.useContext(Context) ?? + raise("Could not find instance, was this component rendered via Reacord?") + ) +} diff --git a/packages/reacord/library/core/reacord.ts b/packages/reacord/library/core/reacord.tsx similarity index 85% rename from packages/reacord/library/core/reacord.ts rename to packages/reacord/library/core/reacord.tsx index b1de60c..d402ffe 100644 --- a/packages/reacord/library/core/reacord.ts +++ b/packages/reacord/library/core/reacord.tsx @@ -1,8 +1,10 @@ import type { ReactNode } from "react" +import React from "react" import type { ComponentInteraction } from "../internal/interaction" import { reconciler } from "../internal/reconciler.js" import type { Renderer } from "../internal/renderers/renderer" import type { ReacordInstance } from "./instance" +import { InstanceProvider } from "./instance-context" /** * @category Core @@ -47,13 +49,12 @@ export abstract class Reacord { const container = reconciler.createContainer(renderer, 0, false, {}) - if (initialContent !== undefined) { - reconciler.updateContainer(initialContent, container) - } - - return { + const instance: ReacordInstance = { render: (content: ReactNode) => { - reconciler.updateContainer(content, container) + reconciler.updateContainer( + {content}, + container, + ) }, deactivate: () => { this.deactivate(renderer) @@ -63,6 +64,12 @@ export abstract class Reacord { renderer.destroy() }, } + + if (initialContent !== undefined) { + instance.render(initialContent) + } + + return instance } private deactivate(renderer: Renderer) { diff --git a/packages/reacord/library/main.ts b/packages/reacord/library/main.ts index 536d7c6..8ae77f1 100644 --- a/packages/reacord/library/main.ts +++ b/packages/reacord/library/main.ts @@ -13,5 +13,6 @@ export * from "./core/components/link" export * from "./core/components/option" export * from "./core/components/select" export * from "./core/instance" +export { useInstance } from "./core/instance-context" export * from "./core/reacord" export * from "./core/reacord-discord-js" diff --git a/packages/reacord/package.json b/packages/reacord/package.json index 1ec2a59..c7027f3 100644 --- a/packages/reacord/package.json +++ b/packages/reacord/package.json @@ -23,7 +23,7 @@ "test": "vitest --coverage --no-watch", "test-dev": "vitest", "typecheck": "tsc --noEmit", - "playground": "nodemon --exec esmo --ext ts,tsx ./playground/main.tsx", + "playground": "nodemon --exec esmo --ext ts,tsx --inspect=5858 --enable-source-maps ./playground/main.tsx", "release": "release-it" }, "dependencies": { diff --git a/packages/reacord/playground/main.tsx b/packages/reacord/playground/main.tsx index b16b72f..2e3492d 100644 --- a/packages/reacord/playground/main.tsx +++ b/packages/reacord/playground/main.tsx @@ -1,7 +1,7 @@ import { Client } from "discord.js" import "dotenv/config" import React from "react" -import { Button, ReacordDiscordJs } from "../library/main" +import { Button, ReacordDiscordJs, useInstance } from "../library/main" import { createCommandHandler } from "./command-handler" import { Counter } from "./counter" import { FruitSelect } from "./fruit-select" @@ -93,6 +93,17 @@ createCommandHandler(client, [ ) }, }, + { + name: "delete-this", + description: "delete this", + run: (interaction) => { + function DeleteThis() { + const instance = useInstance() + return