{"id":27203982,"url":"https://github.com/sebastiengllmt/material-chalk","last_synced_at":"2025-10-13T07:15:57.487Z","repository":{"id":265957210,"uuid":"896920814","full_name":"SebastienGllmt/material-chalk","owner":"SebastienGllmt","description":"Generate beautiful colors from namespaces based on color theory","archived":false,"fork":false,"pushed_at":"2024-12-15T08:21:23.000Z","size":1677,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-09-18T10:59:11.098Z","etag":null,"topics":["chalk","console","log","logging","material","material-design","terminal"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/SebastienGllmt.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-12-01T16:23:41.000Z","updated_at":"2025-01-21T18:10:03.000Z","dependencies_parsed_at":"2025-04-12T02:01:18.320Z","dependency_job_id":null,"html_url":"https://github.com/SebastienGllmt/material-chalk","commit_stats":null,"previous_names":["sebastiengllmt/material-chalk"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/SebastienGllmt/material-chalk","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SebastienGllmt%2Fmaterial-chalk","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SebastienGllmt%2Fmaterial-chalk/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SebastienGllmt%2Fmaterial-chalk/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SebastienGllmt%2Fmaterial-chalk/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/SebastienGllmt","download_url":"https://codeload.github.com/SebastienGllmt/material-chalk/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SebastienGllmt%2Fmaterial-chalk/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279014113,"owners_count":26085462,"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","status":"online","status_checked_at":"2025-10-13T02:00:06.723Z","response_time":61,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["chalk","console","log","logging","material","material-design","terminal"],"created_at":"2025-04-09T22:57:08.463Z","updated_at":"2025-10-13T07:15:57.468Z","avatar_url":"https://github.com/SebastienGllmt.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://www.npmjs.com/package/material-chalk\"\u003e\n    \u003cpicture\u003e\n      \u003cimg src=\"https://img.shields.io/npm/v/material-chalk\" alt=\"NPM\"\u003e\n    \u003c/picture\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://jsr.io/@sebastiengllmt/material-chalk\"\u003e\n    \u003cimg src=\"https://jsr.io/badges/@sebastiengllmt/material-chalk\" alt=\"JSR\" /\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\n# Overview\n\n`material-chalk` is a library for generating beautiful colors for namespaces based on color theory in a way that is deterministic and extensible.\n\nIt is built using the latest Typescript and ESM standards, while being compatible with older standards when needed.\n\nIt is focused on being an opinionated standard to encourage consistent colors for the same namespace across different programming languages and tools, while still being composable with any frontend from [terminal-focused](https://www.npmjs.com/package/chalk) libraries to full GUI applications.\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"https://github.com/user-attachments/assets/897173dc-0cfa-4c27-9443-d19b85ebf006\" alt=\"lib-preview\" /\u003e\n\u003c/p\u003e\n\n# How to Use\n\n## Simple color\n\n\u003e :warning: your terminal must support `truecolor` to see all possible colors. Although tools like `chalk` attempt to detect this automatically, you may have to set [chalk.level](https://github.com/chalk/chalk?tab=readme-ov-file#chalklevel) manually or set `export COLORTERM=truecolor` in your shell (many shells use `xterm-256color` by default which limits the color range).\n\n\n```typescript\nimport chalk from 'chalk';\nimport { createMaterial, Format } from 'material-chalk'\n\nconst chalkFormat = Format.Chalk(chalk)\nconst namespaceFoo = createMaterial('foo').formatAs(chalkFormat);\nconsole.log(\n  namespaceFoo(`Hello, world!`)\n);\n```\n\nThere are multiple format options available, notably:\n- `Format.Htc` for the direct HCT (hue, chroma, tone) representation from Material Design\n- `Format.Hex` for a hex color representation (ex: `#ff0000`)\n- `Format.Custom` for a custom format function that you provide\n- `Format.Chalk` for to use Chalk to print with color\n- `Format.Scheme` for generating palettes (see [below](#building-a-full-palette))\n\n## Creating nested namespaces\n\n`material-chalk` allows you to define namespaces both statically and dynamically.\n\nStatic nested namespaces\n```typescript\nconst nestedNamespace =\n  createMaterial(['parent', 'child'])\n  .formatAs(chalkFormat);\n```\nDynamic nested namespaces\n```typescript\nconst parentNamespace = createMaterial('parent');\nconst nestedNamespace = parentNamespace\n  .subMaterial('child')\n  .formatAs(chalkFormat);\n```\n\nNamespaces leverage the `blend` concept in Material Design which shifts the hue of the children towards that of the parent.\n\n![blend-example](https://github.com/user-attachments/assets/b21cd532-0ad6-452a-b3b9-d2e6a3313f50)\n\n## Building a full palette\n\nYou can easily build full UIs around the color generated for a namespace using Material Design v3 [dynamic color schemes](https://m3.material.io/styles/color/choosing-a-scheme).\n\nMaterial Design allows you to create your own color scheme [manually](https://github.com/material-foundation/material-color-utilities/blob/main/dev_guide/creating_color_scheme.md#typescript-1), but it also comes with many [built-in schemes](https://github.com/material-foundation/material-color-utilities/tree/main/typescript/scheme).\n\nMaterial Design will modify the hue/chroma/tone of your colors as needed for (this is by design), but we provide a helper function to convert a scheme to one that more strongly retains the color generated for the namespace: `sourceAsPrimary`.\n\n```typescript\nimport chalk from 'chalk';\nimport { createMaterial, sourceAsPrimary, Format } from 'material-chalk'\nimport { hexFromArgb, SchemeVibrant } from \"@material/material-color-utilities\";\n\n// convert one of the many built-in schemes\n// to one that more accurately uses the namespace's color\nconst SchemeVibrantNamespace = Format.Scheme(sourceAsPrimary(SchemeVibrant))(\n  true, // isDark\n  0 // contrast level (for accessibility). 0 is normal contrast\n)\n\n// instantiate our new color scheme on a specific namespace\nconst namespaceFoo = createMaterial('foo').formatAs(SchemeVibrantNamespace);\n\n// utility function just to demo functionality\nfunction printWithChalk(color: number, text: string) {\n  console.log(chalk.hex(hexFromArgb(color)).bold(text));\n}\n\nprintWithChalk(namespaceFoo.primaryPaletteKeyColor, 'Primary');\nprintWithChalk(namespaceFoo.secondaryPaletteKeyColor, 'Secondary');\nprintWithChalk(namespaceFoo.tertiaryPaletteKeyColor, 'Tertiary');\nprintWithChalk(namespaceFoo.neutralPaletteKeyColor, 'Neutral');\nprintWithChalk(namespaceFoo.neutralVariantPaletteKeyColor, 'Neutral Variant');\n```\n\nHere are some examples of how a namespace looks like under different schemes:\n\n![scheme-preview](https://github.com/user-attachments/assets/1c3b13f8-75a4-4592-a3aa-c650f6444bbd)\n\n### Material Design v2\n\nIf you're still using Material Design v2, you can still use this library to generate your palette\n\n```typescript\nimport chalk from 'chalk';\nimport { createMaterial, Format } from \"@material/material-color-utilities\";\nimport { hctForNamespace } from 'material-chalk'\n\nconst namespaceFoo = createMaterial('foo').formatAs(Format.Hct);\n\n// utility function just to demo functionality\nfunction printWithChalk(color: number, text: string) {\n  console.log(chalk.hex(hexFromArgb(color)).bold(text));\n}\n\nconst corePalette = CorePalette.of(namespaceFoo.toInt());\nprintWithChalk(corePalette.a1.keyColor.toInt(), \"Primary\");\nprintWithChalk(corePalette.a2.keyColor.toInt(), \"Secondary\");\nprintWithChalk(corePalette.a3.keyColor.toInt(), \"Tertiary\");\nprintWithChalk(corePalette.n1.keyColor.toInt(), \"Neutral 1\");\nprintWithChalk(corePalette.n2.keyColor.toInt(), \"Neutral 2\");\n```\n\n## Utility functions\n\n`material-chalk` provides a few utility functions to make it easier to work with colors.\n\n### Brand colors with `registerBrand` and `matchColor` \n\nSometimes, for business reasons, you need to enforce that a namespace is associated with a specific brand color. In those cases, you can `registerBrand` to override cache the color that should be generated for a specific namespace.\n\nIf you want to make sure your color matches the same brightness as other colors in `material-chalk`, you can use the `matchColor` function to adjust the brightness (internally, this will try its best to maintain your brand color)\n\n```typescript\nimport { createMaterial, matchColor, registerBrand, Format } from 'material-chalk'\n\nconst brandColor = matchColor(\"#ff0000\");\nregisterBrand(\"my-brand\", brandColor.formatAs(Format.Hct));\n\n// this will retrieve the cached color\nconst namespace = createMaterial(\"my-brand\").formatAs(Format.Hct);\n```\n\n### Printing chains of namespaces with `chainedMessage`\n\nOften times you want to print a chain of all the namespaces leading up to a specific message. You can use `chainedMessage` to do this:\n\n```typescript\nimport chalk from 'chalk';\nimport { createMaterial, chainedMessage, Format } from 'material-chalk'\n\nconst chalkFormat = Format.Chalk(chalk)\nconst namespaceFoo = createMaterial('foo').formatAs(chalkFormat);\nconsole.log(\n  chainedMessage(chalk, ['root-namespace', 'middle', 'child'], 'Hello, world!')\n);\n```\n\nHere is a preview of what it looks like for different chain lengths:\n\n![chained-message-preview](https://github.com/user-attachments/assets/910bb26c-c213-40d8-bac4-fba10806d711)\n\n## Performance\n\n`material-chalk` caches namespaces generated by default, meaning the performance hit is negligible for the majority of use-cases.\n\nPerformance does matter in the not-so-realistic scenarios that you are generating millions of random strings as namespaces. In this case:\n1. It takes `0.01` milliseconds per namespace color generation *(cached)*\n2. It takes some memory to cache the namespaces\n\nIf you need to save memory, you can disable the cache:\n\n```typescript\nimport { createMaterial } from 'material-chalk'\n\nconst namespaceFoo = createMaterial(\n  'foo',\n  { cache: false }\n);\n```\n\n# Problems with existing implementations\n\nThere are other ad-hoc implementations of generating colors from strings, but they generally have at least one of the following issues:\n\n| Issue                                       | Other libraries                                                                                                | `material-chalk`                                                  |\n|---------------------------------------------|----------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------|\n| **Legacy code**                             | old and do not have Typescript/ESM support                                                                     | built on the latest best practices                                |\n| **Poor color choices**                      | no justification based on color theory for why a specific choice was made, leading to poor color choices       | full justification for choices [here](https://github.com/SebastienGllmt/material-chalk/blob/master/Justifications.md)                       |\n| **Not extensible** ex: color sub-namespaces | provide no opinionated way on how to extend it for a given namespace                                           | leverage Material Design to build for palettes for your namespace |\n| **Lack of standardization**                 | provide too many configurations leading to inconsistent colors across tools \u0026 languages for the same namespace | opinionated deterministic choices based on color theory           |\n| **Limited to RGB**                          | only support the RGB range                                                                                     | supports colors outside the standard RGB range                    |\n| **Poor randomness**                         | depend on non-deterministic poor sources of randomness like Math.random() internally                           | uses fnv-1a for good deterministic seeding of randomness          |\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsebastiengllmt%2Fmaterial-chalk","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsebastiengllmt%2Fmaterial-chalk","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsebastiengllmt%2Fmaterial-chalk/lists"}