[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-3243":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":9,"language":10,"languages":9,"totalLinesOfCode":9,"stars":11,"forks":12,"watchers":13,"openIssues":14,"contributorsCount":15,"subscribersCount":15,"size":15,"stars1d":16,"stars7d":16,"stars30d":17,"stars90d":15,"forks30d":15,"starsTrendScore":18,"compositeScore":19,"rankGlobal":9,"rankLanguage":9,"license":20,"archived":21,"fork":21,"defaultBranch":22,"hasWiki":23,"hasPages":23,"topics":24,"createdAt":9,"pushedAt":9,"updatedAt":25,"readmeContent":26,"aiSummary":27,"trendingCount":15,"starSnapshotCount":15,"syncStatus":28,"lastSyncTime":29,"discoverSource":30},3243,"classnames","JedWatson\u002Fclassnames","JedWatson","A simple javascript utility for conditionally joining classNames together",null,"JavaScript",17793,557,115,5,0,1,6,3,43.24,"MIT License",false,"main",true,[],"2026-06-12 02:00:47","# Classnames\n\n> A simple JavaScript utility for conditionally joining classNames together.\n\n\u003Cp>\n  \u003Ca aria-label=\"NPM version\" href=\"https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002Fclassnames\">\n    \u003Cimg alt=\"\" src=\"https:\u002F\u002Fimg.shields.io\u002Fnpm\u002Fv\u002Fclassnames.svg?style=for-the-badge&labelColor=0869B8\">\n  \u003C\u002Fa>\n  \u003Ca aria-label=\"License\" href=\"#\">\n    \u003Cimg alt=\"\" src=\"https:\u002F\u002Fimg.shields.io\u002Fnpm\u002Fl\u002Fclassnames.svg?style=for-the-badge&labelColor=579805\">\n  \u003C\u002Fa>\n  \u003Ca aria-label=\"Thinkmill Logo\" href=\"https:\u002F\u002Fwww.thinkmill.com.au\u002Fopen-source?utm_campaign=github-classnames\">\n    \u003Cimg src=\"https:\u002F\u002Fimg.shields.io\u002Fbadge\u002FSponsored%20BY%20Thinkmill-ed0000.svg?style=for-the-badge&logo=data:image\u002Fsvg+xml;base64,PHN2ZyB3aWR0aD0iNTg2IiBoZWlnaHQ9IjU4NiIgdmlld0JveD0iMCAwIDU4NiA1ODYiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMF8xOTk2XzQwNikiPgo8cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTU4NiAyOTNDNTg2IDQ1NC44MTkgNDU0LjgxOSA1ODYgMjkzIDU4NkMxMzEuMTgxIDU4NiAwIDQ1NC44MTkgMCAyOTNDMCAxMzEuMTgxIDEzMS4xODEgMCAyOTMgMEM0NTQuODE5IDAgNTg2IDEzMS4xODEgNTg2IDI5M1pNMjA1Ljc3NiAzNTguOTQ0QzE5MS4zNzYgMzU4Ljk0NCAxODUuOTA0IDM1Mi4zMiAxODUuOTA0IDMzNS45MDRWMjYyLjc1MkgyMTQuNDE2VjIzNy42OTZIMTg1LjkwNFYyMDEuMTJIMTUzLjA3MlYyMzcuNjk2SDEyOC41OTJWMjYyLjc1MkgxNTMuMDcyVjM0MC44QzE1My4wNzIgMzcyLjc2OCAxNjYuNjA4IDM4NS43MjggMTk3LjQyNCAzODUuNzI4QzIwMy40NzIgMzg1LjcyOCAyMTAuOTYgMzg0LjU3NiAyMTUuODU2IDM4My4xMzZWMzU3LjUwNEMyMTMuNTUyIDM1OC4zNjggMjA5LjUyIDM1OC45NDQgMjA1Ljc3NiAzNTguOTQ0Wk00MDcuMzc2IDIzNC4yNEMzODUuMiAyMzQuMjQgMzcxLjA4OCAyNDQuMDMyIDM2MC40MzIgMjYwLjczNkMzNTIuOTQ0IDI0My40NTYgMzM3LjM5MiAyMzQuMjQgMzE3LjIzMiAyMzQuMjRDMjk5Ljk1MiAyMzQuMjQgMjg2Ljk5MiAyNDEuMTUyIDI3Ni42MjQgMjU1LjI2NEgyNzYuMDQ4VjIzNy42OTZIMjQ0LjY1NlYzODRIMjc3LjQ4OFYzMDUuNjY0QzI3Ny40ODggMjc3LjQ0IDI4OC43MiAyNjAuNzM2IDMwOC4zMDQgMjYwLjczNkMzMjUuMjk2IDI2MC43MzYgMzM0LjUxMiAyNzIuODMyIDMzNC41MTIgMjkzLjU2OFYzODRIMzY3LjM0NFYzMDUuMDg4QzM2Ny4zNDQgMjc3LjE1MiAzNzguODY0IDI2MC43MzYgMzk4LjE2IDI2MC43MzZDNDE0LjU3NiAyNjAuNzM2IDQyNC42NTYgMjcxLjEwNCA0MjQuNjU2IDI5Ny4wMjRWMzg0SDQ1Ny40ODhWMjkzLjg1NkM0NTcuNDg4IDI1NC40IDQzOC40OCAyMzQuMjQgNDA3LjM3NiAyMzQuMjRaIiBmaWxsPSJ3aGl0ZSIvPgo8L2c+CjxkZWZzPgo8Y2xpcFBhdGggaWQ9ImNsaXAwXzE5OTZfNDA2Ij4KPHJlY3Qgd2lkdGg9IjU4NiIgaGVpZ2h0PSI1ODYiIGZpbGw9IndoaXRlIi8+CjwvY2xpcFBhdGg+CjwvZGVmcz4KPC9zdmc+Cg==&labelColor=C60200&locoColor=white&logoWidth=0\">\n  \u003C\u002Fa>\n\n  \u003C\u002Fp>\n\nInstall from the [npm registry](https:\u002F\u002Fwww.npmjs.com\u002F) with your package manager:\n```bash\nnpm install classnames\n```\n\nUse with [Node.js](https:\u002F\u002Fnodejs.org\u002Fen\u002F), [Browserify](https:\u002F\u002Fbrowserify.org\u002F), or [webpack](https:\u002F\u002Fwebpack.github.io\u002F):\n\n```js\nconst classNames = require('classnames');\nclassNames('foo', 'bar'); \u002F\u002F => 'foo bar'\n```\n\nAlternatively, you can simply include `index.js` on your page with a standalone `\u003Cscript>` tag and it will export a global `classNames` method, or define the module if you are using RequireJS.\n\n### Project philosophy\n\nWe take the stability and performance of this package seriously, because it is run millions of times a day in browsers all around the world. Updates are thoroughly reviewed for performance implications before being released, and we have a comprehensive test suite.\n\nClassnames follows the [SemVer](https:\u002F\u002Fsemver.org\u002F) standard for versioning.\n\nThere is also a [Changelog](https:\u002F\u002Fgithub.com\u002FJedWatson\u002Fclassnames\u002Fblob\u002Fmaster\u002FHISTORY.md).\n\n## Usage\n\nThe `classNames` function takes any number of arguments which can be a string or object.\nThe argument `'foo'` is short for `{ foo: true }`. If the value associated with a given key is falsy, that key won't be included in the output.\n\n```js\nclassNames('foo', 'bar'); \u002F\u002F => 'foo bar'\nclassNames('foo', { bar: true }); \u002F\u002F => 'foo bar'\nclassNames({ 'foo-bar': true }); \u002F\u002F => 'foo-bar'\nclassNames({ 'foo-bar': false }); \u002F\u002F => ''\nclassNames({ foo: true }, { bar: true }); \u002F\u002F => 'foo bar'\nclassNames({ foo: true, bar: true }); \u002F\u002F => 'foo bar'\n\n\u002F\u002F lots of arguments of various types\nclassNames('foo', { bar: true, duck: false }, 'baz', { quux: true }); \u002F\u002F => 'foo bar baz quux'\n\n\u002F\u002F other falsy values are just ignored\nclassNames(null, false, 'bar', undefined, 0, { baz: null }, ''); \u002F\u002F => 'bar'\n```\n\nArrays will be recursively flattened as per the rules above:\n\n```js\nconst arr = ['b', { c: true, d: false }];\nclassNames('a', arr); \u002F\u002F => 'a b c'\n```\n\n### Dynamic class names with ES2015\n\nIf you're in an environment that supports [computed keys](https:\u002F\u002Fwww.ecma-international.org\u002Fecma-262\u002F6.0\u002F#sec-object-initializer) (available in ES2015 and Babel) you can use dynamic class names:\n\n```js\nconst buttonType = 'primary';\nclassNames({ [`btn-${buttonType}`]: true });\n```\n\n### Usage with React.js\n\nThis package is the official replacement for `classSet`, which was originally shipped in the React.js Addons bundle.\n\nOne of its primary use cases is to make dynamic and conditional `className` props simpler to work with (especially more so than conditional string manipulation). So where you may have the following code to generate a `className` prop for a `\u003Cbutton>` in React:\n\n```js\nimport React, { useState } from 'react';\n\nexport default function Button (props) {\n  const [isPressed, setIsPressed] = useState(false);\n  const [isHovered, setIsHovered] = useState(false);\n\n  let btnClass = 'btn';\n  if (isPressed) btnClass += ' btn-pressed';\n  else if (isHovered) btnClass += ' btn-over';\n\n  return (\n    \u003Cbutton\n      className={btnClass}\n      onMouseDown={() => setIsPressed(true)}\n      onMouseUp={() => setIsPressed(false)}\n      onMouseEnter={() => setIsHovered(true)}\n      onMouseLeave={() => setIsHovered(false)}\n    >\n      {props.label}\n    \u003C\u002Fbutton>\n  );\n}\n```\n\nYou can express the conditional classes more simply as an object:\n\n```js\nimport React, { useState } from 'react';\nimport classNames from 'classnames';\n\nexport default function Button (props) {\n  const [isPressed, setIsPressed] = useState(false);\n  const [isHovered, setIsHovered] = useState(false);\n\n  const btnClass = classNames({\n    btn: true,\n    'btn-pressed': isPressed,\n    'btn-over': !isPressed && isHovered,\n  });\n\n  return (\n    \u003Cbutton\n      className={btnClass}\n      onMouseDown={() => setIsPressed(true)}\n      onMouseUp={() => setIsPressed(false)}\n      onMouseEnter={() => setIsHovered(true)}\n      onMouseLeave={() => setIsHovered(false)}\n    >\n      {props.label}\n    \u003C\u002Fbutton>\n  );\n}\n```\n\nBecause you can mix together object, array and string arguments, supporting optional `className` props is also simpler as only truthy arguments get included in the result:\n\n```js\nconst btnClass = classNames('btn', this.props.className, {\n  'btn-pressed': isPressed,\n  'btn-over': !isPressed && isHovered,\n});\n```\n\n### Alternate `dedupe` version\n\nThere is an alternate version of `classNames` available which correctly dedupes classes and ensures that falsy classes specified in later arguments are excluded from the result set.\n\nThis version is slower (about 5x) so it is offered as an opt-in.\n\nTo use the dedupe version with Node.js, Browserify, or webpack:\n\n```js\nconst classNames = require('classnames\u002Fdedupe');\n\nclassNames('foo', 'foo', 'bar'); \u002F\u002F => 'foo bar'\nclassNames('foo', { foo: false, bar: true }); \u002F\u002F => 'bar'\n```\n\nFor standalone (global \u002F AMD) use, include `dedupe.js` in a `\u003Cscript>` tag on your page.\n\n### Alternate `bind` version (for [css-modules](https:\u002F\u002Fgithub.com\u002Fcss-modules\u002Fcss-modules))\n\nIf you are using [css-modules](https:\u002F\u002Fgithub.com\u002Fcss-modules\u002Fcss-modules), or a similar approach to abstract class 'names' and the real `className` values that are actually output to the DOM, you may want to use the `bind` variant.\n\n_Note that in ES2015 environments, it may be better to use the \"dynamic class names\" approach documented above._\n\n```js\nconst classNames = require('classnames\u002Fbind');\n\nconst styles = {\n  foo: 'abc',\n  bar: 'def',\n  baz: 'xyz',\n};\n\nconst cx = classNames.bind(styles);\n\nconst className = cx('foo', ['bar'], { baz: true }); \u002F\u002F => 'abc def xyz'\n```\n\nReal-world example:\n\n```js\n\u002F* components\u002Fsubmit-button.js *\u002F\nimport { useState } from 'react';\nimport classNames from 'classnames\u002Fbind';\nimport styles from '.\u002Fsubmit-button.css';\n\nconst cx = classNames.bind(styles);\n\nexport default function SubmitButton ({ store, form }) {\n  const [submissionInProgress, setSubmissionInProgress] = useState(store.submissionInProgress);\n  const [errorOccurred, setErrorOccurred] = useState(store.errorOccurred);\n  const [valid, setValid] = useState(form.valid);\n\n  const text = submissionInProgress ? 'Processing...' : 'Submit';\n  const className = cx({\n    base: true,\n    inProgress: submissionInProgress,\n    error: errorOccurred,\n    disabled: valid,\n  });\n\n  return \u003Cbutton className={className}>{text}\u003C\u002Fbutton>;\n}\n```\n\n## Polyfills needed to support older browsers\n\n#### `classNames >=2.0.0`\n\n`Array.isArray`: see [MDN](https:\u002F\u002Fdeveloper.mozilla.org\u002Fen-US\u002Fdocs\u002FWeb\u002FJavaScript\u002FReference\u002FGlobal_Objects\u002FArray\u002FisArray) for details about unsupported older browsers (e.g. \u003C= IE8) and a simple polyfill.\n\n## LICENSE [MIT](LICENSE)\n\nCopyright (c) 2018 Jed Watson.\nCopyright of the Typescript bindings are respective of each contributor listed in the definition file.\n","classnames 是一个用于条件性组合 CSS 类名的简单 JavaScript 工具。其核心功能是通过逻辑判断将多个类名动态地连接起来，支持多种使用方式，包括 Node.js、Browserify 和 webpack 等环境，并且可以直接在浏览器中以全局变量的形式使用。该项目具有高度的稳定性和性能优化，适用于任何需要根据条件动态生成 HTML 元素类名的前端开发场景，如响应式布局或基于状态变化的样式调整。MIT 许可证下开源，得到了广泛的应用和社区支持。",2,"2026-06-11 02:53:03","top_language"]