@unbound-app/api 0.5.3 → 0.7.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.
@@ -1,17 +1,20 @@
1
1
  // Auto-generated by generate-plugin-sdk.ts - DO NOT EDIT
2
2
 
3
+ import type { LiteralUnion } from './utils';
4
+ import * as ReactModule from 'react';
5
+ import { ComponentType, ReactNode } from 'react';
6
+ import * as ReactNativeModule from 'react-native';
3
7
  import {
8
+ AccessibilityState,
4
9
  ImageSourcePropType,
5
10
  ImageStyle,
11
+ PressableProps,
6
12
  StyleProp,
7
13
  TextInputProps as RNTextInputProps,
8
14
  TextStyle,
9
15
  ViewProps,
10
16
  ViewStyle,
11
17
  } from 'react-native';
12
- import { ComponentType, ReactNode } from 'react';
13
-
14
- import type { Fn, LiteralUnion } from './utils';
15
18
 
16
19
  declare const THEME_FLAG_KEYS: readonly [
17
20
  'MOBILE_DARK_GRADIENT_THEME_ENABLED',
@@ -21,21 +24,49 @@ declare const THEME_FLAG_KEYS: readonly [
21
24
  'REDUCE_SATURATION_ENABLED',
22
25
  ];
23
26
  declare const TRANSITION_STATE_KEYS: readonly ['MOUNTED', 'ENTERED', 'YEETED'];
24
-
27
+ declare const nativeHandle: unique symbol;
28
+ /** The kinds of addon a manifest can declare. */
29
+ export declare const ADDON_TYPES: readonly ['plugin', 'theme', 'icon-pack', 'font'];
30
+ export declare const NATIVE_PLUGIN_CAPABILITIES: readonly [
31
+ 'native.objc.classes',
32
+ 'native.objc.invoke',
33
+ 'native.objc.ivars',
34
+ 'native.objc.associations',
35
+ 'native.objc.hooks',
36
+ 'native.ffi.symbols',
37
+ 'native.ffi.call',
38
+ 'native.fabric.mount',
39
+ ];
40
+ export type ActionSheetProps = {
41
+ children?: ReactModule.ReactNode;
42
+ };
43
+ export type ActionSheetRowProps = {
44
+ label: ReactModule.ReactNode;
45
+ subLabel?: ReactModule.ReactNode;
46
+ icon?: ReactModule.ReactNode;
47
+ onPress?: DiscordFunction<void>;
48
+ };
25
49
  /** A loaded addon entity: its runtime state, instance, source bundle, and {@link AddonManifest}. */
26
- export interface Addon {
50
+ export type Addon = {
27
51
  started: boolean;
28
- instance: any;
52
+ /** What the bundle evaluated to. Every addon kind may implement the {@link Plugin} lifecycle hooks. */
53
+ instance: Plugin$1 | null;
54
+ context?: PluginContext;
29
55
  id: string;
30
56
  failed: boolean;
31
57
  data: AddonManifest;
32
58
  bundle: string;
33
- }
59
+ };
60
+ /** The author of an addon: a display name and a numeric user id. */
61
+ export type AddonAuthor = {
62
+ name: string;
63
+ id: `${number}`;
64
+ };
34
65
  /** The manifest describing an addon's metadata, entry point, and source. */
35
- export interface AddonManifest {
66
+ export type AddonManifest = {
36
67
  id: string;
37
68
  /** The addon kind this manifest describes; used to validate installs. */
38
- type?: 'plugin' | 'theme' | 'icon-pack' | 'font';
69
+ type?: AddonType;
39
70
  name: string;
40
71
  description: string;
41
72
  authors: AddonAuthor[];
@@ -50,21 +81,47 @@ export interface AddonManifest {
50
81
  folder: string;
51
82
  path: string;
52
83
  url: string;
53
- }
84
+ capabilities?: NativePluginCapability[];
85
+ minNativePluginApi?: string;
86
+ /** Requirements on the Unbound client running the addon. */
87
+ unbound?: {
88
+ /** The minimum Unbound client version (semver) the addon supports. */
89
+ min?: string;
90
+ };
91
+ };
92
+ /** An addon referenced either by its id string or the {@link Addon} entity itself. */
93
+ export type AddonResolveable = string | Addon;
94
+ export type AddonType = (typeof ADDON_TYPES)[number];
95
+ export type AlertActionButtonProps = {
96
+ text: string;
97
+ variant?: ButtonVariant;
98
+ loading?: boolean;
99
+ disabled?: boolean;
100
+ onPress?: DiscordFunction<void>;
101
+ };
102
+ export type AlertModalProps = {
103
+ title?: ReactModule.ReactNode;
104
+ content?: ReactModule.ReactNode;
105
+ extraContent?: ReactModule.ReactNode;
106
+ actions?: ReactModule.ReactNode;
107
+ };
54
108
  /** The native module used to register and resolve {@link DiscordAsset}s by id. */
55
- export interface AssetsModule {
109
+ export type AssetsModule = {
56
110
  registerAsset: (asset: DiscordAsset) => number;
57
111
  getAssetByID: (id: number) => DiscordAsset | null;
58
- [key: PropertyKey]: any;
59
- }
60
- export interface ButtonProps {
112
+ };
113
+ /** `Button` with its attached `Icon` static. */
114
+ export type ButtonComponent = ReactModule.ComponentType<ButtonProps> & {
115
+ Icon: ReactModule.ComponentType<TableRowIconProps>;
116
+ };
117
+ export type ButtonProps = {
61
118
  text?: string;
62
- textElement?: ReactNode;
119
+ textElement?: ReactModule.ReactNode;
63
120
  variant?: ButtonVariant;
64
121
  size?: ButtonSize;
65
122
  loading?: boolean;
66
123
  disabled?: boolean;
67
- icon?: ReactNode | number;
124
+ icon?: ReactModule.ReactNode | number;
68
125
  iconPosition?: 'start' | 'end';
69
126
  grow?: boolean;
70
127
  shrink?: boolean;
@@ -72,72 +129,100 @@ export interface ButtonProps {
72
129
  textVariant?: TextVariant;
73
130
  style?: StyleProp<ViewStyle>;
74
131
  accessibilityLabel?: string;
75
- onPress?: Fn<void>;
76
- onPressIn?: Fn<void>;
77
- onPressOut?: Fn<void>;
78
- }
79
- export interface CardProps extends ViewProps {
132
+ onPress?: DiscordFunction<void>;
133
+ onPressIn?: DiscordFunction<void>;
134
+ onPressOut?: DiscordFunction<void>;
135
+ };
136
+ export type ButtonSize = LiteralUnion<'sm' | 'md' | 'lg'>;
137
+ export type ButtonVariant = LiteralUnion<
138
+ 'primary' | 'secondary' | 'tertiary' | 'destructive' | 'active' | 'expressive'
139
+ >;
140
+ export type CardProps = {
80
141
  variant?: LiteralUnion<'primary' | 'secondary' | 'muted' | 'transparent'>;
81
142
  border?: LiteralUnion<'none' | 'subtle' | 'strong'>;
82
143
  shadow?: LiteralUnion<'none' | 'low' | 'medium' | 'high' | 'border'>;
83
144
  radius?: number;
84
145
  start?: boolean;
85
146
  end?: boolean;
86
- children?: ReactNode;
87
- }
88
- export interface CheckboxProps {
89
- label?: ReactNode;
90
- description?: ReactNode;
147
+ children?: ReactModule.ReactNode;
148
+ } & ViewProps;
149
+ export type CheckboxProps = {
150
+ label?: ReactModule.ReactNode;
151
+ description?: ReactModule.ReactNode;
91
152
  checked: boolean;
92
153
  required?: boolean;
93
154
  accessibilityRole?: string;
94
- accessibilityState?: Record<string, any>;
95
- onToggle: Fn<void>;
96
- }
155
+ accessibilityState?: AccessibilityState;
156
+ onToggle: DiscordFunction<void>;
157
+ };
158
+ /** An entry of a `ContextMenu`. */
159
+ export type ContextMenuItem = {
160
+ label: string;
161
+ action: DiscordFunction<void>;
162
+ variant?: LiteralUnion<'default' | 'destructive'>;
163
+ iconSource?: number;
164
+ };
165
+ /** `ContextMenu`: an anchored popover whose `children` render the trigger from the props it passes. */
166
+ export type ContextMenuProps = {
167
+ title?: string;
168
+ items: ContextMenuItem[];
169
+ triggerOnTap?: boolean;
170
+ children: (props: PressableProps) => ReactModule.ReactNode;
171
+ };
172
+ /**
173
+ * The style factory: turns a spec (or a function returning one) into a theme-aware hook, so call it
174
+ * inside a component body: `const styles = useStyles();`.
175
+ */
176
+ export type CreateStyles = <T extends StyleSheetSpec>(
177
+ styles: StyleSheetSpecOrFactory<T>,
178
+ ) => () => ResolvedStyles<T>;
97
179
  /**
98
- * The Discord mobile design system. This is the single metro module keyed by
99
- * `createStyles` / `dismissAlerts` / `ContextMenu` (aliased `Design` on the v3 branch). It is
100
- * intentionally left open: every listed member is precisely typed, and the index signature keeps
101
- * the rest (and anything Discord adds in a future build) accessible as `any` without a change here.
102
- *
103
- * See `DESIGN.md` at the repo root for the full catalogue.
180
+ * The Discord mobile design system module (keyed by `createStyles` / `dismissAlerts` / `ContextMenu`).
181
+ * See `DESIGN.md` for the full catalogue.
104
182
  */
105
- export interface DesignModule {
183
+ export type DesignModule = {
106
184
  createStyles: CreateStyles;
107
185
  TextStyleSheet: Record<TextVariant, TextStyle>;
108
- Text: ComponentType<TextProps>;
109
- Heading: ComponentType<TextProps>;
186
+ Text: ReactModule.ComponentType<TextProps>;
187
+ Heading: ReactModule.ComponentType<TextProps>;
110
188
  TableRow: TableRowComponent;
111
- TableSwitchRow: ComponentType<TableSwitchRowProps>;
112
- TableCheckboxRow: ComponentType<TableCheckboxRowProps>;
113
- TableRadioRow: ComponentType<TableRadioRowProps>;
114
- TableRowGroup: ComponentType<TableRowGroupProps>;
115
- TableRowGroupTitle: ComponentType<TableRowGroupTitleProps>;
116
- TableRowIcon: ComponentType<TableRowIconProps>;
117
- RowButton: ComponentType<RowButtonProps>;
118
- RowGroup: ComponentType<ViewProps>;
189
+ TableSwitchRow: ReactModule.ComponentType<TableSwitchRowProps>;
190
+ TableCheckboxRow: ReactModule.ComponentType<TableCheckboxRowProps>;
191
+ TableRadioRow: ReactModule.ComponentType<TableRadioRowProps>;
192
+ TableRowGroup: ReactModule.ComponentType<TableRowGroupProps>;
193
+ TableRowGroupTitle: ReactModule.ComponentType<TableRowGroupTitleProps>;
194
+ TableRowIcon: ReactModule.ComponentType<TableRowIconProps>;
195
+ RowButton: ReactModule.ComponentType<RowButtonProps>;
196
+ RowGroup: ReactModule.ComponentType<ViewProps>;
119
197
  Button: ButtonComponent;
120
- IconButton: ComponentType<IconButtonProps>;
121
- ImageButton: ComponentType<ViewProps>;
122
- FloatingActionButton: ComponentType<FloatingActionButtonProps>;
123
- TextInput: ComponentType<TextInputProps>;
124
- TextField: ComponentType<TextFieldProps>;
125
- TextArea: ComponentType<TextAreaProps>;
126
- TextAreaField: ComponentType<TextAreaProps>;
127
- SearchField: ComponentType<Omit<TextFieldProps, 'leadingIcon'>>;
128
- GhostInput: ComponentType<GhostInputProps>;
129
- SplitTextInput: ComponentType<SplitTextInputProps>;
130
- Slider: ComponentType<SliderProps>;
131
- Checkbox: ComponentType<CheckboxProps>;
132
- SegmentedControl: ComponentType<SegmentedControlProps>;
133
- Stack: ComponentType<StackProps>;
134
- Card: ComponentType<CardProps>;
135
- openAlert: Fn<void>;
198
+ IconButton: ReactModule.ComponentType<IconButtonProps>;
199
+ ImageButton: ReactModule.ComponentType<ViewProps>;
200
+ FloatingActionButton: ReactModule.ComponentType<FloatingActionButtonProps>;
201
+ TextInput: ReactModule.ComponentType<TextInputProps>;
202
+ TextField: ReactModule.ComponentType<TextFieldProps>;
203
+ TextArea: ReactModule.ComponentType<TextAreaProps>;
204
+ TextAreaField: ReactModule.ComponentType<TextAreaProps>;
205
+ SearchField: ReactModule.ComponentType<Omit<TextFieldProps, 'leadingIcon'>>;
206
+ GhostInput: ReactModule.ComponentType<GhostInputProps>;
207
+ SplitTextInput: ReactModule.ComponentType<SplitTextInputProps>;
208
+ Slider: ReactModule.ComponentType<SliderProps>;
209
+ Checkbox: ReactModule.ComponentType<CheckboxProps>;
210
+ SegmentedControl: ReactModule.ComponentType<SegmentedControlProps>;
211
+ SegmentedControlPages: ReactModule.ComponentType<SegmentedControlPagesProps>;
212
+ useSegmentedControlState: (options: SegmentedControlStateOptions) => SegmentedControlState;
213
+ Stack: ReactModule.ComponentType<StackProps>;
214
+ Card: ReactModule.ComponentType<CardProps>;
215
+ AlertModal: ReactModule.ComponentType<AlertModalProps>;
216
+ AlertActionButton: ReactModule.ComponentType<AlertActionButtonProps>;
217
+ ActionSheet: ReactModule.ComponentType<ActionSheetProps>;
218
+ ActionSheetRow: ReactModule.ComponentType<ActionSheetRowProps>;
219
+ ContextMenu: ReactModule.ComponentType<ContextMenuProps>;
220
+ openAlert: DiscordFunction<void>;
136
221
  dismissAlert: (key: string) => void;
137
- dismissAlerts: Fn<void>;
138
- showConfirmModal: Fn;
139
- showSimpleActionSheet: Fn;
140
- hideContextMenu: Fn<void>;
222
+ dismissAlerts: DiscordFunction<void>;
223
+ showConfirmModal: DiscordFunction;
224
+ showSimpleActionSheet: DiscordFunction;
225
+ hideContextMenu: DiscordFunction<void>;
141
226
  useNavigation: <T = any>() => Navigation<T>;
142
227
  setColorOpacity: (color: string, opacity: number) => string;
143
228
  darkenColor: (color: string, amount: number) => string;
@@ -146,33 +231,47 @@ export interface DesignModule {
146
231
  TransitionStates: EnumLike<typeof TRANSITION_STATE_KEYS>;
147
232
  ThemeContextFlags: EnumLike<typeof THEME_FLAG_KEYS>;
148
233
  WCAGContrastRatios: Record<'NonText' | 'Text' | 'HighContrastText', number>;
149
- [key: PropertyKey]: any;
150
- }
234
+ };
151
235
  /** An asset registered with Discord's packager (its metadata and dimensions). */
152
- export interface DiscordAsset {
236
+ export type DiscordAsset = {
153
237
  __packager_asset?: boolean;
154
238
  name: string;
155
- httpServerLocation?: string;
239
+ httpServerLocation: string;
156
240
  width: number;
157
241
  height: number;
158
242
  scales: number[];
159
243
  hash: string;
160
244
  type: string;
161
- [key: PropertyKey]: any;
162
- }
245
+ };
246
+ /** A function exported by a Discord module, whose signature Discord does not document. */
247
+ export type DiscordFunction<T = any> = (...args: any[]) => T;
248
+ /** Discord ships numeric enums as bidirectional maps; this models both directions. */
249
+ export type EnumLike<K extends readonly string[]> = {
250
+ [P in K[number]]: number;
251
+ } & {
252
+ [n: number]: K[number];
253
+ };
163
254
  /** `FloatingActionButton`: a single-icon FAB, typically pinned to a screen corner. */
164
- export interface FloatingActionButtonProps {
165
- icon?: ReactNode | number;
255
+ export type FloatingActionButtonProps = {
256
+ icon?: ReactModule.ReactNode | number;
166
257
  style?: StyleProp<ViewStyle>;
167
- onPress?: Fn<void>;
168
- }
258
+ onPress?: DiscordFunction<void>;
259
+ };
260
+ /** A custom font the native loader has registered, as injected on `window.UNBOUND_FONTS`. */
261
+ export type FontDescriptor = {
262
+ name: string;
263
+ file: string;
264
+ path: string;
265
+ };
266
+ /** A font managed by the Fonts manager: currently identical to its {@link FontDescriptor}. */
267
+ export type FontEntity = FontDescriptor;
169
268
  /** `GhostInput`: a borderless field bridging to the `useTextField` hook. */
170
- export interface GhostInputProps extends TextFieldProps {
269
+ export type GhostInputProps = {
171
270
  isCentered?: boolean;
172
271
  containerStyle?: StyleProp<ViewStyle>;
173
- }
174
- export interface IconButtonProps {
175
- icon?: ReactNode | number;
272
+ } & TextFieldProps;
273
+ export type IconButtonProps = {
274
+ icon?: ReactModule.ReactNode | number;
176
275
  variant?: ButtonVariant;
177
276
  size?: ButtonSize;
178
277
  loading?: boolean;
@@ -180,46 +279,304 @@ export interface IconButtonProps {
180
279
  label?: string;
181
280
  accessibilityLabel?: string;
182
281
  style?: StyleProp<ViewStyle>;
183
- onPress?: Fn<void>;
184
- }
282
+ onPress?: DiscordFunction<void>;
283
+ };
284
+ /** A loaded icon pack: its bundle marker and {@link IconPackManifest}. */
285
+ export type IconPack = {
286
+ bundle: string;
287
+ manifest: IconPackManifest;
288
+ };
289
+ /** An icon pack's manifest: an {@link AddonManifest} tagged with its source kind. */
290
+ export type IconPackManifest = AddonManifest & {
291
+ type: 'icon-pack';
292
+ source: 'github' | 'other';
293
+ };
294
+ /** Icon slot: a rendered node, a component, or a render function. */
295
+ export type IconSlot =
296
+ | ReactModule.ReactNode
297
+ | ReactModule.ComponentType<any>
298
+ | DiscordFunction<ReactModule.ReactNode>;
299
+ /** Input sizing, shared by the whole `TextField`/`Input` family. */
300
+ export type InputSize = LiteralUnion<'sm' | 'md' | 'lg'>;
301
+ /** Input status. `focused` is an internal state and is not user-settable. */
302
+ export type InputStatus = LiteralUnion<'default' | 'error'>;
185
303
  /** {@link ToastOptions} enriched with the fields the store tracks internally. */
186
- export interface InternalToastOptions extends ToastOptions {
304
+ export type InternalToastOptions = {
187
305
  id: string;
188
306
  closing?: boolean;
189
307
  date?: number;
190
- }
191
- export interface Navigation<T = any> {
308
+ } & ToastOptions;
309
+ export type NativeAssociationKey = NativeHandle;
310
+ export type NativeCallOptions = {
311
+ thread?: NativeThreadPolicy;
312
+ };
313
+ export type NativeClassHandle = NativeHandle;
314
+ export type NativeFFIBridge = {
315
+ symbol(name: string, image?: string): NativePointer | null;
316
+ call(pointer: NativePointer, signature: NativeFFISignature, ...args: unknown[]): unknown;
317
+ };
318
+ export type NativeFFISignature = {
319
+ returnType: NativeFFIType;
320
+ args: NativeFFIType[];
321
+ };
322
+ export type NativeFFIType =
323
+ | NativeFFITypeName
324
+ | {
325
+ struct: string;
326
+ };
327
+ export type NativeFFITypeName =
328
+ | 'void'
329
+ | 'bool'
330
+ | 'i8'
331
+ | 'u8'
332
+ | 'i16'
333
+ | 'u16'
334
+ | 'i32'
335
+ | 'u32'
336
+ | 'i64'
337
+ | 'u64'
338
+ | 'float'
339
+ | 'double'
340
+ | 'cstring'
341
+ | 'pointer'
342
+ | 'object'
343
+ | 'class'
344
+ | 'selector';
345
+ export type NativeFabricBridge = {
346
+ mount(
347
+ container: NativeObjectHandle,
348
+ moduleName: string,
349
+ properties?: NativeSerializableObject,
350
+ ): NativeFabricSurface;
351
+ update(surface: NativeFabricSurface, properties: NativeSerializableObject): void;
352
+ setSize(
353
+ surface: NativeFabricSurface,
354
+ minimumSize: NativeFabricSize,
355
+ maximumSize: NativeFabricSize,
356
+ ): void;
357
+ setFrame(surface: NativeFabricSurface, frame: NativeFabricFrame): void;
358
+ measure(view: NativeObjectHandle): NativeFabricFrame;
359
+ unmount(surface: NativeFabricSurface): void;
360
+ };
361
+ export type NativeFabricFrame = {
362
+ x: number;
363
+ y: number;
364
+ width: number;
365
+ height: number;
366
+ };
367
+ export type NativeFabricSize = {
368
+ width: number;
369
+ height: number;
370
+ };
371
+ export type NativeFabricSurface = NativeHandle;
372
+ /** An opaque reference to a native object. Only the bridge creates handles; plugins pass them back. */
373
+ export type NativeHandle = {
374
+ readonly [nativeHandle]: true;
375
+ };
376
+ export type NativeHookContext = {
377
+ self: NativeObjectHandle;
378
+ selector: string;
379
+ args: unknown[];
380
+ original: (...args: unknown[]) => unknown;
381
+ replaceObjectArgument(index: number, value: NativeObjectHandle | null): void;
382
+ };
383
+ export type NativeHookHandlers = {
384
+ before?: (context: NativeHookContext) => void | Promise<void>;
385
+ after?: (context: NativeHookContext) => void | Promise<void>;
386
+ replace?: (context: NativeHookContext) => unknown;
387
+ };
388
+ export type NativeHookOptions = {
389
+ cacheOnly?: boolean;
390
+ instance?: NativeObjectHandle;
391
+ once?: boolean;
392
+ } & NativeCallOptions;
393
+ export type NativeHookToken = {
394
+ readonly active: boolean;
395
+ setReturnValue(self: NativeObjectHandle, args: unknown[], value: unknown): void;
396
+ removeReturnValue(self: NativeObjectHandle, args: unknown[]): void;
397
+ clearReturnValues(): void;
398
+ remove(): void;
399
+ };
400
+ export type NativeObjCBridge = {
401
+ getClass(name: string): NativeClassHandle | null;
402
+ alloc(classOrName: string | NativeClassHandle): NativeObjectHandle;
403
+ className(handle: NativeHandle): string | null;
404
+ respondsTo(handle: NativeHandle, selector: string): boolean;
405
+ call(handle: NativeHandle, selector: string, ...args: unknown[]): unknown;
406
+ callSuper(
407
+ handle: NativeObjectHandle,
408
+ currentClass: NativeClassHandle | string,
409
+ selector: string,
410
+ ...args: unknown[]
411
+ ): unknown;
412
+ invoke(
413
+ handle: NativeObjectHandle,
414
+ selector: string,
415
+ args: unknown[],
416
+ options?: NativeCallOptions,
417
+ ): unknown;
418
+ invokeSuper(
419
+ handle: NativeObjectHandle,
420
+ currentClass: NativeClassHandle | string,
421
+ selector: string,
422
+ args: unknown[],
423
+ options?: NativeCallOptions,
424
+ ): unknown;
425
+ getIvar(handle: NativeObjectHandle, name: string): unknown;
426
+ setIvar(handle: NativeObjectHandle, name: string, value: unknown): void;
427
+ createAssociationKey(): NativeAssociationKey;
428
+ getAssociatedObject(handle: NativeObjectHandle, key: NativeAssociationKey): unknown;
429
+ setAssociatedObject(
430
+ handle: NativeObjectHandle,
431
+ key: NativeAssociationKey,
432
+ value: unknown,
433
+ policy?: string,
434
+ ): void;
435
+ struct<T extends NativeStructFields = NativeStructFields>(
436
+ name: string,
437
+ fields: T,
438
+ ): NativeStruct<T>;
439
+ array(handle: NativeObjectHandle): unknown[];
440
+ data(value: ArrayBuffer | Uint8Array): NativeObjectHandle;
441
+ hook(
442
+ className: string,
443
+ selector: string,
444
+ handlers: NativeHookHandlers,
445
+ options?: NativeHookOptions,
446
+ ): NativeHookToken;
447
+ };
448
+ export type NativeObjectHandle = NativeHandle;
449
+ export type NativePlatformApp = {
450
+ getAppSource(): string;
451
+ };
452
+ export type NativePlatformBridge = {
453
+ evaluateBytecode(bytecode: ArrayBuffer, tag?: string): unknown;
454
+ readonly device: NativePlatformDevice;
455
+ readonly app: NativePlatformApp;
456
+ };
457
+ export type NativePlatformDevice = {
458
+ getDeviceModel(): string;
459
+ getiOSVersionString(): string;
460
+ isJailbroken(): boolean;
461
+ isSystemApp(): boolean;
462
+ isVerifiedBuild(): boolean;
463
+ getEntitlements(): NativeSerializableObject;
464
+ getEntitlementsAsPlist(): string;
465
+ };
466
+ export type NativePluginBridge = {
467
+ readonly apiVersion: string;
468
+ readonly abiVersion: string;
469
+ readonly capabilities: readonly NativePluginCapability[];
470
+ readonly objc: NativeObjCBridge;
471
+ readonly ffi: NativeFFIBridge;
472
+ readonly fabric: NativeFabricBridge;
473
+ };
474
+ export type NativePluginCapability = (typeof NATIVE_PLUGIN_CAPABILITIES)[number];
475
+ export type NativePluginError = {
476
+ code: NativePluginErrorCode;
477
+ message: string;
478
+ capability?: NativePluginCapability;
479
+ };
480
+ export type NativePluginErrorCode =
481
+ | 'NATIVE_BRIDGE_ERROR'
482
+ | 'NATIVE_PLUGIN_API_VERSION_UNSUPPORTED'
483
+ | 'NATIVE_PLUGIN_CAPABILITY_DENIED'
484
+ | 'NATIVE_PLUGIN_SCOPE_DISPOSED'
485
+ | 'NATIVE_PLUGIN_UNAVAILABLE';
486
+ export type NativePointer = NativeHandle;
487
+ /** A value the bridge serializes by structure, such as Fabric surface props or a plist. */
488
+ export type NativeSerializable =
489
+ | string
490
+ | number
491
+ | boolean
492
+ | null
493
+ | NativeSerializable[]
494
+ | NativeSerializableObject;
495
+ export type NativeSerializableObject = {
496
+ [key: string]: NativeSerializable;
497
+ };
498
+ export type NativeStruct<T extends NativeStructFields = NativeStructFields> = {
499
+ readonly name: string;
500
+ readonly value?: T;
501
+ } & NativeHandle;
502
+ /** A C struct field: a scalar, a pointer or object, or a nested struct. */
503
+ export type NativeStructField = number | boolean | NativeHandle | NativeStructFields;
504
+ export type NativeStructFields = {
505
+ [field: string]: NativeStructField;
506
+ };
507
+ export type NativeThreadPolicy = 'current' | 'main';
508
+ export type Navigation<T = any> = {
192
509
  push: (route: string, params?: T) => void;
193
510
  pop: () => void;
194
511
  navigate: (route: string, params?: T) => void;
195
512
  goBack: () => void;
196
- setOptions: (options: Record<string, any>) => void;
197
- addListener: (event: string, callback: Fn) => Fn<void>;
198
- [key: string]: any;
199
- }
200
- export interface RowButtonProps {
201
- label?: ReactNode;
202
- icon?: ReactNode;
513
+ setOptions: (options: NavigationOptions) => void;
514
+ addListener: (event: string, callback: DiscordFunction) => DiscordFunction<void>;
515
+ };
516
+ /** The screen options accepted by {@link Navigation.setOptions}. */
517
+ export type NavigationOptions = {
518
+ title?: string;
519
+ headerRight?: DiscordFunction<ReactModule.ReactNode>;
520
+ };
521
+ export type PluginContext = {
522
+ readonly manifest: AddonManifest;
523
+ readonly id: string;
524
+ readonly capabilities: readonly NativePluginCapability[];
525
+ readonly native: NativePluginBridge;
526
+ dispose(): void;
527
+ };
528
+ /** An {@link Addon} whose instance is a {@link Plugin}. */
529
+ export type PluginEntity = Addon & {
530
+ instance: Plugin$1 | null;
531
+ };
532
+ /** Resolves each key of a {@link StyleSheetSpec} to the concrete RN style type it produced. */
533
+ export type ResolvedStyles<T extends StyleSheetSpec> = {
534
+ [K in keyof T]: T[K] extends ImageStyle
535
+ ? ImageStyle
536
+ : T[K] extends TextStyle
537
+ ? TextStyle
538
+ : ViewStyle;
539
+ };
540
+ export type RowButtonProps = {
541
+ label?: ReactModule.ReactNode;
542
+ icon?: ReactModule.ReactNode;
203
543
  arrow?: boolean;
204
544
  disabled?: boolean;
205
545
  variant?: LiteralUnion<'primary' | 'secondary'>;
206
- onPress?: Fn<void>;
207
- }
208
- export interface SegmentedControlProps {
546
+ onPress?: DiscordFunction<void>;
547
+ };
548
+ /** A tab of a segmented control, with the page it shows. */
549
+ export type SegmentedControlItem = {
550
+ id: string;
551
+ label: string;
552
+ page?: ReactModule.ReactNode;
553
+ };
554
+ /** `SegmentedControlPages`: the swipeable pages driven by a segmented control's state. */
555
+ export type SegmentedControlPagesProps = {
556
+ state: SegmentedControlState;
557
+ };
558
+ export type SegmentedControlProps = {
209
559
  /** The controller returned by `useSegmentedControlState`. */
210
560
  state: SegmentedControlState;
211
561
  /** @default 'default' */
212
562
  variant?: LiteralUnion<'default'>;
213
563
  keyboardShouldPersistTaps?: boolean | 'always' | 'never' | 'handled';
214
- }
564
+ };
215
565
  /** The state controller a `SegmentedControl` is driven by. */
216
- export interface SegmentedControlState {
566
+ export type SegmentedControlState = {
217
567
  activeIndex: number;
218
- items: any[];
568
+ items: SegmentedControlItem[];
219
569
  setActiveIndex: (index: number) => void;
220
- }
570
+ };
571
+ /** The options `useSegmentedControlState` builds a {@link SegmentedControlState} from. */
572
+ export type SegmentedControlStateOptions = {
573
+ items: SegmentedControlItem[];
574
+ pageWidth: number;
575
+ defaultIndex?: number;
576
+ onPageChange?: (index: number) => void;
577
+ };
221
578
  /** A registered Unbound settings entry, mirroring Discord's `SETTING_RENDERER_CONFIG` route shape. */
222
- export interface SettingsEntry {
579
+ export type SettingsEntry = {
223
580
  type: 'route';
224
581
  key: string;
225
582
  useTitle: () => string;
@@ -227,19 +584,26 @@ export interface SettingsEntry {
227
584
  parent: string | null;
228
585
  section?: string;
229
586
  excludeFromDisplay?: boolean;
230
- IconComponent?: ComponentType<any>;
587
+ IconComponent?: ReactModule.ComponentType;
231
588
  screen: SettingsScreen;
232
- }
589
+ };
590
+ /** A settings store, or a nested group of settings within one. */
591
+ export type SettingsObject = {
592
+ [key: string]: SettingsValue;
593
+ };
233
594
  /** The screen descriptor a settings route entry renders. */
234
- export interface SettingsScreen {
595
+ export type SettingsScreen = {
235
596
  route: string;
236
- getComponent: () => ComponentType<any>;
237
- }
597
+ /** Discord's navigator renders the screen with its own route props, so any component fits. */
598
+ getComponent: () => ReactModule.ComponentType<never>;
599
+ };
600
+ /** A JSON value held in a settings store. */
601
+ export type SettingsValue = string | number | boolean | null | SettingsValue[] | SettingsObject;
238
602
  /**
239
603
  * The DS `Slider`. It reads only `startIcon` / `endIcon` / `style` / `onValueChange` / `step`; the
240
604
  * remaining slider props (`value`, bounds, tint colours) are spread onto the underlying RN slider.
241
605
  */
242
- export interface SliderProps {
606
+ export type SliderProps = {
243
607
  value?: number;
244
608
  defaultValue?: number;
245
609
  minimumValue?: number;
@@ -250,52 +614,62 @@ export interface SliderProps {
250
614
  tapToSeek?: boolean;
251
615
  lowerLimit?: number;
252
616
  upperLimit?: number;
253
- startIcon?: ReactNode;
254
- endIcon?: ReactNode;
255
- valueLabel?: ReactNode;
617
+ startIcon?: ReactModule.ReactNode;
618
+ endIcon?: ReactModule.ReactNode;
619
+ valueLabel?: ReactModule.ReactNode;
256
620
  minimumTrackTintColor?: string;
257
621
  maximumTrackTintColor?: string;
258
622
  style?: StyleProp<ViewStyle>;
259
623
  onValueChange?: (value: number) => void;
260
624
  onSlidingStart?: (value: number) => void;
261
625
  onSlidingComplete?: (value: number) => void;
262
- }
626
+ };
263
627
  /** `SplitTextInput` / `SplitTextField`: a segmented input (e.g. verification codes). */
264
- export interface SplitTextInputProps extends TextFieldProps {
628
+ export type SplitTextInputProps = {
265
629
  isRound?: boolean;
266
630
  leadingText?: string;
267
- leadingPressableProps?: Record<string, any>;
268
- }
269
- export interface StackProps extends ViewProps {
631
+ leadingPressableProps?: PressableProps;
632
+ } & TextFieldProps;
633
+ export type StackProps = {
270
634
  spacing?: number;
271
635
  direction?: 'horizontal' | 'vertical';
272
636
  align?: 'start' | 'center' | 'end' | 'stretch';
273
637
  justify?: 'start' | 'center' | 'end' | 'between' | 'around';
274
- children?: ReactNode;
275
- }
276
- export interface SwitchProps {
638
+ children?: ReactModule.ReactNode;
639
+ } & ViewProps;
640
+ /** A stylesheet spec: each key maps to a view, text, or image style. */
641
+ export type StyleSheetSpec = Record<string, ViewStyle | TextStyle | ImageStyle>;
642
+ /** A stylesheet spec, or a function producing one (Discord accepts both forms). */
643
+ export type StyleSheetSpecOrFactory<T extends StyleSheetSpec> = T | ((...args: any[]) => T);
644
+ export type SwitchProps = {
277
645
  value: boolean;
278
646
  disabled?: boolean;
279
647
  accessibilityLabel?: string;
280
648
  onValueChange: (value: boolean) => void;
281
- }
282
- export interface TableCheckboxRowProps {
283
- label?: ReactNode;
284
- subLabel?: ReactNode;
649
+ };
650
+ export type TableCheckboxRowProps = {
651
+ label?: ReactModule.ReactNode;
652
+ subLabel?: ReactModule.ReactNode;
285
653
  checked: boolean;
286
654
  disabled?: boolean;
287
655
  accessibilityHint?: string;
288
- onPress: Fn<void>;
289
- }
290
- export interface TableRadioRowProps {
291
- label?: ReactNode;
292
- subLabel?: ReactNode;
656
+ onPress: DiscordFunction<void>;
657
+ };
658
+ export type TableRadioRowProps = {
659
+ label?: ReactModule.ReactNode;
660
+ subLabel?: ReactModule.ReactNode;
293
661
  value: any;
294
662
  disabled?: boolean;
295
663
  accessibilityHint?: string;
296
664
  legacyCompat?: boolean;
297
- }
298
- export interface TableRowGroupProps {
665
+ };
666
+ /** `TableRow` with its attached statics (`Icon`, `Arrow`, `TrailingText`). */
667
+ export type TableRowComponent = ReactModule.ComponentType<TableRowProps> & {
668
+ Icon: ReactModule.ComponentType<TableRowIconProps>;
669
+ Arrow: ReactModule.ComponentType<ViewProps>;
670
+ TrailingText: ReactModule.ComponentType<TrailingTextProps>;
671
+ };
672
+ export type TableRowGroupProps = {
299
673
  title?: string;
300
674
  description?: string;
301
675
  helperText?: string;
@@ -303,21 +677,21 @@ export interface TableRowGroupProps {
303
677
  hasTrailingText?: boolean;
304
678
  accessibilityRole?: string;
305
679
  accessibilityLabel?: string;
306
- children?: ReactNode;
307
- }
308
- export interface TableRowGroupTitleProps {
680
+ children?: ReactModule.ReactNode;
681
+ };
682
+ export type TableRowGroupTitleProps = {
309
683
  title: string;
310
- }
311
- export interface TableRowIconProps {
684
+ };
685
+ export type TableRowIconProps = {
312
686
  source?: number;
313
- IconComponent?: ComponentType<any>;
687
+ IconComponent?: ReactModule.ComponentType<any>;
314
688
  variant?: LiteralUnion<'default' | 'danger' | 'blurple'>;
315
- }
316
- export interface TableRowProps {
317
- label?: ReactNode;
318
- subLabel?: ReactNode;
319
- icon?: ReactNode;
320
- trailing?: ReactNode;
689
+ };
690
+ export type TableRowProps = {
691
+ label?: ReactModule.ReactNode;
692
+ subLabel?: ReactModule.ReactNode;
693
+ icon?: ReactModule.ReactNode;
694
+ trailing?: ReactModule.ReactNode;
321
695
  arrow?: boolean;
322
696
  disabled?: boolean;
323
697
  /** Rounds the top corners; set on the first row of a manually laid-out group. */
@@ -328,30 +702,29 @@ export interface TableRowProps {
328
702
  subLabelLineClamp?: number;
329
703
  variant?: LiteralUnion<'default' | 'danger'>;
330
704
  draggable?: boolean;
331
- onPress?: Fn<void>;
332
- children?: ReactNode;
333
- }
334
- export interface TableSwitchRowProps {
335
- label?: ReactNode;
336
- subLabel?: ReactNode;
337
- icon?: ReactNode;
338
- trailing?: ReactNode;
705
+ onPress?: DiscordFunction<void>;
706
+ children?: ReactModule.ReactNode;
707
+ };
708
+ export type TableSwitchRowProps = {
709
+ label?: ReactModule.ReactNode;
710
+ subLabel?: ReactModule.ReactNode;
711
+ icon?: ReactModule.ReactNode;
712
+ trailing?: ReactModule.ReactNode;
339
713
  value: boolean;
340
714
  disabled?: boolean;
341
715
  accessibilityHint?: string;
342
716
  variant?: LiteralUnion<'default'>;
343
717
  onValueChange: (value: boolean) => void;
344
- }
718
+ };
345
719
  /** `TextArea` extends the field family with a character limit. */
346
- export interface TextAreaProps extends TextFieldProps {
720
+ export type TextAreaProps = {
347
721
  maxLength?: number;
348
- }
722
+ } & TextFieldProps;
349
723
  /**
350
- * The redesign `TextField` and its siblings (`TextArea`, `SearchField`, `GhostInput`,
351
- * `SplitTextInput`). This is where the `size` / `status` / `isClearable` / `leadingIcon` chrome
352
- * actually lives, unlike {@link TextInputProps}. `onChange` receives the string value.
724
+ * The redesign `TextField` family (`TextArea`, `SearchField`, `GhostInput`, `SplitTextInput`), which
725
+ * owns the `size` / `status` / `leadingIcon` chrome. `onChange` receives the string value.
353
726
  */
354
- export interface TextFieldProps {
727
+ export type TextFieldProps = {
355
728
  value?: string;
356
729
  defaultValue?: string;
357
730
  placeholder?: string;
@@ -367,8 +740,8 @@ export interface TextFieldProps {
367
740
  trailingIcon?: IconSlot;
368
741
  leadingText?: string;
369
742
  trailingText?: string;
370
- leadingPressableProps?: Record<string, any>;
371
- trailingPressableProps?: Record<string, any>;
743
+ leadingPressableProps?: PressableProps;
744
+ trailingPressableProps?: PressableProps;
372
745
  secureTextEntry?: boolean;
373
746
  keyboardType?: RNTextInputProps['keyboardType'];
374
747
  autoComplete?: RNTextInputProps['autoComplete'];
@@ -377,19 +750,36 @@ export interface TextFieldProps {
377
750
  enableAndroidSanitizedInputWorkaround?: boolean;
378
751
  style?: StyleProp<ViewStyle>;
379
752
  inputStyle?: StyleProp<TextStyle>;
380
- children?: ReactNode;
753
+ children?: ReactModule.ReactNode;
381
754
  onChange?: (value: string) => void;
382
- onClear?: Fn<void>;
755
+ onClear?: DiscordFunction<void>;
383
756
  onFocus?: RNTextInputProps['onFocus'];
384
757
  onBlur?: RNTextInputProps['onBlur'];
385
- }
758
+ };
759
+ /**
760
+ * Native `TextInput` props forwarded through `TextInput` (`maxLength`, `selectionColor`, `onFocus`, …),
761
+ * minus the members `TextInput` overrides with its own semantics.
762
+ */
763
+ export type TextInputPassthrough = Omit<
764
+ RNTextInputProps,
765
+ | 'value'
766
+ | 'placeholder'
767
+ | 'multiline'
768
+ | 'numberOfLines'
769
+ | 'autoFocus'
770
+ | 'secureTextEntry'
771
+ | 'keyboardType'
772
+ | 'keyboardAppearance'
773
+ | 'autoCapitalize'
774
+ | 'autoCorrect'
775
+ | 'style'
776
+ | 'onChange'
777
+ >;
386
778
  /**
387
- * Discord's own form-style `TextInput` (`TextInput.native`), not React Native's. Its `onChange`
388
- * receives the raw string value, not an event. These are the props it reads verbatim off its props
389
- * object; every other prop is collected and spread onto the underlying native input via
390
- * {@link TextInputPassthrough}.
779
+ * Discord's form-style `TextInput` (`TextInput.native`), whose `onChange` receives the string value.
780
+ * Props it does not read are spread onto the native input via {@link TextInputPassthrough}.
391
781
  */
392
- export interface TextInputProps extends TextInputPassthrough {
782
+ export type TextInputProps = {
393
783
  value?: string;
394
784
  /** @default '' */
395
785
  placeholder?: string;
@@ -425,9 +815,9 @@ export interface TextInputProps extends TextInputPassthrough {
425
815
  /** Switches between the legacy and redesign render paths. @default true */
426
816
  allowRedesignTextInput?: boolean;
427
817
  onChange?: (value: string) => void;
428
- }
429
- export interface TextProps extends ViewProps {
430
- children?: ReactNode;
818
+ } & TextInputPassthrough;
819
+ export type TextProps = {
820
+ children?: ReactModule.ReactNode;
431
821
  variant?: TextVariant;
432
822
  color?: LiteralUnion<'text-normal' | 'text-muted' | 'header-primary' | 'header-secondary'>;
433
823
  style?: StyleProp<TextStyle>;
@@ -437,9 +827,28 @@ export interface TextProps extends ViewProps {
437
827
  animated?: boolean;
438
828
  numberOfLines?: number;
439
829
  allowFontScaling?: boolean;
440
- }
830
+ } & ViewProps;
831
+ /** Every typography variant Discord ships in `TextStyleSheet`, kept open for new ones. */
832
+ export type TextVariant = LiteralUnion<
833
+ | `heading-${'sm' | 'md' | 'lg' | 'xl' | 'xxl'}/${TextWeight | 'extrabold'}`
834
+ | `experimental/heading-${'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'xxl'}/${'semibold' | 'bold'}`
835
+ | `heading-deprecated-12/${TextWeight | 'extrabold'}`
836
+ | `redesign/heading-18/${'medium' | 'semibold' | 'bold'}`
837
+ | `text-${'xxs' | 'xs' | 'sm' | 'md' | 'lg'}/${TextWeight}`
838
+ | `redesign/message-preview/${TextWeight}`
839
+ | `redesign/channel-title/${TextWeight}`
840
+ | `experimental/body-${'xs' | 'sm' | 'md' | 'lg'}/${'normal' | 'medium'}`
841
+ | `experimental/meta/${'normal' | 'medium'}`
842
+ | `experimental/label-${'xs' | 'sm' | 'md' | 'lg'}/${'medium' | 'semibold'}`
843
+ | `experimental/mono-${'sm' | 'md'}/${'normal' | 'bold'}`
844
+ | `display-${'sm' | 'md' | 'lg'}`
845
+ | `experimental/display-${'xs' | 'sm' | 'md' | 'lg'}`
846
+ | 'eyebrow'
847
+ >;
848
+ /** The four common font weights used across typography variants. */
849
+ export type TextWeight = 'normal' | 'medium' | 'semibold' | 'bold';
441
850
  /** A theme's semantic and raw colour definitions plus optional background. */
442
- export interface Theme {
851
+ export type Theme = {
443
852
  semantic: Record<PropertyKey, ThemeSemanticColor>;
444
853
  raw: Record<PropertyKey, string>;
445
854
  type: 'midnight' | 'darker' | 'light';
@@ -448,168 +857,51 @@ export interface Theme {
448
857
  opacity?: number;
449
858
  url: string;
450
859
  };
451
- }
860
+ };
861
+ /** An {@link Addon} whose instance is a {@link Theme}, tracking its registration state. */
862
+ export type ThemeEntity = Addon & {
863
+ registered: boolean;
864
+ instance: Theme | null;
865
+ };
866
+ /** A single semantic colour definition in a {@link Theme}. */
867
+ export type ThemeSemanticColor = {
868
+ type: 'color' | 'raw';
869
+ value: string;
870
+ opacity?: number;
871
+ };
452
872
  /** A button rendered inside a toast. */
453
- export interface ToastButton {
873
+ export type ToastButton = {
454
874
  variant?: 'primary' | 'secondary' | 'tertiary';
455
875
  size?: 'sm' | 'md' | 'lg' | 'xl' | '2xl';
456
876
  iconPosition?: 'start' | 'end';
457
877
  content: string;
458
878
  icon?: number;
459
- onPress: Fn;
460
- }
879
+ onPress: () => void;
880
+ };
461
881
  /** A handle returned when showing a toast, used to update or close it. */
462
- export interface ToastHandle {
882
+ export type ToastHandle = {
463
883
  update: (options: Partial<ToastOptions>) => void;
464
884
  close: () => void;
465
- }
885
+ };
466
886
  /** Options accepted when showing a toast. */
467
- export interface ToastOptions {
468
- title?: string | ComponentType;
887
+ export type ToastOptions = {
888
+ title?: string | ReactModule.ComponentType;
469
889
  content?: string;
470
890
  duration?: number;
471
- onTimeout?: Fn;
891
+ onTimeout?: () => void;
472
892
  icon?: string | number | ImageSourcePropType;
473
893
  id?: string;
474
894
  buttons?: ToastButton[];
475
895
  tintedIcon?: boolean;
476
- }
896
+ };
477
897
  /** State and actions of the toast store. */
478
- export interface ToastStoreState {
898
+ export type ToastStoreState = {
479
899
  toasts: Record<string, InternalToastOptions>;
480
900
  addToast: (options: InternalToastOptions) => ToastHandle;
481
901
  updateToastWithOptions: (id: string, options: Partial<InternalToastOptions>) => void;
482
- }
483
- export interface TrailingTextProps {
484
- text: string;
485
- }
486
- /** The author of an addon: a display name and a numeric user id. */
487
- export type AddonAuthor = {
488
- name: string;
489
- id: `${number}`;
490
- };
491
- /** An addon referenced either by its id string or the {@link Addon} entity itself. */
492
- export type AddonResolveable = string | Addon;
493
- /** `Button` with its attached `Icon` static. */
494
- export type ButtonComponent = ComponentType<ButtonProps> & {
495
- Icon: ComponentType<TableRowIconProps>;
496
- };
497
- export type ButtonSize = LiteralUnion<'sm' | 'md' | 'lg'>;
498
- export type ButtonVariant = LiteralUnion<
499
- 'primary' | 'secondary' | 'tertiary' | 'destructive' | 'active' | 'expressive'
500
- >;
501
- /**
502
- * The style factory. Accepts a spec object (or a function returning one) and returns a hook. The
503
- * hook subscribes to the theme context and lazily resolves each key on access, so it must be called
504
- * inside a component body: `const styles = useStyles();`.
505
- */
506
- export type CreateStyles = <T extends StyleSheetSpec>(
507
- styles: StyleSheetSpecOrFactory<T>,
508
- ) => Fn<ResolvedStyles<T>>;
509
- /** Discord ships numeric enums as bidirectional maps; this models both directions. */
510
- export type EnumLike<K extends readonly string[]> = {
511
- [P in K[number]]: number;
512
- } & {
513
- [n: number]: K[number];
514
- };
515
- /** A custom font the native loader has registered, as injected on `window.UNBOUND_FONTS`. */
516
- export type FontDescriptor = {
517
- name: string;
518
- file: string;
519
- path: string;
520
- };
521
- /** A font managed by the Fonts manager: currently identical to its {@link FontDescriptor}. */
522
- export type FontEntity = FontDescriptor;
523
- /** A loaded icon pack: its bundle marker and {@link IconPackManifest}. */
524
- export type IconPack = {
525
- bundle: string;
526
- manifest: IconPackManifest;
527
- };
528
- /** An icon pack's manifest: an {@link AddonManifest} tagged with its source kind. */
529
- export type IconPackManifest = AddonManifest & {
530
- type: 'icon-pack';
531
- source: 'github' | 'other';
532
- };
533
- /** Icon slot: a rendered node, a component, or a render function. */
534
- export type IconSlot = ReactNode | ComponentType<any> | Fn<ReactNode>;
535
- /** Input sizing, shared by the whole `TextField`/`Input` family. */
536
- export type InputSize = LiteralUnion<'sm' | 'md' | 'lg'>;
537
- /** Input status. `focused` is an internal state and is not user-settable. */
538
- export type InputStatus = LiteralUnion<'default' | 'error'>;
539
- /** An {@link Addon} whose instance is a {@link Plugin}. */
540
- export type PluginEntity = Addon & {
541
- instance: Plugin$1 | null;
542
- };
543
- /** Resolves each key of a {@link StyleSheetSpec} to the concrete RN style type it produced. */
544
- export type ResolvedStyles<T extends StyleSheetSpec> = {
545
- [K in keyof T]: T[K] extends ImageStyle
546
- ? ImageStyle
547
- : T[K] extends TextStyle
548
- ? TextStyle
549
- : ViewStyle;
550
- };
551
- /** A stylesheet spec: each key maps to a view, text, or image style. */
552
- export type StyleSheetSpec = Record<
553
- string,
554
- ViewStyle | TextStyle | ImageStyle | Record<PropertyKey, any>
555
- >;
556
- /** A stylesheet spec, or a function producing one (Discord accepts both forms). */
557
- export type StyleSheetSpecOrFactory<T extends StyleSheetSpec> = T | ((...args: any[]) => T);
558
- /** `TableRow` with its attached statics (`Icon`, `Arrow`, `TrailingText`). */
559
- export type TableRowComponent = ComponentType<TableRowProps> & {
560
- Icon: ComponentType<TableRowIconProps>;
561
- Arrow: ComponentType<ViewProps>;
562
- TrailingText: ComponentType<TrailingTextProps>;
563
- };
564
- /**
565
- * Native `TextInput` props forwarded through `TextInput`. Everything the DS component does not read
566
- * itself (`maxLength`, `selectionColor`, `onFocus`, …) is spread onto the underlying native input,
567
- * so it accepts the RN surface too, minus the members `TextInput` overrides with its own semantics.
568
- */
569
- export type TextInputPassthrough = Omit<
570
- RNTextInputProps,
571
- | 'value'
572
- | 'placeholder'
573
- | 'multiline'
574
- | 'numberOfLines'
575
- | 'autoFocus'
576
- | 'secureTextEntry'
577
- | 'keyboardType'
578
- | 'keyboardAppearance'
579
- | 'autoCapitalize'
580
- | 'autoCorrect'
581
- | 'style'
582
- | 'onChange'
583
- >;
584
- /** Every typography variant Discord ships in `TextStyleSheet`, kept open for new ones. */
585
- export type TextVariant = LiteralUnion<
586
- | `heading-${'sm' | 'md' | 'lg' | 'xl' | 'xxl'}/${TextWeight | 'extrabold'}`
587
- | `experimental/heading-${'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'xxl'}/${'semibold' | 'bold'}`
588
- | `heading-deprecated-12/${TextWeight | 'extrabold'}`
589
- | `redesign/heading-18/${'medium' | 'semibold' | 'bold'}`
590
- | `text-${'xxs' | 'xs' | 'sm' | 'md' | 'lg'}/${TextWeight}`
591
- | `redesign/message-preview/${TextWeight}`
592
- | `redesign/channel-title/${TextWeight}`
593
- | `experimental/body-${'xs' | 'sm' | 'md' | 'lg'}/${'normal' | 'medium'}`
594
- | `experimental/meta/${'normal' | 'medium'}`
595
- | `experimental/label-${'xs' | 'sm' | 'md' | 'lg'}/${'medium' | 'semibold'}`
596
- | `experimental/mono-${'sm' | 'md'}/${'normal' | 'bold'}`
597
- | `display-${'sm' | 'md' | 'lg'}`
598
- | `experimental/display-${'xs' | 'sm' | 'md' | 'lg'}`
599
- | 'eyebrow'
600
- >;
601
- /** The four common font weights used across typography variants. */
602
- export type TextWeight = 'normal' | 'medium' | 'semibold' | 'bold';
603
- /** An {@link Addon} whose instance is a {@link Theme}, tracking its registration state. */
604
- export type ThemeEntity = Addon & {
605
- registered: boolean;
606
- instance: Theme | null;
607
902
  };
608
- /** A single semantic colour definition in a {@link Theme}. */
609
- export type ThemeSemanticColor = {
610
- type: 'color' | 'raw';
611
- value: string;
612
- opacity?: number;
903
+ export type TrailingTextProps = {
904
+ text: string;
613
905
  };
614
906
  /** `TransitionStates`: MOUNTED = 0, ENTERED = 1, YEETED = 2. */
615
907
  export type TransitionState = 'MOUNTED' | 'ENTERED' | 'YEETED';
@@ -618,12 +910,13 @@ export type UnboundAsset = DiscordAsset & {
618
910
  iconPackPath?: string;
619
911
  iconPackScale?: number;
620
912
  };
621
-
622
913
  /** The lifecycle and settings contract implemented by a plugin. */
623
- interface Plugin$1 {
624
- start?(): void;
914
+ type Plugin$1 = {
915
+ start?(context?: PluginContext): void;
625
916
  stop?(): void;
626
- getSettingsPanel?(): ReactNode;
627
- }
917
+ getSettingsPanel?(): ReactModule.ReactNode;
918
+ };
628
919
 
629
920
  export { Plugin$1 as Plugin };
921
+
922
+ export {};