@jakubmazanec/cli 0.1.0-a500263 → 0.1.0-c2efc51

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.
Files changed (64) hide show
  1. package/README.md +3 -1
  2. package/dist/program/Command.d.ts +2 -2
  3. package/dist/program/Command.js +4 -4
  4. package/dist/program/Command.js.map +1 -1
  5. package/dist/program/CommandOptions.d.ts +1 -1
  6. package/dist/program/CommandOptions.js.map +1 -1
  7. package/dist/program/Program.d.ts +8 -3
  8. package/dist/program/Program.js +32 -12
  9. package/dist/program/Program.js.map +1 -1
  10. package/dist/program/ProgramOptions.d.ts +5 -1
  11. package/dist/program/ProgramOptions.js +1 -3
  12. package/dist/program/ProgramOptions.js.map +1 -1
  13. package/dist/program/ProgramStreams.d.ts +1 -1
  14. package/dist/program/ProgramStreams.js +1 -1
  15. package/dist/program/ProgramStreams.js.map +1 -1
  16. package/dist/program/getProgramDetail.js.map +1 -1
  17. package/dist/ui/Failure.d.ts +2 -2
  18. package/dist/ui/Failure.js +2 -2
  19. package/dist/ui/Failure.js.map +1 -1
  20. package/dist/ui/Header.d.ts +1 -1
  21. package/dist/ui/Header.js +1 -1
  22. package/dist/ui/Header.js.map +1 -1
  23. package/dist/ui/Help.d.ts +2 -2
  24. package/dist/ui/Help.js +1 -1
  25. package/dist/ui/Help.js.map +1 -1
  26. package/dist/ui/Spinner.js.map +1 -1
  27. package/dist/ui/form/FormRow.js +1 -1
  28. package/dist/ui/form/FormRow.js.map +1 -1
  29. package/dist/ui/form/SelectInput.d.ts +3 -3
  30. package/dist/ui/form/SelectInput.js +20 -29
  31. package/dist/ui/form/SelectInput.js.map +1 -1
  32. package/dist/ui/form/TextInput.d.ts +1 -1
  33. package/dist/ui/form/TextInput.js +5 -8
  34. package/dist/ui/form/TextInput.js.map +1 -1
  35. package/dist/ui/form/createForm.js +1 -1
  36. package/dist/ui/form/createForm.js.map +1 -1
  37. package/dist/ui/getErrorDetail.js +9 -0
  38. package/dist/ui/getErrorDetail.js.map +1 -1
  39. package/dist/ui/icons.js.map +1 -1
  40. package/dist/ui/internals/Wrapper.d.ts +2 -2
  41. package/dist/ui/internals/Wrapper.js +4 -4
  42. package/dist/ui/internals/Wrapper.js.map +1 -1
  43. package/dist/ui/internals/programContext.d.ts +1 -1
  44. package/dist/ui/internals/programContext.js +1 -1
  45. package/dist/ui/internals/programContext.js.map +1 -1
  46. package/dist/ui/internals/rotate.js.map +1 -1
  47. package/dist/ui/useProgram.d.ts +1 -1
  48. package/dist/ui/useProgram.js +5 -5
  49. package/dist/ui/useProgram.js.map +1 -1
  50. package/package.json +8 -7
  51. package/src/program/Command.ts +2 -3
  52. package/src/program/CommandOptions.ts +1 -1
  53. package/src/program/Program.ts +38 -5
  54. package/src/program/ProgramOptions.ts +7 -1
  55. package/src/program/ProgramStreams.ts +1 -1
  56. package/src/ui/Failure.tsx +2 -2
  57. package/src/ui/Header.tsx +1 -1
  58. package/src/ui/Help.tsx +2 -2
  59. package/src/ui/form/SelectInput.tsx +23 -28
  60. package/src/ui/form/TextInput.tsx +5 -10
  61. package/src/ui/getErrorDetail.ts +11 -0
  62. package/src/ui/internals/Wrapper.tsx +5 -5
  63. package/src/ui/internals/programContext.ts +1 -1
  64. package/src/ui/useProgram.ts +3 -3
@@ -1,38 +1,38 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { Box, Text, useInput } from 'ink';
3
3
  import _ from 'lodash';
4
- import { useState, useEffect, useRef, useCallback } from 'react';
4
+ import { useState, useEffect, useRef } from 'react';
5
5
  import * as colors from '../colors.js';
6
6
  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: userDefinedLimit, onSelect, onHighlight, isComplete, ...boxProps }) {
11
11
  var _items_selectedIndex, _items_selectedIndex1;
12
- let [rotateIndex, setRotateIndex] = useState(0);
12
+ let [rotatedIndex, setRotatedIndex] = useState(0);
13
13
  let [selectedIndex, setSelectedIndex] = useState(initialIndex);
14
- let hasLimit = typeof customLimit === 'number' && items.length > customLimit;
15
- let limit = hasLimit ? Math.min(customLimit, items.length) : items.length;
14
+ let hasLimit = typeof userDefinedLimit === 'number' && items.length > userDefinedLimit;
15
+ let limit = hasLimit ? Math.min(userDefinedLimit, items.length) : items.length;
16
16
  let previousItems = useRef(items);
17
17
  useEffect(()=>{
18
18
  if (!_.isEqual(previousItems.current.map((item)=>item.value), items.map((item)=>item.value))) {
19
- setRotateIndex(0);
19
+ setRotatedIndex(0);
20
20
  setSelectedIndex(0);
21
21
  }
22
22
  previousItems.current = items;
23
23
  }, [
24
24
  items
25
25
  ]);
26
- let inputHandler = useCallback((input, key)=>{
26
+ useInput((input, key)=>{
27
27
  if (input === 'k' || key.upArrow) {
28
28
  let lastIndex = (hasLimit ? limit : items.length) - 1;
29
- let atFirstIndex = selectedIndex === 0;
29
+ let isAtFirstIndex = selectedIndex === 0;
30
30
  let nextIndex = hasLimit ? selectedIndex : lastIndex;
31
- let nextRotateIndex = atFirstIndex ? rotateIndex + 1 : rotateIndex;
32
- let nextSelectedIndex = atFirstIndex ? nextIndex : selectedIndex - 1;
33
- setRotateIndex(nextRotateIndex);
31
+ let nextRotatedIndex = isAtFirstIndex ? rotatedIndex + 1 : rotatedIndex;
32
+ let nextSelectedIndex = isAtFirstIndex ? nextIndex : selectedIndex - 1;
33
+ setRotatedIndex(nextRotatedIndex);
34
34
  setSelectedIndex(nextSelectedIndex);
35
- let slicedItems = hasLimit ? rotate(items, nextRotateIndex).slice(0, limit) : items;
35
+ let slicedItems = hasLimit ? rotate(items, nextRotatedIndex).slice(0, limit) : items;
36
36
  if (typeof onHighlight === 'function') {
37
37
  onHighlight(slicedItems[nextSelectedIndex]);
38
38
  }
@@ -40,34 +40,25 @@ import { rotate } from '../internals.js';
40
40
  if (input === 'j' || key.downArrow) {
41
41
  let isAtLastIndex = selectedIndex === (hasLimit ? limit : items.length) - 1;
42
42
  let nextIndex = hasLimit ? selectedIndex : 0;
43
- let nextRotateIndex = isAtLastIndex ? rotateIndex - 1 : rotateIndex;
43
+ let nextRotatedIndex = isAtLastIndex ? rotatedIndex - 1 : rotatedIndex;
44
44
  let nextSelectedIndex = isAtLastIndex ? nextIndex : selectedIndex + 1;
45
- setRotateIndex(nextRotateIndex);
45
+ setRotatedIndex(nextRotatedIndex);
46
46
  setSelectedIndex(nextSelectedIndex);
47
- let slicedItems = hasLimit ? rotate(items, nextRotateIndex).slice(0, limit) : items;
47
+ let slicedItems = hasLimit ? rotate(items, nextRotatedIndex).slice(0, limit) : items;
48
48
  if (typeof onHighlight === 'function') {
49
49
  onHighlight(slicedItems[nextSelectedIndex]);
50
50
  }
51
51
  }
52
52
  if (key.return) {
53
- let slicedItems = hasLimit ? rotate(items, rotateIndex).slice(0, limit) : items;
53
+ let slicedItems = hasLimit ? rotate(items, rotatedIndex).slice(0, limit) : items;
54
54
  if (typeof onSelect === 'function') {
55
55
  onSelect(slicedItems[selectedIndex]);
56
56
  }
57
57
  }
58
- }, [
59
- hasLimit,
60
- limit,
61
- rotateIndex,
62
- selectedIndex,
63
- items,
64
- onSelect,
65
- onHighlight
66
- ]);
67
- useInput(inputHandler, {
58
+ }, {
68
59
  isActive: focus
69
60
  });
70
- let visibleItem = hasLimit ? rotate(items, rotateIndex).slice(0, limit) : items;
61
+ let visibleItems = hasLimit ? rotate(items, rotatedIndex).slice(0, limit) : items;
71
62
  return /*#__PURE__*/ _jsxs(Box, {
72
63
  ...boxProps,
73
64
  children: [
@@ -92,7 +83,7 @@ import { rotate } from '../internals.js';
92
83
  children: ((_items_selectedIndex = items[selectedIndex]) === null || _items_selectedIndex === void 0 ? void 0 : _items_selectedIndex.label) ?? String((_items_selectedIndex1 = items[selectedIndex]) === null || _items_selectedIndex1 === void 0 ? void 0 : _items_selectedIndex1.value)
93
84
  }) : /*#__PURE__*/ _jsx(Box, {
94
85
  flexDirection: "column",
95
- children: visibleItem.map((item, index)=>{
86
+ children: visibleItems.map((item, index)=>{
96
87
  let isSelected = index === selectedIndex;
97
88
  return /*#__PURE__*/ _jsxs(Box, {
98
89
  children: [
@@ -108,7 +99,7 @@ import { rotate } from '../internals.js';
108
99
  }),
109
100
  /*#__PURE__*/ _jsx(Text, {
110
101
  color: isSelected ? colors.highlighted : colors.muted,
111
- children: `${item.label}`
102
+ children: item.label
112
103
  })
113
104
  ]
114
105
  }, item.value);
@@ -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} 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 * {@linkcode SelectInput} 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 user's input? Useful in case there are multiple input components at the same time and input must be handled only by 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: userDefinedLimit,\n onSelect,\n onHighlight,\n isComplete,\n ...boxProps\n}: SelectInputProps): JSX.Element {\n let [rotatedIndex, setRotatedIndex] = useState(0);\n let [selectedIndex, setSelectedIndex] = useState(initialIndex);\n let hasLimit = typeof userDefinedLimit === 'number' && items.length > userDefinedLimit;\n let limit = hasLimit ? Math.min(userDefinedLimit 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 setRotatedIndex(0);\n setSelectedIndex(0);\n }\n\n previousItems.current = items;\n }, [items]);\n\n useInput(\n (input: string, key: Key) => {\n if (input === 'k' || key.upArrow) {\n let lastIndex = (hasLimit ? limit : items.length) - 1;\n let isAtFirstIndex = selectedIndex === 0;\n let nextIndex = hasLimit ? selectedIndex : lastIndex;\n let nextRotatedIndex = isAtFirstIndex ? rotatedIndex + 1 : rotatedIndex;\n let nextSelectedIndex = isAtFirstIndex ? nextIndex : selectedIndex - 1;\n\n setRotatedIndex(nextRotatedIndex);\n setSelectedIndex(nextSelectedIndex);\n\n let slicedItems = hasLimit ? rotate(items, nextRotatedIndex).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 nextRotatedIndex = isAtLastIndex ? rotatedIndex - 1 : rotatedIndex;\n let nextSelectedIndex = isAtLastIndex ? nextIndex : selectedIndex + 1;\n\n setRotatedIndex(nextRotatedIndex);\n setSelectedIndex(nextSelectedIndex);\n\n let slicedItems = hasLimit ? rotate(items, nextRotatedIndex).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, rotatedIndex).slice(0, limit) : items;\n\n if (typeof onSelect === 'function') {\n onSelect(slicedItems[selectedIndex] as SelectInputItem);\n }\n }\n },\n {isActive: focus},\n );\n\n let visibleItems: SelectInputItem[] = hasLimit\n ? rotate(items, rotatedIndex).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 {visibleItems.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 color={isSelected ? colors.highlighted : colors.muted}>{item.label}</Text>\n </Box>\n );\n })}\n </Box>\n )}\n </Box>\n </Box>\n );\n}\n"],"names":["Box","Text","useInput","_","useState","useEffect","useRef","colors","icons","rotate","SelectInput","label","items","focus","initialIndex","limit","userDefinedLimit","onSelect","onHighlight","isComplete","boxProps","rotatedIndex","setRotatedIndex","selectedIndex","setSelectedIndex","hasLimit","length","Math","min","previousItems","isEqual","current","map","item","value","input","key","upArrow","lastIndex","isAtFirstIndex","nextIndex","nextRotatedIndex","nextSelectedIndex","slicedItems","slice","downArrow","isAtLastIndex","return","isActive","visibleItems","marginRight","success","question","flexDirection","color","highlighted","body","String","index","isSelected","selected","selectedCircle","unselected","unselectedCircle","muted"],"mappings":"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"}
@@ -9,7 +9,7 @@ export type TextInputProps = BoxProps & {
9
9
  placeholder?: string | undefined;
10
10
  /** Value. */
11
11
  value: string;
12
- /** 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. */
12
+ /** 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 handled only by a specific component. */
13
13
  focus?: boolean | undefined;
14
14
  /** Replace all chars and mask the value. Useful for password inputs. */
15
15
  mask?: string | undefined;
@@ -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,
@@ -35,18 +35,15 @@ import * as icons from '../icons.js';
35
35
  let value = mask ? mask.repeat(originalValue.length) : originalValue;
36
36
  let renderedValue = value;
37
37
  let renderedPlaceholder = placeholder ? chalk[colors.muted](placeholder) : undefined;
38
- // fake mouse cursor; dealing with with actual cursor and ANSI escape codes is inconvinient
39
38
  if (showCursor && focus) {
40
39
  renderedPlaceholder = placeholder.length > 0 ? chalk.inverse(placeholder[0]) + chalk[colors.muted](placeholder.slice(1)) : chalk.inverse(' ');
41
40
  renderedValue = value.length > 0 ? '' : chalk.inverse(' ');
42
- let i = 0;
43
- for (let char of value){
44
- if (i >= state.cursorOffset && i <= state.cursorOffset) {
45
- renderedValue += chalk.inverse(char);
41
+ for (let [i, character] of Object.entries(value)){
42
+ if (Number(i) >= state.cursorOffset && Number(i) <= state.cursorOffset) {
43
+ renderedValue += chalk.inverse(character);
46
44
  } else {
47
- renderedValue += char;
45
+ renderedValue += character;
48
46
  }
49
- i += 1;
50
47
  }
51
48
  if (value.length > 0 && state.cursorOffset === value.length) {
52
49
  renderedValue += chalk.inverse(' ');
@@ -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 handled only by 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 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 for (let [i, character] of Object.entries(value)) {\n if (Number(i) >= state.cursorOffset && Number(i) <= state.cursorOffset) {\n renderedValue += chalk.inverse(character);\n } else {\n renderedValue += character;\n }\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","character","Object","entries","Number","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,4 +1,6 @@
1
1
  import { ValidationError, ParsingError } from '@jakubmazanec/args';
2
+ import { zodIssuesToStrings } from '@jakubmazanec/zod-utils';
3
+ import { ZodError } from 'zod';
2
4
  /**
3
5
  * Creates detailed information about an error.
4
6
  */ export function getErrorDetail(error) {
@@ -37,6 +39,13 @@ import { ValidationError, ParsingError } from '@jakubmazanec/args';
37
39
  }
38
40
  return errorDetail;
39
41
  }
42
+ if (error instanceof ZodError) {
43
+ let errorDetail = {
44
+ label: 'Error',
45
+ description: zodIssuesToStrings(error.issues).join('\n')
46
+ };
47
+ return errorDetail;
48
+ }
40
49
  if (error instanceof Error) {
41
50
  let errorDetail = {
42
51
  label: 'Error',
@@ -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';\nimport {zodIssuesToStrings} from '@jakubmazanec/zod-utils';\nimport {ZodError} from 'zod';\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 ZodError) {\n let errorDetail: ErrorDetail = {\n label: 'Error',\n description: zodIssuesToStrings(error.issues).join('\\n'),\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","zodIssuesToStrings","ZodError","getErrorDetail","error","code","label","description","message","ReferenceError","errorDetail","stack","issues","join","Error","cause"],"mappings":"AAAA,SAAQA,eAAe,EAAEC,YAAY,QAAO,qBAAqB;AACjE,SAAQC,kBAAkB,QAAO,0BAA0B;AAC3D,SAAQC,QAAQ,QAAO,MAAM;AAI7B;;CAEC,GACD,OAAO,SAASC,eAAeC,KAAc;IAC3C,sBAAsB;IACtB,IAAIA,iBAAiBJ,cAAc;QACjC,OAAQI,MAAMC,IAAI;YAChB;gBAAS;oBACP,OAAO;wBACLC,OAAO;wBACPC,aAAaH,MAAMI,OAAO;oBAC5B;gBACF;QACF;IACF;IAEA,sBAAsB;IACtB,IAAIJ,iBAAiBL,iBAAiB;QACpC,OAAQK,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,iBAAiBF,UAAU;QAC7B,IAAIQ,cAA2B;YAC7BJ,OAAO;YACPC,aAAaN,mBAAmBG,MAAMQ,MAAM,EAAEC,IAAI,CAAC;QACrD;QAEA,OAAOH;IACT;IAEA,IAAIN,iBAAiBU,OAAO;QAC1B,IAAIJ,cAA2B;YAC7BJ,OAAO;YACPC,aAAaH,MAAMI,OAAO;QAC5B;QAEA,IAAIJ,MAAMO,KAAK,EAAE;YACfD,YAAYC,KAAK,GAAGP,MAAMO,KAAK;QACjC;QAEA,IAAIP,MAAMW,KAAK,YAAYD,OAAO;YAChCJ,YAAYK,KAAK,GAAG;gBAClBR,aAAaH,MAAMW,KAAK,CAACP,OAAO;YAClC;YAEA,IAAIJ,MAAMW,KAAK,CAACJ,KAAK,EAAE;gBACrBD,YAAYK,KAAK,CAACJ,KAAK,GAAGP,MAAMW,KAAK,CAACJ,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,12 +1,12 @@
1
1
  import { type FC, type PropsWithChildren } from 'react';
2
2
  import { type Program } from '../../program.js';
3
3
  /**
4
- * {@linkcode Wrapper} component props.
4
+ * {@link Wrapper} component props.
5
5
  */
6
6
  export type WrapperProps = {
7
7
  program: Program;
8
8
  };
9
9
  /**
10
- * A component that wraps anything {@linkcode Program} tries to render with an error boundary and all neccessary providers.
10
+ * A component that wraps anything {@link Program} tries to render with an error boundary and all neccessary providers.
11
11
  */
12
12
  export declare const Wrapper: FC<PropsWithChildren<WrapperProps>>;
@@ -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
- * A component that wraps anything {@linkcode Program} tries to render with an error boundary and all neccessary providers.
9
- */ export const Wrapper = ({ program , children })=>{
8
+ * A component that wraps anything {@link Program} tries to render with an error boundary and all neccessary providers.
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 * {@link Wrapper} component props.\n */\nexport type WrapperProps = {\n program: Program;\n};\n\n/**\n * A component that wraps anything {@link 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"}
@@ -4,6 +4,6 @@ export type ProgramContext = {
4
4
  program: Program;
5
5
  };
6
6
  /**
7
- * A React context that stores {@linkcode Program} instance.
7
+ * A React context that stores {@link Program} instance.
8
8
  */
9
9
  export declare const programContext: React.Context<ProgramContext>;
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
2
  /**
3
- * A React context that stores {@linkcode Program} instance.
3
+ * A React context that stores {@link Program} instance.
4
4
  */ export const programContext = React.createContext({});
5
5
 
6
6
  //# sourceMappingURL=programContext.js.map
@@ -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 {@link 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,5 +1,5 @@
1
1
  /**
2
- * A React hook for accessing {@linkcode Program} instance and `exit` function that is used for showing an error (via an error boundary) and exiting.
2
+ * A React hook for accessing {@link Program} instance and `exit` function that is used for showing an error (via an error boundary) and exiting.
3
3
  */
4
4
  export declare function useProgram(): {
5
5
  program: import("../program.js").Program;
@@ -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
- * A React hook for accessing {@linkcode Program} instance and `exit` function that is used for showing an error (via an error boundary) and exiting.
6
+ * A React hook for accessing {@link 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 {@link 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,10 +1,10 @@
1
1
  {
2
2
  "name": "@jakubmazanec/cli",
3
- "version": "0.1.0-a500263",
3
+ "version": "0.1.0-c2efc51",
4
4
  "description": "TypeScript-first library for building CLIs.",
5
5
  "repository": {
6
6
  "type": "git",
7
- "url": "https://github.com/jakubmazanec/js-tools",
7
+ "url": "git@github.com:jakubmazanec/js-tools.git",
8
8
  "directory": "packages/cli"
9
9
  },
10
10
  "license": "LGPL-3.0-only",
@@ -27,13 +27,14 @@
27
27
  "typecheck": "tsc --project tsconfig.typecheck.json"
28
28
  },
29
29
  "dependencies": {
30
- "@jakubmazanec/args": "1.0.1-a500263",
31
- "@jakubmazanec/error": "2.0.1-a500263",
32
- "@jakubmazanec/ts-utils": "2.1.0-a500263",
33
- "@jakubmazanec/zod-utils": "1.0.0-a500263",
30
+ "@jakubmazanec/args": "1.0.1-c2efc51",
31
+ "@jakubmazanec/error": "2.0.1-c2efc51",
32
+ "@jakubmazanec/ts-utils": "2.1.0-c2efc51",
33
+ "@jakubmazanec/zod-utils": "1.0.0-c2efc51",
34
34
  "chalk": "^5.2.0",
35
35
  "lodash": "^4.17.21",
36
- "react-error-boundary": "^4.0.7"
36
+ "react-error-boundary": "^4.0.7",
37
+ "zod": "^3.14.4"
37
38
  },
38
39
  "devDependencies": {
39
40
  "@jest/globals": "^29.5.0",
@@ -12,7 +12,7 @@ import {type Program} from './Program.js';
12
12
  // import {type ProgramCommand} from './ProgramCommand.js';
13
13
 
14
14
  /**
15
- * Command encapsulates piece of a CLI's logic and is executed when {@linkcode Program} instance parses that command from the command line arguments.
15
+ * Command encapsulates piece of a CLI's logic and is executed when {@link Program} instance parses that command from the command line arguments.
16
16
  */
17
17
  export class Command<
18
18
  A extends string,
@@ -21,7 +21,6 @@ export class Command<
21
21
  D extends boolean = false,
22
22
  E extends boolean = false,
23
23
  > {
24
- /* implements ProgramCommand*/
25
24
  readonly name: A;
26
25
  readonly description?: string;
27
26
  readonly parameters: B extends ParametersConfig ? B : null;
@@ -104,7 +103,7 @@ export class Command<
104
103
  }
105
104
 
106
105
  /**
107
- * Executes command action with provided parsed arguments and {@linkcode Program} instance.
106
+ * Executes command action with provided parsed arguments and {@link Program} instance.
108
107
  */
109
108
  async run(
110
109
  parsedArgs: Arguments<{
@@ -1,7 +1,7 @@
1
1
  import {type OptionsConfig, type ParametersConfig} from '@jakubmazanec/args';
2
2
 
3
3
  /**
4
- * New command options.
4
+ * {@link Command.constructor | Command constructor} options parameter.
5
5
  */
6
6
  export type CommandOptions<
7
7
  B extends ParametersConfig,