55 * https://github.com/deltablot/malle
66 */
77
8+ // type for lazy loaders
9+ type Lazy < T > = T | Promise < T > | ( ( ) => T | Promise < T > ) ;
10+
11+ function isPromise < T > ( v : unknown ) : v is Promise < T > {
12+ return typeof v === 'object' && v !== null && 'then' in v &&
13+ typeof ( v as { then ?: unknown } ) . then === 'function' ;
14+ }
15+
16+ async function resolveLazy < T > ( src : Lazy < T > ) : Promise < T > {
17+ const value = typeof src === 'function' ? ( src as ( ) => T | Promise < T > ) ( ) : src ;
18+ return isPromise < T > ( value ) ? await value : value ;
19+ }
20+
821// The `InputType` will set the `type` attribute of the generated input element.
922export enum InputType {
1023 Color = 'color' ,
@@ -163,7 +176,7 @@ export interface Options {
163176 * selectOptions: Something.getOptions(),
164177 * ```
165178 */
166- selectOptions ?: Array < SelectOptions > | Promise < Array < SelectOptions > > ;
179+ selectOptions ?: Lazy < SelectOptions [ ] > ;
167180 // What is the name of the key to use to lookup the values in the selectOptions array?
168181 // @default value
169182 selectOptionsValueKey ?: string ;
@@ -394,7 +407,7 @@ export class Malle {
394407 }
395408 }
396409
397- getInput ( ) : HTMLInputElement {
410+ async getInput ( ) : Promise < HTMLInputElement > {
398411 // create the input
399412 let inputElement = 'input' ;
400413 if ( this . opt . inputType === InputType . Textarea ) {
@@ -443,14 +456,13 @@ export class Malle {
443456
444457 // add options for a select
445458 if ( this . opt . inputType === InputType . Select ) {
446- Promise . resolve ( this . opt . selectOptions ) . then ( o => {
447- o . forEach ( o => {
448- const option = document . createElement ( 'option' ) ;
449- option . value = o [ this . opt . selectOptionsValueKey ] ;
450- option [ this . innerFun ] = o [ this . opt . selectOptionsTextKey ] ;
451- option . selected = ( o . selected ?? false ) || this . original [ this . innerFun ] === o [ this . opt . selectOptionsTextKey ] ;
452- input . appendChild ( option ) ;
453- } ) ;
459+ const opts = this . opt . selectOptions ? await resolveLazy ( this . opt . selectOptions ) : [ ] ;
460+ opts . forEach ( o => {
461+ const option = document . createElement ( 'option' ) ;
462+ option . value = o [ this . opt . selectOptionsValueKey ] ;
463+ option [ this . innerFun ] = o [ this . opt . selectOptionsTextKey ] ;
464+ option . selected = ( o . selected ?? false ) || this . original [ this . innerFun ] === o [ this . opt . selectOptionsTextKey ] ;
465+ input . appendChild ( option ) ;
454466 } ) ;
455467 }
456468 // listen on keypress for Enter/Escape keys. Note that Escape will only appear with keydown/keyup, not keypress event.
@@ -467,7 +479,7 @@ export class Malle {
467479 /**
468480 * Process the triggering event: replace target element with an input
469481 */
470- process ( event : Event ) {
482+ async process ( event : Event ) {
471483 this . debug ( 'Event triggered:' ) ;
472484 this . debug ( event . toString ( ) ) ;
473485
@@ -488,7 +500,7 @@ export class Malle {
488500 this . opt . formClasses . forEach ( cl => {
489501 form . classList . add ( cl ) ;
490502 } ) ;
491- const input = this . getInput ( ) ;
503+ const input = await this . getInput ( ) ;
492504 form . appendChild ( input ) ;
493505
494506 // now the submit/cancel buttons
0 commit comments