1 | "use strict";
|
2 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
3 | if (k2 === undefined) k2 = k;
|
4 | Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
5 | }) : (function(o, m, k, k2) {
|
6 | if (k2 === undefined) k2 = k;
|
7 | o[k2] = m[k];
|
8 | }));
|
9 | var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
10 | Object.defineProperty(o, "default", { enumerable: true, value: v });
|
11 | }) : function(o, v) {
|
12 | o["default"] = v;
|
13 | });
|
14 | var __importStar = (this && this.__importStar) || function (mod) {
|
15 | if (mod && mod.__esModule) return mod;
|
16 | var result = {};
|
17 | if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
18 | __setModuleDefault(result, mod);
|
19 | return result;
|
20 | };
|
21 | var __importDefault = (this && this.__importDefault) || function (mod) {
|
22 | return (mod && mod.__esModule) ? mod : { "default": mod };
|
23 | };
|
24 | Object.defineProperty(exports, "__esModule", { value: true });
|
25 |
|
26 | const react_1 = __importStar(require("react"));
|
27 | const cli_cursor_1 = __importDefault(require("cli-cursor"));
|
28 | const AppContext_1 = __importDefault(require("./AppContext"));
|
29 | const StdinContext_1 = __importDefault(require("./StdinContext"));
|
30 | const StdoutContext_1 = __importDefault(require("./StdoutContext"));
|
31 | const StderrContext_1 = __importDefault(require("./StderrContext"));
|
32 | const FocusContext_1 = __importDefault(require("./FocusContext"));
|
33 | const ErrorOverview_1 = __importDefault(require("./ErrorOverview"));
|
34 | const TAB = '\t';
|
35 | const SHIFT_TAB = '\u001B[Z';
|
36 | const ESC = '\u001B';
|
37 |
|
38 |
|
39 |
|
40 | class App extends react_1.PureComponent {
|
41 | constructor() {
|
42 | super(...arguments);
|
43 | this.state = {
|
44 | isFocusEnabled: true,
|
45 | activeFocusId: undefined,
|
46 | focusables: [],
|
47 | error: undefined
|
48 | };
|
49 |
|
50 |
|
51 | this.rawModeEnabledCount = 0;
|
52 | this.handleSetRawMode = (isEnabled) => {
|
53 | const { stdin } = this.props;
|
54 | if (!this.isRawModeSupported()) {
|
55 | if (stdin === process.stdin) {
|
56 | throw new Error('Raw mode is not supported on the current process.stdin, which Ink uses as input stream by default.\nRead about how to prevent this error on https://github.com/vadimdemedes/ink/#israwmodesupported');
|
57 | }
|
58 | else {
|
59 | throw new Error('Raw mode is not supported on the stdin provided to Ink.\nRead about how to prevent this error on https://github.com/vadimdemedes/ink/#israwmodesupported');
|
60 | }
|
61 | }
|
62 | stdin.setEncoding('utf8');
|
63 | if (isEnabled) {
|
64 |
|
65 | if (this.rawModeEnabledCount === 0) {
|
66 | stdin.addListener('data', this.handleInput);
|
67 | stdin.resume();
|
68 | stdin.setRawMode(true);
|
69 | }
|
70 | this.rawModeEnabledCount++;
|
71 | return;
|
72 | }
|
73 |
|
74 | if (--this.rawModeEnabledCount === 0) {
|
75 | stdin.setRawMode(false);
|
76 | stdin.removeListener('data', this.handleInput);
|
77 | stdin.pause();
|
78 | }
|
79 | };
|
80 | this.handleInput = (input) => {
|
81 |
|
82 |
|
83 | if (input === '\x03' && this.props.exitOnCtrlC) {
|
84 | this.handleExit();
|
85 | }
|
86 |
|
87 | if (input === ESC && this.state.activeFocusId) {
|
88 | this.setState({
|
89 | activeFocusId: undefined
|
90 | });
|
91 | }
|
92 | if (this.state.isFocusEnabled && this.state.focusables.length > 0) {
|
93 | if (input === TAB) {
|
94 | this.focusNext();
|
95 | }
|
96 | if (input === SHIFT_TAB) {
|
97 | this.focusPrevious();
|
98 | }
|
99 | }
|
100 | };
|
101 | this.handleExit = (error) => {
|
102 | if (this.isRawModeSupported()) {
|
103 | this.handleSetRawMode(false);
|
104 | }
|
105 | this.props.onExit(error);
|
106 | };
|
107 | this.enableFocus = () => {
|
108 | this.setState({
|
109 | isFocusEnabled: true
|
110 | });
|
111 | };
|
112 | this.disableFocus = () => {
|
113 | this.setState({
|
114 | isFocusEnabled: false
|
115 | });
|
116 | };
|
117 | this.focusNext = () => {
|
118 | this.setState(previousState => {
|
119 | var _a;
|
120 | const firstFocusableId = (_a = previousState.focusables[0]) === null || _a === void 0 ? void 0 : _a.id;
|
121 | const nextFocusableId = this.findNextFocusable(previousState);
|
122 | return {
|
123 | activeFocusId: nextFocusableId || firstFocusableId
|
124 | };
|
125 | });
|
126 | };
|
127 | this.focusPrevious = () => {
|
128 | this.setState(previousState => {
|
129 | var _a;
|
130 | const lastFocusableId = (_a = previousState.focusables[previousState.focusables.length - 1]) === null || _a === void 0 ? void 0 : _a.id;
|
131 | const previousFocusableId = this.findPreviousFocusable(previousState);
|
132 | return {
|
133 | activeFocusId: previousFocusableId || lastFocusableId
|
134 | };
|
135 | });
|
136 | };
|
137 | this.addFocusable = (id, { autoFocus }) => {
|
138 | this.setState(previousState => {
|
139 | let nextFocusId = previousState.activeFocusId;
|
140 | if (!nextFocusId && autoFocus) {
|
141 | nextFocusId = id;
|
142 | }
|
143 | return {
|
144 | activeFocusId: nextFocusId,
|
145 | focusables: [
|
146 | ...previousState.focusables,
|
147 | {
|
148 | id,
|
149 | isActive: true
|
150 | }
|
151 | ]
|
152 | };
|
153 | });
|
154 | };
|
155 | this.removeFocusable = (id) => {
|
156 | this.setState(previousState => ({
|
157 | activeFocusId: previousState.activeFocusId === id
|
158 | ? undefined
|
159 | : previousState.activeFocusId,
|
160 | focusables: previousState.focusables.filter(focusable => {
|
161 | return focusable.id !== id;
|
162 | })
|
163 | }));
|
164 | };
|
165 | this.activateFocusable = (id) => {
|
166 | this.setState(previousState => ({
|
167 | focusables: previousState.focusables.map(focusable => {
|
168 | if (focusable.id !== id) {
|
169 | return focusable;
|
170 | }
|
171 | return {
|
172 | id,
|
173 | isActive: true
|
174 | };
|
175 | })
|
176 | }));
|
177 | };
|
178 | this.deactivateFocusable = (id) => {
|
179 | this.setState(previousState => ({
|
180 | activeFocusId: previousState.activeFocusId === id
|
181 | ? undefined
|
182 | : previousState.activeFocusId,
|
183 | focusables: previousState.focusables.map(focusable => {
|
184 | if (focusable.id !== id) {
|
185 | return focusable;
|
186 | }
|
187 | return {
|
188 | id,
|
189 | isActive: false
|
190 | };
|
191 | })
|
192 | }));
|
193 | };
|
194 | this.findNextFocusable = (state) => {
|
195 | var _a;
|
196 | const activeIndex = state.focusables.findIndex(focusable => {
|
197 | return focusable.id === state.activeFocusId;
|
198 | });
|
199 | for (let index = activeIndex + 1; index < state.focusables.length; index++) {
|
200 | if ((_a = state.focusables[index]) === null || _a === void 0 ? void 0 : _a.isActive) {
|
201 | return state.focusables[index].id;
|
202 | }
|
203 | }
|
204 | return undefined;
|
205 | };
|
206 | this.findPreviousFocusable = (state) => {
|
207 | var _a;
|
208 | const activeIndex = state.focusables.findIndex(focusable => {
|
209 | return focusable.id === state.activeFocusId;
|
210 | });
|
211 | for (let index = activeIndex - 1; index >= 0; index--) {
|
212 | if ((_a = state.focusables[index]) === null || _a === void 0 ? void 0 : _a.isActive) {
|
213 | return state.focusables[index].id;
|
214 | }
|
215 | }
|
216 | return undefined;
|
217 | };
|
218 | }
|
219 | static getDerivedStateFromError(error) {
|
220 | return { error };
|
221 | }
|
222 |
|
223 | isRawModeSupported() {
|
224 | return this.props.stdin.isTTY;
|
225 | }
|
226 | render() {
|
227 | return (react_1.default.createElement(AppContext_1.default.Provider, { value: {
|
228 | exit: this.handleExit
|
229 | } },
|
230 | react_1.default.createElement(StdinContext_1.default.Provider, { value: {
|
231 | stdin: this.props.stdin,
|
232 | setRawMode: this.handleSetRawMode,
|
233 | isRawModeSupported: this.isRawModeSupported(),
|
234 | internal_exitOnCtrlC: this.props.exitOnCtrlC
|
235 | } },
|
236 | react_1.default.createElement(StdoutContext_1.default.Provider, { value: {
|
237 | stdout: this.props.stdout,
|
238 | write: this.props.writeToStdout
|
239 | } },
|
240 | react_1.default.createElement(StderrContext_1.default.Provider, { value: {
|
241 | stderr: this.props.stderr,
|
242 | write: this.props.writeToStderr
|
243 | } },
|
244 | react_1.default.createElement(FocusContext_1.default.Provider, { value: {
|
245 | activeId: this.state.activeFocusId,
|
246 | add: this.addFocusable,
|
247 | remove: this.removeFocusable,
|
248 | activate: this.activateFocusable,
|
249 | deactivate: this.deactivateFocusable,
|
250 | enableFocus: this.enableFocus,
|
251 | disableFocus: this.disableFocus,
|
252 | focusNext: this.focusNext,
|
253 | focusPrevious: this.focusPrevious
|
254 | } }, this.state.error ? (react_1.default.createElement(ErrorOverview_1.default, { error: this.state.error })) : (this.props.children)))))));
|
255 | }
|
256 | componentDidMount() {
|
257 | cli_cursor_1.default.hide(this.props.stdout);
|
258 | }
|
259 | componentWillUnmount() {
|
260 | cli_cursor_1.default.show(this.props.stdout);
|
261 |
|
262 | if (this.isRawModeSupported()) {
|
263 | this.handleSetRawMode(false);
|
264 | }
|
265 | }
|
266 | componentDidCatch(error) {
|
267 | this.handleExit(error);
|
268 | }
|
269 | }
|
270 | exports.default = App;
|
271 | App.displayName = 'InternalApp';
|
272 |
|
\ | No newline at end of file |