add JSX components v2
This commit is contained in:
parent
b5dd0ed413
commit
4b1227149f
25 changed files with 1080 additions and 3 deletions
13
components-jsx/ActionRow.tsx
Normal file
13
components-jsx/ActionRow.tsx
Normal file
|
@ -0,0 +1,13 @@
|
|||
import { ComponentTypes, MessageActionRow, MessageActionRowComponent } from "oceanic.js";
|
||||
|
||||
import { childrenToArray } from "./utils";
|
||||
|
||||
export type ActionRowProps = Omit<MessageActionRow, "type" | "components"> & { children?: MessageActionRowComponent | MessageActionRowComponent[] };
|
||||
|
||||
export function ActionRow(props: ActionRowProps): MessageActionRow {
|
||||
return {
|
||||
type: ComponentTypes.ACTION_ROW,
|
||||
components: childrenToArray(props.children),
|
||||
...props
|
||||
};
|
||||
}
|
16
components-jsx/Button.tsx
Normal file
16
components-jsx/Button.tsx
Normal file
|
@ -0,0 +1,16 @@
|
|||
import { ButtonComponent, ComponentTypes, TextButton, URLButton } from "oceanic.js";
|
||||
|
||||
import { childrenToString } from "./utils";
|
||||
|
||||
export { ButtonStyles } from "oceanic.js";
|
||||
|
||||
type Button = Omit<TextButton, "type" | "label"> | Omit<URLButton, "type" | "label">;
|
||||
export type ButtonProps = Button & { children?: any; };
|
||||
|
||||
export function Button({ children, ...props }: ButtonProps): ButtonComponent {
|
||||
return {
|
||||
type: ComponentTypes.BUTTON,
|
||||
label: childrenToString("Button", children) ?? undefined,
|
||||
...props
|
||||
};
|
||||
}
|
14
components-jsx/ComponentMessage.tsx
Normal file
14
components-jsx/ComponentMessage.tsx
Normal file
|
@ -0,0 +1,14 @@
|
|||
import { CreateMessageOptions, EditMessageOptions, MessageComponent, MessageFlags } from "oceanic.js";
|
||||
|
||||
import { childrenToArray } from "./utils";
|
||||
|
||||
type MessageOptions = CreateMessageOptions | EditMessageOptions;
|
||||
export type ComponentMessageProps = MessageOptions & { children?: MessageComponent[]; };
|
||||
|
||||
export function ComponentMessage({ children, flags, ...props }: ComponentMessageProps): MessageOptions {
|
||||
return {
|
||||
flags: MessageFlags.IS_COMPONENTS_V2 | (flags ?? 0),
|
||||
components: childrenToArray(children),
|
||||
...props
|
||||
};
|
||||
}
|
13
components-jsx/Container.tsx
Normal file
13
components-jsx/Container.tsx
Normal file
|
@ -0,0 +1,13 @@
|
|||
import { ComponentTypes, ContainerComponent } from "oceanic.js";
|
||||
|
||||
import { childrenToArray } from "./utils";
|
||||
|
||||
export type ContainerProps = Omit<ContainerComponent, "type" | "components"> & { children?: ContainerComponent["components"] };
|
||||
|
||||
export function Container({ children, ...props }: ContainerProps): ContainerComponent {
|
||||
return {
|
||||
type: ComponentTypes.CONTAINER,
|
||||
components: childrenToArray(children),
|
||||
...props
|
||||
};
|
||||
}
|
18
components-jsx/File.tsx
Normal file
18
components-jsx/File.tsx
Normal file
|
@ -0,0 +1,18 @@
|
|||
import { ComponentTypes, FileComponent } from "oceanic.js";
|
||||
|
||||
import { MediaItem } from "./MediaItem";
|
||||
|
||||
interface FileProps {
|
||||
filename: string;
|
||||
id?: number;
|
||||
spoiler?: boolean;
|
||||
}
|
||||
|
||||
export function File({ filename, id, spoiler }: FileProps): FileComponent {
|
||||
return {
|
||||
type: ComponentTypes.FILE,
|
||||
id,
|
||||
spoiler,
|
||||
file: <MediaItem url={`attachment://${filename}`} />,
|
||||
};
|
||||
}
|
13
components-jsx/MediaGallery.tsx
Normal file
13
components-jsx/MediaGallery.tsx
Normal file
|
@ -0,0 +1,13 @@
|
|||
import { ComponentTypes, MediaGalleryComponent } from "oceanic.js";
|
||||
|
||||
import { childrenToArray } from "./utils";
|
||||
|
||||
export type MediaGalleryProps = Omit<MediaGalleryComponent, "type" | "items"> & { children: MediaGalleryComponent["items"] };
|
||||
|
||||
export function MediaGallery(props: MediaGalleryProps): MediaGalleryComponent {
|
||||
return {
|
||||
type: ComponentTypes.MEDIA_GALLERY,
|
||||
items: childrenToArray(props.children),
|
||||
...props
|
||||
};
|
||||
}
|
17
components-jsx/MediaGalleryItem.tsx
Normal file
17
components-jsx/MediaGalleryItem.tsx
Normal file
|
@ -0,0 +1,17 @@
|
|||
import type { MediaGalleryItem as MediaGalleryItemComponent } from "oceanic.js";
|
||||
|
||||
import { MediaItem } from "./MediaItem";
|
||||
|
||||
export interface MediaGalleryItemProps {
|
||||
url: string;
|
||||
description?: string;
|
||||
spoiler?: boolean;
|
||||
}
|
||||
|
||||
export function MediaGalleryItem({ url, description, spoiler }: MediaGalleryItemProps): MediaGalleryItemComponent {
|
||||
return {
|
||||
media: <MediaItem url={url} />,
|
||||
description,
|
||||
spoiler,
|
||||
};
|
||||
}
|
7
components-jsx/MediaItem.tsx
Normal file
7
components-jsx/MediaItem.tsx
Normal file
|
@ -0,0 +1,7 @@
|
|||
import { UnfurledMediaItem } from "oceanic.js";
|
||||
|
||||
export type MediaItemProps = UnfurledMediaItem;
|
||||
|
||||
export function MediaItem(props: MediaItemProps): UnfurledMediaItem {
|
||||
return props;
|
||||
}
|
10
components-jsx/MentionableSelect.tsx
Normal file
10
components-jsx/MentionableSelect.tsx
Normal file
|
@ -0,0 +1,10 @@
|
|||
import { ComponentTypes, MentionableSelectMenu } from "oceanic.js";
|
||||
|
||||
export type MentionableSelectProps = Omit<MentionableSelectMenu, "type">;
|
||||
|
||||
export function MentionableSelect(props: MentionableSelectProps): MentionableSelectMenu {
|
||||
return {
|
||||
type: ComponentTypes.MENTIONABLE_SELECT,
|
||||
...props
|
||||
};
|
||||
}
|
10
components-jsx/RoleSelect.tsx
Normal file
10
components-jsx/RoleSelect.tsx
Normal file
|
@ -0,0 +1,10 @@
|
|||
import { ComponentTypes, RoleSelectMenu } from "oceanic.js";
|
||||
|
||||
export type RoleSelectProps = Omit<RoleSelectMenu, "type">;
|
||||
|
||||
export function RoleSelect(props: RoleSelectProps): RoleSelectMenu {
|
||||
return {
|
||||
type: ComponentTypes.ROLE_SELECT,
|
||||
...props
|
||||
};
|
||||
}
|
16
components-jsx/Section.tsx
Normal file
16
components-jsx/Section.tsx
Normal file
|
@ -0,0 +1,16 @@
|
|||
import { ButtonComponent, ComponentTypes, SectionComponent, TextDisplayComponent, ThumbnailComponent } from "oceanic.js";
|
||||
|
||||
import { childrenToArray } from "./utils";
|
||||
|
||||
export interface SectionProps {
|
||||
children: TextDisplayComponent[]
|
||||
accessory: ThumbnailComponent | ButtonComponent;
|
||||
}
|
||||
|
||||
export function Section(props: SectionProps): SectionComponent {
|
||||
return {
|
||||
type: ComponentTypes.SECTION,
|
||||
components: childrenToArray(props.children),
|
||||
...props
|
||||
};
|
||||
}
|
10
components-jsx/Separator.tsx
Normal file
10
components-jsx/Separator.tsx
Normal file
|
@ -0,0 +1,10 @@
|
|||
import { ComponentTypes, SeparatorComponent } from "oceanic.js";
|
||||
|
||||
export type SeparatorProps = Omit<SeparatorComponent, "type">;
|
||||
|
||||
export function Separator(props: SeparatorProps): SeparatorComponent {
|
||||
return {
|
||||
type: ComponentTypes.SEPARATOR,
|
||||
...props
|
||||
};
|
||||
}
|
13
components-jsx/StringSelect.tsx
Normal file
13
components-jsx/StringSelect.tsx
Normal file
|
@ -0,0 +1,13 @@
|
|||
import { ComponentTypes, StringSelectMenu } from "oceanic.js";
|
||||
|
||||
import { childrenToArray } from "./utils";
|
||||
|
||||
export type StringSelectProps = Omit<StringSelectMenu, "type" | "options"> & { children: StringSelectMenu["options"] };
|
||||
|
||||
export function StringSelect(props: StringSelectProps): StringSelectMenu {
|
||||
return {
|
||||
type: ComponentTypes.STRING_SELECT,
|
||||
options: childrenToArray(props.children),
|
||||
...props
|
||||
};
|
||||
}
|
21
components-jsx/TextDisplay.tsx
Normal file
21
components-jsx/TextDisplay.tsx
Normal file
|
@ -0,0 +1,21 @@
|
|||
import { ComponentTypes, TextDisplayComponent } from "oceanic.js";
|
||||
|
||||
import { childrenToString } from "./utils";
|
||||
|
||||
export interface TextDisplayProps {
|
||||
children?: any;
|
||||
id?: number;
|
||||
}
|
||||
|
||||
export function TextDisplay({ children, id }: TextDisplayProps): TextDisplayComponent {
|
||||
children = childrenToString("TextDisplay", children);
|
||||
if (!children) {
|
||||
throw new Error("TextDisplay requires at least one child");
|
||||
}
|
||||
|
||||
return {
|
||||
type: ComponentTypes.TEXT_DISPLAY,
|
||||
content: children,
|
||||
id,
|
||||
};
|
||||
}
|
12
components-jsx/TextInput.tsx
Normal file
12
components-jsx/TextInput.tsx
Normal file
|
@ -0,0 +1,12 @@
|
|||
import { ComponentTypes, TextInput } from "oceanic.js";
|
||||
|
||||
export { TextInputStyles } from "oceanic.js";
|
||||
|
||||
export type TextInputProps = Omit<TextInput, "type">;
|
||||
|
||||
export function TextInput(props: TextInputProps): TextInput {
|
||||
return {
|
||||
type: ComponentTypes.TEXT_INPUT,
|
||||
...props
|
||||
};
|
||||
}
|
11
components-jsx/Thumbnail.tsx
Normal file
11
components-jsx/Thumbnail.tsx
Normal file
|
@ -0,0 +1,11 @@
|
|||
import { ComponentTypes, ThumbnailComponent } from "oceanic.js";
|
||||
|
||||
export type ThumbnailProps = Omit<ThumbnailComponent, "type" | "media"> & { children: ThumbnailComponent["media"] };
|
||||
|
||||
export function Thumbnail(props: ThumbnailProps): ThumbnailComponent {
|
||||
return {
|
||||
type: ComponentTypes.THUMBNAIL,
|
||||
media: props.children,
|
||||
...props
|
||||
};
|
||||
}
|
10
components-jsx/UserSelect.tsx
Normal file
10
components-jsx/UserSelect.tsx
Normal file
|
@ -0,0 +1,10 @@
|
|||
import { ComponentTypes, UserSelectMenu } from "oceanic.js";
|
||||
|
||||
export type UserSelectProps = Omit<UserSelectMenu, "type">;
|
||||
|
||||
export function UserSelect(props: UserSelectProps): UserSelectMenu {
|
||||
return {
|
||||
type: ComponentTypes.USER_SELECT,
|
||||
...props
|
||||
};
|
||||
}
|
17
components-jsx/index.ts
Normal file
17
components-jsx/index.ts
Normal file
|
@ -0,0 +1,17 @@
|
|||
export * from "./ActionRow";
|
||||
export * from "./Button";
|
||||
export * from "./ComponentMessage";
|
||||
export * from "./Container";
|
||||
export * from "./File";
|
||||
export * from "./MediaGallery";
|
||||
export * from "./MediaGalleryItem";
|
||||
export * from "./MediaItem";
|
||||
export * from "./MentionableSelect";
|
||||
export * from "./RoleSelect";
|
||||
export * from "./Section";
|
||||
export * from "./Separator";
|
||||
export * from "./StringSelect";
|
||||
export * from "./TextDisplay";
|
||||
export * from "./TextInput";
|
||||
export * from "./Thumbnail";
|
||||
export * from "./UserSelect";
|
11
components-jsx/runtime.ts
Normal file
11
components-jsx/runtime.ts
Normal file
|
@ -0,0 +1,11 @@
|
|||
export const Fragment = Symbol("ComponentsJsx.Fragment");
|
||||
|
||||
export function createElement(type: typeof Fragment | ((props: any) => any), props: any, ...children: any[]) {
|
||||
if (type === Fragment) {
|
||||
return children;
|
||||
}
|
||||
|
||||
props ??= {};
|
||||
props.children = children;
|
||||
return type(props);
|
||||
}
|
29
components-jsx/utils.ts
Normal file
29
components-jsx/utils.ts
Normal file
|
@ -0,0 +1,29 @@
|
|||
const isFalseOrNullish = (value: any) => value === false || value == null;
|
||||
const isNotFalseOrNullish = (value: any) => !isFalseOrNullish(value);
|
||||
|
||||
export function filterChildren(children: any[]) {
|
||||
return children.filter(isNotFalseOrNullish);
|
||||
}
|
||||
|
||||
export function childrenToString(name: string, children: any) {
|
||||
if (Array.isArray(children)) {
|
||||
return filterChildren(children).join("\n");
|
||||
}
|
||||
if (typeof children === "string") {
|
||||
return children;
|
||||
}
|
||||
if (isFalseOrNullish(children)) {
|
||||
return null;
|
||||
}
|
||||
throw new Error(`${name} children must be a string or an array of strings`);
|
||||
}
|
||||
|
||||
export function childrenToArray(children: any) {
|
||||
if (Array.isArray(children)) {
|
||||
return filterChildren(children);
|
||||
}
|
||||
if (isFalseOrNullish(children)) {
|
||||
return [];
|
||||
}
|
||||
return [children];
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue