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