{"id":25473425,"url":"https://github.com/drizzle-team/hanji","last_synced_at":"2025-10-08T04:11:27.345Z","repository":{"id":57906553,"uuid":"528443981","full_name":"drizzle-team/hanji","owner":"drizzle-team","description":"Designless command line user interface builder for nodejs+typescript","archived":false,"fork":false,"pushed_at":"2022-09-06T19:27:01.000Z","size":12,"stargazers_count":65,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2024-10-30T04:29:53.482Z","etag":null,"topics":["command-line","nodejs","prompt","typescript","typescript-library"],"latest_commit_sha":null,"homepage":"https://github.com/drizzle-team/armin","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/drizzle-team.png","metadata":{"files":{"readme":"readme.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2022-08-24T13:48:16.000Z","updated_at":"2024-09-30T05:07:08.000Z","dependencies_parsed_at":"2023-01-17T21:45:32.466Z","dependency_job_id":null,"html_url":"https://github.com/drizzle-team/hanji","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/drizzle-team%2Fhanji","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/drizzle-team%2Fhanji/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/drizzle-team%2Fhanji/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/drizzle-team%2Fhanji/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/drizzle-team","download_url":"https://codeload.github.com/drizzle-team/hanji/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":239119188,"owners_count":19584970,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["command-line","nodejs","prompt","typescript","typescript-library"],"created_at":"2025-02-18T10:21:15.671Z","updated_at":"2025-10-08T04:11:22.307Z","avatar_url":"https://github.com/drizzle-team.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"Hanji is a designless command line user interface builder for nodejs+typescript.\nby [@_alexblokh](https://twitter.com/_alexblokh)\n\nYou can implement prompts by extending `Prompt` class   \nBelow is an example of how to implement `Select` with utility `SelectData` bundle provided from the library   \nI will provide more view agnostic datasets to make implementing custom views like `input` a breath    \n```typescript\nimport color from \"kleur\";\nimport { ITerminal, Prompt, render, SelectData } from \"hanji\";\n\nexport class Select extends Prompt\u003c{ index: number; value: string }\u003e {\n  private readonly data: SelectState\u003c{ label: string; value: string }\u003e;\n  private readonly spinner: () =\u003e string;\n  private timeout: NodeJS.Timer | undefined;\n\n  constructor(items: string[]) {\n    super();\n    this.on(\"attach\", (terminal) =\u003e terminal.toggleCursor(\"hide\"));\n    this.on(\"detach\", () =\u003e clearInterval(this.timeout));\n\n    this.data = new SelectState(\n      items.map((it) =\u003e ({ label: it, value: `${it}-value` }))\n    );\n    this.data.bind(this);\n  }\n\n  render(status: \"idle\" | \"submitted\" | \"aborted\"): string {\n    if (status === \"submitted\" || status === \"aborted\") {\n      return \"\";\n    }\n\n    let text = \"\";\n    this.data.items.forEach((it, idx) =\u003e {\n      text +=\n        idx === this.data.selectedIdx\n          ? `${color.green(\"❯ \" + it.label)}`\n          : `  ${it.label}`;\n      text += idx != this.data.items.length - 1 ? \"\\n\" : \"\";\n    });\n\n    return text;\n  }\n\n  result() {\n    return {\n      index: this.data.selectedIdx,\n      value: this.data.items[this.data.selectedIdx]!.value!,\n    };\n  }\n}\n\n const { status, data } = await render(\n  new Select([\"user1\", \"user2\", \"user3\", \"user4\"])\n);\nif (status === \"aborted\") return;\nconsole.log(data);\n// { index: 0, value: 'users1' }\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdrizzle-team%2Fhanji","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdrizzle-team%2Fhanji","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdrizzle-team%2Fhanji/lists"}