{"id":19810353,"url":"https://github.com/elius94/console-gui-tools","last_synced_at":"2025-04-07T11:09:10.302Z","repository":{"id":39633056,"uuid":"479072497","full_name":"Elius94/console-gui-tools","owner":"Elius94","description":"A simple library to draw option menu or other popup inputs and layout on Node.js console.","archived":false,"fork":false,"pushed_at":"2024-06-11T09:28:27.000Z","size":1018,"stargazers_count":130,"open_issues_count":8,"forks_count":19,"subscribers_count":4,"default_branch":"main","last_synced_at":"2025-03-31T10:03:19.832Z","etag":null,"topics":["command-line","console","consoleapp","gui","logs","ncurses","node","node-js","terminal","terminal-colors","terminal-graphics","terminal-ui"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Elius94.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-04-07T16:52:21.000Z","updated_at":"2025-03-06T16:53:19.000Z","dependencies_parsed_at":"2023-02-16T09:30:26.806Z","dependency_job_id":"478db41b-2caa-4a1c-90ec-db5177e84c2b","html_url":"https://github.com/Elius94/console-gui-tools","commit_stats":{"total_commits":211,"total_committers":3,"mean_commits":70.33333333333333,"dds":0.009478672985781977,"last_synced_commit":"cf60052c4a81b2106e2bc7bc6191d9e26a078769"},"previous_names":[],"tags_count":67,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Elius94%2Fconsole-gui-tools","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Elius94%2Fconsole-gui-tools/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Elius94%2Fconsole-gui-tools/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Elius94%2Fconsole-gui-tools/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Elius94","download_url":"https://codeload.github.com/Elius94/console-gui-tools/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247640465,"owners_count":20971557,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["command-line","console","consoleapp","gui","logs","ncurses","node","node-js","terminal","terminal-colors","terminal-graphics","terminal-ui"],"created_at":"2024-11-12T09:21:02.273Z","updated_at":"2025-04-07T11:09:10.273Z","avatar_url":"https://github.com/Elius94.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# console-gui-tools \n[![npm version](https://badge.fury.io/js/console-gui-tools.svg)](https://npmjs.com/package/console-gui-tools) [![npm](https://img.shields.io/npm/dt/console-gui-tools)](https://npmjs.com/package/console-gui-tools) ![GitHub](https://img.shields.io/github/license/elius94/console-gui-tools)\n\nA simple Node.js library to create Console Apps like a wizard (or maybe if you like old style colored screen or something like \"teletext\" programs 😂)\nApart from jokes, it is a library that allows you to create a screen divided into a part with everything you want to see (such as variable values) and another in which the logs run.\nMoreover in this way the application is managed by the input event \"keypressed\" to which each key corresponds to a bindable command.\nFor example, to change variables you can open popups with an option selector or with a textbox.\nIt's in embryonic phase, any suggestion will be constructive :D\n\n![Animation](https://user-images.githubusercontent.com/14907987/164886106-b9c1e295-f4bf-4cc3-9065-365e1141dfd9.gif)\n\n## Requirements\n\n#### Node.js\nVersion: \u003e= ~~14.17~~ 18.18.0 (since 3.2.2)\n\n#### OS\nIt works well in all os with a terminal that supports styling, colors and other nice features. I've tested it on Linux: Ubuntu LTS, Arch, and Windows 10 and 11 and Mac OS.\nSince 1.1.4 mouse SGR and X11 protocols are supported. It works well on most linux terminals, but it doesn't work on Windows 10 and 11. You can use it on Windows 10 and 11 with [Windows Terminal](https://www.microsoft.com/it-it/p/windows-terminal/9n0dx20hk701?activetab=pivot:overviewtab) or [Cmder](https://cmder.net/) and using WSL (Windows Subsystem for Linux) with Ubuntu LTS or others.\nIn this way you can use mouse also on Windows 10 and 11.\n\n#### Windows users\nIn windows you can use it in both 10, and 11 but don't use the old Powershell (💩), make you a favor and use [Windows Terminal](https://github.com/microsoft/terminal) with Powershell Core (the last official)\nThat is currently installed by default in Windows 11.\nIn alternative i've runned this also with git bash shell.\n\n## Installation\n\nInstall with:\n```sh\nnpm i console-gui-tools\n```\n\n## Importing the library\nThe library is transpiled to ESM and CJS, so you can import it with both syntax.\n\n### ESM syntax\n```js\nimport { ConsoleManager } from 'console-gui-tools'\n```\n\n### CommonJS syntax\n```js\nconst { ConsoleManager } = require('console-gui-tools')\n```\n\n\u003cdetails\u003e\n\u003csummary\u003eOPTIONS\u003c/summary\u003e\n\nThe library has a few options that can be set in the constructor.\n\n### options.title\nThe title of the application. It will be displayed in the top of the screen.\n\n### options.logsPageSize\nThe number of lines that will be displayed in the logs page.\n\n### options.logLocation\nChoose where the logs are displayed: number (0,1) - to pot them on one of the two layouts, string (\"popup\") - to put them on a CustomPopup that can be displayed on the window.\n\n### options.showLogKey\nThe key that will be used to show the logs popup if the logLocation is set to \"popup\".\n\n### options.enableMouse\nEnable mouse support. It works well on most linux terminals, but it doesn't work on Windows 10 and 11 unless you use WSL (Windows Subsystem for Linux).\n\n![Mouse Example](https://user-images.githubusercontent.com/14907987/201913001-713ca6e7-c277-42f7-ac1a-5f90ee1b144f.gif)\n\n### options.overrideConsole\nOverride the console.log, console.info, console.warn, console.error, console.debug functions to print the logs on the screen.\n\n### options.layoutOptions\nThe options that will be passed to the layout.\n```js\nconst layoutOptions = {\n    boxed: true, // Set to true to enable boxed layout mode\n    showTitle: true, // Set to false to hide titles\n    changeFocusKey: 'ctrl+l', // The key or the combination that will change the focus between the two layouts\n    type: \"double\", // Can be \"single\", \"double\" or \"quad\" to choose the layout type\n    direction: 'vertical', // Set to 'horizontal' to enable horizontal layout (only for \"double\" layout)\n    boxColor: 'yellow', // The color of the box\n    boxStyle: 'bold', // The style of the box (bold)\n    fitHeight: true, // Set to false to disable the auto height fit [default: false] (since v3.2.0 - **NEW!**)\n}\n```\n\n### options.focusKey [v3.0.0]\nThe key that will be used to change the focus between controls in the focused layout. [default: 'tab']\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eEXAMPLE OF USAGE:\u003c/summary\u003e\n\n```js\n// Import module with ES6 syntax\nimport { ConsoleManager, OptionPopup, InputPopup, PageBuilder, ButtonPopup, ConfirmPopup } from 'console-gui-tools'\nconst GUI = new ConsoleManager({\n    title: 'TCP Simulator', // Title of the console\n    logsPageSize: 8, // Number of lines to show in logs page\n    changeLayoutKey: 'ctrl+l', // Change layout with ctrl+l to switch to the logs page\n})\n\n// Creating a main page updater:\nconst updateConsole = async() =\u003e {\n    const p = new PageBuilder()\n    p.addRow({ text: `TCP server simulator app! Welcome...`, color: 'yellow' })\n    p.addRow({ text: `TCP Server listening on ${HOST}:${PORT}`, color: 'green' })\n    p.addRow({ text: `Connected clients:`, color: 'green' }, { text: ` ${connectedClients}`, color: 'white' })\n    p.addRow({ text: `TCP messages sent:`, color: 'green', bg: 'bgRed', bold: true, italic: true, underline: true }, { text: ` ${tcpCounter}`, color: 'white' })\n\n    // Print if simulator is running or not\n    if (!valueEmitter) {\n        p.addRow({ text: `Simulator is not running! `, color: 'red' }, { text: `press 'space' to start`, color: 'white' })\n    } else {\n        p.addRow({ text: `Simulator is running! `, color: 'green' }, { text: `press 'space' to stop`, color: 'white' })\n    }\n\n    // Print mode:\n    p.addRow({ text: `Mode: `, color: 'cyan' }, { text: `${mode}`, color: 'white' })\n        // Print message frequency:\n    p.addRow({ text: `Message period: `, color: 'cyan' }, { text: `${period} ms`, color: 'white' })\n        // Print Min and Max\n    p.addRow({ text: `Min: `, color: 'cyan' }, { text: `${min}`, color: 'white' })\n    p.addRow({ text: `Max: `, color: 'cyan' }, { text: `${max}`, color: 'white' })\n        // Print current values:\n    p.addRow({ text: `Values: `, color: 'cyan' }, { text: ` ${values.map(v =\u003e v.toFixed(4)).join('   ')}`, color: 'white' })\n\n    // Spacer\n    p.addSpacer()\n\n    if (lastErr.length \u003e 0) {\n        p.addRow({ text: lastErr, color: 'red' })\n        p.addSpacer(2)\n    }\n\n    p.addRow({ text: \"Commands:\", color: 'white', bg: 'black' })\n    p.addRow({ text: `  'space'`, color: 'gray', bold: true }, { text: `   - Start/stop simulator`, color: 'white', italic: true })\n    p.addRow({ text: `  'm'`, color: 'gray', bold: true }, { text: `       - Select simulation mode`, color: 'white', italic: true })\n    p.addRow({ text: `  's'`, color: 'gray', bold: true }, { text: `       - Select message period`, color: 'white', italic: true })\n    p.addRow({ text: `  'h'`, color: 'gray', bold: true }, { text: `       - Set max value`, color: 'white', italic: true })\n    p.addRow({ text: `  'l'`, color: 'gray', bold: true }, { text: `       - Set min value`, color: 'white', italic: true })\n    p.addRow({ text: `  'q'`, color: 'gray', bold: true }, { text: `       - Quit`, color: 'white', italic: true })\n\n    GUI.setPage(p)\n}\n\nGUI.on(\"exit\", () =\u003e {\n    closeApp()\n})\n\n// And manage the keypress event from the library\nGUI.on(\"keypressed\", (key) =\u003e {\n    switch (key.name) {\n    case \"space\":\n        if (valueEmitter) {\n            clearInterval(valueEmitter)\n            valueEmitter = null\n        } else {\n            valueEmitter = setInterval(frame, period)\n        }\n        break\n    case \"m\":\n        new OptionPopup({\n            id: \"popupSelectMode\", \n            title: \"Select simulation mode\", \n            options: modeList, \n            selected: mode \n        }).show().on(\"confirm\", (_mode) =\u003e {\n            mode = _mode\n            GUI.warn(`NEW MODE: ${mode}`)\n            drawGui()\n        })\n        break\n    case \"s\":\n        new OptionPopup({\n            id: \"popupSelectPeriod\", \n            title: \"Select simulation period\", \n            options: periodList, \n            selected: period \n        }).show().on(\"confirm\", (_period) =\u003e {\n            const msgMultiLine = `Changing period from ${period} to ${_period} ms.${EOL}This will restart the simulator.${EOL}Do you want to continue?`\n            new ButtonPopup({\n                id: \"popupConfirmPeriod\", \n                title: \"Confirm period\", \n                message: msgMultiLine, \n                buttons: [\"Yes\", \"No\", \"?\"]\n            }).show().on(\"confirm\", (answer) =\u003e {\n                if (answer === \"Yes\") {\n                    period = _period\n                    GUI.warn(`NEW PERIOD: ${period}`)\n                } else if (answer === \"?\") {\n                    GUI.info(\"Choose ok to confirm period\")\n                }\n                drawGui()\n            })\n        })\n        break\n    case \"h\":\n        new InputPopup({\n            id: \"popupTypeMax\", \n            title: \"Type max value\", \n            value: max,\n            numeric: true\n        }).show().on(\"confirm\", (_max) =\u003e {\n            max = _max\n            GUI.warn(`NEW MAX VALUE: ${max}`)\n            drawGui()\n        })\n        break\n    case \"l\":\n        new InputPopup({\n            id: \"popupTypeMin\", \n            title: \"Type min value\", \n            value: min, \n            numeric: true\n        }).show().on(\"confirm\", (_min) =\u003e {\n            min = _min\n            GUI.warn(`NEW MIN VALUE: ${min}`)\n            drawGui()\n        })\n        break\n    case \"1\":\n        {\n            const p = new PageBuilder(5) // Add a scroll limit so it will be scrollable with up and down\n            p.addRow({ text: \"Example of a custom popup content!\", color: \"yellow\" })\n            p.addRow({ text: \"This is a custom popup!\", color: \"green\" })\n            p.addRow({ text: \"It can be used to show a message,\", color: \"green\" })\n            p.addRow({ text: \"or to show variables.\", color: \"green\" })\n            p.addRow({ text: \"TCP Message sent: \", color: \"green\" }, { text: `${tcpCounter}`, color: \"white\" })\n            p.addRow({ text: \"Connected clients: \", color: \"green\" }, { text: `${connectedClients}`, color: \"white\" })\n            p.addRow({ text: \"Mode: \", color: \"green\" }, { text: `${mode}`, color: \"white\" })\n            p.addRow({ text: \"Message period: \", color: \"green\" }, { text: `${period} ms`, color: \"white\" })\n            new CustomPopup({\n                id: \"popupCustom1\", \n                title: \"See that values\", \n                content: p, \n                width: 32\n            }).show()\n        }\n        break\n    case \"f\":\n        new FileSelectorPopup({\n            id: \"popupFileManager\", \n            title: \"File Manager\", \n            basePath: \"./\"\n        }).show()\n        break\n    case \"q\":\n        new ConfirmPopup({\n            id: \"popupQuit\", \n            title: \"Are you sure you want to quit?\"\n        }).show().on(\"confirm\", () =\u003e closeApp())\n        break\n    default:\n        break\n    }\n})\n\nconst drawGui = () =\u003e {\n    updateConsole()\n}\n\n```\n\n\u003c/details\u003e\n\n## How to draw the application page?\n\n### New drawing algorytm\n\nAll the page is prerendered before printing on the console to prevent noisy flickering.\n\nIntroduced new styling design pattern:\nEach page need to be created with the new class\n```js\nconst p = new PageBuilder()\n```\nand to add a styled row it's neccessary to call:\n```js\np.addRow({ text: `  'm'`, color: 'gray', bold: true }, { text: `       - Select simulation mode`, color: 'white', italic: true })\n```\nThe arguments of that function is an array of object (function arguments syntax, no []!), so in a row you can add different phrases with different styles.\n\nThe styles are converted to the Chalk modificator:\n\n\u003cdetails\u003e\n  \u003csummary\u003eCOLORS AND FORMATTERS\u003c/summary\u003e\n\n### HEX color (since 1.4.0)\n\n```js\n{ text: `  'm'`, color: '#FF0000' }\n```\n\n### RGB color (since 1.4.0)\n\n```js\n{ text: `  'm'`, color: 'rgb(255,0,0)' }\n```\n\n### Standard Chalk colors:\n - black\n - red\n - green\n - yellow\n - blue\n - magenta\n - cyan\n - white\n - blackBright (alias: gray, grey)\n - redBright\n - greenBright\n - yellowBright\n - blueBright\n - magentaBright\n - cyanBright\n - whiteBright\n\n### Standard Chalk Background colors ('bg')\n - bgBlack\n - bgRed\n - bgGreen\n - bgYellow\n - bgBlue\n - bgMagenta\n - bgCyan\n - bgWhite\n - bgBlackBright (alias: bgGray, bgGrey)\n - bgRedBright\n - bgGreenBright\n - bgYellowBright\n - bgBlueBright\n - bgMagentaBright\n - bgCyanBright\n - bgWhiteBright\n\n### Formatters (Each is a prop):\n - italic\n - bold\n - dim\n - underline\n - overline\n - inverse\n - hidden\n - strikethrough\n\neg:\n\n```js\np.addRow({ text: `TCP messages sent:`, color: 'green', bg: 'bgRed', bold: true, italic: true, underline: true }, { text: ` ${tcpCounter}`, color: 'white' })\n```\n\n\u003c/details\u003e\n\nAnd so, we can add the PageBuilder to the first page\n\n```js\nGUI.setPage(p, 0)\n```\n\n## Layout\nThe application instance needs to output the content through a layout class.\nIn the \"layoutOptions\" provided to the ConsoleManager, we can set the layout:\n\n\u003cdetails\u003e\u003csummary\u003eboxed: Set to true to enable boxed layout mode (default: true)\u003c/summary\u003e\n\n| boxed: true | boxed: false |\n| ----------- | ------------ |\n| ![boxed layout](https://user-images.githubusercontent.com/14907987/170996957-cb28414b-7be2-4aa0-938b-f6d1724cfa4c.png) | ![not boxed layout](https://user-images.githubusercontent.com/14907987/170997089-ef0c1460-1f81-4623-832c-5eee5d26fa17.png) |\n\n\u003c/details\u003e\n\n - showTitle: Set to false to hide titles (default: true, on title per page)\n - changeFocusKey: The key or the combination that will change the focus between the pages of the layout (default: 'ctrl+l')\n\u003cdetails\u003e\u003csummary\u003etype: Can be \"single\", \"double\" or \"quad\" to choose the layout type (default: \"double\")\u003c/summary\u003e\n \n| type: \"single\" | type: \"double\" | type: \"quad\" | \n| -------------- | -------------- | ------------ |\n| ![single layout](https://user-images.githubusercontent.com/14907987/170997567-b1260996-cc7e-4c26-8389-39519313f3f6.png) | ![double layout](https://user-images.githubusercontent.com/14907987/170996957-cb28414b-7be2-4aa0-938b-f6d1724cfa4c.png) | ![quad layout](https://user-images.githubusercontent.com/14907987/170998201-59880c90-7b1a-491a-8a45-6610e5c33de9.png) |\n\n\u003c/details\u003e\n\n - direction: Set to 'horizontal' to enable horizontal layout (only for \"double\" layout)\n - boxColor: The color of the box (default: 'yellow')\n - boxStyle: The style of the box (default: 'bold')\n - fitHeight: Set to false to disable the auto height fit [default: false] (since v3.2.0 - **NEW!**)\n\n To draw multiple pages, we need to use the setPage or setPages methods:\n\n```js\nGUI.setPage(p, 0) // Add the first page without explicit name (default: application title)\n\nconst p1 = new PageBuilder()\np1.addRow({ text: \"SECOND PAGE\", color: \"green\" })\n\nconst P2 = new PageBuilder()\nP2.addRow({ text: \"THIRD PAGE\", color: \"cyan\" })\n\nGUI.setPage(p1, 1, \"Top Right\")\nGUI.setPage(P2, 2, \"Bottom Left\")\n\n// Or if we want to add the pages in the same order (only one render):\nGUI.setPages([p, p1, P2], [\"App Title\", \"Top Right\", \"Bottom Left\"])\n```\n\n\u003cdetails\u003e\u003csummary\u003eChanging the layout aspect ratio\u003c/summary\u003e\n \nIf we are in quad layout mode or double horizontal layout, we can change the aspect ratio of the layout rows by pressing the \"left\" and \"right\" keys:\n \n![change ratio](https://user-images.githubusercontent.com/14907987/170999347-868eac7b-6bdf-4147-bcb0-b7465282ed5f.gif)\n \n \u003e If you are using the quad layout mode the arrow keys will change the aspect ratio of the layout selected row (the top or the bottom row, depending on the selected page)\n \n\u003c/details\u003e\n \n# Widgets\nThere are two types of widgets: the \"popup\" widgets and the \"control\" widgets.\n\n## Control widgets (since 1.1.42) [New!](docs/Control.md)\nThe control widgets are the widgets that are displayed on the page and are not \"popup\" widgets.\nThey has an absolute position and size and are not affected by the layout.\nIntroduced since the version 1.1.42 of the library.\nCurrently there is only the base class for the control widgets, \"Control\" class and the \"Button\" class.\nIt is possible to create a custom control widget by extending the Control class and implementing the draw method.\nExample:\n ```ts\nconst widget1 = new InPageWidgetBuilder()\nwidget1.addRow({ text: \"┌────────┐\", color: \"yellow\", style: \"bold\" })\nwidget1.addRow({ text: \"│ START! │\", color: \"yellow\", style: \"bold\" })\nwidget1.addRow({ text: \"└────────┘\", color: \"yellow\", style: \"bold\" })\n\nconst button1 = new Control({\n   id: \"btn1\",\n   visible: false,\n   attributes: { x: 30, y: 18, width: 10, height: 3 },\n   children: widget1\n})\nbutton1.on(\"relativeMouse\", (event) =\u003e {\n    if (event.name === \"MOUSE_LEFT_BUTTON_RELEASED\") console.log(\"Button clicked!\")\n})\n```\n\n\u003e Since the version 3.0.0 of the library, this constructor has been changed. See the [v3.0.0 Release Note](https://github.com/Elius94/console-gui-tools/releases/tag/v3.0.0) for more information.\n\nResult:\n\n![InPageWidget](https://user-images.githubusercontent.com/14907987/202858694-82ca7f26-2a7a-4210-92da-fbbd40ad10b4.gif)\n\n## Box (since 3.0.0) [New!](docs/Box.md)\nThe box is a control widget that allows you to create a box with a title and a content. The content is a InPageWidgetBuilder object, so you can add rows to it. It can have a title and can be boxed or not. It can be used to place some texts in a specific position of the screen, without using the layout. It also can be draggable.\n\n```ts\nnew Box({\n    id: \"box1\",\n    x: 22,\n    y: 3,\n    width: 28,\n    height: 3,\n    draggable: true,\n    style: {\n        boxed: true,\n    }\n}).setContent(new InPageWidgetBuilder().addRow({ text: \"This is a draggable Box!\", color: \"rgb(255,0,0)\", bg: \"rgb(0,0,255)\"}))\n```\n\nSee the [Box documentation](docs/Box.md) for more information. or try the [Box example](examples/box.mjs).\n\n![htop](https://user-images.githubusercontent.com/14907987/215077472-3fd24bd5-ec71-420d-bdcf-f518a8f5d837.gif)\n\n\u003e This example is inspired by the htop command line tool.\n\n### Button (since 1.2.0) [New!](docs/Button.md)\nThe button is a control widget that basically do the previous example for you in a simpler way.\n\n`new Button(id, text, width, height, x, y, style, visible, enabled, onClick, onRelease)`\n\u003cp\u003eThis class is an overload of Control that is used to create a button.\u003c/p\u003e\n\u003cp\u003e\u003cimg src=\"https://user-images.githubusercontent.com/14907987/202866824-047503fc-9af6-4990-aa9a-57a3d691f6b0.gif\" alt=\"Button\"\u003e\u003c/p\u003e\n\u003cp\u003eEmits the following events:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u0026quot;click\u0026quot; when the user confirm\u003c/li\u003e\n\u003cli\u003e\u0026quot;relese\u0026quot; when the user cancel\u003c/li\u003e\n\u003c/ul\u003e\n\n```js\nnew Button({\n    id: \"btnRun\", \n    text: \"Run me!\", \n    x: 48, \n    y: 1,\n    style: {\n        color: \"magentaBright\",\n        bold: true,\n        italic: true,\n        borderColor: \"green\"\n    },\n    onRelease: () =\u003e {\n        GUI.log(\"Button clicked!\")\n    },\n    draggable: true,\n})\n```\n\nSee the [Button documentation](docs/Button.md) for more information. or try the [Button example](examples/mouse_test.mjs).\n\n\u003e Since the version 3.0.0 of the library, this constructor has been changed. See the [v3.0.0 Release Note](https://github.com/Elius94/console-gui-tools/releases/tag/v3.0.0) for more information.\n\n### Progress (since 1.3.0) [New!](docs/ProgressBar.md)\nThis is a control widget that is used to draw a customizable progress bar. \nIt can also be used as interactive control (slider) by setting the `interactive` option to `true`.\n\n```js\nconst p2 = new Progress({\n    id: \"prog1\",\n    x: 2,\n    y: 1,\n    label: \"Mem\",\n    length: 40,\n    min: 0,\n    max: 100,\n    unit: \"G\",\n    style: {\n        boxed: true,\n        theme: \"htop\",\n        showMinMax: false,\n    }\n})\np2.setText(\"Interactive\")\np2.on(\"valueChanged\", (value) =\u003e {\n    console.log(`Value changed: ${value}`)\n})\n```\n\n\u003e Since the version 3.0.0 of the library, this constructor has been changed. See the [v3.0.0 Release Note](https://github.com/Elius94/console-gui-tools/releases/tag/v3.0.0) for more information.\n\n**Example**  \n\u003cp\u003e\u003cimg src=\"https://user-images.githubusercontent.com/14907987/203607512-6ce3656c-7ffb-4185-b36e-6c10619b2b6e.gif\" alt=\"Progress_Interactive\"\u003e\u003c/p\u003e\n\nSee the [Progress documentation](docs/ProgressBar.md) for more information. or try the [Progress example](examples/progress.mjs).\n\nIn the next versions of the library, more control widgets will be added as Control extensions.\n\n## Popup widgets\n## To create an option popup (select)\n```js\nnew OptionPopup({ \n    id: \"popupSelectPeriod\",\n    title: \"Select simulation period\", \n    options: periodList, \n    selected: period \n}).show().on(\"confirm\", (_period) =\u003e {\n    period = _period\n    GUI.warn(`NEW PERIOD: ${period}`)\n    drawGui()\n})\n```\n\n### Class OptionPopup:\nconstructor(id, title, options, selected)\n - id: string\n - title: string\n - options: Array\u003cstring | number\u003e\n - selected: string | number\n\nThe response is triggered via EventEmitter using \"on\"\nThe result is this:\n\n![Animation](https://user-images.githubusercontent.com/14907987/162480195-b08b4a0b-5d10-4122-8bff-9210295aac1f.gif)\n\nPressing enter it will close the popup and set the new value. If the list is too long, it will scroll reaching the bottom or top.\nNow you can also use \"pageup\" amd \"pagedown\" keys to navigate faster.\n\n## To create an input popup (numeric or string)\n```js\nnew InputPopup({ \n    id: \"popupTypeMax\", \n    title: \"Type max value\", \n    value: max, \n    numeric: true,\n    maxLen: 5,\n    placeholder: \"Type a number\" // since v3.1.0\n}).show().on(\"confirm\", (_max) =\u003e {\n    max = _max\n    GUI.warn(`NEW MAX VALUE: ${max}`)\n    drawGui()\n})\n```\n\n### Class InputPopup (updated in v3.4.0):\nconstructor(id, title, value, isNumeric)\n - id: string\n - title: string\n - value: string | number\n - isNumeric: boolean\n - maxLen: number (since v3.4.0)\n - placeholder: string (since v3.1.0)\n\nYou can use it for example to set a numeric threshold:\n\n![Animation](https://github.com/Elius94/console-gui-tools/assets/14907987/eecac72f-9ccc-444b-a0e3-2b7e277fdeea)\n\nIf you set isNumeric to true, only numbers are allowed.\nAll class of components will be destroyed when the popup is closed. The event listeners are removed from the store. Then the garbage collector will clean the memory.\n\n## To create a button popup\n```js\nnew ButtonPopup({ \n    id: \"popupConfirmPeriod\", \n    title: \"Confirm period\", \n    message: `Period set to ${period} ms, apply?`, \n    buttons: [\"Yes\", \"No\", \"?\"]\n}).show().on(\"confirm\", (answer) =\u003e {\n    if (answer === \"Yes\") {\n        period = _period\n        GUI.warn(`NEW PERIOD: ${period}`)\n    } else if (answer === \"?\") {\n        GUI.info(`Choose ok to confirm period`)\n    }\n    drawGui()\n})\n```\n\n### Class ButtonPopup:\nconstructor(id, title, message, buttons = [\"Ok\", \"Cancel\", \"?\"])\n - id: string\n - title: string\n - message: string\n - buttons: Array\u003cstring\u003e - The text of the buttons\n\nYou can use it for example to make a question:\n\n![Animation](https://user-images.githubusercontent.com/14907987/164768181-48f18d25-d05a-4959-88ec-8ce93212e356.gif)\n\n## To create a confirm popup (if you only need a yes or no answer)\n```js\nnew ConfirmPopup({ id: \"popupQuit\", title: \"Are you sure you want to quit?\" }).show().on(\"confirm\", () =\u003e closeApp())\n```\n\n### Class ConfirmPopup:\nconstructor(id, title)\n - id: string\n - title: string\n\nYou can use it for example to confirm before quit the app:\n\n![Animation](https://user-images.githubusercontent.com/14907987/164768797-3f538673-78da-4f67-b2c3-be1319f2fb95.gif)\n\n## To create a Custom Content Popup (Free content inside)\n```js\nconst p = new PageBuilder(5) // Add a scroll limit so it will be scrollable with up and down\np.addRow({ text: `Example of a custom popup content!`, color: 'yellow' })\np.addRow({ text: `This is a custom popup!`, color: 'green' })\np.addRow({ text: `It can be used to show a message,`, color: 'green' })\np.addRow({ text: `or to show variables.`, color: 'green' })\np.addRow({ text: `TCP Message sent: `, color: 'green' }, { text: `${tcpCounter}`, color: 'white' })\np.addRow({ text: `Connected clients: `, color: 'green' }, { text: `${connectedClients}`, color: 'white' })\np.addRow({ text: `Mode: `, color: 'green' }, { text: `${mode}`, color: 'white' })\np.addRow({ text: `Message period: `, color: 'green' }, { text: `${period} ms`, color: 'white' })\nnew CustomPopup({ id: \"popupCustom1\", title: \"See that values\", content: p, width: 32 }).show()\n```\n\n### Class CustomPopup:\nconstructor(id, title, content, width)\n - id: string\n - title: string\n - content: PageBuilder\n - width: number\n\nYou can use it for example to snow some custo text or values.\nIf you declare it as a global variable, you can update it anytime.\nIn the next steps I will add a new kind of components: InPageComponents, that will be added as a child of a PageBuilder class.\nThat means that they allows to build a custom popup widget with components inside.\n\n![Animation](https://user-images.githubusercontent.com/14907987/165717880-db959165-8c43-4780-b76c-190172de25d5.gif)\n\n\n## To create a File Selector popup\n```js\nnew FileSelectorPopup({ \n    id: \"popupFileManager\", \n    title: \"File Manager\", \n    basePath: \"./\"\n}).show().on(\"confirm\", (file) =\u003e {\n    GUI.warn(`File selected: ${file}`)\n    drawGui()\n})\n```\n### Class FileSelectorPopup:\nconstructor(id, title, content, width)\n - id: \u003ccode\u003estring\u003c/code\u003e\n - title: \u003ccode\u003estring\u003c/code\u003e\n - basePath: \u003ccode\u003estring\u003c/code\u003e - _The main path of the popup. re case sensitive._\n - limitToPath: \u003ccode\u003eboolean\u003c/code\u003e - _If true, the user can select a directory. Otherwise, only files are selectable. When true, to enter a directory, the user must press the space key instead of the enter key._\n - allowedExtensions: \u003ccode\u003e\u003ccode\u003eArray\u0026lt;string\u0026gt;\u003c/code\u003e\u003c/code\u003e - _The allowed extensions. If not set, all extensions are allowed. The extensions a can only select files in the path. If false, the user can select files in the path and parent directories._\n\n\u003eThis class is used to create a popup with a file input to select a file or a directory. It will run a promise with fs.readdir to get the list of files and directories. The user can select a file or a directory and the popup will be closed. \n\n![FileSelectorPopup](https://user-images.githubusercontent.com/14907987/165938464-c1426102-b598-42bb-8597-6337f0bcb009.gif)\n\nEmits the following events: \n- \"confirm\" when the user confirm the file or directory selection. The file or directory path is passed as parameter like this: {path: \"path/to/file\", name: \"file.ext\"}\n- \"cancel\" when the user cancel the file or directory selection.\n- \"exit\" when the user exit\n \nAll class of components will be destroyed when the popup is closed. The event listeners are removed from the store. Then the garbage collector will clean the memory.\n\n\u003e Since the version 3.0.0 of the library, all the popup constructors has been changed. See the [v3.0.0 Release Note](https://github.com/Elius94/console-gui-tools/releases/tag/v3.0.0) for more information.\n\n## Console.log and other logging tools\nBy default (since version 1.1.42) the console.log|warn|error|info are replaced by a custom function that will show the message in the apposite GUI space. To disable this override you can set the option `overrideConsole` to false in the options object of the constructor.\nThey are replaced by theese functions (that are also available in the ConsoleManager instance):\n\n```js\nGUI.log(`NEW MIN VALUE: ${min}`)\nGUI.warn(`NEW MIN VALUE: ${min}`)\nGUI.error(`NEW MIN VALUE: ${min}`)\nGUI.info(`NEW MIN VALUE: ${min}`)\n```\nAnd then written to the bottom of the page.\n\n![Animation](https://user-images.githubusercontent.com/14907987/162482192-042d88e5-f810-4523-8f0d-1d87a573d1b1.gif)\n\nYou can switch to the log view by pressing the \"changeLayoutKey\" key or combination:\nThe maximum number of lines is set to 10 by default but you can change it by setting the option \"logsPageSize\".\nWhen the logs exceed the limit, you can scroll up and down with up and down arrows (if you are in the log view).\n\n![Animation](https://user-images.githubusercontent.com/14907987/162482410-bfe26922-88f5-46bd-8659-059fcc698cf8.gif)\n\n\u003e This library is in development now. New componets will come asap.\n\n## License and copyright\n\nMIT License Copyright (c) 2022 [Elia Lazzari](https://github.com/Elius94)\n \nColors and styles are managed using [Chalk](https://github.com/chalk/chalk)\n \n![image](https://user-images.githubusercontent.com/14907987/164770011-d29579ad-e681-43b2-b550-7fb52fd74021.png)\n\n## Code Documentation\n\nTo see the code documentation, please click on the following link:\n\n[Code documentation](DOCS.md)\n\n## How To Contribute\nAny kind of contribution is welcome! Feel free to help, but first read [CONTRIBUTING.md](./CONTRIBUTING.md)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Felius94%2Fconsole-gui-tools","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Felius94%2Fconsole-gui-tools","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Felius94%2Fconsole-gui-tools/lists"}