diff --git a/packages/reacord/package.json b/packages/reacord/package.json index 51e6851..b3f45c2 100644 --- a/packages/reacord/package.json +++ b/packages/reacord/package.json @@ -12,7 +12,7 @@ "require": "./dist/main.cjs" }, "scripts": { - "build": "tsup-node src/main.ts --clean --target node16 --format cjs,esm --dts" + "build": "tsup src/main.ts --clean --target node16 --format cjs,esm --dts" }, "keywords": [], "author": "itsMapleLeaf", @@ -21,6 +21,7 @@ "@types/node": "*", "@types/react": "*", "@types/react-reconciler": "^0.26.4", + "immer": "^9.0.7", "react-reconciler": "^0.26.2" }, "peerDependencies": { diff --git a/packages/reacord/src/components/embed.tsx b/packages/reacord/src/components/embed.tsx index 095e9df..c411b59 100644 --- a/packages/reacord/src/components/embed.tsx +++ b/packages/reacord/src/components/embed.tsx @@ -1,4 +1,5 @@ -import type { ColorResolvable } from "discord.js" +import type { ColorResolvable, MessageEmbedOptions } from "discord.js" +import { raise } from "reacord-helpers/raise" import type { ReactNode } from "react" import * as React from "react" @@ -8,12 +9,99 @@ export type EmbedProps = { } export function Embed(props: EmbedProps) { + const [instance] = React.useState(() => new EmbedInstance()) return ( { - options.embeds ??= [] - options.embeds.push({ color: props.color }) - }} + modifyOptions={(options) => ({ + ...options, + embeds: [ + ...(options.embeds || []), + { + color: props.color, + description: props.children, + }, + ], + })} /> ) } + +export type EmbedTitleProps = { + children?: string + url?: string +} + +export function EmbedTitle(props: EmbedTitleProps) { + const { useEmbedChild } = useEmbedContext() + + useEmbedChild( + React.useCallback( + (options) => { + options.title = props.children + options.url = props.url + }, + [props.children, props.url], + ), + ) + + return <> +} + +function useEmbedContext() { + const instance = + React.useContext(EmbedInstanceContext) ?? + raise("Embed instance provider not found") + + return React.useMemo(() => { + function useEmbedChild( + modifyEmbedOptions: (options: MessageEmbedOptions) => void, + ) { + React.useEffect(() => { + instance.add(modifyEmbedOptions) + return () => instance.remove(modifyEmbedOptions) + }, [modifyEmbedOptions]) + } + + return { useEmbedChild } + }, [instance]) +} + +const EmbedInstanceContext = React.createContext( + undefined, +) + +function EmbedInstanceProvider({ + instance, + children, +}: { + instance: EmbedInstance + children: ReactNode +}) { + return ( + + {children} + + ) +} + +class EmbedInstance { + private children = new Set() + + add(child: EmbedChild) { + this.children.add(child) + } + + remove(child: EmbedChild) { + this.children.delete(child) + } + + getEmbedOptions(): MessageEmbedOptions { + const options: MessageEmbedOptions = {} + for (const child of this.children) { + child(options) + } + return options + } +} + +type EmbedChild = (options: MessageEmbedOptions) => void diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 88476b6..14c964e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -110,6 +110,7 @@ importers: discord.js: ^13.3.1 dotenv: ^10.0.0 esbuild: ^0.14.2 + immer: ^9.0.7 nanoid: ^3.1.30 reacord-helpers: workspace:* react: ^17.0.2 @@ -119,6 +120,7 @@ importers: '@types/node': 17.0.0 '@types/react': 17.0.37 '@types/react-reconciler': 0.26.4 + immer: 9.0.7 react-reconciler: 0.26.2_react@17.0.2 devDependencies: discord.js: 13.3.1 @@ -2817,6 +2819,10 @@ packages: engines: {node: '>= 4'} dev: true + /immer/9.0.7: + resolution: {integrity: sha512-KGllzpbamZDvOIxnmJ0jI840g7Oikx58lBPWV0hUh7dtAyZpFqqrBZdKka5GlTwMTZ1Tjc/bKKW4VSFAt6BqMA==} + dev: false + /import-cwd/3.0.0: resolution: {integrity: sha512-4pnzH16plW+hgvRECbDWpQl3cqtvSofHWh44met7ESfZ8UZOWWddm8hEyDTqREJ9RbYHY8gi8DqmaelApoOGMg==} engines: {node: '>=8'}