@unbound-app/api 0.9.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ambient/image-modules.d.ts +58 -0
- package/package.json +30 -5
- package/src/_internal.d.ts +6110 -462
- package/src/{utils.d.ts → _types.d.ts} +10 -0
- package/src/assets.d.ts +64 -26
- package/src/builtins.d.ts +17 -0
- package/src/commands.d.ts +331 -0
- package/src/dialogs.d.ts +134 -0
- package/src/flux.d.ts +317 -0
- package/src/fonts.d.ts +51 -0
- package/src/fs.d.ts +16 -26
- package/src/global.d.ts +514 -31
- package/src/i18n.d.ts +33 -31
- package/src/iconPacks.d.ts +43 -0
- package/src/index.d.ts +16 -0
- package/src/marketplace.d.ts +50 -0
- package/src/metro/api.d.ts +10 -0
- package/src/metro/common.d.ts +34 -5
- package/src/metro/components.d.ts +100 -16
- package/src/metro/filters.d.ts +31 -16
- package/src/metro/index.d.ts +26097 -82
- package/src/metro/stores.d.ts +5 -0
- package/src/native.d.ts +123 -3
- package/src/patcher.d.ts +214 -57
- package/src/plugins.d.ts +55 -0
- package/src/settings.d.ts +9 -17
- package/src/shims.d.ts +5 -0
- package/src/storage.d.ts +80 -223
- package/src/sync.d.ts +51 -0
- package/src/themes.d.ts +43 -0
- package/src/toasts.d.ts +62 -9
- package/src/ui.d.ts +650 -0
- package/src/updates.d.ts +25 -0
- package/src/utils/index.d.ts +53 -0
- package/src/utils/react/index.d.ts +82 -0
- package/testing/fake-api.ts +256 -0
- package/testing/fake-components.ts +183 -0
- package/testing/fake-feedback.ts +258 -0
- package/testing/fake-fs.ts +54 -0
- package/testing/fake-java.ts +513 -0
- package/testing/fake-locales.ts +85 -0
- package/testing/fake-metro.ts +346 -0
- package/testing/fake-native-bridge.ts +98 -0
- package/testing/fake-native.ts +211 -0
- package/testing/fake-objc.ts +388 -0
- package/testing/fake-plugins.ts +176 -0
- package/testing/fake-react-native-modules.ts +362 -0
- package/testing/fake-react-native.ts +180 -0
- package/testing/fake-react.ts +54 -0
- package/testing/fake-settings-panel.ts +173 -0
- package/testing/fake-settings.ts +428 -0
- package/testing/fake-timers.ts +74 -0
- package/testing/fake-utils.ts +216 -0
- package/testing/icu-format.ts +132 -0
- package/testing/icu-parse.ts +277 -0
- package/testing/index.ts +42 -0
- package/testing/install-addon-globals.ts +260 -0
- package/testing/listener-registry.ts +39 -0
- package/testing/memory-storage.ts +149 -0
- package/testing/plugin-files.ts +155 -0
- package/testing/plugin-lifecycle.ts +149 -0
- package/testing/plugin-types.ts +34 -0
- package/testing/preset.ts +263 -0
- package/testing/react-patcher.ts +154 -0
- package/testing/react-value.ts +3 -0
- package/testing/recorders.ts +183 -0
- package/testing/recording-patcher.ts +173 -0
- package/testing/render.ts +84 -0
- package/testing/session.ts +77 -0
- package/testing/test-node.ts +163 -0
- package/testing/test-renderer.ts +753 -0
- package/testing/unfrozen-elements.ts +49 -0
|
@@ -4,10 +4,14 @@ import * as ReactModule from 'react';
|
|
|
4
4
|
import * as ReactNativeModule from 'react-native';
|
|
5
5
|
/** Any supported colour string: a {@link HexColor} or {@link RgbaColor}. */
|
|
6
6
|
export type ColorString = HexColor | RgbaColor;
|
|
7
|
+
/** A Unicode emoji, or a custom emoji's name then `:` and its id. */
|
|
8
|
+
export type EmojiString = string;
|
|
7
9
|
/** The set of all falsy values. */
|
|
8
10
|
export type Falsy = false | 0 | '' | null | undefined;
|
|
9
11
|
/** A hexadecimal colour string prefixed with `#`. */
|
|
10
12
|
export type HexColor = `#${string}`;
|
|
13
|
+
/** An http or https URL, as a `url` setting holds it. */
|
|
14
|
+
export type HttpUrl = `https://${string}` | `http://${string}`;
|
|
11
15
|
/**
|
|
12
16
|
* A string union that keeps `T`'s literals for autocomplete while still accepting any other string,
|
|
13
17
|
* for Discord's open-ended enums (typography variants, colour tokens, sizes).
|
|
@@ -17,6 +21,8 @@ export type LiteralUnion<T extends string> = T | (string & {});
|
|
|
17
21
|
export type PredicateResult = Truthy | false | null | undefined;
|
|
18
22
|
/** An `rgba(...)` colour string. */
|
|
19
23
|
export type RgbaColor = `rgba(${string})`;
|
|
24
|
+
/** A Discord id. */
|
|
25
|
+
export type Snowflake = `${bigint}`;
|
|
20
26
|
/** The set of all truthy values. */
|
|
21
27
|
export type Truthy = true | number | string | object | symbol | bigint;
|
|
22
28
|
/** Widens a literal type to its primitive base (e.g. `'a'` to `string`, `1` to `number`). */
|
|
@@ -27,5 +33,9 @@ export type Widen<T> = T extends number
|
|
|
27
33
|
: T extends boolean
|
|
28
34
|
? boolean
|
|
29
35
|
: T;
|
|
36
|
+
/** `T` without the keys `K`. Unlike `Omit`, it keeps the known keys of a type that also has an index signature. */
|
|
37
|
+
export type Without<T, K extends PropertyKey> = {
|
|
38
|
+
[Key in keyof T as Key extends K ? never : Key]: T[Key];
|
|
39
|
+
};
|
|
30
40
|
|
|
31
41
|
export {};
|
package/src/assets.d.ts
CHANGED
|
@@ -1,51 +1,89 @@
|
|
|
1
1
|
// Auto-generated by generate-plugin-sdk.ts - DO NOT EDIT
|
|
2
2
|
|
|
3
|
-
export type { UnboundAsset } from './_internal';
|
|
4
|
-
import type { UnboundAsset } from './_internal';
|
|
5
|
-
|
|
6
|
-
assets: Map<number, UnboundAsset>;
|
|
7
|
-
find: typeof find;
|
|
8
|
-
getByName: typeof getByName;
|
|
9
|
-
getByID: typeof getByID;
|
|
10
|
-
getIDByName: typeof getIDByName;
|
|
11
|
-
getAll: typeof getAll;
|
|
12
|
-
Icons: Record<string, number | undefined>;
|
|
13
|
-
};
|
|
14
|
-
/** Proxy resolving any property name to its asset id via {@link getIDByName}. */
|
|
15
|
-
export declare const Icons: Record<string, number | undefined>;
|
|
16
|
-
/** Map of discovered asset ids to their resolved {@link UnboundAsset} record. */
|
|
3
|
+
export type { AssetName, AssetType, DiscordAssetName, UnboundAsset } from './_internal';
|
|
4
|
+
import type { AssetName, AssetType, DiscordAssetName, UnboundAsset } from './_internal';
|
|
5
|
+
/** Map of registered asset ids to their {@link UnboundAsset} record. */
|
|
17
6
|
export declare const assets: Map<number, UnboundAsset>;
|
|
7
|
+
/** Proxy resolving any property name to its PNG asset id via {@link getIdByName}; Discord's names are suggested. */
|
|
8
|
+
export declare const icons: Readonly<Partial<Record<DiscordAssetName<'png'>, number>>> &
|
|
9
|
+
Readonly<Record<string, number | undefined>>;
|
|
18
10
|
/**
|
|
19
|
-
* @description Finds the first
|
|
11
|
+
* @description Finds the first asset matching the given predicate, initializing every asset module first.
|
|
20
12
|
* @param filter Predicate run against each asset.
|
|
21
13
|
* @returns The matched {@link UnboundAsset}, or `undefined` if none match.
|
|
22
14
|
*/
|
|
23
15
|
export declare function find(filter: (asset: UnboundAsset) => boolean): UnboundAsset | undefined;
|
|
24
16
|
/**
|
|
25
|
-
* @description Returns every
|
|
17
|
+
* @description Returns every asset, initializing every asset module first.
|
|
26
18
|
* @returns An array of all registered {@link UnboundAsset} records.
|
|
27
19
|
*/
|
|
28
20
|
export declare function getAll(): UnboundAsset[];
|
|
29
21
|
/**
|
|
30
|
-
* @description Looks up a
|
|
22
|
+
* @description Looks up a registered asset by its id.
|
|
31
23
|
* @param id The asset id to look up.
|
|
32
24
|
* @returns The matched {@link UnboundAsset}, or `undefined` if none is registered for that id.
|
|
33
25
|
*/
|
|
34
|
-
export declare function
|
|
26
|
+
export declare function getById(id: number): UnboundAsset | undefined;
|
|
35
27
|
/**
|
|
36
|
-
* @description Finds
|
|
28
|
+
* @description Finds an asset by its name and type, initializing the module that registers it if needed.
|
|
29
|
+
* @template T The asset's file type, which picks the names suggested for `name`.
|
|
37
30
|
* @param name The asset name to match.
|
|
38
|
-
* @param type The asset type to match.
|
|
31
|
+
* @param type The asset type to match, `png` by default.
|
|
39
32
|
* @returns The matched {@link UnboundAsset}, or `undefined` if none match.
|
|
40
33
|
*/
|
|
41
|
-
export declare function getByName
|
|
34
|
+
export declare function getByName<T extends AssetType = 'png'>(
|
|
35
|
+
name: AssetName<T>,
|
|
36
|
+
type?: T,
|
|
37
|
+
): UnboundAsset | undefined;
|
|
42
38
|
/**
|
|
43
|
-
* @description Looks up
|
|
39
|
+
* @description Looks up an asset's id by its name and type, initializing the module that registers it if needed.
|
|
40
|
+
* @template T The asset's file type, which picks the names suggested for `name`.
|
|
44
41
|
* @param name The asset name to match.
|
|
45
|
-
* @param type The asset type to match.
|
|
42
|
+
* @param type The asset type to match, `png` by default.
|
|
46
43
|
* @returns The matched asset's id, or `undefined` if none match.
|
|
47
44
|
*/
|
|
48
|
-
export declare function
|
|
49
|
-
|
|
50
|
-
|
|
45
|
+
export declare function getIdByName<T extends AssetType = 'png'>(
|
|
46
|
+
name: AssetName<T>,
|
|
47
|
+
type?: T,
|
|
48
|
+
): number | undefined;
|
|
49
|
+
/**
|
|
50
|
+
* @description Calls `listener` with each asset registered from now on.
|
|
51
|
+
* @param listener Receives the asset and its id.
|
|
52
|
+
* @returns A function that removes the listener.
|
|
53
|
+
*/
|
|
54
|
+
export declare function onAssetRegistered(listener: AssetRegistrationListener): () => void;
|
|
55
|
+
/**
|
|
56
|
+
* @description Registers an image generated at runtime, such as a `data:` URI or a file the plugin wrote, with
|
|
57
|
+
* Discord's asset registry, so `<Image source={id}>` and Discord's icon props draw it. Images a plugin imports
|
|
58
|
+
* are registered for it. A plugin's names never collide with another's, and its registrations end when it stops.
|
|
59
|
+
* @param options The image: its name, `uri` or `path`, size in points, type and other `scales`.
|
|
60
|
+
* @returns The asset's id, and `unregister`.
|
|
61
|
+
*/
|
|
62
|
+
export declare function register(options: AssetRegistration): RegisteredAsset;
|
|
63
|
+
/** An image to register with Discord's asset registry, so `<Image source={id}>` and Discord's icon props draw it. */
|
|
64
|
+
export type AssetRegistration = {
|
|
65
|
+
/** The asset's name; a plugin's names are kept apart from every other plugin's. */
|
|
66
|
+
name: string;
|
|
67
|
+
/** The image's URI at scale 1, such as a `data:` or `file://` URI. */
|
|
68
|
+
uri?: string;
|
|
69
|
+
/** The image file at scale 1, as an absolute path such as `${fs.documentsPath}/MyPlugin/star.png`. */
|
|
70
|
+
path?: string;
|
|
71
|
+
/** Width in points. */
|
|
72
|
+
width: number;
|
|
73
|
+
/** Height in points. */
|
|
74
|
+
height: number;
|
|
75
|
+
/** The file type, such as `png`. */
|
|
76
|
+
type: string;
|
|
77
|
+
/** The image at other pixel densities, as URIs or absolute paths by scale, such as `{ 2: '/…/star@2x.png' }`. */
|
|
78
|
+
scales?: Record<number, string>;
|
|
79
|
+
};
|
|
80
|
+
/** Called with each asset Discord registers, and its id. */
|
|
81
|
+
export type AssetRegistrationListener = (asset: UnboundAsset, id: number) => void;
|
|
82
|
+
/** A registered asset: its id, and the function that takes it out of the registry. */
|
|
83
|
+
export type RegisteredAsset = {
|
|
84
|
+
/** The asset registry id, which an image `source` or an `icon` option takes. */
|
|
85
|
+
id: number;
|
|
86
|
+
/** Takes the asset out of the registry; registering its name again reuses the id. */
|
|
87
|
+
unregister: () => void;
|
|
88
|
+
};
|
|
51
89
|
export {};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
// Auto-generated by generate-plugin-sdk.ts - DO NOT EDIT
|
|
2
|
+
|
|
3
|
+
/** Starts a built-in feature under a name, skipping a name already registered. */
|
|
4
|
+
export declare const register: (name: string, builtin: BuiltIn) => void;
|
|
5
|
+
/** Stops the built-in feature registered under a name. */
|
|
6
|
+
export declare const unregister: (name: string) => void;
|
|
7
|
+
/** A built-in feature exposing optional `start`/`stop` lifecycle hooks. */
|
|
8
|
+
export type BuiltIn = {
|
|
9
|
+
/** Runs when the built-in is registered; if it throws, the built-in is logged and left inactive. */
|
|
10
|
+
start?: () => void;
|
|
11
|
+
/** Runs when the built-in is unregistered or the built-ins shut down, in reverse start order. */
|
|
12
|
+
stop?: () => void;
|
|
13
|
+
/** Checked once at initialisation; returning `false` skips registering the built-in. */
|
|
14
|
+
shouldStart?: () => boolean;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export {};
|
|
@@ -0,0 +1,331 @@
|
|
|
1
|
+
// Auto-generated by generate-plugin-sdk.ts - DO NOT EDIT
|
|
2
|
+
|
|
3
|
+
declare const valueType: unique symbol;
|
|
4
|
+
/** Option builders, one per kind: `option.string({ required: true })`, `option.user()`, `option.choice({ ... })`. */
|
|
5
|
+
export declare const option: OptionBuilders;
|
|
6
|
+
/**
|
|
7
|
+
* @description Creates the commands handle for one owner, like `createPatcher` does for patches. A plugin passes
|
|
8
|
+
* its manifest id, so its commands are removed when it stops; a built-in passes `'unbound'`. Text is message keys.
|
|
9
|
+
* @param owner The plugin id, or `'unbound'` for a built-in.
|
|
10
|
+
* @param options The owner's own picker section; omitted, the shared Unbound section.
|
|
11
|
+
* @returns The handle.
|
|
12
|
+
*/
|
|
13
|
+
export declare function createCommands(owner: string, options?: CommandsOptions): CommandsHandle;
|
|
14
|
+
/**
|
|
15
|
+
* @description Adds commands to the shared Unbound section of the `/` picker. Registering a root name again
|
|
16
|
+
* replaces that whole command; a root name another owner has throws `CommandDefinitionError`.
|
|
17
|
+
* @template T The command tree, inferred from it.
|
|
18
|
+
* @param commands The commands, keyed by root name.
|
|
19
|
+
* @returns A function that removes this call's commands; it is safe to call twice.
|
|
20
|
+
*/
|
|
21
|
+
export declare function register<T>(commands: CommandTree<T>): () => void;
|
|
22
|
+
/**
|
|
23
|
+
* @description Removes a root command added with `register`, with its subcommands. Does nothing when there is none.
|
|
24
|
+
* @param name The root command's name.
|
|
25
|
+
*/
|
|
26
|
+
export declare function unregister(name: string): void;
|
|
27
|
+
/** Suggests values for an option while the user types. At most 25 are shown. */
|
|
28
|
+
export type Autocomplete<V extends string | number> = (
|
|
29
|
+
query: string,
|
|
30
|
+
context: AutocompleteContext,
|
|
31
|
+
) => Awaitable<readonly Choice<V>[]>;
|
|
32
|
+
/** What autocomplete sees: where it runs and the raw values of the other options filled in so far. */
|
|
33
|
+
export type AutocompleteContext = CommandContext & {
|
|
34
|
+
values: Readonly<Record<string, RawOptionValue>>;
|
|
35
|
+
};
|
|
36
|
+
/** A value, or a promise of one. */
|
|
37
|
+
export type Awaitable<T> = T | Promise<T>;
|
|
38
|
+
/** Settings every builder accepts. */
|
|
39
|
+
export type BuilderInput<K extends OptionKind, R extends boolean> = OptionSettings<K> & {
|
|
40
|
+
/** The message key of the text the picker shows for the option; 1 to 100 characters in en-US. Omitted, its name. */
|
|
41
|
+
description?: CommandMessageKey;
|
|
42
|
+
/** Whether Discord requires the option. Defaults to `false`. */
|
|
43
|
+
required?: R;
|
|
44
|
+
};
|
|
45
|
+
/** Settings of `option.channel`. */
|
|
46
|
+
export type ChannelOptionSettings = {
|
|
47
|
+
/** Discord channel types the picker offers. */
|
|
48
|
+
channelTypes?: readonly number[];
|
|
49
|
+
};
|
|
50
|
+
/** An autocomplete suggestion: a bare value, shown as itself, or a value with a label. */
|
|
51
|
+
export type Choice<V extends string | number> = V | ChoiceWithLabel<V>;
|
|
52
|
+
/** Settings `option.choice` accepts. */
|
|
53
|
+
export type ChoiceInput<R extends boolean> = {
|
|
54
|
+
/** The message key of the text the picker shows for the option; 1 to 100 characters in en-US. Omitted, its name. */
|
|
55
|
+
description?: CommandMessageKey;
|
|
56
|
+
/** Whether Discord requires the option. Defaults to `false`. */
|
|
57
|
+
required?: R;
|
|
58
|
+
};
|
|
59
|
+
/** Each value `option.choice` allows, mapped to the message key of its label. Labels must differ in en-US. */
|
|
60
|
+
export type ChoiceMap = Readonly<Record<string, CommandMessageKey>>;
|
|
61
|
+
/** An autocomplete suggestion's value with the label the picker shows for it. */
|
|
62
|
+
export type ChoiceWithLabel<V extends string | number> = {
|
|
63
|
+
/** The text the picker shows: data, such as a name, so it is not a message key. */
|
|
64
|
+
label: string;
|
|
65
|
+
/** The value the handler receives when this choice is picked. */
|
|
66
|
+
value: V;
|
|
67
|
+
};
|
|
68
|
+
/** A Discord channel, as the channel store returns it. */
|
|
69
|
+
export type CommandChannel = {
|
|
70
|
+
/** The channel's Discord snowflake id. */
|
|
71
|
+
id: string;
|
|
72
|
+
/** Discord's numeric channel type, such as `0` for a guild text channel or `1` for a DM. */
|
|
73
|
+
type: number;
|
|
74
|
+
/** The channel name; DMs may have none. */
|
|
75
|
+
name?: string;
|
|
76
|
+
/** The id of the guild the channel belongs to; `null` or absent for DMs and group DMs. */
|
|
77
|
+
guild_id?: string | null;
|
|
78
|
+
};
|
|
79
|
+
/** Where a command runs. Discord never runs a command without a channel. */
|
|
80
|
+
export type CommandContext = {
|
|
81
|
+
/** The channel the command was sent in. */
|
|
82
|
+
channel: CommandChannel;
|
|
83
|
+
/** The guild of that channel; `undefined` in DMs and group DMs. */
|
|
84
|
+
guild: CommandGuild | undefined;
|
|
85
|
+
};
|
|
86
|
+
/** A command that only groups subcommands: `/root sub` or `/root group sub`. */
|
|
87
|
+
export type CommandGroup<S> = {
|
|
88
|
+
/** The message key of the text the picker shows under the group name; 1 to 100 characters in en-US. */
|
|
89
|
+
description: CommandMessageKey;
|
|
90
|
+
/** The group's commands keyed by name, 1 to 25 of them. */
|
|
91
|
+
subcommands: CommandTree<S>;
|
|
92
|
+
/** Never set on a group; only a {@link LeafCommand} takes options. */
|
|
93
|
+
options?: never;
|
|
94
|
+
/** Never set on a group; only a {@link LeafCommand} runs. */
|
|
95
|
+
execute?: never;
|
|
96
|
+
};
|
|
97
|
+
/** A Discord guild. */
|
|
98
|
+
export type CommandGuild = {
|
|
99
|
+
/** The guild's Discord snowflake id. */
|
|
100
|
+
id: string;
|
|
101
|
+
/** The guild's display name. */
|
|
102
|
+
name: string;
|
|
103
|
+
};
|
|
104
|
+
/**
|
|
105
|
+
* A key of the owner's `i18n/en-US.json`. The picker shows its message in the user's locale, falling back to en-US;
|
|
106
|
+
* a plugin's keys come from its generated `src/unbound-i18n.d.ts`.
|
|
107
|
+
*/
|
|
108
|
+
export type CommandMessageKey = Extract<keyof UnboundMessageKeys, string>;
|
|
109
|
+
/** A leaf or a group. */
|
|
110
|
+
export type CommandNode<T> = LeafCommand<T> | CommandGroup<T>;
|
|
111
|
+
/** A Discord guild role. */
|
|
112
|
+
export type CommandRole = {
|
|
113
|
+
/** The role's Discord snowflake id. */
|
|
114
|
+
id: string;
|
|
115
|
+
/** The role's display name. */
|
|
116
|
+
name: string;
|
|
117
|
+
/** The role colour as a 24-bit RGB integer; `0` when the role has no colour. */
|
|
118
|
+
color?: number;
|
|
119
|
+
};
|
|
120
|
+
/**
|
|
121
|
+
* Commands keyed by name, at every level. TypeScript infers `T` per key by reversing this mapped type,
|
|
122
|
+
* from `options` on a leaf and from `subcommands` on a group. A conditional type here breaks inference.
|
|
123
|
+
*/
|
|
124
|
+
export type CommandTree<T> = {
|
|
125
|
+
[K in keyof T]: CommandNode<T[K]>;
|
|
126
|
+
};
|
|
127
|
+
/** A Discord user, as the user store returns it. Only the fields commands rely on. */
|
|
128
|
+
export type CommandUser = {
|
|
129
|
+
/** The user's Discord snowflake id. */
|
|
130
|
+
id: string;
|
|
131
|
+
/** The unique account name, without the `@`. */
|
|
132
|
+
username: string;
|
|
133
|
+
/** The display name the user set; `null` or absent when they set none. */
|
|
134
|
+
globalName?: string | null;
|
|
135
|
+
/** `true` for bot accounts. */
|
|
136
|
+
bot?: boolean;
|
|
137
|
+
};
|
|
138
|
+
/** The handle `createCommands` returns, scoped to one owner. */
|
|
139
|
+
export type CommandsHandle = {
|
|
140
|
+
/**
|
|
141
|
+
* Adds commands. Registering a root name this owner already has replaces that whole command.
|
|
142
|
+
* Returns a function that removes this call's commands; it is safe to call twice or after a sweep.
|
|
143
|
+
*/
|
|
144
|
+
register<T>(commands: CommandTree<T>): () => void;
|
|
145
|
+
/** Removes this owner's root command `name` with its subcommands. Does nothing when there is none. */
|
|
146
|
+
unregister(name: string): void;
|
|
147
|
+
/** Removes every command of this owner. */
|
|
148
|
+
unregisterAll(): void;
|
|
149
|
+
};
|
|
150
|
+
/** Options of `createCommands`. */
|
|
151
|
+
export type CommandsOptions = {
|
|
152
|
+
/** The owner's own picker section. Omitted, commands go in the shared Unbound section. */
|
|
153
|
+
section?: SectionInput;
|
|
154
|
+
};
|
|
155
|
+
/** Shown only to the user, as a bot message. */
|
|
156
|
+
export type EphemeralReply = {
|
|
157
|
+
/** Marks the reply as shown only to the user instead of sent. */
|
|
158
|
+
ephemeral: true;
|
|
159
|
+
/** The message text; empty when absent. */
|
|
160
|
+
content?: string;
|
|
161
|
+
/** Embeds shown under the text. */
|
|
162
|
+
embeds?: readonly ReplyEmbed[];
|
|
163
|
+
};
|
|
164
|
+
/** An asset id from `assets.Icons`, or a `data:` or `https:` uri. */
|
|
165
|
+
export type IconSource = number | string;
|
|
166
|
+
/**
|
|
167
|
+
* A command that runs. `O` is inferred from `options` and types `execute`'s args.
|
|
168
|
+
* `execute` uses method syntax so its parameter stays bivariant and the registry can hold it erased.
|
|
169
|
+
*/
|
|
170
|
+
export type LeafCommand<O> = {
|
|
171
|
+
/** The message key of the text the picker shows under the command name; 1 to 100 characters in en-US. */
|
|
172
|
+
description: CommandMessageKey;
|
|
173
|
+
/** The command's options keyed by name, made with the `option` builders. At most 25. */
|
|
174
|
+
options?: O;
|
|
175
|
+
/** Runs the command with the parsed options. A throw or rejection shows the user an ephemeral error. */
|
|
176
|
+
execute(args: OptionArgs<O>, context: CommandContext): Awaitable<Reply>;
|
|
177
|
+
/** Never set on a leaf; a command with `subcommands` is a {@link CommandGroup}. */
|
|
178
|
+
subcommands?: never;
|
|
179
|
+
};
|
|
180
|
+
/** The settings of an option kind that takes none. */
|
|
181
|
+
export type NoSettings = Record<never, never>;
|
|
182
|
+
/** Settings of `option.integer` and `option.number`. */
|
|
183
|
+
export type NumberOptionSettings = {
|
|
184
|
+
/** The smallest value Discord accepts, inclusive. */
|
|
185
|
+
minValue?: number;
|
|
186
|
+
/** The largest value Discord accepts, inclusive. */
|
|
187
|
+
maxValue?: number;
|
|
188
|
+
/** Suggests values while the user types; setting it turns on Discord's autocomplete for the option. */
|
|
189
|
+
autocomplete?: Autocomplete<number>;
|
|
190
|
+
};
|
|
191
|
+
/** A handler's args, derived from its options: a required option is `V`, an optional one `V | undefined`. */
|
|
192
|
+
export type OptionArgs<O> = {
|
|
193
|
+
[K in keyof O]: O[K] extends OptionSpec<OptionKind, infer R, infer V>
|
|
194
|
+
? R extends true
|
|
195
|
+
? V
|
|
196
|
+
: V | undefined
|
|
197
|
+
: never;
|
|
198
|
+
};
|
|
199
|
+
/** One kind's builder. */
|
|
200
|
+
export type OptionBuilder<K extends OptionKind> = <const R extends boolean = false>(
|
|
201
|
+
settings?: BuilderInput<K, R>,
|
|
202
|
+
) => OptionSpec<K, R>;
|
|
203
|
+
/** The `option` builders: one per kind, plus `choice`. */
|
|
204
|
+
export type OptionBuilders = {
|
|
205
|
+
[K in OptionKind]: OptionBuilder<K>;
|
|
206
|
+
} & {
|
|
207
|
+
/**
|
|
208
|
+
* Restricts a string option to listed values; the handler gets their literal union.
|
|
209
|
+
* @param choices Each value mapped to its label's message key, in picker order: `{ heads: 'COIN_HEADS' }`. 1 to 25.
|
|
210
|
+
* @param settings The option's description and whether it is required.
|
|
211
|
+
*/
|
|
212
|
+
choice<const M extends ChoiceMap, const R extends boolean = false>(
|
|
213
|
+
choices: M,
|
|
214
|
+
settings?: ChoiceInput<R>,
|
|
215
|
+
): OptionSpec<'string', R, keyof M & string>;
|
|
216
|
+
};
|
|
217
|
+
/** The option kinds: one builder each on `option`. */
|
|
218
|
+
export type OptionKind = keyof OptionKindTypes;
|
|
219
|
+
/** Each option kind's handler value and builder settings. The client's kind table implements every key. */
|
|
220
|
+
export type OptionKindTypes = {
|
|
221
|
+
/** Free text. */
|
|
222
|
+
string: {
|
|
223
|
+
value: string;
|
|
224
|
+
settings: StringOptionSettings;
|
|
225
|
+
};
|
|
226
|
+
/** A whole number; a fractional value fails the command. */
|
|
227
|
+
integer: {
|
|
228
|
+
value: number;
|
|
229
|
+
settings: NumberOptionSettings;
|
|
230
|
+
};
|
|
231
|
+
/** Any finite number. */
|
|
232
|
+
number: {
|
|
233
|
+
value: number;
|
|
234
|
+
settings: NumberOptionSettings;
|
|
235
|
+
};
|
|
236
|
+
/** True or false. */
|
|
237
|
+
boolean: {
|
|
238
|
+
value: boolean;
|
|
239
|
+
settings: NoSettings;
|
|
240
|
+
};
|
|
241
|
+
/** A user, resolved from the picked id through Discord's user store. */
|
|
242
|
+
user: {
|
|
243
|
+
value: CommandUser;
|
|
244
|
+
settings: NoSettings;
|
|
245
|
+
};
|
|
246
|
+
/** A channel, resolved from the picked id through Discord's channel store. */
|
|
247
|
+
channel: {
|
|
248
|
+
value: CommandChannel;
|
|
249
|
+
settings: ChannelOptionSettings;
|
|
250
|
+
};
|
|
251
|
+
/** A role of the current guild, resolved from the picked id through Discord's role store. */
|
|
252
|
+
role: {
|
|
253
|
+
value: CommandRole;
|
|
254
|
+
settings: NoSettings;
|
|
255
|
+
};
|
|
256
|
+
};
|
|
257
|
+
/** The settings a kind's builder accepts beyond `description` and `required`. */
|
|
258
|
+
export type OptionSettings<K extends OptionKind> = OptionKindTypes[K]['settings'];
|
|
259
|
+
/** One declared option, made by an `option` builder. */
|
|
260
|
+
export type OptionSpec<
|
|
261
|
+
K extends OptionKind = OptionKind,
|
|
262
|
+
R extends boolean = boolean,
|
|
263
|
+
V = OptionValue<K>,
|
|
264
|
+
> = {
|
|
265
|
+
/** The option kind; `option.choice` derives it from its values. */
|
|
266
|
+
readonly kind: K;
|
|
267
|
+
/** Whether Discord requires the option. Defaults to `false`; required options are listed first. */
|
|
268
|
+
readonly required: R;
|
|
269
|
+
/** The message key of the text the picker shows for the option; `undefined` shows the option's name. */
|
|
270
|
+
readonly description: string | undefined;
|
|
271
|
+
/** The kind-specific settings given to the builder; empty for `option.choice`. */
|
|
272
|
+
readonly settings: OptionSettings<K>;
|
|
273
|
+
/** Each value from `option.choice` mapped to its label's message key; `undefined` for every other builder. */
|
|
274
|
+
readonly choices: Readonly<Record<string, string>> | undefined;
|
|
275
|
+
/** Carries the handler's value type for inference only; never set at runtime. */
|
|
276
|
+
readonly [valueType]?: V;
|
|
277
|
+
};
|
|
278
|
+
/** The value a handler receives for a kind. */
|
|
279
|
+
export type OptionValue<K extends OptionKind> = OptionKindTypes[K]['value'];
|
|
280
|
+
/** Sent by Discord as a normal message from the user. */
|
|
281
|
+
export type PublicReply = {
|
|
282
|
+
/** The message text. An empty string sends nothing. */
|
|
283
|
+
content: string;
|
|
284
|
+
/** Sends the message as text-to-speech. */
|
|
285
|
+
tts?: boolean;
|
|
286
|
+
/** Absent or `false`; `true` makes the reply an {@link EphemeralReply}. */
|
|
287
|
+
ephemeral?: false;
|
|
288
|
+
};
|
|
289
|
+
/** An option value as Discord passes it. User, channel and role options arrive as id strings. */
|
|
290
|
+
export type RawOptionValue = string | number | boolean;
|
|
291
|
+
/** What `execute` returns. A string is shorthand for `{ content }`; nothing means the command did its own work. */
|
|
292
|
+
export type Reply = string | PublicReply | EphemeralReply | undefined | void;
|
|
293
|
+
/** An embed in an ephemeral reply. */
|
|
294
|
+
export type ReplyEmbed = {
|
|
295
|
+
/** The heading at the top of the embed. */
|
|
296
|
+
title?: string;
|
|
297
|
+
/** The embed's body text, below the title. */
|
|
298
|
+
description?: string;
|
|
299
|
+
/** A link the title opens. */
|
|
300
|
+
url?: string;
|
|
301
|
+
/** The colour of the embed's side bar, as a 24-bit RGB integer such as `0x5865f2`. */
|
|
302
|
+
color?: number;
|
|
303
|
+
/** Name and value pairs shown below the description. */
|
|
304
|
+
fields?: readonly ReplyEmbedField[];
|
|
305
|
+
};
|
|
306
|
+
/** A field of an embed in an ephemeral reply. */
|
|
307
|
+
export type ReplyEmbedField = {
|
|
308
|
+
/** The field's heading. */
|
|
309
|
+
name: string;
|
|
310
|
+
/** The field's body text. */
|
|
311
|
+
value: string;
|
|
312
|
+
/** Lays the field out beside neighbouring inline fields instead of on its own row. */
|
|
313
|
+
inline?: boolean;
|
|
314
|
+
};
|
|
315
|
+
/** A section of the `/` picker owned by one owner. */
|
|
316
|
+
export type SectionInput = {
|
|
317
|
+
/** The section's heading in the picker; also the author name on its ephemeral replies. Must not be blank. */
|
|
318
|
+
name: string;
|
|
319
|
+
/** The section's icon and reply avatar. Omitted, Discord's default application command icon. */
|
|
320
|
+
icon?: IconSource;
|
|
321
|
+
};
|
|
322
|
+
/** Settings of `option.string`. */
|
|
323
|
+
export type StringOptionSettings = {
|
|
324
|
+
/** The fewest characters Discord accepts for the value. */
|
|
325
|
+
minLength?: number;
|
|
326
|
+
/** The most characters Discord accepts for the value. */
|
|
327
|
+
maxLength?: number;
|
|
328
|
+
/** Suggests values while the user types; setting it turns on Discord's autocomplete for the option. */
|
|
329
|
+
autocomplete?: Autocomplete<string>;
|
|
330
|
+
};
|
|
331
|
+
export {};
|
package/src/dialogs.d.ts
ADDED
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
// Auto-generated by generate-plugin-sdk.ts - DO NOT EDIT
|
|
2
|
+
|
|
3
|
+
import type { MessageKey, FormatVars as MessageVars } from '@unbound-app/i18n';
|
|
4
|
+
import * as React$1 from 'react';
|
|
5
|
+
import { ComponentType } from 'react';
|
|
6
|
+
/**
|
|
7
|
+
* @description Tells the user something in a dialog with one button, each text a message key.
|
|
8
|
+
* @template T The title's key.
|
|
9
|
+
* @template B The body's key.
|
|
10
|
+
* @param title The dialog's message key.
|
|
11
|
+
* @param options The `body` and `confirm` keys, and `titleVars` and `bodyVars` for keys with placeholders.
|
|
12
|
+
* @returns A promise that resolves once the dialog closes, however it closes.
|
|
13
|
+
*/
|
|
14
|
+
declare function alert$1<T extends PlainMessageKey, B extends MessageKey = never>(
|
|
15
|
+
title: T,
|
|
16
|
+
options?: AlertOptions<T, B>,
|
|
17
|
+
): Promise<void>;
|
|
18
|
+
/**
|
|
19
|
+
* @description Tells the user something in a dialog with one button, titled by a key with placeholders.
|
|
20
|
+
* @template T The title's key.
|
|
21
|
+
* @template B The body's key.
|
|
22
|
+
* @param title The dialog's message key.
|
|
23
|
+
* @param options `titleVars`, then the `body` and `confirm` keys, and `bodyVars` for a body with placeholders.
|
|
24
|
+
* @returns A promise that resolves once the dialog closes, however it closes.
|
|
25
|
+
*/
|
|
26
|
+
declare function alert$1<T extends VarsMessageKey, B extends MessageKey = never>(
|
|
27
|
+
title: T,
|
|
28
|
+
options: AlertOptions<T, B>,
|
|
29
|
+
): Promise<void>;
|
|
30
|
+
/**
|
|
31
|
+
* @description Asks a yes-or-no question with a confirm and a cancel button, each text a message key.
|
|
32
|
+
* @template T The title's key.
|
|
33
|
+
* @template B The body's key.
|
|
34
|
+
* @param title The question's message key.
|
|
35
|
+
* @param options The `body`, `confirm` and `cancel` keys, `titleVars` and `bodyVars` for keys with placeholders, and `destructive`.
|
|
36
|
+
* @returns Whether the user confirmed; cancel, the backdrop, the back gesture or a dismiss resolve `false`.
|
|
37
|
+
*/
|
|
38
|
+
declare function confirm$1<T extends MessageKey, B extends MessageKey = never>(
|
|
39
|
+
title: T,
|
|
40
|
+
options: ConfirmOptions<T, B>,
|
|
41
|
+
): Promise<boolean>;
|
|
42
|
+
/**
|
|
43
|
+
* @description Closes every dialog this API opened, running each one's `onDismiss`.
|
|
44
|
+
*/
|
|
45
|
+
export declare function dismissAll(): void;
|
|
46
|
+
/**
|
|
47
|
+
* @description Opens a dialog with Discord's own alert: a title, an optional body and custom component,
|
|
48
|
+
* and action buttons, each of which closes the dialog before running its handler. On a Discord build
|
|
49
|
+
* without the alert it falls back to the system alert, which shows the title, body and buttons only.
|
|
50
|
+
* @param options The dialog's content and buttons.
|
|
51
|
+
* @returns The dialog's key and a function that closes it.
|
|
52
|
+
*/
|
|
53
|
+
export declare function showDialog(options: AlertDialogProps): DialogHandle;
|
|
54
|
+
/** What {@link showDialog} shows: a title, an optional body and custom content, and buttons. */
|
|
55
|
+
export type AlertDialogProps = {
|
|
56
|
+
/** The heading at the top of the dialog. */
|
|
57
|
+
title: string;
|
|
58
|
+
/** Text shown below the title. */
|
|
59
|
+
body?: string;
|
|
60
|
+
/** A component rendered below the body, given a way to close the dialog. */
|
|
61
|
+
content?: React$1.ComponentType<DialogContentProps>;
|
|
62
|
+
/** The action buttons, in order, before the cancel button. */
|
|
63
|
+
buttons?: DialogButton[];
|
|
64
|
+
/** Adds a cancel button last; a string sets its label. */
|
|
65
|
+
cancel?: boolean | string;
|
|
66
|
+
/** Runs when the cancel button closes the dialog. */
|
|
67
|
+
onCancel?: () => void;
|
|
68
|
+
/** Runs when the dialog closes without a button: the backdrop, the back gesture, or its handle's `dismiss`. */
|
|
69
|
+
onDismiss?: () => void;
|
|
70
|
+
};
|
|
71
|
+
/** What `alert` shows after its title key: the body and button keys, and the title's and body's vars. */
|
|
72
|
+
export type AlertOptions<T extends MessageKey, B extends MessageKey = never> = BodyOptions<B> &
|
|
73
|
+
KeyVars<T, 'titleVars'> & {
|
|
74
|
+
/** The key of the button that closes the dialog; Unbound's `OK` when omitted. */
|
|
75
|
+
confirm?: PlainMessageKey;
|
|
76
|
+
};
|
|
77
|
+
/** The optional body key of a dialog, and its vars when the message has placeholders. */
|
|
78
|
+
export type BodyOptions<B extends MessageKey> = {
|
|
79
|
+
/** The key of the text shown below the title. */
|
|
80
|
+
body?: B;
|
|
81
|
+
} & KeyVars<B, 'bodyVars'>;
|
|
82
|
+
/** What `confirm` asks after its title key: the body and button keys, and the title's and body's vars. */
|
|
83
|
+
export type ConfirmOptions<T extends MessageKey, B extends MessageKey = never> = BodyOptions<B> &
|
|
84
|
+
KeyVars<T, 'titleVars'> & {
|
|
85
|
+
/** The key of the button that resolves `true`. */
|
|
86
|
+
confirm: PlainMessageKey;
|
|
87
|
+
/** The key of the button that resolves `false`; Unbound's `Cancel` when omitted. */
|
|
88
|
+
cancel?: PlainMessageKey;
|
|
89
|
+
/** Styles the confirm button as `destructive` instead of `primary`. Use it whenever confirming loses data. */
|
|
90
|
+
destructive?: boolean;
|
|
91
|
+
};
|
|
92
|
+
/** One action button in a dialog opened by {@link showDialog}. */
|
|
93
|
+
export type DialogButton = {
|
|
94
|
+
/** The text shown on the button. */
|
|
95
|
+
label: string;
|
|
96
|
+
/** The button's style; `primary` when omitted. */
|
|
97
|
+
variant?: DialogButtonVariant;
|
|
98
|
+
/** Runs after the press closes the dialog. */
|
|
99
|
+
onPress?: () => void;
|
|
100
|
+
};
|
|
101
|
+
/** A dialog button's style; the system alert fallback only distinguishes `destructive`. */
|
|
102
|
+
export type DialogButtonVariant = 'primary' | 'secondary' | 'destructive';
|
|
103
|
+
/** The props a dialog's custom `content` component receives. */
|
|
104
|
+
export type DialogContentProps = {
|
|
105
|
+
/** Closes the dialog without running any button's handler. */
|
|
106
|
+
dismiss: () => void;
|
|
107
|
+
};
|
|
108
|
+
/** An open dialog, as {@link showDialog} returns it. */
|
|
109
|
+
export type DialogHandle = {
|
|
110
|
+
/** The `unbound-dialog-<uuid>` key the dialog was opened under in Discord's alert stack. */
|
|
111
|
+
key: string;
|
|
112
|
+
/** Closes the dialog; does nothing once it is closed or when the system alert fallback showed it. */
|
|
113
|
+
dismiss: () => void;
|
|
114
|
+
};
|
|
115
|
+
/** An options field holding a key's placeholder values: required when the key has placeholders, absent otherwise. */
|
|
116
|
+
export type KeyVars<K extends MessageKey, Field extends string> = [K] extends [never]
|
|
117
|
+
? {
|
|
118
|
+
[P in Field]?: never;
|
|
119
|
+
}
|
|
120
|
+
: K extends keyof MessageVars
|
|
121
|
+
? {
|
|
122
|
+
[P in Field]: MessageVars[K];
|
|
123
|
+
}
|
|
124
|
+
: {
|
|
125
|
+
[P in Field]?: never;
|
|
126
|
+
};
|
|
127
|
+
/** A message key whose en-US text has no placeholders. */
|
|
128
|
+
export type PlainMessageKey = Exclude<MessageKey, keyof MessageVars>;
|
|
129
|
+
/** A message key whose en-US text has placeholders. */
|
|
130
|
+
export type VarsMessageKey = Extract<MessageKey, keyof MessageVars>;
|
|
131
|
+
|
|
132
|
+
export { alert$1 as alert, confirm$1 as confirm };
|
|
133
|
+
|
|
134
|
+
export {};
|