cordo 2.2.4 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cordo",
3
- "version": "2.2.4",
3
+ "version": "2.3.0",
4
4
  "description": "A framework for handling complex discord api interactions",
5
5
  "exports": {
6
6
  ".": "./src/index.ts",
@@ -17,8 +17,8 @@ export function container(...components: AllowedComponentArray) {
17
17
  spoiler
18
18
  })),
19
19
 
20
- accentColor: (color: string | number) => {
21
- accentColor = color
20
+ accentColor: (color: string | number | null) => {
21
+ accentColor = color ?? undefined
22
22
  return out
23
23
  },
24
24
  spoiler: (value: boolean = true) => {
@@ -0,0 +1,53 @@
1
+ import { Hooks } from "../../core/hooks"
2
+ import type { CordoFunct, CordoFunctRun } from "../../functions"
3
+ import { FunctCompiler } from "../../functions/compiler"
4
+ import { ComponentType, createComponent, renderComponentList, type CordoComponent } from "../component"
5
+ import type { CordoModifier } from "../modifier"
6
+
7
+
8
+ export type AllowedComponents = CordoComponent<'TextInput'> | CordoModifier
9
+ type AllowedComponentArray = Array<AllowedComponents | AllowedComponents[]>
10
+
11
+ export function modal(...components: AllowedComponentArray) {
12
+ let titleVal: string | undefined = undefined
13
+ const functVal: CordoFunct[] = []
14
+
15
+ function getTitle() {
16
+ if (!titleVal)
17
+ return 'Modal'
18
+
19
+ return Hooks.callHook(
20
+ 'transformUserFacingText',
21
+ titleVal,
22
+ { component: 'Modal', position: 'title' }
23
+ )
24
+ }
25
+
26
+ const out = {
27
+ ...createComponent('Modal', ({ hirarchy, attributes }) => ({
28
+ type: ComponentType.Modal,
29
+ components: renderComponentList(components.flat(), 'Modal', hirarchy, attributes),
30
+ title: getTitle(),
31
+ custom_id: FunctCompiler.toCustomId(functVal)
32
+ })),
33
+
34
+ title: (value: string) => {
35
+ titleVal = value
36
+ return out
37
+ },
38
+ onClick: (...funct: CordoFunctRun) => {
39
+ functVal.push(...funct)
40
+ return out
41
+ },
42
+ *[Symbol.iterator]() {
43
+ for (const component of components) {
44
+ if (Array.isArray(component))
45
+ yield* component
46
+ else
47
+ yield component
48
+ }
49
+ }
50
+ }
51
+
52
+ return out
53
+ }
@@ -2,6 +2,7 @@ import defu from "defu"
2
2
  import { row } from "./builtin/row"
3
3
  import { readModifier, type CordoModifier } from "./modifier"
4
4
  import type { AllowedComponents as ContainerAllowedComponents } from "./builtin/container"
5
+ import type { AllowedComponents as ModalAllowedComponents } from "./builtin/modal"
5
6
 
6
7
 
7
8
  const CordoComponentSymbol = Symbol.for('CordoComponent')
@@ -21,7 +22,9 @@ export const ComponentType = {
21
22
  MediaGallery: 12,
22
23
  File: 13,
23
24
  Seperator: 14,
24
- Container: 17
25
+ Container: 17,
26
+
27
+ Modal: -1, // This is a special type that is not used in the API, but for Cordo's internal use
25
28
  } as const
26
29
  export type StringComponentType = keyof typeof ComponentType
27
30
  export type ComponentIdFromName<Name extends StringComponentType> = typeof ComponentType[Name]
@@ -42,7 +45,9 @@ export type CordoComponent<Type extends StringComponentType = StringComponentTyp
42
45
  } & (
43
46
  Type extends 'Container'
44
47
  ? { [Symbol.iterator]: () => Iterator<ContainerAllowedComponents> }
45
- : { [Symbol.iterator]: never }
48
+ : Type extends 'Modal'
49
+ ? { [Symbol.iterator]: () => Iterator<ModalAllowedComponents> }
50
+ : { [Symbol.iterator]: never }
46
51
  )
47
52
  export type CordoComponentPayload<Type extends StringComponentType> = CordoComponent<Type>[typeof CordoComponentSymbol]
48
53
 
@@ -16,6 +16,7 @@ export { divider } from './builtin/divider'
16
16
  export { gallery } from './builtin/gallery'
17
17
  export { image } from './builtin/image'
18
18
  export { linkButton } from './builtin/link-button'
19
+ export { modal } from './builtin/modal'
19
20
  export { row } from './builtin/row'
20
21
  export { section } from './builtin/section'
21
22
  export { selectString } from './builtin/select-string'
@@ -105,6 +105,8 @@ export type RouteRequest = {
105
105
  ack: () => void
106
106
  /** render the provided components */
107
107
  render: (...response: RouteResponse) => void
108
+ /** open a modal with the provided components */
109
+ prompt: (modal: CordoComponent<'Modal'>) => void
108
110
  /** run a different route. use await to await the call. Returns whether successful, null if not run */
109
111
  run: (...params: Parameters<typeof run>) => Promise<boolean | null>
110
112
  /** let a different route handle this. Returns whether successful, null if not run */
@@ -133,7 +135,7 @@ export function assertCordoRequest<
133
135
  >(request: RouteRequest, assumptions: {
134
136
  location: Location
135
137
  source: Source
136
- }): request is RouteRequest & (
138
+ }): asserts request is RouteRequest & (
137
139
  Location extends 'guild'
138
140
  ? RouteRequestInGuild
139
141
  : RouteRequestInDM
@@ -148,7 +150,6 @@ export function assertCordoRequest<
148
150
  throw new RouteAssumptionFailedError(request, assumptions)
149
151
  if (assumptions.source && request.source !== assumptions.source)
150
152
  throw new RouteAssumptionFailedError(request, assumptions)
151
- return true
152
153
  }
153
154
 
154
155
  export namespace RouteInternals {
@@ -1,6 +1,6 @@
1
- import { ApplicationCommandType, ComponentType, InteractionContextType, InteractionResponseType, InteractionType, MessageFlags, type APIUser } from "discord-api-types/v10"
1
+ import { ApplicationCommandType, InteractionContextType, InteractionResponseType, InteractionType, MessageFlags, type APIUser } from "discord-api-types/v10"
2
2
  import { disableAllComponents } from "../../components"
3
- import { isComponent, renderComponentList } from "../../components/component"
3
+ import { ComponentType, isComponent, renderComponent, renderComponentList, type CordoComponent } from "../../components/component"
4
4
  import type { RouteInternals, RouteRequest, RouteResponse } from "../files/route"
5
5
  import { InteractionInternals, type CordoInteraction } from "../interaction"
6
6
  import { CordoMagic } from "../magic"
@@ -60,6 +60,23 @@ export namespace RoutingRespond {
60
60
  }
61
61
  }
62
62
 
63
+ export function renderModal(modal: CordoComponent<'Modal'>) {
64
+ CordoMagic.resetIdCounter()
65
+ const rendered = renderComponent(modal, null)
66
+
67
+ if (!rendered || rendered.type !== ComponentType.Modal)
68
+ return null
69
+
70
+ return {
71
+ type: InteractionResponseType.Modal,
72
+ data: {
73
+ custom_id: rendered.custom_id,
74
+ title: rendered.title,
75
+ components: rendered.components,
76
+ }
77
+ }
78
+ }
79
+
63
80
  export function buildRouteRequest(
64
81
  route: RouteInternals.ParsedRoute,
65
82
  args: string[],
@@ -117,6 +134,10 @@ export namespace RoutingRespond {
117
134
  const rendered = renderRouteResponse(response, interaction, opts)
118
135
  CordoGateway.respondTo(interaction, rendered)
119
136
  },
137
+ prompt: opts.disableRendering ? noOp : (modal) => {
138
+ const rendered = renderModal(modal)
139
+ CordoGateway.respondTo(interaction, rendered)
140
+ },
120
141
  goto: opts.disableRendering ? noOp(Promise.resolve(null)) : (...args) => FunctInternals.evalFunct(goto(...args), interaction),
121
142
  run: opts.disableRendering ? noOp(Promise.resolve(null)) : (...args) => FunctInternals.evalFunct(run(...args), interaction),
122
143
 
@@ -68,6 +68,7 @@ export namespace HandleErrors {
68
68
  }
69
69
 
70
70
  export function handleNonCordoError(error: any) {
71
+ console.error('(dev) Non cordo error:')
71
72
  console.error(error)
72
73
  }
73
74