├── .babelrc ├── .eslintrc ├── .github └── workflows │ └── release-package.yml ├── .gitignore ├── .npmignore ├── .npmrc ├── .nvmrc ├── .prettierignore ├── .prettierrc ├── CHANGELOG.md ├── DETAIL.md ├── LICENSE ├── README.md ├── dist ├── scripts │ ├── TCG copy.d.ts │ ├── TCG copy.js │ ├── TCG nobuffer.d.ts │ ├── TCG nobuffer.js │ ├── TCG origin.d.ts │ ├── TCG origin.js │ ├── TCG.d.ts │ ├── TCG.js │ ├── global.d.ts │ └── global.js └── src │ ├── index.d.ts │ ├── index.js │ └── lib │ ├── CLIApplication.d.ts │ ├── CLIApplication.js │ └── CLIWidgets │ ├── CLIButton.d.ts │ ├── CLIButton.js │ ├── CLICanvas.d.ts │ ├── CLICanvas.js │ ├── CLICheckbox.d.ts │ ├── CLICheckbox.js │ ├── CLICustom.d.ts │ ├── CLICustom.js │ ├── CLIImage.d.ts │ ├── CLIImage.js │ ├── CLILabel.d.ts │ ├── CLILabel.js │ ├── CLIPanel.d.ts │ ├── CLIPanel.js │ ├── CLIRadio.d.ts │ ├── CLIRadio.js │ ├── CLITextbox.d.ts │ ├── CLITextbox.js │ ├── CLIWebview.d.ts │ └── CLIWebview.js ├── imgs ├── dog.jpg ├── tcg.gif └── video.gif ├── package.json ├── scripts ├── TCG nobuffer.ts ├── TCG origin.ts ├── TCG.ts └── global.ts ├── src ├── index.ts └── lib │ ├── CLIApplication.ts │ └── CLIWidgets │ ├── CLIButton.ts │ ├── CLICanvas.ts │ ├── CLICheckbox.ts │ ├── CLICustom.ts │ ├── CLIImage.ts │ ├── CLILabel.ts │ ├── CLIPanel.ts │ ├── CLIRadio.ts │ ├── CLITextbox.ts │ └── CLIWebview.ts ├── tests ├── default.js ├── default.jsx ├── normal.js ├── tcg.js ├── tcg2.js └── tcg3.js ├── transform-jsx-syntax.js └── tsconfig.json /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["@babel/preset-env"], 3 | "plugins": ["@babel/plugin-syntax-jsx", "./transform-jsx-syntax"] 4 | } -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "root": true, 3 | "extends": [ 4 | "eslint:recommended", 5 | "plugin:@typescript-eslint/recommended" 6 | ], 7 | "parser": "@typescript-eslint/parser", 8 | "parserOptions": { "project": ["./tsconfig.json"], "ecmaFeatures": { "jsx": true }, "ecmaVersion": "latest", "sourceType": "module" }, 9 | "plugins": [ 10 | "@typescript-eslint" 11 | ], 12 | "rules": { 13 | "@typescript-eslint/strict-boolean-expressions": [ 14 | 2, 15 | { 16 | "allowString" : false, 17 | "allowNumber" : false 18 | } 19 | ] 20 | }, 21 | "ignorePatterns": ["src/**/*.test.ts", "src/frontend/generated/*"] 22 | } -------------------------------------------------------------------------------- /.github/workflows/release-package.yml: -------------------------------------------------------------------------------- 1 | name: Node.js Package 2 | 3 | on: 4 | release: 5 | types: [created] 6 | 7 | jobs: 8 | build: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/checkout@v4 12 | - uses: actions/setup-node@v3 13 | with: 14 | node-version: 16 15 | - run: npm ci 16 | - run: npm test 17 | 18 | publish-gpr: 19 | needs: build 20 | runs-on: ubuntu-latest 21 | permissions: 22 | packages: write 23 | contents: read 24 | steps: 25 | - uses: actions/checkout@v4 26 | - uses: actions/setup-node@v3 27 | with: 28 | node-version: 16 29 | registry-url: https://npm.pkg.github.com/ 30 | - run: npm ci 31 | - run: npm publish 32 | env: 33 | NODE_AUTH_TOKEN: ${{secrets.GITHUB_TOKEN}} 34 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | .env 3 | package-lock.json -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .github/ 2 | imgs/ 3 | node_modules/ 4 | scripts/ 5 | src/ 6 | tests/ 7 | .gitignore 8 | .npmrc 9 | CHANGELOG.md 10 | DETAIL.md 11 | package-lock.json -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | @ice1:registry=https://npm.pkg.github.com -------------------------------------------------------------------------------- /.nvmrc: -------------------------------------------------------------------------------- 1 | v3.0.25 -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | dist -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "prettier.semi": true, 3 | "prettier.tabWidth": 4 4 | } -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ### 3.0.21 (30 Nov, 2023) 2 | 3 | #### Three CLI Graphics 4 | - Implementation of triple buffering 5 | 6 | --- 7 | 8 | ### 3.0.19 (30 Nov, 2023) 9 | 10 | #### Three CLI Graphics 11 | - TCG ready to use (You can draw a 3d figure) 12 | 13 | --- 14 | 15 | ### 2.9.14 (21 Nov, 2023) 16 | 17 | #### Three CLI Graphics 18 | - A `scripts` folder has been created for TCG library use. 19 | - Externally tested. To be uploaded later 20 | 21 | --- 22 | 23 | ### 1.8.1 (17 Nov, 2023) 24 | 25 | #### CLIApplication 26 | - Add an `onChange` event to events and defaultEvents, and in the case of `CLITextbox`, call the function if the text has been modified. 27 | 28 | #### More Documents 29 | - `CHANGELOG.md` created to record what you did today and what you updated -------------------------------------------------------------------------------- /DETAIL.md: -------------------------------------------------------------------------------- 1 | ## 💫 Package Detail 2 | 3 | This is a detailed description of the package. 4 | 5 | ### 🎬 Usage 6 | 7 | In the most known way: 8 | ```jsx 9 | const title = ; 10 | const title = new CLILabel({ text: "title", styles: { "text-color": "#222831", y: 2 }}); 11 | ``` 12 | 13 | #### 💾 Configuration required for use 14 | 15 | ##### directory structure 16 | ``` 17 | - build 18 | - node_modules 19 | - babel.config.js 20 | - index.js (main) 21 | - package.json 22 | - package-lock.json 23 | - transform-syntax-linterf.js 24 | ``` 25 | 26 | ##### npm package installation 27 | ```bash 28 | $ npm install babel linterf linterf-scripts 29 | $ npm install --save-dev @babel/cli @babel/core @babel/plugin-syntax-jsx @babel/plugin-transform-react-jsx @babel/preset-env @babel/preset-react 30 | ``` 31 | 32 | ##### package.json 33 | ```json 34 | "scripts": { 35 | "build": "linterf-scripts" 36 | } 37 | ``` 38 | 39 | ##### babel.config.js 40 | ```js 41 | module.exports = { 42 | "presets": ["@babel/preset-env"], 43 | "plugins": ["@babel/plugin-syntax-jsx", "./transform-syntax-linterf"], 44 | 45 | "ignore": ["node_modules", "build"] 46 | // Add folders to exclude 47 | } 48 | ``` 49 | 50 | ##### transform-syntax-linterf 51 | ```js 52 | module.exports = function(babel) { 53 | const { types: t } = babel; 54 | 55 | const supportedElements = []; 56 | // Make sure you write down the names of the widgets you want to use! 57 | 58 | return { 59 | name: 'transform-jsx-syntax', 60 | visitor: { 61 | JSXElement(path) { 62 | const elementName = path.node.openingElement.name.name; 63 | 64 | if (supportedElements.includes(elementName)) { 65 | const pathAttr = path.node.openingElement.attributes; 66 | const pathProps = pathAttr.map((attr) => { 67 | const key = attr.name.name; 68 | let value; 69 | 70 | if (t.isJSXExpressionContainer(attr.value)) value = attr.value.expression; 71 | else value = attr.value; 72 | 73 | return t.objectProperty(t.stringLiteral(key), value); 74 | }); 75 | 76 | const newElement = t.newExpression(t.identifier(elementName), [ 77 | t.objectExpression(pathProps), 78 | ]); 79 | 80 | path.replaceWith(newElement); 81 | } 82 | }, 83 | }, 84 | }; 85 | }; 86 | ``` 87 | 88 | We're all ready now! Please write the code and build it at the terminal. -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright 2023 kithub-Inc 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 💫 linterf 4 | 5 | > ***install `GraphicsMagick`*** 6 | > 7 | > Be sure to watch [DETAIL.md](https://github.com/ICe1BotMaker/linterf/blob/master/DETAIL.md) before using it! 8 | 9 | ### 💬 An advanced version of nodecli-gui 10 | 11 | - **Widgets**: Panel, Button, Label, Checkbox, Radio, Image, Textbox, Webview, Custom 12 | - **Presets**: Modal (create-later) 13 | - **Functions**: TCG (3D CLI Graphic) 14 | 15 | 17 | 18 | #### 🆕 **TCG ?** 19 | - A 3D engine using cli, and text is drawn on the screen using location and size data. 20 | 21 | ##### When running tcg, use the program below to run it. 22 | - [**Windows Terminal**](https://apps.microsoft.com/detail/9N0DX20HK701?hl=ko-kr&gl=US) 23 | 24 | 25 | 26 | ```jsx 27 | const { CLIApplication } = require(`linterf`); 28 | const global = require(`linterf/dist/scripts/global`); 29 | 30 | const app = new CLIApplication(); 31 | 32 | const tcg = new global.TCG([ 33 | { 34 | id: `cube`, 35 | center: { x: .5, y: .8, z: .5 }, 36 | rotation: { x: .5, y: .5, z: 0 }, 37 | vertices: [ 38 | { x: 0, y: .7, z: 0 }, 39 | { x: 1, y: .7, z: 0 }, 40 | { x: 0, y: 1.3, z: 0 }, 41 | { x: 1, y: 1.3, z: 0 }, 42 | { x: 0, y: .7, z: 1 }, 43 | { x: 1, y: .7, z: 1 }, 44 | { x: 0, y: 1.3, z: 1 }, 45 | { x: 1, y: 1.3, z: 1 }, 46 | ] 47 | } 48 | ], { events: { 49 | onFrame: (objects, camera) => { 50 | if (objects[0].vertices[0].x >= 5) { 51 | objects[0].center.x = .5; 52 | objects[0].vertices.map((e, idx) => e.x = (((idx + 1) % 2) === 0)); 53 | } 54 | 55 | objects[0].center.x += .15; 56 | objects[0].rotation.y += .2; 57 | objects[0].vertices.map(e => e.x += .15); 58 | } 59 | } }); 60 | 61 | app.append(tcg); 62 | app.show(24); 63 | ``` 64 | 65 | ### 💾 Installation 66 | 67 | ```bash 68 | $ npm install linterf 69 | ``` 70 | 71 | ### 💾 Usage 72 | 73 | ```jsx 74 | const { CLIApplication, CLILabel } = require(`linterf`); 75 | 76 | const app = new CLIApplication(); 77 | 78 | const title = ; 79 | 80 | app.append(title); 81 | app.show(30); // frame: 30 82 | ``` 83 | 84 | ### 🎥 Run 85 | 86 | ```bash 87 | $ npx linterf-scripts 88 | ``` -------------------------------------------------------------------------------- /dist/scripts/TCG copy.d.ts: -------------------------------------------------------------------------------- 1 | import * as app from '../src/lib/CLIApplication'; 2 | export interface Iobject { 3 | id: string; 4 | center: Iposition; 5 | rotation: Iposition; 6 | vertices: Iposition[]; 7 | buffer: { 8 | buffer1: any[]; 9 | buffer2: any[]; 10 | buffer3: any[]; 11 | currentBuffer: any[]; 12 | }; 13 | } 14 | export interface Iposition { 15 | x: number; 16 | y: number; 17 | z: number; 18 | } 19 | export declare class TCG { 20 | data: app.Idata; 21 | camera: Iposition; 22 | objects: Iobject[]; 23 | constructor(objects: Iobject[], props?: app.Iproperties); 24 | private rotateX; 25 | private rotateY; 26 | private rotateZ; 27 | private drawToBuffer; 28 | private swapBuffers; 29 | private drawBufferToConsole; 30 | private clearBuffer; 31 | private draw; 32 | private connectAndDraw; 33 | private drawLine; 34 | prerun(widget: app.Iwidget): void; 35 | } 36 | -------------------------------------------------------------------------------- /dist/scripts/TCG copy.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { 3 | if (k2 === undefined) k2 = k; 4 | var desc = Object.getOwnPropertyDescriptor(m, k); 5 | if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { 6 | desc = { enumerable: true, get: function() { return m[k]; } }; 7 | } 8 | Object.defineProperty(o, k2, desc); 9 | }) : (function(o, m, k, k2) { 10 | if (k2 === undefined) k2 = k; 11 | o[k2] = m[k]; 12 | })); 13 | var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { 14 | Object.defineProperty(o, "default", { enumerable: true, value: v }); 15 | }) : function(o, v) { 16 | o["default"] = v; 17 | }); 18 | var __importStar = (this && this.__importStar) || function (mod) { 19 | if (mod && mod.__esModule) return mod; 20 | var result = {}; 21 | if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); 22 | __setModuleDefault(result, mod); 23 | return result; 24 | }; 25 | var __importDefault = (this && this.__importDefault) || function (mod) { 26 | return (mod && mod.__esModule) ? mod : { "default": mod }; 27 | }; 28 | Object.defineProperty(exports, "__esModule", { value: true }); 29 | exports.TCG = void 0; 30 | const chalk_1 = __importDefault(require("chalk")); 31 | const app = __importStar(require("../src/lib/CLIApplication")); 32 | class TCG { 33 | constructor(objects, props) { 34 | this.data = { 35 | "type": "tcg", 36 | "properties": { 37 | "accepts": ["accepts", "paths", "global", "styles", "events", "defaultEvents", "text", "placeholder", "checked"], 38 | "paths": [], 39 | "global": "", 40 | "styles": { 41 | "x": 1, 42 | "y": 1, 43 | "visible": true 44 | }, 45 | "events": {}, 46 | "defaultEvents": {} 47 | } 48 | }; 49 | this.camera = { x: 1, y: -1, z: 0 }; 50 | this.objects = []; 51 | objects = objects.map(e => { 52 | e.buffer = { buffer1: [], buffer2: [], buffer3: [], currentBuffer: [] }; 53 | return e; 54 | }); 55 | this.objects = this.objects.concat(objects); 56 | if (props) 57 | this.data.properties = app.setProps(props, this.data.properties); 58 | } 59 | rotateX(point, angle, center) { 60 | const y = (point.y - center.y) * Math.cos(angle) - (point.z - center.z) * Math.sin(angle) + center.y; 61 | const z = (point.y - center.y) * Math.sin(angle) + (point.z - center.z) * Math.cos(angle) + center.z; 62 | return Object.assign(Object.assign({}, point), { y, z }); 63 | } 64 | rotateY(point, angle, center) { 65 | const x = (point.x - center.x) * Math.cos(angle) + (point.z - center.z) * Math.sin(angle) + center.x; 66 | const z = -(point.x - center.x) * Math.sin(angle) + (point.z - center.z) * Math.cos(angle) + center.z; 67 | return Object.assign(Object.assign({}, point), { x, z }); 68 | } 69 | rotateZ(point, angle, center) { 70 | const x = (point.x - center.x) * Math.cos(angle) - (point.y - center.y) * Math.sin(angle) + center.x; 71 | const y = (point.x - center.x) * Math.sin(angle) + (point.y - center.y) * Math.cos(angle) + center.y; 72 | return Object.assign(Object.assign({}, point), { x, y }); 73 | } 74 | drawToBuffer(buffer, x, y, char) { 75 | if (!buffer[y]) 76 | buffer[y] = []; 77 | buffer[y][x] = char; 78 | } 79 | swapBuffers(object) { 80 | if (object.buffer.currentBuffer === object.buffer.buffer1) { 81 | object.buffer.currentBuffer = object.buffer.buffer2; 82 | } 83 | else if (object.buffer.currentBuffer === object.buffer.buffer2) { 84 | object.buffer.currentBuffer = object.buffer.buffer3; 85 | } 86 | else { 87 | object.buffer.currentBuffer = object.buffer.buffer1; 88 | } 89 | } 90 | drawBufferToConsole(buffer) { 91 | for (let row of buffer) 92 | if (row) 93 | process.stdout.write(row.join('') + '\n'); 94 | } 95 | clearBuffer(buffer) { 96 | for (let i = 0; i < buffer.length; i++) 97 | buffer[i] = []; 98 | } 99 | draw() { 100 | process.stdout.write('\x1Bc'); 101 | this.objects.forEach(object => { 102 | if (!object.buffer) 103 | object.buffer = { buffer1: [], buffer2: [], buffer3: [], currentBuffer: [] }; 104 | this.clearBuffer(object.buffer.currentBuffer); 105 | let rotatedVertices = object.vertices.map(point => this.rotateX(this.rotateY(this.rotateZ(point, object.rotation.z, object.center), object.rotation.y, object.center), object.rotation.x, object.center)); 106 | let translatedVertices = rotatedVertices.map(point => ({ 107 | x: point.x - this.camera.x, 108 | y: point.y - this.camera.y, 109 | z: point.z - this.camera.z 110 | })); 111 | this.connectAndDraw([0, 1, 3, 2], translatedVertices); 112 | this.connectAndDraw([4, 5, 7, 6], translatedVertices); 113 | this.connectAndDraw([0, 1, 5, 4], translatedVertices); 114 | this.connectAndDraw([2, 3, 7, 6], translatedVertices); 115 | this.connectAndDraw([0, 2, 6, 4], translatedVertices); 116 | this.connectAndDraw([1, 3, 7, 5], translatedVertices); 117 | this.swapBuffers(object); 118 | this.drawBufferToConsole(object.buffer.currentBuffer); 119 | }); 120 | } 121 | connectAndDraw(faceVertices, vertices) { 122 | for (let i = 0; i < faceVertices.length; i++) { 123 | const start = faceVertices[i]; 124 | const end = faceVertices[(i + 1) % faceVertices.length]; 125 | const startPoint = vertices[start]; 126 | const endPoint = vertices[end]; 127 | const startScreenX = Math.round(startPoint.x * 10) + 40; 128 | const startScreenY = Math.round(startPoint.y * 10) + 5; 129 | const endScreenX = Math.round(endPoint.x * 10) + 40; 130 | const endScreenY = Math.round(endPoint.y * 10) + 5; 131 | this.drawLine(startScreenX, startScreenY, endScreenX, endScreenY); 132 | } 133 | } 134 | drawLine(x0, y0, x1, y1) { 135 | const dx = Math.abs(x1 - x0); 136 | const dy = Math.abs(y1 - y0); 137 | const sx = x0 < x1 ? 1 : -1; 138 | const sy = y0 < y1 ? 1 : -1; 139 | let err = dx - dy; 140 | while (true) { 141 | process.stdout.cursorTo(x0 - 20, y0 - 10); 142 | process.stdout.write(chalk_1.default.white('█')); 143 | if (x0 === x1 && y0 === y1) 144 | break; 145 | const e2 = 2 * err; 146 | if (e2 > -dy) { 147 | err -= dy; 148 | x0 += sx; 149 | } 150 | if (e2 < dx) { 151 | err += dx; 152 | y0 += sy; 153 | } 154 | } 155 | } 156 | prerun(widget) { 157 | // console.log("Objects:", this.objects); 158 | var _a; 159 | const { events } = widget.data.properties; 160 | (_a = events.onFrame) === null || _a === void 0 ? void 0 : _a.call(events, this.objects, this.camera); 161 | this.draw(); 162 | } 163 | } 164 | exports.TCG = TCG; 165 | -------------------------------------------------------------------------------- /dist/scripts/TCG nobuffer.d.ts: -------------------------------------------------------------------------------- 1 | import * as app from '../src/lib/CLIApplication'; 2 | export interface Iobject { 3 | id: string; 4 | center: Iposition; 5 | rotation: Iposition; 6 | vertices: Iposition[]; 7 | } 8 | export interface Iposition { 9 | x: number; 10 | y: number; 11 | z: number; 12 | } 13 | export declare class TCG { 14 | data: app.Idata; 15 | camera: Iposition; 16 | objects: Iobject[]; 17 | constructor(objects: Iobject[], props?: app.Iproperties); 18 | private rotateX; 19 | private rotateY; 20 | private rotateZ; 21 | private draw; 22 | private connectAndDraw; 23 | private drawLine; 24 | prerun(widget: app.Iwidget): void; 25 | } 26 | -------------------------------------------------------------------------------- /dist/scripts/TCG nobuffer.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { 3 | if (k2 === undefined) k2 = k; 4 | var desc = Object.getOwnPropertyDescriptor(m, k); 5 | if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { 6 | desc = { enumerable: true, get: function() { return m[k]; } }; 7 | } 8 | Object.defineProperty(o, k2, desc); 9 | }) : (function(o, m, k, k2) { 10 | if (k2 === undefined) k2 = k; 11 | o[k2] = m[k]; 12 | })); 13 | var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { 14 | Object.defineProperty(o, "default", { enumerable: true, value: v }); 15 | }) : function(o, v) { 16 | o["default"] = v; 17 | }); 18 | var __importStar = (this && this.__importStar) || function (mod) { 19 | if (mod && mod.__esModule) return mod; 20 | var result = {}; 21 | if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); 22 | __setModuleDefault(result, mod); 23 | return result; 24 | }; 25 | var __importDefault = (this && this.__importDefault) || function (mod) { 26 | return (mod && mod.__esModule) ? mod : { "default": mod }; 27 | }; 28 | Object.defineProperty(exports, "__esModule", { value: true }); 29 | exports.TCG = void 0; 30 | const chalk_1 = __importDefault(require("chalk")); 31 | const app = __importStar(require("../src/lib/CLIApplication")); 32 | class TCG { 33 | constructor(objects, props) { 34 | this.data = { 35 | "type": "tcg", 36 | "properties": { 37 | "accepts": ["accepts", "paths", "global", "styles", "events", "defaultEvents", "text", "placeholder", "checked"], 38 | "paths": [], 39 | "global": "", 40 | "styles": { 41 | "x": 1, 42 | "y": 1, 43 | "visible": true 44 | }, 45 | "events": {}, 46 | "defaultEvents": {} 47 | } 48 | }; 49 | this.camera = { x: 1, y: -1, z: 0 }; 50 | this.objects = []; 51 | this.objects = this.objects.concat(objects); 52 | if (props) 53 | this.data.properties = app.setProps(props, this.data.properties); 54 | } 55 | rotateX(point, angle, center) { 56 | const y = (point.y - center.y) * Math.cos(angle) - (point.z - center.z) * Math.sin(angle) + center.y; 57 | const z = (point.y - center.y) * Math.sin(angle) + (point.z - center.z) * Math.cos(angle) + center.z; 58 | return Object.assign(Object.assign({}, point), { y, z }); 59 | } 60 | rotateY(point, angle, center) { 61 | const x = (point.x - center.x) * Math.cos(angle) + (point.z - center.z) * Math.sin(angle) + center.x; 62 | const z = -(point.x - center.x) * Math.sin(angle) + (point.z - center.z) * Math.cos(angle) + center.z; 63 | return Object.assign(Object.assign({}, point), { x, z }); 64 | } 65 | rotateZ(point, angle, center) { 66 | const x = (point.x - center.x) * Math.cos(angle) - (point.y - center.y) * Math.sin(angle) + center.x; 67 | const y = (point.x - center.x) * Math.sin(angle) + (point.y - center.y) * Math.cos(angle) + center.y; 68 | return Object.assign(Object.assign({}, point), { x, y }); 69 | } 70 | draw() { 71 | process.stdout.write('\x1Bc'); 72 | this.objects.forEach(object => { 73 | let rotatedVertices = object.vertices.map(point => this.rotateX(this.rotateY(this.rotateZ(point, object.rotation.z, object.center), object.rotation.y, object.center), object.rotation.x, object.center)); 74 | let translatedVertices = rotatedVertices.map(point => ({ 75 | x: point.x - this.camera.x, 76 | y: point.y - this.camera.y, 77 | z: point.z - this.camera.z 78 | })); 79 | this.connectAndDraw([0, 1, 3, 2], translatedVertices); 80 | this.connectAndDraw([4, 5, 7, 6], translatedVertices); 81 | this.connectAndDraw([0, 1, 5, 4], translatedVertices); 82 | this.connectAndDraw([2, 3, 7, 6], translatedVertices); 83 | this.connectAndDraw([0, 2, 6, 4], translatedVertices); 84 | this.connectAndDraw([1, 3, 7, 5], translatedVertices); 85 | }); 86 | } 87 | connectAndDraw(faceVertices, vertices) { 88 | for (let i = 0; i < faceVertices.length; i++) { 89 | const start = faceVertices[i]; 90 | const end = faceVertices[(i + 1) % faceVertices.length]; 91 | const startPoint = vertices[start]; 92 | const endPoint = vertices[end]; 93 | const startScreenX = Math.round(startPoint.x * 10) + 40; 94 | const startScreenY = Math.round(startPoint.y * 10) + 5; 95 | const endScreenX = Math.round(endPoint.x * 10) + 40; 96 | const endScreenY = Math.round(endPoint.y * 10) + 5; 97 | this.drawLine(startScreenX, startScreenY, endScreenX, endScreenY); 98 | } 99 | } 100 | drawLine(x0, y0, x1, y1) { 101 | const dx = Math.abs(x1 - x0); 102 | const dy = Math.abs(y1 - y0); 103 | const sx = x0 < x1 ? 1 : -1; 104 | const sy = y0 < y1 ? 1 : -1; 105 | let err = dx - dy; 106 | while (true) { 107 | process.stdout.cursorTo(x0 - 20, y0 - 10); 108 | process.stdout.write(chalk_1.default.white('█')); 109 | if (x0 === x1 && y0 === y1) 110 | break; 111 | const e2 = 2 * err; 112 | if (e2 > -dy) { 113 | err -= dy; 114 | x0 += sx; 115 | } 116 | if (e2 < dx) { 117 | err += dx; 118 | y0 += sy; 119 | } 120 | } 121 | } 122 | prerun(widget) { 123 | var _a; 124 | const { events } = widget.data.properties; 125 | (_a = events.onFrame) === null || _a === void 0 ? void 0 : _a.call(events, this.objects, this.camera); 126 | this.draw(); 127 | } 128 | } 129 | exports.TCG = TCG; 130 | -------------------------------------------------------------------------------- /dist/scripts/TCG origin.d.ts: -------------------------------------------------------------------------------- 1 | import * as app from '../src/lib/CLIApplication'; 2 | export interface Iobject { 3 | id: string; 4 | center: Iposition; 5 | rotation: Iposition; 6 | vertices: Iposition[]; 7 | buffer: { 8 | buffer1: any[]; 9 | buffer2: any[]; 10 | buffer3: any[]; 11 | currentBuffer: any[]; 12 | }; 13 | } 14 | export interface Iposition { 15 | x: number; 16 | y: number; 17 | z: number; 18 | } 19 | export declare class TCG { 20 | data: app.Idata; 21 | camera: Iposition; 22 | objects: Iobject[]; 23 | constructor(objects: Iobject[], props?: app.Iproperties); 24 | private rotateX; 25 | private rotateY; 26 | private rotateZ; 27 | private drawToBuffer; 28 | private swapBuffers; 29 | private drawBufferToConsole; 30 | private clearBuffer; 31 | private draw; 32 | private connectAndDraw; 33 | private drawLine; 34 | prerun(widget: app.Iwidget): void; 35 | } 36 | -------------------------------------------------------------------------------- /dist/scripts/TCG origin.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { 3 | if (k2 === undefined) k2 = k; 4 | var desc = Object.getOwnPropertyDescriptor(m, k); 5 | if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { 6 | desc = { enumerable: true, get: function() { return m[k]; } }; 7 | } 8 | Object.defineProperty(o, k2, desc); 9 | }) : (function(o, m, k, k2) { 10 | if (k2 === undefined) k2 = k; 11 | o[k2] = m[k]; 12 | })); 13 | var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { 14 | Object.defineProperty(o, "default", { enumerable: true, value: v }); 15 | }) : function(o, v) { 16 | o["default"] = v; 17 | }); 18 | var __importStar = (this && this.__importStar) || function (mod) { 19 | if (mod && mod.__esModule) return mod; 20 | var result = {}; 21 | if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); 22 | __setModuleDefault(result, mod); 23 | return result; 24 | }; 25 | var __importDefault = (this && this.__importDefault) || function (mod) { 26 | return (mod && mod.__esModule) ? mod : { "default": mod }; 27 | }; 28 | Object.defineProperty(exports, "__esModule", { value: true }); 29 | exports.TCG = void 0; 30 | const chalk_1 = __importDefault(require("chalk")); 31 | const app = __importStar(require("../src/lib/CLIApplication")); 32 | class TCG { 33 | constructor(objects, props) { 34 | this.data = { 35 | "type": "tcg", 36 | "properties": { 37 | "accepts": ["accepts", "paths", "global", "styles", "events", "defaultEvents", "text", "placeholder", "checked"], 38 | "paths": [], 39 | "global": "", 40 | "styles": { 41 | "x": 1, 42 | "y": 1, 43 | "visible": true 44 | }, 45 | "events": {}, 46 | "defaultEvents": {} 47 | } 48 | }; 49 | this.camera = { x: 1, y: -1, z: 0 }; 50 | this.objects = []; 51 | objects = objects.map(e => { 52 | e.buffer = { buffer1: [], buffer2: [], buffer3: [], currentBuffer: [] }; 53 | return e; 54 | }); 55 | this.objects = this.objects.concat(objects); 56 | if (props) 57 | this.data.properties = app.setProps(props, this.data.properties); 58 | } 59 | rotateX(point, angle, center) { 60 | const y = (point.y - center.y) * Math.cos(angle) - (point.z - center.z) * Math.sin(angle) + center.y; 61 | const z = (point.y - center.y) * Math.sin(angle) + (point.z - center.z) * Math.cos(angle) + center.z; 62 | return Object.assign(Object.assign({}, point), { y, z }); 63 | } 64 | rotateY(point, angle, center) { 65 | const x = (point.x - center.x) * Math.cos(angle) + (point.z - center.z) * Math.sin(angle) + center.x; 66 | const z = -(point.x - center.x) * Math.sin(angle) + (point.z - center.z) * Math.cos(angle) + center.z; 67 | return Object.assign(Object.assign({}, point), { x, z }); 68 | } 69 | rotateZ(point, angle, center) { 70 | const x = (point.x - center.x) * Math.cos(angle) - (point.y - center.y) * Math.sin(angle) + center.x; 71 | const y = (point.x - center.x) * Math.sin(angle) + (point.y - center.y) * Math.cos(angle) + center.y; 72 | return Object.assign(Object.assign({}, point), { x, y }); 73 | } 74 | drawToBuffer(buffer, x, y, char) { 75 | if (!buffer[y]) 76 | buffer[y] = []; 77 | buffer[y][x] = char; 78 | } 79 | swapBuffers(object) { 80 | if (object.buffer.currentBuffer === object.buffer.buffer1) { 81 | object.buffer.currentBuffer = object.buffer.buffer2; 82 | } 83 | else if (object.buffer.currentBuffer === object.buffer.buffer2) { 84 | object.buffer.currentBuffer = object.buffer.buffer3; 85 | } 86 | else { 87 | object.buffer.currentBuffer = object.buffer.buffer1; 88 | } 89 | } 90 | drawBufferToConsole(buffer) { 91 | for (let row of buffer) 92 | if (row) 93 | process.stdout.write(row.join('') + '\n'); 94 | } 95 | clearBuffer(buffer) { 96 | for (let i = 0; i < buffer.length; i++) 97 | buffer[i] = []; 98 | } 99 | draw() { 100 | process.stdout.write('\x1Bc'); 101 | this.objects.forEach(object => { 102 | if (!object.buffer) 103 | object.buffer = { buffer1: [], buffer2: [], buffer3: [], currentBuffer: [] }; 104 | this.clearBuffer(object.buffer.currentBuffer); 105 | let rotatedVertices = object.vertices.map(point => this.rotateX(this.rotateY(this.rotateZ(point, object.rotation.z, object.center), object.rotation.y, object.center), object.rotation.x, object.center)); 106 | let translatedVertices = rotatedVertices.map(point => ({ 107 | x: point.x - this.camera.x, 108 | y: point.y - this.camera.y, 109 | z: point.z - this.camera.z 110 | })); 111 | this.connectAndDraw([0, 1, 3, 2], translatedVertices); 112 | this.connectAndDraw([4, 5, 7, 6], translatedVertices); 113 | this.connectAndDraw([0, 1, 5, 4], translatedVertices); 114 | this.connectAndDraw([2, 3, 7, 6], translatedVertices); 115 | this.connectAndDraw([0, 2, 6, 4], translatedVertices); 116 | this.connectAndDraw([1, 3, 7, 5], translatedVertices); 117 | this.swapBuffers(object); 118 | this.drawBufferToConsole(object.buffer.currentBuffer); 119 | }); 120 | } 121 | connectAndDraw(faceVertices, vertices) { 122 | for (let i = 0; i < faceVertices.length; i++) { 123 | const start = faceVertices[i]; 124 | const end = faceVertices[(i + 1) % faceVertices.length]; 125 | const startPoint = vertices[start]; 126 | const endPoint = vertices[end]; 127 | const startScreenX = Math.round(startPoint.x * 10) + 40; 128 | const startScreenY = Math.round(startPoint.y * 10) + 5; 129 | const endScreenX = Math.round(endPoint.x * 10) + 40; 130 | const endScreenY = Math.round(endPoint.y * 10) + 5; 131 | this.drawLine(startScreenX, startScreenY, endScreenX, endScreenY); 132 | } 133 | } 134 | drawLine(x0, y0, x1, y1) { 135 | const dx = Math.abs(x1 - x0); 136 | const dy = Math.abs(y1 - y0); 137 | const sx = x0 < x1 ? 1 : -1; 138 | const sy = y0 < y1 ? 1 : -1; 139 | let err = dx - dy; 140 | while (true) { 141 | process.stdout.cursorTo(x0 - 20, y0 - 10); 142 | process.stdout.write(chalk_1.default.white('█')); 143 | if (x0 === x1 && y0 === y1) 144 | break; 145 | const e2 = 2 * err; 146 | if (e2 > -dy) { 147 | err -= dy; 148 | x0 += sx; 149 | } 150 | if (e2 < dx) { 151 | err += dx; 152 | y0 += sy; 153 | } 154 | } 155 | } 156 | prerun(widget) { 157 | // console.log("Objects:", this.objects); 158 | var _a; 159 | const { events } = widget.data.properties; 160 | (_a = events.onFrame) === null || _a === void 0 ? void 0 : _a.call(events, this.objects, this.camera); 161 | this.draw(); 162 | } 163 | } 164 | exports.TCG = TCG; 165 | -------------------------------------------------------------------------------- /dist/scripts/TCG.d.ts: -------------------------------------------------------------------------------- 1 | import * as app from '../src/lib/CLIApplication'; 2 | export interface Iobject { 3 | id: string; 4 | center: Iposition; 5 | rotation: Iposition; 6 | vertices: Iposition[]; 7 | } 8 | export interface Iposition { 9 | x: number; 10 | y: number; 11 | z: number; 12 | } 13 | export declare class TCG { 14 | data: app.Idata; 15 | camera: Iposition; 16 | objects: Iobject[]; 17 | constructor(objects: Iobject[], props?: app.Iproperties); 18 | private rotateX; 19 | private rotateY; 20 | private rotateZ; 21 | private draw; 22 | private connectAndDraw; 23 | private drawLine; 24 | prerun(widget: app.Iwidget): void; 25 | } 26 | -------------------------------------------------------------------------------- /dist/scripts/TCG.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { 3 | if (k2 === undefined) k2 = k; 4 | var desc = Object.getOwnPropertyDescriptor(m, k); 5 | if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { 6 | desc = { enumerable: true, get: function() { return m[k]; } }; 7 | } 8 | Object.defineProperty(o, k2, desc); 9 | }) : (function(o, m, k, k2) { 10 | if (k2 === undefined) k2 = k; 11 | o[k2] = m[k]; 12 | })); 13 | var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { 14 | Object.defineProperty(o, "default", { enumerable: true, value: v }); 15 | }) : function(o, v) { 16 | o["default"] = v; 17 | }); 18 | var __importStar = (this && this.__importStar) || function (mod) { 19 | if (mod && mod.__esModule) return mod; 20 | var result = {}; 21 | if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); 22 | __setModuleDefault(result, mod); 23 | return result; 24 | }; 25 | var __importDefault = (this && this.__importDefault) || function (mod) { 26 | return (mod && mod.__esModule) ? mod : { "default": mod }; 27 | }; 28 | Object.defineProperty(exports, "__esModule", { value: true }); 29 | exports.TCG = void 0; 30 | const chalk_1 = __importDefault(require("chalk")); 31 | const app = __importStar(require("../src/lib/CLIApplication")); 32 | class TCG { 33 | constructor(objects, props) { 34 | this.data = { 35 | "type": "tcg", 36 | "properties": { 37 | "accepts": ["accepts", "paths", "global", "styles", "events", "defaultEvents", "text", "placeholder", "checked"], 38 | "paths": [], 39 | "global": "", 40 | "styles": { 41 | "x": 1, 42 | "y": 1, 43 | "visible": true 44 | }, 45 | "events": {}, 46 | "defaultEvents": {} 47 | } 48 | }; 49 | this.camera = { x: 1, y: -1, z: 0 }; 50 | this.objects = []; 51 | this.objects = this.objects.concat(objects); 52 | if (props) 53 | this.data.properties = app.setProps(props, this.data.properties); 54 | } 55 | rotateX(point, angle, center) { 56 | const y = (point.y - center.y) * Math.cos(angle) - (point.z - center.z) * Math.sin(angle) + center.y; 57 | const z = (point.y - center.y) * Math.sin(angle) + (point.z - center.z) * Math.cos(angle) + center.z; 58 | return Object.assign(Object.assign({}, point), { y, z }); 59 | } 60 | rotateY(point, angle, center) { 61 | const x = (point.x - center.x) * Math.cos(angle) + (point.z - center.z) * Math.sin(angle) + center.x; 62 | const z = -(point.x - center.x) * Math.sin(angle) + (point.z - center.z) * Math.cos(angle) + center.z; 63 | return Object.assign(Object.assign({}, point), { x, z }); 64 | } 65 | rotateZ(point, angle, center) { 66 | const x = (point.x - center.x) * Math.cos(angle) - (point.y - center.y) * Math.sin(angle) + center.x; 67 | const y = (point.x - center.x) * Math.sin(angle) + (point.y - center.y) * Math.cos(angle) + center.y; 68 | return Object.assign(Object.assign({}, point), { x, y }); 69 | } 70 | draw() { 71 | process.stdout.write('\x1Bc'); 72 | this.objects.forEach(object => { 73 | let rotatedVertices = object.vertices.map(point => this.rotateX(this.rotateY(this.rotateZ(point, object.rotation.z, object.center), object.rotation.y, object.center), object.rotation.x, object.center)); 74 | let translatedVertices = rotatedVertices.map(point => ({ 75 | x: point.x - this.camera.x, 76 | y: point.y - this.camera.y, 77 | z: point.z - this.camera.z 78 | })); 79 | this.connectAndDraw([0, 1, 3, 2], translatedVertices); 80 | this.connectAndDraw([4, 5, 7, 6], translatedVertices); 81 | this.connectAndDraw([0, 1, 5, 4], translatedVertices); 82 | this.connectAndDraw([2, 3, 7, 6], translatedVertices); 83 | this.connectAndDraw([0, 2, 6, 4], translatedVertices); 84 | this.connectAndDraw([1, 3, 7, 5], translatedVertices); 85 | }); 86 | } 87 | connectAndDraw(faceVertices, vertices) { 88 | for (let i = 0; i < faceVertices.length; i++) { 89 | const start = faceVertices[i]; 90 | const end = faceVertices[(i + 1) % faceVertices.length]; 91 | const startPoint = vertices[start]; 92 | const endPoint = vertices[end]; 93 | const startScreenX = Math.round(startPoint.x * 10) + 40; 94 | const startScreenY = Math.round(startPoint.y * 10) + 5; 95 | const endScreenX = Math.round(endPoint.x * 10) + 40; 96 | const endScreenY = Math.round(endPoint.y * 10) + 5; 97 | this.drawLine(startScreenX, startScreenY, endScreenX, endScreenY); 98 | } 99 | } 100 | drawLine(x0, y0, x1, y1) { 101 | const dx = Math.abs(x1 - x0); 102 | const dy = Math.abs(y1 - y0); 103 | const sx = x0 < x1 ? 1 : -1; 104 | const sy = y0 < y1 ? 1 : -1; 105 | let err = dx - dy; 106 | while (true) { 107 | process.stdout.cursorTo(x0 - 20, y0 - 10); 108 | process.stdout.write(chalk_1.default.white('█')); 109 | if (x0 === x1 && y0 === y1) 110 | break; 111 | const e2 = 2 * err; 112 | if (e2 > -dy) { 113 | err -= dy; 114 | x0 += sx; 115 | } 116 | if (e2 < dx) { 117 | err += dx; 118 | y0 += sy; 119 | } 120 | } 121 | } 122 | prerun(widget) { 123 | var _a; 124 | const { events } = widget.data.properties; 125 | (_a = events.onFrame) === null || _a === void 0 ? void 0 : _a.call(events, this.objects, this.camera); 126 | this.draw(); 127 | } 128 | } 129 | exports.TCG = TCG; 130 | -------------------------------------------------------------------------------- /dist/scripts/global.d.ts: -------------------------------------------------------------------------------- 1 | export { TCG } from './TCG'; 2 | -------------------------------------------------------------------------------- /dist/scripts/global.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | exports.TCG = void 0; 4 | var TCG_1 = require("./TCG"); 5 | Object.defineProperty(exports, "TCG", { enumerable: true, get: function () { return TCG_1.TCG; } }); 6 | -------------------------------------------------------------------------------- /dist/src/index.d.ts: -------------------------------------------------------------------------------- 1 | export { CLIApplication } from "./lib/CLIApplication"; 2 | export { CLIPanel } from "./lib/CLIWidgets/CLIPanel"; 3 | export { CLILabel } from "./lib/CLIWidgets/CLILabel"; 4 | export { CLIButton } from "./lib/CLIWidgets/CLIButton"; 5 | export { CLICheckbox } from "./lib/CLIWidgets/CLICheckbox"; 6 | export { CLIRadio } from "./lib/CLIWidgets/CLIRadio"; 7 | export { CLIImage } from "./lib/CLIWidgets/CLIImage"; 8 | export { CLITextbox } from './lib/CLIWidgets/CLITextbox'; 9 | export { CLIWebview } from "./lib/CLIWidgets/CLIWebview"; 10 | export { CLICanvas } from "./lib/CLIWidgets/CLICanvas"; 11 | export { CLICustom } from "./lib/CLIWidgets/CLICustom"; 12 | -------------------------------------------------------------------------------- /dist/src/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | exports.CLICustom = exports.CLICanvas = exports.CLIWebview = exports.CLITextbox = exports.CLIImage = exports.CLIRadio = exports.CLICheckbox = exports.CLIButton = exports.CLILabel = exports.CLIPanel = exports.CLIApplication = void 0; 4 | var CLIApplication_1 = require("./lib/CLIApplication"); 5 | Object.defineProperty(exports, "CLIApplication", { enumerable: true, get: function () { return CLIApplication_1.CLIApplication; } }); 6 | var CLIPanel_1 = require("./lib/CLIWidgets/CLIPanel"); 7 | Object.defineProperty(exports, "CLIPanel", { enumerable: true, get: function () { return CLIPanel_1.CLIPanel; } }); 8 | var CLILabel_1 = require("./lib/CLIWidgets/CLILabel"); 9 | Object.defineProperty(exports, "CLILabel", { enumerable: true, get: function () { return CLILabel_1.CLILabel; } }); 10 | var CLIButton_1 = require("./lib/CLIWidgets/CLIButton"); 11 | Object.defineProperty(exports, "CLIButton", { enumerable: true, get: function () { return CLIButton_1.CLIButton; } }); 12 | var CLICheckbox_1 = require("./lib/CLIWidgets/CLICheckbox"); 13 | Object.defineProperty(exports, "CLICheckbox", { enumerable: true, get: function () { return CLICheckbox_1.CLICheckbox; } }); 14 | var CLIRadio_1 = require("./lib/CLIWidgets/CLIRadio"); 15 | Object.defineProperty(exports, "CLIRadio", { enumerable: true, get: function () { return CLIRadio_1.CLIRadio; } }); 16 | var CLIImage_1 = require("./lib/CLIWidgets/CLIImage"); 17 | Object.defineProperty(exports, "CLIImage", { enumerable: true, get: function () { return CLIImage_1.CLIImage; } }); 18 | var CLITextbox_1 = require("./lib/CLIWidgets/CLITextbox"); 19 | Object.defineProperty(exports, "CLITextbox", { enumerable: true, get: function () { return CLITextbox_1.CLITextbox; } }); 20 | var CLIWebview_1 = require("./lib/CLIWidgets/CLIWebview"); 21 | Object.defineProperty(exports, "CLIWebview", { enumerable: true, get: function () { return CLIWebview_1.CLIWebview; } }); 22 | var CLICanvas_1 = require("./lib/CLIWidgets/CLICanvas"); 23 | Object.defineProperty(exports, "CLICanvas", { enumerable: true, get: function () { return CLICanvas_1.CLICanvas; } }); 24 | var CLICustom_1 = require("./lib/CLIWidgets/CLICustom"); 25 | Object.defineProperty(exports, "CLICustom", { enumerable: true, get: function () { return CLICustom_1.CLICustom; } }); 26 | -------------------------------------------------------------------------------- /dist/src/lib/CLIApplication.d.ts: -------------------------------------------------------------------------------- 1 | export interface Iwidget { 2 | data: Idata; 3 | prerun: Function; 4 | isTyping?: boolean; 5 | } 6 | export interface Idata { 7 | type: string; 8 | properties: Iproperties; 9 | } 10 | export interface Iproperties { 11 | accepts: Array; 12 | paths: Array; 13 | global: string; 14 | styles: Istyles; 15 | events: Ievents; 16 | defaultEvents: Ievents; 17 | canvasChilds?: Array; 18 | text?: string; 19 | placeholder?: string; 20 | checked?: boolean; 21 | [key: string]: any; 22 | } 23 | export interface IcanvasChild { 24 | type: string; 25 | x: number; 26 | y: number; 27 | toX?: number; 28 | toY?: number; 29 | centerX?: number; 30 | centerY?: number; 31 | fill: string; 32 | radius?: number; 33 | width?: number; 34 | height?: number; 35 | private?: Iresult[]; 36 | } 37 | export interface Iresult { 38 | x: number; 39 | y: number; 40 | fill: string; 41 | } 42 | export interface Istyles { 43 | x: number; 44 | y: number; 45 | width?: number; 46 | height?: number; 47 | fill?: string; 48 | "background-color"?: string; 49 | "text-color"?: string; 50 | "placeholder-color"?: string; 51 | visible: boolean; 52 | check?: Array; 53 | img?: string; 54 | page?: string; 55 | "img-pixels"?: (string | Array); 56 | } 57 | export interface Ievents { 58 | onEnter?: Function; 59 | onPut?: Function; 60 | onLeave?: Function; 61 | onChange?: Function; 62 | onConnect?: (object); 63 | onFrame?: Function; 64 | } 65 | export declare class CLIApplication { 66 | private debug; 67 | private widgets; 68 | private Vwidgets; 69 | private curlocs; 70 | constructor(option?: any); 71 | append(...widgets: Array): void; 72 | private event; 73 | isOverLapping(widget: Iwidget, props: Istyles): boolean | "" | 0 | undefined; 74 | hexbn(hex: string, brightness: number): string; 75 | show(frame: number): void; 76 | find(path: string): Iwidget | undefined; 77 | modify(path: string, props: Iproperties): void; 78 | } 79 | export declare function setProps(get: Iproperties, origin: Iproperties): Iproperties; 80 | -------------------------------------------------------------------------------- /dist/src/lib/CLIApplication.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __importDefault = (this && this.__importDefault) || function (mod) { 3 | return (mod && mod.__esModule) ? mod : { "default": mod }; 4 | }; 5 | Object.defineProperty(exports, "__esModule", { value: true }); 6 | exports.setProps = exports.CLIApplication = void 0; 7 | const chalk_1 = __importDefault(require("chalk")); 8 | class CLIApplication { 9 | constructor(option) { 10 | this.debug = false; 11 | this.widgets = []; 12 | this.Vwidgets = []; 13 | this.curlocs = { 14 | tab: 0, 15 | textloc: 0 16 | }; 17 | this.widgets = []; 18 | this.curlocs = { 19 | tab: 0, 20 | textloc: 0 21 | }; 22 | if (option === null || option === void 0 ? void 0 : option.debug) 23 | this.debug = true; 24 | } 25 | append(...widgets) { 26 | let exists = []; 27 | widgets.forEach((widget) => { 28 | widget.data.properties.paths.forEach((path) => { 29 | if (exists.includes(path)) 30 | throw new Error(`[unique.path] ${path} is already exists`); 31 | exists.push(path); 32 | if (this.find(path)) { 33 | throw new Error(`[unique.path] ${path} is already exists`); 34 | } 35 | }); 36 | }); 37 | this.widgets = this.widgets.concat(widgets); 38 | } 39 | event() { 40 | process.stdin.setRawMode(true); 41 | process.stdin.setEncoding(`utf-8`); 42 | process.stdin.on(`data`, (key) => { 43 | var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z; 44 | if (key === `\u0003`) { 45 | process.stdout.write(`\x1b[${process.stdout.rows - 1};${process.stdout.columns}H`); 46 | process.exit(); 47 | } 48 | const selected = this.Vwidgets[this.curlocs.tab]; 49 | if (selected.isTyping && selected.data.type === `textbox`) { 50 | if (selected.data.properties.text && (this.curlocs.textloc < selected.data.properties.text.length) && key === `\u001b[C`) 51 | this.curlocs.textloc += 1; 52 | if (this.curlocs.textloc > 0 && key === `\u001b[D`) 53 | this.curlocs.textloc -= 1; 54 | if (![`\u001b[D`, `\u001b[C`, `\u0008`, `\r`, `\n`].includes(key)) { 55 | selected.data.properties.text = `${(_a = selected.data.properties.text) === null || _a === void 0 ? void 0 : _a.substring(0, this.curlocs.textloc)}${key}${(_b = selected.data.properties.text) === null || _b === void 0 ? void 0 : _b.substring(this.curlocs.textloc, selected.data.properties.text.length)}`; 56 | this.curlocs.textloc += 1; 57 | } 58 | if (key === `\r` || key === `\n`) { 59 | (_d = (_c = selected.data.properties.defaultEvents) === null || _c === void 0 ? void 0 : _c.onEnter) === null || _d === void 0 ? void 0 : _d.call(_c); 60 | (_f = (_e = selected.data.properties.events) === null || _e === void 0 ? void 0 : _e.onEnter) === null || _f === void 0 ? void 0 : _f.call(_e); 61 | (_h = (_g = selected.data.properties.defaultEvents).onChange) === null || _h === void 0 ? void 0 : _h.call(_g); 62 | (_k = (_j = selected.data.properties.events).onChange) === null || _k === void 0 ? void 0 : _k.call(_j); 63 | } 64 | if (key === `\u0008` && this.curlocs.textloc > 0) { 65 | selected.data.properties.text = `${(_l = selected.data.properties.text) === null || _l === void 0 ? void 0 : _l.substring(0, this.curlocs.textloc - 1)}${(_m = selected.data.properties.text) === null || _m === void 0 ? void 0 : _m.substring(this.curlocs.textloc, selected.data.properties.text.length)}`; 66 | this.curlocs.textloc -= 1; 67 | } 68 | } 69 | else { 70 | if (key === `\u001b[C`) 71 | this.curlocs.tab += 1; 72 | if (key === `\u001b[D`) 73 | this.curlocs.tab -= 1; 74 | if (key === `\u001b[C` || key === `\u001b[D`) { 75 | this.curlocs.textloc = 0; 76 | (_p = (_o = selected.data.properties.events) === null || _o === void 0 ? void 0 : _o.onLeave) === null || _p === void 0 ? void 0 : _p.call(_o); 77 | (_r = (_q = selected.data.properties.defaultEvents) === null || _q === void 0 ? void 0 : _q.onLeave) === null || _r === void 0 ? void 0 : _r.call(_q); 78 | } 79 | if (key === `\r` || key === `\n`) { 80 | this.curlocs.textloc = selected.data.properties.text ? selected.data.properties.text.length : 0; 81 | let result = (_t = (_s = selected.data.properties.defaultEvents) === null || _s === void 0 ? void 0 : _s.onEnter) === null || _t === void 0 ? void 0 : _t.call(_s); 82 | (_v = (_u = selected.data.properties.events) === null || _u === void 0 ? void 0 : _u.onEnter) === null || _v === void 0 ? void 0 : _v.call(_u); 83 | if (selected.data.type === `radio`) 84 | this.widgets = result; 85 | } 86 | } 87 | if (this.curlocs.tab >= this.Vwidgets.length) 88 | this.curlocs.tab = this.Vwidgets.length - 1; 89 | if (this.curlocs.tab < 0) 90 | this.curlocs.tab = 0; 91 | if (selected.data.properties.styles.height !== process.stdout.rows) { 92 | (_x = (_w = selected.data.properties.events) === null || _w === void 0 ? void 0 : _w.onPut) === null || _x === void 0 ? void 0 : _x.call(_w); 93 | (_z = (_y = selected.data.properties.defaultEvents) === null || _y === void 0 ? void 0 : _y.onPut) === null || _z === void 0 ? void 0 : _z.call(_y); 94 | } 95 | }); 96 | process.stdout.write(`\x1B[?25l`); 97 | } 98 | isOverLapping(widget, props) { 99 | const { styles } = widget.data.properties; 100 | return ((styles === null || styles === void 0 ? void 0 : styles.width) && 101 | (styles === null || styles === void 0 ? void 0 : styles.height) && 102 | (styles === null || styles === void 0 ? void 0 : styles["background-color"]) && 103 | (props.x >= styles.x && props.x <= styles.x + styles.width) && 104 | (props.y >= styles.y && props.y <= styles.y + styles.height)); 105 | } 106 | hexbn(hex, brightness) { 107 | hex = hex.replace(/^#/, ``); 108 | if (!/^(?:[0-9a-fA-F]{3}){1,2}$/.test(hex)) 109 | return ``; 110 | let bigint = parseInt(hex, 16); 111 | let rgb = [(bigint >> 16) & 255, (bigint >> 8) & 255, bigint & 255]; 112 | rgb = rgb.map(e => e -= brightness); 113 | rgb = rgb.map(e => Math.max(0, Math.min(255, e))); 114 | let res = rgb.map(e => e.toString(16).padStart(2, `0`)); 115 | const hexColor = `#${res.join(``)}`; 116 | return hexColor; 117 | } 118 | show(frame) { 119 | this.event(); 120 | setInterval(() => { 121 | console.clear(); 122 | if (this.curlocs.tab >= this.Vwidgets.length) 123 | this.curlocs.tab = this.Vwidgets.length - 1; 124 | if (this.curlocs.tab < 0) 125 | this.curlocs.tab = 0; 126 | this.Vwidgets = this.widgets.filter(e => e.data.properties.styles.visible); 127 | this.Vwidgets.forEach((widget, idx) => { 128 | const { type } = widget.data; 129 | const { styles } = widget.data.properties; 130 | let focus = ``; 131 | if (styles.height !== process.stdout.rows && this.curlocs.tab === idx) 132 | focus = chalk_1.default.bgHex(this.hexbn(styles[`background-color`] || styles[`text-color`] || `#ffffff`, 25))(` `); 133 | if (styles.visible && type === `panel`) 134 | widget.prerun(widget, focus); 135 | if (styles.visible && type === `label`) 136 | widget.prerun(this.widgets, widget, this.isOverLapping, focus); 137 | if (styles.visible && type === `button`) 138 | widget.prerun(widget, focus); 139 | if (styles.visible && type === `checkbox`) 140 | widget.prerun(this.widgets, widget, this.isOverLapping, focus); 141 | if (styles.visible && type === `radio`) 142 | widget.prerun(this.widgets, widget, this.isOverLapping, focus); 143 | if (styles.visible && type === `image`) 144 | widget.prerun(widget); 145 | if (styles.visible && type === `textbox`) 146 | widget.prerun(widget, focus, this.curlocs.textloc); 147 | if (styles.visible && type === `canvas`) 148 | widget.prerun(widget); 149 | if (styles.visible && type === `custom`) 150 | widget.prerun(widget, focus, this.widgets, this.isOverLapping, this.curlocs); 151 | if (styles.visible && type === `tcg`) 152 | widget.prerun(widget); 153 | }); 154 | if (this.debug) { 155 | process.stdout.write(`\x1b[1;1H`); 156 | console.log(this.curlocs.tab); 157 | } 158 | }, 1000 / frame); 159 | } 160 | find(path) { 161 | return this.widgets.find(value => value.data.properties.paths.includes(path)); 162 | } 163 | modify(path, props) { 164 | const widgetIdx = this.widgets.findIndex(value => value.data.properties.paths.includes(path)); 165 | this.widgets[widgetIdx].data.properties = setProps(props, this.widgets[widgetIdx].data.properties); 166 | } 167 | } 168 | exports.CLIApplication = CLIApplication; 169 | function setProps(get, origin) { 170 | if (get) 171 | Object.keys(get).forEach((prop) => { 172 | if ((origin === null || origin === void 0 ? void 0 : origin.accepts) && !origin.accepts.includes(prop) && origin.accepts.length !== 0) 173 | return; 174 | if (!Array.isArray(origin[prop]) && typeof origin[prop] === `object`) { 175 | origin[prop] = setProps(get[prop], origin[prop]); 176 | } 177 | else { 178 | const value = get[prop]; 179 | origin[prop] = value; 180 | } 181 | }); 182 | return origin; 183 | } 184 | exports.setProps = setProps; 185 | -------------------------------------------------------------------------------- /dist/src/lib/CLIWidgets/CLIButton.d.ts: -------------------------------------------------------------------------------- 1 | import * as app from "../CLIApplication"; 2 | export declare class CLIButton { 3 | data: app.Idata; 4 | constructor(props?: app.Iproperties); 5 | prerun(widget: app.Iwidget, focus: string): void; 6 | } 7 | -------------------------------------------------------------------------------- /dist/src/lib/CLIWidgets/CLIButton.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { 3 | if (k2 === undefined) k2 = k; 4 | var desc = Object.getOwnPropertyDescriptor(m, k); 5 | if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { 6 | desc = { enumerable: true, get: function() { return m[k]; } }; 7 | } 8 | Object.defineProperty(o, k2, desc); 9 | }) : (function(o, m, k, k2) { 10 | if (k2 === undefined) k2 = k; 11 | o[k2] = m[k]; 12 | })); 13 | var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { 14 | Object.defineProperty(o, "default", { enumerable: true, value: v }); 15 | }) : function(o, v) { 16 | o["default"] = v; 17 | }); 18 | var __importStar = (this && this.__importStar) || function (mod) { 19 | if (mod && mod.__esModule) return mod; 20 | var result = {}; 21 | if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); 22 | __setModuleDefault(result, mod); 23 | return result; 24 | }; 25 | var __importDefault = (this && this.__importDefault) || function (mod) { 26 | return (mod && mod.__esModule) ? mod : { "default": mod }; 27 | }; 28 | Object.defineProperty(exports, "__esModule", { value: true }); 29 | exports.CLIButton = void 0; 30 | const chalk_1 = __importDefault(require("chalk")); 31 | const app = __importStar(require("../CLIApplication")); 32 | class CLIButton { 33 | constructor(props) { 34 | this.data = { 35 | "type": "button", 36 | "properties": { 37 | "text": "lorem ipsum", 38 | "accepts": ["paths", "styles", "events", "text", "global"], 39 | "paths": [], 40 | "global": "", 41 | "styles": { 42 | "x": 1, 43 | "y": 1, 44 | "text-color": "#ffffff", 45 | "visible": true 46 | }, 47 | "events": {}, 48 | "defaultEvents": {} 49 | } 50 | }; 51 | if (props) 52 | this.data.properties = app.setProps(props, this.data.properties); 53 | } 54 | prerun(widget, focus) { 55 | const { styles, text } = widget.data.properties; 56 | if (!styles.fill) 57 | styles.fill = `█`; 58 | process.stdout.write(`\x1b[${styles.y};${styles.x}H`); 59 | if (styles.width) 60 | console.log(focus + chalk_1.default.hex(styles[`background-color`] ? styles[`background-color`] : `#ffffff`)(styles.fill.repeat(styles.width))); 61 | if (styles.height) 62 | for (let i = 0; i < styles.height; i++) { 63 | process.stdout.write(`\x1b[${styles.y + i};${styles.x}H`); 64 | if (styles.width) 65 | console.log(focus + chalk_1.default.hex(styles[`background-color`] ? styles[`background-color`] : `#ffffff`)(styles.fill.repeat(styles.width))); 66 | } 67 | process.stdout.write(`\x1b[${styles.y};${styles.x}H`); 68 | console.log(focus + chalk_1.default.bgHex((styles === null || styles === void 0 ? void 0 : styles[`background-color`]) ? styles[`background-color`] : `#000000`).hex((styles === null || styles === void 0 ? void 0 : styles[`text-color`]) ? styles[`text-color`] : `#ffffff`)(text)); 69 | } 70 | } 71 | exports.CLIButton = CLIButton; 72 | -------------------------------------------------------------------------------- /dist/src/lib/CLIWidgets/CLICanvas.d.ts: -------------------------------------------------------------------------------- 1 | import * as app from "../CLIApplication"; 2 | export declare class CLICanvas { 3 | private lines; 4 | private circles; 5 | private rectangles; 6 | private line; 7 | private circle; 8 | private rectangle; 9 | data: app.Idata; 10 | constructor(props?: app.Iproperties); 11 | prerun(widget: app.Iwidget): void; 12 | } 13 | -------------------------------------------------------------------------------- /dist/src/lib/CLIWidgets/CLICanvas.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { 3 | if (k2 === undefined) k2 = k; 4 | var desc = Object.getOwnPropertyDescriptor(m, k); 5 | if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { 6 | desc = { enumerable: true, get: function() { return m[k]; } }; 7 | } 8 | Object.defineProperty(o, k2, desc); 9 | }) : (function(o, m, k, k2) { 10 | if (k2 === undefined) k2 = k; 11 | o[k2] = m[k]; 12 | })); 13 | var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { 14 | Object.defineProperty(o, "default", { enumerable: true, value: v }); 15 | }) : function(o, v) { 16 | o["default"] = v; 17 | }); 18 | var __importStar = (this && this.__importStar) || function (mod) { 19 | if (mod && mod.__esModule) return mod; 20 | var result = {}; 21 | if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); 22 | __setModuleDefault(result, mod); 23 | return result; 24 | }; 25 | Object.defineProperty(exports, "__esModule", { value: true }); 26 | exports.CLICanvas = void 0; 27 | const app = __importStar(require("../CLIApplication")); 28 | class CLICanvas { 29 | line(object) { 30 | if (!object.toX || !object.toY) 31 | return; 32 | let result = []; 33 | const deltaX = object.toX - object.x; 34 | const deltaY = object.toY - object.y; 35 | const steps = Math.max(Math.abs(deltaX), Math.abs(deltaY)); 36 | for (let i = 0; i <= steps; i++) { 37 | let x, y; 38 | if (deltaX >= 0 && deltaY >= 0) { 39 | x = Math.round(object.x + (i / steps) * Math.abs(deltaX)); 40 | y = Math.round(object.y + (i / steps) * Math.abs(deltaY)); 41 | } 42 | else if (deltaX < 0 && deltaY >= 0) { 43 | x = Math.round(object.x - (i / steps) * Math.abs(deltaX)); 44 | y = Math.round(object.y + (i / steps) * Math.abs(deltaY)); 45 | } 46 | else if (deltaX >= 0 && deltaY < 0) { 47 | x = Math.round(object.x + (i / steps) * Math.abs(deltaX)); 48 | y = Math.round(object.y - (i / steps) * Math.abs(deltaY)); 49 | } 50 | else { // deltaX < 0 && deltaY < 0 51 | x = Math.round(object.x - (i / steps) * Math.abs(deltaX)); 52 | y = Math.round(object.y - (i / steps) * Math.abs(deltaY)); 53 | } 54 | process.stdout.write(`\x1b[${y};${x}H`); 55 | console.log(object.fill); 56 | result.push({ fill: object.fill, x: x, y: y }); 57 | } 58 | return result; 59 | } 60 | circle(object) { 61 | if (!object.centerX || !object.centerY || !object.radius) 62 | return; 63 | let result = []; 64 | for (let y = object.centerY - object.radius; y <= object.centerY + object.radius; y++) { 65 | for (let x = object.centerX - object.radius; x <= object.centerX + object.radius; x++) { 66 | const distance = Math.sqrt((x - object.centerX) ** 2 + (y - object.centerY) ** 2); 67 | if (distance <= object.radius) { 68 | process.stdout.write(`\x1b[${y};${x}H`); 69 | console.log(object.fill); 70 | result.push({ fill: object.fill, x: x, y: y }); 71 | } 72 | } 73 | } 74 | return result; 75 | } 76 | rectangle(object) { 77 | if (!object.height || !object.width) 78 | return; 79 | let result = []; 80 | for (let i = object.y; i < object.y + object.height; i++) { 81 | for (let j = object.x; j < object.x + object.width; j++) { 82 | process.stdout.write(`\x1b[${i};${j}H`); 83 | console.log(object.fill); 84 | result.push({ fill: object.fill, x: j, y: i }); 85 | } 86 | } 87 | return result; 88 | } 89 | constructor(props) { 90 | this.lines = []; 91 | this.circles = []; 92 | this.rectangles = []; 93 | this.data = { 94 | "type": "canvas", 95 | "properties": { 96 | "canvasChilds": [], 97 | "accepts": ["paths", "global", "styles", "events", "defaultEvents", "canvasChilds"], 98 | "paths": [], 99 | "global": "", 100 | "styles": { 101 | "x": 1, 102 | "y": 1, 103 | "width": 20, 104 | "height": 10, 105 | "visible": true 106 | }, 107 | "events": {}, 108 | "defaultEvents": {} 109 | } 110 | }; 111 | if (props) 112 | this.data.properties = app.setProps(props, this.data.properties); 113 | } 114 | prerun(widget) { 115 | var _a; 116 | (_a = widget.data.properties.canvasChilds) === null || _a === void 0 ? void 0 : _a.forEach((child) => { 117 | var _a, _b, _c; 118 | if (child.type === `line`) { 119 | if (this.lines.includes(child)) { 120 | const idx = this.lines.findIndex(e => e === child); 121 | (_a = this.lines[idx].private) === null || _a === void 0 ? void 0 : _a.forEach(_private => { 122 | if (!_private.x || !_private.y) 123 | return; 124 | process.stdout.write(`\x1b[${_private.y};${_private.x}H`); 125 | console.log(_private.fill); 126 | }); 127 | } 128 | else { 129 | child.private = this.line(child); 130 | this.lines.push(child); 131 | } 132 | } 133 | else if (child.type === `rectangle`) { 134 | if (this.rectangles.includes(child)) { 135 | const idx = this.rectangles.findIndex(e => e === child); 136 | (_b = this.rectangles[idx].private) === null || _b === void 0 ? void 0 : _b.forEach(_private => { 137 | if (!_private.x || !_private.y) 138 | return; 139 | process.stdout.write(`\x1b[${_private.y};${_private.x}H`); 140 | console.log(_private.fill); 141 | }); 142 | } 143 | else { 144 | child.private = this.rectangle(child); 145 | this.rectangles.push(child); 146 | } 147 | } 148 | else if (child.type === `circle`) { 149 | if (this.circles.includes(child)) { 150 | const idx = this.circles.findIndex(e => e === child); 151 | (_c = this.circles[idx].private) === null || _c === void 0 ? void 0 : _c.forEach(_private => { 152 | if (!_private.x || !_private.y) 153 | return; 154 | process.stdout.write(`\x1b[${_private.y};${_private.x}H`); 155 | console.log(_private.fill); 156 | }); 157 | } 158 | else { 159 | child.private = this.circle(child); 160 | this.circles.push(child); 161 | } 162 | } 163 | }); 164 | } 165 | } 166 | exports.CLICanvas = CLICanvas; 167 | -------------------------------------------------------------------------------- /dist/src/lib/CLIWidgets/CLICheckbox.d.ts: -------------------------------------------------------------------------------- 1 | import * as app from "../CLIApplication"; 2 | export declare class CLICheckbox { 3 | data: app.Idata; 4 | constructor(props?: app.Iproperties); 5 | prerun(widgets: Array, widget: app.Iwidget, func: Function, focus: string): void; 6 | } 7 | -------------------------------------------------------------------------------- /dist/src/lib/CLIWidgets/CLICheckbox.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { 3 | if (k2 === undefined) k2 = k; 4 | var desc = Object.getOwnPropertyDescriptor(m, k); 5 | if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { 6 | desc = { enumerable: true, get: function() { return m[k]; } }; 7 | } 8 | Object.defineProperty(o, k2, desc); 9 | }) : (function(o, m, k, k2) { 10 | if (k2 === undefined) k2 = k; 11 | o[k2] = m[k]; 12 | })); 13 | var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { 14 | Object.defineProperty(o, "default", { enumerable: true, value: v }); 15 | }) : function(o, v) { 16 | o["default"] = v; 17 | }); 18 | var __importStar = (this && this.__importStar) || function (mod) { 19 | if (mod && mod.__esModule) return mod; 20 | var result = {}; 21 | if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); 22 | __setModuleDefault(result, mod); 23 | return result; 24 | }; 25 | var __importDefault = (this && this.__importDefault) || function (mod) { 26 | return (mod && mod.__esModule) ? mod : { "default": mod }; 27 | }; 28 | Object.defineProperty(exports, "__esModule", { value: true }); 29 | exports.CLICheckbox = void 0; 30 | const chalk_1 = __importDefault(require("chalk")); 31 | const app = __importStar(require("../CLIApplication")); 32 | class CLICheckbox { 33 | constructor(props) { 34 | this.data = { 35 | "type": "checkbox", 36 | "properties": { 37 | "text": "lorem ipsum", 38 | "checked": false, 39 | "accepts": ["paths", "styles", "text", "events", "checked", "global"], 40 | "paths": [], 41 | "global": "", 42 | "styles": { 43 | "x": 1, 44 | "y": 1, 45 | "text-color": "#ffffff", 46 | "visible": true, 47 | "check": ["✅ ", "❌ "] 48 | }, 49 | "events": {}, 50 | "defaultEvents": { 51 | "onEnter": () => { 52 | this.data.properties.checked = !this.data.properties.checked; 53 | } 54 | } 55 | } 56 | }; 57 | if (props) 58 | this.data.properties = app.setProps(props, this.data.properties); 59 | } 60 | prerun(widgets, widget, func, focus) { 61 | var _a, _b; 62 | const { styles, text } = widget.data.properties; 63 | let isOverLapping = false; 64 | widgets.forEach((_widget) => { 65 | var _a, _b; 66 | if (func(_widget, styles)) { 67 | isOverLapping = true; 68 | process.stdout.write(`\x1b[${styles.y};${styles.x}H`); 69 | const backgroundColor = _widget.data.properties.styles["background-color"] || `#000000`; 70 | const textColor = styles["text-color"] || _widget.data.properties.styles["text-color"] || `#ffffff`; 71 | console.log(focus + (this.data.properties.checked ? (_a = styles.check) === null || _a === void 0 ? void 0 : _a[0] : (_b = styles.check) === null || _b === void 0 ? void 0 : _b[1]) + chalk_1.default.bgHex(backgroundColor)(chalk_1.default.hex(textColor)(text))); 72 | } 73 | }); 74 | if (!isOverLapping) { 75 | process.stdout.write(`\x1b[${styles.y};${styles.x}H`); 76 | const backgroundColor = `#000000`; 77 | const textColor = styles["text-color"] || `#ffffff`; 78 | console.log(focus + (this.data.properties.checked ? (_a = styles.check) === null || _a === void 0 ? void 0 : _a[0] : (_b = styles.check) === null || _b === void 0 ? void 0 : _b[1]) + chalk_1.default.bgHex(backgroundColor)(chalk_1.default.hex(textColor)(text))); 79 | } 80 | } 81 | } 82 | exports.CLICheckbox = CLICheckbox; 83 | -------------------------------------------------------------------------------- /dist/src/lib/CLIWidgets/CLICustom.d.ts: -------------------------------------------------------------------------------- 1 | import * as app from "../CLIApplication"; 2 | export declare class CLICustom { 3 | data: app.Idata; 4 | constructor(props?: app.Iproperties); 5 | prerun(widget: app.Iwidget, focus: string, widgets: Array, func: Function, object: any): void; 6 | } 7 | -------------------------------------------------------------------------------- /dist/src/lib/CLIWidgets/CLICustom.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { 3 | if (k2 === undefined) k2 = k; 4 | var desc = Object.getOwnPropertyDescriptor(m, k); 5 | if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { 6 | desc = { enumerable: true, get: function() { return m[k]; } }; 7 | } 8 | Object.defineProperty(o, k2, desc); 9 | }) : (function(o, m, k, k2) { 10 | if (k2 === undefined) k2 = k; 11 | o[k2] = m[k]; 12 | })); 13 | var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { 14 | Object.defineProperty(o, "default", { enumerable: true, value: v }); 15 | }) : function(o, v) { 16 | o["default"] = v; 17 | }); 18 | var __importStar = (this && this.__importStar) || function (mod) { 19 | if (mod && mod.__esModule) return mod; 20 | var result = {}; 21 | if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); 22 | __setModuleDefault(result, mod); 23 | return result; 24 | }; 25 | Object.defineProperty(exports, "__esModule", { value: true }); 26 | exports.CLICustom = void 0; 27 | const app = __importStar(require("../CLIApplication")); 28 | class CLICustom { 29 | constructor(props) { 30 | this.data = { 31 | "type": "custom", 32 | "properties": { 33 | "accepts": ["accepts", "paths", "global", "styles", "events", "defaultEvents", "text", "placeholder", "checked"], 34 | "paths": [], 35 | "global": "", 36 | "styles": { 37 | "x": 1, 38 | "y": 1, 39 | "visible": true 40 | }, 41 | "events": {}, 42 | "defaultEvents": {} 43 | } 44 | }; 45 | if (props) 46 | this.data.properties = app.setProps(props, this.data.properties); 47 | } 48 | prerun(widget, focus, widgets, func, object) { } 49 | } 50 | exports.CLICustom = CLICustom; 51 | -------------------------------------------------------------------------------- /dist/src/lib/CLIWidgets/CLIImage.d.ts: -------------------------------------------------------------------------------- 1 | import * as app from "../CLIApplication"; 2 | export declare class CLIImage { 3 | private text; 4 | private isDoing; 5 | data: app.Idata; 6 | constructor(props?: app.Iproperties); 7 | prerun(widget: app.Iwidget): void; 8 | } 9 | -------------------------------------------------------------------------------- /dist/src/lib/CLIWidgets/CLIImage.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { 3 | if (k2 === undefined) k2 = k; 4 | var desc = Object.getOwnPropertyDescriptor(m, k); 5 | if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { 6 | desc = { enumerable: true, get: function() { return m[k]; } }; 7 | } 8 | Object.defineProperty(o, k2, desc); 9 | }) : (function(o, m, k, k2) { 10 | if (k2 === undefined) k2 = k; 11 | o[k2] = m[k]; 12 | })); 13 | var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { 14 | Object.defineProperty(o, "default", { enumerable: true, value: v }); 15 | }) : function(o, v) { 16 | o["default"] = v; 17 | }); 18 | var __importStar = (this && this.__importStar) || function (mod) { 19 | if (mod && mod.__esModule) return mod; 20 | var result = {}; 21 | if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); 22 | __setModuleDefault(result, mod); 23 | return result; 24 | }; 25 | var __importDefault = (this && this.__importDefault) || function (mod) { 26 | return (mod && mod.__esModule) ? mod : { "default": mod }; 27 | }; 28 | Object.defineProperty(exports, "__esModule", { value: true }); 29 | exports.CLIImage = void 0; 30 | const image_to_ascii_1 = __importDefault(require("image-to-ascii")); 31 | const app = __importStar(require("../CLIApplication")); 32 | class CLIImage { 33 | constructor(props) { 34 | this.text = ``; 35 | this.isDoing = false; 36 | this.data = { 37 | "type": "image", 38 | "properties": { 39 | "accepts": ["paths", "styles", "global"], 40 | "paths": [], 41 | "global": "", 42 | "styles": { 43 | "x": 1, 44 | "y": 1, 45 | "width": 50, 46 | "height": 50, 47 | "visible": true, 48 | "img": "", 49 | "img-pixels": " " 50 | }, 51 | "events": {}, 52 | "defaultEvents": {} 53 | } 54 | }; 55 | if (props) 56 | this.data.properties = app.setProps(props, this.data.properties); 57 | } 58 | prerun(widget) { 59 | const { styles } = widget.data.properties; 60 | if (this.text !== ``) { 61 | this.text.split(`\n`).forEach((line, idx) => { 62 | process.stdout.write(`\x1b[${styles.y + idx};${styles.x}H`); 63 | console.log(line); 64 | }); 65 | } 66 | else if (!this.isDoing) { 67 | this.isDoing = true; 68 | (0, image_to_ascii_1.default)(styles.img, { 69 | size: { 70 | width: styles.width, 71 | height: styles.height 72 | }, 73 | bg: true, 74 | fg: false, 75 | pixels: styles["img-pixels"] 76 | }, (err, converted) => { 77 | if (err) 78 | throw new Error(err); 79 | this.text = converted; 80 | }); 81 | } 82 | } 83 | } 84 | exports.CLIImage = CLIImage; 85 | -------------------------------------------------------------------------------- /dist/src/lib/CLIWidgets/CLILabel.d.ts: -------------------------------------------------------------------------------- 1 | import * as app from "../CLIApplication"; 2 | export declare class CLILabel { 3 | data: app.Idata; 4 | constructor(props?: app.Iproperties); 5 | prerun(widgets: Array, widget: app.Iwidget, func: Function, focus: string): void; 6 | } 7 | -------------------------------------------------------------------------------- /dist/src/lib/CLIWidgets/CLILabel.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { 3 | if (k2 === undefined) k2 = k; 4 | var desc = Object.getOwnPropertyDescriptor(m, k); 5 | if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { 6 | desc = { enumerable: true, get: function() { return m[k]; } }; 7 | } 8 | Object.defineProperty(o, k2, desc); 9 | }) : (function(o, m, k, k2) { 10 | if (k2 === undefined) k2 = k; 11 | o[k2] = m[k]; 12 | })); 13 | var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { 14 | Object.defineProperty(o, "default", { enumerable: true, value: v }); 15 | }) : function(o, v) { 16 | o["default"] = v; 17 | }); 18 | var __importStar = (this && this.__importStar) || function (mod) { 19 | if (mod && mod.__esModule) return mod; 20 | var result = {}; 21 | if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); 22 | __setModuleDefault(result, mod); 23 | return result; 24 | }; 25 | var __importDefault = (this && this.__importDefault) || function (mod) { 26 | return (mod && mod.__esModule) ? mod : { "default": mod }; 27 | }; 28 | Object.defineProperty(exports, "__esModule", { value: true }); 29 | exports.CLILabel = void 0; 30 | const chalk_1 = __importDefault(require("chalk")); 31 | const app = __importStar(require("../CLIApplication")); 32 | class CLILabel { 33 | constructor(props) { 34 | this.data = { 35 | "type": "label", 36 | "properties": { 37 | "text": "lorem ipsum", 38 | "accepts": ["paths", "styles", "text", "global"], 39 | "paths": [], 40 | "global": "", 41 | "styles": { 42 | "x": 1, 43 | "y": 1, 44 | "text-color": "#ffffff", 45 | "visible": true 46 | }, 47 | "events": {}, 48 | "defaultEvents": {} 49 | } 50 | }; 51 | if (props) 52 | this.data.properties = app.setProps(props, this.data.properties); 53 | } 54 | prerun(widgets, widget, func, focus) { 55 | const { styles, text } = widget.data.properties; 56 | let isOverLapping = false; 57 | widgets.forEach((_widget) => { 58 | if (func(_widget, styles)) { 59 | isOverLapping = true; 60 | process.stdout.write(`\x1b[${styles.y};${styles.x}H`); 61 | const backgroundColor = _widget.data.properties.styles["background-color"] || `#000000`; 62 | const textColor = styles["text-color"] || _widget.data.properties.styles["text-color"] || `#ffffff`; 63 | console.log(focus + chalk_1.default.bgHex(backgroundColor)(chalk_1.default.hex(textColor)(text))); 64 | } 65 | }); 66 | if (!isOverLapping) { 67 | process.stdout.write(`\x1b[${styles.y};${styles.x}H`); 68 | const backgroundColor = `#000000`; 69 | const textColor = styles["text-color"] || `#ffffff`; 70 | console.log(focus + chalk_1.default.bgHex(backgroundColor)(chalk_1.default.hex(textColor)(text))); 71 | } 72 | } 73 | } 74 | exports.CLILabel = CLILabel; 75 | -------------------------------------------------------------------------------- /dist/src/lib/CLIWidgets/CLIPanel.d.ts: -------------------------------------------------------------------------------- 1 | import * as app from "../CLIApplication"; 2 | export declare class CLIPanel { 3 | data: app.Idata; 4 | constructor(props?: app.Iproperties); 5 | prerun(widget: app.Iwidget, focus: string): void; 6 | } 7 | -------------------------------------------------------------------------------- /dist/src/lib/CLIWidgets/CLIPanel.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { 3 | if (k2 === undefined) k2 = k; 4 | var desc = Object.getOwnPropertyDescriptor(m, k); 5 | if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { 6 | desc = { enumerable: true, get: function() { return m[k]; } }; 7 | } 8 | Object.defineProperty(o, k2, desc); 9 | }) : (function(o, m, k, k2) { 10 | if (k2 === undefined) k2 = k; 11 | o[k2] = m[k]; 12 | })); 13 | var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { 14 | Object.defineProperty(o, "default", { enumerable: true, value: v }); 15 | }) : function(o, v) { 16 | o["default"] = v; 17 | }); 18 | var __importStar = (this && this.__importStar) || function (mod) { 19 | if (mod && mod.__esModule) return mod; 20 | var result = {}; 21 | if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); 22 | __setModuleDefault(result, mod); 23 | return result; 24 | }; 25 | var __importDefault = (this && this.__importDefault) || function (mod) { 26 | return (mod && mod.__esModule) ? mod : { "default": mod }; 27 | }; 28 | Object.defineProperty(exports, "__esModule", { value: true }); 29 | exports.CLIPanel = void 0; 30 | const chalk_1 = __importDefault(require("chalk")); 31 | const app = __importStar(require("../CLIApplication")); 32 | class CLIPanel { 33 | constructor(props) { 34 | this.data = { 35 | "type": "panel", 36 | "properties": { 37 | "accepts": ["paths", "styles", "global"], 38 | "paths": [], 39 | "global": "", 40 | "styles": { 41 | "x": 0, 42 | "y": 0, 43 | "width": process.stdout.columns, 44 | "height": process.stdout.rows, 45 | "fill": "█", 46 | "background-color": "#000000", 47 | "text-color": "#ffffff", 48 | "visible": true 49 | }, 50 | "events": {}, 51 | "defaultEvents": {} 52 | } 53 | }; 54 | if (props) 55 | this.data.properties = app.setProps(props, this.data.properties); 56 | } 57 | prerun(widget, focus) { 58 | const { styles } = widget.data.properties; 59 | if (!styles.fill) 60 | styles.fill = `█`; 61 | process.stdout.write(`\x1b[${styles.y};${styles.x}H`); 62 | if (styles.width) 63 | console.log(focus + chalk_1.default.hex(styles[`background-color`] ? styles[`background-color`] : `#ffffff`)(styles.fill.repeat(styles.width))); 64 | if (styles.height) 65 | for (let i = 0; i < styles.height; i++) { 66 | process.stdout.write(`\x1b[${styles.y + i};${styles.x}H`); 67 | if (styles.width) 68 | console.log(focus + chalk_1.default.hex(styles[`background-color`] ? styles[`background-color`] : `#ffffff`)(styles.fill.repeat(styles.width))); 69 | } 70 | } 71 | } 72 | exports.CLIPanel = CLIPanel; 73 | -------------------------------------------------------------------------------- /dist/src/lib/CLIWidgets/CLIRadio.d.ts: -------------------------------------------------------------------------------- 1 | import * as app from "../CLIApplication"; 2 | export declare class CLIRadio { 3 | private widgets; 4 | data: app.Idata; 5 | constructor(props?: app.Iproperties); 6 | prerun(widgets: Array, widget: app.Iwidget, func: Function, focus: string): void; 7 | } 8 | -------------------------------------------------------------------------------- /dist/src/lib/CLIWidgets/CLIRadio.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { 3 | if (k2 === undefined) k2 = k; 4 | var desc = Object.getOwnPropertyDescriptor(m, k); 5 | if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { 6 | desc = { enumerable: true, get: function() { return m[k]; } }; 7 | } 8 | Object.defineProperty(o, k2, desc); 9 | }) : (function(o, m, k, k2) { 10 | if (k2 === undefined) k2 = k; 11 | o[k2] = m[k]; 12 | })); 13 | var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { 14 | Object.defineProperty(o, "default", { enumerable: true, value: v }); 15 | }) : function(o, v) { 16 | o["default"] = v; 17 | }); 18 | var __importStar = (this && this.__importStar) || function (mod) { 19 | if (mod && mod.__esModule) return mod; 20 | var result = {}; 21 | if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); 22 | __setModuleDefault(result, mod); 23 | return result; 24 | }; 25 | var __importDefault = (this && this.__importDefault) || function (mod) { 26 | return (mod && mod.__esModule) ? mod : { "default": mod }; 27 | }; 28 | Object.defineProperty(exports, "__esModule", { value: true }); 29 | exports.CLIRadio = void 0; 30 | const chalk_1 = __importDefault(require("chalk")); 31 | const app = __importStar(require("../CLIApplication")); 32 | class CLIRadio { 33 | constructor(props) { 34 | this.widgets = []; 35 | this.data = { 36 | "type": "radio", 37 | "properties": { 38 | "text": "lorem ipsum", 39 | "checked": false, 40 | "accepts": ["paths", "styles", "text", "events", "checked", "global"], 41 | "paths": [], 42 | "global": "default", 43 | "styles": { 44 | "x": 1, 45 | "y": 1, 46 | "text-color": "#ffffff", 47 | "visible": true, 48 | "check": ["⚪ ", "⚫ "] 49 | }, 50 | "events": {}, 51 | "defaultEvents": { 52 | "onEnter": () => { 53 | this.widgets.map((e) => e.data.properties.checked = e.data.properties.global === this.data.properties.global ? false : e.data.properties.checked); 54 | this.data.properties.checked = !this.data.properties.checked; 55 | return this.widgets; 56 | } 57 | } 58 | } 59 | }; 60 | if (props) 61 | this.data.properties = app.setProps(props, this.data.properties); 62 | } 63 | prerun(widgets, widget, func, focus) { 64 | var _a, _b; 65 | const { styles, text } = widget.data.properties; 66 | this.widgets = widgets; 67 | let isOverLapping = false; 68 | widgets.forEach((_widget) => { 69 | var _a, _b; 70 | if (func(_widget, styles)) { 71 | isOverLapping = true; 72 | process.stdout.write(`\x1b[${styles.y};${styles.x}H`); 73 | const backgroundColor = _widget.data.properties.styles["background-color"] || `#000000`; 74 | const textColor = styles["text-color"] || _widget.data.properties.styles["text-color"] || `#ffffff`; 75 | console.log(focus + (this.data.properties.checked ? (_a = styles.check) === null || _a === void 0 ? void 0 : _a[0] : (_b = styles.check) === null || _b === void 0 ? void 0 : _b[1]) + chalk_1.default.bgHex(backgroundColor)(chalk_1.default.hex(textColor)(text))); 76 | } 77 | }); 78 | if (!isOverLapping) { 79 | process.stdout.write(`\x1b[${styles.y};${styles.x}H`); 80 | const backgroundColor = `#000000`; 81 | const textColor = styles["text-color"] || `#ffffff`; 82 | console.log(focus + (this.data.properties.checked ? (_a = styles.check) === null || _a === void 0 ? void 0 : _a[0] : (_b = styles.check) === null || _b === void 0 ? void 0 : _b[1]) + chalk_1.default.bgHex(backgroundColor)(chalk_1.default.hex(textColor)(text))); 83 | } 84 | } 85 | } 86 | exports.CLIRadio = CLIRadio; 87 | -------------------------------------------------------------------------------- /dist/src/lib/CLIWidgets/CLITextbox.d.ts: -------------------------------------------------------------------------------- 1 | import * as app from "../CLIApplication"; 2 | export declare class CLITextbox { 3 | isTyping: boolean; 4 | data: app.Idata; 5 | constructor(props?: app.Iproperties); 6 | prerun(widget: app.Iwidget, focus: string, textloc: number): void; 7 | } 8 | -------------------------------------------------------------------------------- /dist/src/lib/CLIWidgets/CLITextbox.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { 3 | if (k2 === undefined) k2 = k; 4 | var desc = Object.getOwnPropertyDescriptor(m, k); 5 | if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { 6 | desc = { enumerable: true, get: function() { return m[k]; } }; 7 | } 8 | Object.defineProperty(o, k2, desc); 9 | }) : (function(o, m, k, k2) { 10 | if (k2 === undefined) k2 = k; 11 | o[k2] = m[k]; 12 | })); 13 | var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { 14 | Object.defineProperty(o, "default", { enumerable: true, value: v }); 15 | }) : function(o, v) { 16 | o["default"] = v; 17 | }); 18 | var __importStar = (this && this.__importStar) || function (mod) { 19 | if (mod && mod.__esModule) return mod; 20 | var result = {}; 21 | if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); 22 | __setModuleDefault(result, mod); 23 | return result; 24 | }; 25 | var __importDefault = (this && this.__importDefault) || function (mod) { 26 | return (mod && mod.__esModule) ? mod : { "default": mod }; 27 | }; 28 | Object.defineProperty(exports, "__esModule", { value: true }); 29 | exports.CLITextbox = void 0; 30 | const chalk_1 = __importDefault(require("chalk")); 31 | const app = __importStar(require("../CLIApplication")); 32 | class CLITextbox { 33 | constructor(props) { 34 | this.isTyping = false; 35 | this.data = { 36 | "type": "textbox", 37 | "properties": { 38 | "text": "", 39 | "placeholder": "", 40 | "accepts": ["paths", "styles", "global", "text", "placeholder", "events"], 41 | "paths": [], 42 | "global": "", 43 | "styles": { 44 | "x": 1, 45 | "y": 1, 46 | "background-color": "#ffffff", 47 | "placeholder-color": "#777777", 48 | "text-color": "#000000", 49 | "visible": true 50 | }, 51 | "events": {}, 52 | "defaultEvents": { 53 | "onEnter": () => { 54 | this.isTyping = !this.isTyping; 55 | } 56 | } 57 | } 58 | }; 59 | if (props) 60 | this.data.properties = app.setProps(props, this.data.properties); 61 | } 62 | prerun(widget, focus, textloc) { 63 | const { styles, text, placeholder } = widget.data.properties; 64 | const backgroundColor = styles["background-color"] || `#ffffff`; 65 | const placeholderColor = styles["placeholder-color"] || `#777777`; 66 | const textColor = styles["text-color"] || `#000000`; 67 | if (this.isTyping) { 68 | process.stdout.write(`\x1b[${styles.y};${styles.x}H`); 69 | console.log(focus + (text === `` ? chalk_1.default.bgHex(backgroundColor)(chalk_1.default.hex(placeholderColor)(placeholder)) : chalk_1.default.bgHex(backgroundColor)(chalk_1.default.hex(textColor)(`${text === null || text === void 0 ? void 0 : text.substring(0, textloc)}|${text === null || text === void 0 ? void 0 : text.substring(textloc, text.length)}`)))); 70 | } 71 | else { 72 | process.stdout.write(`\x1b[${styles.y};${styles.x}H`); 73 | console.log(focus + (text === `` ? chalk_1.default.bgHex(backgroundColor)(chalk_1.default.hex(placeholderColor)(placeholder)) : chalk_1.default.bgHex(backgroundColor)(chalk_1.default.hex(textColor)(text)))); 74 | } 75 | } 76 | } 77 | exports.CLITextbox = CLITextbox; 78 | -------------------------------------------------------------------------------- /dist/src/lib/CLIWidgets/CLIWebview.d.ts: -------------------------------------------------------------------------------- 1 | import * as app from "../CLIApplication"; 2 | export declare class CLIWebview { 3 | private text; 4 | private isDoing; 5 | data: app.Idata; 6 | constructor(props?: app.Iproperties); 7 | prerun(widget: app.Iwidget): void; 8 | } 9 | -------------------------------------------------------------------------------- /dist/src/lib/CLIWidgets/CLIWebview.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { 3 | if (k2 === undefined) k2 = k; 4 | var desc = Object.getOwnPropertyDescriptor(m, k); 5 | if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { 6 | desc = { enumerable: true, get: function() { return m[k]; } }; 7 | } 8 | Object.defineProperty(o, k2, desc); 9 | }) : (function(o, m, k, k2) { 10 | if (k2 === undefined) k2 = k; 11 | o[k2] = m[k]; 12 | })); 13 | var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { 14 | Object.defineProperty(o, "default", { enumerable: true, value: v }); 15 | }) : function(o, v) { 16 | o["default"] = v; 17 | }); 18 | var __importStar = (this && this.__importStar) || function (mod) { 19 | if (mod && mod.__esModule) return mod; 20 | var result = {}; 21 | if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); 22 | __setModuleDefault(result, mod); 23 | return result; 24 | }; 25 | var __importDefault = (this && this.__importDefault) || function (mod) { 26 | return (mod && mod.__esModule) ? mod : { "default": mod }; 27 | }; 28 | Object.defineProperty(exports, "__esModule", { value: true }); 29 | exports.CLIWebview = void 0; 30 | const puppeteer_1 = __importDefault(require("puppeteer")); 31 | const image_to_ascii_1 = __importDefault(require("image-to-ascii")); 32 | const app = __importStar(require("../CLIApplication")); 33 | class CLIWebview { 34 | constructor(props) { 35 | this.text = ``; 36 | this.isDoing = false; 37 | this.data = { 38 | "type": "image", 39 | "properties": { 40 | "accepts": ["paths", "styles", "global"], 41 | "paths": [], 42 | "global": "", 43 | "styles": { 44 | "x": 1, 45 | "y": 1, 46 | "visible": true, 47 | "img": "", 48 | "img-pixels": " ", 49 | "page": "https://www.google.com" 50 | }, 51 | "events": {}, 52 | "defaultEvents": {} 53 | } 54 | }; 55 | if (props) 56 | this.data.properties = app.setProps(props, this.data.properties); 57 | } 58 | prerun(widget) { 59 | const { styles, events } = widget.data.properties; 60 | if (this.text !== ``) { 61 | this.text.split(`\n`).forEach((line, idx) => { 62 | process.stdout.write(`\x1b[${styles.y + idx};${styles.x}H`); 63 | console.log(line); 64 | }); 65 | } 66 | else if (!this.isDoing) { 67 | this.isDoing = true; 68 | const browser = puppeteer_1.default.launch(); 69 | const page = browser.then(value => value.newPage()); 70 | page.then(value => { 71 | var _a; 72 | if (typeof events.onConnect === `function`) 73 | (_a = events.onConnect) === null || _a === void 0 ? void 0 : _a.call(events, value, () => { 74 | if (this.text === ``) { 75 | value.waitForTimeout(2000).then(() => { 76 | value.screenshot({ path: `browse.png` }).then(() => { 77 | styles.img = `browse.png`; 78 | (0, image_to_ascii_1.default)(styles.img, { 79 | size: { 80 | width: styles.width, 81 | height: styles.height 82 | }, 83 | bg: true, 84 | fg: false, 85 | pixels: styles["img-pixels"] 86 | }, (err, converted) => { 87 | if (err) 88 | throw new Error(err); 89 | this.text = converted; 90 | }); 91 | }); 92 | }); 93 | } 94 | }); 95 | // if (styles.page) value.goto(styles.page).then(() => { 96 | // value.type(`textarea[type="search"]`, `sans`).then(() => { 97 | // value.click(`body > div > div > form > div:nth-child(1) > div > div > center > input`).then(() => { 98 | // value.waitForTimeout(2000).then(() => { 99 | // value.screenshot({ path: `browse.png` }).then(() => { 100 | // styles.img = `browse.png`; 101 | // imageToAscii(styles.img, { 102 | // size: { 103 | // width: styles.width, 104 | // height: styles.height 105 | // }, 106 | // bg: true, 107 | // fg: false, 108 | // pixels: styles["img-pixels"] 109 | // }, (err: string, converted: string) => { 110 | // if (err) throw new Error(err); 111 | // this.text = converted; 112 | // }); 113 | // }); 114 | // }); 115 | // }); 116 | // }); 117 | // }); 118 | }); 119 | } 120 | } 121 | } 122 | exports.CLIWebview = CLIWebview; 123 | -------------------------------------------------------------------------------- /imgs/dog.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ICe1BotMaker/linterf/31a5ba11c5bbf7bfb9c43a8d2f89cec32a6269be/imgs/dog.jpg -------------------------------------------------------------------------------- /imgs/tcg.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ICe1BotMaker/linterf/31a5ba11c5bbf7bfb9c43a8d2f89cec32a6269be/imgs/tcg.gif -------------------------------------------------------------------------------- /imgs/video.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ICe1BotMaker/linterf/31a5ba11c5bbf7bfb9c43a8d2f89cec32a6269be/imgs/video.gif -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "linterf", 3 | "version": "3.0.25", 4 | "description": "Line interface for easier use of cli", 5 | "main": "dist/src/index.js", 6 | "author": "ice1", 7 | "license": "Apache-2.0", 8 | "dependencies": { 9 | "@typescript-eslint/parser": "^6.11.0", 10 | "chalk": "^4.1.2", 11 | "eslint": "^8.53.0", 12 | "image-to-ascii": "^3.2.0", 13 | "puppeteer": "^21.5.1", 14 | "typescript": "^5.2.2" 15 | }, 16 | "devDependencies": { 17 | "@babel/cli": "^7.23.0", 18 | "@babel/core": "^7.23.2", 19 | "@babel/plugin-syntax-jsx": "^7.22.5", 20 | "@babel/plugin-transform-react-jsx": "^7.22.15", 21 | "@babel/preset-env": "^7.23.2", 22 | "@babel/preset-react": "^7.22.15", 23 | "@types/ascii-art": "^1.4.3" 24 | }, 25 | "scripts": { 26 | "test": "npx babel tests --out-dir tests" 27 | }, 28 | "publishConfig": { 29 | "@ice1:registry": "https://npm.pkg.github.com" 30 | }, 31 | "repository": "https://github.com/ICe1BotMaker/linterf", 32 | "keywords": [ 33 | "linterf", 34 | "cli", 35 | "3d", 36 | "argument", 37 | "argv", 38 | "args" 39 | ] 40 | } 41 | -------------------------------------------------------------------------------- /scripts/TCG nobuffer.ts: -------------------------------------------------------------------------------- 1 | import chalk from "chalk"; 2 | import * as app from '../src/lib/CLIApplication'; 3 | 4 | export interface Iobject { 5 | id: string; 6 | center: Iposition; 7 | rotation: Iposition; 8 | vertices: Iposition[]; 9 | } 10 | 11 | export interface Iposition { 12 | x: number; 13 | y: number; 14 | z: number; 15 | } 16 | 17 | export class TCG { 18 | public data: app.Idata = { 19 | "type": "tcg", 20 | "properties": { 21 | "accepts": ["accepts", "paths", "global", "styles", "events", "defaultEvents", "text", "placeholder", "checked"], 22 | "paths": [], 23 | "global": "", 24 | "styles": { 25 | "x": 1, 26 | "y": 1, 27 | "visible": true 28 | }, 29 | "events": {}, 30 | "defaultEvents": {} 31 | } 32 | }; 33 | 34 | public camera: Iposition = { x: 1, y: -1, z: 0 }; 35 | public objects: Iobject[] = []; 36 | 37 | public constructor(objects: Iobject[], props?: app.Iproperties) { 38 | this.objects = this.objects.concat(objects); 39 | 40 | if (props) this.data.properties = app.setProps(props, this.data.properties); 41 | } 42 | 43 | private rotateX(point: Iposition, angle: number, center: Iposition): Iposition { 44 | const y = (point.y - center.y) * Math.cos(angle) - (point.z - center.z) * Math.sin(angle) + center.y; 45 | const z = (point.y - center.y) * Math.sin(angle) + (point.z - center.z) * Math.cos(angle) + center.z; 46 | return { ...point, y, z }; 47 | } 48 | 49 | private rotateY(point: Iposition, angle: number, center: Iposition): Iposition { 50 | const x = (point.x - center.x) * Math.cos(angle) + (point.z - center.z) * Math.sin(angle) + center.x; 51 | const z = -(point.x - center.x) * Math.sin(angle) + (point.z - center.z) * Math.cos(angle) + center.z; 52 | return { ...point, x, z }; 53 | } 54 | 55 | private rotateZ(point: Iposition, angle: number, center: Iposition): Iposition { 56 | const x = (point.x - center.x) * Math.cos(angle) - (point.y - center.y) * Math.sin(angle) + center.x; 57 | const y = (point.x - center.x) * Math.sin(angle) + (point.y - center.y) * Math.cos(angle) + center.y; 58 | return { ...point, x, y }; 59 | } 60 | 61 | private draw() { 62 | process.stdout.write('\x1Bc'); 63 | 64 | this.objects.forEach(object => { 65 | let rotatedVertices = object.vertices.map(point => 66 | this.rotateX(this.rotateY(this.rotateZ(point, object.rotation.z, object.center), object.rotation.y, object.center), object.rotation.x, object.center) 67 | ); 68 | 69 | let translatedVertices = rotatedVertices.map(point => ({ 70 | x: point.x - this.camera.x, 71 | y: point.y - this.camera.y, 72 | z: point.z - this.camera.z 73 | })); 74 | 75 | this.connectAndDraw([0, 1, 3, 2], translatedVertices); 76 | this.connectAndDraw([4, 5, 7, 6], translatedVertices); 77 | this.connectAndDraw([0, 1, 5, 4], translatedVertices); 78 | this.connectAndDraw([2, 3, 7, 6], translatedVertices); 79 | this.connectAndDraw([0, 2, 6, 4], translatedVertices); 80 | this.connectAndDraw([1, 3, 7, 5], translatedVertices); 81 | }); 82 | } 83 | 84 | private connectAndDraw(faceVertices: any, vertices: any) { 85 | for (let i = 0; i < faceVertices.length; i++) { 86 | const start = faceVertices[i]; 87 | const end = faceVertices[(i + 1) % faceVertices.length]; 88 | 89 | const startPoint = vertices[start]; 90 | const endPoint = vertices[end]; 91 | 92 | const startScreenX = Math.round(startPoint.x * 10) + 40; 93 | const startScreenY = Math.round(startPoint.y * 10) + 5; 94 | const endScreenX = Math.round(endPoint.x * 10) + 40; 95 | const endScreenY = Math.round(endPoint.y * 10) + 5; 96 | 97 | this.drawLine(startScreenX, startScreenY, endScreenX, endScreenY); 98 | } 99 | } 100 | 101 | private drawLine(x0: number, y0: number, x1: number, y1: number) { 102 | const dx = Math.abs(x1 - x0); 103 | const dy = Math.abs(y1 - y0); 104 | const sx = x0 < x1 ? 1 : -1; 105 | const sy = y0 < y1 ? 1 : -1; 106 | let err = dx - dy; 107 | 108 | while (true) { 109 | process.stdout.cursorTo(x0 - 20, y0 - 10); 110 | process.stdout.write(chalk.white('█')); 111 | 112 | if (x0 === x1 && y0 === y1) break; 113 | const e2 = 2 * err; 114 | if (e2 > -dy) { 115 | err -= dy; 116 | x0 += sx; 117 | } 118 | if (e2 < dx) { 119 | err += dx; 120 | y0 += sy; 121 | } 122 | } 123 | } 124 | 125 | public prerun(widget: app.Iwidget) { 126 | const { events } = widget.data.properties; 127 | events.onFrame?.(this.objects, this.camera); 128 | this.draw(); 129 | } 130 | } -------------------------------------------------------------------------------- /scripts/TCG origin.ts: -------------------------------------------------------------------------------- 1 | import chalk from "chalk"; 2 | import * as app from '../src/lib/CLIApplication'; 3 | 4 | export interface Iobject { 5 | id: string; 6 | center: Iposition; 7 | rotation: Iposition; 8 | vertices: Iposition[]; 9 | 10 | buffer: { 11 | buffer1: any[]; 12 | buffer2: any[]; 13 | buffer3: any[]; 14 | currentBuffer: any[]; 15 | }; 16 | } 17 | 18 | export interface Iposition { 19 | x: number; 20 | y: number; 21 | z: number; 22 | } 23 | 24 | export class TCG { 25 | public data: app.Idata = { 26 | "type": "tcg", 27 | "properties": { 28 | "accepts": ["accepts", "paths", "global", "styles", "events", "defaultEvents", "text", "placeholder", "checked"], 29 | "paths": [], 30 | "global": "", 31 | "styles": { 32 | "x": 1, 33 | "y": 1, 34 | "visible": true 35 | }, 36 | "events": {}, 37 | "defaultEvents": {} 38 | } 39 | }; 40 | 41 | public camera: Iposition = { x: 1, y: -1, z: 0 }; 42 | public objects: Iobject[] = []; 43 | 44 | public constructor(objects: Iobject[], props?: app.Iproperties) { 45 | objects = objects.map(e => { 46 | e.buffer = { buffer1: [], buffer2: [], buffer3: [], currentBuffer: [] }; 47 | return e; 48 | }); 49 | 50 | this.objects = this.objects.concat(objects); 51 | 52 | if (props) this.data.properties = app.setProps(props, this.data.properties); 53 | } 54 | 55 | private rotateX(point: Iposition, angle: number, center: Iposition): Iposition { 56 | const y = (point.y - center.y) * Math.cos(angle) - (point.z - center.z) * Math.sin(angle) + center.y; 57 | const z = (point.y - center.y) * Math.sin(angle) + (point.z - center.z) * Math.cos(angle) + center.z; 58 | return { ...point, y, z }; 59 | } 60 | 61 | private rotateY(point: Iposition, angle: number, center: Iposition): Iposition { 62 | const x = (point.x - center.x) * Math.cos(angle) + (point.z - center.z) * Math.sin(angle) + center.x; 63 | const z = -(point.x - center.x) * Math.sin(angle) + (point.z - center.z) * Math.cos(angle) + center.z; 64 | return { ...point, x, z }; 65 | } 66 | 67 | private rotateZ(point: Iposition, angle: number, center: Iposition): Iposition { 68 | const x = (point.x - center.x) * Math.cos(angle) - (point.y - center.y) * Math.sin(angle) + center.x; 69 | const y = (point.x - center.x) * Math.sin(angle) + (point.y - center.y) * Math.cos(angle) + center.y; 70 | return { ...point, x, y }; 71 | } 72 | 73 | private drawToBuffer(buffer: any[], x: number, y: number, char: any) { 74 | if (!buffer[y]) buffer[y] = []; 75 | buffer[y][x] = char; 76 | } 77 | 78 | private swapBuffers(object: Iobject) { 79 | if (object.buffer.currentBuffer === object.buffer.buffer1) { 80 | object.buffer.currentBuffer = object.buffer.buffer2; 81 | } else if (object.buffer.currentBuffer === object.buffer.buffer2) { 82 | object.buffer.currentBuffer = object.buffer.buffer3; 83 | } else { 84 | object.buffer.currentBuffer = object.buffer.buffer1; 85 | } 86 | } 87 | 88 | private drawBufferToConsole(buffer: any[]) { 89 | for (let row of buffer) if (row) process.stdout.write(row.join('') + '\n'); 90 | } 91 | 92 | private clearBuffer(buffer: any[]) { 93 | for (let i = 0; i < buffer.length; i++) buffer[i] = []; 94 | } 95 | 96 | private draw() { 97 | process.stdout.write('\x1Bc'); 98 | 99 | this.objects.forEach(object => { 100 | if (!object.buffer) object.buffer = { buffer1: [], buffer2: [], buffer3: [], currentBuffer: [] }; 101 | 102 | this.clearBuffer(object.buffer.currentBuffer); 103 | 104 | let rotatedVertices = object.vertices.map(point => 105 | this.rotateX(this.rotateY(this.rotateZ(point, object.rotation.z, object.center), object.rotation.y, object.center), object.rotation.x, object.center) 106 | ); 107 | 108 | let translatedVertices = rotatedVertices.map(point => ({ 109 | x: point.x - this.camera.x, 110 | y: point.y - this.camera.y, 111 | z: point.z - this.camera.z 112 | })); 113 | 114 | this.connectAndDraw([0, 1, 3, 2], translatedVertices); 115 | this.connectAndDraw([4, 5, 7, 6], translatedVertices); 116 | this.connectAndDraw([0, 1, 5, 4], translatedVertices); 117 | this.connectAndDraw([2, 3, 7, 6], translatedVertices); 118 | this.connectAndDraw([0, 2, 6, 4], translatedVertices); 119 | this.connectAndDraw([1, 3, 7, 5], translatedVertices); 120 | 121 | this.swapBuffers(object); 122 | this.drawBufferToConsole(object.buffer.currentBuffer); 123 | }); 124 | } 125 | 126 | private connectAndDraw(faceVertices: any, vertices: any) { 127 | for (let i = 0; i < faceVertices.length; i++) { 128 | const start = faceVertices[i]; 129 | const end = faceVertices[(i + 1) % faceVertices.length]; 130 | 131 | const startPoint = vertices[start]; 132 | const endPoint = vertices[end]; 133 | 134 | const startScreenX = Math.round(startPoint.x * 10) + 40; 135 | const startScreenY = Math.round(startPoint.y * 10) + 5; 136 | const endScreenX = Math.round(endPoint.x * 10) + 40; 137 | const endScreenY = Math.round(endPoint.y * 10) + 5; 138 | 139 | this.drawLine(startScreenX, startScreenY, endScreenX, endScreenY); 140 | } 141 | } 142 | 143 | private drawLine(x0: number, y0: number, x1: number, y1: number) { 144 | const dx = Math.abs(x1 - x0); 145 | const dy = Math.abs(y1 - y0); 146 | const sx = x0 < x1 ? 1 : -1; 147 | const sy = y0 < y1 ? 1 : -1; 148 | let err = dx - dy; 149 | 150 | while (true) { 151 | process.stdout.cursorTo(x0 - 20, y0 - 10); 152 | process.stdout.write(chalk.white('█')); 153 | 154 | if (x0 === x1 && y0 === y1) break; 155 | const e2 = 2 * err; 156 | if (e2 > -dy) { 157 | err -= dy; 158 | x0 += sx; 159 | } 160 | if (e2 < dx) { 161 | err += dx; 162 | y0 += sy; 163 | } 164 | } 165 | } 166 | 167 | public prerun(widget: app.Iwidget) { 168 | // console.log("Objects:", this.objects); 169 | 170 | const { events } = widget.data.properties; 171 | events.onFrame?.(this.objects, this.camera); 172 | this.draw(); 173 | } 174 | } -------------------------------------------------------------------------------- /scripts/TCG.ts: -------------------------------------------------------------------------------- 1 | import chalk from "chalk"; 2 | import * as app from '../src/lib/CLIApplication'; 3 | 4 | export interface Iobject { 5 | id: string; 6 | center: Iposition; 7 | rotation: Iposition; 8 | vertices: Iposition[]; 9 | } 10 | 11 | export interface Iposition { 12 | x: number; 13 | y: number; 14 | z: number; 15 | } 16 | 17 | export class TCG { 18 | public data: app.Idata = { 19 | "type": "tcg", 20 | "properties": { 21 | "accepts": ["accepts", "paths", "global", "styles", "events", "defaultEvents", "text", "placeholder", "checked"], 22 | "paths": [], 23 | "global": "", 24 | "styles": { 25 | "x": 1, 26 | "y": 1, 27 | "visible": true 28 | }, 29 | "events": {}, 30 | "defaultEvents": {} 31 | } 32 | }; 33 | 34 | public camera: Iposition = { x: 1, y: -1, z: 0 }; 35 | public objects: Iobject[] = []; 36 | 37 | public constructor(objects: Iobject[], props?: app.Iproperties) { 38 | this.objects = this.objects.concat(objects); 39 | 40 | if (props) this.data.properties = app.setProps(props, this.data.properties); 41 | } 42 | 43 | private rotateX(point: Iposition, angle: number, center: Iposition): Iposition { 44 | const y = (point.y - center.y) * Math.cos(angle) - (point.z - center.z) * Math.sin(angle) + center.y; 45 | const z = (point.y - center.y) * Math.sin(angle) + (point.z - center.z) * Math.cos(angle) + center.z; 46 | return { ...point, y, z }; 47 | } 48 | 49 | private rotateY(point: Iposition, angle: number, center: Iposition): Iposition { 50 | const x = (point.x - center.x) * Math.cos(angle) + (point.z - center.z) * Math.sin(angle) + center.x; 51 | const z = -(point.x - center.x) * Math.sin(angle) + (point.z - center.z) * Math.cos(angle) + center.z; 52 | return { ...point, x, z }; 53 | } 54 | 55 | private rotateZ(point: Iposition, angle: number, center: Iposition): Iposition { 56 | const x = (point.x - center.x) * Math.cos(angle) - (point.y - center.y) * Math.sin(angle) + center.x; 57 | const y = (point.x - center.x) * Math.sin(angle) + (point.y - center.y) * Math.cos(angle) + center.y; 58 | return { ...point, x, y }; 59 | } 60 | 61 | private draw() { 62 | process.stdout.write('\x1Bc'); 63 | 64 | this.objects.forEach(object => { 65 | let rotatedVertices = object.vertices.map(point => 66 | this.rotateX(this.rotateY(this.rotateZ(point, object.rotation.z, object.center), object.rotation.y, object.center), object.rotation.x, object.center) 67 | ); 68 | 69 | let translatedVertices = rotatedVertices.map(point => ({ 70 | x: point.x - this.camera.x, 71 | y: point.y - this.camera.y, 72 | z: point.z - this.camera.z 73 | })); 74 | 75 | this.connectAndDraw([0, 1, 3, 2], translatedVertices); 76 | this.connectAndDraw([4, 5, 7, 6], translatedVertices); 77 | this.connectAndDraw([0, 1, 5, 4], translatedVertices); 78 | this.connectAndDraw([2, 3, 7, 6], translatedVertices); 79 | this.connectAndDraw([0, 2, 6, 4], translatedVertices); 80 | this.connectAndDraw([1, 3, 7, 5], translatedVertices); 81 | }); 82 | } 83 | 84 | private connectAndDraw(faceVertices: any, vertices: any) { 85 | for (let i = 0; i < faceVertices.length; i++) { 86 | const start = faceVertices[i]; 87 | const end = faceVertices[(i + 1) % faceVertices.length]; 88 | 89 | const startPoint = vertices[start]; 90 | const endPoint = vertices[end]; 91 | 92 | const startScreenX = Math.round(startPoint.x * 10) + 40; 93 | const startScreenY = Math.round(startPoint.y * 10) + 5; 94 | const endScreenX = Math.round(endPoint.x * 10) + 40; 95 | const endScreenY = Math.round(endPoint.y * 10) + 5; 96 | 97 | this.drawLine(startScreenX, startScreenY, endScreenX, endScreenY); 98 | } 99 | } 100 | 101 | private drawLine(x0: number, y0: number, x1: number, y1: number) { 102 | const dx = Math.abs(x1 - x0); 103 | const dy = Math.abs(y1 - y0); 104 | const sx = x0 < x1 ? 1 : -1; 105 | const sy = y0 < y1 ? 1 : -1; 106 | let err = dx - dy; 107 | 108 | while (true) { 109 | process.stdout.cursorTo(x0 - 20, y0 - 10); 110 | process.stdout.write(chalk.white('█')); 111 | 112 | if (x0 === x1 && y0 === y1) break; 113 | const e2 = 2 * err; 114 | if (e2 > -dy) { 115 | err -= dy; 116 | x0 += sx; 117 | } 118 | if (e2 < dx) { 119 | err += dx; 120 | y0 += sy; 121 | } 122 | } 123 | } 124 | 125 | public prerun(widget: app.Iwidget) { 126 | const { events } = widget.data.properties; 127 | events.onFrame?.(this.objects, this.camera); 128 | this.draw(); 129 | } 130 | } -------------------------------------------------------------------------------- /scripts/global.ts: -------------------------------------------------------------------------------- 1 | export { TCG } from './TCG'; -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | export { CLIApplication } from "./lib/CLIApplication"; 2 | 3 | export { CLIPanel } from "./lib/CLIWidgets/CLIPanel"; 4 | export { CLILabel } from "./lib/CLIWidgets/CLILabel"; 5 | export { CLIButton } from "./lib/CLIWidgets/CLIButton"; 6 | export { CLICheckbox } from "./lib/CLIWidgets/CLICheckbox"; 7 | export { CLIRadio } from "./lib/CLIWidgets/CLIRadio"; 8 | export { CLIImage } from "./lib/CLIWidgets/CLIImage"; 9 | export { CLITextbox } from './lib/CLIWidgets/CLITextbox' 10 | export { CLIWebview } from "./lib/CLIWidgets/CLIWebview"; 11 | export { CLICanvas } from "./lib/CLIWidgets/CLICanvas"; 12 | 13 | export { CLICustom } from "./lib/CLIWidgets/CLICustom"; -------------------------------------------------------------------------------- /src/lib/CLIApplication.ts: -------------------------------------------------------------------------------- 1 | import chalk from 'chalk'; 2 | 3 | export interface Iwidget { 4 | data: Idata; 5 | prerun: Function; 6 | isTyping?: boolean; 7 | } 8 | 9 | export interface Idata { 10 | type: string; 11 | properties: Iproperties; 12 | } 13 | 14 | export interface Iproperties { 15 | accepts: Array; 16 | paths: Array; 17 | global: string; 18 | styles: Istyles; 19 | events: Ievents; 20 | defaultEvents: Ievents; 21 | 22 | canvasChilds?: Array; 23 | 24 | text?: string; 25 | placeholder?: string; 26 | 27 | checked?: boolean; 28 | 29 | [key: string]: any; 30 | } 31 | 32 | export interface IcanvasChild { 33 | type: string; 34 | 35 | x: number; 36 | y: number; 37 | toX?: number; 38 | toY?: number; 39 | centerX?: number; 40 | centerY?: number, 41 | 42 | fill: string; 43 | 44 | radius?: number; 45 | 46 | width?: number; 47 | height?: number; 48 | 49 | private?: Iresult[]; 50 | } 51 | 52 | export interface Iresult { 53 | x: number; 54 | y: number; 55 | 56 | fill: string; 57 | } 58 | 59 | export interface Istyles { 60 | x: number; 61 | y: number; 62 | 63 | width?: number; 64 | height?: number; 65 | 66 | fill?: string; 67 | "background-color"?: string; 68 | 69 | "text-color"?: string; 70 | "placeholder-color"?: string; 71 | 72 | visible: boolean; 73 | 74 | check?: Array; 75 | 76 | img?: string; 77 | page?: string; 78 | "img-pixels"?: (string | Array); 79 | } 80 | 81 | export interface Ievents { 82 | onEnter?: Function; 83 | onPut?: Function; 84 | onLeave?: Function; 85 | onChange?: Function; 86 | onConnect?: (object); 87 | 88 | onFrame?: Function; 89 | } 90 | 91 | export class CLIApplication { 92 | private debug: boolean = false; 93 | private widgets: Array = []; 94 | private Vwidgets: Array = []; 95 | private curlocs = { 96 | tab: 0, 97 | textloc: 0 98 | }; 99 | 100 | public constructor(option?: any) { 101 | this.widgets = []; 102 | this.curlocs = { 103 | tab: 0, 104 | textloc: 0 105 | }; 106 | 107 | if (option?.debug) this.debug = true; 108 | } 109 | 110 | public append(...widgets: Array) { 111 | let exists: Array = []; 112 | 113 | widgets.forEach((widget: Iwidget) => { 114 | widget.data.properties.paths.forEach((path: string) => { 115 | if (exists.includes(path)) throw new Error(`[unique.path] ${path} is already exists`); 116 | exists.push(path); 117 | 118 | if (this.find(path)) { 119 | throw new Error(`[unique.path] ${path} is already exists`); 120 | } 121 | }); 122 | }); 123 | 124 | this.widgets = this.widgets.concat(widgets); 125 | } 126 | 127 | private event() { 128 | process.stdin.setRawMode(true); 129 | process.stdin.setEncoding(`utf-8`); 130 | 131 | process.stdin.on(`data`, (key: string) => { 132 | if (key === `\u0003`) { 133 | process.stdout.write(`\x1b[${process.stdout.rows - 1};${process.stdout.columns}H`); 134 | process.exit(); 135 | } 136 | 137 | const selected = this.Vwidgets[this.curlocs.tab]; 138 | 139 | if (selected.isTyping && selected.data.type === `textbox`) { 140 | if (selected.data.properties.text && (this.curlocs.textloc < selected.data.properties.text.length) && key === `\u001b[C`) this.curlocs.textloc += 1; 141 | if (this.curlocs.textloc !> 0 && key === `\u001b[D`) this.curlocs.textloc -= 1; 142 | 143 | if (![`\u001b[D`, `\u001b[C`, `\u0008`, `\r`, `\n`].includes(key)) { 144 | selected.data.properties.text = `${selected.data.properties.text?.substring(0, this.curlocs.textloc)}${key}${selected.data.properties.text?.substring(this.curlocs.textloc, selected.data.properties.text.length)}`; 145 | this.curlocs.textloc += 1; 146 | } 147 | 148 | if (key === `\r` || key === `\n`) { 149 | selected.data.properties.defaultEvents?.onEnter?.(); 150 | selected.data.properties.events?.onEnter?.(); 151 | 152 | selected.data.properties.defaultEvents.onChange?.(); 153 | selected.data.properties.events.onChange?.(); 154 | } 155 | 156 | if (key === `\u0008` && this.curlocs.textloc > 0) { 157 | selected.data.properties.text = `${selected.data.properties.text?.substring(0, this.curlocs.textloc - 1)}${selected.data.properties.text?.substring(this.curlocs.textloc, selected.data.properties.text.length)}`; 158 | this.curlocs.textloc -= 1; 159 | } 160 | } else { 161 | if (key === `\u001b[C`) this.curlocs.tab += 1; 162 | if (key === `\u001b[D`) this.curlocs.tab -= 1; 163 | 164 | if (key === `\u001b[C` || key === `\u001b[D`) { 165 | this.curlocs.textloc = 0; 166 | selected.data.properties.events?.onLeave?.(); 167 | selected.data.properties.defaultEvents?.onLeave?.(); 168 | } 169 | 170 | if (key === `\r` || key === `\n`) { 171 | this.curlocs.textloc = selected.data.properties.text ? selected.data.properties.text.length : 0; 172 | 173 | let result = selected.data.properties.defaultEvents?.onEnter?.(); 174 | selected.data.properties.events?.onEnter?.(); 175 | 176 | if (selected.data.type === `radio`) this.widgets = result; 177 | } 178 | } 179 | 180 | if (this.curlocs.tab >= this.Vwidgets.length) this.curlocs.tab = this.Vwidgets.length - 1; 181 | if (this.curlocs.tab < 0) this.curlocs.tab = 0; 182 | 183 | if (selected.data.properties.styles.height !== process.stdout.rows) { 184 | selected.data.properties.events?.onPut?.(); 185 | selected.data.properties.defaultEvents?.onPut?.(); 186 | } 187 | }); 188 | 189 | process.stdout.write(`\x1B[?25l`); 190 | } 191 | 192 | public isOverLapping(widget: Iwidget, props: Istyles) { 193 | const { styles } = widget.data.properties; 194 | 195 | return ( 196 | styles?.width && 197 | styles?.height && 198 | styles?.["background-color"] && 199 | (props.x >= styles.x && props.x <= styles.x + styles.width) && 200 | (props.y >= styles.y && props.y <= styles.y + styles.height) 201 | ); 202 | } 203 | 204 | public hexbn(hex: string, brightness: number) { 205 | hex = hex.replace(/^#/, ``); 206 | if (!/^(?:[0-9a-fA-F]{3}){1,2}$/.test(hex)) return ``; 207 | let bigint = parseInt(hex, 16); 208 | let rgb = [(bigint >> 16) & 255, (bigint >> 8) & 255, bigint & 255]; 209 | rgb = rgb.map(e => e -= brightness); 210 | rgb = rgb.map(e => Math.max(0, Math.min(255, e))); 211 | let res = rgb.map(e => e.toString(16).padStart(2, `0`)); 212 | const hexColor = `#${res.join(``)}`; 213 | return hexColor; 214 | } 215 | 216 | public show(frame: number) { 217 | this.event(); 218 | 219 | setInterval(() => { 220 | console.clear(); 221 | 222 | if (this.curlocs.tab >= this.Vwidgets.length) this.curlocs.tab = this.Vwidgets.length - 1; 223 | if (this.curlocs.tab < 0) this.curlocs.tab = 0; 224 | 225 | this.Vwidgets = this.widgets.filter(e => e.data.properties.styles.visible); 226 | 227 | this.Vwidgets.forEach((widget: Iwidget, idx: number) => { 228 | const { type } = widget.data; 229 | const { styles } = widget.data.properties; 230 | 231 | let focus: string = ``; 232 | if (styles.height !== process.stdout.rows && this.curlocs.tab === idx) focus = chalk.bgHex(this.hexbn(styles[`background-color`] || styles[`text-color`] || `#ffffff`, 25))(` `); 233 | 234 | if (styles.visible && type === `panel`) widget.prerun(widget, focus); 235 | if (styles.visible && type === `label`) widget.prerun(this.widgets, widget, this.isOverLapping, focus); 236 | if (styles.visible && type === `button`) widget.prerun(widget, focus); 237 | if (styles.visible && type === `checkbox`) widget.prerun(this.widgets, widget, this.isOverLapping, focus); 238 | if (styles.visible && type === `radio`) widget.prerun(this.widgets, widget, this.isOverLapping, focus); 239 | if (styles.visible && type === `image`) widget.prerun(widget); 240 | if (styles.visible && type === `textbox`) widget.prerun(widget, focus, this.curlocs.textloc); 241 | if (styles.visible && type === `canvas`) widget.prerun(widget); 242 | 243 | if (styles.visible && type === `custom`) widget.prerun(widget, focus, this.widgets, this.isOverLapping, this.curlocs); 244 | 245 | if (styles.visible && type === `tcg`) widget.prerun(widget); 246 | }); 247 | 248 | if (this.debug) { 249 | process.stdout.write(`\x1b[1;1H`); 250 | console.log(this.curlocs.tab); 251 | } 252 | }, 1000 / frame); 253 | } 254 | 255 | public find(path: string) { 256 | return this.widgets.find(value => value.data.properties.paths.includes(path)); 257 | } 258 | 259 | public modify(path: string, props: Iproperties) { 260 | const widgetIdx = this.widgets.findIndex(value => value.data.properties.paths.includes(path)); 261 | this.widgets[widgetIdx].data.properties = setProps(props, this.widgets[widgetIdx].data.properties); 262 | } 263 | } 264 | 265 | export function setProps(get: Iproperties, origin: Iproperties): Iproperties { 266 | if (get) Object.keys(get).forEach((prop: string) => { 267 | if (origin?.accepts && !origin.accepts.includes(prop) && origin.accepts.length !== 0) return; 268 | 269 | if (!Array.isArray(origin[prop]) && typeof origin[prop] === `object`) { 270 | origin[prop] = setProps(get[prop], origin[prop]); 271 | } else { 272 | const value = get[prop]; 273 | origin[prop] = value; 274 | } 275 | }); 276 | 277 | return origin; 278 | } 279 | -------------------------------------------------------------------------------- /src/lib/CLIWidgets/CLIButton.ts: -------------------------------------------------------------------------------- 1 | import chalk from "chalk"; 2 | import * as app from "../CLIApplication"; 3 | 4 | export class CLIButton { 5 | public data: app.Idata = { 6 | "type": "button", 7 | "properties": { 8 | "text": "lorem ipsum", 9 | "accepts": ["paths", "styles", "events", "text", "global"], 10 | "paths": [], 11 | "global": "", 12 | "styles": { 13 | "x": 1, 14 | "y": 1, 15 | "text-color": "#ffffff", 16 | "visible": true 17 | }, 18 | "events": {}, 19 | "defaultEvents": {} 20 | } 21 | }; 22 | 23 | public constructor(props?: app.Iproperties) { 24 | if (props) this.data.properties = app.setProps(props, this.data.properties); 25 | } 26 | 27 | public prerun(widget: app.Iwidget, focus: string) { 28 | const { styles, text } = widget.data.properties; 29 | 30 | if (!styles.fill) styles.fill = `█`; 31 | 32 | process.stdout.write(`\x1b[${styles.y};${styles.x}H`); 33 | if (styles.width) console.log(focus + chalk.hex(styles[`background-color`] ? styles[`background-color`] : `#ffffff`)(styles.fill.repeat(styles.width))); 34 | 35 | if (styles.height) for (let i = 0; i < styles.height; i++) { 36 | process.stdout.write(`\x1b[${styles.y + i};${styles.x}H`); 37 | if (styles.width) console.log(focus + chalk.hex(styles[`background-color`] ? styles[`background-color`] : `#ffffff`)(styles.fill.repeat(styles.width))); 38 | } 39 | 40 | process.stdout.write(`\x1b[${styles.y};${styles.x}H`); 41 | console.log(focus + chalk.bgHex(styles?.[`background-color`] ? styles[`background-color`] : `#000000`).hex(styles?.[`text-color`] ? styles[`text-color`] : `#ffffff`)(text)); 42 | } 43 | } -------------------------------------------------------------------------------- /src/lib/CLIWidgets/CLICanvas.ts: -------------------------------------------------------------------------------- 1 | import * as app from "../CLIApplication"; 2 | 3 | export class CLICanvas { 4 | private lines: app.IcanvasChild[] = []; 5 | private circles: app.IcanvasChild[] = []; 6 | private rectangles: app.IcanvasChild[] = []; 7 | 8 | private line(object: app.IcanvasChild): (app.Iresult[] | undefined) { 9 | if (!object.toX || !object.toY) return; 10 | 11 | let result: app.Iresult[] = []; 12 | 13 | const deltaX = object.toX - object.x; 14 | const deltaY = object.toY - object.y; 15 | const steps = Math.max(Math.abs(deltaX), Math.abs(deltaY)); 16 | 17 | for (let i = 0; i <= steps; i++) { 18 | let x: number, y: number; 19 | 20 | if (deltaX >= 0 && deltaY >= 0) { 21 | x = Math.round(object.x + (i / steps) * Math.abs(deltaX)); 22 | y = Math.round(object.y + (i / steps) * Math.abs(deltaY)); 23 | } else if (deltaX < 0 && deltaY >= 0) { 24 | x = Math.round(object.x - (i / steps) * Math.abs(deltaX)); 25 | y = Math.round(object.y + (i / steps) * Math.abs(deltaY)); 26 | } else if (deltaX >= 0 && deltaY < 0) { 27 | x = Math.round(object.x + (i / steps) * Math.abs(deltaX)); 28 | y = Math.round(object.y - (i / steps) * Math.abs(deltaY)); 29 | } else { // deltaX < 0 && deltaY < 0 30 | x = Math.round(object.x - (i / steps) * Math.abs(deltaX)); 31 | y = Math.round(object.y - (i / steps) * Math.abs(deltaY)); 32 | } 33 | 34 | process.stdout.write(`\x1b[${y};${x}H`); 35 | console.log(object.fill); 36 | 37 | result.push({ fill: object.fill, x: x, y: y }); 38 | } 39 | 40 | return result; 41 | } 42 | 43 | private circle(object: app.IcanvasChild): (app.Iresult[] | undefined) { 44 | if (!object.centerX || !object.centerY || !object.radius) return; 45 | 46 | let result: app.Iresult[] = []; 47 | 48 | for (let y = object.centerY - object.radius; y <= object.centerY + object.radius; y++) { 49 | for (let x = object.centerX - object.radius; x <= object.centerX + object.radius; x++) { 50 | const distance = Math.sqrt((x - object.centerX) ** 2 + (y - object.centerY) ** 2); 51 | 52 | if (distance <= object.radius) { 53 | process.stdout.write(`\x1b[${y};${x}H`); 54 | console.log(object.fill); 55 | 56 | result.push({ fill: object.fill, x: x, y: y }); 57 | } 58 | } 59 | } 60 | 61 | return result; 62 | } 63 | 64 | private rectangle(object: app.IcanvasChild): (app.Iresult[] | undefined) { 65 | if (!object.height || !object.width) return; 66 | 67 | let result: app.Iresult[] = []; 68 | 69 | for (let i = object.y; i < object.y + object.height; i++) { 70 | for (let j = object.x; j < object.x + object.width; j++) { 71 | process.stdout.write(`\x1b[${i};${j}H`); 72 | console.log(object.fill); 73 | 74 | result.push({ fill: object.fill, x: j, y: i }); 75 | } 76 | } 77 | 78 | return result; 79 | } 80 | 81 | public data: app.Idata = { 82 | "type": "canvas", 83 | "properties": { 84 | "canvasChilds": [], 85 | "accepts": ["paths", "global", "styles", "events", "defaultEvents", "canvasChilds"], 86 | "paths": [], 87 | "global": "", 88 | "styles": { 89 | "x": 1, 90 | "y": 1, 91 | "width": 20, 92 | "height": 10, 93 | "visible": true 94 | }, 95 | "events": {}, 96 | "defaultEvents": {} 97 | } 98 | }; 99 | 100 | public constructor(props?: app.Iproperties) { 101 | if (props) this.data.properties = app.setProps(props, this.data.properties); 102 | } 103 | 104 | public prerun(widget: app.Iwidget) { 105 | widget.data.properties.canvasChilds?.forEach((child: app.IcanvasChild) => { 106 | if (child.type === `line`) { 107 | if (this.lines.includes(child)) { 108 | const idx = this.lines.findIndex(e => e === child); 109 | 110 | this.lines[idx].private?.forEach(_private => { 111 | if (!_private.x || !_private.y) return; 112 | process.stdout.write(`\x1b[${_private.y};${_private.x}H`); 113 | console.log(_private.fill); 114 | }); 115 | } else { 116 | child.private = this.line(child); 117 | this.lines.push(child); 118 | } 119 | } else if (child.type === `rectangle`) { 120 | if (this.rectangles.includes(child)) { 121 | const idx = this.rectangles.findIndex(e => e === child); 122 | 123 | this.rectangles[idx].private?.forEach(_private => { 124 | if (!_private.x || !_private.y) return; 125 | process.stdout.write(`\x1b[${_private.y};${_private.x}H`); 126 | console.log(_private.fill); 127 | }); 128 | } else { 129 | child.private = this.rectangle(child); 130 | this.rectangles.push(child); 131 | } 132 | } else if (child.type === `circle`) { 133 | if (this.circles.includes(child)) { 134 | const idx = this.circles.findIndex(e => e === child); 135 | 136 | this.circles[idx].private?.forEach(_private => { 137 | if (!_private.x || !_private.y) return; 138 | process.stdout.write(`\x1b[${_private.y};${_private.x}H`); 139 | console.log(_private.fill); 140 | }); 141 | } else { 142 | child.private = this.circle(child); 143 | this.circles.push(child); 144 | } 145 | } 146 | }); 147 | } 148 | } -------------------------------------------------------------------------------- /src/lib/CLIWidgets/CLICheckbox.ts: -------------------------------------------------------------------------------- 1 | import chalk from "chalk"; 2 | import * as app from "../CLIApplication"; 3 | 4 | export class CLICheckbox { 5 | public data: app.Idata = { 6 | "type": "checkbox", 7 | "properties": { 8 | "text": "lorem ipsum", 9 | "checked": false, 10 | "accepts": ["paths", "styles", "text", "events", "checked", "global"], 11 | "paths": [], 12 | "global": "", 13 | "styles": { 14 | "x": 1, 15 | "y": 1, 16 | "text-color": "#ffffff", 17 | "visible": true, 18 | "check": ["✅ ", "❌ "] 19 | }, 20 | "events": {}, 21 | "defaultEvents": { 22 | "onEnter": () => { 23 | this.data.properties.checked = !this.data.properties.checked; 24 | } 25 | } 26 | } 27 | }; 28 | 29 | public constructor(props?: app.Iproperties) { 30 | if (props) this.data.properties = app.setProps(props, this.data.properties); 31 | } 32 | 33 | public prerun(widgets: Array, widget: app.Iwidget, func: Function, focus: string) { 34 | const { styles, text } = widget.data.properties; 35 | 36 | let isOverLapping: boolean = false; 37 | widgets.forEach((_widget: app.Iwidget) => { 38 | if (func(_widget, styles)) { 39 | isOverLapping = true; 40 | 41 | process.stdout.write(`\x1b[${styles.y};${styles.x}H`); 42 | 43 | const backgroundColor = _widget.data.properties.styles["background-color"] || `#000000`; 44 | const textColor = styles["text-color"] || _widget.data.properties.styles["text-color"] || `#ffffff`; 45 | 46 | console.log(focus + (this.data.properties.checked ? styles.check?.[0] : styles.check?.[1]) + chalk.bgHex(backgroundColor)(chalk.hex(textColor)(text))); 47 | } 48 | }); 49 | 50 | if (!isOverLapping) { 51 | process.stdout.write(`\x1b[${styles.y};${styles.x}H`); 52 | 53 | const backgroundColor = `#000000`; 54 | const textColor = styles["text-color"] || `#ffffff`; 55 | 56 | console.log(focus + (this.data.properties.checked ? styles.check?.[0] : styles.check?.[1]) + chalk.bgHex(backgroundColor)(chalk.hex(textColor)(text))); 57 | } 58 | } 59 | } -------------------------------------------------------------------------------- /src/lib/CLIWidgets/CLICustom.ts: -------------------------------------------------------------------------------- 1 | import * as app from "../CLIApplication"; 2 | 3 | export class CLICustom { 4 | public data: app.Idata = { 5 | "type": "custom", 6 | "properties": { 7 | "accepts": ["accepts", "paths", "global", "styles", "events", "defaultEvents", "text", "placeholder", "checked"], 8 | "paths": [], 9 | "global": "", 10 | "styles": { 11 | "x": 1, 12 | "y": 1, 13 | "visible": true 14 | }, 15 | "events": {}, 16 | "defaultEvents": {} 17 | } 18 | }; 19 | 20 | public constructor(props?: app.Iproperties) { 21 | if (props) this.data.properties = app.setProps(props, this.data.properties); 22 | } 23 | 24 | public prerun(widget: app.Iwidget, focus: string, widgets: Array, func: Function, object: any) {} 25 | } -------------------------------------------------------------------------------- /src/lib/CLIWidgets/CLIImage.ts: -------------------------------------------------------------------------------- 1 | import imageToAscii from 'image-to-ascii'; 2 | import * as app from "../CLIApplication"; 3 | 4 | export class CLIImage { 5 | private text: string = ``; 6 | private isDoing: boolean = false; 7 | 8 | public data: app.Idata = { 9 | "type": "image", 10 | "properties": { 11 | "accepts": ["paths", "styles", "global"], 12 | "paths": [], 13 | "global": "", 14 | "styles": { 15 | "x": 1, 16 | "y": 1, 17 | "width": 50, 18 | "height": 50, 19 | "visible": true, 20 | "img": "", 21 | "img-pixels": " " 22 | }, 23 | "events": {}, 24 | "defaultEvents": {} 25 | } 26 | }; 27 | 28 | public constructor(props?: app.Iproperties) { 29 | if (props) this.data.properties = app.setProps(props, this.data.properties); 30 | } 31 | 32 | public prerun(widget: app.Iwidget) { 33 | const { styles } = widget.data.properties; 34 | 35 | if (this.text !== ``) { 36 | this.text.split(`\n`).forEach((line: string, idx: number) => { 37 | process.stdout.write(`\x1b[${styles.y + idx};${styles.x}H`); 38 | console.log(line); 39 | }) 40 | } else if (!this.isDoing) { 41 | this.isDoing = true; 42 | imageToAscii(styles.img, { 43 | size: { 44 | width: styles.width, 45 | height: styles.height 46 | }, 47 | bg: true, 48 | fg: false, 49 | pixels: styles["img-pixels"] 50 | }, (err: string, converted: string) => { 51 | if (err) throw new Error(err); 52 | this.text = converted; 53 | }); 54 | } 55 | } 56 | } -------------------------------------------------------------------------------- /src/lib/CLIWidgets/CLILabel.ts: -------------------------------------------------------------------------------- 1 | import chalk from "chalk"; 2 | import * as app from "../CLIApplication"; 3 | 4 | export class CLILabel { 5 | public data: app.Idata = { 6 | "type": "label", 7 | "properties": { 8 | "text": "lorem ipsum", 9 | "accepts": ["paths", "styles", "text", "global"], 10 | "paths": [], 11 | "global": "", 12 | "styles": { 13 | "x": 1, 14 | "y": 1, 15 | "text-color": "#ffffff", 16 | "visible": true 17 | }, 18 | "events": {}, 19 | "defaultEvents": {} 20 | } 21 | }; 22 | 23 | public constructor(props?: app.Iproperties) { 24 | if (props) this.data.properties = app.setProps(props, this.data.properties); 25 | } 26 | 27 | public prerun(widgets: Array, widget: app.Iwidget, func: Function, focus: string) { 28 | const { styles, text } = widget.data.properties; 29 | 30 | let isOverLapping: boolean = false; 31 | widgets.forEach((_widget: app.Iwidget) => { 32 | if (func(_widget, styles)) { 33 | isOverLapping = true; 34 | 35 | process.stdout.write(`\x1b[${styles.y};${styles.x}H`); 36 | 37 | const backgroundColor = _widget.data.properties.styles["background-color"] || `#000000`; 38 | const textColor = styles["text-color"] || _widget.data.properties.styles["text-color"] || `#ffffff`; 39 | 40 | console.log(focus + chalk.bgHex(backgroundColor)(chalk.hex(textColor)(text))); 41 | } 42 | }); 43 | 44 | if (!isOverLapping) { 45 | process.stdout.write(`\x1b[${styles.y};${styles.x}H`); 46 | 47 | const backgroundColor = `#000000`; 48 | const textColor = styles["text-color"] || `#ffffff`; 49 | 50 | console.log(focus + chalk.bgHex(backgroundColor)(chalk.hex(textColor)(text))); 51 | } 52 | } 53 | } -------------------------------------------------------------------------------- /src/lib/CLIWidgets/CLIPanel.ts: -------------------------------------------------------------------------------- 1 | import chalk from "chalk"; 2 | import * as app from "../CLIApplication"; 3 | 4 | export class CLIPanel { 5 | public data: app.Idata = { 6 | "type": "panel", 7 | "properties": { 8 | "accepts": ["paths", "styles", "global"], 9 | "paths": [], 10 | "global": "", 11 | "styles": { 12 | "x": 0, 13 | "y": 0, 14 | "width": process.stdout.columns, 15 | "height": process.stdout.rows, 16 | "fill": "█", 17 | "background-color": "#000000", 18 | "text-color": "#ffffff", 19 | "visible": true 20 | }, 21 | "events": {}, 22 | "defaultEvents": {} 23 | } 24 | }; 25 | 26 | public constructor(props?: app.Iproperties) { 27 | if (props) this.data.properties = app.setProps(props, this.data.properties); 28 | } 29 | 30 | public prerun(widget: app.Iwidget, focus: string) { 31 | const { styles } = widget.data.properties; 32 | 33 | if (!styles.fill) styles.fill = `█`; 34 | 35 | process.stdout.write(`\x1b[${styles.y};${styles.x}H`); 36 | if (styles.width) console.log(focus + chalk.hex(styles[`background-color`] ? styles[`background-color`] : `#ffffff`)(styles.fill.repeat(styles.width))); 37 | 38 | if (styles.height) for (let i = 0; i < styles.height; i++) { 39 | process.stdout.write(`\x1b[${styles.y + i};${styles.x}H`); 40 | if (styles.width) console.log(focus + chalk.hex(styles[`background-color`] ? styles[`background-color`] : `#ffffff`)(styles.fill.repeat(styles.width))); 41 | } 42 | } 43 | } -------------------------------------------------------------------------------- /src/lib/CLIWidgets/CLIRadio.ts: -------------------------------------------------------------------------------- 1 | import chalk from "chalk"; 2 | import * as app from "../CLIApplication"; 3 | 4 | export class CLIRadio { 5 | private widgets: Array = []; 6 | 7 | public data: app.Idata = { 8 | "type": "radio", 9 | "properties": { 10 | "text": "lorem ipsum", 11 | "checked": false, 12 | "accepts": ["paths", "styles", "text", "events", "checked", "global"], 13 | "paths": [], 14 | "global": "default", 15 | "styles": { 16 | "x": 1, 17 | "y": 1, 18 | "text-color": "#ffffff", 19 | "visible": true, 20 | "check": ["⚪ ", "⚫ "] 21 | }, 22 | "events": {}, 23 | "defaultEvents": { 24 | "onEnter": () => { 25 | this.widgets.map((e: app.Iwidget) => e.data.properties.checked = e.data.properties.global === this.data.properties.global ? false : e.data.properties.checked); 26 | this.data.properties.checked = !this.data.properties.checked; 27 | 28 | return this.widgets; 29 | } 30 | } 31 | } 32 | }; 33 | 34 | public constructor(props?: app.Iproperties) { 35 | if (props) this.data.properties = app.setProps(props, this.data.properties); 36 | } 37 | 38 | public prerun(widgets: Array, widget: app.Iwidget, func: Function, focus: string) { 39 | const { styles, text } = widget.data.properties; 40 | 41 | this.widgets = widgets; 42 | 43 | let isOverLapping: boolean = false; 44 | widgets.forEach((_widget: app.Iwidget) => { 45 | if (func(_widget, styles)) { 46 | isOverLapping = true; 47 | 48 | process.stdout.write(`\x1b[${styles.y};${styles.x}H`); 49 | 50 | const backgroundColor = _widget.data.properties.styles["background-color"] || `#000000`; 51 | const textColor = styles["text-color"] || _widget.data.properties.styles["text-color"] || `#ffffff`; 52 | 53 | console.log(focus + (this.data.properties.checked ? styles.check?.[0] : styles.check?.[1]) + chalk.bgHex(backgroundColor)(chalk.hex(textColor)(text))); 54 | } 55 | }); 56 | 57 | if (!isOverLapping) { 58 | process.stdout.write(`\x1b[${styles.y};${styles.x}H`); 59 | 60 | const backgroundColor = `#000000`; 61 | const textColor = styles["text-color"] || `#ffffff`; 62 | 63 | console.log(focus + (this.data.properties.checked ? styles.check?.[0] : styles.check?.[1]) + chalk.bgHex(backgroundColor)(chalk.hex(textColor)(text))); 64 | } 65 | } 66 | } -------------------------------------------------------------------------------- /src/lib/CLIWidgets/CLITextbox.ts: -------------------------------------------------------------------------------- 1 | import chalk from "chalk"; 2 | import * as app from "../CLIApplication"; 3 | 4 | export class CLITextbox { 5 | public isTyping: boolean = false; 6 | 7 | public data: app.Idata = { 8 | "type": "textbox", 9 | "properties": { 10 | "text": "", 11 | "placeholder": "", 12 | "accepts": ["paths", "styles", "global", "text", "placeholder", "events"], 13 | "paths": [], 14 | "global": "", 15 | "styles": { 16 | "x": 1, 17 | "y": 1, 18 | "background-color": "#ffffff", 19 | "placeholder-color": "#777777", 20 | "text-color": "#000000", 21 | "visible": true 22 | }, 23 | "events": {}, 24 | "defaultEvents": { 25 | "onEnter": () => { 26 | this.isTyping = !this.isTyping; 27 | } 28 | } 29 | } 30 | }; 31 | 32 | public constructor(props?: app.Iproperties) { 33 | if (props) this.data.properties = app.setProps(props, this.data.properties); 34 | } 35 | 36 | public prerun(widget: app.Iwidget, focus: string, textloc: number) { 37 | const { styles, text, placeholder } = widget.data.properties; 38 | 39 | const backgroundColor = styles["background-color"] || `#ffffff`; 40 | const placeholderColor = styles["placeholder-color"] || `#777777`; 41 | const textColor = styles["text-color"] || `#000000`; 42 | 43 | if (this.isTyping) { 44 | process.stdout.write(`\x1b[${styles.y};${styles.x}H`); 45 | console.log(focus + (text === `` ? chalk.bgHex(backgroundColor)(chalk.hex(placeholderColor)(placeholder)) : chalk.bgHex(backgroundColor)(chalk.hex(textColor)(`${text?.substring(0, textloc)}|${text?.substring(textloc, text.length)}`)))); 46 | } else { 47 | process.stdout.write(`\x1b[${styles.y};${styles.x}H`); 48 | console.log(focus + (text === `` ? chalk.bgHex(backgroundColor)(chalk.hex(placeholderColor)(placeholder)) : chalk.bgHex(backgroundColor)(chalk.hex(textColor)(text)))); 49 | } 50 | } 51 | } -------------------------------------------------------------------------------- /src/lib/CLIWidgets/CLIWebview.ts: -------------------------------------------------------------------------------- 1 | import puppeteer from 'puppeteer'; 2 | import imageToAscii from 'image-to-ascii'; 3 | import * as app from "../CLIApplication"; 4 | 5 | export class CLIWebview { 6 | private text: string = ``; 7 | private isDoing: boolean = false; 8 | 9 | public data: app.Idata = { 10 | "type": "image", 11 | "properties": { 12 | "accepts": ["paths", "styles", "global"], 13 | "paths": [], 14 | "global": "", 15 | "styles": { 16 | "x": 1, 17 | "y": 1, 18 | "visible": true, 19 | "img": "", 20 | "img-pixels": " ", 21 | "page": "https://www.google.com" 22 | }, 23 | "events": {}, 24 | "defaultEvents": {} 25 | } 26 | }; 27 | 28 | public constructor(props?: app.Iproperties) { 29 | if (props) this.data.properties = app.setProps(props, this.data.properties); 30 | } 31 | 32 | public prerun(widget: app.Iwidget) { 33 | const { styles, events } = widget.data.properties; 34 | 35 | if (this.text !== ``) { 36 | this.text.split(`\n`).forEach((line: string, idx: number) => { 37 | process.stdout.write(`\x1b[${styles.y + idx};${styles.x}H`); 38 | console.log(line); 39 | }); 40 | } else if (!this.isDoing) { 41 | this.isDoing = true; 42 | 43 | const browser = puppeteer.launch(); 44 | const page = browser.then(value => value.newPage()); 45 | 46 | page.then(value => { 47 | if (typeof events.onConnect === `function`) events.onConnect?.(value, () => { 48 | if (this.text === ``) { 49 | value.waitForTimeout(2000).then(() => { 50 | value.screenshot({ path: `browse.png` }).then(() => { 51 | styles.img = `browse.png`; 52 | 53 | imageToAscii(styles.img, { 54 | size: { 55 | width: styles.width, 56 | height: styles.height 57 | }, 58 | bg: true, 59 | fg: false, 60 | pixels: styles["img-pixels"] 61 | }, (err: string, converted: string) => { 62 | if (err) throw new Error(err); 63 | this.text = converted; 64 | }); 65 | }); 66 | }); 67 | } 68 | }); 69 | 70 | // if (styles.page) value.goto(styles.page).then(() => { 71 | // value.type(`textarea[type="search"]`, `sans`).then(() => { 72 | // value.click(`body > div > div > form > div:nth-child(1) > div > div > center > input`).then(() => { 73 | // value.waitForTimeout(2000).then(() => { 74 | // value.screenshot({ path: `browse.png` }).then(() => { 75 | // styles.img = `browse.png`; 76 | 77 | // imageToAscii(styles.img, { 78 | // size: { 79 | // width: styles.width, 80 | // height: styles.height 81 | // }, 82 | // bg: true, 83 | // fg: false, 84 | // pixels: styles["img-pixels"] 85 | // }, (err: string, converted: string) => { 86 | // if (err) throw new Error(err); 87 | // this.text = converted; 88 | // }); 89 | // }); 90 | // }); 91 | // }); 92 | // }); 93 | // }); 94 | }); 95 | } 96 | } 97 | } -------------------------------------------------------------------------------- /tests/default.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var _require = require("../"), 4 | CLIApplication = _require.CLIApplication, 5 | CLIPanel = _require.CLIPanel, 6 | CLILabel = _require.CLILabel, 7 | CLIButton = _require.CLIButton; 8 | var app = new CLIApplication(); 9 | var background = new CLIPanel({ 10 | "styles": { 11 | "background-color": "#EEEEEE" 12 | } 13 | }); 14 | var title = new CLILabel({ 15 | "text": "simple-modal-app", 16 | "styles": { 17 | "text-color": "#222831", 18 | x: 4, 19 | y: 2 20 | } 21 | }); 22 | var label1 = new CLILabel({ 23 | "paths": ["root/label1"], 24 | "text": "open-modal", 25 | "styles": { 26 | "text-color": "#00ADB5", 27 | x: 4, 28 | y: 3, 29 | visible: false 30 | } 31 | }); 32 | var timeout; 33 | var button1 = new CLIButton({ 34 | "text": " button ", 35 | "styles": { 36 | "background-color": "#222831", 37 | "text-color": "#EEEEEE", 38 | x: 4, 39 | y: 4, 40 | width: 8, 41 | height: 1 42 | }, 43 | "events": { 44 | "onPut": function onPut() { 45 | timeout = setTimeout(function () { 46 | app.modify("root/label1", { 47 | styles: { 48 | visible: true 49 | } 50 | }); 51 | }, 500); 52 | }, 53 | "onLeave": function onLeave() { 54 | clearTimeout(timeout); 55 | app.modify("root/label1", { 56 | styles: { 57 | visible: false 58 | } 59 | }); 60 | }, 61 | "onEnter": function onEnter() { 62 | app.modify("root/modalp", { 63 | styles: { 64 | visible: true 65 | } 66 | }); 67 | app.modify("root/modall", { 68 | styles: { 69 | visible: true 70 | } 71 | }); 72 | app.modify("root/modalb", { 73 | styles: { 74 | visible: true 75 | } 76 | }); 77 | } 78 | } 79 | }); 80 | var modalPanel = new CLIPanel({ 81 | "paths": ["root/modalp"], 82 | "styles": { 83 | "background-color": "#222831", 84 | "visible": false, 85 | x: 8, 86 | y: 2, 87 | "width": 50, 88 | "height": 10 89 | } 90 | }); 91 | var modalLabel = new CLILabel({ 92 | "paths": ["root/modall"], 93 | "text": "modal-title", 94 | "styles": { 95 | "text-color": "#EEEEEE", 96 | x: 12, 97 | y: 3, 98 | "visible": false 99 | } 100 | }); 101 | var modalButton = new CLIButton({ 102 | "paths": ["root/modalb"], 103 | "text": " close ", 104 | "styles": { 105 | "background-color": "#EEEEEE", 106 | "text-color": "#222831", 107 | x: 12, 108 | y: 4, 109 | width: 6, 110 | height: 1, 111 | visible: false 112 | }, 113 | "events": { 114 | "onEnter": function onEnter() { 115 | app.modify("root/modalp", { 116 | styles: { 117 | visible: false 118 | } 119 | }); 120 | app.modify("root/modall", { 121 | styles: { 122 | visible: false 123 | } 124 | }); 125 | app.modify("root/modalb", { 126 | styles: { 127 | visible: false 128 | } 129 | }); 130 | } 131 | } 132 | }); 133 | app.append(background, title, label1, button1, modalPanel, modalLabel, modalButton); 134 | app.show(30); 135 | 136 | // const siu = 137 | // 138 | 139 | // 140 | // { 142 | // timeout = setTimeout(() => { 143 | // app.modify(`root/label1`, { styles: { visible: true } }); 144 | // }, 500); 145 | // }, 146 | // "onLeave": () => { 147 | // clearTimeout(timeout); 148 | // app.modify(`root/label1`, { styles: { visible: false } }); 149 | // }, 150 | // "onEnter": () => { 151 | // app.modify(`root/modalp`, { styles: { visible: true } }); 152 | // app.modify(`root/modall`, { styles: { visible: true } }); 153 | // app.modify(`root/modalb`, { styles: { visible: true } }); 154 | // } 155 | // }} /> 156 | 157 | // 158 | // 159 | // { 161 | // app.modify(`root/modalp`, { styles: { visible: false } }); 162 | // app.modify(`root/modall`, { styles: { visible: false } }); 163 | // app.modify(`root/modalb`, { styles: { visible: false } }); 164 | // } 165 | // }} /> 166 | // 167 | // ; 168 | 169 | // app.append(siu); -------------------------------------------------------------------------------- /tests/default.jsx: -------------------------------------------------------------------------------- 1 | const { CLIApplication, CLIPanel, CLILabel, CLIButton } = require(`../`); 2 | 3 | const app = new CLIApplication(); 4 | 5 | const background = ; 6 | const title = ; 7 | 8 | const label1 = ; 9 | let timeout; 10 | const button1 = { 12 | timeout = setTimeout(() => { 13 | app.modify(`root/label1`, { styles: { visible: true } }); 14 | }, 500); 15 | }, 16 | "onLeave": () => { 17 | clearTimeout(timeout); 18 | app.modify(`root/label1`, { styles: { visible: false } }); 19 | }, 20 | "onEnter": () => { 21 | app.modify(`root/modalp`, { styles: { visible: true } }); 22 | app.modify(`root/modall`, { styles: { visible: true } }); 23 | app.modify(`root/modalb`, { styles: { visible: true } }); 24 | } 25 | }} />; 26 | 27 | const modalPanel = ; 28 | const modalLabel = ; 29 | const modalButton = { 31 | app.modify(`root/modalp`, { styles: { visible: false } }); 32 | app.modify(`root/modall`, { styles: { visible: false } }); 33 | app.modify(`root/modalb`, { styles: { visible: false } }); 34 | } 35 | }} />; 36 | 37 | app.append(background, title, label1, button1, modalPanel, modalLabel, modalButton); 38 | app.show(30); 39 | 40 | 41 | 42 | 43 | // const siu = 44 | // 45 | 46 | // 47 | // { 49 | // timeout = setTimeout(() => { 50 | // app.modify(`root/label1`, { styles: { visible: true } }); 51 | // }, 500); 52 | // }, 53 | // "onLeave": () => { 54 | // clearTimeout(timeout); 55 | // app.modify(`root/label1`, { styles: { visible: false } }); 56 | // }, 57 | // "onEnter": () => { 58 | // app.modify(`root/modalp`, { styles: { visible: true } }); 59 | // app.modify(`root/modall`, { styles: { visible: true } }); 60 | // app.modify(`root/modalb`, { styles: { visible: true } }); 61 | // } 62 | // }} /> 63 | 64 | // 65 | // 66 | // { 68 | // app.modify(`root/modalp`, { styles: { visible: false } }); 69 | // app.modify(`root/modall`, { styles: { visible: false } }); 70 | // app.modify(`root/modalb`, { styles: { visible: false } }); 71 | // } 72 | // }} /> 73 | // 74 | // ; 75 | 76 | // app.append(siu); -------------------------------------------------------------------------------- /tests/normal.js: -------------------------------------------------------------------------------- 1 | const { CLIApplication, CLICanvas, CLITextbox } = require(`../`); 2 | 3 | const app = new CLIApplication(); 4 | 5 | const canvas = new CLICanvas({ 6 | canvasChilds: [ 7 | { 8 | type: `rectangle`, 9 | x: 1, 10 | y: 1, 11 | width: 10, 12 | height: 5, 13 | fill: `█` 14 | }, 15 | { 16 | type: `circle`, 17 | centerX: 20, 18 | centerY: 6, 19 | radius: 5, 20 | fill: `█` 21 | }, 22 | { 23 | type: `line`, 24 | x: 1, 25 | y: 7, 26 | toX: 10, 27 | toY: 11, 28 | fill: `█` 29 | } 30 | ] 31 | }); 32 | 33 | const textbox = new CLITextbox({ 34 | placeholder: `sans`, 35 | styles: { 36 | y: 9 37 | } 38 | }) 39 | 40 | app.append(canvas, textbox); 41 | app.show(30); -------------------------------------------------------------------------------- /tests/tcg.js: -------------------------------------------------------------------------------- 1 | const { CLIApplication } = require(`../`); 2 | const global = require(`../dist/scripts/global`); 3 | 4 | const app = new CLIApplication(); 5 | 6 | const tcg = new global.TCG([ 7 | { 8 | id: `cube`, 9 | center: { x: .5, y: .8, z: .5 }, 10 | rotation: { x: .5, y: .5, z: 0 }, 11 | vertices: [ 12 | { x: 0, y: .7, z: 0 }, 13 | { x: 1, y: .7, z: 0 }, 14 | { x: 0, y: 1.3, z: 0 }, 15 | { x: 1, y: 1.3, z: 0 }, 16 | { x: 0, y: .7, z: 1 }, 17 | { x: 1, y: .7, z: 1 }, 18 | { x: 0, y: 1.3, z: 1 }, 19 | { x: 1, y: 1.3, z: 1 }, 20 | ] 21 | } 22 | ], { events: { 23 | onFrame: (objects, camera) => { 24 | const playerFirstX = objects[0].vertices[0].x; 25 | const playerFirstY = objects[0].vertices[0].y; 26 | const playerFirstZ = objects[0].vertices[0].z; 27 | const playerSecondX = objects[0].vertices[2].x; 28 | const playerSecondY = objects[0].vertices[2].y; 29 | const playerSecondZ = objects[0].vertices[3].z; 30 | const playerWidth = objects[0].vertices[1].x - objects[0].vertices[0].x; 31 | const playerHeight = objects[0].vertices[1].y - objects[0].vertices[0].y; 32 | 33 | const objectFirstX = objects[1].vertices[0].x; 34 | const objectFirstY = objects[1].vertices[0].y; 35 | const objectFirstZ = objects[1].vertices[0].z; 36 | const objectSecondX = objects[1].vertices[2].x; 37 | const objectSecondY = objects[1].vertices[2].y; 38 | const objectSecondZ = objects[1].vertices[3].z; 39 | const objectWidth = objects[1].vertices[1].x - objects[1].vertices[0].x; 40 | const objectHeight = objects[1].vertices[1].y - objects[1].vertices[0].y; 41 | 42 | if ( 43 | (playerFirstX >= 5.5 && playerFirstX <= 9) && ( 44 | (Math.floor(playerFirstY + playerSecondZ) === Math.floor(objectFirstY + objectSecondZ)) || 45 | (Math.floor(playerFirstY + playerSecondZ) === Math.floor(objectFirstY + objectSecondZ)) 46 | ) 47 | ) { 48 | process.exit(); 49 | } 50 | 51 | if (playerFirstX * 10 >= process.stdout.columns) { 52 | const idx = tcg.objects.findIndex(e => e.id.includes(`pyramid`)); 53 | if (idx !== -1) tcg.objects.splice(idx, 1); 54 | createObstacles(); 55 | 56 | objects[0].center.x = .5; 57 | objects[0].center.z = .5; 58 | objects[0].rotation.y = .5; 59 | objects[0].vertices.forEach((e, idx) => e.x = (idx + 1) % 2 === 0 ? 1 : 0); 60 | objects[0].vertices.forEach((e, idx) => e.z = idx >= 4 ? 1 : 0); 61 | } 62 | 63 | objects[0].center.x += .05 + .1; 64 | objects[0].rotation.y += .1 + .1; 65 | objects[0].vertices.map(e => e.x += .05 + .1); 66 | } 67 | } }); 68 | 69 | const createObstacles = () => { 70 | const location = { x: 7, y: Math.floor(Math.random() * 2) }; 71 | 72 | tcg.objects.push({ 73 | id: `pyramid-${Math.random().toString(36).substring(2)}`, 74 | center: { x: .5 + location.x, y: .5 + location.y, z: .5 }, 75 | rotation: { x: -.5, y: .5, z: 0 }, 76 | vertices: [ 77 | { x: 0 + location.x, y: 0 + location.y, z: 0 }, 78 | { x: 1 + location.x, y: 0 + location.y, z: 0 }, 79 | { x: 0 + location.x, y: 1 + location.y, z: 0 }, 80 | { x: 1 + location.x, y: 1 + location.y, z: 0 }, 81 | { x: .5 + location.x, y: .5 + location.y, z: 1 }, 82 | { x: .5 + location.x, y: .5 + location.y, z: 1 }, 83 | { x: .5 + location.x, y: .5 + location.y, z: 1 }, 84 | { x: .5 + location.x, y: .5 + location.y, z: 1 }, 85 | ] 86 | }); 87 | }; 88 | 89 | createObstacles(); 90 | 91 | process.stdin.on(`data`, key => { 92 | if (key === `w`) { 93 | tcg.objects[0].vertices.map(e => e.y -= .1); 94 | tcg.objects[0].center.y -= .1; 95 | } 96 | 97 | if (key === `s`) { 98 | tcg.objects[0].vertices.map(e => e.y += .1); 99 | tcg.objects[0].center.y += .1; 100 | } 101 | 102 | if (key === `d`) { 103 | tcg.objects[0].vertices.map(e => e.x += .2); 104 | tcg.objects[0].center.x += .2; 105 | } 106 | }); 107 | 108 | app.append(tcg); 109 | app.show(30); -------------------------------------------------------------------------------- /tests/tcg2.js: -------------------------------------------------------------------------------- 1 | const { CLIApplication } = require(`../`); 2 | const global = require(`../dist/scripts/TCG`); 3 | 4 | const app = new CLIApplication({ debug: true }); 5 | 6 | const tcg = new global.TCG([ 7 | { 8 | id: `cube`, 9 | center: { x: 1, y: 1, z: 1 }, 10 | rotation: { x: 0, y: 0, z: 0 }, 11 | vertices: [ 12 | { x: 0, y: 0, z: 0 }, 13 | { x: 2, y: 0, z: 0 }, 14 | { x: 0, y: 2, z: 0 }, 15 | { x: 2, y: 2, z: 0 }, 16 | { x: 0, y: 0, z: 2 }, 17 | { x: 2, y: 0, z: 2 }, 18 | { x: 0, y: 2, z: 2 }, 19 | { x: 2, y: 2, z: 2 }, 20 | ] 21 | } 22 | ], { events: { 23 | onFrame: (objects, camera) => { 24 | objects[0].rotation.x += .1; 25 | objects[0].rotation.y += .1; 26 | objects[0].rotation.z += .1; 27 | } 28 | } }); 29 | 30 | app.append(tcg); 31 | app.show(30); -------------------------------------------------------------------------------- /tests/tcg3.js: -------------------------------------------------------------------------------- 1 | const { CLIApplication } = require(`../`); 2 | const global = require(`../dist/scripts/global`); 3 | 4 | const app = new CLIApplication(); 5 | 6 | const tcg = new global.TCG([ 7 | { 8 | id: `cube`, 9 | center: { x: .5, y: .8, z: .5 }, 10 | rotation: { x: .5, y: .5, z: 0 }, 11 | vertices: [ 12 | { x: 0, y: .7, z: 0 }, 13 | { x: 1, y: .7, z: 0 }, 14 | { x: 0, y: 1.3, z: 0 }, 15 | { x: 1, y: 1.3, z: 0 }, 16 | { x: 0, y: .7, z: 1 }, 17 | { x: 1, y: .7, z: 1 }, 18 | { x: 0, y: 1.3, z: 1 }, 19 | { x: 1, y: 1.3, z: 1 }, 20 | ] 21 | } 22 | ], { events: { 23 | onFrame: (objects, camera) => { 24 | if (objects[0].vertices[0].x >= 5) { 25 | objects[0].center.x = .5; 26 | objects[0].vertices.map((e, idx) => e.x = (((idx + 1) % 2) === 0)); 27 | } 28 | 29 | objects[0].center.x += .15; 30 | objects[0].rotation.y += .2; 31 | objects[0].vertices.map(e => e.x += .15); 32 | } 33 | } }); 34 | 35 | app.append(tcg); 36 | app.show(24); -------------------------------------------------------------------------------- /transform-jsx-syntax.js: -------------------------------------------------------------------------------- 1 | module.exports = function(babel) { 2 | const { types: t } = babel; 3 | 4 | const supportedElements = ['CLILabel', 'CLIButton', 'CLIPanel', 'CLICheckbox', 'CLIRadio', 'CLIImage', 'CLITextbox', 'CLIWebview', 'CLICanvas', 'CLICustom']; 5 | 6 | return { 7 | name: 'transform-jsx-syntax', 8 | visitor: { 9 | JSXElement(path) { 10 | const elementName = path.node.openingElement.name.name; 11 | 12 | if (supportedElements.includes(elementName)) { 13 | const pathAttr = path.node.openingElement.attributes; 14 | const pathProps = pathAttr.map((attr) => { 15 | const key = attr.name.name; 16 | let value; 17 | 18 | if (t.isJSXExpressionContainer(attr.value)) value = attr.value.expression; 19 | else value = attr.value; 20 | 21 | return t.objectProperty(t.stringLiteral(key), value); 22 | }); 23 | 24 | const newElement = t.newExpression(t.identifier(elementName), [ 25 | t.objectExpression(pathProps), 26 | ]); 27 | 28 | path.replaceWith(newElement); 29 | } 30 | }, 31 | }, 32 | }; 33 | }; -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2016", 4 | "module": "commonjs", 5 | "esModuleInterop": true, 6 | "forceConsistentCasingInFileNames": true, 7 | "strict": true, 8 | "skipLibCheck": true, 9 | "outDir": "./dist", 10 | "declaration": true, 11 | "noImplicitAny": false 12 | }, 13 | "include": ["src/**/*", "scripts/**/*"], 14 | "exclude": ["node_modules"] 15 | } --------------------------------------------------------------------------------