@jakubmazanec/cli 0.1.0-11dd4a3 → 0.1.0-265acad

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/README.md CHANGED
@@ -1,10 +1,12 @@
1
+ <!-- header -->
1
2
  <div align="center">
2
3
 
3
4
  # @jakubmazanec/cli
4
5
 
5
- <!-- description -->TypeScript-first library for building CLIs.<!-- description -->
6
+ TypeScript-first library for building CLIs.
6
7
 
7
8
  </div>
9
+ <!-- header -->
8
10
 
9
11
  ## Installation
10
12
 
@@ -14,7 +14,7 @@ import { parseArguments } from '@jakubmazanec/args';
14
14
  * @param name Command name, ie. space-separated words consisting only of letters, numbers (but not at the start of the word) or dashes.
15
15
  * @param action Function that runs when command is executed.
16
16
  * @param options Additionl command options.
17
- */ constructor(name, action, { description , parameters , options , allowUnknownOptions , allowUnknownParameters }){
17
+ */ constructor(name, action, { description, parameters, options, allowUnknownOptions, allowUnknownParameters }){
18
18
  this.name = name;
19
19
  this.action = action;
20
20
  if (description) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/program/Command.ts"],"sourcesContent":["import {\n type Argv,\n parseArguments,\n type OptionsConfig,\n type ParametersConfig,\n type Arguments,\n} from '@jakubmazanec/args';\n\nimport {type CommandAction} from './CommandAction.js';\nimport {type CommandOptions} from './CommandOptions.js';\nimport {type Program} from './Program.js';\n// import {type ProgramCommand} from './ProgramCommand.js';\n\n/**\n * Command encapsulates piece of a CLI's logic and is executed when {@linkcode Program} instance parses that command from the command line arguments.\n */\nexport class Command<\n A extends string,\n const B extends ParametersConfig | undefined = undefined,\n const C extends OptionsConfig | undefined = undefined,\n D extends boolean = false,\n E extends boolean = false,\n> {\n /* implements ProgramCommand*/\n readonly name: A;\n readonly description?: string;\n readonly parameters: B extends ParametersConfig ? B : null;\n readonly options: C extends OptionsConfig ? C : null;\n readonly allowUnknownOptions: D;\n readonly allowUnknownParameters: E;\n private readonly action: CommandAction<A, B, C, D, E>;\n\n /**\n * @param name Command name, ie. space-separated words consisting only of letters, numbers (but not at the start of the word) or dashes.\n * @param action Function that runs when command is executed.\n * @param options Additionl command options.\n */\n constructor(\n name: A,\n action: CommandAction<A, B, C, D, E>,\n {\n description,\n parameters,\n options,\n allowUnknownOptions,\n allowUnknownParameters,\n }: CommandOptions<NonNullable<B>, NonNullable<C>, D, E>,\n ) {\n this.name = name;\n this.action = action;\n\n if (description) {\n this.description = description;\n }\n\n if (parameters) {\n this.parameters = parameters as B extends ParametersConfig ? B : null;\n } else {\n this.parameters = null as B extends ParametersConfig ? B : null;\n }\n\n if (options) {\n this.options = options as C extends OptionsConfig ? C : null;\n } else {\n this.options = null as C extends OptionsConfig ? C : null;\n }\n\n if (allowUnknownOptions) {\n this.allowUnknownOptions = allowUnknownOptions;\n } else {\n this.allowUnknownOptions = false as D;\n }\n\n if (allowUnknownParameters) {\n this.allowUnknownParameters = allowUnknownParameters;\n } else {\n this.allowUnknownParameters = false as E;\n }\n }\n\n /**\n * Parses a list of command line arguments into an arguments object. Parser is pre-configured based on this command.\n */\n parseArguments(argv: Argv): Arguments<{\n commands: readonly [A];\n parameters: B;\n options: C;\n allowUnknownOptions: D;\n allowUnknownParameters: E;\n }> {\n return parseArguments(argv, {\n commands: [this.name],\n parameters: this.parameters ?? undefined,\n options: this.options ?? undefined,\n allowUnknownOptions: this.allowUnknownOptions,\n allowUnknownParameters: this.allowUnknownParameters,\n } as {\n commands: readonly [A];\n parameters: B;\n options: C;\n allowUnknownOptions: D;\n allowUnknownParameters: E;\n });\n }\n\n /**\n * Executes command action with provided parsed arguments and {@linkcode Program} instance.\n */\n async run(\n parsedArgs: Arguments<{\n commands: readonly [A];\n parameters: B;\n options: C;\n allowUnknownOptions: D;\n allowUnknownParameters: E;\n }>,\n program: Program,\n ): Promise<void> {\n await this.action(parsedArgs, program);\n }\n}\n"],"names":["parseArguments","Command","name","description","parameters","options","allowUnknownOptions","allowUnknownParameters","action","constructor","argv","commands","undefined","run","parsedArgs","program"],"mappings":"AAAA,SAEEA,cAAc,QAIT,qBAAqB;AAK5B,2DAA2D;AAE3D;;CAEC,GACD,OAAO,MAAMC;IAOX,4BAA4B,GAC5B,AAASC,KAAQ;IACRC,YAAqB;IACrBC,WAAkD;IAClDC,QAA4C;IAC5CC,oBAAuB;IACvBC,uBAA0B;IAClBC,OAAqC;IAEtD;;;;GAIC,GACDC,YACEP,IAAO,EACPM,MAAoC,EACpC,EACEL,YAAW,EACXC,WAAU,EACVC,QAAO,EACPC,oBAAmB,EACnBC,uBAAsB,EAC+B,CACvD;QACA,IAAI,CAACL,OAAOA;QACZ,IAAI,CAACM,SAASA;QAEd,IAAIL,aAAa;YACf,IAAI,CAACA,cAAcA;QACrB;QAEA,IAAIC,YAAY;YACd,IAAI,CAACA,aAAaA;QACpB,OAAO;YACL,IAAI,CAACA,aAAa;QACpB;QAEA,IAAIC,SAAS;YACX,IAAI,CAACA,UAAUA;QACjB,OAAO;YACL,IAAI,CAACA,UAAU;QACjB;QAEA,IAAIC,qBAAqB;YACvB,IAAI,CAACA,sBAAsBA;QAC7B,OAAO;YACL,IAAI,CAACA,sBAAsB;QAC7B;QAEA,IAAIC,wBAAwB;YAC1B,IAAI,CAACA,yBAAyBA;QAChC,OAAO;YACL,IAAI,CAACA,yBAAyB;QAChC;IACF;IAEA;;GAEC,GACDP,eAAeU,IAAU,EAMtB;QACD,OAAOV,eAAeU,MAAM;YAC1BC,UAAU;gBAAC,IAAI,CAACT;aAAK;YACrBE,YAAY,IAAI,CAACA,cAAcQ;YAC/BP,SAAS,IAAI,CAACA,WAAWO;YACzBN,qBAAqB,IAAI,CAACA;YAC1BC,wBAAwB,IAAI,CAACA;QAC/B;IAOF;IAEA;;GAEC,GACD,MAAMM,IACJC,UAME,EACFC,OAAgB,EACD;QACf,MAAM,IAAI,CAACP,OAAOM,YAAYC;IAChC;AACF"}
1
+ {"version":3,"sources":["../../src/program/Command.ts"],"sourcesContent":["import {\n type Argv,\n parseArguments,\n type OptionsConfig,\n type ParametersConfig,\n type Arguments,\n} from '@jakubmazanec/args';\n\nimport {type CommandAction} from './CommandAction.js';\nimport {type CommandOptions} from './CommandOptions.js';\nimport {type Program} from './Program.js';\n// import {type ProgramCommand} from './ProgramCommand.js';\n\n/**\n * Command encapsulates piece of a CLI's logic and is executed when {@linkcode Program} instance parses that command from the command line arguments.\n */\nexport class Command<\n A extends string,\n const B extends ParametersConfig | undefined = undefined,\n const C extends OptionsConfig | undefined = undefined,\n D extends boolean = false,\n E extends boolean = false,\n> {\n /* implements ProgramCommand*/\n readonly name: A;\n readonly description?: string;\n readonly parameters: B extends ParametersConfig ? B : null;\n readonly options: C extends OptionsConfig ? C : null;\n readonly allowUnknownOptions: D;\n readonly allowUnknownParameters: E;\n private readonly action: CommandAction<A, B, C, D, E>;\n\n /**\n * @param name Command name, ie. space-separated words consisting only of letters, numbers (but not at the start of the word) or dashes.\n * @param action Function that runs when command is executed.\n * @param options Additionl command options.\n */\n constructor(\n name: A,\n action: CommandAction<A, B, C, D, E>,\n {\n description,\n parameters,\n options,\n allowUnknownOptions,\n allowUnknownParameters,\n }: CommandOptions<NonNullable<B>, NonNullable<C>, D, E>,\n ) {\n this.name = name;\n this.action = action;\n\n if (description) {\n this.description = description;\n }\n\n if (parameters) {\n this.parameters = parameters as B extends ParametersConfig ? B : null;\n } else {\n this.parameters = null as B extends ParametersConfig ? B : null;\n }\n\n if (options) {\n this.options = options as C extends OptionsConfig ? C : null;\n } else {\n this.options = null as C extends OptionsConfig ? C : null;\n }\n\n if (allowUnknownOptions) {\n this.allowUnknownOptions = allowUnknownOptions;\n } else {\n this.allowUnknownOptions = false as D;\n }\n\n if (allowUnknownParameters) {\n this.allowUnknownParameters = allowUnknownParameters;\n } else {\n this.allowUnknownParameters = false as E;\n }\n }\n\n /**\n * Parses a list of command line arguments into an arguments object. Parser is pre-configured based on this command.\n */\n parseArguments(argv: Argv): Arguments<{\n commands: readonly [A];\n parameters: B;\n options: C;\n allowUnknownOptions: D;\n allowUnknownParameters: E;\n }> {\n return parseArguments(argv, {\n commands: [this.name],\n parameters: this.parameters ?? undefined,\n options: this.options ?? undefined,\n allowUnknownOptions: this.allowUnknownOptions,\n allowUnknownParameters: this.allowUnknownParameters,\n } as {\n commands: readonly [A];\n parameters: B;\n options: C;\n allowUnknownOptions: D;\n allowUnknownParameters: E;\n });\n }\n\n /**\n * Executes command action with provided parsed arguments and {@linkcode Program} instance.\n */\n async run(\n parsedArgs: Arguments<{\n commands: readonly [A];\n parameters: B;\n options: C;\n allowUnknownOptions: D;\n allowUnknownParameters: E;\n }>,\n program: Program,\n ): Promise<void> {\n await this.action(parsedArgs, program);\n }\n}\n"],"names":["parseArguments","Command","name","description","parameters","options","allowUnknownOptions","allowUnknownParameters","action","constructor","argv","commands","undefined","run","parsedArgs","program"],"mappings":"AAAA,SAEEA,cAAc,QAIT,qBAAqB;AAK5B,2DAA2D;AAE3D;;CAEC,GACD,OAAO,MAAMC;IAOX,4BAA4B,GAC5B,AAASC,KAAQ;IACRC,YAAqB;IACrBC,WAAkD;IAClDC,QAA4C;IAC5CC,oBAAuB;IACvBC,uBAA0B;IAClBC,OAAqC;IAEtD;;;;GAIC,GACDC,YACEP,IAAO,EACPM,MAAoC,EACpC,EACEL,WAAW,EACXC,UAAU,EACVC,OAAO,EACPC,mBAAmB,EACnBC,sBAAsB,EAC+B,CACvD;QACA,IAAI,CAACL,IAAI,GAAGA;QACZ,IAAI,CAACM,MAAM,GAAGA;QAEd,IAAIL,aAAa;YACf,IAAI,CAACA,WAAW,GAAGA;QACrB;QAEA,IAAIC,YAAY;YACd,IAAI,CAACA,UAAU,GAAGA;QACpB,OAAO;YACL,IAAI,CAACA,UAAU,GAAG;QACpB;QAEA,IAAIC,SAAS;YACX,IAAI,CAACA,OAAO,GAAGA;QACjB,OAAO;YACL,IAAI,CAACA,OAAO,GAAG;QACjB;QAEA,IAAIC,qBAAqB;YACvB,IAAI,CAACA,mBAAmB,GAAGA;QAC7B,OAAO;YACL,IAAI,CAACA,mBAAmB,GAAG;QAC7B;QAEA,IAAIC,wBAAwB;YAC1B,IAAI,CAACA,sBAAsB,GAAGA;QAChC,OAAO;YACL,IAAI,CAACA,sBAAsB,GAAG;QAChC;IACF;IAEA;;GAEC,GACDP,eAAeU,IAAU,EAMtB;QACD,OAAOV,eAAeU,MAAM;YAC1BC,UAAU;gBAAC,IAAI,CAACT,IAAI;aAAC;YACrBE,YAAY,IAAI,CAACA,UAAU,IAAIQ;YAC/BP,SAAS,IAAI,CAACA,OAAO,IAAIO;YACzBN,qBAAqB,IAAI,CAACA,mBAAmB;YAC7CC,wBAAwB,IAAI,CAACA,sBAAsB;QACrD;IAOF;IAEA;;GAEC,GACD,MAAMM,IACJC,UAME,EACFC,OAAgB,EACD;QACf,MAAM,IAAI,CAACP,MAAM,CAACM,YAAYC;IAChC;AACF"}
@@ -15,7 +15,7 @@ import { Failure, Help } from '../ui.js';
15
15
  stdin: process.stdin,
16
16
  stdout: process.stdout
17
17
  };
18
- constructor({ name , version , description , bin }){
18
+ constructor({ name, version, description, bin }){
19
19
  if (name) {
20
20
  this.name = name;
21
21
  }
@@ -47,9 +47,9 @@ import { Failure, Help } from '../ui.js';
47
47
  } else {
48
48
  this.isRendering = true;
49
49
  }
50
- let { render } = await import('ink');
51
- let { createElement } = await import('react');
52
- let { stdin , stdout , stderr } = this.streams;
50
+ let { render } = await import('ink');
51
+ let { createElement } = await import('react');
52
+ let { stdin, stdout, stderr } = this.streams;
53
53
  try {
54
54
  render(createElement(Wrapper, {
55
55
  program: this
@@ -81,7 +81,7 @@ import { Failure, Help } from '../ui.js';
81
81
  if (parsedArgs.command) {
82
82
  hasCommandRun = true;
83
83
  if (parsedArgs.errors.length) {
84
- let { createElement } = await import('react');
84
+ let { createElement } = await import('react');
85
85
  for (let error of parsedArgs.errors){
86
86
  await this.renderElement(createElement(Failure, {
87
87
  error
@@ -94,7 +94,7 @@ import { Failure, Help } from '../ui.js';
94
94
  }
95
95
  }
96
96
  if (!hasCommandRun) {
97
- let { createElement } = await import('react');
97
+ let { createElement } = await import('react');
98
98
  await this.renderElement(createElement(Help, {
99
99
  program: this
100
100
  }));
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/program/Program.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any -- needed */\nimport {type ParametersConfig, type Argv, type OptionsConfig} from '@jakubmazanec/args';\n\nimport {type Command} from './Command.js';\nimport {ProgramError} from './ProgramError.js';\nimport {type ProgramOptions} from './ProgramOptions.js';\nimport {type ProgramStreams} from './ProgramStreams.js';\nimport {Wrapper} from '../ui/internals.js';\nimport {Failure, Help} from '../ui.js';\n\n/**\n * Program manages and executes {@linkcode Program} instances attached to it based on parsing command line arguments.\n */\nexport class Program {\n /** Program name. */\n readonly name?: string;\n\n /** Program version. */\n readonly version?: string;\n\n /** Program description. */\n readonly description?: string;\n\n /** Program executable name. */\n readonly bin?: string;\n\n /** Program commands */\n readonly commands: Array<\n Command<string, ParametersConfig | undefined, OptionsConfig | undefined, boolean, boolean>\n > = [];\n\n protected isRendering = false;\n\n readonly streams: ProgramStreams = {\n stderr: process.stderr,\n stdin: process.stdin,\n stdout: process.stdout,\n };\n\n constructor({name, version, description, bin}: ProgramOptions) {\n if (name) {\n this.name = name;\n }\n\n if (version) {\n this.version = version;\n }\n\n if (description) {\n this.description = description;\n }\n\n if (bin) {\n this.bin = bin;\n }\n }\n\n /**\n * Adds command to the program.\n *\n * @param command Command to add.\n * @returns Program instance.\n */\n addCommand(command: Command<any, any, any, any, any>): this {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-argument -- it doesn't matter here; `any` is used to make TypeScript happy in this method, but isn't propagated further.\n this.commands.push(command);\n\n return this;\n }\n\n /**\n * Renders a React element using Ink and outputs to the configured streams.\n */\n async renderElement(element: React.ReactElement): Promise<void> {\n if (this.isRendering) {\n throw new ProgramError('NO_NESTED_RENDER');\n } else {\n this.isRendering = true;\n }\n\n let {render} = await import('ink');\n let {createElement} = await import('react');\n let {stdin, stdout, stderr} = this.streams;\n\n try {\n render(createElement(Wrapper, {program: this}, element), {\n exitOnCtrlC: true,\n patchConsole: true,\n stderr,\n stdin,\n stdout,\n });\n } catch (error: unknown) {\n if (error instanceof Error) {\n await this.renderElement(createElement(Failure, {error}));\n }\n } finally {\n this.isRendering = false;\n }\n }\n\n /**\n * Runs the program.\n *\n * @param argv Unparsed command line arguments.\n */\n async run(argv: Argv): Promise<void> {\n let hasCommandRun = false;\n\n for (let command of this.commands) {\n let parsedArgs = command.parseArguments(argv);\n\n if (parsedArgs.command) {\n hasCommandRun = true;\n\n if (parsedArgs.errors.length) {\n let {createElement} = await import('react');\n\n for (let error of parsedArgs.errors) {\n await this.renderElement(createElement(Failure, {error}));\n }\n } else {\n await command.run(parsedArgs, this);\n\n break;\n }\n }\n }\n\n if (!hasCommandRun) {\n let {createElement} = await import('react');\n\n await this.renderElement(createElement(Help, {program: this}));\n }\n }\n}\n"],"names":["ProgramError","Wrapper","Failure","Help","Program","name","version","description","bin","commands","isRendering","streams","stderr","process","stdin","stdout","constructor","addCommand","command","push","renderElement","element","render","createElement","program","exitOnCtrlC","patchConsole","error","Error","run","argv","hasCommandRun","parsedArgs","parseArguments","errors","length"],"mappings":"AAAA,+DAA+D,GAI/D,SAAQA,YAAY,QAAO,oBAAoB;AAG/C,SAAQC,OAAO,QAAO,qBAAqB;AAC3C,SAAQC,OAAO,EAAEC,IAAI,QAAO,WAAW;AAEvC;;CAEC,GACD,OAAO,MAAMC;IACX,kBAAkB,GAClB,AAASC,KAAc;IAEvB,qBAAqB,GACrB,AAASC,QAAiB;IAE1B,yBAAyB,GACzB,AAASC,YAAqB;IAE9B,6BAA6B,GAC7B,AAASC,IAAa;IAEtB,qBAAqB,GACrB,AAASC,WAEL,EAAE,CAAC;IAEGC,cAAc,MAAM;IAErBC,UAA0B;QACjCC,QAAQC,QAAQD;QAChBE,OAAOD,QAAQC;QACfC,QAAQF,QAAQE;IAClB,EAAE;IAEFC,YAAY,EAACX,KAAI,EAAEC,QAAO,EAAEC,YAAW,EAAEC,IAAG,EAAiB,CAAE;QAC7D,IAAIH,MAAM;YACR,IAAI,CAACA,OAAOA;QACd;QAEA,IAAIC,SAAS;YACX,IAAI,CAACA,UAAUA;QACjB;QAEA,IAAIC,aAAa;YACf,IAAI,CAACA,cAAcA;QACrB;QAEA,IAAIC,KAAK;YACP,IAAI,CAACA,MAAMA;QACb;IACF;IAEA;;;;;GAKC,GACDS,WAAWC,OAAyC,EAAQ;QAC1D,iLAAiL;QACjL,IAAI,CAACT,SAASU,KAAKD;QAEnB,OAAO,IAAI;IACb;IAEA;;GAEC,GACD,MAAME,cAAcC,OAA2B,EAAiB;QAC9D,IAAI,IAAI,CAACX,aAAa;YACpB,MAAM,IAAIV,aAAa;QACzB,OAAO;YACL,IAAI,CAACU,cAAc;QACrB;QAEA,IAAI,EAACY,OAAM,EAAC,GAAG,MAAM,MAAM,CAAC;QAC5B,IAAI,EAACC,cAAa,EAAC,GAAG,MAAM,MAAM,CAAC;QACnC,IAAI,EAACT,MAAK,EAAEC,OAAM,EAAEH,OAAM,EAAC,GAAG,IAAI,CAACD;QAEnC,IAAI;YACFW,OAAOC,cAActB,SAAS;gBAACuB,SAAS,IAAI;YAAA,GAAGH,UAAU;gBACvDI,aAAa;gBACbC,cAAc;gBACdd;gBACAE;gBACAC;YACF;QACF,EAAE,OAAOY,OAAgB;YACvB,IAAIA,iBAAiBC,OAAO;gBAC1B,MAAM,IAAI,CAACR,cAAcG,cAAcrB,SAAS;oBAACyB;gBAAK;YACxD;QACF,SAAU;YACR,IAAI,CAACjB,cAAc;QACrB;IACF;IAEA;;;;GAIC,GACD,MAAMmB,IAAIC,IAAU,EAAiB;QACnC,IAAIC,gBAAgB;QAEpB,KAAK,IAAIb,WAAW,IAAI,CAACT,SAAU;YACjC,IAAIuB,aAAad,QAAQe,eAAeH;YAExC,IAAIE,WAAWd,SAAS;gBACtBa,gBAAgB;gBAEhB,IAAIC,WAAWE,OAAOC,QAAQ;oBAC5B,IAAI,EAACZ,cAAa,EAAC,GAAG,MAAM,MAAM,CAAC;oBAEnC,KAAK,IAAII,SAASK,WAAWE,OAAQ;wBACnC,MAAM,IAAI,CAACd,cAAcG,cAAcrB,SAAS;4BAACyB;wBAAK;oBACxD;gBACF,OAAO;oBACL,MAAMT,QAAQW,IAAIG,YAAY,IAAI;oBAElC;gBACF;YACF;QACF;QAEA,IAAI,CAACD,eAAe;YAClB,IAAI,EAACR,cAAa,EAAC,GAAG,MAAM,MAAM,CAAC;YAEnC,MAAM,IAAI,CAACH,cAAcG,cAAcpB,MAAM;gBAACqB,SAAS,IAAI;YAAA;QAC7D;IACF;AACF"}
1
+ {"version":3,"sources":["../../src/program/Program.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any -- needed */\nimport {type ParametersConfig, type Argv, type OptionsConfig} from '@jakubmazanec/args';\n\nimport {type Command} from './Command.js';\nimport {ProgramError} from './ProgramError.js';\nimport {type ProgramOptions} from './ProgramOptions.js';\nimport {type ProgramStreams} from './ProgramStreams.js';\nimport {Wrapper} from '../ui/internals.js';\nimport {Failure, Help} from '../ui.js';\n\n/**\n * Program manages and executes {@linkcode Program} instances attached to it based on parsing command line arguments.\n */\nexport class Program {\n /** Program name. */\n readonly name?: string;\n\n /** Program version. */\n readonly version?: string;\n\n /** Program description. */\n readonly description?: string;\n\n /** Program executable name. */\n readonly bin?: string;\n\n /** Program commands */\n readonly commands: Array<\n Command<string, ParametersConfig | undefined, OptionsConfig | undefined, boolean, boolean>\n > = [];\n\n protected isRendering = false;\n\n readonly streams: ProgramStreams = {\n stderr: process.stderr,\n stdin: process.stdin,\n stdout: process.stdout,\n };\n\n constructor({name, version, description, bin}: ProgramOptions) {\n if (name) {\n this.name = name;\n }\n\n if (version) {\n this.version = version;\n }\n\n if (description) {\n this.description = description;\n }\n\n if (bin) {\n this.bin = bin;\n }\n }\n\n /**\n * Adds command to the program.\n *\n * @param command Command to add.\n * @returns Program instance.\n */\n addCommand(command: Command<any, any, any, any, any>): this {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-argument -- it doesn't matter here; `any` is used to make TypeScript happy in this method, but isn't propagated further.\n this.commands.push(command);\n\n return this;\n }\n\n /**\n * Renders a React element using Ink and outputs to the configured streams.\n */\n async renderElement(element: React.ReactElement): Promise<void> {\n if (this.isRendering) {\n throw new ProgramError('NO_NESTED_RENDER');\n } else {\n this.isRendering = true;\n }\n\n let {render} = await import('ink');\n let {createElement} = await import('react');\n let {stdin, stdout, stderr} = this.streams;\n\n try {\n render(createElement(Wrapper, {program: this}, element), {\n exitOnCtrlC: true,\n patchConsole: true,\n stderr,\n stdin,\n stdout,\n });\n } catch (error: unknown) {\n if (error instanceof Error) {\n await this.renderElement(createElement(Failure, {error}));\n }\n } finally {\n this.isRendering = false;\n }\n }\n\n /**\n * Runs the program.\n *\n * @param argv Unparsed command line arguments.\n */\n async run(argv: Argv): Promise<void> {\n let hasCommandRun = false;\n\n for (let command of this.commands) {\n let parsedArgs = command.parseArguments(argv);\n\n if (parsedArgs.command) {\n hasCommandRun = true;\n\n if (parsedArgs.errors.length) {\n let {createElement} = await import('react');\n\n for (let error of parsedArgs.errors) {\n await this.renderElement(createElement(Failure, {error}));\n }\n } else {\n await command.run(parsedArgs, this);\n\n break;\n }\n }\n }\n\n if (!hasCommandRun) {\n let {createElement} = await import('react');\n\n await this.renderElement(createElement(Help, {program: this}));\n }\n }\n}\n"],"names":["ProgramError","Wrapper","Failure","Help","Program","name","version","description","bin","commands","isRendering","streams","stderr","process","stdin","stdout","constructor","addCommand","command","push","renderElement","element","render","createElement","program","exitOnCtrlC","patchConsole","error","Error","run","argv","hasCommandRun","parsedArgs","parseArguments","errors","length"],"mappings":"AAAA,+DAA+D,GAI/D,SAAQA,YAAY,QAAO,oBAAoB;AAG/C,SAAQC,OAAO,QAAO,qBAAqB;AAC3C,SAAQC,OAAO,EAAEC,IAAI,QAAO,WAAW;AAEvC;;CAEC,GACD,OAAO,MAAMC;IACX,kBAAkB,GAClB,AAASC,KAAc;IAEvB,qBAAqB,GACrB,AAASC,QAAiB;IAE1B,yBAAyB,GACzB,AAASC,YAAqB;IAE9B,6BAA6B,GAC7B,AAASC,IAAa;IAEtB,qBAAqB,GACrB,AAASC,WAEL,EAAE,CAAC;IAEGC,cAAc,MAAM;IAErBC,UAA0B;QACjCC,QAAQC,QAAQD,MAAM;QACtBE,OAAOD,QAAQC,KAAK;QACpBC,QAAQF,QAAQE,MAAM;IACxB,EAAE;IAEFC,YAAY,EAACX,IAAI,EAAEC,OAAO,EAAEC,WAAW,EAAEC,GAAG,EAAiB,CAAE;QAC7D,IAAIH,MAAM;YACR,IAAI,CAACA,IAAI,GAAGA;QACd;QAEA,IAAIC,SAAS;YACX,IAAI,CAACA,OAAO,GAAGA;QACjB;QAEA,IAAIC,aAAa;YACf,IAAI,CAACA,WAAW,GAAGA;QACrB;QAEA,IAAIC,KAAK;YACP,IAAI,CAACA,GAAG,GAAGA;QACb;IACF;IAEA;;;;;GAKC,GACDS,WAAWC,OAAyC,EAAQ;QAC1D,iLAAiL;QACjL,IAAI,CAACT,QAAQ,CAACU,IAAI,CAACD;QAEnB,OAAO,IAAI;IACb;IAEA;;GAEC,GACD,MAAME,cAAcC,OAA2B,EAAiB;QAC9D,IAAI,IAAI,CAACX,WAAW,EAAE;YACpB,MAAM,IAAIV,aAAa;QACzB,OAAO;YACL,IAAI,CAACU,WAAW,GAAG;QACrB;QAEA,IAAI,EAACY,MAAM,EAAC,GAAG,MAAM,MAAM,CAAC;QAC5B,IAAI,EAACC,aAAa,EAAC,GAAG,MAAM,MAAM,CAAC;QACnC,IAAI,EAACT,KAAK,EAAEC,MAAM,EAAEH,MAAM,EAAC,GAAG,IAAI,CAACD,OAAO;QAE1C,IAAI;YACFW,OAAOC,cAActB,SAAS;gBAACuB,SAAS,IAAI;YAAA,GAAGH,UAAU;gBACvDI,aAAa;gBACbC,cAAc;gBACdd;gBACAE;gBACAC;YACF;QACF,EAAE,OAAOY,OAAgB;YACvB,IAAIA,iBAAiBC,OAAO;gBAC1B,MAAM,IAAI,CAACR,aAAa,CAACG,cAAcrB,SAAS;oBAACyB;gBAAK;YACxD;QACF,SAAU;YACR,IAAI,CAACjB,WAAW,GAAG;QACrB;IACF;IAEA;;;;GAIC,GACD,MAAMmB,IAAIC,IAAU,EAAiB;QACnC,IAAIC,gBAAgB;QAEpB,KAAK,IAAIb,WAAW,IAAI,CAACT,QAAQ,CAAE;YACjC,IAAIuB,aAAad,QAAQe,cAAc,CAACH;YAExC,IAAIE,WAAWd,OAAO,EAAE;gBACtBa,gBAAgB;gBAEhB,IAAIC,WAAWE,MAAM,CAACC,MAAM,EAAE;oBAC5B,IAAI,EAACZ,aAAa,EAAC,GAAG,MAAM,MAAM,CAAC;oBAEnC,KAAK,IAAII,SAASK,WAAWE,MAAM,CAAE;wBACnC,MAAM,IAAI,CAACd,aAAa,CAACG,cAAcrB,SAAS;4BAACyB;wBAAK;oBACxD;gBACF,OAAO;oBACL,MAAMT,QAAQW,GAAG,CAACG,YAAY,IAAI;oBAElC;gBACF;YACF;QACF;QAEA,IAAI,CAACD,eAAe;YAClB,IAAI,EAACR,aAAa,EAAC,GAAG,MAAM,MAAM,CAAC;YAEnC,MAAM,IAAI,CAACH,aAAa,CAACG,cAAcpB,MAAM;gBAACqB,SAAS,IAAI;YAAA;QAC7D;IACF;AACF"}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/program/getProgramDetail.ts"],"sourcesContent":["import {type PackageJson} from '@jakubmazanec/zod-utils';\n\nimport {type ProgramDetail} from './ProgramDetail.js';\n\n/**\n * Creates detailed information about a {@lincode Program}.\n */\nexport function getProgramDetail(packageJson: PackageJson) {\n let programDetail: ProgramDetail = {};\n\n if (packageJson.name) {\n programDetail.name = packageJson.name;\n }\n\n if (packageJson.version) {\n programDetail.version = packageJson.version;\n }\n\n if (packageJson.description) {\n programDetail.description = packageJson.description;\n }\n\n if (packageJson.bin && typeof packageJson.bin !== 'string') {\n let bins = Object.entries(packageJson.bin);\n\n if (bins.length === 1) {\n let firstBin = bins[0] as [string, string];\n\n [programDetail.bin] = firstBin;\n }\n }\n\n if (typeof packageJson.bin === 'string' && packageJson.name) {\n programDetail.bin = packageJson.name;\n }\n\n return programDetail;\n}\n"],"names":["getProgramDetail","packageJson","programDetail","name","version","description","bin","bins","Object","entries","length","firstBin"],"mappings":"AAIA;;CAEC,GACD,OAAO,SAASA,iBAAiBC,WAAwB;IACvD,IAAIC,gBAA+B,CAAC;IAEpC,IAAID,YAAYE,MAAM;QACpBD,cAAcC,OAAOF,YAAYE;IACnC;IAEA,IAAIF,YAAYG,SAAS;QACvBF,cAAcE,UAAUH,YAAYG;IACtC;IAEA,IAAIH,YAAYI,aAAa;QAC3BH,cAAcG,cAAcJ,YAAYI;IAC1C;IAEA,IAAIJ,YAAYK,OAAO,OAAOL,YAAYK,QAAQ,UAAU;QAC1D,IAAIC,OAAOC,OAAOC,QAAQR,YAAYK;QAEtC,IAAIC,KAAKG,WAAW,GAAG;YACrB,IAAIC,WAAWJ,IAAI,CAAC,EAAE;YAEtB,CAACL,cAAcI,IAAI,GAAGK;QACxB;IACF;IAEA,IAAI,OAAOV,YAAYK,QAAQ,YAAYL,YAAYE,MAAM;QAC3DD,cAAcI,MAAML,YAAYE;IAClC;IAEA,OAAOD;AACT"}
1
+ {"version":3,"sources":["../../src/program/getProgramDetail.ts"],"sourcesContent":["import {type PackageJson} from '@jakubmazanec/zod-utils';\n\nimport {type ProgramDetail} from './ProgramDetail.js';\n\n/**\n * Creates detailed information about a {@lincode Program}.\n */\nexport function getProgramDetail(packageJson: PackageJson) {\n let programDetail: ProgramDetail = {};\n\n if (packageJson.name) {\n programDetail.name = packageJson.name;\n }\n\n if (packageJson.version) {\n programDetail.version = packageJson.version;\n }\n\n if (packageJson.description) {\n programDetail.description = packageJson.description;\n }\n\n if (packageJson.bin && typeof packageJson.bin !== 'string') {\n let bins = Object.entries(packageJson.bin);\n\n if (bins.length === 1) {\n let firstBin = bins[0] as [string, string];\n\n [programDetail.bin] = firstBin;\n }\n }\n\n if (typeof packageJson.bin === 'string' && packageJson.name) {\n programDetail.bin = packageJson.name;\n }\n\n return programDetail;\n}\n"],"names":["getProgramDetail","packageJson","programDetail","name","version","description","bin","bins","Object","entries","length","firstBin"],"mappings":"AAIA;;CAEC,GACD,OAAO,SAASA,iBAAiBC,WAAwB;IACvD,IAAIC,gBAA+B,CAAC;IAEpC,IAAID,YAAYE,IAAI,EAAE;QACpBD,cAAcC,IAAI,GAAGF,YAAYE,IAAI;IACvC;IAEA,IAAIF,YAAYG,OAAO,EAAE;QACvBF,cAAcE,OAAO,GAAGH,YAAYG,OAAO;IAC7C;IAEA,IAAIH,YAAYI,WAAW,EAAE;QAC3BH,cAAcG,WAAW,GAAGJ,YAAYI,WAAW;IACrD;IAEA,IAAIJ,YAAYK,GAAG,IAAI,OAAOL,YAAYK,GAAG,KAAK,UAAU;QAC1D,IAAIC,OAAOC,OAAOC,OAAO,CAACR,YAAYK,GAAG;QAEzC,IAAIC,KAAKG,MAAM,KAAK,GAAG;YACrB,IAAIC,WAAWJ,IAAI,CAAC,EAAE;YAEtB,CAACL,cAAcI,GAAG,CAAC,GAAGK;QACxB;IACF;IAEA,IAAI,OAAOV,YAAYK,GAAG,KAAK,YAAYL,YAAYE,IAAI,EAAE;QAC3DD,cAAcI,GAAG,GAAGL,YAAYE,IAAI;IACtC;IAEA,OAAOD;AACT"}
@@ -6,8 +6,8 @@ import { Header } from './Header.js';
6
6
  import * as icons from './icons.js';
7
7
  /**
8
8
  * A component that renders a failure state.
9
- */ export function Failure({ error , errorDetail , ...boxProps }) {
10
- let { label , description , stack , cause } = errorDetail ?? getErrorDetail(error);
9
+ */ export function Failure({ error, errorDetail, ...boxProps }) {
10
+ let { label, description, stack, cause } = errorDetail ?? getErrorDetail(error);
11
11
  return /*#__PURE__*/ _jsxs(Box, {
12
12
  ...boxProps,
13
13
  flexDirection: "column",
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/ui/Failure.tsx"],"sourcesContent":["import {Box, Text, type BoxProps} from 'ink';\n\nimport * as colors from './colors.js';\nimport {type ErrorDetail} from './ErrorDetail.js';\nimport {getErrorDetail} from './getErrorDetail.js';\nimport {Header} from './Header.js';\nimport * as icons from './icons.js';\n\n/**\n * {@linkcode Failure} component props.\n */\nexport type FailureProps = BoxProps & {\n /** Error that describes a failure state. Function {@linkcode getErrorDetail} is used for getting all the information from the error; you can use it to implement own retrieval logic and pass the result as `errorDetail` prop. */\n error: Error;\n\n /** Information about the failure state. Overrides information retireved from `error` prop. */\n errorDetail?: ErrorDetail;\n};\n\n/**\n * A component that renders a failure state.\n */\nexport function Failure({error, errorDetail, ...boxProps}: FailureProps) {\n let {label, description, stack, cause} = errorDetail ?? getErrorDetail(error);\n\n return (\n <Box {...boxProps} flexDirection=\"column\">\n <Header icon={icons.error}>\n <Text color={colors.highlighted}>{label}</Text>\n </Header>\n\n {description ? (\n <Box flexDirection=\"column\" marginLeft={2}>\n <Text color={colors.failure}>{description}</Text>\n </Box>\n ) : null}\n\n {stack ? (\n <Box flexDirection=\"column\" marginTop={1} marginLeft={2}>\n <Text color={colors.muted}>{stack}</Text>\n </Box>\n ) : null}\n\n {cause ? (\n <>\n <Box flexDirection=\"column\" marginTop={1} marginLeft={2}>\n <Text color={colors.muted}>{cause.description}</Text>\n </Box>\n\n {cause.stack ? (\n <Box flexDirection=\"column\" marginTop={1} marginLeft={2}>\n <Text color={colors.muted}>{cause.stack}</Text>\n </Box>\n ) : null}\n </>\n ) : null}\n </Box>\n );\n}\n"],"names":["Box","Text","colors","getErrorDetail","Header","icons","Failure","error","errorDetail","boxProps","label","description","stack","cause","flexDirection","icon","color","highlighted","marginLeft","failure","marginTop","muted"],"mappings":";AAAA,SAAQA,GAAG,EAAEC,IAAI,QAAsB,MAAM;AAE7C,YAAYC,YAAY,cAAc;AAEtC,SAAQC,cAAc,QAAO,sBAAsB;AACnD,SAAQC,MAAM,QAAO,cAAc;AACnC,YAAYC,WAAW,aAAa;AAapC;;CAEC,GACD,OAAO,SAASC,QAAQ,EAACC,MAAK,EAAEC,YAAW,EAAE,GAAGC,UAAuB;IACrE,IAAI,EAACC,MAAK,EAAEC,YAAW,EAAEC,MAAK,EAAEC,MAAK,EAAC,GAAGL,eAAeL,eAAeI;IAEvE,qBACE,MAACP;QAAK,GAAGS,QAAQ;QAAEK,eAAc;;0BAC/B,KAACV;gBAAOW,MAAMV,MAAME;0BAClB,cAAA,KAACN;oBAAKe,OAAOd,OAAOe;8BAAcP;;;YAGnCC,4BACC,KAACX;gBAAIc,eAAc;gBAASI,YAAY;0BACtC,cAAA,KAACjB;oBAAKe,OAAOd,OAAOiB;8BAAUR;;iBAE9B;YAEHC,sBACC,KAACZ;gBAAIc,eAAc;gBAASM,WAAW;gBAAGF,YAAY;0BACpD,cAAA,KAACjB;oBAAKe,OAAOd,OAAOmB;8BAAQT;;iBAE5B;YAEHC,sBACC;;kCACE,KAACb;wBAAIc,eAAc;wBAASM,WAAW;wBAAGF,YAAY;kCACpD,cAAA,KAACjB;4BAAKe,OAAOd,OAAOmB;sCAAQR,MAAMF;;;oBAGnCE,MAAMD,sBACL,KAACZ;wBAAIc,eAAc;wBAASM,WAAW;wBAAGF,YAAY;kCACpD,cAAA,KAACjB;4BAAKe,OAAOd,OAAOmB;sCAAQR,MAAMD;;yBAElC;;iBAEJ;;;AAGV"}
1
+ {"version":3,"sources":["../../src/ui/Failure.tsx"],"sourcesContent":["import {Box, Text, type BoxProps} from 'ink';\n\nimport * as colors from './colors.js';\nimport {type ErrorDetail} from './ErrorDetail.js';\nimport {getErrorDetail} from './getErrorDetail.js';\nimport {Header} from './Header.js';\nimport * as icons from './icons.js';\n\n/**\n * {@linkcode Failure} component props.\n */\nexport type FailureProps = BoxProps & {\n /** Error that describes a failure state. Function {@linkcode getErrorDetail} is used for getting all the information from the error; you can use it to implement own retrieval logic and pass the result as `errorDetail` prop. */\n error: Error;\n\n /** Information about the failure state. Overrides information retireved from `error` prop. */\n errorDetail?: ErrorDetail;\n};\n\n/**\n * A component that renders a failure state.\n */\nexport function Failure({error, errorDetail, ...boxProps}: FailureProps) {\n let {label, description, stack, cause} = errorDetail ?? getErrorDetail(error);\n\n return (\n <Box {...boxProps} flexDirection=\"column\">\n <Header icon={icons.error}>\n <Text color={colors.highlighted}>{label}</Text>\n </Header>\n\n {description ? (\n <Box flexDirection=\"column\" marginLeft={2}>\n <Text color={colors.failure}>{description}</Text>\n </Box>\n ) : null}\n\n {stack ? (\n <Box flexDirection=\"column\" marginTop={1} marginLeft={2}>\n <Text color={colors.muted}>{stack}</Text>\n </Box>\n ) : null}\n\n {cause ? (\n <>\n <Box flexDirection=\"column\" marginTop={1} marginLeft={2}>\n <Text color={colors.muted}>{cause.description}</Text>\n </Box>\n\n {cause.stack ? (\n <Box flexDirection=\"column\" marginTop={1} marginLeft={2}>\n <Text color={colors.muted}>{cause.stack}</Text>\n </Box>\n ) : null}\n </>\n ) : null}\n </Box>\n );\n}\n"],"names":["Box","Text","colors","getErrorDetail","Header","icons","Failure","error","errorDetail","boxProps","label","description","stack","cause","flexDirection","icon","color","highlighted","marginLeft","failure","marginTop","muted"],"mappings":";AAAA,SAAQA,GAAG,EAAEC,IAAI,QAAsB,MAAM;AAE7C,YAAYC,YAAY,cAAc;AAEtC,SAAQC,cAAc,QAAO,sBAAsB;AACnD,SAAQC,MAAM,QAAO,cAAc;AACnC,YAAYC,WAAW,aAAa;AAapC;;CAEC,GACD,OAAO,SAASC,QAAQ,EAACC,KAAK,EAAEC,WAAW,EAAE,GAAGC,UAAuB;IACrE,IAAI,EAACC,KAAK,EAAEC,WAAW,EAAEC,KAAK,EAAEC,KAAK,EAAC,GAAGL,eAAeL,eAAeI;IAEvE,qBACE,MAACP;QAAK,GAAGS,QAAQ;QAAEK,eAAc;;0BAC/B,KAACV;gBAAOW,MAAMV,MAAME,KAAK;0BACvB,cAAA,KAACN;oBAAKe,OAAOd,OAAOe,WAAW;8BAAGP;;;YAGnCC,4BACC,KAACX;gBAAIc,eAAc;gBAASI,YAAY;0BACtC,cAAA,KAACjB;oBAAKe,OAAOd,OAAOiB,OAAO;8BAAGR;;iBAE9B;YAEHC,sBACC,KAACZ;gBAAIc,eAAc;gBAASM,WAAW;gBAAGF,YAAY;0BACpD,cAAA,KAACjB;oBAAKe,OAAOd,OAAOmB,KAAK;8BAAGT;;iBAE5B;YAEHC,sBACC;;kCACE,KAACb;wBAAIc,eAAc;wBAASM,WAAW;wBAAGF,YAAY;kCACpD,cAAA,KAACjB;4BAAKe,OAAOd,OAAOmB,KAAK;sCAAGR,MAAMF,WAAW;;;oBAG9CE,MAAMD,KAAK,iBACV,KAACZ;wBAAIc,eAAc;wBAASM,WAAW;wBAAGF,YAAY;kCACpD,cAAA,KAACjB;4BAAKe,OAAOd,OAAOmB,KAAK;sCAAGR,MAAMD,KAAK;;yBAEvC;;iBAEJ;;;AAGV"}
package/dist/ui/Header.js CHANGED
@@ -3,7 +3,7 @@ import { Box, Text } from 'ink';
3
3
  import { Spinner } from './Spinner.js';
4
4
  /**
5
5
  * Header component.
6
- */ export function Header({ children , icon , showSpinner =false , ...boxProps }) {
6
+ */ export function Header({ children, icon, showSpinner = false, ...boxProps }) {
7
7
  return /*#__PURE__*/ _jsxs(Box, {
8
8
  ...boxProps,
9
9
  children: [
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/ui/Header.tsx"],"sourcesContent":["import {Box, type BoxProps, Text} from 'ink';\nimport {type PropsWithChildren} from 'react';\n\nimport {Spinner} from './Spinner.js';\n\n/**\n * {@linkcode Header} component props.\n */\nexport type HeaderProps = BoxProps & {\n /** Icon (recommended is 1 character) to render before the header itself. */\n icon?: string;\n\n /** Show spinner instead of the icon. */\n showSpinner?: boolean;\n};\n\n/**\n * Header component.\n */\nexport function Header({\n children,\n icon,\n showSpinner = false,\n ...boxProps\n}: PropsWithChildren<HeaderProps>) {\n return (\n <Box {...boxProps}>\n {icon || showSpinner ? (\n <Box marginRight={1}>\n {showSpinner ? <Spinner /> : null}\n {!showSpinner && icon ? <Text>{icon}</Text> : null}\n </Box>\n ) : null}\n <Box>{children}</Box>\n </Box>\n );\n}\n"],"names":["Box","Text","Spinner","Header","children","icon","showSpinner","boxProps","marginRight"],"mappings":";AAAA,SAAQA,GAAG,EAAiBC,IAAI,QAAO,MAAM;AAG7C,SAAQC,OAAO,QAAO,eAAe;AAarC;;CAEC,GACD,OAAO,SAASC,OAAO,EACrBC,SAAQ,EACRC,KAAI,EACJC,aAAc,MAAK,EACnB,GAAGC,UAC4B;IAC/B,qBACE,MAACP;QAAK,GAAGO,QAAQ;;YACdF,QAAQC,4BACP,MAACN;gBAAIQ,aAAa;;oBACfF,4BAAc,KAACJ,eAAa;oBAC5B,CAACI,eAAeD,qBAAO,KAACJ;kCAAMI;yBAAe;;iBAE9C;0BACJ,KAACL;0BAAKI;;;;AAGZ"}
1
+ {"version":3,"sources":["../../src/ui/Header.tsx"],"sourcesContent":["import {Box, type BoxProps, Text} from 'ink';\nimport {type PropsWithChildren} from 'react';\n\nimport {Spinner} from './Spinner.js';\n\n/**\n * {@linkcode Header} component props.\n */\nexport type HeaderProps = BoxProps & {\n /** Icon (recommended is 1 character) to render before the header itself. */\n icon?: string;\n\n /** Show spinner instead of the icon. */\n showSpinner?: boolean;\n};\n\n/**\n * Header component.\n */\nexport function Header({\n children,\n icon,\n showSpinner = false,\n ...boxProps\n}: PropsWithChildren<HeaderProps>) {\n return (\n <Box {...boxProps}>\n {icon || showSpinner ? (\n <Box marginRight={1}>\n {showSpinner ? <Spinner /> : null}\n {!showSpinner && icon ? <Text>{icon}</Text> : null}\n </Box>\n ) : null}\n <Box>{children}</Box>\n </Box>\n );\n}\n"],"names":["Box","Text","Spinner","Header","children","icon","showSpinner","boxProps","marginRight"],"mappings":";AAAA,SAAQA,GAAG,EAAiBC,IAAI,QAAO,MAAM;AAG7C,SAAQC,OAAO,QAAO,eAAe;AAarC;;CAEC,GACD,OAAO,SAASC,OAAO,EACrBC,QAAQ,EACRC,IAAI,EACJC,cAAc,KAAK,EACnB,GAAGC,UAC4B;IAC/B,qBACE,MAACP;QAAK,GAAGO,QAAQ;;YACdF,QAAQC,4BACP,MAACN;gBAAIQ,aAAa;;oBACfF,4BAAc,KAACJ,eAAa;oBAC5B,CAACI,eAAeD,qBAAO,KAACJ;kCAAMI;yBAAe;;iBAE9C;0BACJ,KAACL;0BAAKI;;;;AAGZ"}
package/dist/ui/Help.js CHANGED
@@ -6,7 +6,7 @@ import { Header } from './Header.js';
6
6
  import * as icons from './icons.js';
7
7
  /**
8
8
  * A component that renders help information.
9
- */ export function Help({ program , ...boxProps }) {
9
+ */ export function Help({ program, ...boxProps }) {
10
10
  return /*#__PURE__*/ _jsxs(Box, {
11
11
  ...boxProps,
12
12
  flexDirection: "column",
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/ui/Help.tsx"],"sourcesContent":["import chalk from 'chalk';\nimport {Box, Text, type BoxProps} from 'ink';\n\nimport * as colors from './colors.js';\nimport {Header} from './Header.js';\nimport * as icons from './icons.js';\nimport {type Program} from '../program.js';\n\n/**\n * {@linkcode Help} component props.\n */\nexport type HelpProps = BoxProps & {\n /** {@linkcode Program} instance. */\n program: Program;\n};\n\n/**\n * A component that renders help information.\n */\nexport function Help({program, ...boxProps}: HelpProps) {\n return (\n <Box {...boxProps} flexDirection=\"column\">\n <Text>{`${chalk[colors.notice](program.name ?? '?')} ${chalk[colors.muted](\n program.version ?? '?',\n )}`}</Text>\n <Text color={colors.body}>{program.description}</Text>\n\n {program.commands.length ? (\n <>\n <Header icon={icons.info} marginTop={1}>\n <Text color={colors.highlighted}>Usage</Text>\n </Header>\n {program.commands.map((command) => {\n let line = `${chalk[colors.muted](program.bin ?? '?')} ${command.name}`;\n\n if (command.parameters) {\n if (command.parameters.some((parameterConfig) => !!parameterConfig.required)) {\n line += ` ${chalk[colors.muted]('<parameters>')}`;\n } else {\n line += ` ${chalk[colors.muted]('[<parameters>]')}`;\n }\n }\n\n if (command.options) {\n if (\n Object.entries(command.options).some(([, optionConfig]) => !!optionConfig.required)\n ) {\n line += ` ${chalk[colors.muted]('<options>')}`;\n } else {\n line += ` ${chalk[colors.muted]('[<options>]')}`;\n }\n }\n\n if (command.description) {\n line += ` ${command.description}`;\n }\n\n return (\n <Box key={command.name} marginLeft={2} flexDirection=\"column\">\n <Text>{line}</Text>\n </Box>\n );\n })}\n </>\n ) : null}\n </Box>\n );\n}\n"],"names":["chalk","Box","Text","colors","Header","icons","Help","program","boxProps","flexDirection","notice","name","muted","version","color","body","description","commands","length","icon","info","marginTop","highlighted","map","command","line","bin","parameters","some","parameterConfig","required","options","Object","entries","optionConfig","marginLeft"],"mappings":";AAAA,OAAOA,WAAW,QAAQ;AAC1B,SAAQC,GAAG,EAAEC,IAAI,QAAsB,MAAM;AAE7C,YAAYC,YAAY,cAAc;AACtC,SAAQC,MAAM,QAAO,cAAc;AACnC,YAAYC,WAAW,aAAa;AAWpC;;CAEC,GACD,OAAO,SAASC,KAAK,EAACC,QAAO,EAAE,GAAGC,UAAoB;IACpD,qBACE,MAACP;QAAK,GAAGO,QAAQ;QAAEC,eAAc;;0BAC/B,KAACP;0BAAM,CAAC,EAAEF,KAAK,CAACG,OAAOO,OAAO,CAACH,QAAQI,QAAQ,KAAK,CAAC,EAAEX,KAAK,CAACG,OAAOS,MAAM,CACxEL,QAAQM,WAAW,KACnB,CAAC;;0BACH,KAACX;gBAAKY,OAAOX,OAAOY;0BAAOR,QAAQS;;YAElCT,QAAQU,SAASC,uBAChB;;kCACE,KAACd;wBAAOe,MAAMd,MAAMe;wBAAMC,WAAW;kCACnC,cAAA,KAACnB;4BAAKY,OAAOX,OAAOmB;sCAAa;;;oBAElCf,QAAQU,SAASM,IAAI,CAACC;wBACrB,IAAIC,OAAO,CAAC,EAAEzB,KAAK,CAACG,OAAOS,MAAM,CAACL,QAAQmB,OAAO,KAAK,CAAC,EAAEF,QAAQb,KAAK,CAAC;wBAEvE,IAAIa,QAAQG,YAAY;4BACtB,IAAIH,QAAQG,WAAWC,KAAK,CAACC,kBAAoB,CAAC,CAACA,gBAAgBC,WAAW;gCAC5EL,QAAQ,CAAC,CAAC,EAAEzB,KAAK,CAACG,OAAOS,MAAM,CAAC,gBAAgB,CAAC;4BACnD,OAAO;gCACLa,QAAQ,CAAC,CAAC,EAAEzB,KAAK,CAACG,OAAOS,MAAM,CAAC,kBAAkB,CAAC;4BACrD;wBACF;wBAEA,IAAIY,QAAQO,SAAS;4BACnB,IACEC,OAAOC,QAAQT,QAAQO,SAASH,KAAK,CAAC,GAAGM,aAAa,GAAK,CAAC,CAACA,aAAaJ,WAC1E;gCACAL,QAAQ,CAAC,CAAC,EAAEzB,KAAK,CAACG,OAAOS,MAAM,CAAC,aAAa,CAAC;4BAChD,OAAO;gCACLa,QAAQ,CAAC,CAAC,EAAEzB,KAAK,CAACG,OAAOS,MAAM,CAAC,eAAe,CAAC;4BAClD;wBACF;wBAEA,IAAIY,QAAQR,aAAa;4BACvBS,QAAQ,CAAC,CAAC,EAAED,QAAQR,YAAY,CAAC;wBACnC;wBAEA,qBACE,KAACf;4BAAuBkC,YAAY;4BAAG1B,eAAc;sCACnD,cAAA,KAACP;0CAAMuB;;2BADCD,QAAQb;oBAItB;;iBAEA;;;AAGV"}
1
+ {"version":3,"sources":["../../src/ui/Help.tsx"],"sourcesContent":["import chalk from 'chalk';\nimport {Box, Text, type BoxProps} from 'ink';\n\nimport * as colors from './colors.js';\nimport {Header} from './Header.js';\nimport * as icons from './icons.js';\nimport {type Program} from '../program.js';\n\n/**\n * {@linkcode Help} component props.\n */\nexport type HelpProps = BoxProps & {\n /** {@linkcode Program} instance. */\n program: Program;\n};\n\n/**\n * A component that renders help information.\n */\nexport function Help({program, ...boxProps}: HelpProps) {\n return (\n <Box {...boxProps} flexDirection=\"column\">\n <Text>{`${chalk[colors.notice](program.name ?? '?')} ${chalk[colors.muted](\n program.version ?? '?',\n )}`}</Text>\n <Text color={colors.body}>{program.description}</Text>\n\n {program.commands.length ? (\n <>\n <Header icon={icons.info} marginTop={1}>\n <Text color={colors.highlighted}>Usage</Text>\n </Header>\n {program.commands.map((command) => {\n let line = `${chalk[colors.muted](program.bin ?? '?')} ${command.name}`;\n\n if (command.parameters) {\n if (command.parameters.some((parameterConfig) => !!parameterConfig.required)) {\n line += ` ${chalk[colors.muted]('<parameters>')}`;\n } else {\n line += ` ${chalk[colors.muted]('[<parameters>]')}`;\n }\n }\n\n if (command.options) {\n if (\n Object.entries(command.options).some(([, optionConfig]) => !!optionConfig.required)\n ) {\n line += ` ${chalk[colors.muted]('<options>')}`;\n } else {\n line += ` ${chalk[colors.muted]('[<options>]')}`;\n }\n }\n\n if (command.description) {\n line += ` ${command.description}`;\n }\n\n return (\n <Box key={command.name} marginLeft={2} flexDirection=\"column\">\n <Text>{line}</Text>\n </Box>\n );\n })}\n </>\n ) : null}\n </Box>\n );\n}\n"],"names":["chalk","Box","Text","colors","Header","icons","Help","program","boxProps","flexDirection","notice","name","muted","version","color","body","description","commands","length","icon","info","marginTop","highlighted","map","command","line","bin","parameters","some","parameterConfig","required","options","Object","entries","optionConfig","marginLeft"],"mappings":";AAAA,OAAOA,WAAW,QAAQ;AAC1B,SAAQC,GAAG,EAAEC,IAAI,QAAsB,MAAM;AAE7C,YAAYC,YAAY,cAAc;AACtC,SAAQC,MAAM,QAAO,cAAc;AACnC,YAAYC,WAAW,aAAa;AAWpC;;CAEC,GACD,OAAO,SAASC,KAAK,EAACC,OAAO,EAAE,GAAGC,UAAoB;IACpD,qBACE,MAACP;QAAK,GAAGO,QAAQ;QAAEC,eAAc;;0BAC/B,KAACP;0BAAM,CAAC,EAAEF,KAAK,CAACG,OAAOO,MAAM,CAAC,CAACH,QAAQI,IAAI,IAAI,KAAK,CAAC,EAAEX,KAAK,CAACG,OAAOS,KAAK,CAAC,CACxEL,QAAQM,OAAO,IAAI,KACnB,CAAC;;0BACH,KAACX;gBAAKY,OAAOX,OAAOY,IAAI;0BAAGR,QAAQS,WAAW;;YAE7CT,QAAQU,QAAQ,CAACC,MAAM,iBACtB;;kCACE,KAACd;wBAAOe,MAAMd,MAAMe,IAAI;wBAAEC,WAAW;kCACnC,cAAA,KAACnB;4BAAKY,OAAOX,OAAOmB,WAAW;sCAAE;;;oBAElCf,QAAQU,QAAQ,CAACM,GAAG,CAAC,CAACC;wBACrB,IAAIC,OAAO,CAAC,EAAEzB,KAAK,CAACG,OAAOS,KAAK,CAAC,CAACL,QAAQmB,GAAG,IAAI,KAAK,CAAC,EAAEF,QAAQb,IAAI,CAAC,CAAC;wBAEvE,IAAIa,QAAQG,UAAU,EAAE;4BACtB,IAAIH,QAAQG,UAAU,CAACC,IAAI,CAAC,CAACC,kBAAoB,CAAC,CAACA,gBAAgBC,QAAQ,GAAG;gCAC5EL,QAAQ,CAAC,CAAC,EAAEzB,KAAK,CAACG,OAAOS,KAAK,CAAC,CAAC,gBAAgB,CAAC;4BACnD,OAAO;gCACLa,QAAQ,CAAC,CAAC,EAAEzB,KAAK,CAACG,OAAOS,KAAK,CAAC,CAAC,kBAAkB,CAAC;4BACrD;wBACF;wBAEA,IAAIY,QAAQO,OAAO,EAAE;4BACnB,IACEC,OAAOC,OAAO,CAACT,QAAQO,OAAO,EAAEH,IAAI,CAAC,CAAC,GAAGM,aAAa,GAAK,CAAC,CAACA,aAAaJ,QAAQ,GAClF;gCACAL,QAAQ,CAAC,CAAC,EAAEzB,KAAK,CAACG,OAAOS,KAAK,CAAC,CAAC,aAAa,CAAC;4BAChD,OAAO;gCACLa,QAAQ,CAAC,CAAC,EAAEzB,KAAK,CAACG,OAAOS,KAAK,CAAC,CAAC,eAAe,CAAC;4BAClD;wBACF;wBAEA,IAAIY,QAAQR,WAAW,EAAE;4BACvBS,QAAQ,CAAC,CAAC,EAAED,QAAQR,WAAW,CAAC,CAAC;wBACnC;wBAEA,qBACE,KAACf;4BAAuBkC,YAAY;4BAAG1B,eAAc;sCACnD,cAAA,KAACP;0CAAMuB;;2BADCD,QAAQb,IAAI;oBAI1B;;iBAEA;;;AAGV"}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/ui/Spinner.tsx"],"sourcesContent":["import {Text} from 'ink';\nimport {useState, useEffect} from 'react';\n\nconst SPINNER = {\n interval: 80,\n frames: ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'],\n};\n\n/**\n * Spinner component.\n */\nexport function Spinner() {\n let [frame, setFrame] = useState(0);\n\n useEffect(() => {\n let timer = setInterval(() => {\n setFrame((previousFrame) => {\n let isLastFrame = previousFrame === SPINNER.frames.length - 1;\n\n return isLastFrame ? 0 : previousFrame + 1;\n });\n }, SPINNER.interval);\n\n return () => {\n clearInterval(timer);\n };\n }, []);\n\n return <Text>{SPINNER.frames[frame]}</Text>;\n}\n"],"names":["Text","useState","useEffect","SPINNER","interval","frames","Spinner","frame","setFrame","timer","setInterval","previousFrame","isLastFrame","length","clearInterval"],"mappings":";AAAA,SAAQA,IAAI,QAAO,MAAM;AACzB,SAAQC,QAAQ,EAAEC,SAAS,QAAO,QAAQ;AAE1C,MAAMC,UAAU;IACdC,UAAU;IACVC,QAAQ;QAAC;QAAK;QAAK;QAAK;QAAK;QAAK;QAAK;QAAK;QAAK;QAAK;KAAI;AAC5D;AAEA;;CAEC,GACD,OAAO,SAASC;IACd,IAAI,CAACC,OAAOC,SAAS,GAAGP,SAAS;IAEjCC,UAAU;QACR,IAAIO,QAAQC,YAAY;YACtBF,SAAS,CAACG;gBACR,IAAIC,cAAcD,kBAAkBR,QAAQE,OAAOQ,SAAS;gBAE5D,OAAOD,cAAc,IAAID,gBAAgB;YAC3C;QACF,GAAGR,QAAQC;QAEX,OAAO;YACLU,cAAcL;QAChB;IACF,GAAG,EAAE;IAEL,qBAAO,KAACT;kBAAMG,QAAQE,MAAM,CAACE,MAAM;;AACrC"}
1
+ {"version":3,"sources":["../../src/ui/Spinner.tsx"],"sourcesContent":["import {Text} from 'ink';\nimport {useState, useEffect} from 'react';\n\nconst SPINNER = {\n interval: 80,\n frames: ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'],\n};\n\n/**\n * Spinner component.\n */\nexport function Spinner() {\n let [frame, setFrame] = useState(0);\n\n useEffect(() => {\n let timer = setInterval(() => {\n setFrame((previousFrame) => {\n let isLastFrame = previousFrame === SPINNER.frames.length - 1;\n\n return isLastFrame ? 0 : previousFrame + 1;\n });\n }, SPINNER.interval);\n\n return () => {\n clearInterval(timer);\n };\n }, []);\n\n return <Text>{SPINNER.frames[frame]}</Text>;\n}\n"],"names":["Text","useState","useEffect","SPINNER","interval","frames","Spinner","frame","setFrame","timer","setInterval","previousFrame","isLastFrame","length","clearInterval"],"mappings":";AAAA,SAAQA,IAAI,QAAO,MAAM;AACzB,SAAQC,QAAQ,EAAEC,SAAS,QAAO,QAAQ;AAE1C,MAAMC,UAAU;IACdC,UAAU;IACVC,QAAQ;QAAC;QAAK;QAAK;QAAK;QAAK;QAAK;QAAK;QAAK;QAAK;QAAK;KAAI;AAC5D;AAEA;;CAEC,GACD,OAAO,SAASC;IACd,IAAI,CAACC,OAAOC,SAAS,GAAGP,SAAS;IAEjCC,UAAU;QACR,IAAIO,QAAQC,YAAY;YACtBF,SAAS,CAACG;gBACR,IAAIC,cAAcD,kBAAkBR,QAAQE,MAAM,CAACQ,MAAM,GAAG;gBAE5D,OAAOD,cAAc,IAAID,gBAAgB;YAC3C;QACF,GAAGR,QAAQC,QAAQ;QAEnB,OAAO;YACLU,cAAcL;QAChB;IACF,GAAG,EAAE;IAEL,qBAAO,KAACT;kBAAMG,QAAQE,MAAM,CAACE,MAAM;;AACrC"}
@@ -4,7 +4,7 @@ import { SelectInput } from './SelectInput.js';
4
4
  import { TextInput } from './TextInput.js';
5
5
  /**
6
6
  * Form row component.
7
- */ export function FormRow({ rowName , config , rows , value , focus , isComplete , onChange , onComplete , ...boxProps }) {
7
+ */ export function FormRow({ rowName, config, rows, value, focus, isComplete, onChange, onComplete, ...boxProps }) {
8
8
  // TODO: Each input component handles values and events differently; the APIs should be adjusted.
9
9
  let handleChange = useCallback((newValue)=>{
10
10
  onChange(newValue, rowName);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/ui/form/FormRow.tsx"],"sourcesContent":["import {type BoxProps} from 'ink';\nimport {useCallback} from 'react';\n\nimport {type FormConfig} from './FormConfig.js';\nimport {type FormProps} from './FormProps.js';\nimport {type FormRowConfig} from './FormRowConfig.js';\nimport {SelectInput} from './SelectInput.js';\nimport {TextInput} from './TextInput.js';\n\n/**\n * Form row component props.\n */\ntype FormRowProps<C extends FormConfig> = BoxProps & {\n /** Form row configuration. */\n config: FormRowConfig;\n\n // TODO: Should all rows props be passed to each row?\n /** Props of all form rows. */\n rows: FormProps<C>['rows'] | null;\n\n /** Row name. */\n rowName: keyof C['rows'];\n\n /** Value. */\n value: unknown;\n\n /** Should component listen to Listen to user's input? Useful in case there are multiple input components at the same time and input must be \"routed\" to a specific component. */\n focus: boolean;\n\n /** Handler function that is called when value changes. */\n onChange: (value: unknown, inputName: keyof C['rows']) => void;\n\n /** Handler function that is called when the value is accepted. */\n onComplete: (value: unknown, inputName: keyof C['rows']) => void;\n\n /** Indicates whether value has been accepted. Component in the row then doesn't accept more input. */\n isComplete: boolean;\n};\n\n/**\n * Form row component.\n */\nexport function FormRow<C extends FormConfig>({\n rowName,\n config,\n rows,\n value,\n focus,\n isComplete,\n onChange,\n onComplete,\n ...boxProps\n}: FormRowProps<C>) {\n // TODO: Each input component handles values and events differently; the APIs should be adjusted.\n let handleChange = useCallback(\n (newValue: unknown) => {\n onChange(newValue, rowName);\n },\n [rowName, onChange],\n );\n\n let handleFinish = useCallback(\n (newValue: unknown) => {\n onComplete(newValue, rowName);\n },\n [rowName, onComplete],\n );\n\n let handleSelectFinish = useCallback(\n (item: {value: unknown}) => {\n onComplete(item.value, rowName);\n },\n [rowName, onComplete],\n );\n\n switch (config.type) {\n case 'text': {\n return (\n <TextInput\n key={String(rowName)}\n label={config.label ?? ''}\n validate={config.validate}\n value={value as string}\n focus={focus}\n isComplete={isComplete}\n onChange={handleChange}\n onSubmit={handleFinish}\n {...boxProps}\n />\n );\n }\n case 'select': {\n return (\n <SelectInput\n key={String(rowName)}\n label={config.label ?? ''}\n items={\n rows\n ? (\n (\n rows as {\n [key: string]: unknown;\n }\n )[rowName as string] as {choices: Array<{value: string; label: string}>}\n ).choices\n : []\n }\n focus={focus}\n isComplete={isComplete}\n onSelect={handleSelectFinish}\n {...boxProps}\n />\n );\n }\n default: {\n return null;\n }\n }\n}\n"],"names":["useCallback","SelectInput","TextInput","FormRow","rowName","config","rows","value","focus","isComplete","onChange","onComplete","boxProps","handleChange","newValue","handleFinish","handleSelectFinish","item","type","label","validate","onSubmit","String","items","choices","onSelect"],"mappings":";AACA,SAAQA,WAAW,QAAO,QAAQ;AAKlC,SAAQC,WAAW,QAAO,mBAAmB;AAC7C,SAAQC,SAAS,QAAO,iBAAiB;AAgCzC;;CAEC,GACD,OAAO,SAASC,QAA8B,EAC5CC,QAAO,EACPC,OAAM,EACNC,KAAI,EACJC,MAAK,EACLC,MAAK,EACLC,WAAU,EACVC,SAAQ,EACRC,WAAU,EACV,GAAGC,UACa;IAChB,iGAAiG;IACjG,IAAIC,eAAeb,YACjB,CAACc;QACCJ,SAASI,UAAUV;IACrB,GACA;QAACA;QAASM;KAAS;IAGrB,IAAIK,eAAef,YACjB,CAACc;QACCH,WAAWG,UAAUV;IACvB,GACA;QAACA;QAASO;KAAW;IAGvB,IAAIK,qBAAqBhB,YACvB,CAACiB;QACCN,WAAWM,KAAKV,OAAOH;IACzB,GACA;QAACA;QAASO;KAAW;IAGvB,OAAQN,OAAOa;QACb,KAAK;YAAQ;gBACX,qBACE,KAAChB;oBAECiB,OAAOd,OAAOc,SAAS;oBACvBC,UAAUf,OAAOe;oBACjBb,OAAOA;oBACPC,OAAOA;oBACPC,YAAYA;oBACZC,UAAUG;oBACVQ,UAAUN;oBACT,GAAGH,QAAQ;mBARPU,OAAOlB;YAWlB;QACA,KAAK;YAAU;gBACb,qBACE,KAACH;oBAECkB,OAAOd,OAAOc,SAAS;oBACvBI,OACEjB,OACI,AACE,AACEA,IAGD,CAACF,QAAkB,CACpBoB,UACF,EAAE;oBAERhB,OAAOA;oBACPC,YAAYA;oBACZgB,UAAUT;oBACT,GAAGJ,QAAQ;mBAhBPU,OAAOlB;YAmBlB;QACA;YAAS;gBACP,OAAO;YACT;IACF;AACF"}
1
+ {"version":3,"sources":["../../../src/ui/form/FormRow.tsx"],"sourcesContent":["import {type BoxProps} from 'ink';\nimport {useCallback} from 'react';\n\nimport {type FormConfig} from './FormConfig.js';\nimport {type FormProps} from './FormProps.js';\nimport {type FormRowConfig} from './FormRowConfig.js';\nimport {SelectInput} from './SelectInput.js';\nimport {TextInput} from './TextInput.js';\n\n/**\n * Form row component props.\n */\ntype FormRowProps<C extends FormConfig> = BoxProps & {\n /** Form row configuration. */\n config: FormRowConfig;\n\n // TODO: Should all rows props be passed to each row?\n /** Props of all form rows. */\n rows: FormProps<C>['rows'] | null;\n\n /** Row name. */\n rowName: keyof C['rows'];\n\n /** Value. */\n value: unknown;\n\n /** Should component listen to Listen to user's input? Useful in case there are multiple input components at the same time and input must be \"routed\" to a specific component. */\n focus: boolean;\n\n /** Handler function that is called when value changes. */\n onChange: (value: unknown, inputName: keyof C['rows']) => void;\n\n /** Handler function that is called when the value is accepted. */\n onComplete: (value: unknown, inputName: keyof C['rows']) => void;\n\n /** Indicates whether value has been accepted. Component in the row then doesn't accept more input. */\n isComplete: boolean;\n};\n\n/**\n * Form row component.\n */\nexport function FormRow<C extends FormConfig>({\n rowName,\n config,\n rows,\n value,\n focus,\n isComplete,\n onChange,\n onComplete,\n ...boxProps\n}: FormRowProps<C>) {\n // TODO: Each input component handles values and events differently; the APIs should be adjusted.\n let handleChange = useCallback(\n (newValue: unknown) => {\n onChange(newValue, rowName);\n },\n [rowName, onChange],\n );\n\n let handleFinish = useCallback(\n (newValue: unknown) => {\n onComplete(newValue, rowName);\n },\n [rowName, onComplete],\n );\n\n let handleSelectFinish = useCallback(\n (item: {value: unknown}) => {\n onComplete(item.value, rowName);\n },\n [rowName, onComplete],\n );\n\n switch (config.type) {\n case 'text': {\n return (\n <TextInput\n key={String(rowName)}\n label={config.label ?? ''}\n validate={config.validate}\n value={value as string}\n focus={focus}\n isComplete={isComplete}\n onChange={handleChange}\n onSubmit={handleFinish}\n {...boxProps}\n />\n );\n }\n case 'select': {\n return (\n <SelectInput\n key={String(rowName)}\n label={config.label ?? ''}\n items={\n rows\n ? (\n (\n rows as {\n [key: string]: unknown;\n }\n )[rowName as string] as {choices: Array<{value: string; label: string}>}\n ).choices\n : []\n }\n focus={focus}\n isComplete={isComplete}\n onSelect={handleSelectFinish}\n {...boxProps}\n />\n );\n }\n default: {\n return null;\n }\n }\n}\n"],"names":["useCallback","SelectInput","TextInput","FormRow","rowName","config","rows","value","focus","isComplete","onChange","onComplete","boxProps","handleChange","newValue","handleFinish","handleSelectFinish","item","type","label","validate","onSubmit","String","items","choices","onSelect"],"mappings":";AACA,SAAQA,WAAW,QAAO,QAAQ;AAKlC,SAAQC,WAAW,QAAO,mBAAmB;AAC7C,SAAQC,SAAS,QAAO,iBAAiB;AAgCzC;;CAEC,GACD,OAAO,SAASC,QAA8B,EAC5CC,OAAO,EACPC,MAAM,EACNC,IAAI,EACJC,KAAK,EACLC,KAAK,EACLC,UAAU,EACVC,QAAQ,EACRC,UAAU,EACV,GAAGC,UACa;IAChB,iGAAiG;IACjG,IAAIC,eAAeb,YACjB,CAACc;QACCJ,SAASI,UAAUV;IACrB,GACA;QAACA;QAASM;KAAS;IAGrB,IAAIK,eAAef,YACjB,CAACc;QACCH,WAAWG,UAAUV;IACvB,GACA;QAACA;QAASO;KAAW;IAGvB,IAAIK,qBAAqBhB,YACvB,CAACiB;QACCN,WAAWM,KAAKV,KAAK,EAAEH;IACzB,GACA;QAACA;QAASO;KAAW;IAGvB,OAAQN,OAAOa,IAAI;QACjB,KAAK;YAAQ;gBACX,qBACE,KAAChB;oBAECiB,OAAOd,OAAOc,KAAK,IAAI;oBACvBC,UAAUf,OAAOe,QAAQ;oBACzBb,OAAOA;oBACPC,OAAOA;oBACPC,YAAYA;oBACZC,UAAUG;oBACVQ,UAAUN;oBACT,GAAGH,QAAQ;mBARPU,OAAOlB;YAWlB;QACA,KAAK;YAAU;gBACb,qBACE,KAACH;oBAECkB,OAAOd,OAAOc,KAAK,IAAI;oBACvBI,OACEjB,OACI,AACE,AACEA,IAGD,CAACF,QAAkB,CACpBoB,OAAO,GACT,EAAE;oBAERhB,OAAOA;oBACPC,YAAYA;oBACZgB,UAAUT;oBACT,GAAGJ,QAAQ;mBAhBPU,OAAOlB;YAmBlB;QACA;YAAS;gBACP,OAAO;YACT;IACF;AACF"}
@@ -7,7 +7,7 @@ import * as icons from '../icons.js';
7
7
  import { rotate } from '../internals.js';
8
8
  /**
9
9
  * Select input component.
10
- */ export function SelectInput({ label , items =[] , focus =true , initialIndex =0 , limit: customLimit , onSelect , onHighlight , marginTop =0 , isComplete , ...boxProps }) {
10
+ */ export function SelectInput({ label, items = [], focus = true, initialIndex = 0, limit: customLimit, onSelect, onHighlight, marginTop = 0, isComplete, ...boxProps }) {
11
11
  var _items_selectedIndex, _items_selectedIndex1;
12
12
  let [rotateIndex, setRotateIndex] = useState(0);
13
13
  let [selectedIndex, setSelectedIndex] = useState(initialIndex);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/ui/form/SelectInput.tsx"],"sourcesContent":["import {Box, type BoxProps, Text, useInput, type Key} from 'ink';\nimport _ from 'lodash';\nimport {useState, useEffect, useRef, useCallback} from 'react';\n\nimport {type SelectInputItem} from './SelectInputItem.js';\nimport * as colors from '../colors.js';\nimport * as icons from '../icons.js';\nimport {rotate} from '../internals.js';\n\n/**\n * Select input component props.\n */\ntype SelectInputProps = BoxProps & {\n /** Text to display as a label. */\n label: string;\n\n /** Items to display in a list. */\n items: SelectInputItem[];\n\n /** Should component listen to Listen to user's input? Useful in case there are multiple input components at the same time and input must be \"routed\" to a specific component. */\n focus?: boolean | undefined;\n\n /** Index of initially selected item. */\n initialIndex?: number | undefined;\n\n /** Number of items to display. */\n limit?: number | undefined;\n\n /** Handler function that is called when item is selected. */\n onSelect?: ((item: SelectInputItem) => void) | undefined;\n\n /** Handler function that is called when item is highlighted. */\n onHighlight?: ((item: SelectInputItem) => void) | undefined;\n\n /** Indicates whether value has been accepted. Component then doesn't accept more input. */\n isComplete?: boolean | undefined;\n};\n\n/**\n * Select input component.\n */\nexport function SelectInput({\n label,\n items = [],\n focus = true,\n initialIndex = 0,\n limit: customLimit,\n onSelect,\n onHighlight,\n marginTop = 0,\n isComplete,\n ...boxProps\n}: SelectInputProps): JSX.Element {\n let [rotateIndex, setRotateIndex] = useState(0);\n let [selectedIndex, setSelectedIndex] = useState(initialIndex);\n let hasLimit = typeof customLimit === 'number' && items.length > customLimit;\n let limit = hasLimit ? Math.min(customLimit as number, items.length) : items.length;\n let previousItems = useRef<SelectInputItem[]>(items);\n\n useEffect(() => {\n if (\n !_.isEqual(\n previousItems.current.map((item) => item.value),\n items.map((item) => item.value),\n )\n ) {\n setRotateIndex(0);\n setSelectedIndex(0);\n }\n\n previousItems.current = items;\n }, [items]);\n\n let inputHandler = useCallback(\n (input: string, key: Key) => {\n if (input === 'k' || key.upArrow) {\n let lastIndex = (hasLimit ? limit : items.length) - 1;\n let atFirstIndex = selectedIndex === 0;\n let nextIndex = hasLimit ? selectedIndex : lastIndex;\n let nextRotateIndex = atFirstIndex ? rotateIndex + 1 : rotateIndex;\n let nextSelectedIndex = atFirstIndex ? nextIndex : selectedIndex - 1;\n\n setRotateIndex(nextRotateIndex);\n setSelectedIndex(nextSelectedIndex);\n\n let slicedItems = hasLimit ? rotate(items, nextRotateIndex).slice(0, limit) : items;\n\n if (typeof onHighlight === 'function') {\n onHighlight(slicedItems[nextSelectedIndex] as SelectInputItem);\n }\n }\n\n if (input === 'j' || key.downArrow) {\n let isAtLastIndex = selectedIndex === (hasLimit ? limit : items.length) - 1;\n let nextIndex = hasLimit ? selectedIndex : 0;\n let nextRotateIndex = isAtLastIndex ? rotateIndex - 1 : rotateIndex;\n let nextSelectedIndex = isAtLastIndex ? nextIndex : selectedIndex + 1;\n\n setRotateIndex(nextRotateIndex);\n setSelectedIndex(nextSelectedIndex);\n\n let slicedItems = hasLimit ? rotate(items, nextRotateIndex).slice(0, limit) : items;\n\n if (typeof onHighlight === 'function') {\n onHighlight(slicedItems[nextSelectedIndex] as SelectInputItem);\n }\n }\n\n if (key.return) {\n let slicedItems = hasLimit ? rotate(items, rotateIndex).slice(0, limit) : items;\n\n if (typeof onSelect === 'function') {\n onSelect(slicedItems[selectedIndex] as SelectInputItem);\n }\n }\n },\n [hasLimit, limit, rotateIndex, selectedIndex, items, onSelect, onHighlight],\n );\n\n useInput(inputHandler, {isActive: focus});\n\n let visibleItem: SelectInputItem[] = hasLimit\n ? rotate(items, rotateIndex).slice(0, limit)\n : items;\n\n return (\n <Box {...boxProps}>\n <Box marginRight={1}>\n <Text>{isComplete ? icons.success : icons.question}</Text>\n </Box>\n\n <Box flexDirection=\"column\">\n <Box marginRight={1}>\n <Text color={colors.highlighted}>{label}</Text>\n </Box>\n {isComplete ? (\n <Text color={colors.body}>\n {items[selectedIndex]?.label ?? String(items[selectedIndex]?.value)}\n </Text>\n ) : (\n <Box flexDirection=\"column\">\n {visibleItem.map((item, index) => {\n let isSelected = index === selectedIndex;\n\n return (\n <Box key={item.value}>\n <Box marginRight={1}>\n {isSelected ? (\n <Text color={colors.selected}>{icons.selectedCircle}</Text>\n ) : (\n <Text color={colors.unselected}>{icons.unselectedCircle}</Text>\n )}\n </Box>\n <Text\n color={isSelected ? colors.highlighted : colors.muted}\n >{`${item.label}`}</Text>\n </Box>\n );\n })}\n </Box>\n )}\n </Box>\n </Box>\n );\n}\n"],"names":["Box","Text","useInput","_","useState","useEffect","useRef","useCallback","colors","icons","rotate","SelectInput","label","items","focus","initialIndex","limit","customLimit","onSelect","onHighlight","marginTop","isComplete","boxProps","rotateIndex","setRotateIndex","selectedIndex","setSelectedIndex","hasLimit","length","Math","min","previousItems","isEqual","current","map","item","value","inputHandler","input","key","upArrow","lastIndex","atFirstIndex","nextIndex","nextRotateIndex","nextSelectedIndex","slicedItems","slice","downArrow","isAtLastIndex","return","isActive","visibleItem","marginRight","success","question","flexDirection","color","highlighted","body","String","index","isSelected","selected","selectedCircle","unselected","unselectedCircle","muted"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/ui/form/SelectInput.tsx"],"sourcesContent":["import {Box, type BoxProps, Text, useInput, type Key} from 'ink';\nimport _ from 'lodash';\nimport {useState, useEffect, useRef, useCallback} from 'react';\n\nimport {type SelectInputItem} from './SelectInputItem.js';\nimport * as colors from '../colors.js';\nimport * as icons from '../icons.js';\nimport {rotate} from '../internals.js';\n\n/**\n * Select input component props.\n */\ntype SelectInputProps = BoxProps & {\n /** Text to display as a label. */\n label: string;\n\n /** Items to display in a list. */\n items: SelectInputItem[];\n\n /** Should component listen to Listen to user's input? Useful in case there are multiple input components at the same time and input must be \"routed\" to a specific component. */\n focus?: boolean | undefined;\n\n /** Index of initially selected item. */\n initialIndex?: number | undefined;\n\n /** Number of items to display. */\n limit?: number | undefined;\n\n /** Handler function that is called when item is selected. */\n onSelect?: ((item: SelectInputItem) => void) | undefined;\n\n /** Handler function that is called when item is highlighted. */\n onHighlight?: ((item: SelectInputItem) => void) | undefined;\n\n /** Indicates whether value has been accepted. Component then doesn't accept more input. */\n isComplete?: boolean | undefined;\n};\n\n/**\n * Select input component.\n */\nexport function SelectInput({\n label,\n items = [],\n focus = true,\n initialIndex = 0,\n limit: customLimit,\n onSelect,\n onHighlight,\n marginTop = 0,\n isComplete,\n ...boxProps\n}: SelectInputProps): JSX.Element {\n let [rotateIndex, setRotateIndex] = useState(0);\n let [selectedIndex, setSelectedIndex] = useState(initialIndex);\n let hasLimit = typeof customLimit === 'number' && items.length > customLimit;\n let limit = hasLimit ? Math.min(customLimit as number, items.length) : items.length;\n let previousItems = useRef<SelectInputItem[]>(items);\n\n useEffect(() => {\n if (\n !_.isEqual(\n previousItems.current.map((item) => item.value),\n items.map((item) => item.value),\n )\n ) {\n setRotateIndex(0);\n setSelectedIndex(0);\n }\n\n previousItems.current = items;\n }, [items]);\n\n let inputHandler = useCallback(\n (input: string, key: Key) => {\n if (input === 'k' || key.upArrow) {\n let lastIndex = (hasLimit ? limit : items.length) - 1;\n let atFirstIndex = selectedIndex === 0;\n let nextIndex = hasLimit ? selectedIndex : lastIndex;\n let nextRotateIndex = atFirstIndex ? rotateIndex + 1 : rotateIndex;\n let nextSelectedIndex = atFirstIndex ? nextIndex : selectedIndex - 1;\n\n setRotateIndex(nextRotateIndex);\n setSelectedIndex(nextSelectedIndex);\n\n let slicedItems = hasLimit ? rotate(items, nextRotateIndex).slice(0, limit) : items;\n\n if (typeof onHighlight === 'function') {\n onHighlight(slicedItems[nextSelectedIndex] as SelectInputItem);\n }\n }\n\n if (input === 'j' || key.downArrow) {\n let isAtLastIndex = selectedIndex === (hasLimit ? limit : items.length) - 1;\n let nextIndex = hasLimit ? selectedIndex : 0;\n let nextRotateIndex = isAtLastIndex ? rotateIndex - 1 : rotateIndex;\n let nextSelectedIndex = isAtLastIndex ? nextIndex : selectedIndex + 1;\n\n setRotateIndex(nextRotateIndex);\n setSelectedIndex(nextSelectedIndex);\n\n let slicedItems = hasLimit ? rotate(items, nextRotateIndex).slice(0, limit) : items;\n\n if (typeof onHighlight === 'function') {\n onHighlight(slicedItems[nextSelectedIndex] as SelectInputItem);\n }\n }\n\n if (key.return) {\n let slicedItems = hasLimit ? rotate(items, rotateIndex).slice(0, limit) : items;\n\n if (typeof onSelect === 'function') {\n onSelect(slicedItems[selectedIndex] as SelectInputItem);\n }\n }\n },\n [hasLimit, limit, rotateIndex, selectedIndex, items, onSelect, onHighlight],\n );\n\n useInput(inputHandler, {isActive: focus});\n\n let visibleItem: SelectInputItem[] = hasLimit\n ? rotate(items, rotateIndex).slice(0, limit)\n : items;\n\n return (\n <Box {...boxProps}>\n <Box marginRight={1}>\n <Text>{isComplete ? icons.success : icons.question}</Text>\n </Box>\n\n <Box flexDirection=\"column\">\n <Box marginRight={1}>\n <Text color={colors.highlighted}>{label}</Text>\n </Box>\n {isComplete ? (\n <Text color={colors.body}>\n {items[selectedIndex]?.label ?? String(items[selectedIndex]?.value)}\n </Text>\n ) : (\n <Box flexDirection=\"column\">\n {visibleItem.map((item, index) => {\n let isSelected = index === selectedIndex;\n\n return (\n <Box key={item.value}>\n <Box marginRight={1}>\n {isSelected ? (\n <Text color={colors.selected}>{icons.selectedCircle}</Text>\n ) : (\n <Text color={colors.unselected}>{icons.unselectedCircle}</Text>\n )}\n </Box>\n <Text\n color={isSelected ? colors.highlighted : colors.muted}\n >{`${item.label}`}</Text>\n </Box>\n );\n })}\n </Box>\n )}\n </Box>\n </Box>\n );\n}\n"],"names":["Box","Text","useInput","_","useState","useEffect","useRef","useCallback","colors","icons","rotate","SelectInput","label","items","focus","initialIndex","limit","customLimit","onSelect","onHighlight","marginTop","isComplete","boxProps","rotateIndex","setRotateIndex","selectedIndex","setSelectedIndex","hasLimit","length","Math","min","previousItems","isEqual","current","map","item","value","inputHandler","input","key","upArrow","lastIndex","atFirstIndex","nextIndex","nextRotateIndex","nextSelectedIndex","slicedItems","slice","downArrow","isAtLastIndex","return","isActive","visibleItem","marginRight","success","question","flexDirection","color","highlighted","body","String","index","isSelected","selected","selectedCircle","unselected","unselectedCircle","muted"],"mappings":"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"}
@@ -7,7 +7,7 @@ import * as colors from '../colors.js';
7
7
  import * as icons from '../icons.js';
8
8
  /**
9
9
  * Text input component.
10
- */ export function TextInput({ label , validate , isComplete , value: originalValue , placeholder ='' , focus =true , mask , showCursor =true , onChange , onSubmit , ...boxProps }) {
10
+ */ export function TextInput({ label, validate, isComplete, value: originalValue, placeholder = '', focus = true, mask, showCursor = true, onChange, onSubmit, ...boxProps }) {
11
11
  let [validationError, setValidationError] = useState('');
12
12
  let [state, setState] = useState({
13
13
  cursorOffset: (originalValue || '').length,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/ui/form/TextInput.tsx"],"sourcesContent":["// TODO: resolve\n/* eslint-disable complexity -- TODO */\nimport chalk from 'chalk';\nimport {Box, type BoxProps, Text, useInput} from 'ink';\nimport {useEffect, useState} from 'react';\n\nimport * as colors from '../colors.js';\nimport * as icons from '../icons.js';\n\n/**\n * Text input component props.\n */\nexport type TextInputProps = BoxProps & {\n /** Text to display as a label. */\n label: string;\n\n /** Text to display when `value` is empty. */\n placeholder?: string | undefined;\n\n /** Value. */\n value: string;\n\n /** Should component listen to Listen to user's input? Useful in case there are multiple input components at the same time and input must be \"routed\" to a specific component. */\n focus?: boolean | undefined;\n\n /** Replace all chars and mask the value. Useful for password inputs. */\n mask?: string | undefined;\n\n /** Show cursor and allow navigation using arrow keys. */\n showCursor?: boolean | undefined;\n\n /** Validation function that is called when value changes. If this function throws an error*/\n validate?: ((value: string) => void) | undefined;\n\n /** Handler function that is called when value changes. */\n onChange: (value: string) => void;\n\n /** Handler function that is called when enter is pressed. */\n onSubmit?: ((value: string) => void) | undefined;\n\n /** Indicates whether value has been accepted. Component then doesn't accept more input. */\n isComplete?: boolean | undefined;\n};\n\n/**\n * Text input component.\n */\nexport function TextInput({\n label,\n validate,\n isComplete,\n value: originalValue,\n placeholder = '',\n focus = true,\n mask,\n showCursor = true,\n onChange,\n onSubmit,\n ...boxProps\n}: TextInputProps) {\n let [validationError, setValidationError] = useState('');\n let [state, setState] = useState({\n cursorOffset: (originalValue || '').length,\n cursorWidth: 0,\n });\n\n useEffect(() => {\n setState((previousState) => {\n if (!focus || !showCursor) {\n return previousState;\n }\n\n let newValue = originalValue || '';\n\n if (previousState.cursorOffset > newValue.length - 1) {\n return {\n cursorOffset: newValue.length,\n cursorWidth: 0,\n };\n }\n\n return previousState;\n });\n }, [originalValue, focus, showCursor]);\n\n let value = mask ? mask.repeat(originalValue.length) : originalValue;\n let renderedValue = value;\n let renderedPlaceholder = placeholder ? chalk[colors.muted](placeholder) : undefined;\n\n // fake mouse cursor; dealing with with actual cursor and ANSI escape codes is inconvinient\n if (showCursor && focus) {\n renderedPlaceholder =\n placeholder.length > 0\n ? chalk.inverse(placeholder[0]) + chalk[colors.muted](placeholder.slice(1))\n : chalk.inverse(' ');\n\n renderedValue = value.length > 0 ? '' : chalk.inverse(' ');\n\n let i = 0;\n\n for (let char of value) {\n if (i >= state.cursorOffset && i <= state.cursorOffset) {\n renderedValue += chalk.inverse(char);\n } else {\n renderedValue += char;\n }\n\n i += 1;\n }\n\n if (value.length > 0 && state.cursorOffset === value.length) {\n renderedValue += chalk.inverse(' ');\n }\n }\n\n useInput(\n (input, key) => {\n if (\n key.upArrow ||\n key.downArrow ||\n (key.ctrl && input === 'c') ||\n (key.shift && key.tab) ||\n key.tab\n ) {\n return;\n }\n\n if (key.return) {\n if (onSubmit) {\n if (validate) {\n try {\n validate(originalValue);\n } catch (error: unknown) {\n setValidationError((error as Error).message);\n\n return;\n }\n }\n\n if (validationError) {\n setValidationError('');\n } else {\n onSubmit(originalValue);\n }\n }\n\n return;\n }\n\n let nextCursorOffset = state.cursorOffset;\n let nextValue = originalValue;\n let nextCursorWidth = 0;\n\n if (key.leftArrow) {\n if (showCursor) {\n nextCursorOffset -= 1;\n }\n } else if (key.rightArrow) {\n if (showCursor) {\n nextCursorOffset += 1;\n }\n } else if (key.backspace || key.delete) {\n if (state.cursorOffset > 0) {\n nextValue =\n originalValue.slice(0, state.cursorOffset - 1) +\n originalValue.slice(state.cursorOffset, originalValue.length);\n\n nextCursorOffset -= 1;\n }\n } else {\n nextValue =\n originalValue.slice(0, state.cursorOffset) +\n input +\n originalValue.slice(state.cursorOffset, originalValue.length);\n\n nextCursorOffset += input.length;\n\n if (input.length > 1) {\n nextCursorWidth = input.length;\n }\n }\n\n if (state.cursorOffset < 0) {\n nextCursorOffset = 0;\n }\n\n if (state.cursorOffset > originalValue.length) {\n nextCursorOffset = originalValue.length;\n }\n\n setState({\n cursorOffset: nextCursorOffset,\n cursorWidth: nextCursorWidth,\n });\n\n if (nextValue !== originalValue) {\n onChange(nextValue);\n }\n },\n {isActive: focus},\n );\n\n return (\n <Box {...boxProps}>\n <Box marginRight={1}>\n <Text>{isComplete ? icons.success : icons.question}</Text>\n </Box>\n\n <Box flexDirection=\"column\">\n <Box marginRight={1}>\n <Text color={colors.highlighted}>{label}</Text>\n </Box>\n {isComplete ? (\n <Text color={colors.body}>{value}</Text>\n ) : (\n <Text color={colors.highlighted}>\n {placeholder ? (value.length > 0 ? renderedValue : renderedPlaceholder) : renderedValue}\n </Text>\n )}\n {validationError ? (\n <Box marginTop={0}>\n <Text color={colors.warning}>{validationError}</Text>\n </Box>\n ) : null}\n </Box>\n </Box>\n );\n}\n"],"names":["chalk","Box","Text","useInput","useEffect","useState","colors","icons","TextInput","label","validate","isComplete","value","originalValue","placeholder","focus","mask","showCursor","onChange","onSubmit","boxProps","validationError","setValidationError","state","setState","cursorOffset","length","cursorWidth","previousState","newValue","repeat","renderedValue","renderedPlaceholder","muted","undefined","inverse","slice","i","char","input","key","upArrow","downArrow","ctrl","shift","tab","return","error","message","nextCursorOffset","nextValue","nextCursorWidth","leftArrow","rightArrow","backspace","delete","isActive","marginRight","success","question","flexDirection","color","highlighted","body","marginTop","warning"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/ui/form/TextInput.tsx"],"sourcesContent":["// TODO: resolve\n/* eslint-disable complexity -- TODO */\nimport chalk from 'chalk';\nimport {Box, type BoxProps, Text, useInput} from 'ink';\nimport {useEffect, useState} from 'react';\n\nimport * as colors from '../colors.js';\nimport * as icons from '../icons.js';\n\n/**\n * Text input component props.\n */\nexport type TextInputProps = BoxProps & {\n /** Text to display as a label. */\n label: string;\n\n /** Text to display when `value` is empty. */\n placeholder?: string | undefined;\n\n /** Value. */\n value: string;\n\n /** Should component listen to Listen to user's input? Useful in case there are multiple input components at the same time and input must be \"routed\" to a specific component. */\n focus?: boolean | undefined;\n\n /** Replace all chars and mask the value. Useful for password inputs. */\n mask?: string | undefined;\n\n /** Show cursor and allow navigation using arrow keys. */\n showCursor?: boolean | undefined;\n\n /** Validation function that is called when value changes. If this function throws an error*/\n validate?: ((value: string) => void) | undefined;\n\n /** Handler function that is called when value changes. */\n onChange: (value: string) => void;\n\n /** Handler function that is called when enter is pressed. */\n onSubmit?: ((value: string) => void) | undefined;\n\n /** Indicates whether value has been accepted. Component then doesn't accept more input. */\n isComplete?: boolean | undefined;\n};\n\n/**\n * Text input component.\n */\nexport function TextInput({\n label,\n validate,\n isComplete,\n value: originalValue,\n placeholder = '',\n focus = true,\n mask,\n showCursor = true,\n onChange,\n onSubmit,\n ...boxProps\n}: TextInputProps) {\n let [validationError, setValidationError] = useState('');\n let [state, setState] = useState({\n cursorOffset: (originalValue || '').length,\n cursorWidth: 0,\n });\n\n useEffect(() => {\n setState((previousState) => {\n if (!focus || !showCursor) {\n return previousState;\n }\n\n let newValue = originalValue || '';\n\n if (previousState.cursorOffset > newValue.length - 1) {\n return {\n cursorOffset: newValue.length,\n cursorWidth: 0,\n };\n }\n\n return previousState;\n });\n }, [originalValue, focus, showCursor]);\n\n let value = mask ? mask.repeat(originalValue.length) : originalValue;\n let renderedValue = value;\n let renderedPlaceholder = placeholder ? chalk[colors.muted](placeholder) : undefined;\n\n // fake mouse cursor; dealing with with actual cursor and ANSI escape codes is inconvinient\n if (showCursor && focus) {\n renderedPlaceholder =\n placeholder.length > 0\n ? chalk.inverse(placeholder[0]) + chalk[colors.muted](placeholder.slice(1))\n : chalk.inverse(' ');\n\n renderedValue = value.length > 0 ? '' : chalk.inverse(' ');\n\n let i = 0;\n\n for (let char of value) {\n if (i >= state.cursorOffset && i <= state.cursorOffset) {\n renderedValue += chalk.inverse(char);\n } else {\n renderedValue += char;\n }\n\n i += 1;\n }\n\n if (value.length > 0 && state.cursorOffset === value.length) {\n renderedValue += chalk.inverse(' ');\n }\n }\n\n useInput(\n (input, key) => {\n if (\n key.upArrow ||\n key.downArrow ||\n (key.ctrl && input === 'c') ||\n (key.shift && key.tab) ||\n key.tab\n ) {\n return;\n }\n\n if (key.return) {\n if (onSubmit) {\n if (validate) {\n try {\n validate(originalValue);\n } catch (error: unknown) {\n setValidationError((error as Error).message);\n\n return;\n }\n }\n\n if (validationError) {\n setValidationError('');\n } else {\n onSubmit(originalValue);\n }\n }\n\n return;\n }\n\n let nextCursorOffset = state.cursorOffset;\n let nextValue = originalValue;\n let nextCursorWidth = 0;\n\n if (key.leftArrow) {\n if (showCursor) {\n nextCursorOffset -= 1;\n }\n } else if (key.rightArrow) {\n if (showCursor) {\n nextCursorOffset += 1;\n }\n } else if (key.backspace || key.delete) {\n if (state.cursorOffset > 0) {\n nextValue =\n originalValue.slice(0, state.cursorOffset - 1) +\n originalValue.slice(state.cursorOffset, originalValue.length);\n\n nextCursorOffset -= 1;\n }\n } else {\n nextValue =\n originalValue.slice(0, state.cursorOffset) +\n input +\n originalValue.slice(state.cursorOffset, originalValue.length);\n\n nextCursorOffset += input.length;\n\n if (input.length > 1) {\n nextCursorWidth = input.length;\n }\n }\n\n if (state.cursorOffset < 0) {\n nextCursorOffset = 0;\n }\n\n if (state.cursorOffset > originalValue.length) {\n nextCursorOffset = originalValue.length;\n }\n\n setState({\n cursorOffset: nextCursorOffset,\n cursorWidth: nextCursorWidth,\n });\n\n if (nextValue !== originalValue) {\n onChange(nextValue);\n }\n },\n {isActive: focus},\n );\n\n return (\n <Box {...boxProps}>\n <Box marginRight={1}>\n <Text>{isComplete ? icons.success : icons.question}</Text>\n </Box>\n\n <Box flexDirection=\"column\">\n <Box marginRight={1}>\n <Text color={colors.highlighted}>{label}</Text>\n </Box>\n {isComplete ? (\n <Text color={colors.body}>{value}</Text>\n ) : (\n <Text color={colors.highlighted}>\n {placeholder ? (value.length > 0 ? renderedValue : renderedPlaceholder) : renderedValue}\n </Text>\n )}\n {validationError ? (\n <Box marginTop={0}>\n <Text color={colors.warning}>{validationError}</Text>\n </Box>\n ) : null}\n </Box>\n </Box>\n );\n}\n"],"names":["chalk","Box","Text","useInput","useEffect","useState","colors","icons","TextInput","label","validate","isComplete","value","originalValue","placeholder","focus","mask","showCursor","onChange","onSubmit","boxProps","validationError","setValidationError","state","setState","cursorOffset","length","cursorWidth","previousState","newValue","repeat","renderedValue","renderedPlaceholder","muted","undefined","inverse","slice","i","char","input","key","upArrow","downArrow","ctrl","shift","tab","return","error","message","nextCursorOffset","nextValue","nextCursorWidth","leftArrow","rightArrow","backspace","delete","isActive","marginRight","success","question","flexDirection","color","highlighted","body","marginTop","warning"],"mappings":"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"}
@@ -8,7 +8,7 @@ import { FormRow } from './FormRow.js';
8
8
  * @param formConfig Form configuration.
9
9
  * @returns Form component.
10
10
  */ export function createForm(formConfig) {
11
- let Form = ({ rows , values: results , onChange , onComplete: onFinish , ...boxProps })=>{
11
+ let Form = ({ rows, values: results, onChange, onComplete: onFinish, ...boxProps })=>{
12
12
  let handleChange = useCallback((value, rowName)=>{
13
13
  if (onChange) {
14
14
  onChange({
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/ui/form/createForm.tsx"],"sourcesContent":["import {Box, type BoxProps} from 'ink';\nimport {useCallback} from 'react';\n\nimport {type Form} from './Form.js';\nimport {type FormConfig} from './FormConfig.js';\nimport {type FormProps} from './FormProps.js';\nimport {FormRow} from './FormRow.js';\n\n/**\n * Creates form component that contains individual rows with inputs based on the provided config.\n *\n * @param formConfig Form configuration.\n * @returns Form component.\n */\nexport function createForm<C extends FormConfig>(formConfig: C): Form<C> {\n let Form = ({\n rows,\n values: results,\n onChange,\n onComplete: onFinish,\n ...boxProps\n }: FormProps<C>) => {\n let handleChange = useCallback(\n (value: unknown, rowName: keyof C['rows']) => {\n if (onChange) {\n onChange({\n ...results,\n [rowName]: {\n ...results[rowName],\n value,\n },\n });\n }\n },\n [onChange, results],\n );\n\n let handleFinish = useCallback(\n (value: unknown, rowName: keyof C['rows']) => {\n onFinish({\n ...results,\n [rowName]: {\n value,\n isComplete: true,\n },\n });\n },\n [onFinish, results],\n );\n\n let inputElements = [];\n let activeInputName: string | null = null;\n\n for (let [rowName] of Object.entries(formConfig.rows)) {\n if (!results[rowName as keyof C['rows']].isComplete) {\n activeInputName = String(rowName);\n\n break;\n }\n }\n\n for (let [rowName, input] of Object.entries(formConfig.rows)) {\n if (results[rowName as keyof C['rows']].isComplete || rowName === activeInputName) {\n inputElements.push(\n <FormRow\n key={rowName}\n marginTop={inputElements.length === 0 ? 0 : 1}\n focus={rowName === activeInputName}\n isComplete={results[rowName as keyof C['rows']].isComplete}\n config={input}\n rows={rows}\n rowName={rowName}\n value={results[rowName as keyof C['rows']].value}\n onChange={handleChange}\n onComplete={handleFinish}\n />,\n );\n }\n }\n\n return (\n <Box {...(boxProps as BoxProps)} flexDirection=\"column\">\n {inputElements}\n </Box>\n );\n };\n\n return Object.assign(Form, {config: formConfig});\n}\n"],"names":["Box","useCallback","FormRow","createForm","formConfig","Form","rows","values","results","onChange","onComplete","onFinish","boxProps","handleChange","value","rowName","handleFinish","isComplete","inputElements","activeInputName","Object","entries","String","input","push","marginTop","length","focus","config","flexDirection","assign"],"mappings":";AAAA,SAAQA,GAAG,QAAsB,MAAM;AACvC,SAAQC,WAAW,QAAO,QAAQ;AAKlC,SAAQC,OAAO,QAAO,eAAe;AAErC;;;;;CAKC,GACD,OAAO,SAASC,WAAiCC,UAAa;IAC5D,IAAIC,OAAO,CAAC,EACVC,KAAI,EACJC,QAAQC,QAAO,EACfC,SAAQ,EACRC,YAAYC,SAAQ,EACpB,GAAGC,UACU;QACb,IAAIC,eAAeZ,YACjB,CAACa,OAAgBC;YACf,IAAIN,UAAU;gBACZA,SAAS;oBACP,GAAGD,OAAO;oBACV,CAACO,QAAQ,EAAE;wBACT,GAAGP,OAAO,CAACO,QAAQ;wBACnBD;oBACF;gBACF;YACF;QACF,GACA;YAACL;YAAUD;SAAQ;QAGrB,IAAIQ,eAAef,YACjB,CAACa,OAAgBC;YACfJ,SAAS;gBACP,GAAGH,OAAO;gBACV,CAACO,QAAQ,EAAE;oBACTD;oBACAG,YAAY;gBACd;YACF;QACF,GACA;YAACN;YAAUH;SAAQ;QAGrB,IAAIU,gBAAgB,EAAE;QACtB,IAAIC,kBAAiC;QAErC,KAAK,IAAI,CAACJ,QAAQ,IAAIK,OAAOC,QAAQjB,WAAWE,MAAO;YACrD,IAAI,CAACE,OAAO,CAACO,QAA2B,CAACE,YAAY;gBACnDE,kBAAkBG,OAAOP;gBAEzB;YACF;QACF;QAEA,KAAK,IAAI,CAACA,SAASQ,MAAM,IAAIH,OAAOC,QAAQjB,WAAWE,MAAO;YAC5D,IAAIE,OAAO,CAACO,QAA2B,CAACE,cAAcF,YAAYI,iBAAiB;gBACjFD,cAAcM,mBACZ,KAACtB;oBAECuB,WAAWP,cAAcQ,WAAW,IAAI,IAAI;oBAC5CC,OAAOZ,YAAYI;oBACnBF,YAAYT,OAAO,CAACO,QAA2B,CAACE;oBAChDW,QAAQL;oBACRjB,MAAMA;oBACNS,SAASA;oBACTD,OAAON,OAAO,CAACO,QAA2B,CAACD;oBAC3CL,UAAUI;oBACVH,YAAYM;mBATPD;YAYX;QACF;QAEA,qBACE,KAACf;YAAK,GAAIY,QAAQ;YAAeiB,eAAc;sBAC5CX;;IAGP;IAEA,OAAOE,OAAOU,OAAOzB,MAAM;QAACuB,QAAQxB;IAAU;AAChD"}
1
+ {"version":3,"sources":["../../../src/ui/form/createForm.tsx"],"sourcesContent":["import {Box, type BoxProps} from 'ink';\nimport {useCallback} from 'react';\n\nimport {type Form} from './Form.js';\nimport {type FormConfig} from './FormConfig.js';\nimport {type FormProps} from './FormProps.js';\nimport {FormRow} from './FormRow.js';\n\n/**\n * Creates form component that contains individual rows with inputs based on the provided config.\n *\n * @param formConfig Form configuration.\n * @returns Form component.\n */\nexport function createForm<C extends FormConfig>(formConfig: C): Form<C> {\n let Form = ({\n rows,\n values: results,\n onChange,\n onComplete: onFinish,\n ...boxProps\n }: FormProps<C>) => {\n let handleChange = useCallback(\n (value: unknown, rowName: keyof C['rows']) => {\n if (onChange) {\n onChange({\n ...results,\n [rowName]: {\n ...results[rowName],\n value,\n },\n });\n }\n },\n [onChange, results],\n );\n\n let handleFinish = useCallback(\n (value: unknown, rowName: keyof C['rows']) => {\n onFinish({\n ...results,\n [rowName]: {\n value,\n isComplete: true,\n },\n });\n },\n [onFinish, results],\n );\n\n let inputElements = [];\n let activeInputName: string | null = null;\n\n for (let [rowName] of Object.entries(formConfig.rows)) {\n if (!results[rowName as keyof C['rows']].isComplete) {\n activeInputName = String(rowName);\n\n break;\n }\n }\n\n for (let [rowName, input] of Object.entries(formConfig.rows)) {\n if (results[rowName as keyof C['rows']].isComplete || rowName === activeInputName) {\n inputElements.push(\n <FormRow\n key={rowName}\n marginTop={inputElements.length === 0 ? 0 : 1}\n focus={rowName === activeInputName}\n isComplete={results[rowName as keyof C['rows']].isComplete}\n config={input}\n rows={rows}\n rowName={rowName}\n value={results[rowName as keyof C['rows']].value}\n onChange={handleChange}\n onComplete={handleFinish}\n />,\n );\n }\n }\n\n return (\n <Box {...(boxProps as BoxProps)} flexDirection=\"column\">\n {inputElements}\n </Box>\n );\n };\n\n return Object.assign(Form, {config: formConfig});\n}\n"],"names":["Box","useCallback","FormRow","createForm","formConfig","Form","rows","values","results","onChange","onComplete","onFinish","boxProps","handleChange","value","rowName","handleFinish","isComplete","inputElements","activeInputName","Object","entries","String","input","push","marginTop","length","focus","config","flexDirection","assign"],"mappings":";AAAA,SAAQA,GAAG,QAAsB,MAAM;AACvC,SAAQC,WAAW,QAAO,QAAQ;AAKlC,SAAQC,OAAO,QAAO,eAAe;AAErC;;;;;CAKC,GACD,OAAO,SAASC,WAAiCC,UAAa;IAC5D,IAAIC,OAAO,CAAC,EACVC,IAAI,EACJC,QAAQC,OAAO,EACfC,QAAQ,EACRC,YAAYC,QAAQ,EACpB,GAAGC,UACU;QACb,IAAIC,eAAeZ,YACjB,CAACa,OAAgBC;YACf,IAAIN,UAAU;gBACZA,SAAS;oBACP,GAAGD,OAAO;oBACV,CAACO,QAAQ,EAAE;wBACT,GAAGP,OAAO,CAACO,QAAQ;wBACnBD;oBACF;gBACF;YACF;QACF,GACA;YAACL;YAAUD;SAAQ;QAGrB,IAAIQ,eAAef,YACjB,CAACa,OAAgBC;YACfJ,SAAS;gBACP,GAAGH,OAAO;gBACV,CAACO,QAAQ,EAAE;oBACTD;oBACAG,YAAY;gBACd;YACF;QACF,GACA;YAACN;YAAUH;SAAQ;QAGrB,IAAIU,gBAAgB,EAAE;QACtB,IAAIC,kBAAiC;QAErC,KAAK,IAAI,CAACJ,QAAQ,IAAIK,OAAOC,OAAO,CAACjB,WAAWE,IAAI,EAAG;YACrD,IAAI,CAACE,OAAO,CAACO,QAA2B,CAACE,UAAU,EAAE;gBACnDE,kBAAkBG,OAAOP;gBAEzB;YACF;QACF;QAEA,KAAK,IAAI,CAACA,SAASQ,MAAM,IAAIH,OAAOC,OAAO,CAACjB,WAAWE,IAAI,EAAG;YAC5D,IAAIE,OAAO,CAACO,QAA2B,CAACE,UAAU,IAAIF,YAAYI,iBAAiB;gBACjFD,cAAcM,IAAI,eAChB,KAACtB;oBAECuB,WAAWP,cAAcQ,MAAM,KAAK,IAAI,IAAI;oBAC5CC,OAAOZ,YAAYI;oBACnBF,YAAYT,OAAO,CAACO,QAA2B,CAACE,UAAU;oBAC1DW,QAAQL;oBACRjB,MAAMA;oBACNS,SAASA;oBACTD,OAAON,OAAO,CAACO,QAA2B,CAACD,KAAK;oBAChDL,UAAUI;oBACVH,YAAYM;mBATPD;YAYX;QACF;QAEA,qBACE,KAACf;YAAK,GAAIY,QAAQ;YAAeiB,eAAc;sBAC5CX;;IAGP;IAEA,OAAOE,OAAOU,MAAM,CAACzB,MAAM;QAACuB,QAAQxB;IAAU;AAChD"}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/ui/getErrorDetail.ts"],"sourcesContent":["import {ValidationError, ParsingError} from '@jakubmazanec/args';\n\nimport {type ErrorDetail} from './ErrorDetail.js';\n\n/**\n * Creates detailed information about an error.\n */\nexport function getErrorDetail(error: unknown): ErrorDetail {\n // TODO: add all codes\n if (error instanceof ParsingError) {\n switch (error.code) {\n default: {\n return {\n label: 'Parsing error',\n description: error.message,\n };\n }\n }\n }\n\n // TODO: add all codes\n if (error instanceof ValidationError) {\n switch (error.code) {\n default: {\n return {\n label: 'Validation error',\n description: error.message,\n };\n }\n }\n }\n\n // TODO: add all built-in errors\n if (error instanceof ReferenceError) {\n let errorDetail: ErrorDetail = {\n label: 'Error',\n description: error.message,\n };\n\n if (error.stack) {\n errorDetail.stack = error.stack;\n }\n\n return errorDetail;\n }\n\n if (error instanceof Error) {\n let errorDetail: ErrorDetail = {\n label: 'Error',\n description: error.message,\n };\n\n if (error.stack) {\n errorDetail.stack = error.stack;\n }\n\n if (error.cause instanceof Error) {\n errorDetail.cause = {\n description: error.cause.message,\n };\n\n if (error.cause.stack) {\n errorDetail.cause.stack = error.cause.stack;\n }\n }\n\n return errorDetail;\n }\n\n return {\n label: 'Error',\n };\n}\n"],"names":["ValidationError","ParsingError","getErrorDetail","error","code","label","description","message","ReferenceError","errorDetail","stack","Error","cause"],"mappings":"AAAA,SAAQA,eAAe,EAAEC,YAAY,QAAO,qBAAqB;AAIjE;;CAEC,GACD,OAAO,SAASC,eAAeC,KAAc;IAC3C,sBAAsB;IACtB,IAAIA,iBAAiBF,cAAc;QACjC,OAAQE,MAAMC;YACZ;gBAAS;oBACP,OAAO;wBACLC,OAAO;wBACPC,aAAaH,MAAMI;oBACrB;gBACF;QACF;IACF;IAEA,sBAAsB;IACtB,IAAIJ,iBAAiBH,iBAAiB;QACpC,OAAQG,MAAMC;YACZ;gBAAS;oBACP,OAAO;wBACLC,OAAO;wBACPC,aAAaH,MAAMI;oBACrB;gBACF;QACF;IACF;IAEA,gCAAgC;IAChC,IAAIJ,iBAAiBK,gBAAgB;QACnC,IAAIC,cAA2B;YAC7BJ,OAAO;YACPC,aAAaH,MAAMI;QACrB;QAEA,IAAIJ,MAAMO,OAAO;YACfD,YAAYC,QAAQP,MAAMO;QAC5B;QAEA,OAAOD;IACT;IAEA,IAAIN,iBAAiBQ,OAAO;QAC1B,IAAIF,cAA2B;YAC7BJ,OAAO;YACPC,aAAaH,MAAMI;QACrB;QAEA,IAAIJ,MAAMO,OAAO;YACfD,YAAYC,QAAQP,MAAMO;QAC5B;QAEA,IAAIP,MAAMS,iBAAiBD,OAAO;YAChCF,YAAYG,QAAQ;gBAClBN,aAAaH,MAAMS,MAAML;YAC3B;YAEA,IAAIJ,MAAMS,MAAMF,OAAO;gBACrBD,YAAYG,MAAMF,QAAQP,MAAMS,MAAMF;YACxC;QACF;QAEA,OAAOD;IACT;IAEA,OAAO;QACLJ,OAAO;IACT;AACF"}
1
+ {"version":3,"sources":["../../src/ui/getErrorDetail.ts"],"sourcesContent":["import {ValidationError, ParsingError} from '@jakubmazanec/args';\n\nimport {type ErrorDetail} from './ErrorDetail.js';\n\n/**\n * Creates detailed information about an error.\n */\nexport function getErrorDetail(error: unknown): ErrorDetail {\n // TODO: add all codes\n if (error instanceof ParsingError) {\n switch (error.code) {\n default: {\n return {\n label: 'Parsing error',\n description: error.message,\n };\n }\n }\n }\n\n // TODO: add all codes\n if (error instanceof ValidationError) {\n switch (error.code) {\n default: {\n return {\n label: 'Validation error',\n description: error.message,\n };\n }\n }\n }\n\n // TODO: add all built-in errors\n if (error instanceof ReferenceError) {\n let errorDetail: ErrorDetail = {\n label: 'Error',\n description: error.message,\n };\n\n if (error.stack) {\n errorDetail.stack = error.stack;\n }\n\n return errorDetail;\n }\n\n if (error instanceof Error) {\n let errorDetail: ErrorDetail = {\n label: 'Error',\n description: error.message,\n };\n\n if (error.stack) {\n errorDetail.stack = error.stack;\n }\n\n if (error.cause instanceof Error) {\n errorDetail.cause = {\n description: error.cause.message,\n };\n\n if (error.cause.stack) {\n errorDetail.cause.stack = error.cause.stack;\n }\n }\n\n return errorDetail;\n }\n\n return {\n label: 'Error',\n };\n}\n"],"names":["ValidationError","ParsingError","getErrorDetail","error","code","label","description","message","ReferenceError","errorDetail","stack","Error","cause"],"mappings":"AAAA,SAAQA,eAAe,EAAEC,YAAY,QAAO,qBAAqB;AAIjE;;CAEC,GACD,OAAO,SAASC,eAAeC,KAAc;IAC3C,sBAAsB;IACtB,IAAIA,iBAAiBF,cAAc;QACjC,OAAQE,MAAMC,IAAI;YAChB;gBAAS;oBACP,OAAO;wBACLC,OAAO;wBACPC,aAAaH,MAAMI,OAAO;oBAC5B;gBACF;QACF;IACF;IAEA,sBAAsB;IACtB,IAAIJ,iBAAiBH,iBAAiB;QACpC,OAAQG,MAAMC,IAAI;YAChB;gBAAS;oBACP,OAAO;wBACLC,OAAO;wBACPC,aAAaH,MAAMI,OAAO;oBAC5B;gBACF;QACF;IACF;IAEA,gCAAgC;IAChC,IAAIJ,iBAAiBK,gBAAgB;QACnC,IAAIC,cAA2B;YAC7BJ,OAAO;YACPC,aAAaH,MAAMI,OAAO;QAC5B;QAEA,IAAIJ,MAAMO,KAAK,EAAE;YACfD,YAAYC,KAAK,GAAGP,MAAMO,KAAK;QACjC;QAEA,OAAOD;IACT;IAEA,IAAIN,iBAAiBQ,OAAO;QAC1B,IAAIF,cAA2B;YAC7BJ,OAAO;YACPC,aAAaH,MAAMI,OAAO;QAC5B;QAEA,IAAIJ,MAAMO,KAAK,EAAE;YACfD,YAAYC,KAAK,GAAGP,MAAMO,KAAK;QACjC;QAEA,IAAIP,MAAMS,KAAK,YAAYD,OAAO;YAChCF,YAAYG,KAAK,GAAG;gBAClBN,aAAaH,MAAMS,KAAK,CAACL,OAAO;YAClC;YAEA,IAAIJ,MAAMS,KAAK,CAACF,KAAK,EAAE;gBACrBD,YAAYG,KAAK,CAACF,KAAK,GAAGP,MAAMS,KAAK,CAACF,KAAK;YAC7C;QACF;QAEA,OAAOD;IACT;IAEA,OAAO;QACLJ,OAAO;IACT;AACF"}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/ui/icons.ts"],"sourcesContent":["import chalk from 'chalk';\n\nimport * as colors from './colors.js';\n\nexport const question = chalk[colors.notice]('?');\nexport const info = chalk[colors.info]('i');\nexport const success = chalk[colors.success]('✓');\nexport const warning = chalk[colors.warning]('▲');\nexport const error = chalk[colors.failure]('×');\nexport const unselectedSquare = chalk[colors.unselected]('◻');\nexport const selectedSquare = chalk[colors.selected]('◼');\nexport const unselectedCircle = chalk[colors.unselected]('○');\nexport const selectedCircle = chalk[colors.selected]('●');\n"],"names":["chalk","colors","question","notice","info","success","warning","error","failure","unselectedSquare","unselected","selectedSquare","selected","unselectedCircle","selectedCircle"],"mappings":"AAAA,OAAOA,WAAW,QAAQ;AAE1B,YAAYC,YAAY,cAAc;AAEtC,OAAO,MAAMC,WAAWF,KAAK,CAACC,OAAOE,OAAO,CAAC,KAAK;AAClD,OAAO,MAAMC,OAAOJ,KAAK,CAACC,OAAOG,KAAK,CAAC,KAAK;AAC5C,OAAO,MAAMC,UAAUL,KAAK,CAACC,OAAOI,QAAQ,CAAC,KAAK;AAClD,OAAO,MAAMC,UAAUN,KAAK,CAACC,OAAOK,QAAQ,CAAC,KAAK;AAClD,OAAO,MAAMC,QAAQP,KAAK,CAACC,OAAOO,QAAQ,CAAC,KAAK;AAChD,OAAO,MAAMC,mBAAmBT,KAAK,CAACC,OAAOS,WAAW,CAAC,KAAK;AAC9D,OAAO,MAAMC,iBAAiBX,KAAK,CAACC,OAAOW,SAAS,CAAC,KAAK;AAC1D,OAAO,MAAMC,mBAAmBb,KAAK,CAACC,OAAOS,WAAW,CAAC,KAAK;AAC9D,OAAO,MAAMI,iBAAiBd,KAAK,CAACC,OAAOW,SAAS,CAAC,KAAK"}
1
+ {"version":3,"sources":["../../src/ui/icons.ts"],"sourcesContent":["import chalk from 'chalk';\n\nimport * as colors from './colors.js';\n\nexport const question = chalk[colors.notice]('?');\nexport const info = chalk[colors.info]('i');\nexport const success = chalk[colors.success]('✓');\nexport const warning = chalk[colors.warning]('▲');\nexport const error = chalk[colors.failure]('×');\nexport const unselectedSquare = chalk[colors.unselected]('◻');\nexport const selectedSquare = chalk[colors.selected]('◼');\nexport const unselectedCircle = chalk[colors.unselected]('○');\nexport const selectedCircle = chalk[colors.selected]('●');\n"],"names":["chalk","colors","question","notice","info","success","warning","error","failure","unselectedSquare","unselected","selectedSquare","selected","unselectedCircle","selectedCircle"],"mappings":"AAAA,OAAOA,WAAW,QAAQ;AAE1B,YAAYC,YAAY,cAAc;AAEtC,OAAO,MAAMC,WAAWF,KAAK,CAACC,OAAOE,MAAM,CAAC,CAAC,KAAK;AAClD,OAAO,MAAMC,OAAOJ,KAAK,CAACC,OAAOG,IAAI,CAAC,CAAC,KAAK;AAC5C,OAAO,MAAMC,UAAUL,KAAK,CAACC,OAAOI,OAAO,CAAC,CAAC,KAAK;AAClD,OAAO,MAAMC,UAAUN,KAAK,CAACC,OAAOK,OAAO,CAAC,CAAC,KAAK;AAClD,OAAO,MAAMC,QAAQP,KAAK,CAACC,OAAOO,OAAO,CAAC,CAAC,KAAK;AAChD,OAAO,MAAMC,mBAAmBT,KAAK,CAACC,OAAOS,UAAU,CAAC,CAAC,KAAK;AAC9D,OAAO,MAAMC,iBAAiBX,KAAK,CAACC,OAAOW,QAAQ,CAAC,CAAC,KAAK;AAC1D,OAAO,MAAMC,mBAAmBb,KAAK,CAACC,OAAOS,UAAU,CAAC,CAAC,KAAK;AAC9D,OAAO,MAAMI,iBAAiBd,KAAK,CAACC,OAAOW,QAAQ,CAAC,CAAC,KAAK"}
@@ -1,18 +1,18 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { Box } from 'ink';
3
3
  import { useMemo } from 'react';
4
- import errorBoundary from 'react-error-boundary';
4
+ import { ErrorBoundary } from 'react-error-boundary';
5
5
  import { programContext } from './programContext.js';
6
6
  import { Failure } from '../Failure.js';
7
7
  /**
8
8
  * A component that wraps anything {@linkcode Program} tries to render with an error boundary and all neccessary providers.
9
- */ export const Wrapper = ({ program , children })=>{
9
+ */ export const Wrapper = ({ program, children })=>{
10
10
  let programContextValue = useMemo(()=>({
11
11
  program
12
12
  }), [
13
13
  program
14
14
  ]);
15
- return /*#__PURE__*/ _jsx(errorBoundary.ErrorBoundary, {
15
+ return /*#__PURE__*/ _jsx(ErrorBoundary, {
16
16
  FallbackComponent: Failure,
17
17
  children: /*#__PURE__*/ _jsx(programContext.Provider, {
18
18
  value: programContextValue,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/ui/internals/Wrapper.tsx"],"sourcesContent":["import {Box} from 'ink';\nimport {useMemo, type FC, type PropsWithChildren} from 'react';\nimport errorBoundary from 'react-error-boundary';\n\nimport {programContext} from './programContext.js';\nimport {type Program} from '../../program.js';\nimport {Failure} from '../Failure.js';\n\n/**\n * {@linkcode Wrapper} component props.\n */\nexport type WrapperProps = {\n program: Program;\n};\n\n/**\n * A component that wraps anything {@linkcode Program} tries to render with an error boundary and all neccessary providers.\n */\nexport const Wrapper: FC<PropsWithChildren<WrapperProps>> = ({program, children}) => {\n let programContextValue = useMemo(\n () => ({\n program,\n }),\n [program],\n );\n\n return (\n <errorBoundary.ErrorBoundary FallbackComponent={Failure}>\n <programContext.Provider value={programContextValue}>\n <Box>{children}</Box>\n </programContext.Provider>\n </errorBoundary.ErrorBoundary>\n );\n};\n"],"names":["Box","useMemo","errorBoundary","programContext","Failure","Wrapper","program","children","programContextValue","ErrorBoundary","FallbackComponent","Provider","value"],"mappings":";AAAA,SAAQA,GAAG,QAAO,MAAM;AACxB,SAAQC,OAAO,QAAwC,QAAQ;AAC/D,OAAOC,mBAAmB,uBAAuB;AAEjD,SAAQC,cAAc,QAAO,sBAAsB;AAEnD,SAAQC,OAAO,QAAO,gBAAgB;AAStC;;CAEC,GACD,OAAO,MAAMC,UAA+C,CAAC,EAACC,QAAO,EAAEC,SAAQ,EAAC;IAC9E,IAAIC,sBAAsBP,QACxB,IAAO,CAAA;YACLK;QACF,CAAA,GACA;QAACA;KAAQ;IAGX,qBACE,KAACJ,cAAcO;QAAcC,mBAAmBN;kBAC9C,cAAA,KAACD,eAAeQ;YAASC,OAAOJ;sBAC9B,cAAA,KAACR;0BAAKO;;;;AAId,EAAE"}
1
+ {"version":3,"sources":["../../../src/ui/internals/Wrapper.tsx"],"sourcesContent":["import {Box} from 'ink';\nimport {useMemo, type FC, type PropsWithChildren} from 'react';\nimport {ErrorBoundary} from 'react-error-boundary';\n\nimport {programContext} from './programContext.js';\nimport {type Program} from '../../program.js';\nimport {Failure} from '../Failure.js';\n\n/**\n * {@linkcode Wrapper} component props.\n */\nexport type WrapperProps = {\n program: Program;\n};\n\n/**\n * A component that wraps anything {@linkcode Program} tries to render with an error boundary and all neccessary providers.\n */\nexport const Wrapper: FC<PropsWithChildren<WrapperProps>> = ({program, children}) => {\n let programContextValue = useMemo(\n () => ({\n program,\n }),\n [program],\n );\n\n return (\n <ErrorBoundary FallbackComponent={Failure}>\n <programContext.Provider value={programContextValue}>\n <Box>{children}</Box>\n </programContext.Provider>\n </ErrorBoundary>\n );\n};\n"],"names":["Box","useMemo","ErrorBoundary","programContext","Failure","Wrapper","program","children","programContextValue","FallbackComponent","Provider","value"],"mappings":";AAAA,SAAQA,GAAG,QAAO,MAAM;AACxB,SAAQC,OAAO,QAAwC,QAAQ;AAC/D,SAAQC,aAAa,QAAO,uBAAuB;AAEnD,SAAQC,cAAc,QAAO,sBAAsB;AAEnD,SAAQC,OAAO,QAAO,gBAAgB;AAStC;;CAEC,GACD,OAAO,MAAMC,UAA+C,CAAC,EAACC,OAAO,EAAEC,QAAQ,EAAC;IAC9E,IAAIC,sBAAsBP,QACxB,IAAO,CAAA;YACLK;QACF,CAAA,GACA;QAACA;KAAQ;IAGX,qBACE,KAACJ;QAAcO,mBAAmBL;kBAChC,cAAA,KAACD,eAAeO,QAAQ;YAACC,OAAOH;sBAC9B,cAAA,KAACR;0BAAKO;;;;AAId,EAAE"}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/ui/internals/programContext.ts"],"sourcesContent":["import React from 'react';\n\nimport {type Program} from '../../program/Program.js';\n\nexport type ProgramContext = {\n program: Program;\n};\n\n/**\n * A React context that stores {@linkcode Program} instance.\n */\nexport const programContext = React.createContext<ProgramContext>({} as ProgramContext);\n"],"names":["React","programContext","createContext"],"mappings":"AAAA,OAAOA,WAAW,QAAQ;AAQ1B;;CAEC,GACD,OAAO,MAAMC,iBAAiBD,MAAME,cAA8B,CAAC,GAAqB"}
1
+ {"version":3,"sources":["../../../src/ui/internals/programContext.ts"],"sourcesContent":["import React from 'react';\n\nimport {type Program} from '../../program/Program.js';\n\nexport type ProgramContext = {\n program: Program;\n};\n\n/**\n * A React context that stores {@linkcode Program} instance.\n */\nexport const programContext = React.createContext<ProgramContext>({} as ProgramContext);\n"],"names":["React","programContext","createContext"],"mappings":"AAAA,OAAOA,WAAW,QAAQ;AAQ1B;;CAEC,GACD,OAAO,MAAMC,iBAAiBD,MAAME,aAAa,CAAiB,CAAC,GAAqB"}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/ui/internals/rotate.ts"],"sourcesContent":["/**\n * Rotate an array by `n` places.\n *\n * @param value An array to rotate.\n * @param n By how many places the items should move.\n * @returns The new item with items rotated.\n */\nexport function rotate<T>(value: T[], n: number) {\n let x = [...value];\n\n return [...x.splice(-n % x.length), ...x];\n}\n"],"names":["rotate","value","n","x","splice","length"],"mappings":"AAAA;;;;;;CAMC,GACD,OAAO,SAASA,OAAUC,KAAU,EAAEC,CAAS;IAC7C,IAAIC,IAAI;WAAIF;KAAM;IAElB,OAAO;WAAIE,EAAEC,OAAO,CAACF,IAAIC,EAAEE;WAAYF;KAAE;AAC3C"}
1
+ {"version":3,"sources":["../../../src/ui/internals/rotate.ts"],"sourcesContent":["/**\n * Rotate an array by `n` places.\n *\n * @param value An array to rotate.\n * @param n By how many places the items should move.\n * @returns The new item with items rotated.\n */\nexport function rotate<T>(value: T[], n: number) {\n let x = [...value];\n\n return [...x.splice(-n % x.length), ...x];\n}\n"],"names":["rotate","value","n","x","splice","length"],"mappings":"AAAA;;;;;;CAMC,GACD,OAAO,SAASA,OAAUC,KAAU,EAAEC,CAAS;IAC7C,IAAIC,IAAI;WAAIF;KAAM;IAElB,OAAO;WAAIE,EAAEC,MAAM,CAAC,CAACF,IAAIC,EAAEE,MAAM;WAAMF;KAAE;AAC3C"}
@@ -1,13 +1,13 @@
1
1
  import { useApp } from 'ink';
2
2
  import { useCallback, useContext } from 'react';
3
- import errorBoundary from 'react-error-boundary';
3
+ import { useErrorBoundary } from 'react-error-boundary';
4
4
  import { programContext } from './internals.js';
5
5
  /**
6
6
  * A React hook for accessing {@linkcode Program} instance and `exit` function that is used for showing an error (via an error boundary) and exiting.
7
7
  */ export function useProgram() {
8
- let { showBoundary } = errorBoundary.useErrorBoundary();
9
- let { exit: appExit } = useApp();
10
- let { program } = useContext(programContext);
8
+ let { showBoundary } = useErrorBoundary();
9
+ let { exit: appExit } = useApp();
10
+ let { program } = useContext(programContext);
11
11
  let exit = useCallback((error)=>{
12
12
  showBoundary(error);
13
13
  appExit(error);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/ui/useProgram.ts"],"sourcesContent":["import {useApp} from 'ink';\nimport {useCallback, useContext} from 'react';\nimport errorBoundary from 'react-error-boundary';\n\nimport {programContext} from './internals.js';\n\n/**\n * A React hook for accessing {@linkcode Program} instance and `exit` function that is used for showing an error (via an error boundary) and exiting.\n */\nexport function useProgram() {\n let {showBoundary} = errorBoundary.useErrorBoundary();\n let {exit: appExit} = useApp();\n let {program} = useContext(programContext);\n\n let exit = useCallback(\n (error: unknown) => {\n showBoundary(error);\n appExit(error as Error);\n },\n [appExit, showBoundary],\n );\n\n return {program, exit};\n}\n"],"names":["useApp","useCallback","useContext","errorBoundary","programContext","useProgram","showBoundary","useErrorBoundary","exit","appExit","program","error"],"mappings":"AAAA,SAAQA,MAAM,QAAO,MAAM;AAC3B,SAAQC,WAAW,EAAEC,UAAU,QAAO,QAAQ;AAC9C,OAAOC,mBAAmB,uBAAuB;AAEjD,SAAQC,cAAc,QAAO,iBAAiB;AAE9C;;CAEC,GACD,OAAO,SAASC;IACd,IAAI,EAACC,aAAY,EAAC,GAAGH,cAAcI;IACnC,IAAI,EAACC,MAAMC,QAAO,EAAC,GAAGT;IACtB,IAAI,EAACU,QAAO,EAAC,GAAGR,WAAWE;IAE3B,IAAII,OAAOP,YACT,CAACU;QACCL,aAAaK;QACbF,QAAQE;IACV,GACA;QAACF;QAASH;KAAa;IAGzB,OAAO;QAACI;QAASF;IAAI;AACvB"}
1
+ {"version":3,"sources":["../../src/ui/useProgram.ts"],"sourcesContent":["import {useApp} from 'ink';\nimport {useCallback, useContext} from 'react';\nimport {useErrorBoundary} from 'react-error-boundary';\n\nimport {programContext} from './internals.js';\n\n/**\n * A React hook for accessing {@linkcode Program} instance and `exit` function that is used for showing an error (via an error boundary) and exiting.\n */\nexport function useProgram() {\n let {showBoundary} = useErrorBoundary();\n let {exit: appExit} = useApp();\n let {program} = useContext(programContext);\n\n let exit = useCallback(\n (error: unknown) => {\n showBoundary(error);\n appExit(error as Error);\n },\n [appExit, showBoundary],\n );\n\n return {program, exit};\n}\n"],"names":["useApp","useCallback","useContext","useErrorBoundary","programContext","useProgram","showBoundary","exit","appExit","program","error"],"mappings":"AAAA,SAAQA,MAAM,QAAO,MAAM;AAC3B,SAAQC,WAAW,EAAEC,UAAU,QAAO,QAAQ;AAC9C,SAAQC,gBAAgB,QAAO,uBAAuB;AAEtD,SAAQC,cAAc,QAAO,iBAAiB;AAE9C;;CAEC,GACD,OAAO,SAASC;IACd,IAAI,EAACC,YAAY,EAAC,GAAGH;IACrB,IAAI,EAACI,MAAMC,OAAO,EAAC,GAAGR;IACtB,IAAI,EAACS,OAAO,EAAC,GAAGP,WAAWE;IAE3B,IAAIG,OAAON,YACT,CAACS;QACCJ,aAAaI;QACbF,QAAQE;IACV,GACA;QAACF;QAASF;KAAa;IAGzB,OAAO;QAACG;QAASF;IAAI;AACvB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jakubmazanec/cli",
3
- "version": "0.1.0-11dd4a3",
3
+ "version": "0.1.0-265acad",
4
4
  "description": "TypeScript-first library for building CLIs.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -27,10 +27,10 @@
27
27
  "typecheck": "tsc --project tsconfig.typecheck.json"
28
28
  },
29
29
  "dependencies": {
30
- "@jakubmazanec/args": "1.0.1-11dd4a3",
31
- "@jakubmazanec/error": "2.0.1-11dd4a3",
32
- "@jakubmazanec/ts-utils": "2.1.0-11dd4a3",
33
- "@jakubmazanec/zod-utils": "1.0.0-11dd4a3",
30
+ "@jakubmazanec/args": "1.0.1-265acad",
31
+ "@jakubmazanec/error": "2.0.1-265acad",
32
+ "@jakubmazanec/ts-utils": "2.1.0-265acad",
33
+ "@jakubmazanec/zod-utils": "1.0.0-265acad",
34
34
  "chalk": "^5.2.0",
35
35
  "lodash": "^4.17.21",
36
36
  "react-error-boundary": "^4.0.7"
@@ -1,6 +1,6 @@
1
1
  import {Box} from 'ink';
2
2
  import {useMemo, type FC, type PropsWithChildren} from 'react';
3
- import errorBoundary from 'react-error-boundary';
3
+ import {ErrorBoundary} from 'react-error-boundary';
4
4
 
5
5
  import {programContext} from './programContext.js';
6
6
  import {type Program} from '../../program.js';
@@ -25,10 +25,10 @@ export const Wrapper: FC<PropsWithChildren<WrapperProps>> = ({program, children}
25
25
  );
26
26
 
27
27
  return (
28
- <errorBoundary.ErrorBoundary FallbackComponent={Failure}>
28
+ <ErrorBoundary FallbackComponent={Failure}>
29
29
  <programContext.Provider value={programContextValue}>
30
30
  <Box>{children}</Box>
31
31
  </programContext.Provider>
32
- </errorBoundary.ErrorBoundary>
32
+ </ErrorBoundary>
33
33
  );
34
34
  };
@@ -1,6 +1,6 @@
1
1
  import {useApp} from 'ink';
2
2
  import {useCallback, useContext} from 'react';
3
- import errorBoundary from 'react-error-boundary';
3
+ import {useErrorBoundary} from 'react-error-boundary';
4
4
 
5
5
  import {programContext} from './internals.js';
6
6
 
@@ -8,7 +8,7 @@ import {programContext} from './internals.js';
8
8
  * A React hook for accessing {@linkcode Program} instance and `exit` function that is used for showing an error (via an error boundary) and exiting.
9
9
  */
10
10
  export function useProgram() {
11
- let {showBoundary} = errorBoundary.useErrorBoundary();
11
+ let {showBoundary} = useErrorBoundary();
12
12
  let {exit: appExit} = useApp();
13
13
  let {program} = useContext(programContext);
14
14