pax_global_header00006660000000000000000000000064150221075600014510gustar00rootroot0000000000000052 comment=40d8feed6aafd389eed0a20acb6d9e174fe2fa24 node-tailwind-merge-3.3.1/000077500000000000000000000000001502210756000153475ustar00rootroot00000000000000node-tailwind-merge-3.3.1/.github/000077500000000000000000000000001502210756000167075ustar00rootroot00000000000000node-tailwind-merge-3.3.1/.github/CODE_OF_CONDUCT.md000066400000000000000000000017531502210756000215140ustar00rootroot00000000000000# tailwind-merge Community Guidelines The following community guidelines are based on [The Ruby Community Conduct Guidelines](https://www.ruby-lang.org/en/conduct) which are also used by [Tailwind CSS](https://github.com/tailwindlabs/tailwindcss/blob/master/.github/CODE_OF_CONDUCT.md). This document provides community guidelines for a safe, respectful, productive, and collaborative place for any person who is willing to contribute to the tailwind-merge project. It applies to all “collaborative space”, which is defined as community communications channels (such as issues, discussions, pull requests, commit comments, etc.). - Participants will be tolerant of opposing views. - Participants must ensure that their language and actions are free of personal attacks and disparaging personal remarks. - When interpreting the words and actions of others, participants should always assume good intentions. - Behaviour which can be reasonably considered harassment will not be tolerated. node-tailwind-merge-3.3.1/.github/CONTRIBUTING.md000066400000000000000000000056171502210756000211510ustar00rootroot00000000000000# Contributing Contributions are welcome and will be fully credited. Please take a moment to review this document before creating an issue or pull request. It is based on the [Tiptap contributing guidelines](https://github.com/ueberdosis/tiptap/blob/main/CONTRIBUTING.md). ## Etiquette This project is open source, and as such, the maintainers give their free time to build and maintain the source code held within. They make the code freely available in the hope that it will be of use to other developers. It would be extremely unfair for them to suffer abuse or anger for their hard work. Please be considerate towards maintainers when raising issues or presenting pull requests. Let's show the world that developers are civilized and selfless people. It's the duty of the maintainer to ensure that all submissions to the project are of sufficient quality to benefit the project. Many developers have different skillsets, strengths, and weaknesses. Respect the maintainer's decision, and do not be upset or abusive if your submission is not used. See [CODE OF CONDUCT](CODE_OF_CONDUCT.md) for more info. ## Viability When requesting or submitting new features, first consider whether it might be useful to others. Open source projects are used by many developers, who may have entirely different needs to your own. Think about whether or not your feature is likely to be used by other users of the project. ## Procedure Before filing an issue: - Attempt to replicate the problem, to ensure that it wasn't a coincidental incident. - Check to make sure your feature suggestion isn't already present within the project. - Check the pull requests tab to ensure that the bug doesn't have a fix in progress. - Check the pull requests tab to ensure that the feature isn't already in progress. Before submitting a pull request: - Check the codebase to ensure that your feature doesn't already exist. - Check the pull requests to ensure that another person hasn't already submitted the feature or fix. ## Requirements - **Document any change in behaviour** - Make sure the `README.md` and any other relevant documentation are kept up-to-date. - **One pull request per feature** - If you want to do more than one thing, send multiple pull requests. - **Send coherent history** - Make sure each individual commit in your pull request is meaningful. If you had to make multiple intermediate commits while developing, please [squash them](https://www.git-scm.com/book/en/v2/Git-Tools-Rewriting-History#Changing-Multiple-Commit-Messages) before submitting. ## Development You will need [Node.js](https://nodejs.org) and [yarn](https://classic.yarnpkg.com) installed on your machine. I recommend running tests in watch mode while you work on the code. Then the correct subset of tests is being run as you modify source code or the tests itself. ```sh # Install dependencies $ yarn # Run tests $ yarn test --watch ``` Happy coding! node-tailwind-merge-3.3.1/.github/ISSUE_TEMPLATE/000077500000000000000000000000001502210756000210725ustar00rootroot00000000000000node-tailwind-merge-3.3.1/.github/ISSUE_TEMPLATE/bug-report.md000066400000000000000000000013161502210756000235030ustar00rootroot00000000000000--- name: Bug Report about: Report that something isn't working as expected in tailwind-merge --- ### Describe the bug ### To Reproduce ### Expected behavior ### Environment - tailwind-merge version: [e.g. 1.13.1] ### Additional context node-tailwind-merge-3.3.1/.github/ISSUE_TEMPLATE/config.yml000066400000000000000000000011341502210756000230610ustar00rootroot00000000000000blank_issues_enabled: true contact_links: - name: Get Help url: https://github.com/dcastil/tailwind-merge/discussions/new?category=help about: If you can't get something to work the way you expect, open a question in the discussion forums. - name: Feature Request url: https://github.com/dcastil/tailwind-merge/discussions/new?category=ideas about: Suggest any ideas you have using the discussion forum. - name: Start discussion url: https://github.com/dcastil/tailwind-merge/discussions about: Anything else on your mind? Check out the discussions forum. node-tailwind-merge-3.3.1/.github/SECURITY.md000066400000000000000000000022121502210756000204750ustar00rootroot00000000000000# Security Policy ## Supported Versions Security updates are available for the two latest major versions. In the event of a security vulnerability in tailwind-merge, a patch release with a fix will be made to all affected latest major versions. I.e. if the two latest major versions of tailwind-merge would be `v9.3.4` and `v8.10.0` and a security vulnerability would get discovered which affected all versions from `v6.0.0` to `v9.3.4`, then at least the releases `v9.3.5` and `v8.10.1` would be made to fix the security vulnerability. ## Reporting a Vulnerability Please report vulnerabilities privately via GitHub at https://github.com/dcastil/tailwind-merge/security. In case it is not possible to report a vulnerability via GitHub, you can send me an email to metro_comical_03@icloud.com. However, I might change or disable this email address at any time depending on how much spam I get through it. You can expect an answer from me within 24 hours most of the time. However, if I'm travelling and don't have good reception, it could take up to a few days. Usually I set my GitHub status to busy when I expect to be unresponsive for more than a day. node-tailwind-merge-3.3.1/.github/actions/000077500000000000000000000000001502210756000203475ustar00rootroot00000000000000node-tailwind-merge-3.3.1/.github/actions/metrics-report/000077500000000000000000000000001502210756000233265ustar00rootroot00000000000000node-tailwind-merge-3.3.1/.github/actions/metrics-report/.gitignore000066400000000000000000000000051502210756000253110ustar00rootroot00000000000000temp node-tailwind-merge-3.3.1/.github/actions/metrics-report/action.yml000066400000000000000000000006041502210756000253260ustar00rootroot00000000000000name: 'metrics-report-action' author: 'Dany Castillo' description: 'Posts a comment with a report about changes in important metrics related to tailwind-merge' inputs: github_token: description: 'Github token of the repository (automatically created by Github)' default: '${{ github.token }}' required: false runs: using: 'node20' main: 'src/main.mjs' node-tailwind-merge-3.3.1/.github/actions/metrics-report/package.json000066400000000000000000000007151502210756000256170ustar00rootroot00000000000000{ "name": "metrics-report-action", "version": "0.1.0", "private": true, "author": "Dany Castillo", "scripts": { "start": "node src/main.mjs" }, "dependencies": { "@actions/core": "^1.11.1", "@actions/exec": "^1.1.1", "@actions/github": "^6.0.1", "@octokit/types": "^14.1.0", "@octokit/webhooks-definitions": "^3.67.3", "esbuild": "^0.25.5", "rollup": "^4.41.1" } } node-tailwind-merge-3.3.1/.github/actions/metrics-report/src/000077500000000000000000000000001502210756000241155ustar00rootroot00000000000000node-tailwind-merge-3.3.1/.github/actions/metrics-report/src/get-package-size.mjs000066400000000000000000000150051502210756000277510ustar00rootroot00000000000000// @ts-check import fs from 'fs/promises' import path from 'path' import { promisify } from 'util' import zlib from 'zlib' import core from '@actions/core' import { exec } from '@actions/exec' import { transform } from 'esbuild' import { rollup } from 'rollup' import { actionRootPath, repoRootPath } from './utils/path.mjs' /** * @typedef {object} GetPackageSizeOptions * @property {boolean=} shouldOmitFailures */ /** * @param {GetPackageSizeOptions=} options */ export async function getPackageSize(options = {}) { await buildPackage() return getEntryPointSizes(options) } async function buildPackage() { core.info('Installing dependencies') await exec('yarn install --frozen-lockfile', [], { cwd: repoRootPath }) core.info('Building package') await exec('yarn build', [], { cwd: repoRootPath }) } /** * @typedef {object} EntryPointSize * @property {BundleSize} bundleSize * @property {BundleSize[]=} singleExportSizes */ /** * @param {GetPackageSizeOptions} param0 * @returns {Promise} */ async function getEntryPointSizes({ shouldOmitFailures }) { core.info('Getting entry point configs') const entryPointConfigs = await getEntryPointConfigs() core.info('Getting bundle sizes') const maybeEntryPointSizes = await Promise.all( entryPointConfigs.map(async (entryPointConfig, entryPointIndex) => { const entryPointBundlePath = path.resolve(repoRootPath, entryPointConfig.bundlePath) const bundle = await getBundle(entryPointConfig, entryPointBundlePath).catch( (error) => { if (shouldOmitFailures) { core.info( `Failed to get bundle for ${entryPointConfig.entryPoint}: ${error.message}`, ) return } throw error }, ) if (!bundle) { return } const [bundleSize, singleExportSizes] = await Promise.all([ getBundleSize(entryPointConfig.entryPoint, bundle), getSingleExportBundleSizes( entryPointConfig, entryPointIndex, entryPointBundlePath, bundle, ), ]) return { bundleSize, singleExportSizes, } }), ) /** @type {any} */ const entryPointSizes = maybeEntryPointSizes.filter((bundleSize) => bundleSize !== undefined) return entryPointSizes } /** * @typedef {object} EntryPointConfiguration * @property {string} entryPoint * @property {string} bundlePath * @property {'esm' | 'cjs'} format */ /** * @returns {Promise} */ async function getEntryPointConfigs() { const pkg = (await import('../../../../package.json', { assert: { type: 'json' } })).default return Object.entries(pkg.exports).flatMap(([relativeEntryPointPath, bundleObject]) => { const entryPointPath = path.join('tailwind-merge', relativeEntryPointPath) /** @type {EntryPointConfiguration[]} */ const entryPointConfigs = [] if (bundleObject.import) { entryPointConfigs.push({ entryPoint: entryPointPath + ' esm', bundlePath: bundleObject.import, format: 'esm', }) } if (bundleObject.require) { entryPointConfigs.push({ entryPoint: entryPointPath + ' cjs', bundlePath: bundleObject.require, format: 'cjs', }) } return entryPointConfigs }) } /** * @param {EntryPointConfiguration} entryPointConfig * @param {string} entryPoint */ async function getBundle(entryPointConfig, entryPoint) { const rollupBuild = await rollup({ input: entryPoint }) let rollupOutput try { rollupOutput = await rollupBuild.generate({ format: entryPointConfig.format, }) } catch (error) { await rollupBuild.close() throw error } await rollupBuild.close() if (rollupOutput.output.length !== 1) { throw Error(`Expected a single output chunk for bundle ${entryPoint}`) } const outputChunk = rollupOutput.output[0] return outputChunk } /** * @param {EntryPointConfiguration} entryPointConfig * @param {number} entryPointIndex * @param {string} bundlePath * @param {import('rollup').OutputChunk} bundle */ async function getSingleExportBundleSizes(entryPointConfig, entryPointIndex, bundlePath, bundle) { if (entryPointConfig.format === 'esm' && bundle.exports.length !== 0) { const singleExportBundlesDirPath = path.resolve( actionRootPath, `temp/bundle-${entryPointIndex}`, ) await fs.mkdir(singleExportBundlesDirPath, { recursive: true }) return Promise.all( bundle.exports.map(async (exportName) => { const entryPoint = await createEntryPoint( singleExportBundlesDirPath, bundlePath, exportName, ) const singleExportBundle = await getBundle(entryPointConfig, entryPoint) return getBundleSize(exportName, singleExportBundle) }), ) } } /** * @param {string} singleExportBundlesDirPath * @param {string} bundlePath * @param {string} exportName */ async function createEntryPoint(singleExportBundlesDirPath, bundlePath, exportName) { const filePath = path.resolve(singleExportBundlesDirPath, `${exportName}.mjs`) const fileContent = `export { ${exportName} } from '${bundlePath}'` await fs.writeFile(filePath, fileContent) return filePath } /** * @typedef {object} BundleSize * @property {string} label * @property {number} size * @property {number} sizeMinified * @property {number} sizeBrotliCompressed */ /** * @param {string} label * @param {import('rollup').OutputChunk} bundle * @returns {Promise} */ async function getBundleSize(label, bundle) { const esBuildTransformResult = await transform(bundle.code, { minify: true }) const minifiedCode = esBuildTransformResult.code const brotliCompressedCode = (await brotliCompress(minifiedCode)).toString() return { label, size: bundle.code.length, sizeMinified: minifiedCode.length, sizeBrotliCompressed: brotliCompressedCode.length, } } const brotliCompress = promisify(zlib.brotliCompress) node-tailwind-merge-3.3.1/.github/actions/metrics-report/src/get-size-metrics-report-content.mjs000066400000000000000000000146021502210756000330070ustar00rootroot00000000000000// @ts-check import { getDetails, getTableHtml, nonBreaking } from './utils/html.mjs' /** * @param {import('./get-package-size.mjs').EntryPointSize[]} entryPointSizesHead * @param {import('./get-package-size.mjs').EntryPointSize[]} entryPointSizesBase */ export function getSizeMetricsReportContent(entryPointSizesHead, entryPointSizesBase) { const entryPointSizeMetrics = getEntryPointSizeMetrics(entryPointSizesHead, entryPointSizesBase) const entryPointSizeChanges = entryPointSizeMetrics .filter(({ bundleSize, singleExportSizes }) => { return hasBundleSizeChange(bundleSize) || singleExportSizes?.some(hasBundleSizeChange) }) .map((entryPointSizeMetrics) => { if (!entryPointSizeMetrics.singleExportSizes) { return entryPointSizeMetrics } return { ...entryPointSizeMetrics, singleExportSizes: entryPointSizeMetrics.singleExportSizes.filter(hasBundleSizeChange), } }) return [ '### Size', entryPointSizeChanges.length ? getTableHtmlForSizeMetrics(entryPointSizeChanges) : 'No changes', getDetails({ summary: 'All size metrics', content: getTableHtmlForSizeMetrics(entryPointSizeMetrics), }), ].join('\n\n') } /** * @param {import('./get-package-size.mjs').EntryPointSize[]} entryPointSizesHead * @param {import('./get-package-size.mjs').EntryPointSize[]} entryPointSizesBase */ function getEntryPointSizeMetrics(entryPointSizesHead, entryPointSizesBase) { const baseEntryPointSizesMap = new Map( entryPointSizesBase.map((entryPointSize) => [ entryPointSize.bundleSize.label, entryPointSize, ]), ) return entryPointSizesHead.map(({ bundleSize, singleExportSizes }) => { const baseEntryPointSize = baseEntryPointSizesMap.get(bundleSize.label) const bundleSizeMetrics = getBundleSizeMetrics(bundleSize, baseEntryPointSize?.bundleSize) if (singleExportSizes) { const baseBundleSizeMap = new Map( baseEntryPointSize?.singleExportSizes?.map((bundleSize) => [ bundleSize.label, bundleSize, ]), ) return { bundleSize: bundleSizeMetrics, singleExportSizes: singleExportSizes.map((singleExportSize) => { const baseBundleSize = baseBundleSizeMap.get(singleExportSize.label) return getBundleSizeMetrics(singleExportSize, baseBundleSize) }), } } return { bundleSize: bundleSizeMetrics, } }) } /** * @param {import('./get-package-size.mjs').BundleSize} bundleSizeHead * @param {import('./get-package-size.mjs').BundleSize=} bundleSizeBase */ function getBundleSizeMetrics(bundleSizeHead, bundleSizeBase) { return { label: bundleSizeHead.label, size: getSizeMetrics(bundleSizeHead.size, bundleSizeBase?.size), sizeMinified: getSizeMetrics(bundleSizeHead.sizeMinified, bundleSizeBase?.sizeMinified), sizeBrotliCompressed: getSizeMetrics( bundleSizeHead.sizeBrotliCompressed, bundleSizeBase?.sizeBrotliCompressed, ), } } /** * @param {number} sizeHead * @param {number=} sizeBase */ function getSizeMetrics(sizeHead, sizeBase) { return { value: sizeHead, changePercent: sizeBase ? (sizeHead - sizeBase) / sizeBase : undefined, } } /** * * @param {ReturnType} entryPointSizeMetrics */ function getTableHtmlForSizeMetrics(entryPointSizeMetrics) { return getTableHtml({ headers: [ 'Export', 'Size original', 'Size minified', 'Size minified and Brotli compressed', ], columnAlignments: ['left', 'center', 'center', 'center'], columnWidths: ['225px', '200px', '200px', '200px'], rows: entryPointSizeMetrics.flatMap(({ bundleSize, singleExportSizes }) => { const mainBundleRow = getBundleSizeTableRow(bundleSize) if (singleExportSizes) { return [ mainBundleRow, ...singleExportSizes.map((singleExportSize) => { return getBundleSizeTableRow(singleExportSize, true) }), ] } return [mainBundleRow] }), }) } /** * @param {ReturnType} bundleSizeMetrics * @param {boolean=} isIndented */ function getBundleSizeTableRow(bundleSizeMetrics, isIndented) { return [ nonBreaking( [isIndented ? ' › ' : '', '', bundleSizeMetrics.label, ''].join(''), ), getSizeMetricsTableContent(bundleSizeMetrics.size), getSizeMetricsTableContent(bundleSizeMetrics.sizeMinified), getSizeMetricsTableContent(bundleSizeMetrics.sizeBrotliCompressed), ] } /** * @param {ReturnType} size */ function getSizeMetricsTableContent(size) { const sizeString = nonBreaking(getSizeInKb(size.value)) if (size.changePercent === undefined) { return sizeString } return sizeString + ' ' + nonBreaking(getChangePercentString(size.changePercent)) } /** * @param {number} size */ export function getSizeInKb(size) { return (size / 1024).toLocaleString('en-GB', { style: 'unit', unit: 'kilobyte', unitDisplay: 'short', minimumFractionDigits: 2, maximumFractionDigits: 2, }) } /** * @param {number} changePercent */ function getChangePercentString(changePercent) { const isZero = changePercent === 0 const isPositive = changePercent > 0 const percentageString = changePercent.toLocaleString('en-GB', { style: 'percent', minimumFractionDigits: isZero ? 0 : 1, maximumFractionDigits: 1, signDisplay: 'exceptZero', }) return percentageString + (isZero ? '' : isPositive ? ' 🔴' : ' 🟢') } /** * @param {ReturnType} bundleSizeMetrics */ function hasBundleSizeChange(bundleSizeMetrics) { return ( bundleSizeMetrics.size.changePercent !== 0 || bundleSizeMetrics.sizeMinified.changePercent !== 0 || bundleSizeMetrics.sizeBrotliCompressed.changePercent !== 0 ) } node-tailwind-merge-3.3.1/.github/actions/metrics-report/src/main.mjs000066400000000000000000000053121502210756000255550ustar00rootroot00000000000000// @ts-check import core from '@actions/core' import { context } from '@actions/github' import { getPackageSize } from './get-package-size.mjs' import { getSizeInKb, getSizeMetricsReportContent } from './get-size-metrics-report-content.mjs' import { setComment } from './set-comment.mjs' import { checkoutBranch } from './utils/git.mjs' run() async function run() { const pullRequest = /** @type {import('@octokit/webhooks-definitions/schema').PullRequestEvent} */ ( context.payload ).pull_request if (!pullRequest) { throw Error('This action can only be run in a pull request') } core.info('Getting local package sizes') const entryPointSizesHead = await getPackageSize() logEntryPointSizes(entryPointSizesHead) await checkoutBranch(pullRequest.base.ref) core.info('Getting PR base package sizes') const entryPointSizesBase = await getPackageSize({ shouldOmitFailures: true }) logEntryPointSizes(entryPointSizesBase) const commentBody = getBodyText([ ['### Metrics report'], [ `At head commit ${pullRequest.head?.sha} and base commit ${pullRequest.base?.sha} at \`${new Date().toISOString()}\``, ], [getSizeMetricsReportContent(entryPointSizesHead, entryPointSizesBase)], ]) const isPullRequestFromFork = pullRequest.head.repo.full_name !== `${context.repo.owner}/${context.repo.repo}` if (isPullRequestFromFork) { core.info('Pull request is from a fork, printing comment instead of posting it') core.info(commentBody) } else { await setComment(commentBody) } } /** * @param {import('./get-package-size.mjs').EntryPointSize[]} entryPointSizes */ function logEntryPointSizes(entryPointSizes) { core.info('Package sizes') entryPointSizes.forEach(({ bundleSize, singleExportSizes }) => { logBundleSize(bundleSize) singleExportSizes?.forEach((singleExportSize) => { logBundleSize(singleExportSize, true) }) }) } /** * @param {import('./get-package-size.mjs').BundleSize} bundleSize * @param {boolean=} isIndented */ function logBundleSize(bundleSize, isIndented) { core.info( [ [isIndented ? ' ' : '', bundleSize.label].join('').padEnd(30), [ getSizeInKb(bundleSize.size).padStart(14), `${getSizeInKb(bundleSize.sizeMinified).padStart(14)} minified`, `${getSizeInKb(bundleSize.sizeBrotliCompressed).padStart(14)} brotli compressed`, ].join(' '), ].join(''), ) } /** * @param {string[][]} paragraphs */ function getBodyText(paragraphs) { return paragraphs.map((lines) => lines.join('\n')).join('\n\n') } node-tailwind-merge-3.3.1/.github/actions/metrics-report/src/set-comment.mjs000066400000000000000000000050721502210756000270670ustar00rootroot00000000000000// @ts-check import core from '@actions/core' import { context } from '@actions/github' import { octokit } from './utils/github.mjs' const commentIdComment = '' const commentAdditionComment = "\n\n\n" /** * @param {string} body */ export async function setComment(body) { const commentToUpdate = await findCommentToUpdate() if (commentToUpdate) { await updateComment(body, commentToUpdate.id) } else { await createComment(body) } } async function findCommentToUpdate() { if (!context.payload.pull_request) { throw new Error('Can only list comments in a pull request') } core.info('Searching comment to update') const iterator = octokit.paginate.iterator(octokit.rest.issues.listComments, { owner: context.repo.owner, repo: context.repo.repo, issue_number: context.payload.pull_request.number, }) /** @type {import('@octokit/types').GetResponseDataTypeFromEndpointMethod[number]=} */ let commentToUpdate iteratorLoop: for await (const response of iterator) { for (const comment of response.data) { if (comment.body?.startsWith(commentIdComment)) { commentToUpdate = comment break iteratorLoop } } } if (commentToUpdate) { core.info(`Found comment to update with URL ${commentToUpdate.url}`) } else { core.info('No comment to update found') } return commentToUpdate } /** * @param {string} body */ async function createComment(body) { if (!context.payload.pull_request) { throw new Error('Can only create a comment in a pull request') } const response = await octokit.rest.issues.createComment({ owner: context.repo.owner, repo: context.repo.repo, issue_number: context.payload.pull_request.number, body: commentIdComment + commentAdditionComment + body, }) core.info(`Created comment with URL ${response.data.url}`) } /** * @param {string} body * @param {number} commentId */ async function updateComment(body, commentId) { const response = await octokit.rest.issues.updateComment({ owner: context.repo.owner, repo: context.repo.repo, comment_id: commentId, body: commentIdComment + commentAdditionComment + body, }) core.info(`Updated comment with URL ${response.data.url}`) } node-tailwind-merge-3.3.1/.github/actions/metrics-report/src/utils/000077500000000000000000000000001502210756000252555ustar00rootroot00000000000000node-tailwind-merge-3.3.1/.github/actions/metrics-report/src/utils/git.mjs000066400000000000000000000007441502210756000265600ustar00rootroot00000000000000// @ts-check import core from '@actions/core' import { exec } from '@actions/exec' /** * @param {string} branch */ export async function checkoutBranch(branch) { try { core.info(`Fetching branch ${branch}`) await exec(`git fetch origin ${branch} --depth=1`) } catch (error) { core.error('git fetch failed', error.message) throw error } core.info(`Checking out branch ${branch}`) await exec(`git checkout --force ${branch}`) } node-tailwind-merge-3.3.1/.github/actions/metrics-report/src/utils/github.mjs000066400000000000000000000002761502210756000272570ustar00rootroot00000000000000// @ts-check import core from '@actions/core' import { getOctokit } from '@actions/github' const githubToken = core.getInput('github_token') export const octokit = getOctokit(githubToken) node-tailwind-merge-3.3.1/.github/actions/metrics-report/src/utils/html.mjs000066400000000000000000000071261502210756000267420ustar00rootroot00000000000000// @ts-check /** * @typedef {object} DetailsData * @property {string} summary * @property {string} content */ /** * @param {DetailsData} param0 */ export function getDetails({ summary, content }) { return [`
`, `${summary}`, '', content, '', `
`].join('\n') } /** * @typedef {object} TableData * @property {('left' | 'center' | 'right' | undefined)[]=} columnAlignments * @property {(string | undefined)[]=} columnWidths * @property {string[]} headers * @property {string[][]} rows */ /** * @param {TableData} param0 */ export function getTableHtml({ columnAlignments = [], columnWidths = [], headers, rows }) { return getHtml([ { tag: 'table', children: [ { tag: 'thead', children: [ { tag: 'tr', children: headers.map((header, headerIndex) => ({ tag: 'th', attributes: { width: columnWidths[headerIndex], align: columnAlignments[headerIndex], }, children: [header], })), }, ], }, { tag: 'tbody', children: rows.map((row) => ({ tag: 'tr', children: row.map((cell, cellIndex) => ({ tag: 'td', attributes: { align: columnAlignments[cellIndex], }, children: [cell], })), })), }, ], }, ]) } /** * @typedef {object} HtmlElement * @property {string} tag * @property {Record=} attributes * @property {(HtmlElement | string)[]=} children */ /** * @param {(HtmlElement | string)[]} elements */ function getHtml(elements) { return indent(getHtmlLinesToIndent(elements)) } /** * @typedef {(string | LinesToIndent)[]} LinesToIndent */ /** * @param {LinesToIndent} lines * @param {number=} level * @returns {string} */ function indent(lines, level = 0) { const indentation = ' '.repeat(level * 4) return lines .map((element) => { if (typeof element === 'string') { return indentation + element } return indent(element, level + 1) }) .join('\n') } /** * @param {(HtmlElement | string)[]} elements * @returns {LinesToIndent} */ function getHtmlLinesToIndent(elements) { return elements.flatMap((element) => { if (typeof element === 'string') { return element } const attributes = Object.entries(element.attributes ?? {}) .filter(([, value]) => value !== undefined) .map(([key, value]) => `${key}="${value}"`) .join(' ') const openingTag = `<${element.tag}${attributes ? ' ' + attributes : ''}>` const closingTag = `` const innerHtmlLines = element.children ? getHtmlLinesToIndent(element.children) : [] if (innerHtmlLines.length === 0) { return [openingTag, closingTag] } return [openingTag, innerHtmlLines, closingTag] }) } /** * @param {string} text */ export function nonBreaking(text) { return text.replace(/ /g, ' ') } node-tailwind-merge-3.3.1/.github/actions/metrics-report/src/utils/path.mjs000066400000000000000000000004311502210756000267220ustar00rootroot00000000000000// @ts-check import path from 'path' import { fileURLToPath } from 'url' const currentDirPath = path.dirname(fileURLToPath(import.meta.url)) export const actionRootPath = path.resolve(currentDirPath, '../..') export const repoRootPath = path.resolve(actionRootPath, '../../..') node-tailwind-merge-3.3.1/.github/actions/metrics-report/yarn.lock000066400000000000000000000627621502210756000251660ustar00rootroot00000000000000# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. # yarn lockfile v1 "@actions/core@^1.11.1": version "1.11.1" resolved "https://registry.yarnpkg.com/@actions/core/-/core-1.11.1.tgz#ae683aac5112438021588030efb53b1adb86f172" integrity sha512-hXJCSrkwfA46Vd9Z3q4cpEpHB1rL5NG04+/rbqW9d3+CSvtB1tYe8UTpAlixa1vj0m/ULglfEK2UKxMGxCxv5A== dependencies: "@actions/exec" "^1.1.1" "@actions/http-client" "^2.0.1" "@actions/exec@^1.1.1": version "1.1.1" resolved "https://registry.yarnpkg.com/@actions/exec/-/exec-1.1.1.tgz#2e43f28c54022537172819a7cf886c844221a611" integrity sha512-+sCcHHbVdk93a0XT19ECtO/gIXoxvdsgQLzb2fE2/5sIZmWQuluYyjPQtrtTHdU1YzTZ7bAPN4sITq2xi1679w== dependencies: "@actions/io" "^1.0.1" "@actions/github@^6.0.1": version "6.0.1" resolved "https://registry.yarnpkg.com/@actions/github/-/github-6.0.1.tgz#76e5f96df062c90635a7181ef45ff1c4ac21306e" integrity sha512-xbZVcaqD4XnQAe35qSQqskb3SqIAfRyLBrHMd/8TuL7hJSz2QtbDwnNM8zWx4zO5l2fnGtseNE3MbEvD7BxVMw== dependencies: "@actions/http-client" "^2.2.0" "@octokit/core" "^5.0.1" "@octokit/plugin-paginate-rest" "^9.2.2" "@octokit/plugin-rest-endpoint-methods" "^10.4.0" "@octokit/request" "^8.4.1" "@octokit/request-error" "^5.1.1" undici "^5.28.5" "@actions/http-client@^2.0.1", "@actions/http-client@^2.2.0": version "2.2.1" resolved "https://registry.yarnpkg.com/@actions/http-client/-/http-client-2.2.1.tgz#ed3fe7a5a6d317ac1d39886b0bb999ded229bb38" integrity sha512-KhC/cZsq7f8I4LfZSJKgCvEwfkE8o1538VoBeoGzokVLLnbFDEAdFD3UhoMklxo2un9NJVBdANOresx7vTHlHw== dependencies: tunnel "^0.0.6" undici "^5.25.4" "@actions/io@^1.0.1": version "1.1.3" resolved "https://registry.yarnpkg.com/@actions/io/-/io-1.1.3.tgz#4cdb6254da7962b07473ff5c335f3da485d94d71" integrity sha512-wi9JjgKLYS7U/z8PPbco+PvTb/nRWjeoFlJ1Qer83k/3C5PHQi28hiVdeE2kHXmIL99mQFawx8qt/JPjZilJ8Q== "@esbuild/aix-ppc64@0.25.5": version "0.25.5" resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.25.5.tgz#4e0f91776c2b340e75558f60552195f6fad09f18" integrity sha512-9o3TMmpmftaCMepOdA5k/yDw8SfInyzWWTjYTFCX3kPSDJMROQTb8jg+h9Cnwnmm1vOzvxN7gIfB5V2ewpjtGA== "@esbuild/android-arm64@0.25.5": version "0.25.5" resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.25.5.tgz#bc766407f1718923f6b8079c8c61bf86ac3a6a4f" integrity sha512-VGzGhj4lJO+TVGV1v8ntCZWJktV7SGCs3Pn1GRWI1SBFtRALoomm8k5E9Pmwg3HOAal2VDc2F9+PM/rEY6oIDg== "@esbuild/android-arm@0.25.5": version "0.25.5" resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.25.5.tgz#4290d6d3407bae3883ad2cded1081a234473ce26" integrity sha512-AdJKSPeEHgi7/ZhuIPtcQKr5RQdo6OO2IL87JkianiMYMPbCtot9fxPbrMiBADOWWm3T2si9stAiVsGbTQFkbA== "@esbuild/android-x64@0.25.5": version "0.25.5" resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.25.5.tgz#40c11d9cbca4f2406548c8a9895d321bc3b35eff" integrity sha512-D2GyJT1kjvO//drbRT3Hib9XPwQeWd9vZoBJn+bu/lVsOZ13cqNdDeqIF/xQ5/VmWvMduP6AmXvylO/PIc2isw== "@esbuild/darwin-arm64@0.25.5": version "0.25.5" resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.25.5.tgz#49d8bf8b1df95f759ac81eb1d0736018006d7e34" integrity sha512-GtaBgammVvdF7aPIgH2jxMDdivezgFu6iKpmT+48+F8Hhg5J/sfnDieg0aeG/jfSvkYQU2/pceFPDKlqZzwnfQ== "@esbuild/darwin-x64@0.25.5": version "0.25.5" resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.25.5.tgz#e27a5d92a14886ef1d492fd50fc61a2d4d87e418" integrity sha512-1iT4FVL0dJ76/q1wd7XDsXrSW+oLoquptvh4CLR4kITDtqi2e/xwXwdCVH8hVHU43wgJdsq7Gxuzcs6Iq/7bxQ== "@esbuild/freebsd-arm64@0.25.5": version "0.25.5" resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.5.tgz#97cede59d638840ca104e605cdb9f1b118ba0b1c" integrity sha512-nk4tGP3JThz4La38Uy/gzyXtpkPW8zSAmoUhK9xKKXdBCzKODMc2adkB2+8om9BDYugz+uGV7sLmpTYzvmz6Sw== "@esbuild/freebsd-x64@0.25.5": version "0.25.5" resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.25.5.tgz#71c77812042a1a8190c3d581e140d15b876b9c6f" integrity sha512-PrikaNjiXdR2laW6OIjlbeuCPrPaAl0IwPIaRv+SMV8CiM8i2LqVUHFC1+8eORgWyY7yhQY+2U2fA55mBzReaw== "@esbuild/linux-arm64@0.25.5": version "0.25.5" resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.25.5.tgz#f7b7c8f97eff8ffd2e47f6c67eb5c9765f2181b8" integrity sha512-Z9kfb1v6ZlGbWj8EJk9T6czVEjjq2ntSYLY2cw6pAZl4oKtfgQuS4HOq41M/BcoLPzrUbNd+R4BXFyH//nHxVg== "@esbuild/linux-arm@0.25.5": version "0.25.5" resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.25.5.tgz#2a0be71b6cd8201fa559aea45598dffabc05d911" integrity sha512-cPzojwW2okgh7ZlRpcBEtsX7WBuqbLrNXqLU89GxWbNt6uIg78ET82qifUy3W6OVww6ZWobWub5oqZOVtwolfw== "@esbuild/linux-ia32@0.25.5": version "0.25.5" resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.25.5.tgz#763414463cd9ea6fa1f96555d2762f9f84c61783" integrity sha512-sQ7l00M8bSv36GLV95BVAdhJ2QsIbCuCjh/uYrWiMQSUuV+LpXwIqhgJDcvMTj+VsQmqAHL2yYaasENvJ7CDKA== "@esbuild/linux-loong64@0.25.5": version "0.25.5" resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.25.5.tgz#428cf2213ff786a502a52c96cf29d1fcf1eb8506" integrity sha512-0ur7ae16hDUC4OL5iEnDb0tZHDxYmuQyhKhsPBV8f99f6Z9KQM02g33f93rNH5A30agMS46u2HP6qTdEt6Q1kg== "@esbuild/linux-mips64el@0.25.5": version "0.25.5" resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.25.5.tgz#5cbcc7fd841b4cd53358afd33527cd394e325d96" integrity sha512-kB/66P1OsHO5zLz0i6X0RxlQ+3cu0mkxS3TKFvkb5lin6uwZ/ttOkP3Z8lfR9mJOBk14ZwZ9182SIIWFGNmqmg== "@esbuild/linux-ppc64@0.25.5": version "0.25.5" resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.25.5.tgz#0d954ab39ce4f5e50f00c4f8c4fd38f976c13ad9" integrity sha512-UZCmJ7r9X2fe2D6jBmkLBMQetXPXIsZjQJCjgwpVDz+YMcS6oFR27alkgGv3Oqkv07bxdvw7fyB71/olceJhkQ== "@esbuild/linux-riscv64@0.25.5": version "0.25.5" resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.25.5.tgz#0e7dd30730505abd8088321e8497e94b547bfb1e" integrity sha512-kTxwu4mLyeOlsVIFPfQo+fQJAV9mh24xL+y+Bm6ej067sYANjyEw1dNHmvoqxJUCMnkBdKpvOn0Ahql6+4VyeA== "@esbuild/linux-s390x@0.25.5": version "0.25.5" resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.25.5.tgz#5669af81327a398a336d7e40e320b5bbd6e6e72d" integrity sha512-K2dSKTKfmdh78uJ3NcWFiqyRrimfdinS5ErLSn3vluHNeHVnBAFWC8a4X5N+7FgVE1EjXS1QDZbpqZBjfrqMTQ== "@esbuild/linux-x64@0.25.5": version "0.25.5" resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.25.5.tgz#b2357dd153aa49038967ddc1ffd90c68a9d2a0d4" integrity sha512-uhj8N2obKTE6pSZ+aMUbqq+1nXxNjZIIjCjGLfsWvVpy7gKCOL6rsY1MhRh9zLtUtAI7vpgLMK6DxjO8Qm9lJw== "@esbuild/netbsd-arm64@0.25.5": version "0.25.5" resolved "https://registry.yarnpkg.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.5.tgz#53b4dfb8fe1cee93777c9e366893bd3daa6ba63d" integrity sha512-pwHtMP9viAy1oHPvgxtOv+OkduK5ugofNTVDilIzBLpoWAM16r7b/mxBvfpuQDpRQFMfuVr5aLcn4yveGvBZvw== "@esbuild/netbsd-x64@0.25.5": version "0.25.5" resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.25.5.tgz#a0206f6314ce7dc8713b7732703d0f58de1d1e79" integrity sha512-WOb5fKrvVTRMfWFNCroYWWklbnXH0Q5rZppjq0vQIdlsQKuw6mdSihwSo4RV/YdQ5UCKKvBy7/0ZZYLBZKIbwQ== "@esbuild/openbsd-arm64@0.25.5": version "0.25.5" resolved "https://registry.yarnpkg.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.5.tgz#2a796c87c44e8de78001d808c77d948a21ec22fd" integrity sha512-7A208+uQKgTxHd0G0uqZO8UjK2R0DDb4fDmERtARjSHWxqMTye4Erz4zZafx7Di9Cv+lNHYuncAkiGFySoD+Mw== "@esbuild/openbsd-x64@0.25.5": version "0.25.5" resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.25.5.tgz#28d0cd8909b7fa3953af998f2b2ed34f576728f0" integrity sha512-G4hE405ErTWraiZ8UiSoesH8DaCsMm0Cay4fsFWOOUcz8b8rC6uCvnagr+gnioEjWn0wC+o1/TAHt+It+MpIMg== "@esbuild/sunos-x64@0.25.5": version "0.25.5" resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.25.5.tgz#a28164f5b997e8247d407e36c90d3fd5ddbe0dc5" integrity sha512-l+azKShMy7FxzY0Rj4RCt5VD/q8mG/e+mDivgspo+yL8zW7qEwctQ6YqKX34DTEleFAvCIUviCFX1SDZRSyMQA== "@esbuild/win32-arm64@0.25.5": version "0.25.5" resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.25.5.tgz#6eadbead38e8bd12f633a5190e45eff80e24007e" integrity sha512-O2S7SNZzdcFG7eFKgvwUEZ2VG9D/sn/eIiz8XRZ1Q/DO5a3s76Xv0mdBzVM5j5R639lXQmPmSo0iRpHqUUrsxw== "@esbuild/win32-ia32@0.25.5": version "0.25.5" resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.25.5.tgz#bab6288005482f9ed2adb9ded7e88eba9a62cc0d" integrity sha512-onOJ02pqs9h1iMJ1PQphR+VZv8qBMQ77Klcsqv9CNW2w6yLqoURLcgERAIurY6QE63bbLuqgP9ATqajFLK5AMQ== "@esbuild/win32-x64@0.25.5": version "0.25.5" resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.25.5.tgz#7fc114af5f6563f19f73324b5d5ff36ece0803d1" integrity sha512-TXv6YnJ8ZMVdX+SXWVBo/0p8LTcrUYngpWjvm91TMjjBQii7Oz11Lw5lbDV5Y0TzuhSJHwiH4hEtC1I42mMS0g== "@fastify/busboy@^2.0.0": version "2.1.1" resolved "https://registry.yarnpkg.com/@fastify/busboy/-/busboy-2.1.1.tgz#b9da6a878a371829a0502c9b6c1c143ef6663f4d" integrity sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA== "@octokit/auth-token@^4.0.0": version "4.0.0" resolved "https://registry.yarnpkg.com/@octokit/auth-token/-/auth-token-4.0.0.tgz#40d203ea827b9f17f42a29c6afb93b7745ef80c7" integrity sha512-tY/msAuJo6ARbK6SPIxZrPBms3xPbfwBrulZe0Wtr/DIY9lje2HeV1uoebShn6mx7SjCHif6EjMvoREj+gZ+SA== "@octokit/core@^5.0.1": version "5.2.0" resolved "https://registry.yarnpkg.com/@octokit/core/-/core-5.2.0.tgz#ddbeaefc6b44a39834e1bb2e58a49a117672a7ea" integrity sha512-1LFfa/qnMQvEOAdzlQymH0ulepxbxnCYAKJZfMci/5XJyIHWgEYnDmgnKakbTh7CH2tFQ5O60oYDvns4i9RAIg== dependencies: "@octokit/auth-token" "^4.0.0" "@octokit/graphql" "^7.1.0" "@octokit/request" "^8.3.1" "@octokit/request-error" "^5.1.0" "@octokit/types" "^13.0.0" before-after-hook "^2.2.0" universal-user-agent "^6.0.0" "@octokit/endpoint@^9.0.6": version "9.0.6" resolved "https://registry.yarnpkg.com/@octokit/endpoint/-/endpoint-9.0.6.tgz#114d912108fe692d8b139cfe7fc0846dfd11b6c0" integrity sha512-H1fNTMA57HbkFESSt3Y9+FBICv+0jFceJFPWDePYlR/iMGrwM5ph+Dd4XRQs+8X+PUFURLQgX9ChPfhJ/1uNQw== dependencies: "@octokit/types" "^13.1.0" universal-user-agent "^6.0.0" "@octokit/graphql@^7.1.0": version "7.1.0" resolved "https://registry.yarnpkg.com/@octokit/graphql/-/graphql-7.1.0.tgz#9bc1c5de92f026648131f04101cab949eeffe4e0" integrity sha512-r+oZUH7aMFui1ypZnAvZmn0KSqAUgE1/tUXIWaqUCa1758ts/Jio84GZuzsvUkme98kv0WFY8//n0J1Z+vsIsQ== dependencies: "@octokit/request" "^8.3.0" "@octokit/types" "^13.0.0" universal-user-agent "^6.0.0" "@octokit/openapi-types@^20.0.0": version "20.0.0" resolved "https://registry.yarnpkg.com/@octokit/openapi-types/-/openapi-types-20.0.0.tgz#9ec2daa0090eeb865ee147636e0c00f73790c6e5" integrity sha512-EtqRBEjp1dL/15V7WiX5LJMIxxkdiGJnabzYx5Apx4FkQIFgAfKumXeYAqqJCj1s+BMX4cPFIFC4OLCR6stlnA== "@octokit/openapi-types@^22.2.0": version "22.2.0" resolved "https://registry.yarnpkg.com/@octokit/openapi-types/-/openapi-types-22.2.0.tgz#75aa7dcd440821d99def6a60b5f014207ae4968e" integrity sha512-QBhVjcUa9W7Wwhm6DBFu6ZZ+1/t/oYxqc2tp81Pi41YNuJinbFRx8B133qVOrAaBbF7D/m0Et6f9/pZt9Rc+tg== "@octokit/openapi-types@^25.1.0": version "25.1.0" resolved "https://registry.yarnpkg.com/@octokit/openapi-types/-/openapi-types-25.1.0.tgz#5a72a9dfaaba72b5b7db375fd05e90ca90dc9682" integrity sha512-idsIggNXUKkk0+BExUn1dQ92sfysJrje03Q0bv0e+KPLrvyqZF8MnBpFz8UNfYDwB3Ie7Z0TByjWfzxt7vseaA== "@octokit/plugin-paginate-rest@^9.2.2": version "9.2.2" resolved "https://registry.yarnpkg.com/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-9.2.2.tgz#c516bc498736bcdaa9095b9a1d10d9d0501ae831" integrity sha512-u3KYkGF7GcZnSD/3UP0S7K5XUFT2FkOQdcfXZGZQPGv3lm4F2Xbf71lvjldr8c1H3nNbF+33cLEkWYbokGWqiQ== dependencies: "@octokit/types" "^12.6.0" "@octokit/plugin-rest-endpoint-methods@^10.4.0": version "10.4.1" resolved "https://registry.yarnpkg.com/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-10.4.1.tgz#41ba478a558b9f554793075b2e20cd2ef973be17" integrity sha512-xV1b+ceKV9KytQe3zCVqjg+8GTGfDYwaT1ATU5isiUyVtlVAO3HNdzpS4sr4GBx4hxQ46s7ITtZrAsxG22+rVg== dependencies: "@octokit/types" "^12.6.0" "@octokit/request-error@^5.1.0", "@octokit/request-error@^5.1.1": version "5.1.1" resolved "https://registry.yarnpkg.com/@octokit/request-error/-/request-error-5.1.1.tgz#b9218f9c1166e68bb4d0c89b638edc62c9334805" integrity sha512-v9iyEQJH6ZntoENr9/yXxjuezh4My67CBSu9r6Ve/05Iu5gNgnisNWOsoJHTP6k0Rr0+HQIpnH+kyammu90q/g== dependencies: "@octokit/types" "^13.1.0" deprecation "^2.0.0" once "^1.4.0" "@octokit/request@^8.3.0", "@octokit/request@^8.3.1", "@octokit/request@^8.4.1": version "8.4.1" resolved "https://registry.yarnpkg.com/@octokit/request/-/request-8.4.1.tgz#715a015ccf993087977ea4365c44791fc4572486" integrity sha512-qnB2+SY3hkCmBxZsR/MPCybNmbJe4KAlfWErXq+rBKkQJlbjdJeS85VI9r8UqeLYLvnAenU8Q1okM/0MBsAGXw== dependencies: "@octokit/endpoint" "^9.0.6" "@octokit/request-error" "^5.1.1" "@octokit/types" "^13.1.0" universal-user-agent "^6.0.0" "@octokit/types@^12.6.0": version "12.6.0" resolved "https://registry.yarnpkg.com/@octokit/types/-/types-12.6.0.tgz#8100fb9eeedfe083aae66473bd97b15b62aedcb2" integrity sha512-1rhSOfRa6H9w4YwK0yrf5faDaDTb+yLyBUKOCV4xtCDB5VmIPqd/v9yr9o6SAzOAlRxMiRiCic6JVM1/kunVkw== dependencies: "@octokit/openapi-types" "^20.0.0" "@octokit/types@^13.0.0", "@octokit/types@^13.1.0": version "13.5.0" resolved "https://registry.yarnpkg.com/@octokit/types/-/types-13.5.0.tgz#4796e56b7b267ebc7c921dcec262b3d5bfb18883" integrity sha512-HdqWTf5Z3qwDVlzCrP8UJquMwunpDiMPt5er+QjGzL4hqr/vBVY/MauQgS1xWxCDT1oMx1EULyqxncdCY/NVSQ== dependencies: "@octokit/openapi-types" "^22.2.0" "@octokit/types@^14.1.0": version "14.1.0" resolved "https://registry.yarnpkg.com/@octokit/types/-/types-14.1.0.tgz#3bf9b3a3e3b5270964a57cc9d98592ed44f840f2" integrity sha512-1y6DgTy8Jomcpu33N+p5w58l6xyt55Ar2I91RPiIA0xCJBXyUAhXCcmZaDWSANiha7R9a6qJJ2CRomGPZ6f46g== dependencies: "@octokit/openapi-types" "^25.1.0" "@octokit/webhooks-definitions@^3.67.3": version "3.67.3" resolved "https://registry.yarnpkg.com/@octokit/webhooks-definitions/-/webhooks-definitions-3.67.3.tgz#d2a905a90b04af8111982d0c13658a49fc4eecb9" integrity sha512-do4Z1r2OVhuI0ihJhQ8Hg+yPWnBYEBNuFNCrvtPKoYT1w81jD7pBXgGe86lYuuNirkDHb0Nxt+zt4O5GiFJfgA== "@rollup/rollup-android-arm-eabi@4.41.1": version "4.41.1" resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.41.1.tgz#f39f09f60d4a562de727c960d7b202a2cf797424" integrity sha512-NELNvyEWZ6R9QMkiytB4/L4zSEaBC03KIXEghptLGLZWJ6VPrL63ooZQCOnlx36aQPGhzuOMwDerC1Eb2VmrLw== "@rollup/rollup-android-arm64@4.41.1": version "4.41.1" resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.41.1.tgz#d19af7e23760717f1d879d4ca3d2cd247742dff2" integrity sha512-DXdQe1BJ6TK47ukAoZLehRHhfKnKg9BjnQYUu9gzhI8Mwa1d2fzxA1aw2JixHVl403bwp1+/o/NhhHtxWJBgEA== "@rollup/rollup-darwin-arm64@4.41.1": version "4.41.1" resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.41.1.tgz#1c3a2fbf205d80641728e05f4a56c909e95218b7" integrity sha512-5afxvwszzdulsU2w8JKWwY8/sJOLPzf0e1bFuvcW5h9zsEg+RQAojdW0ux2zyYAz7R8HvvzKCjLNJhVq965U7w== "@rollup/rollup-darwin-x64@4.41.1": version "4.41.1" resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.41.1.tgz#aa66d2ba1a25e609500e13bef06dc0e71cc0c0d4" integrity sha512-egpJACny8QOdHNNMZKf8xY0Is6gIMz+tuqXlusxquWu3F833DcMwmGM7WlvCO9sB3OsPjdC4U0wHw5FabzCGZg== "@rollup/rollup-freebsd-arm64@4.41.1": version "4.41.1" resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.41.1.tgz#df10a7b6316a0ef1028c6ca71a081124c537e30d" integrity sha512-DBVMZH5vbjgRk3r0OzgjS38z+atlupJ7xfKIDJdZZL6sM6wjfDNo64aowcLPKIx7LMQi8vybB56uh1Ftck/Atg== "@rollup/rollup-freebsd-x64@4.41.1": version "4.41.1" resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.41.1.tgz#a3fdce8a05e95b068cbcb46e4df5185e407d0c35" integrity sha512-3FkydeohozEskBxNWEIbPfOE0aqQgB6ttTkJ159uWOFn42VLyfAiyD9UK5mhu+ItWzft60DycIN1Xdgiy8o/SA== "@rollup/rollup-linux-arm-gnueabihf@4.41.1": version "4.41.1" resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.41.1.tgz#49f766c55383bd0498014a9d76924348c2f3890c" integrity sha512-wC53ZNDgt0pqx5xCAgNunkTzFE8GTgdZ9EwYGVcg+jEjJdZGtq9xPjDnFgfFozQI/Xm1mh+D9YlYtl+ueswNEg== "@rollup/rollup-linux-arm-musleabihf@4.41.1": version "4.41.1" resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.41.1.tgz#1d4d7d32fc557e17d52e1857817381ea365e2959" integrity sha512-jwKCca1gbZkZLhLRtsrka5N8sFAaxrGz/7wRJ8Wwvq3jug7toO21vWlViihG85ei7uJTpzbXZRcORotE+xyrLA== "@rollup/rollup-linux-arm64-gnu@4.41.1": version "4.41.1" resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.41.1.tgz#f4fc317268441e9589edad3be8f62b6c03009bc1" integrity sha512-g0UBcNknsmmNQ8V2d/zD2P7WWfJKU0F1nu0k5pW4rvdb+BIqMm8ToluW/eeRmxCared5dD76lS04uL4UaNgpNA== "@rollup/rollup-linux-arm64-musl@4.41.1": version "4.41.1" resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.41.1.tgz#63a1f1b0671cb17822dabae827fef0e443aebeb7" integrity sha512-XZpeGB5TKEZWzIrj7sXr+BEaSgo/ma/kCgrZgL0oo5qdB1JlTzIYQKel/RmhT6vMAvOdM2teYlAaOGJpJ9lahg== "@rollup/rollup-linux-loongarch64-gnu@4.41.1": version "4.41.1" resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.41.1.tgz#c659b01cc6c0730b547571fc3973e1e955369f98" integrity sha512-bkCfDJ4qzWfFRCNt5RVV4DOw6KEgFTUZi2r2RuYhGWC8WhCA8lCAJhDeAmrM/fdiAH54m0mA0Vk2FGRPyzI+tw== "@rollup/rollup-linux-powerpc64le-gnu@4.41.1": version "4.41.1" resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.41.1.tgz#612e746f9ad7e58480f964d65e0d6c3f4aae69a8" integrity sha512-3mr3Xm+gvMX+/8EKogIZSIEF0WUu0HL9di+YWlJpO8CQBnoLAEL/roTCxuLncEdgcfJcvA4UMOf+2dnjl4Ut1A== "@rollup/rollup-linux-riscv64-gnu@4.41.1": version "4.41.1" resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.41.1.tgz#4610dbd1dcfbbae32fbc10c20ae7387acb31110c" integrity sha512-3rwCIh6MQ1LGrvKJitQjZFuQnT2wxfU+ivhNBzmxXTXPllewOF7JR1s2vMX/tWtUYFgphygxjqMl76q4aMotGw== "@rollup/rollup-linux-riscv64-musl@4.41.1": version "4.41.1" resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.41.1.tgz#054911fab40dc83fafc21e470193c058108f19d8" integrity sha512-LdIUOb3gvfmpkgFZuccNa2uYiqtgZAz3PTzjuM5bH3nvuy9ty6RGc/Q0+HDFrHrizJGVpjnTZ1yS5TNNjFlklw== "@rollup/rollup-linux-s390x-gnu@4.41.1": version "4.41.1" resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.41.1.tgz#98896eca8012547c7f04bd07eaa6896825f9e1a5" integrity sha512-oIE6M8WC9ma6xYqjvPhzZYk6NbobIURvP/lEbh7FWplcMO6gn7MM2yHKA1eC/GvYwzNKK/1LYgqzdkZ8YFxR8g== "@rollup/rollup-linux-x64-gnu@4.41.1": version "4.41.1" resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.41.1.tgz#01cf56844a1e636ee80dfb364e72c2b7142ad896" integrity sha512-cWBOvayNvA+SyeQMp79BHPK8ws6sHSsYnK5zDcsC3Hsxr1dgTABKjMnMslPq1DvZIp6uO7kIWhiGwaTdR4Og9A== "@rollup/rollup-linux-x64-musl@4.41.1": version "4.41.1" resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.41.1.tgz#e67c7531df6dff0b4c241101d4096617fbca87c3" integrity sha512-y5CbN44M+pUCdGDlZFzGGBSKCA4A/J2ZH4edTYSSxFg7ce1Xt3GtydbVKWLlzL+INfFIZAEg1ZV6hh9+QQf9YQ== "@rollup/rollup-win32-arm64-msvc@4.41.1": version "4.41.1" resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.41.1.tgz#7eeada98444e580674de6989284e4baacd48ea65" integrity sha512-lZkCxIrjlJlMt1dLO/FbpZbzt6J/A8p4DnqzSa4PWqPEUUUnzXLeki/iyPLfV0BmHItlYgHUqJe+3KiyydmiNQ== "@rollup/rollup-win32-ia32-msvc@4.41.1": version "4.41.1" resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.41.1.tgz#516c4b54f80587b4a390aaf4940b40870271d35d" integrity sha512-+psFT9+pIh2iuGsxFYYa/LhS5MFKmuivRsx9iPJWNSGbh2XVEjk90fmpUEjCnILPEPJnikAU6SFDiEUyOv90Pg== "@rollup/rollup-win32-x64-msvc@4.41.1": version "4.41.1" resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.41.1.tgz#848f99b0d9936d92221bb6070baeff4db6947a30" integrity sha512-Wq2zpapRYLfi4aKxf2Xff0tN+7slj2d4R87WEzqw7ZLsVvO5zwYCIuEGSZYiK41+GlwUo1HiR+GdkLEJnCKTCw== "@types/estree@1.0.7": version "1.0.7" resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.7.tgz#4158d3105276773d5b7695cd4834b1722e4f37a8" integrity sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ== before-after-hook@^2.2.0: version "2.2.3" resolved "https://registry.yarnpkg.com/before-after-hook/-/before-after-hook-2.2.3.tgz#c51e809c81a4e354084422b9b26bad88249c517c" integrity sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ== deprecation@^2.0.0: version "2.3.1" resolved "https://registry.yarnpkg.com/deprecation/-/deprecation-2.3.1.tgz#6368cbdb40abf3373b525ac87e4a260c3a700919" integrity sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ== esbuild@^0.25.5: version "0.25.5" resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.25.5.tgz#71075054993fdfae76c66586f9b9c1f8d7edd430" integrity sha512-P8OtKZRv/5J5hhz0cUAdu/cLuPIKXpQl1R9pZtvmHWQvrAUVd0UNIPT4IB4W3rNOqVO0rlqHmCIbSwxh/c9yUQ== optionalDependencies: "@esbuild/aix-ppc64" "0.25.5" "@esbuild/android-arm" "0.25.5" "@esbuild/android-arm64" "0.25.5" "@esbuild/android-x64" "0.25.5" "@esbuild/darwin-arm64" "0.25.5" "@esbuild/darwin-x64" "0.25.5" "@esbuild/freebsd-arm64" "0.25.5" "@esbuild/freebsd-x64" "0.25.5" "@esbuild/linux-arm" "0.25.5" "@esbuild/linux-arm64" "0.25.5" "@esbuild/linux-ia32" "0.25.5" "@esbuild/linux-loong64" "0.25.5" "@esbuild/linux-mips64el" "0.25.5" "@esbuild/linux-ppc64" "0.25.5" "@esbuild/linux-riscv64" "0.25.5" "@esbuild/linux-s390x" "0.25.5" "@esbuild/linux-x64" "0.25.5" "@esbuild/netbsd-arm64" "0.25.5" "@esbuild/netbsd-x64" "0.25.5" "@esbuild/openbsd-arm64" "0.25.5" "@esbuild/openbsd-x64" "0.25.5" "@esbuild/sunos-x64" "0.25.5" "@esbuild/win32-arm64" "0.25.5" "@esbuild/win32-ia32" "0.25.5" "@esbuild/win32-x64" "0.25.5" fsevents@~2.3.2: version "2.3.3" resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== once@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== dependencies: wrappy "1" rollup@^4.41.1: version "4.41.1" resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.41.1.tgz#46ddc1b33cf1b0baa99320d3b0b4973dc2253b6a" integrity sha512-cPmwD3FnFv8rKMBc1MxWCwVQFxwf1JEmSX3iQXrRVVG15zerAIXRjMFVWnd5Q5QvgKF7Aj+5ykXFhUl+QGnyOw== dependencies: "@types/estree" "1.0.7" optionalDependencies: "@rollup/rollup-android-arm-eabi" "4.41.1" "@rollup/rollup-android-arm64" "4.41.1" "@rollup/rollup-darwin-arm64" "4.41.1" "@rollup/rollup-darwin-x64" "4.41.1" "@rollup/rollup-freebsd-arm64" "4.41.1" "@rollup/rollup-freebsd-x64" "4.41.1" "@rollup/rollup-linux-arm-gnueabihf" "4.41.1" "@rollup/rollup-linux-arm-musleabihf" "4.41.1" "@rollup/rollup-linux-arm64-gnu" "4.41.1" "@rollup/rollup-linux-arm64-musl" "4.41.1" "@rollup/rollup-linux-loongarch64-gnu" "4.41.1" "@rollup/rollup-linux-powerpc64le-gnu" "4.41.1" "@rollup/rollup-linux-riscv64-gnu" "4.41.1" "@rollup/rollup-linux-riscv64-musl" "4.41.1" "@rollup/rollup-linux-s390x-gnu" "4.41.1" "@rollup/rollup-linux-x64-gnu" "4.41.1" "@rollup/rollup-linux-x64-musl" "4.41.1" "@rollup/rollup-win32-arm64-msvc" "4.41.1" "@rollup/rollup-win32-ia32-msvc" "4.41.1" "@rollup/rollup-win32-x64-msvc" "4.41.1" fsevents "~2.3.2" tunnel@^0.0.6: version "0.0.6" resolved "https://registry.yarnpkg.com/tunnel/-/tunnel-0.0.6.tgz#72f1314b34a5b192db012324df2cc587ca47f92c" integrity sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg== undici@^5.25.4, undici@^5.28.5: version "5.29.0" resolved "https://registry.yarnpkg.com/undici/-/undici-5.29.0.tgz#419595449ae3f2cdcba3580a2e8903399bd1f5a3" integrity sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg== dependencies: "@fastify/busboy" "^2.0.0" universal-user-agent@^6.0.0: version "6.0.1" resolved "https://registry.yarnpkg.com/universal-user-agent/-/universal-user-agent-6.0.1.tgz#15f20f55da3c930c57bddbf1734c6654d5fd35aa" integrity sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ== wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== node-tailwind-merge-3.3.1/.github/funding.yml000066400000000000000000000000201502210756000210540ustar00rootroot00000000000000github: dcastil node-tailwind-merge-3.3.1/.github/release-drafter.yml000066400000000000000000000027741502210756000225110ustar00rootroot00000000000000name-template: 'v$RESOLVED_VERSION' tag-template: 'v$RESOLVED_VERSION' template: | $CHANGES **Full Changelog**: https://github.com/dcastil/tailwind-merge/compare/$PREVIOUS_TAG...v$RESOLVED_VERSION category-template: '### $TITLE' change-template: '- $TITLE by @$AUTHOR in https://github.com/dcastil/tailwind-merge/pull/$NUMBER' change-title-escapes: '\<*_&' no-changes-template: 'No changes' categories: - title: '⚠️ Needs Changelog Edit' label: 'needs changelog edit' - title: 'Breaking Changes' label: 'breaking' - title: 'New Features' label: 'feature' - title: 'Bug Fixes' label: 'bug' - title: 'Documentation' label: 'documentation' - title: 'Other' label: 'other' exclude-labels: - 'skip changelog' version-resolver: major: labels: - 'breaking' minor: labels: - 'feature' patch: labels: - 'bug' - 'documentation' - 'other' default: 'patch' autolabeler: - label: 'feature' branch: - '/\bfeature\b/i' title: - '/\bfeature\b/i' - label: 'bug' branch: - '/\b(bug|bugfix|fix)\b/i' title: - '/\b(bug|bugfix|fix)\b/i' - label: 'documentation' branch: - '/\b(documentation|docs)\b/i' title: - '/\b(documentation|docs)\b/i' - label: 'other' branch: - '/^other\b/i' - label: 'breaking' branch: - '/^breaking-/i' node-tailwind-merge-3.3.1/.github/renovate.json000066400000000000000000000005651502210756000214330ustar00rootroot00000000000000{ "extends": [ "config:recommended", ":combinePatchMinorReleases", "group:allNonMajor", ":labels(dependencies,skip changelog)", ":assignee(dcastil)", ":enableVulnerabilityAlertsWithLabel(security)", "schedule:monthly" ], "timezone": "Europe/Berlin", "prHourlyLimit": 10, "rangeStrategy": "bump" } node-tailwind-merge-3.3.1/.github/workflows/000077500000000000000000000000001502210756000207445ustar00rootroot00000000000000node-tailwind-merge-3.3.1/.github/workflows/benchmark.yml000066400000000000000000000015201502210756000234170ustar00rootroot00000000000000name: Benchmark on: push: branches: - main pull_request: jobs: benchmark: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Use Node.js 22 uses: actions/setup-node@v4 with: node-version: 22.16.0 - name: Use node_modules cache uses: actions/cache@v4 with: path: node_modules key: yarn-node-22-lock-${{ hashFiles('yarn.lock') }} restore-keys: | yarn-node-22-lock- - run: yarn install --frozen-lockfile - name: Run benchmark uses: CodSpeedHQ/action@v3 with: token: ${{ secrets.CODSPEED_TOKEN }} run: yarn bench node-tailwind-merge-3.3.1/.github/workflows/codeql-analysis.yml000066400000000000000000000020671502210756000245640ustar00rootroot00000000000000name: 'CodeQL' on: push: branches: [main] schedule: - cron: '30 8 * * 5' jobs: analyze: name: Analyze runs-on: ubuntu-latest permissions: actions: read contents: read security-events: write steps: - uses: actions/checkout@v4 - name: Use Node.js 22 uses: actions/setup-node@v4 with: node-version: 22.16.0 - name: Use node_modules cache uses: actions/cache@v4 with: path: node_modules key: yarn-node-22-lock-${{ hashFiles('yarn.lock') }} restore-keys: | yarn-node-22-lock- - name: Initialize CodeQL uses: github/codeql-action/init@v3 with: languages: javascript - run: yarn install --frozen-lockfile - run: yarn build - name: Perform CodeQL Analysis uses: github/codeql-action/analyze@v3 node-tailwind-merge-3.3.1/.github/workflows/comment-released-prs-and-issues.yml000066400000000000000000000007641502210756000275750ustar00rootroot00000000000000name: Comment released PRs and issues on: release: types: [published] jobs: release: runs-on: ubuntu-latest permissions: issues: write pull-requests: write steps: - uses: apexskier/github-release-commenter@v1 with: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} comment-template: This was addressed in release {release_link}. skip-label: skip-release-comment node-tailwind-merge-3.3.1/.github/workflows/draft-release.yml000066400000000000000000000005611502210756000242070ustar00rootroot00000000000000name: Draft Release on: push: branches: [main] pull_request: types: [opened, reopened, synchronize] jobs: update_release_draft: runs-on: ubuntu-latest steps: - uses: release-drafter/release-drafter@v6 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} permissions: write-all node-tailwind-merge-3.3.1/.github/workflows/label.yml000066400000000000000000000044761502210756000225610ustar00rootroot00000000000000name: Auto Label New Issues, PRs, and Discussions on: issues: types: [opened] pull_request_target: types: [opened] discussion: types: [created] jobs: add-label: runs-on: ubuntu-latest permissions: issues: write discussions: write pull-requests: write env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} REPO_OWNER: ${{ github.repository_owner }} REPO_NAME: ${{ github.event.repository.name }} LABEL_NAME: context-v3 steps: - name: Checkout repository uses: actions/checkout@v4 - name: Add label to new issue if: github.event_name == 'issues' run: | ISSUE_NUMBER=${{ github.event.issue.number }} gh issue edit "$ISSUE_NUMBER" --add-label "$LABEL_NAME" - name: Add label to new PR if: github.event_name == 'pull_request_target' run: | PR_NUMBER=${{ github.event.pull_request.number }} gh pr edit "$PR_NUMBER" --add-label "$LABEL_NAME" - name: Get label id for discussion id: label-data if: github.event_name == 'discussion' run: | res="$(gh api \ -H "Accept: application/vnd.github+json" \ -H "X-GitHub-Api-Version: 2022-11-28" \ /repos/$REPO_OWNER/$REPO_NAME/labels/$LABEL_NAME --jq '.node_id')" echo "label_id=$res" >> $GITHUB_OUTPUT - name: Add label to new discussion uses: octokit/graphql-action@v2.x if: github.event_name == 'discussion' env: DISCUSSION_ID: ${{ github.event.discussion.node_id }} LABEL_ID: ${{ steps.label-data.outputs.label_id }} with: query: | mutation { addLabelsToLabelable( input:{ labelableId: "${{env.DISCUSSION_ID}}" labelIds: ["${{ env.LABEL_ID}}"] } ) { clientMutationId } } node-tailwind-merge-3.3.1/.github/workflows/metrics-report.yml000066400000000000000000000026531502210756000244540ustar00rootroot00000000000000name: Metrics report on: [pull_request] jobs: metrics-report: runs-on: ubuntu-latest permissions: pull-requests: write steps: - uses: actions/checkout@v4 - name: Use Node.js 22 uses: actions/setup-node@v4 with: node-version: 22.16.0 - name: Restore node_modules cache uses: actions/cache/restore@v4 with: path: node_modules key: yarn-node-22-lock-${{ hashFiles('yarn.lock') }} restore-keys: | yarn-node-22-lock- - run: yarn --frozen-lockfile - name: Save node_modules cache uses: actions/cache/save@v4 with: path: node_modules key: yarn-node-22-lock-${{ hashFiles('yarn.lock') }} - name: Use node_modules cache for metrics-report-action uses: actions/cache@v4 with: path: .github/actions/metrics-report/node_modules key: yarn-node-22-metrics-report-action-lock-${{ hashFiles('.github/actions/metrics-report/yarn.lock') }} restore-keys: | yarn-node-22-metrics-report-action-lock- - run: yarn --cwd .github/actions/metrics-report install --frozen-lockfile - uses: ./.github/actions/metrics-report node-tailwind-merge-3.3.1/.github/workflows/npm-publish-dev.yml000066400000000000000000000033711502210756000245050ustar00rootroot00000000000000name: npm Publish dev on: push: branches: [main] jobs: publish: runs-on: ubuntu-latest permissions: id-token: write steps: - uses: actions/checkout@v4 - name: Use Node.js 22 uses: actions/setup-node@v4 with: node-version: 22.16.0 # More info: https://docs.github.com/en/actions/publishing-packages/publishing-nodejs-packages#publishing-packages-to-the-npm-registry registry-url: 'https://registry.npmjs.org' - name: Use node_modules cache uses: actions/cache@v4 with: path: node_modules key: yarn-node-22-lock-${{ hashFiles('yarn.lock') }} restore-keys: | yarn-node-22-lock- - run: yarn install --frozen-lockfile - run: yarn build - uses: actions/upload-artifact@v4 with: name: build-output path: dist if-no-files-found: error - uses: martinbeentjes/npm-get-version-action@v1.3.1 id: package-version - run: yarn version --no-git-tag-version --new-version ${{ steps.package-version.outputs.current-version }}-dev.${{ github.sha }} # npm install -g npm@latest is necessary to make provenance available (available since v9.6.5 or so). More info: https://docs.npmjs.com/generating-provenance-statements - run: npm install -g npm@latest - run: npm publish --access public --tag dev env: # Is connected with actions/setup-node -> registry-url NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} node-tailwind-merge-3.3.1/.github/workflows/npm-publish.yml000066400000000000000000000024661502210756000237350ustar00rootroot00000000000000name: npm Publish on: release: types: [published] jobs: publish: runs-on: ubuntu-latest permissions: id-token: write steps: - uses: actions/checkout@v4 - name: Use Node.js 22 uses: actions/setup-node@v4 with: node-version: 22.16.0 - name: Use node_modules cache uses: actions/cache@v4 with: path: node_modules key: yarn-node-22-lock-${{ hashFiles('yarn.lock') }} restore-keys: | yarn-node-22-lock- - run: yarn install --frozen-lockfile - run: yarn lint - run: yarn test - run: yarn build - uses: actions/upload-artifact@v4 with: name: build-output path: dist if-no-files-found: error - run: yarn test:exports # npm install -g npm@latest is necessary to make provenance available (available since v9.6.5 or so). More info: https://docs.npmjs.com/generating-provenance-statements - run: npm install -g npm@latest - uses: JS-DevTools/npm-publish@v3 with: token: ${{ secrets.NPM_TOKEN }} node-tailwind-merge-3.3.1/.github/workflows/test.yml000066400000000000000000000017101502210756000224450ustar00rootroot00000000000000name: Test on: push: branches: ['**'] pull_request: branches: ['**'] jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Use Node.js 22 uses: actions/setup-node@v4 with: node-version: 22.16.0 - name: Use node_modules cache uses: actions/cache@v4 with: path: node_modules key: yarn-node-22-lock-${{ hashFiles('yarn.lock') }} restore-keys: | yarn-node-22-lock- - run: yarn install --frozen-lockfile - run: yarn lint - run: yarn test - run: yarn build - uses: actions/upload-artifact@v4 with: name: build-output path: dist if-no-files-found: error - run: yarn test:exports node-tailwind-merge-3.3.1/.gitignore000066400000000000000000000000771502210756000173430ustar00rootroot00000000000000/.vscode/ /dist/ coverage node_modules/ .DS_Store *.local .ideanode-tailwind-merge-3.3.1/.prettierrc000066400000000000000000000001651502210756000175350ustar00rootroot00000000000000{ "tabWidth": 4, "semi": false, "singleQuote": true, "printWidth": 100, "trailingComma": "all" } node-tailwind-merge-3.3.1/LICENSE.md000066400000000000000000000020561502210756000167560ustar00rootroot00000000000000MIT License Copyright (c) 2021 Dany Castillo Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. node-tailwind-merge-3.3.1/README.md000066400000000000000000000037471502210756000166410ustar00rootroot00000000000000 # tailwind-merge Utility function to efficiently merge [Tailwind CSS](https://tailwindcss.com) classes in JS without style conflicts. ```ts import { twMerge } from 'tailwind-merge' twMerge('px-2 py-1 bg-red hover:bg-dark-red', 'p-3 bg-[#B91C1C]') // → 'hover:bg-dark-red p-3 bg-[#B91C1C]' ``` - Supports Tailwind v4.0 up to v4.1 (if you use Tailwind v3, use [tailwind-merge v2.6.0](https://github.com/dcastil/tailwind-merge/tree/v2.6.0)) - Works in all modern browsers and maintained Node versions - Fully typed - [Check bundle size on Bundlephobia](https://bundlephobia.com/package/tailwind-merge) ## Get started - [What is it for](https://github.com/dcastil/tailwind-merge/tree/v3.3.1/docs/what-is-it-for.md) - [When and how to use it](https://github.com/dcastil/tailwind-merge/tree/v3.3.1/docs/when-and-how-to-use-it.md) - [Features](https://github.com/dcastil/tailwind-merge/tree/v3.3.1/docs/features.md) - [Limitations](https://github.com/dcastil/tailwind-merge/tree/v3.3.1/docs/limitations.md) - [Configuration](https://github.com/dcastil/tailwind-merge/tree/v3.3.1/docs/configuration.md) - [Recipes](https://github.com/dcastil/tailwind-merge/tree/v3.3.1/docs/recipes.md) - [API reference](https://github.com/dcastil/tailwind-merge/tree/v3.3.1/docs/api-reference.md) - [Writing plugins](https://github.com/dcastil/tailwind-merge/tree/v3.3.1/docs/writing-plugins.md) - [Versioning](https://github.com/dcastil/tailwind-merge/tree/v3.3.1/docs/versioning.md) - [Contributing](https://github.com/dcastil/tailwind-merge/tree/v3.3.1/docs/contributing.md) - [Similar packages](https://github.com/dcastil/tailwind-merge/tree/v3.3.1/docs/similar-packages.md) node-tailwind-merge-3.3.1/assets/000077500000000000000000000000001502210756000166515ustar00rootroot00000000000000node-tailwind-merge-3.3.1/assets/logo.svg000066400000000000000000000046161502210756000203410ustar00rootroot00000000000000 tailwind-merge node-tailwind-merge-3.3.1/docs/000077500000000000000000000000001502210756000162775ustar00rootroot00000000000000node-tailwind-merge-3.3.1/docs/README.md000066400000000000000000000023031502210756000175540ustar00rootroot00000000000000 # tailwind-merge Utility function to efficiently merge [Tailwind CSS](https://tailwindcss.com) classes in JS without style conflicts. ```ts import { twMerge } from 'tailwind-merge' twMerge('px-2 py-1 bg-red hover:bg-dark-red', 'p-3 bg-[#B91C1C]') // → 'hover:bg-dark-red p-3 bg-[#B91C1C]' ``` - Supports Tailwind v4.0 up to v4.1 (if you use Tailwind v3, use [tailwind-merge v2.6.0](https://github.com/dcastil/tailwind-merge/tree/v2.6.0)) - Works in all modern browsers and maintained Node versions - Fully typed - [Check bundle size on Bundlephobia](https://bundlephobia.com/package/tailwind-merge) ## Get started - [What is it for](./what-is-it-for.md) - [When and how to use it](./when-and-how-to-use-it.md) - [Features](./features.md) - [Limitations](./limitations.md) - [Configuration](./configuration.md) - [Recipes](./recipes.md) - [API reference](./api-reference.md) - [Writing plugins](./writing-plugins.md) - [Versioning](./versioning.md) - [Contributing](./contributing.md) - [Similar packages](./similar-packages.md) node-tailwind-merge-3.3.1/docs/api-reference.md000066400000000000000000000451671502210756000213430ustar00rootroot00000000000000# API reference Reference to all exports of tailwind-merge. ## `twMerge` ```ts function twMerge( ...classLists: Array ): string ``` Default function to use if you're using the default Tailwind config or are close enough to the default config. Check out [basic usage](./configuration.md#basic-usage) for more info. If `twMerge` doesn't work for you, you can create your own custom merge function with [`extendTailwindMerge`](#extendtailwindmerge). ## `twJoin` ```ts function twJoin( ...classLists: Array ): string ``` Function to join className strings conditionally without resolving conflicts. ```ts twJoin( 'border border-red-500', hasBackground && 'bg-red-100', hasLargeText && 'text-lg', hasLargeSpacing && ['p-2', hasLargeText ? 'leading-8' : 'leading-7'], ) ``` It is used internally within `twMerge` and a direct subset of [`clsx`](https://www.npmjs.com/package/clsx). If you use `clsx` or [`classnames`](https://www.npmjs.com/package/classnames) to apply Tailwind classes conditionally and don't need support for object arguments, you can use `twJoin` instead, it is a little faster and will save you a few hundred bytes in bundle size. Why no object support? [Read here](https://github.com/dcastil/tailwind-merge/discussions/137#discussioncomment-3481605). ## `getDefaultConfig` ```ts function getDefaultConfig(): satisfies Config ``` Function which returns the default config used by tailwind-merge. The tailwind-merge config is different from the Tailwind config. It is optimized for small bundle size and fast runtime performance because it is expected to run in the browser. ## `fromTheme` ```ts function fromTheme< AdditionalThemeGroupIds extends string = never, DefaultThemeGroupIdsInner extends string = DefaultThemeGroupIds, >(key: NoInfer): ThemeGetter ``` Function to retrieve values from a theme scale, to be used in class groups. `fromTheme` doesn't return the values from the theme scale, but rather another function which is used by tailwind-merge internally to retrieve the theme values. tailwind-merge can differentiate the theme getter function from a validator because it has a `isThemeGetter` property set to `true`. When using TypeScript, the function only allows passing the default theme group IDs as the `key` argument. If you use custom theme group IDs, you need to pass them as the generic type argument `AdditionalThemeGroupIds`. In case you aren't using the default tailwind-merge config and use a different set of theme group IDs entirely, you can also pass them as the generic type argument `DefaultThemeGroupIdsInner`. If you want to allow any keys, you can call it as `fromTheme('anything-goes-here')`. `fromTheme` can be used like this: ```ts type AdditionalClassGroupIds = 'my-group' | 'my-group-x' type AdditionalThemeGroupIds = 'my-scale' extendTailwindMerge({ extend: { theme: { 'my-scale': ['foo', 'bar'], }, classGroups: { 'my-group': [ { 'my-group': [ fromTheme('my-scale'), fromTheme('spacing'), ], }, ], 'my-group-x': [{ 'my-group-x': [fromTheme('my-scale')] }], }, }, }) ``` ## `extendTailwindMerge` ```ts function extendTailwindMerge< AdditionalClassGroupIds extends string = never, AdditionalThemeGroupIds extends string = never, >( configExtension: ConfigExtension< DefaultClassGroupIds | AdditionalClassGroupIds, DefaultThemeGroupIds | AdditionalThemeGroupIds >, ...createConfig: ((config: GenericConfig) => GenericConfig)[] ): TailwindMerge function extendTailwindMerge< AdditionalClassGroupIds extends string = never, AdditionalThemeGroupIds extends string = never, >(...createConfig: ((config: GenericConfig) => GenericConfig)[]): TailwindMerge ``` Function to create merge function with custom config which extends the default config. Use this if you use the default Tailwind config and just modified it in some places. > [!Note] > The function `extendTailwindMerge` computes a large data structure based on the config passed to it. I recommend to call it only once and store the result in a top-level variable instead of calling it inline within another repeatedly called function. You provide it a `configExtension` object which gets [merged](#mergeconfigs) with the default config. When using TypeScript and you use custom class group IDs or theme group IDs, you need to pass them as the generic type arguments `AdditionalClassGroupIds` and `AdditionalThemeGroupIds`. This is enforced to prevent accidental use of non-existing class group IDs accidentally. If you want to allow any custom keys without explicitly defining them, you can pass as `string` to both arguments. ```ts type AdditionalClassGroupIds = 'aspect-w' | 'aspect-h' | 'aspect-reset' type AdditionalThemeGroupIds = never const twMerge = extendTailwindMerge({ // ↓ Optional cache size // Here we're disabling the cache cacheSize: 0, // ↓ Optional prefix from TaiLwind config prefix: 'tw', // ↓ Optional config overrides // Only elements from the second level onwards are overridden override: { // ↓ Theme scales to override theme: { colors: ['black', 'white', 'yellow-500'], }, // ↓ Class groups to override classGroups: { // ↓ The `shadow` key here is the class group ID // ↓ Creates group of classes which have conflicting styles // Classes here: shadow-100, shadow-200, shadow-300, shadow-400, shadow-500 shadow: [{ shadow: ['100', '200', '300', '400', '500'] }], }, // ↓ Conflicts across different groups to override conflictingClassGroups: { // ↓ ID of class group which creates a conflict with… // ↓ …classes from groups with these IDs // Here we remove the default conflict between the font-size and leading class // groups. 'font-size': [], }, // ↓ Conflicts between the postfix modifier of a group and a different class group to // override conflictingClassGroupModifiers: { // You probably won't need this, but it follows the same shape as // `conflictingClassGroups`. }, // ↓ Modifiers whose order among multiple modifiers should be preserved because their // order changes which element gets targeted. Overrides default value. orderSensitiveModifiers: ['before'], }, // ↓ Optional config extensions // Follows same shape as the `override` object. extend: { // ↓ Theme scales to extend or create theme: { spacing: ['sm', 'md', 'lg'], }, // ↓ Class groups to extend or create classGroups: { // ↓ The `animate` key here is the class group ID // ↓ Adds class animate-shimmer to existing group with ID `animate` or creates // new class group if it doesn't exist. animate: ['animate-shimmer'], // ↓ Functions can also be used to match classes // They take the class part value as argument and return a boolean defining whether // it is a match. // Here we accept all string classes starting with `aspec-w-` followed by a number. 'aspect-w': [{ 'aspect-w': [(value) => Boolean(value) && !isNaN(value)] }], 'aspect-h': [{ 'aspect-h': [(value) => Boolean(value) && !isNaN(value)] }], 'aspect-reset': ['aspect-none'], // ↓ You can also use validators exported by tailwind-merge 'prose-size': [{ prose: ['base', validators.isTshirtSize] }], }, // ↓ Conflicts across different groups to extend or create conflictingClassGroups: { // ↓ ID of class group which creates a conflict with… // ↓ …classes from groups with these IDs // In this case `twMerge('aspect-w-5 aspect-none') → 'aspect-none'` 'aspect-reset': ['aspect-w', 'aspect-h'], }, // ↓ Conflicts between the postfix modifier of a group and a different class group to // extend or create conflictingClassGroupModifiers: { // You probably won't need this, but it follows the same shape as // `conflictingClassGroups`. }, // ↓ Modifiers whose order among multiple modifiers should be preserved because their // order changes which element gets targeted. Extends default value. orderSensitiveModifiers: ['before'], }, }) ``` Additionally, you can pass multiple `createConfig` functions (more to that in [`createTailwindMerge`](#createtailwindmerge)) which is convenient if you want to combine your config with third-party plugins. ```ts const twMerge = extendTailwindMerge({ … }, withSomePlugin) ``` If you only use plugins, you can omit the `configExtension` object as well. ```ts const twMerge = extendTailwindMerge(withSomePlugin) ``` ## `createTailwindMerge` ```ts function createTailwindMerge( ...createConfig: [() => Config, ...Array<(config: Config) => Config>] ): TailwindMerge ``` Function to create merge function with custom config. Use this function instead of [`extendTailwindMerge`](#extendtailwindmerge) if you don't need the default config or want more control over the config. > [!Note] > The function `createTailwindMerge` computes a large data structure based on the config passed to it. I recommend to call it only once and store the result in a top-level variable instead of calling it inline within another repeatedly called function. You need to provide a function which resolves to the config tailwind-merge should use for the new merge function. You can either extend from the default config or create a new one from scratch. ```ts // ↓ Callback passed to `createTailwindMerge` is called when // `twMerge` gets called the first time. const twMerge = createTailwindMerge(() => { const defaultConfig = getDefaultConfig() return { cacheSize: 0, classGroups: { ...defaultConfig.classGroups, foo: ['foo', 'foo-2', { 'bar-baz': ['', '1', '2'] }], bar: [{ qux: ['auto', (value) => Number(value) >= 1000] }], baz: ['baz-sm', 'baz-md', 'baz-lg'], }, conflictingClassGroups: { ...defaultConfig.conflictingClassGroups, foo: ['bar'], }, conflictingClassGroupModifiers: { ...defaultConfig.conflictingClassGroupModifiers, baz: ['bar'], }, orderSensitiveModifiers: [...defaultConfig.orderSensitiveModifiers, 'before'], } }) ``` Same as in [`extendTailwindMerge`](#extendtailwindmerge) you can use multiple `createConfig` functions which is convenient if you want to combine your config with third-party plugins. Just keep in mind that the first `createConfig` function does not get passed any arguments, whereas the subsequent functions get each passed the config from the previous function. ```ts const twMerge = createTailwindMerge(getDefaultConfig, withSomePlugin, (config) => ({ // ↓ Config returned by `withSomePlugin` ...config, classGroups: { ...config.classGroups, mySpecialClassGroup: [{ special: ['1', '2'] }], }, })) ``` But don't merge configs like that. Use [`mergeConfigs`](#mergeconfigs) instead. ## `mergeConfigs` ```ts function mergeConfigs( baseConfig: GenericConfig, configExtension: ConfigExtension, ): GenericConfig ``` Helper function to merge multiple tailwind-merge configs. Properties with the value `undefined` are skipped. When using TypeScript, you need to pass a union of all class group IDs and theme group IDs used in `configExtension` as generic arguments to `mergeConfigs` or pass `string` to both arguments to allow any IDs. ```ts const twMerge = createTailwindMerge(getDefaultConfig, (config) => mergeConfigs<'shadow' | 'animate' | 'prose'>(config, { override: { classGroups: { // ↓ Overriding existing class group shadow: [{ shadow: ['100', '200', '300', '400', '500'] }], }, } extend: { classGroups: { // ↓ Adding value to existing class group animate: ['animate-shimmer'], // ↓ Adding new class group prose: [{ prose: ['', validators.isTshirtSize] }], } }, }), ) ``` ## `validators` ```ts interface Validators { isAny(value: string): boolean isAnyNonArbitrary(value: string): boolean isArbitraryImage(value: string): boolean isArbitraryLength(value: string): boolean isArbitraryNumber(value: string): boolean isArbitraryPosition(value: string): boolean isArbitraryShadow(value: string): boolean isArbitrarySize(value: string): boolean isArbitraryValue(value: string): boolean isArbitraryVariable(value: string): boolean isArbitraryVariableFamilyName(value: string): boolean isArbitraryVariableImage(value: string): boolean isArbitraryVariableLength(value: string): boolean isArbitraryVariablePosition(value: string): boolean isArbitraryVariableShadow(value: string): boolean isArbitraryVariableSize(value: string): boolean isFraction(value: string): boolean isInteger(value: string): boolean isNumber(value: string): boolean isPercent(value: string): boolean isTshirtSize(value: string): boolean } ``` An object containing all the validators used in tailwind-merge. They are useful if you want to use a custom config with [`extendTailwindMerge`](#extendtailwindmerge) or [`createTailwindMerge`](#createtailwindmerge). E.g. the `classGroup` for padding is defined as ```ts const paddingClassGroup = [{ p: [validators.isNumber] }] ``` A brief summary for each validator: - `isAny` always returns true. Be careful with this validator as it might match unwanted classes. I use it primarily to match colors or when I'm certain there are no other class groups in a namespace. - `isAnyNonArbitrary` checks if the class part is not an arbitrary value or arbitrary variable. - `isArbitraryImage` checks whether class part is an arbitrary value which is an iamge, e.g. by starting with `image:`, `url:`, `linear-gradient(` or `url(` (`[url('/path-to-image.png')]`, `image:var(--maybe-an-image-at-runtime)]`) which is necessary for background-image classNames. - `isArbitraryLength` checks for arbitrary length values (`[3%]`, `[4px]`, `[length:var(--my-var)]`). - `isArbitraryNumber` checks whether class part is an arbitrary value which starts with `number:` or is a number (`[number:var(--value)]`, `[450]`) which is necessary for font-weight and stroke-width classNames. - `isArbitraryPosition` checks whether class part is an arbitrary value which starts with `position:` (`[position:200px_100px]`) which is necessary for background-position classNames. - `isArbitraryShadow` checks whether class part is an arbitrary value which starts with the same pattern as a shadow value (`[0_35px_60px_-15px_rgba(0,0,0,0.3)]`), namely with two lengths separated by a underscore, optionally prepended by `inset`. - `isArbitrarySize` checks whether class part is an arbitrary value which starts with `size:` (`[size:200px_100px]`) which is necessary for background-size classNames. - `isArbitraryValue` checks whether the class part is enclosed in brackets (`[something]`) - `isArbitraryVariable` checks whether the class part is an arbitrary variable (`(--my-var)`) - `isArbitraryVariableFamilyName` checks whether class part is an arbitrary variable with the `family-name` label (`(family-name:--my-font)`) - `isArbitraryVariableImage` checks whether class part is an arbitrary variable with the `image` or `url` label (`(image:--my-image)`) - `isArbitraryVariableLength` checks whether class part is an arbitrary variable with the `length` label (`(length:--my-length)`) - `isArbitraryVariablePosition` checks whether class part is an arbitrary variable with the `position` label (`(position:--my-position)`) - `isArbitraryVariableShadow` checks whether class part is an arbitrary variable with the `shadow` label or not label at all (`(shadow:--my-shadow)`, `(--my-shadow)`) - `isArbitraryVariableSize` checks whether class part is an arbitrary variable with the `size`, `length` or `percentage` label (`(size:--my-size)`) - `isFraction` checks whether class part is a fraction of two numbers (`1/2`, `127/256`) - `isInteger` checks for integer values (`3`). - `isNumber` checks for numbers (`3`, `1.5`) - `isPercent` checks for percent values (`12.5%`) which is used for color stop positions. - `isTshirtSize`checks whether class part is a T-shirt size (`sm`, `xl`), optionally with a preceding number (`2xl`). ## `Config` ```ts interface Config { … } ``` TypeScript type for config object. Useful if you want to build a `createConfig` function but don't want to define it inline in [`extendTailwindMerge`](#extendtailwindmerge) or [`createTailwindMerge`](#createtailwindmerge). ## `DefaultClassGroupIds` ```ts type DefaultClassGroupIds = 'accent' | 'align-content' | 'align-items' | … ``` TypeScript type for all class group IDs defined in the default config of tailwind-merge. ## `DefaultThemeGroupIds` ```ts type DefaultThemeGroupIds = 'blur' | 'borderColor' | 'borderRadius' | … ``` TypeScript type for all theme group IDs defined in the default config of tailwind-merge. ## `ClassNameValue` ```ts type ClassNameValue = string | null | undefined | 0 | false | ClassNameValue[] ``` TypeScript type for arguments accepted by [`twMerge`](#twmerge) and [`twJoin`](#twjoin). You might want to use it if you wrap any of those with your own function. ```ts function myWrappedTwMerge(...args: ClassNameValue[]) { doSomething() return twMerge(...args) } ``` ## `ClassValidator` ```ts type ClassValidator = (value: string) => boolean ``` TypeScript type for class validators accepted in class definitions within [`extendTailwindMerge`](#extendtailwindmerge) and [`createTailwindMerge`](#createtailwindmerge). --- Next: [Writing plugins](./writing-plugins.md) Previous: [Recipes](./recipes.md) [Back to overview](./README.md) node-tailwind-merge-3.3.1/docs/changelog/000077500000000000000000000000001502210756000202265ustar00rootroot00000000000000node-tailwind-merge-3.3.1/docs/changelog/v0-changelog.md000066400000000000000000000267071502210756000230360ustar00rootroot00000000000000# Changelog for v0 releases ## v0.9.0 ### New Features - Mimic theme from Tailwind config in tailwind-merge config by [@dcastil](https://github.com/dcastil) in [#55](https://github.com/dcastil/tailwind-merge/pull/55) - Adds support for some theme properties like `spacing`, `borderRadius`, etc. More on that in the [theme docs](https://github.com/dcastil/tailwind-merge/tree/v0.9.0#theme). **Full Changelog**: [`v0.8.2...v0.9.0`](https://github.com/dcastil/tailwind-merge/compare/v0.8.2...v0.9.0) ## v0.8.2 ### Bug Fixes - Fix custom values for list-style-type missing in default config by [@dcastil](https://github.com/dcastil) in [#53](https://github.com/dcastil/tailwind-merge/pull/53) **Full Changelog**: [`v0.8.1...v0.8.2`](https://github.com/dcastil/tailwind-merge/compare/v0.8.1...v0.8.2) ## v0.8.1 ### Bug Fixes - Fix missing support for custom values in some class groups in default config by [@dcastil](https://github.com/dcastil) in [#52](https://github.com/dcastil/tailwind-merge/pull/52) - Adds missing support for custom values in following class groups: Grid Auto Columns, Grid Auto Rows, Max-Width, Transition Property, Transition Timing Function, Animation, Fill, Stroke **Full Changelog**: [`v0.8.0...v0.8.1`](https://github.com/dcastil/tailwind-merge/compare/v0.8.0...v0.8.1) ## v0.8.0 ### Summary This is a big release with breaking changes. These were necessary to improve the API before the coming v1.0.0 release and to add better plugin support. If you feel like writing a plugin, check out the [plugins section](https://github.com/dcastil/tailwind-merge/tree/v0.8.0#writing-plugins) in the docs! ### Breaking Changes - Previously there was a list of prefixes in the tailwind-merge config which was used to match Tailwind prefixes. I removed those and match all prefixes as valid Tailwind prefixes. This is only a breaking change if you use non-Tailwind classes with `:` in them which look like Tailwind classes after the prefix. tailwind-merge will treat those as Tailwind classes and resolve conflicts incorrectly. [#50](https://github.com/dcastil/tailwind-merge/pull/50)) - `createTailwindMerge` - If you added custom prefixes to your tailwind-merge config, you can remove them now. If you use TypeScript, you need to remove them. ([#50](https://github.com/dcastil/tailwind-merge/pull/50)) - Doesn't get passed the `getDefaultConfig` callback anymore. You need to call the exported function [`getDefaultConfig`](https://github.com/dcastil/tailwind-merge/tree/v0.8.0#getdefaultconfig) instead to get the default config. ([#42](https://github.com/dcastil/tailwind-merge/pull/42)) - You probably don't need `createTailwindMerge` anyway. Use the new and much simpler to use [`extendTailwindMerge`](https://github.com/dcastil/tailwind-merge/tree/v0.8.0#extendtailwindmerge) instead. ([#49](https://github.com/dcastil/tailwind-merge/pull/49)) ### New Features - Add plugin documentation by [@dcastil](https://github.com/dcastil) in [#51](https://github.com/dcastil/tailwind-merge/pull/51) - (Breaking change) Consider all prefixes as valid Tailwind prefixes by [@dcastil](https://github.com/dcastil) in [#50](https://github.com/dcastil/tailwind-merge/pull/50) - Add `extendTailwindMerge` function by [@dcastil](https://github.com/dcastil) in [#49](https://github.com/dcastil/tailwind-merge/pull/49) - Add `mergeConfigs` function by [@dcastil](https://github.com/dcastil) in [#45](https://github.com/dcastil/tailwind-merge/pull/45) - (Breaking change) Code-split default config out by [@dcastil](https://github.com/dcastil) in [#42](https://github.com/dcastil/tailwind-merge/pull/42) - Enable multiple `createConfig` functions by [@dcastil](https://github.com/dcastil) in [#40](https://github.com/dcastil/tailwind-merge/pull/40) - Add validators to package exports by [@dcastil](https://github.com/dcastil) in [#38](https://github.com/dcastil/tailwind-merge/pull/38) ### Bug Fixes - Remove unwated side effects when mutating default config by [@dcastil](https://github.com/dcastil) in [#43](https://github.com/dcastil/tailwind-merge/pull/43) - Also added the `Config` type to the package exports **Full Changelog**: [`v0.7.1...v0.8.0`](https://github.com/dcastil/tailwind-merge/compare/v0.7.1...v0.8.0) ## v0.7.1 ### Bug Fixes - Fix CommonJS imports not working by [@navin-moorthy](https://github.com/navin-moorthy) and [@dcastil](https://github.com/dcastil) in [#31](https://github.com/dcastil/tailwind-merge/pull/31) **Full Changelog**: [`v0.7.0...v0.7.1`](https://github.com/dcastil/tailwind-merge/compare/v0.7.0...v0.7.1) ## v0.7.0 ### New Features - Allow passing `false` to `twMerge` by [@dcastil](https://github.com/dcastil) in [#25](https://github.com/dcastil/tailwind-merge/pull/25) **Full Changelog**: [`v0.6.0...v0.7.0`](https://github.com/dcastil/tailwind-merge/compare/v0.6.0...v0.7.0) ## v0.6.0 ### New Features - Allow passing `null` as argument to `twMerge` by [@dcastil](https://github.com/dcastil) in [#20](https://github.com/dcastil/tailwind-merge/pull/20) ### Bug Fixes - Fix merges with important modifier not working when using prefixed classes by [@dcastil](https://github.com/dcastil) in [#22](https://github.com/dcastil/tailwind-merge/pull/22) **Full Changelog**: [`v0.5.2...v0.6.0`](https://github.com/dcastil/tailwind-merge/compare/v0.5.2...v0.6.0) ## v0.5.2 ### Bug Fixes - Add support for custom classes like `cursor-[grab]` by [@dcastil](https://github.com/dcastil) in [#19](https://github.com/dcastil/tailwind-merge/pull/19) - Fix incorrect conflicts in Font Variant Numeric classes by [@dcastil](https://github.com/dcastil) in [#18](https://github.com/dcastil/tailwind-merge/pull/18) **Full Changelog**: [`v0.5.1...v0.5.2`](https://github.com/dcastil/tailwind-merge/compare/v0.5.1...v0.5.2) ## v0.5.1 ### Bug Fixes - Fix incorrect conflict between ring and shadow by [@dcastil](https://github.com/dcastil) in [#15](https://github.com/dcastil/tailwind-merge/pull/15) - Fix not all JIT-enabled pseudo variants working by [@dcastil](https://github.com/dcastil) in [#14](https://github.com/dcastil/tailwind-merge/pull/14) ### Other - Add CodeQL security analysis to repo by [@dcastil](https://github.com/dcastil) in [#10](https://github.com/dcastil/tailwind-merge/pull/10) **Full Changelog**: [`v0.5.0...v0.5.1`](https://github.com/dcastil/tailwind-merge/compare/v0.5.0...v0.5.1) ## v0.5.0 ### New Features - Add support for Tailwind CSS v2.2.6 by [@dcastil](https://github.com/dcastil) in [#8](https://github.com/dcastil/tailwind-merge/pull/8) - Delay `twMerge` initialization until first call by [@dcastil](https://github.com/dcastil) in [#7](https://github.com/dcastil/tailwind-merge/pull/7) ### Other - Make logo in README version-specific by [@dcastil](https://github.com/dcastil) in [#6](https://github.com/dcastil/tailwind-merge/pull/6) **Full Changelog**: [`v0.4.0...v0.5.0`](https://github.com/dcastil/tailwind-merge/compare/v0.4.0...v0.5.0) ## v0.4.0 ### Breaking Changes - `createTailwindMerge` - Config type changed and returned object from `getDefaultConfig` changed. ([#3](https://github.com/dcastil/tailwind-merge/pull/3)) - `dynamicClasses` and `standaloneClasses` were merged into `classGroups` - `conflictingGroups` were renamed to `conflictingClassGroups` - Class group IDs are keys of `classGroups` object instead of full path to class group. E.g. `dynamicClasses.foo.0` → `foo`. ### New Features - (Breaking change) Simplify config by [@dcastil](https://github.com/dcastil) in [#3](https://github.com/dcastil/tailwind-merge/pull/3) - Add support for Tailwind v2.2.5 by [@dcastil](https://github.com/dcastil) in [#2](https://github.com/dcastil/tailwind-merge/pull/2) ### Bug Fixes - Fix non-conflicting border classes being merged incorrectly by [@dcastil](https://github.com/dcastil) in [#5](https://github.com/dcastil/tailwind-merge/pull/5) **Full Changelog**: [`v0.3.0...v0.4.0`](https://github.com/dcastil/tailwind-merge/compare/v0.3.0...v0.4.0) ## v0.3.0 ### New Features - Enable named class group collections by [@dcastil](https://github.com/dcastil) in [`16a3175`](https://github.com/dcastil/tailwind-merge/commit/16a31751fdfd87c39683fb4506dec6a0bf118772) - Class group collections in config can be an object, so you can use group references like `dynamicClasses.flex.direction` instead of just index-based ones like `dynamicClasses.flex.0`. More info on this in the [`createTailwindMerge()` API reference](https://github.com/dcastil/tailwind-merge/tree/v0.3.0#createtailwindmerge). ### Bug Fixes - Fix small typos in README by [@KeKs0r](https://github.com/KeKs0r) in [#1](https://github.com/dcastil/tailwind-merge/pull/1) ### Other - tailwind-merge now has a logo by [@dcastil](https://github.com/dcastil) in [`9402c8e`](https://github.com/dcastil/tailwind-merge/commit/9402c8ec1b19714bb8ecb158eb124b89a8c1ba64), [`b969979`](https://github.com/dcastil/tailwind-merge/commit/b96997942d4e92e045c9b08e7314843305b41fe2), [`dae2aaa`](https://github.com/dcastil/tailwind-merge/commit/dae2aaabf8c00b0d5086aff744aa2c53513daf33), [`e9e8806`](https://github.com/dcastil/tailwind-merge/commit/e9e88060578483a3ed4728430f7b188e51aaef49), [`4e2d9f1`](https://github.com/dcastil/tailwind-merge/commit/4e2d9f160dae00e18ebcbecf54f4dd33dc4264bb)

tailwind-merge **Full Changelog**: [`v0.2.0...v0.3.0`](https://github.com/dcastil/tailwind-merge/compare/v0.2.0...v0.3.0) ## v0.2.0 ### New Features - Add support for important modifier by [@dcastil](https://github.com/dcastil) in [`17a9e9d`](https://github.com/dcastil/tailwind-merge/commit/17a9e9d9d805ba585372e01a9eefae1dba89368b) - Add support for per-side border colors by [@dcastil](https://github.com/dcastil) in [`6cd9ee2`](https://github.com/dcastil/tailwind-merge/commit/6cd9ee255e1a6fb42e5262b7835f876e2ce8e3ae) - Add support for content utiltites by [@dcastil](https://github.com/dcastil) in [`fd097c6`](https://github.com/dcastil/tailwind-merge/commit/fd097c611b5fa02ff6142b66f5ad96d596feed42) - Add support for caret color by [@dcastil](https://github.com/dcastil) in [`fd097c6`](https://github.com/dcastil/tailwind-merge/commit/fd097c611b5fa02ff6142b66f5ad96d596feed42) - Add support for JIT-only prefixes by [@dcastil](https://github.com/dcastil) in [`fd097c6`](https://github.com/dcastil/tailwind-merge/commit/fd097c611b5fa02ff6142b66f5ad96d596feed42) - Mark package as side effect-free by [@dcastil](https://github.com/dcastil) in [`6d00af3`](https://github.com/dcastil/tailwind-merge/commit/6d00af33049c3c7171bce3f1affd561986cc6bfe) ### Bug Fixes - Fix classes like `bottom-auto` not being detected as Tailwind classesby [@dcastil](https://github.com/dcastil) in [`ec65b84`](https://github.com/dcastil/tailwind-merge/commit/ec65b84f0aab57d1305019e4a143772d675798a2) **Full Changelog**: [`v0.1.2...v0.2.0`](https://github.com/dcastil/tailwind-merge/compare/v0.1.2...v0.2.0) ## v0.1.2 ### Bug Fixes - Fix errors when importing tailwind-merge as third party dependency. by [@dcastil](https://github.com/dcastil) in [`3335956`](https://github.com/dcastil/tailwind-merge/commit/3335956da15fdcc484904976864816413fad68f6) **Full Changelog**: [`v0.1.1...v0.1.2`](https://github.com/dcastil/tailwind-merge/compare/v0.1.1...v0.1.2) ## v0.1.1 No changes here. Just testing automated npm publish. **Full Changelog**: [`v0.1.0...v0.1.1`](https://github.com/dcastil/tailwind-merge/compare/v0.1.0...v0.1.1) ## v0.1.0 First published version of tailwind-merge. 🎉 **Full Changelog**: [`v0.1.0`](https://github.com/dcastil/tailwind-merge/commits/v0.1.0) node-tailwind-merge-3.3.1/docs/changelog/v0-to-v1-migration.md000066400000000000000000000052651502210756000240400ustar00rootroot00000000000000# Guide to migrate from tailwind-merge v0 to v1 This document is only about breaking changes between v0 and v1. For a full list of changes, see the [v1.0.0 release](./v1-changelog.md#v100). ## Overview tailwind-merge v1 drops support for Tailwind CSS v2 and in turn adds support for Tailwind CSS v3. There are no breaking changes in the tailwind-merge types and some breaking changes for a small number of users in the return values, so you should get through smoothly. ## Breaking changes ### `twMerge` and `extendTailwindMerge` - Outline utilities from Tailwind v2 don't get merged anymore since they were replaced by outline width, outline style, outline offset and outline color in Tailwind v3 ([`55ab167`](https://github.com/dcastil/tailwind-merge/commit/55ab167b7167519873c5dd4d258dc62212d1659a), [#63](https://github.com/dcastil/tailwind-merge/pull/63)) - The classes `overflow-ellipsis` and `overflow-clip` will not get merged with class `truncate` anymore, but the new Tailwind v3 classes `text-ellipsis` and `text-clip` will. ([`65b03e4`](https://github.com/dcastil/tailwind-merge/commit/65b03e48914ac5d7d52eea9ec178b204d30609c9), [#63](https://github.com/dcastil/tailwind-merge/pull/63)) - The classes `decoration-slice` and `decoration-clone` won't get merged anymore and `box-decoration-slide` nad `box-decoration-clone` will ([`bfe2cc9`](https://github.com/dcastil/tailwind-merge/commit/bfe2cc9bb221107fa0bf363cc325ddbb04677f43), [#63](https://github.com/dcastil/tailwind-merge/pull/63)) ### `getDefaultConfig` - Removed class group `outline` since it was removed in Tailwind v3 ([`55ab167`](https://github.com/dcastil/tailwind-merge/commit/55ab167b7167519873c5dd4d258dc62212d1659a), [#63](https://github.com/dcastil/tailwind-merge/pull/63)) - Renamed class group `vertival-alignment` (yes, the typo was in the code) to `vertical-align` ([`1269ce6`](https://github.com/dcastil/tailwind-merge/commit/1269ce68ae39807ceadbecc98c0929fdfdb446d0), [#63](https://github.com/dcastil/tailwind-merge/pull/63)) - Renamed class groups `flex-basis`, `flex-grow` and `flex-shrink` to `basis`, `grow` and `shrink` to stay consistent with Tailwind v3 ([`e6d8912`](https://github.com/dcastil/tailwind-merge/commit/e6d8912e47bf9a89346b9b0cc822fb2bff2af172), [#63](https://github.com/dcastil/tailwind-merge/pull/63)) ### `validators` - `isCustomLength` and `isCustomValue` were renamed to `isArbitraryLength` and `isArbitraryValue` to be consistent with naming in Tailwind v3 documentation ([`adc3c02`](https://github.com/dcastil/tailwind-merge/commit/adc3c02c7f035069beec1c62777ec008172587ab), [#63](https://github.com/dcastil/tailwind-merge/pull/63)) ## Steps to upgrade - Upgrade to Tailwind CSS v3 - Upgrade to tailwind-merge v1 node-tailwind-merge-3.3.1/docs/changelog/v1-changelog.md000066400000000000000000000606461502210756000230370ustar00rootroot00000000000000# Changelog for v1 releases ## v1.14.0 ### New Features - Improve support for arbitrary values by [@dcastil](https://github.com/dcastil) in [#263](https://github.com/dcastil/tailwind-merge/pull/263) - Previously, tailwind-merge checked the content of the arbitrary value portion of a class in most cases to understand whether the type of the arbitrary value is correct (e.g. it checked for number followed by length unit for the length type). That lead to the issue that a class like `mt-[calc(theme(fontSize.4xl)/1.125)]` would not be recognized correctly because no length unit is present in the arbitrary value. - I changed the check of the arbitrary value to also pass when a `calc()`, `min()`, `max()` and `clamp()` function is used in the arbitrary value. - In ambiguous cases, you can use data type labels to mark the type of a class. [Read more](https://github.com/dcastil/tailwind-merge/blob/v1.14.0/docs/features.md#supports-arbitrary-values) - Moreover, I removed the check where the type of the arbitrary value is unambiguous. In the class `mt-[…]` the arbitrary value can only be a length, so I don't check for it. A consequence of this is that if you use non-Tailwind classes like `mt-[this-is-totally-not-tailwind]`, tailwind-merge will recognize it as a Tailwind class from now on. **Please don't use classes that look like Tailwind classes with arbitrary value but aren't Tailwind classes with tailwind-merge (in default config) to prevent incorrect merging behavior**. ### Bug Fixes - Fix `col-span-full` class missing in default config by [@dcastil](https://github.com/dcastil) in [#267](https://github.com/dcastil/tailwind-merge/pull/267) - Fix arbitrary value with no present length unit not being recognized by [@dcastil](https://github.com/dcastil) in [#263](https://github.com/dcastil/tailwind-merge/pull/263) ### Documentation - Add missing info about where to call config functions to docs by [@dcastil](https://github.com/dcastil) in [#264](https://github.com/dcastil/tailwind-merge/pull/264) **Full Changelog**: [`v1.13.2...v1.14.0`](https://github.com/dcastil/tailwind-merge/compare/v1.13.2...v1.14.0) ## v1.13.2 ### Bug Fixes - Fix TypeScript issue when using `moduleResolution: node16` by [@LiamMartens](https://github.com/LiamMartens) in [#245](https://github.com/dcastil/tailwind-merge/pull/245) ### Documentation - Fix grammar and typos in docs by [@jmmarco](https://github.com/jmmarco) in [#249](https://github.com/dcastil/tailwind-merge/pull/249) - Add tailwind-merge-php to similar packages in docs by [@JamesHemery](https://github.com/JamesHemery) in [#246](https://github.com/dcastil/tailwind-merge/pull/246) **Full Changelog**: [`v1.13.1...v1.13.2`](https://github.com/dcastil/tailwind-merge/compare/v1.13.1...v1.13.2) Thanks to [@bluetch](https://github.com/bluetch) for sponsoring tailwind-merge! ❤️ ## v1.13.1 ### Bug Fixes - Fix `basis-auto` and `basis-full` not being merged correctly by [@lukasz-kapica](https://github.com/lukasz-kapica) in [#242](https://github.com/dcastil/tailwind-merge/pull/242) **Full Changelog**: [`v1.13.0...v1.13.1`](https://github.com/dcastil/tailwind-merge/compare/v1.13.0...v1.13.1) ## v1.13.0 This release focuses on improvements to the docs. ### Bug Fixes - Fix arbitrary length `0` without unit not being recognized by [@dcastil](https://github.com/dcastil) in [#237](https://github.com/dcastil/tailwind-merge/pull/237) - Fix typo in comment in default-config.ts by [@CrutchTheClutch](https://github.com/CrutchTheClutch) in [#227](https://github.com/dcastil/tailwind-merge/pull/227) ### Documentation - Add intro video from Simon Vrachliotis to docs by [@dcastil](https://github.com/dcastil) in [#239](https://github.com/dcastil/tailwind-merge/pull/239) - [@simonswiss](https://github.com/simonswiss) made an intro video to tailwind-merge which I added to the docs. Check it out [here](https://github.com/dcastil/tailwind-merge/blob/v1.13.0/docs/what-is-it-for.md#video-introduction)! - Add docs about when to use tailwind-merge by [@dcastil](https://github.com/dcastil) in [#230](https://github.com/dcastil/tailwind-merge/pull/230) - I added a new page to the docs about [when and how to use tailwind-merge](https://github.com/dcastil/tailwind-merge/blob/v1.13.0/docs/when-and-how-to-use-it.md) which should help you to decide whether you should use it and what alternative approaches exist. - Make it clearer in docs that tailwind-merge supports composition of class strings by [@dcastil](https://github.com/dcastil) in [#229](https://github.com/dcastil/tailwind-merge/pull/229) ### Other - Add npm package provenance by [@dcastil](https://github.com/dcastil) in [#219](https://github.com/dcastil/tailwind-merge/pull/219) - GitHub introduced a new security feature to verify which source commit and build file were used for a specific npm package version. tailwind-merge now publishes provenance signatures alongside all releases on npm. [Read more on the GitHub blog.](https://github.blog/2023-04-19-introducing-npm-package-provenance/) **Full Changelog**: [`v1.12.0...v1.13.0`](https://github.com/dcastil/tailwind-merge/compare/v1.12.0...v1.13.0) ## v1.12.0 With this release tailwind-merge supports all features introduced in [Tailwind CSS v3.3](https://tailwindcss.com/blog/tailwindcss-v3-3). ### New Features - Add support for postfix modifier by [@dcastil](https://github.com/dcastil) in [#214](https://github.com/dcastil/tailwind-merge/pull/214) - This adds support for `line-height` modifiers in `font-size` utilities like `text-lg/7` and more potential postfix modifiers in the future ([learn more](https://github.com/dcastil/tailwind-merge/blob/v1.12.0/docs/features.md#supports-postfix-modifiers)). - All classes are checked for postfix modifiers since there will be more in the future and they'll be configurable with plugins. - tailwind-merge can't know from the class syntax alone whether something is a modifier or not. E.g. there is `w-1/2` which doesn't contain a modifier. So tailwind-merge always checks whether class without potential modifier exists and if it doesn't it checks for full class. This behavior might get reversed in the next major version as a breaking change ([learn more](https://github.com/dcastil/tailwind-merge/issues/215)). - Added `conflictingClassGroupModifiers` object to tailwind-merge config ([learn more](https://github.com/dcastil/tailwind-merge/blob/v1.12.0/docs/configuration.md#postfix-modifiers-conflicting-with-class-groups)). **Full Changelog**: [`v1.11.0...v1.12.0`](https://github.com/dcastil/tailwind-merge/compare/v1.11.0...v1.12.0) ## v1.11.0 ### New Features - Add support for Tailwind CSS v3.3 except line-height shorthand by [@dcastil](https://github.com/dcastil) in [#210](https://github.com/dcastil/tailwind-merge/pull/210) - The line-height shorthand in font-size utilities (`text-lg/7`) [introduced in Tailwind CSS v3.3](https://tailwindcss.com/blog/tailwindcss-v3-3#new-line-height-shorthand-for-font-size-utilities) is not yet supported in tailwind-merge because that feature is a bit more involved. I'll add support for it in a future release. More info in [#211](https://github.com/dcastil/tailwind-merge/issues/211). - Added new [validator](https://github.com/dcastil/tailwind-merge/blob/v1.11.0/docs/api-reference.md#validators) `isPercent` which is needed internally for the default scale of color stop positions. - New [theme](https://github.com/dcastil/tailwind-merge/blob/v1.11.0/docs/configuration.md#theme) key `gradientColorStopPositions` supported in tailwind-merge. - New logical properties like `ps-0` (`padding-inline-start: 0px;`) are de-duplicated away when using the matching property for all sides afterwards like in this case `p-0`, but not when using single axis sides like `px-0` because `padding-inline-start` can also be the top or bottom padding depending on writing mode. - Basically `twMerge('ps-0 p-0') === 'p-0' && twMerge('ps-0 px-0') === 'ps-0 px-0'`. - If you want to use logical properties and know which writing modes your app is limited to, add the right conflicts yourself to your tailwind-merge config. **Full Changelog**: [`v1.10.0...v1.11.0`](https://github.com/dcastil/tailwind-merge/compare/v1.10.0...v1.11.0) Thanks to [@brandonmcconnell](https://github.com/brandonmcconnell) for sponsoring tailwind-merge! ❤️ ## v1.10.0 ### New Features - Add support for container query length units in arbitrary values by [@LesnoyPudge](https://github.com/LesnoyPudge) in [#204](https://github.com/dcastil/tailwind-merge/pull/204) **Full Changelog**: [`v1.9.1...v1.10.0`](https://github.com/dcastil/tailwind-merge/compare/v1.9.1...v1.10.0) ## v1.9.1 ### Bug Fixes - Fix arbitrary floats not supported in opacity, scale, etc. by [@dcastil](https://github.com/dcastil) in [#196](https://github.com/dcastil/tailwind-merge/pull/196) - Up until now classes like `opacity-50 opacity-[.025]` weren't merged correctly. You might not have noticed since classes with arbitrary values are defined after the default ones in the output stylesheet, but merging it the other way around (`opacity-[.025] opacity-50`) would have led to a styling bug. - This fix led to a new [validator](https://github.com/dcastil/tailwind-merge/blob/v1.9.1/docs/api-reference.md#validators) `isNumber`. - Fix arbitrary border color value being merged incorrectly by [@dcastil](https://github.com/dcastil) in [#195](https://github.com/dcastil/tailwind-merge/pull/195) **Full Changelog**: [`v1.9.0...v1.9.1`](https://github.com/dcastil/tailwind-merge/compare/v1.9.0...v1.9.1) ## v1.9.0 ### New Features - Support decimals in T-shirt sizes by [@farreldarian](https://github.com/farreldarian) in [#189](https://github.com/dcastil/tailwind-merge/pull/189) ### Documentation - Fixes typo in recipes docs by [@nicklemmon](https://github.com/nicklemmon) in [#181](https://github.com/dcastil/tailwind-merge/pull/181) ### Other - Added test case by [@chuanyu0201](https://github.com/chuanyu0201) in [#186](https://github.com/dcastil/tailwind-merge/pull/186) **Full Changelog**: [`v1.8.1...v1.9.0`](https://github.com/dcastil/tailwind-merge/compare/v1.8.1...v1.9.0) ## v1.8.1 ### Bug Fixes - Fix incorrect class group conflicts in grid-related classes by [@dcastil](https://github.com/dcastil) in [#177](https://github.com/dcastil/tailwind-merge/pull/177) **Full Changelog**: [`v1.8.0...v1.8.1`](https://github.com/dcastil/tailwind-merge/compare/v1.8.0...v1.8.1) Thanks to [@aniravi24](https://github.com/aniravi24) for sponsoring tailwind-merge! ❤️ ## v1.8.0 ### New Features - Add support for custom separator by [@dcastil](https://github.com/dcastil) in [#168](https://github.com/dcastil/tailwind-merge/pull/168) - Add support for dynamic viewport units in arbitrary lengths by [@dcastil](https://github.com/dcastil) in [#166](https://github.com/dcastil/tailwind-merge/pull/166) - Rename `join` to `twJoin` by [@dcastil](https://github.com/dcastil) in [#161](https://github.com/dcastil/tailwind-merge/pull/161) - I deprecated the [`join`](https://github.com/dcastil/tailwind-merge/blob/v1.7.0/docs/api-reference.md#join) function and renamed it to [`twJoin`](https://github.com/dcastil/tailwind-merge/blob/v1.8.0/docs/api-reference.md#twjoin) to make replacing it via search and replace easier since `join` is a common function name. You don't need to change anything right now, but if you have some spare time, rename join → twJoin in your code since the `join` function will be removed in the next major release. **Full Changelog**: [`v1.7.0...v1.8.0`](https://github.com/dcastil/tailwind-merge/compare/v1.7.0...v1.8.0) Thanks to [@gjtorikian](https://github.com/gjtorikian) for sponsoring tailwind-merge! ❤️ ## v1.7.0 ### New Features - Add support for Tailwind CSS v3.2 by [@dcastil](https://github.com/dcastil) and [@brandonmcconnell](https://github.com/brandonmcconnell) in [#159](https://github.com/dcastil/tailwind-merge/pull/159) **Full Changelog**: [`v1.6.2...v1.7.0`](https://github.com/dcastil/tailwind-merge/compare/v1.6.2...v1.7.0) ## v1.6.2 ### Bug Fixes - Fix arbitrary numbers not working in stroke-width by [@dcastil](https://github.com/dcastil) in [#153](https://github.com/dcastil/tailwind-merge/pull/153) - Now tailwind-merge handles classes like `stroke-[3]` correctly. - I deprecated the [validator](https://github.com/dcastil/tailwind-merge/blob/v1.6.2/docs/api-reference.md#validators) `isArbitraryWeight` and renamed it to `isArbitraryNumber` to reflect its broader use case. You don't need to change anything right now, but if you have some spare time, rename `isArbitraryWeight` → `isArbitraryNumber` in your code since `isArbitraryWeight` will be removed in the next major release. ### Other - Add package version number to dev releases by [@dcastil](https://github.com/dcastil) in [#154](https://github.com/dcastil/tailwind-merge/pull/154) - Now dev releases don't start with `0.0.0-dev` anymore and instead have the version number of the last release, like `1.6.1-dev`. That makes it easier for tools like [Renovate](https://renovatebot.com/) to understand which package version you're using in case you use dev releases. **Full Changelog**: [`v1.6.1...v1.6.2`](https://github.com/dcastil/tailwind-merge/compare/v1.6.1...v1.6.2) ## v1.6.1 ### Bug Fixes - Fix h-min not working by [@dcastil](https://github.com/dcastil) in [#146](https://github.com/dcastil/tailwind-merge/pull/146) **Full Changelog**: [`v1.6.0...v1.6.1`](https://github.com/dcastil/tailwind-merge/compare/v1.6.0...v1.6.1) ## v1.6.0 ### New Features - Add support for arrays as argument by [@dcastil](https://github.com/dcastil) in [#127](https://github.com/dcastil/tailwind-merge/pull/127) - You can now use arbitrarily nested arrays as arguments to `twMerge`. That's especially handy for nested conditions. ```js twMerge('…', someBool && ['…', anotherBool && '…']) ``` - The joining of arguments is done with a new `join` function which [is present in the tailwind-merge exports](https://github.com/dcastil/tailwind-merge/blob/v1.6.0/docs/api-reference.md#join) as well. It has the same functionality as [clsx](https://github.com/lukeed/clsx) but without support for objects as arguments which makes it a little faster. - Why no objects as arguments? You can read about my reasoning in [#137 (comment)](https://github.com/dcastil/tailwind-merge/discussions/137#discussioncomment-3481605). ### Bug Fixes - Replace matchAll with exec by [@dcastil](https://github.com/dcastil) in [#133](https://github.com/dcastil/tailwind-merge/pull/133) - This makes tailwind-merge work in older browsers which don't support `String.prototype.matchAll()` ### Other - Add recipes section to docs by [@dcastil](https://github.com/dcastil) in [#134](https://github.com/dcastil/tailwind-merge/pull/134) - Split docs into multiple files by [@dcastil](https://github.com/dcastil) in [#131](https://github.com/dcastil/tailwind-merge/pull/131) - Add comments to released PRs and their related issues by [@dcastil](https://github.com/dcastil) in [#130](https://github.com/dcastil/tailwind-merge/pull/130) - Add tests to check actual CJS and ESM package exports by [@dcastil](https://github.com/dcastil) in [#129](https://github.com/dcastil/tailwind-merge/pull/129) - Remove ts files from npm package by [@dcastil](https://github.com/dcastil) in [#128](https://github.com/dcastil/tailwind-merge/pull/128) **Full Changelog**: [`v1.5.1...v1.6.0`](https://github.com/dcastil/tailwind-merge/compare/v1.5.1...v1.6.0) Thanks to [@charkour](https://github.com/charkour) for sponsoring tailwind-merge! ❤️ ## v1.5.1 ### Bug Fixes - Fix arbitrary z-index value not being recognized by [@dcastil](https://github.com/dcastil) in [#116](https://github.com/dcastil/tailwind-merge/pull/116) **Full Changelog**: [`v1.5.0...v1.5.1`](https://github.com/dcastil/tailwind-merge/compare/v1.5.0...v1.5.1) Thanks to [@charkour](https://github.com/charkour) for sponsoring tailwind-merge! ❤️ ## v1.5.0 ### New Features - Added missing ESM `types` subpath export condition by [@scott-lc](https://github.com/scott-lc) in [#113](https://github.com/dcastil/tailwind-merge/pull/113) - This makes tailwind-merge work in TypeScript projects using [the new `nodenext` module type introduced in TypeScript 4.7](https://devblogs.microsoft.com/typescript/announcing-typescript-4-7/#ecmascript-module-support-in-node-js). **Full Changelog**: [`v1.4.0...v1.5.0`](https://github.com/dcastil/tailwind-merge/compare/v1.4.0...v1.5.0) Thanks to [@charkour](https://github.com/charkour) for sponsoring tailwind-merge! ❤️ ## v1.4.0 ### New Features - Optimize runtime performance by using Map by [@dcastil](https://github.com/dcastil) in [#105](https://github.com/dcastil/tailwind-merge/pull/105) ### Bug Fixes - Fix overriding w-full with w-fit not working by [@dcastil](https://github.com/dcastil) in [#112](https://github.com/dcastil/tailwind-merge/pull/112) ### Other - Publish dev releases of every commit on main branch by [@dcastil](https://github.com/dcastil) in [#104](https://github.com/dcastil/tailwind-merge/pull/104) **Full Changelog**: [`v1.3.0...v1.4.0`](https://github.com/dcastil/tailwind-merge/compare/v1.3.0...v1.4.0) Thanks to [@charkour](https://github.com/charkour) for sponsoring tailwind-merge! ❤️ ## v1.3.0 ### New Features - Add support for Tailwind v3.1 by [@dcastil](https://github.com/dcastil) in [#103](https://github.com/dcastil/tailwind-merge/pull/103) ### Bug Fixes - Fix readme typos by [@oshi97](https://github.com/oshi97) in [#102](https://github.com/dcastil/tailwind-merge/pull/102) - Fix typos in comments by [@szamanr](https://github.com/szamanr) in [#89](https://github.com/dcastil/tailwind-merge/pull/89) ### Other - Add community health files by [@dcastil](https://github.com/dcastil) in [#93](https://github.com/dcastil/tailwind-merge/pull/93) **Full Changelog**: [`v1.2.1...v1.3.0`](https://github.com/dcastil/tailwind-merge/compare/v1.2.1...v1.3.0) Thanks to [@charkour](https://github.com/charkour) for sponsoring tailwind-merge! ❤️ ## v1.2.1 ### Bug Fixes - Fix isArbitraryWeight incorrectly using `weight:` instead of `number:` for disambiguation for arbitrary values by [@liuqiang1357](https://github.com/liuqiang1357) in [#85](https://github.com/dcastil/tailwind-merge/pull/85) - Fix typos in README.md by [@Gri-ffin](https://github.com/Gri-ffin) in [#82](https://github.com/dcastil/tailwind-merge/pull/82) **Full Changelog**: [`v1.2.0...v1.2.1`](https://github.com/dcastil/tailwind-merge/compare/v1.2.0...v1.2.1) Thanks to [@charkour](https://github.com/charkour) for sponsoring tailwind-merge! ❤️ ## v1.2.0 ### New Features - Add prefix support by [@dcastil](https://github.com/dcastil) in [#78](https://github.com/dcastil/tailwind-merge/pull/78) **Full Changelog**: [`v1.1.1...v1.2.0`](https://github.com/dcastil/tailwind-merge/compare/v1.1.1...v1.2.0) Thanks to [@charkour](https://github.com/charkour) for sponsoring tailwind-merge! ❤️ ## v1.1.1 ### Bug Fixes - Fix TypeScript types not being linked correctly in package.json by [@navin-moorthy](https://github.com/navin-moorthy) and [@dcastil](https://github.com/dcastil) in [#75](https://github.com/dcastil/tailwind-merge/pull/75) **Full Changelog**: [`v1.1.0...v1.1.1`](https://github.com/dcastil/tailwind-merge/compare/v1.1.0...v1.1.1) ## v1.1.0 ### New Features - Fix missing arbitrary value support in some class groups by [@dcastil](https://github.com/dcastil) in [#73](https://github.com/dcastil/tailwind-merge/pull/73) - Adds arbitrary value support for class groups `grayscale`, `invert`, `sepia`, `grow`, `shrink`, `object-position`, `shadow`, `drop-shadow`, `rotate`, `skew` and `transform-origin` - Fixes `break-inside` classes being merged incorrectly - Adds missing classes `overline`, `underline-offset`, `content-none` - Fixes typo in class group name `bg-repeeat` → `bg-repeat` - Adds `isArbitraryShadow` validator - Improve tree-shaking by [@dcastil](https://github.com/dcastil) in [#65](https://github.com/dcastil/tailwind-merge/pull/65) - I changed the build output significantly here and removed `"type": "module"` from the package.json. I did test the new npm package output in Node and in the browser, but it's hard to account for every possible build system tailwind-merge is used in. If some issues come up with bundling tailwind-merge, please open an issue! ### Bug Fixes - Fix stroke-color utilities being merged with stroke-width utilities by [@dcastil](https://github.com/dcastil) in [#72](https://github.com/dcastil/tailwind-merge/pull/72) - Fix mix-blend utilities getting merged incorrectly by [@dcastil](https://github.com/dcastil) in [#71](https://github.com/dcastil/tailwind-merge/pull/71) **Full Changelog**: [`v1.0.0...v1.1.0`](https://github.com/dcastil/tailwind-merge/compare/v1.0.0...v1.1.0) ## v1.0.0 v1! 🎉 ### Overview After being 5 months on v0 I think it's time to release a stable version of tailwind-merge. Tailwind v3 was [released](https://github.com/tailwindlabs/tailwindcss/releases/tag/v3.0.0) yesterday and it's no coincidence that I'm releasing tailwind-merge v1 today. I added full support for Tailwind v3 so you can update both at once. There are no breaking changes in the tailwind-merge types and some breaking changes for a small number of users in the return values, so you should get through smoothly. By the way, you can now [sponsor](https://github.com/sponsors/dcastil) this project. 😊 ### Breaking Changes - `twMerge`, `extendTailwindMerge` - Outline utilities from Tailwind v2 don't get merged anymore since they were replaced by outline width, outline style, outline offset and outline color in Tailwind v3 ([`55ab167`](https://github.com/dcastil/tailwind-merge/commit/55ab167b7167519873c5dd4d258dc62212d1659a), [#63](https://github.com/dcastil/tailwind-merge/pull/63)) - The classes `overflow-ellipsis` and `overflow-clip` will not get merged with class `truncate` anymore, but the new Tailwind v3 classes `text-ellipsis` and `text-clip` will. ([`65b03e4`](https://github.com/dcastil/tailwind-merge/commit/65b03e48914ac5d7d52eea9ec178b204d30609c9), [#63](https://github.com/dcastil/tailwind-merge/pull/63)) - The classes `decoration-slice` and `decoration-clone` won't get merged anymore and `box-decoration-slide` nad `box-decoration-clone` will ([`bfe2cc9`](https://github.com/dcastil/tailwind-merge/commit/bfe2cc9bb221107fa0bf363cc325ddbb04677f43), [#63](https://github.com/dcastil/tailwind-merge/pull/63)) - `getDefaultConfig` - Removed class group `outline` since it was removed in Tailwind v3 ([`55ab167`](https://github.com/dcastil/tailwind-merge/commit/55ab167b7167519873c5dd4d258dc62212d1659a), [#63](https://github.com/dcastil/tailwind-merge/pull/63)) - Renamed class group `vertival-alignment` (yes, the typo was in the code) to `vertical-align` ([`1269ce6`](https://github.com/dcastil/tailwind-merge/commit/1269ce68ae39807ceadbecc98c0929fdfdb446d0), [#63](https://github.com/dcastil/tailwind-merge/pull/63)) - Renamed class groups `flex-basis`, `flex-grow` and `flex-shrink` to `basis`, `grow` and `shrink` to stay consistent with Tailwind v3 ([`e6d8912`](https://github.com/dcastil/tailwind-merge/commit/e6d8912e47bf9a89346b9b0cc822fb2bff2af172), [#63](https://github.com/dcastil/tailwind-merge/pull/63)) - `validators` - `isCustomLength` and `isCustomValue` were renamed to `isArbitraryLength` and `isArbitraryValue` to be consistent with naming in Tailwind v3 documentation ([`adc3c02`](https://github.com/dcastil/tailwind-merge/commit/adc3c02c7f035069beec1c62777ec008172587ab), [#63](https://github.com/dcastil/tailwind-merge/pull/63)) ### New Features - Add support for Tailwind v3 by [@dcastil](https://github.com/dcastil) in [#63](https://github.com/dcastil/tailwind-merge/pull/63) - Support for all the new utility classes and variants in Tailwind v3.0.0 - Support for arbitrary properties like `[--my-var:20px]` - Support for important modifiers in arbitrary properties like `![--my-very-important-var: 21px]` - Support for new labels for classes with arbitrary value: `size`, `position`, `url`, `weight` and `family` - New validators `isTshirtSize`, `isArbitrarySize`, `isArbitraryPosition`, `isArbitraryUrl` and `isArbitraryWeight`, check them out in the [documentation](https://github.com/dcastil/tailwind-merge/tree/v1.0.0#validators)! ([`fec2b18`](https://github.com/dcastil/tailwind-merge/commit/fec2b18870f6806e602009632b52b9fe89ebfb83), [`f8acd7c`](https://github.com/dcastil/tailwind-merge/commit/f8acd7ca5be6cc40ad4c1cbdee7522bbc44c7870), [#63](https://github.com/dcastil/tailwind-merge/pull/63)) **Full Changelog**: [`v0.9.0...v1.0.0`](https://github.com/dcastil/tailwind-merge/compare/v0.9.0...v1.0.0) node-tailwind-merge-3.3.1/docs/changelog/v1-to-v2-migration.md000066400000000000000000000501311502210756000240320ustar00rootroot00000000000000# Guide to migrate from tailwind-merge v1 to v2 This document is only about breaking changes between v1 and v2. For a full list of changes, see the [v2.0.0 release](./v2-changelog.md#v200). ## Overview The tailwind-merge v2 release focuses on making it easier to configure the library for new users. Over the past one and a half years since the v1 release, the biggest source of issues was the initial configuration of the library. That will unfortunately not change since most of the inconvenience comes from keeping the bundle size to a minimum. However, a few ideas with breaking changes accumulated over time to make the configuration a little bit more straight forward without increasing the bundle size. Those ideas were implemented in this release. The highlights: - No changes to `twMerge` and supported Tailwind CSS versions. - You can now override class groups with the object notation in `extendTailwindMerge`. - TypeScript types of configuration object passed to `extendTailwindMerge` are stricter and prevent you from using unknown theme groups and class groups unless specified otherwise. - The library now exports a bundle using modern JS syntax to further reduce its size. There is also an additional bundle with ES5-only syntax for compatibility with older browsers. If you have feedback of any kind regarding this release, feel free to [open an issue or discussion](https://github.com/dcastil/tailwind-merge/issues/new/choose). I'm always happy to hear from you! ## Breaking changes By exports: - All - [Modern JS syntax](#modern-js-syntax) - [Module resolution](#module-resolution) - `extendTailwindMerge` - [Object shape changed](#extendtailwindmerge-object-shape-changed) - [Stricter TypeScript types](#extendtailwindmerge-stricter-typescript-types) - `validators` - [`isLength`: Does not check for arbitrary values anymore](#validatorsislength-does-not-check-for-arbitrary-values-anymore) - [`isInteger`: Does not check for arbitrary values anymore](#validatorsisinteger-does-not-check-for-arbitrary-values-anymore) - [`isArbitraryUrl`: Renamed](#validatorsisarbitraryurl-renamed) - [`isArbitraryWeight`: Removed](#validatorsisarbitraryweight-removed) - `createTailwindMerge` - [Mandatory elements added](#createtailwindmerge-mandatory-elements-added) - `fromTheme` - [Stricter TypeScript types](#fromtheme-stricter-typescript-types) - `mergeConfigs` - [Object shape changed](#mergeconfigs-object-shape-changed) - [Stricter TypeScript types](#mergeconfigs-stricter-typescript-types) - `join` - [Removed](#join-removed) ### Modern JS syntax Related: [#286](https://github.com/dcastil/tailwind-merge/pull/286), [#287](https://github.com/dcastil/tailwind-merge/pull/287) The build of tailwind-merge was updated to output more modern JS syntax. This removes a lot of code to substitute modern JS features like object spread or arrow functions, but also means that the new bundle doesn't work in older browsers anymore in case you don't transpile your dependencies. The exact [browserslist](https://github.com/browserslist/browserslist) query used to define how tailwind-merge gets transpiled from now on is ``` > 0.5%, last 2 versions, Firefox ESR, not dead, maintained node versions ``` which corresponds to the browserslist query `defaults` with the addition of `maintained node versions`. In case you need to support older browsers and don't transpile your dependencies, you can use the new `tailwind-merge/es5` bundle which includes all of the tailwind-merge exports and is transpiled to ES5 syntax using the browserslist query `supports es5`. #### Minimal upgrade Replace all imports of `tailwind-merge` with `tailwind-merge/es5`. ```diff - import { … } from 'tailwind-merge' + import { … } from 'tailwind-merge/es5' ``` #### Full upgrade Check whether the browserslist query `> 0.5%, last 2 versions, Firefox ESR, not dead, maintained node versions` includes all browsers you need to support. If not, replace all imports of `tailwind-merge` with `tailwind-merge/es5` as shown in the minimal upgrade above. ### Module resolution Related: [#289](https://github.com/dcastil/tailwind-merge/issues/289) The `module` field was removed from the `package.json` file of tailwind-merge. This field was briefly introduced by bundlers to import the ES module version of a library. But it was ultimately succeeded by the `exports` field which became a standard in Node.js and is also used by tailwind-merge. All major bundlers support the `exports` field, so removing the `module` field should hopefully not affect anyone. However, if you encounter any problems with this change, please open an issue. #### Upgrade If you can import tailwind-merge and your module resolution system doesn't complain, there is nothing you need to do. If you encounter issues, make sure that you resolve the tailwind-merge library via the `exports` or `main` field of its `package.json` file. ### `extendTailwindMerge`: Object shape changed Related: [#294](https://github.com/dcastil/tailwind-merge/pull/294) In the object passed to `extendTailwindMerge` it is now possible to not just extend groups, but also to override them. To distinguish between extending and overriding, there are two new top level keys in the object: `extend` and `override`. Both of these objects can define a `theme`, `classGroups`, `conflictingClassGroups` and `conflictingClassGroupModifiers` object whose groups will either override or extend the corresponding groups in the default config. You might remember the `extend` key in your `tailwind.config.js`, now it works similarly in tailwind-merge as well. However, you need to use the `override` object instead of defining groups at the top level to override. This was done to make overriding more explicit and to prevent accidentally overriding groups when migrating to tailwind-merge v2. #### Minimal upgrade To get the same behavior as before, move `theme`, `classGroups`, `conflictingClassGroups` and `conflictingClassGroupModifiers` into an `extend` object. ```diff import { extendTailwindMerge } from 'tailwind-merge' const twMerge = extendTailwindMerge({ cacheSize: 1000, - theme: { … }, - classGroups: { … }, - conflictingClassGroups: { … }, - conflictingClassGroupModifiers: { … }, + extend: { + theme: { … }, + classGroups: { … }, + conflictingClassGroups: { … }, + conflictingClassGroupModifiers: { … }, + } }) ``` #### Full upgrade If you override groups in your `tailwind.config.js`, you can now do the same in tailwind-merge. Move the groups you want to override into the `override` object and the rest into the `extend` object. ```diff import { extendTailwindMerge } from 'tailwind-merge' const twMerge = extendTailwindMerge({ - classGroups: { - // Here we actually meant to override this group - shadow: [{ shadow: ['none', '100', '200', '300'] }], - // Here we really meant to extend this group - animate: ['animate-shimmer'], - }, + override: { + classGroups: { + // Now we can override this group + shadow: [{ shadow: ['none', '100', '200', '300'] }], + }, + }, + extend: { + classGroups: { + // And we can still extend this group + animate: ['animate-shimmer'], + }, + }, }) ``` ### `extendTailwindMerge`: Stricter TypeScript types Related: [#279](https://github.com/dcastil/tailwind-merge/pull/279) One of the more annoying things about configuring tailwind-merge is to find the right IDs of groups to edit. Some users also fall into the trap that [not all theme groups from Tailwind CSS are supported in tailwind-merge](../configuration.md#theme). To add some guidance to the process, all the group objects passed to `extendTailwindMerge` don't accept any string keys in TypeScript anymore but only a set of specific keys which are defined in the default config. ```ts import { extendTailwindMerge } from 'tailwind-merge' const twMerge = extendTailwindMerge({ extend: { classGroups: { // ↓ No problem shadow: [{ shadow: ['100', '200', '300'] }], // ↓ Error: Object literal may only specify known properties, and 'animation' does not // exist in type 'Partial>>'. animation: ['animate-shimmer'], }, }, }) ``` This means you can't accidentally extend or override a group with a typo in the ID anymore without noticing and you get code completion when you start typing the ID of a group in your editor. But this also means that you can't add any new groups to the configuration object anymore. To allow custom class group IDs, you can use generic arguments to `extendTailwindMerge` to pass additional allowed IDs for class groups and theme groups separately. ```ts import { extendTailwindMerge } from 'tailwind-merge' const twMerge = extendTailwindMerge< // ↓ Add additional class group IDs as the first generic argument 'class-a' | 'class-b', // ↓ Optionally, you can add additional theme group IDs as the second generic argument 'theme-c' | 'theme-d' >({ extend: { theme: { // ↓ No problem since we defined 'theme-c' as allowed theme group ID 'theme-c': […], // ↓ No problem since we defined 'theme-d' as allowed theme group ID 'theme-d': […], }, classGroups: { // ↓ No problem since it's part of the default allowed class group IDs shadow: […], // ↓ No problem since we defined 'class-a' as allowed class group ID 'class-a': […], // ↓ No problem since we defined 'class-b' as allowed class group ID 'class-b': […], }, }, }) ``` #### Minimal upgrade To get the the same behavior as before, allow any group IDs by passing `string` as generic arguments to `extendTailwindMerge`. ```diff import { extendTailwindMerge } from 'tailwind-merge' - const twMerge = extendTailwindMerge({ + const twMerge = extendTailwindMerge({ extend: { theme: { … }, classGroups: { … }, }, }) ``` #### Full upgrade If you aren't using any custom groups, there is nothing you need to do to upgrade. If you use any custom class group or theme group IDs in your tailwind-merge config, pass them as generic arguments to `extendTailwindMerge`. ```diff import { extendTailwindMerge } from 'tailwind-merge' + type AdditionalClassGroupIds = 'class-a' | 'class-b' + type AdditionalThemeGroupIds = 'theme-c' | 'theme-d' - const twMerge = extendTailwindMerge({ + const twMerge = extendTailwindMerge({ // your config }) ``` You can also pass `never` to any argument if you don't use any custom groups of that type. If you still see TypeScript errors on object keys of class groups or theme groups, check in the [default config](../../src/lib/default-config.ts) whether the group ID is defined there. It might be that you configured tailwind-merge incorrectly. ### `validators.isLength`: Does not check for arbitrary values anymore Related: [#292](https://github.com/dcastil/tailwind-merge/pull/292) To be consistent with other validators and to make validators more composable, each validator only checks for class parts with either arbitrary values or non-arbitrary values. The `isLength` validator previously checked for both which made it inconsistent with the rest. Now, `isLength` does not check for arbitrary lengths anymore. #### Upgrade Compose the `isLength` and `isArbitraryLength` validators to get the same behavior as before. You can use one of several options: ```diff import { validators } from 'tailwind-merge' + function isLengthOrArbitraryLength(value: string) { + return validators.isLength(value) || validators.isArbitraryLength(value) + } - validators.isLength + isLengthOrArbitraryLength ``` ```diff import { validators } from 'tailwind-merge' const twMerge = createTailwindMerge(() => ({ cacheSize: 500, separator: ':', theme: {}, classGroups: { - mySpecialGroup: [{ special: [validators.isLength] }], + mySpecialGroup: [{ special: [validators.isLength, validators.isArbitraryLength] }], }, conflictingClassGroups: {}, conflictingClassGroupModifiers: {}, })) ``` ### `validators.isInteger`: Does not check for arbitrary values anymore Related: [#292](https://github.com/dcastil/tailwind-merge/pull/292) Same as the `isLength` validator: To be consistent with other validators and to make validators more composable, each validator only checks for class parts with either arbitrary values or non-arbitrary values. The `isInteger` validator previously checked for both which made it inconsistent with the rest. Now, `isInteger` does not check for arbitrary integers anymore. #### Minimal upgrade tailwind-merge doesn't export an `isArbitraryInteger` validator because it doesn't use one in the default config (it uses `isArbitraryValue` instead because there are no ambiguous arbitrary values in the default config). You'll need to rebuild the previous functionality. ```diff import { validators } from 'tailwind-merge' + function isIntegerOrArbitraryInteger(value: string) { + return validators.isInteger(value) || /^\[(number:.+|-?\d+)\]$/.test(value) + } - validators.isInteger + isIntegerOrArbitraryInteger ``` #### Full upgrade If the classes where you previously used `validators.isInteger` don't use arbitrary values, you can continue to use it without any changes. If those classes use arbitrary values but there is only a single class group that could use the arbitrary value, you don't need to check that the arbitrary value is an integer, only that it is any arbitrary value. E.g. for the class `px-[]` we don't need to know what is between the brackets because only the `px` class group uses the `px-` prefix. In that case you can compose `isInteger` and `isArbitraryValue` as shown in the upgrade section for `validators.isLength`. Otherwise, proceed as shown in the minimal upgrade. ### `validators.isArbitraryUrl`: Renamed Related: [#300](https://github.com/dcastil/tailwind-merge/pull/300) `isArbitraryUrl` was used to detect arbitrary `background-image` values. However, the `background-image` CSS property supports more than just URLs, so the functionality of the validator was expanded to also detect values like `image:var(--maybe-an-image-at-runtime)]` or `linear-gradient(rgba(0,0,255,0.5),rgba(255,255,0,0.5))` and therefore renamed as well. #### Upgrade Replace all uses of `validators.isArbitraryUrl` with `validators.isArbitraryImage`. ```diff import { validators } from 'tailwind-merge' - validators.isArbitraryUrl + validators.isArbitraryImage ``` ### `validators.isArbitraryWeight`: Removed Related: [#288](https://github.com/dcastil/tailwind-merge/pull/288) The validator was renamed to `validators.isArbitraryNumber` in `v1.6.2` to better reflect what it's doing. `validators.isArbitraryWeight` has been deprecated since then and was removed in this release. #### Upgrade Replace all uses of `validators.isArbitraryWeight` with `validators.isArbitraryNumber`. ```diff import { validators } from 'tailwind-merge' - validators.isArbitraryWeight + validators.isArbitraryNumber ``` ### `createTailwindMerge`: Mandatory elements added Related: [#290](https://github.com/dcastil/tailwind-merge/pull/290), [#291](https://github.com/dcastil/tailwind-merge/pull/291) The `separator` and `conflictingClassGroupModifiers` keys became mandatory in the configuration object returned in the `createTailwindMerge` callback since tailwind-merge defines those defaults only in its default config. This change makes processing for plugins easier. #### Upgrade If you don't have those keys defined in the configuration object, add them with their default values. ```diff import { createTailwindMerge } from 'tailwind-merge' const twMerge = createTailwindMerge(() => { return { cacheSize: 500, + separator: ':', theme: {}, classGroups: {}, conflictingClassGroups: {}, + conflictingClassGroupModifiers: {}, } }) ``` ### `fromTheme`: Stricter TypeScript types Related: [#279](https://github.com/dcastil/tailwind-merge/pull/279) Matching the stricter types in `extendTailwindMerge`, the `fromTheme` function now only accepts theme group IDs that are defined in the default config. You can define additional allowed theme group IDs by passing them as generic arguments to `fromTheme`. If you don't use the default config, you can also redefine the default theme group IDs by passing them as a second generic arguments to `fromTheme`. #### Minimal upgrade To get the the same behavior as before, allow any theme group IDs by passing `string` as generic arguments to `fromTheme`. ```diff import { fromTheme } from 'tailwind-merge' - const myThemeGroup = fromTheme('my-theme-group') + const myThemeGroup = fromTheme('my-theme-group') ``` #### Full upgrade If you don't use any custom theme groups, there is nothing you need to do to upgrade. If you use any custom theme groups in your tailwind-merge config, pass them as a generic argument to `fromTheme`. ```diff import { fromTheme } from 'tailwind-merge' + type AdditionalThemeGroupIds = 'my-theme-group' | 'my-other-theme-group' - const customThemeGroup = fromTheme('my-theme-group') + const customThemeGroup = fromTheme('my-theme-group') ``` In case you're not extending the default config but defining a config from scratch with `createTailwindMerge`, you can also redefine the default theme group IDs by passing them as the second generic arguments to `fromTheme`. ```diff import { fromTheme } from 'tailwind-merge' + type ThemeGroupIds = 'my-theme-group' | 'my-other-theme-group' - const customThemeGroup = fromTheme('my-theme-group') + const customThemeGroup = fromTheme('my-theme-group') ``` ### `mergeConfigs`: Object shape changed Related: [#279](https://github.com/dcastil/tailwind-merge/pull/279) `mergeConfigs` is used internally within `extendTailwindMerge`, therefore the object shape change in `extendTailwindMerge` applies to `mergeConfigs` as well. Please read [`extendTailwindMerge`: Object shape changed](#extendtailwindmerge-object-shape-changed) for the details and upgrade instructions. ### `mergeConfigs`: Stricter TypeScript types Related: [#279](https://github.com/dcastil/tailwind-merge/pull/279) The reason and effect of the stricter TypeScript types is the same as in [`extendTailwindMerge`: Stricter TypeScript types](#extendtailwindmerge-stricter-typescript-types). The main difference in `mergeConfigs` is that the generic arguments don't accept additional group IDs but rather all allowed group IDs since `mergeConfigs` is independent of the default config. #### Minimal upgrade To get the the same behavior as before, allow any group IDs by passing `string` as generic arguments to `mergeConfigs`. ```diff import { mergeConfigs } from 'tailwind-merge' - mergeConfigs(baseConfig, { + mergeConfigs(baseConfig, { extend: { theme: { … }, classGroups: { … }, } }) ``` #### Full upgrade You need to define all the class group IDs and theme group IDs you use in two string literal union types and pass them as generic arguments to `mergeConfigs` unless TypeScript inference can infer the types. ```diff import { mergeConfigs } from 'tailwind-merge' + type ClassGroupIds = 'class-a' | 'class-b' + type ThemeGroupIds = 'theme-c' | 'theme-d' - mergeConfigs(baseConfig, { + mergeConfigs(baseConfig, { extend: { theme: { … }, classGroups: { … }, } }) ``` ### `join`: Removed Related: [#288](https://github.com/dcastil/tailwind-merge/pull/288) The `join` function was renamed to `twJoin` in `v1.8.0` to distinguish it better from other functions with the same name in your codebase. `join` has been deprecated since then and was removed in this release. #### Upgrade Replace all uses of `join` with `twJoin`. ```diff - import { join } from 'tailwind-merge' + import { twJoin } from 'tailwind-merge' - join + twJoin ``` node-tailwind-merge-3.3.1/docs/changelog/v2-changelog.md000066400000000000000000000402451502210756000230310ustar00rootroot00000000000000# Changelog for v2 releases ## v2.6.0 ### New Features - Export ConfigExtension type from package by [@dcastil](https://github.com/dcastil) in [#505](https://github.com/dcastil/tailwind-merge/pull/505) **Full Changelog**: [`v2.5.5...v2.6.0`](https://github.com/dcastil/tailwind-merge/compare/v2.5.5...v2.6.0) Thanks to [@brandonmcconnell](https://github.com/brandonmcconnell), [@manavm1990](https://github.com/manavm1990), [@langy](https://github.com/langy), [@jamesreaco](https://github.com/jamesreaco), [@roboflow](https://github.com/roboflow), [@syntaxfm](https://github.com/syntaxfm), [@getsentry](https://github.com/getsentry), [@codecov](https://github.com/codecov), [@sourcegraph](https://github.com/sourcegraph), a private sponsor and more via [@thnxdev](https://github.com/thnxdev) for sponsoring tailwind-merge! ❤️ ## v2.5.5 ### Bug Fixes - Fix typo "fractons" instead of "fractions" in "stacked-fractions" class by [@oliverhaas](https://github.com/oliverhaas) in [#492](https://github.com/dcastil/tailwind-merge/pull/492) ### Documentation - Add installation instructions to configuration docs by [@dcastil](https://github.com/dcastil) in [#486](https://github.com/dcastil/tailwind-merge/pull/486) **Full Changelog**: [`v2.5.4...v2.5.5`](https://github.com/dcastil/tailwind-merge/compare/v2.5.4...v2.5.5) Thanks to [@brandonmcconnell](https://github.com/brandonmcconnell), [@manavm1990](https://github.com/manavm1990), [@langy](https://github.com/langy), [@jamesreaco](https://github.com/jamesreaco), [@roboflow](https://github.com/roboflow), [@syntaxfm](https://github.com/syntaxfm), [@getsentry](https://github.com/getsentry), [@codecov](https://github.com/codecov) and more via [@thnxdev](https://github.com/thnxdev) for sponsoring tailwind-merge! ❤️ ## v2.5.4 ### Bug Fixes - Fix incorrect paths within sourcemaps by [@dcastil](https://github.com/dcastil) in [#483](https://github.com/dcastil/tailwind-merge/pull/483) **Full Changelog**: [`v2.5.3...v2.5.4`](https://github.com/dcastil/tailwind-merge/compare/v2.5.3...v2.5.4) Thanks to [@brandonmcconnell](https://github.com/brandonmcconnell), [@manavm1990](https://github.com/manavm1990), [@langy](https://github.com/langy), [@jamesreaco](https://github.com/jamesreaco), [@roboflow](https://github.com/roboflow) and [@codecov](https://github.com/codecov) for sponsoring tailwind-merge! ❤️ ## v2.5.3 ### Bug Fixes - Add missing logical border color properties by [@sherlockdoyle](https://github.com/sherlockdoyle) in [#478](https://github.com/dcastil/tailwind-merge/pull/478) ### Documentation - Add benchmark reporting to PRs and commits by [@XantreDev](https://github.com/XantreDev) in [#455](https://github.com/dcastil/tailwind-merge/pull/455) ### Other - Switch test suite to vitest by [@dcastil](https://github.com/dcastil) in [#461](https://github.com/dcastil/tailwind-merge/pull/461) **Full Changelog**: [`v2.5.2...v2.5.3`](https://github.com/dcastil/tailwind-merge/compare/v2.5.2...v2.5.3) Thanks to [@brandonmcconnell](https://github.com/brandonmcconnell), [@manavm1990](https://github.com/manavm1990), [@langy](https://github.com/langy), [@jamesreaco](https://github.com/jamesreaco), [@roboflow](https://github.com/roboflow), [@xeger](https://github.com/xeger) and [@MrDeatHHH](https://github.com/MrDeatHHH) for sponsoring tailwind-merge! ❤️ ## v2.5.2 ### Bug Fixes - Fix multiline input not working anymore by [@dcastil](https://github.com/dcastil) in [#459](https://github.com/dcastil/tailwind-merge/pull/459) **Full Changelog**: [`v2.5.1...v2.5.2`](https://github.com/dcastil/tailwind-merge/compare/v2.5.1...v2.5.2) Thanks to [@brandonmcconnell](https://github.com/brandonmcconnell), [@manavm1990](https://github.com/manavm1990), [@langy](https://github.com/langy), [@jamesreaco](https://github.com/jamesreaco) and [@jamaluddinrumi](https://github.com/jamaluddinrumi) for sponsoring tailwind-merge! ❤️ ## v2.5.1 ### Bug Fixes - Fix space at beginning of input causing infinite loop by [@dcastil](https://github.com/dcastil) in [#457](https://github.com/dcastil/tailwind-merge/pull/457) **Full Changelog**: [`v2.5.0...v2.5.1`](https://github.com/dcastil/tailwind-merge/compare/v2.5.0...v2.5.1) Thanks to [@brandonmcconnell](https://github.com/brandonmcconnell), [@manavm1990](https://github.com/manavm1990), [@langy](https://github.com/langy), [@jamesreaco](https://github.com/jamesreaco) and [@jamaluddinrumi](https://github.com/jamaluddinrumi) for sponsoring tailwind-merge! ❤️ ## v2.5.0 ### New Features - Performance improvements in mergeClassList by [@XantreDev](htttps://github.com/XantreDev) in [#450](https://github.com/dcastil/tailwind-merge/pull/450) and [@rortan134](https://github.com/rortan134) in [#445](https://github.com/dcastil/tailwind-merge/pull/445) - Use arrow functions where possible to help with minification by [@VIKTORVAV99](htttps://github.com/VIKTORVAV99) in [#449](https://github.com/dcastil/tailwind-merge/pull/449) ### Bug FIxes - Fix bg-opacity arbitrary percentages not being recognized properly by [@dcastil](https://github.com/dcastil) in [#451](https://github.com/dcastil/tailwind-merge/pull/451) **Full Changelog**: [`v2.4.0...v2.5.0`](https://github.com/dcastil/tailwind-merge/compare/v2.4.0...v2.5.0) Thanks to [@brandonmcconnell](https://github.com/brandonmcconnell), [@manavm1990](https://github.com/manavm1990), [@langy](https://github.com/langy) and [@jamesreaco](https://github.com/jamesreaco) for sponsoring tailwind-merge! ❤️ ## v2.4.0 ### New Features - Allow hooking into class parsing logic (experimental) by [@dcastil](https://github.com/dcastil) in [#444](https://github.com/dcastil/tailwind-merge/pull/444) - There is no info to this in the docs because this is experimental, but there is a new `experimentalParseClassName` property in the config that allows you to customize how tailwind-merge recognizes classes. If you're interested, you can read how to use it in the [inline JSDocs](https://github.com/dcastil/tailwind-merge/pull/444/files#diff-b8b77f5be18cf56dca425b3a5b8e9d2e754dd37fe0e3612b95cd4e9bccda08a5) and subscribe to https://github.com/dcastil/tailwind-merge/issues/385 for upcoming more powerful low-level functionality. - Create security policy by [@dcastil](https://github.com/dcastil) in [#439](https://github.com/dcastil/tailwind-merge/pull/439) - Added documentation on how to report potential vulnerabilities - Avoid `@babel/runtime` dependency by [@dcastil](https://github.com/dcastil) in [#431](https://github.com/dcastil/tailwind-merge/pull/431) - Now no dependencies in tailwind-merge anymore. This dependency was only used in the `tailwind-merge/es5` bundle anyway which I don't optimize for. ### Documentation - Comment/typo fixes by [@barvian](https://github.com/barvian) in [#443](https://github.com/dcastil/tailwind-merge/pull/443) - Fix typo in doc/recipes.md by [@dsernst](https://github.com/dsernst) in [#428](https://github.com/dcastil/tailwind-merge/pull/428) - Add tailwind-merge-dotnet to similar packages by [@desmondinho](https://github.com/desmondinho) in [#415](https://github.com/dcastil/tailwind-merge/pull/415) ### Other - Added GitHub Action that adds context-v2 label to every issue, discussion and PR by [@Pritam1211](https://github.com/Pritam1211) in [#434](https://github.com/dcastil/tailwind-merge/pull/434) - Replace size-limit action with own metrics-report action by [@dcastil](https://github.com/dcastil) in [#433](https://github.com/dcastil/tailwind-merge/pull/433) **Full Changelog**: [`v2.3.0...v2.4.0`](https://github.com/dcastil/tailwind-merge/compare/v2.3.0...v2.4.0) Thanks to [@brandonmcconnell](https://github.com/brandonmcconnell), [@manavm1990](https://github.com/manavm1990), [@langy](https://github.com/langy), [@jamesreaco](https://github.com/jamesreaco) and [@microsoft](https://github.com/microsoft) for sponsoring tailwind-merge! ❤️ ## v2.3.0 ### New Features - Add support for mix-blend-plus-darker utility by [@dcastil](https://github.com/dcastil) in [#403](https://github.com/dcastil/tailwind-merge/pull/403) - Added support for bigint in ClassNameValue type by [@LarsArtmann](https://github.com/LarsArtmann) in [#402](https://github.com/dcastil/tailwind-merge/pull/402) ### Documentation - Add tailwind-merge-go to similar packages in docs by [@Oudwins](https://github.com/Oudwins) in [#396](https://github.com/dcastil/tailwind-merge/pull/396) **Full Changelog**: [`v2.2.2...v2.3.0`](https://github.com/dcastil/tailwind-merge/compare/v2.2.2...v2.3.0) Thanks to [@brandonmcconnell](https://github.com/brandonmcconnell), [@manavm1990](https://github.com/manavm1990), [@langy](https://github.com/langy) and [@jamesreaco](https://github.com/jamesreaco) for sponsoring tailwind-merge! ❤️ ## v2.2.2 ### Bug Fixes - Fix arbitrary shadow with inset not recognized by [@dcastil](https://github.com/dcastil) in [#392](https://github.com/dcastil/tailwind-merge/pull/392) ### Documentation - Fix minor typos in `configuration.md` by [@stephan281094](https://github.com/stephan281094) in [#372](https://github.com/dcastil/tailwind-merge/pull/372) **Full Changelog**: [`v2.2.1...v2.2.2`](https://github.com/dcastil/tailwind-merge/compare/v2.2.1...v2.2.2) Thanks to [@brandonmcconnell](https://github.com/brandonmcconnell), [@manavm1990](https://github.com/manavm1990), [@langy](https://github.com/langy), a private sponsor and [@jamesreaco](https://github.com/jamesreaco) for sponsoring tailwind-merge! ❤️ ## v2.2.1 ### Bug Fixes - Fix stroke-color being incorrectly detected as stroke-width by [@dcastil](https://github.com/dcastil) in [#371](https://github.com/dcastil/tailwind-merge/pull/371) **Full Changelog**: [`v2.2.0...v2.2.1`](https://github.com/dcastil/tailwind-merge/compare/v2.2.0...v2.2.1) Thanks to [@brandonmcconnell](https://github.com/brandonmcconnell), [@manavm1990](https://github.com/manavm1990) and [@langy](https://github.com/langy) for sponsoring tailwind-merge! ❤️ ## v2.2.0 ### New Features - Add support for Tailwind CSS v3.4 by [@dcastil](https://github.com/dcastil) in [#360](https://github.com/dcastil/tailwind-merge/pull/360) **Full Changelog**: [`v2.1.0...v2.2.0`](https://github.com/dcastil/tailwind-merge/compare/v2.1.0...v2.2.0) Thanks to [@brandonmcconnell](https://github.com/brandonmcconnell), [@manavm1990](https://github.com/manavm1990), [@ErwinAI](https://github.com/ErwinAI) and [@langy](https://github.com/langy) for sponsoring tailwind-merge! ❤️ ## v2.1.0 ### New Features - Add `ClassValidator` type to package exports by [@dcastil](https://github.com/dcastil) in [#348](https://github.com/dcastil/tailwind-merge/pull/348) ### Bug Fixes - Fix display class not removed when it precedes line-clamp class by [@dcastil](https://github.com/dcastil) in [#347](https://github.com/dcastil/tailwind-merge/pull/347) ### Documentation - Fix curly bracket typo in config docs by [@Kosai106](https://github.com/Kosai106) in [#349](https://github.com/dcastil/tailwind-merge/pull/349) **Full Changelog**: [`v2.0.0...v2.1.0`](https://github.com/dcastil/tailwind-merge/compare/v2.0.0...v2.1.0) Thanks to [@brandonmcconnell](https://github.com/brandonmcconnell), [@manavm1990](https://github.com/manavm1990), [@ErwinAI](https://github.com/ErwinAI) and [@langy](https://github.com/langy) for sponsoring tailwind-merge! ❤️ ## v2.0.0 The tailwind-merge v2 release has been sitting here almost finished for 2 months already. But the timing was never quite right, especially thinking about the increased support needed after the release. In the meantime, the product of the company I work at [launched in public beta](https://medium.com/@risecal/meet-rise-the-calendar-that-works-for-you-were-launching-the-public-beta-today-bc07555a2191) and I married. Thank you for your patience. This release focuses on making it easier to configure the library for new users. Check out the [migration guide](./v1-to-v2-migration.md) and if you have any questions, feel free to [create an issue](https://github.com/dcastil/tailwind-merge/issues/new/choose). ### Breaking Changes - Fix `background-image` and `background-position` being merged incorrectly by [@dcastil](https://github.com/dcastil) in [#300](https://github.com/dcastil/tailwind-merge/pull/300) - Values for `background-position` and `background-size` can look very similar and Tailwind CSS uses the same `bg-` prefix for both groups. This results in some [limitations](../limitations.md) for tailwind-merge. If you use background position or background size with arbitrary values, please read [this section](../limitations.md#you-need-to-use-label-in-arbitrary-background-position-and-background-size-classes) about how to use them. - Make types of available keys more strict and configurable through generics by [@kachkaev](https://github.com/kachkaev) in [#279](https://github.com/dcastil/tailwind-merge/pull/279) - Make it possible to override elements with `extendTailwindMerge` by [@dcastil](https://github.com/dcastil) in [#294](https://github.com/dcastil/tailwind-merge/pull/294) - Separate validators better by [@dcastil](https://github.com/dcastil) in [#292](https://github.com/dcastil/tailwind-merge/pull/292) - Make `conflictingClassGroupModifiers` in config non-optional by [@dcastil](https://github.com/dcastil) in [#291](https://github.com/dcastil/tailwind-merge/pull/291) - Move separator to config by [@dcastil](https://github.com/dcastil) in [#290](https://github.com/dcastil/tailwind-merge/pull/290) - Remove `module` field from package.json by [@dcastil](https://github.com/dcastil) in [#289](https://github.com/dcastil/tailwind-merge/pull/289) - Remove deprecated exports by [@dcastil](https://github.com/dcastil) in [#288](https://github.com/dcastil/tailwind-merge/pull/288) - Transpile lib to more modern JS by [@dcastil](https://github.com/dcastil) in [#287](https://github.com/dcastil/tailwind-merge/pull/287) ### New Features - Make types of available keys more strict and configurable through generics by [@kachkaev](https://github.com/kachkaev) in [#279](https://github.com/dcastil/tailwind-merge/pull/279) - Make it possible to override elements with `extendTailwindMerge` by [@dcastil](https://github.com/dcastil) in [#294](https://github.com/dcastil/tailwind-merge/pull/294) - Separate validators better by [@dcastil](https://github.com/dcastil) in [#292](https://github.com/dcastil/tailwind-merge/pull/292) - Make `conflictingClassGroupModifiers` in config non-optional by [@dcastil](https://github.com/dcastil) in [#291](https://github.com/dcastil/tailwind-merge/pull/291) - Move separator to config by [@dcastil](https://github.com/dcastil) in [#290](https://github.com/dcastil/tailwind-merge/pull/290) - Remove `module` field from package.json by [@dcastil](https://github.com/dcastil) in [#289](https://github.com/dcastil/tailwind-merge/pull/289) - Remove deprecated exports by [@dcastil](https://github.com/dcastil) in [#288](https://github.com/dcastil/tailwind-merge/pull/288) - Transpile lib to more modern JS by [@dcastil](https://github.com/dcastil) in [#287](https://github.com/dcastil/tailwind-merge/pull/287) - Add ES5 bundle by [@dcastil](https://github.com/dcastil) in [#286](https://github.com/dcastil/tailwind-merge/pull/286) ### Bug Fixes - Fix touch action classes overriding each other incorrectly by [@dcastil](https://github.com/dcastil) in [#313](https://github.com/dcastil/tailwind-merge/pull/313) - Fix `background-image` and `background-position` being merged incorrectly by [@dcastil](https://github.com/dcastil) in [#300](https://github.com/dcastil/tailwind-merge/pull/300) - Fix number validators accidentally returning `true` for empty strings by [@dcastil](https://github.com/dcastil) in [#295](https://github.com/dcastil/tailwind-merge/pull/295) - Fix typo in test filename by [@CrutchTheClutch](https://github.com/CrutchTheClutch) in [#284](https://github.com/dcastil/tailwind-merge/pull/284) ### Documentation - Explain limitations of arbitrary values in `bg-size` and `bg-position` class groups in docs by [@dcastil](https://github.com/dcastil) in [#328](https://github.com/dcastil/tailwind-merge/pull/328) **Full Changelog**: [`v1.14.0...v2.0.0`](https://github.com/dcastil/tailwind-merge/compare/v1.14.0...v2.0.0) Thanks to [@quezlatch](https://github.com/quezlatch), [@brandonmcconnell](https://github.com/brandonmcconnell), [@manavm1990](https://github.com/manavm1990) and [@ErwinAI](https://github.com/ErwinAI) for sponsoring tailwind-merge! ❤️ node-tailwind-merge-3.3.1/docs/changelog/v2-to-v3-migration.md000066400000000000000000000274111502210756000240410ustar00rootroot00000000000000# Guide to migrate from tailwind-merge v2 to v3 This document is only about breaking changes between v2 and v3. For a full list of changes, see the [v3.0.0 release](./v3-changelog.md#v300). ## Overview tailwind-merge v3 drops support for Tailwind CSS v3 and in turn adds support for Tailwind CSS v4. That means you should upgrade to Tailwind CSS v4 and tailwind-merge v3 together. All breaking changes are related to the Tailwind CSS v4 support. The highlights: - No breaking changes to `twMerge` other than it expecting classes supported in Tailwind CSS v4. - The `theme` scales tailwind-merge supports were changed and now match the Tailwind CSS v4 [theme variable namespace](https://tailwindcss.com/docs/theme#theme-variable-namespaces). If you have feedback of any kind regarding this release, feel free to [open an issue or discussion](https://github.com/dcastil/tailwind-merge/issues/new/choose). I'm always happy to hear from you! ## Breaking changes By exports: - All - [Supported Tailwind CSS version range changes from v3 to v4](#supported-tailwind-css-version-range-changes-from-v3-to-v4) - `extendTailwindMerge` - [Allowed theme keys changed](#extendtailwindmerge-allowed-theme-keys-changed) - [Custom separators are no longer supported](#extendtailwindmerge-and-createtailwindmerge-custom-separators-are-no-longer-supported) - [Prefix defined in config shouldn't include combining character anymore](#extendtailwindmerge-and-createtailwindmerge-prefix-defined-in-config-shouldnt-include-combining-character-anymore) - `createTailwindMerge` - [Custom separators are no longer supported](#extendtailwindmerge-and-createtailwindmerge-custom-separators-are-no-longer-supported) - [Prefix defined in config shouldn't include combining character anymore](#extendtailwindmerge-and-createtailwindmerge-prefix-defined-in-config-shouldnt-include-combining-character-anymore) - [Mandatory field `orderSensitiveModifiers` added](#createtailwindmerge-mandatory-field-ordersensitivemodifiers-added) - `validators` - [`isLength`: Removed](#validatorsislength-removed) - `DefaultThemeGroupIds` - [Type union changed literals](#defaultthemegroupids-type-union-changed-literals) ### Supported Tailwind CSS version range changes from v3 to v4 tailwind-merge v3.0.0 is expected to be used together with Tailwind CSS v4. That means only features that work in Tailwind CSS v4 are supported. If you intend to stay on Tailwind CSS v3, don't upgrade to tailwind-merge v3.0.0 because there are some breaking changes in expected class syntax. ### `extendTailwindMerge`: Allowed theme keys changed In Tailwind CSS v3 tailwind-merge was in a difficult position with Tailwind's theme scales. If tailwind-merge implemented support for all theme scales, the bundle size would become twice as large. If it didn't support any theme scales, users would have had a difficult time extending scales that are used in many class groups, like in the case of the `spacing` scale. tailwind-merge went with an awkward middle ground where it only supported theme scales that were used in multiple class groups. Tailwind CSS v4 reduced the number of theme scales to only 18 (called [theme variable namespaces](https://tailwindcss.com/docs/theme#theme-variable-namespaces) now) which makes it possible for tailwind-merge to support all of them. That means if you add the CSS variable `--inset-shadow-deep` to your Tailwind CSS theme, you can add it to the `theme` object in tailwind-merge like in the following example: ```ts import { extendTailwindMerge } from 'tailwind-merge' const twMerge = extendTailwindMerge({ extend: { theme: { 'inset-shadow': ['deep'], }, }, }) ``` #### Upgrade Here's how to proceed with upgrading each individual theme scale that got removed or renamed. Just keep in mind that theme scales should only define the custom part of a class (i.e. `deep` for the class `inset-shadow-deep`) whereas class groups should define the whole class (i.e. `inset-shadow-deep` for the class `inset-shadow-deep`). Sometimes you might find that values you configured manually before are now supported by Tailwind CSS v4 by default in which case you can remove them from your tailwind-merge config. | Theme scale in tailwind-merge v2 | What to use in tailwind-merge v3 instead | | -------------------------------- | -------------------------------------------------------------------------- | | `borderColor` | theme scale `color` | | `borderRadius` | theme scale `radius` | | `borderSpacing` | theme scale `spacing` or class groups `border-spacing-*` | | `borderWidth` | class groups `border-w-*` | | `brightness` | class groups `brightness` and `backdrop-brightness` | | `colors` | theme scale `color` | | `contrast` | class groups `contrast` and `backdrop-contrast` | | `gap` | class groups `gap-*` | | `gradientColorStopPositions` | class groups `gradient-from-pos`, `gradient-via-pos` and `gradient-to-pos` | | `gradientColorStops` | class groups `gradient-from`, `gradient-via` and `gradient-to` | | `grayscale` | class groups `grayscale` and `backdrop-grayscale` | | `hueRotate` | class groups `hue-rotate` and `backdrop-hue-rotate` | | `inset` | theme scale `spacing` or class groups `inset-*` | | `invert` | class groups `invert` and `backdrop-invert` | | `margin` | theme scale `spacing` or class groups `m-*` | | `opacity` | class groups `opacity` and `backdrop-opacity` | | `padding` | theme scale `spacing` or class groups `p-*` | | `saturate` | class groups `saturate` and `backdrop-saturate` | | `scale` | class groups `scale-*` | | `sepia` | class groups `sepia` and `backdrop-sepia` | | `skew` | class groups `skew-*` | | `space` | theme scale `spacing` or class groups `space-*` | | `translate` | theme scale `spacing` or class groups `translate-*` | In case you were modifying class groups in tailwind-merge v2 because their theme scale was previously not implemented, it is highly likely that you can move those definitions to the `theme` object in tailwind-merge v3. E.g. if you previously modified the `font-family` class group to add a custom font class, you can now use `theme.font` instead. Check out the [theme documentation](../configuration.md#theme) for more info. ### `extendTailwindMerge` and `createTailwindMerge`: Custom separators are no longer supported Tailwind CSS v4 removed support for custom separators for modifiers in Tailwind CSS classes and now only the default separator `:` is allowed. Therefore tailwind-merge also removed support for custom separators and doesn't use the `separator` key in its config anymore. If you use TypeScript, you'll see a type error if you try to use the `separator` key in your config. #### Upgrade Remove the `separator` key from your tailwind-merge config. ```diff import { extendTailwindMerge } from 'tailwind-merge' const twMerge = extendTailwindMerge({ - separator: '_', … }) ``` ```diff import { createTailwindMerge } from 'tailwind-merge' const twMerge = createTailwindMerge(() => ({ - separator: '_', … })) ``` ### `extendTailwindMerge` and `createTailwindMerge`: Prefix defined in config shouldn't include combining character anymore In Tailwind CSS v4 the optional prefix syntax of classes changed from being in front of the base class like in `hover:*:tw-class` to looking like the first modifier of a class like in `tw:hover:*:class`. In tailwind-merge v2 you had to specify the prefix including the final dash character `-` that combined the prefix with the base class. Due to the new syntax this combining character changes to `:`. To prevent having to change your config if the combining character changes in the future, tailwind-merge v3 expects you to specify the prefix without the combining character. #### Upgrade Remove the dash character from the prefix in your tailwind-merge config. ```diff import { extendTailwindMerge } from 'tailwind-merge' const twMerge = extendTailwindMerge({ - prefix: 'tw-', + prefix: 'tw', … }) ``` ```diff import { createTailwindMerge } from 'tailwind-merge' const twMerge = createTailwindMerge(() => ({ - prefix: 'tw-', + prefix: 'tw', … })) ``` ### `createTailwindMerge`: Mandatory field `orderSensitiveModifiers` added tailwind-merge v3 adds a new mandatory field `orderSensitiveModifiers` to the config to specify which modifiers should be considered order-sensitive. Learn more about order-sensitive modifiers in the [documentation](../configuration.md#order-sensitive-modifiers). #### Minimal upgrade Add the `orderSensitiveModifiers` field to your tailwind-merge config. ```diff import { createTailwindMerge } from 'tailwind-merge' const twMerge = createTailwindMerge(() => ({ + orderSensitiveModifiers: [], … })) ``` #### Full upgrade If you have any order-sensitive modifiers in Tailwind, add them to the new `orderSensitiveModifiers` field in your tailwind-merge config. ```diff import { createTailwindMerge } from 'tailwind-merge' const twMerge = createTailwindMerge(() => ({ … + orderSensitiveModifiers: ['before', '*', …], })) ``` ### `validators.isLength`: Removed The validator `isLength` was used to check whether a class part is a number (`3`, `1.5`), a fraction (`3/4`), or one of the strings `px`, `full` or `screen`. This was used for most length-based scales but the name was not really precise in explaining what it allows. Due to how length-based scales were changed in Tailwind CSS v4, tailwind-merge v3 now uses `isNumber` and `isFraction` instead depending on what each scale supports and strings like `px`, `full` and `screen` are instead specified manually in the scales themselves. This makes it more obvious what those validators do. #### Minimal upgrade You can rebuild the previous validator yourself. ```ts import { validators } from 'tailwind-merge' function isLength(value: string) { return ( validators.isNumber(value) || validators.isFraction(value) || value === 'full' || value === 'px' || value === 'screen' ) } ``` #### Full upgrade Replace all uses of `validators.isLength` with `validators.isNumber`, `validators.isFraction` and the strings `full`, `px` and `screen` depending on which of those your scale supports. ```diff import { validators } from 'tailwind-merge' - [validators.isLength] + [validators.isNumber, validators.isFraction, 'full', 'px', 'screen'] ``` ### `DefaultThemeGroupIds`: Type union changed literals Due to the default theme keys changing, the string union of `DefaultThemeGroupIds` changed as well. Since this is a TypeScript type, errors in TypeScript will determine how to handle this change. node-tailwind-merge-3.3.1/docs/changelog/v3-changelog.md000066400000000000000000000231411502210756000230260ustar00rootroot00000000000000# Changelog for v3 releases ## v3.3.1 ### Bug Fixes - Fix arbitrary value using `color-mix()` not being detected as color by [@dcastil](https://github.com/dcastil) in [#591](https://github.com/dcastil/tailwind-merge/pull/591) **Full Changelog**: [`v3.3.0...v3.3.1`](https://github.com/dcastil/tailwind-merge/compare/v3.3.0...v3.3.1) Thanks to [@brandonmcconnell](https://github.com/brandonmcconnell), [@manavm1990](https://github.com/manavm1990), [@langy](https://github.com/langy), [@roboflow](https://github.com/roboflow), [@syntaxfm](https://github.com/syntaxfm), [@getsentry](https://github.com/getsentry), [@codecov](https://github.com/codecov), [@sourcegraph](https://github.com/sourcegraph), a private sponsor, [@block](https://github.com/block) and [shawt3000](https://github.com/shawt3000) for sponsoring tailwind-merge! ❤️ ## v3.3.0 ### New Features - Add support for tailwind CSS v4.1.5 by [@dcastil](https://github.com/dcastil) in [#575](https://github.com/dcastil/tailwind-merge/pull/575) **Full Changelog**: [`v3.2.0...v3.3.0`](https://github.com/dcastil/tailwind-merge/compare/v3.2.0...v3.3.0) Thanks to [@brandonmcconnell](https://github.com/brandonmcconnell), [@manavm1990](https://github.com/manavm1990), [@langy](https://github.com/langy), [@roboflow](https://github.com/roboflow), [@syntaxfm](https://github.com/syntaxfm), [@getsentry](https://github.com/getsentry), [@codecov](https://github.com/codecov), [@sourcegraph](https://github.com/sourcegraph), a private sponsor and [@block](https://github.com/block) for sponsoring tailwind-merge! ❤️ ## v3.2.0 ### New Features - Add support for Tailwind CSS v4.1 by [@dcastil](https://github.com/dcastil) in [#565](https://github.com/dcastil/tailwind-merge/pull/565) **Full Changelog**: [`v3.1.0...v3.2.0`](https://github.com/dcastil/tailwind-merge/compare/v3.1.0...v3.2.0) Thanks to [@brandonmcconnell](https://github.com/brandonmcconnell), [@manavm1990](https://github.com/manavm1990), [@langy](https://github.com/langy), [@jamesreaco](https://github.com/jamesreaco), [@roboflow](https://github.com/roboflow), [@syntaxfm](https://github.com/syntaxfm), [@getsentry](https://github.com/getsentry), [@codecov](https://github.com/codecov), [@sourcegraph](https://github.com/sourcegraph) and a private sponsor for sponsoring tailwind-merge! ❤️ ## v3.1.0 ### New Features - Add support for Tailwind CSS v4.0.10 by [@dcastil](https://github.com/dcastil) in [#546](https://github.com/dcastil/tailwind-merge/pull/546) ### Bug Fixes - Fix length variable in `via-(length:*)` class being merged with `via-` classes accidentally by [@dcastil](https://github.com/dcastil) in [#559](https://github.com/dcastil/tailwind-merge/pull/559) ### Documentation - Fix typo in comment in types.ts by [@roottool](https://github.com/roottool) in [#549](https://github.com/dcastil/tailwind-merge/pull/549) - Update shadow scale recipe to tailwind merge v3 API by [@dcastil](https://github.com/dcastil) in [#545](https://github.com/dcastil/tailwind-merge/pull/545) ### Other - Fix metrics report action erroring on PRs from forks by [@dcastil](https://github.com/dcastil) in [#551](https://github.com/dcastil/tailwind-merge/pull/551) **Full Changelog**: [`v3.0.2...v3.1.0`](https://github.com/dcastil/tailwind-merge/compare/v3.0.2...v3.1.0) Thanks to [@brandonmcconnell](https://github.com/brandonmcconnell), [@manavm1990](https://github.com/manavm1990), [@langy](https://github.com/langy), [@jamesreaco](https://github.com/jamesreaco), [@roboflow](https://github.com/roboflow), [@syntaxfm](https://github.com/syntaxfm), [@getsentry](https://github.com/getsentry), [@codecov](https://github.com/codecov), [@sourcegraph](https://github.com/sourcegraph) and a private sponsor for sponsoring tailwind-merge! ❤️ ## v3.0.2 ### Bug Fixes - Fix `px` value not being recognized for some class groups by [@dcastil](https://github.com/dcastil) in [#538](https://github.com/dcastil/tailwind-merge/pull/538) - Fix doc comment being in incorrect place in default config by [@gjtorikian](https://github.com/gjtorikian) in [#526](https://github.com/dcastil/tailwind-merge/pull/526) **Full Changelog**: [`v3.0.1...v3.0.2](https://github.com/dcastil/tailwind-merge/compare/v3.0.1...v3.0.2) Thanks to [@brandonmcconnell](https://github.com/brandonmcconnell), [@manavm1990](https://github.com/manavm1990), [@langy](https://github.com/langy), [@jamesreaco](https://github.com/jamesreaco), [@roboflow](https://github.com/roboflow), [@syntaxfm](https://github.com/syntaxfm), [@getsentry](https://github.com/getsentry), [@codecov](https://github.com/codecov), [@sourcegraph](https://github.com/sourcegraph) and a private sponsor for sponsoring tailwind-merge! ❤️ ## v3.0.1 ### Bug Fixes - Update info about supported Tailwind CSS version in README by [@dcastil](https://github.com/dcastil) in [`b9c136d`](https://github.com/dcastil/tailwind-merge/commit/b9c136df358ef6012f23bf08258dbf970c0aec43) - Update incorrect link in v3 changelog by [@dcastil](https://github.com/dcastil) in [`e22885e`](https://github.com/dcastil/tailwind-merge/commit/e22885e41e1661f1493f9bf6fb829cfbe1b50281) **Full Changelog**: [`v3.0.0...v3.0.1`](https://github.com/dcastil/tailwind-merge/compare/v3.0.0...v3.0.1) Thanks to [@brandonmcconnell](https://github.com/brandonmcconnell), [@manavm1990](https://github.com/manavm1990), [@langy](https://github.com/langy), [@jamesreaco](https://github.com/jamesreaco), [@roboflow](https://github.com/roboflow), [@syntaxfm](https://github.com/syntaxfm), [@getsentry](https://github.com/getsentry), [@codecov](https://github.com/codecov), [@sourcegraph](https://github.com/sourcegraph) and a private sponsor for sponsoring tailwind-merge! ❤️ ## v3.0.0 [Tailwind CSS v4 is here](https://tailwindcss.com/blog/tailwindcss-v4) and it's time to upgrade tailwind-merge to support it. tailwind-merge v3.0.0 is more accurate than ever and follows the Tailwind CSS spec more closely than in v2. That is thanks to Tailwind CSS v4 being more consistent than ever. This release drops support for Tailwind CSS v3 and in turn adds support for Tailwind CSS v4. That means you should upgrade to Tailwind CSS v4 and tailwind-merge v3 together. All breaking changes are related to the Tailwind CSS v4 support. Check out the [migration guide](./v2-to-v3-migration.md) and if you have any questions, feel free to [create an issue](https://github.com/dcastil/tailwind-merge/issues/new/choose). ### Breaking Changes - Dropping support for Tailwind CSS v3 in favor of support for Tailwind CSS v4 by [@dcastil](https://github.com/dcastil) in [#518](https://github.com/dcastil/tailwind-merge/pull/518) - Theme scales keys changed and now match Tailwind CSS v4 theme variable namespace exactly by [@dcastil](https://github.com/dcastil) in [#518](https://github.com/dcastil/tailwind-merge/pull/518) - `isLength` validator was removed and split into separate validators `isNumber` and `isFraction` by [@dcastil](https://github.com/dcastil) in [#518](https://github.com/dcastil/tailwind-merge/pull/518) - Prefix defined in config shouldn't include combining `-` character anymore by [@dcastil](https://github.com/dcastil) in [#518](https://github.com/dcastil/tailwind-merge/pull/518) - Tailwind CSS v3 prefix position in class not supported anymore in favor of Tailwind CSS v4 position by [@dcastil](https://github.com/dcastil) in [#518](https://github.com/dcastil/tailwind-merge/pull/518) - Custom separators are no longer supported by [@dcastil](https://github.com/dcastil) in [#518](https://github.com/dcastil/tailwind-merge/pull/518) - New mandatory `orderSensitiveModifiers` property in config when using `createTailwindMerge` by [@dcastil](https://github.com/dcastil) in [#518](https://github.com/dcastil/tailwind-merge/pull/518) - `DefaultThemeGroupIds` type union consists of different string literals than before by [@dcastil](https://github.com/dcastil) in [#518](https://github.com/dcastil/tailwind-merge/pull/518) - Classes removed in Tailwind CSS v4 are not supported by tailwind-merge anymore by [@dcastil](https://github.com/dcastil) in [#518](https://github.com/dcastil/tailwind-merge/pull/518) ### New Features - Support for new important modifier position at the end of class by [@dcastil](https://github.com/dcastil) in [#518](https://github.com/dcastil/tailwind-merge/pull/518) - Support for arbitrary CSS variable syntax by [@dcastil](https://github.com/dcastil) in [#518](https://github.com/dcastil/tailwind-merge/pull/518) - There are a bunch of new validators used by tailwind-merge, primarily for new Tailwind CSS v4 features like arbitrary CSS variables by [@dcastil](https://github.com/dcastil) in [#518](https://github.com/dcastil/tailwind-merge/pull/518) ### Bug Fixes - Previously some order-sensitive modifiers like `before:` were treated as not order-sensitive. This is now fixed by [@dcastil](https://github.com/dcastil) in [#518](https://github.com/dcastil/tailwind-merge/pull/518) ### Documentation - Added section explaining order-sensitive modifiers to [configuration docs](../configuration.md#order-sensitive-modifiers) by [@dcastil](https://github.com/dcastil) in [#518](https://github.com/dcastil/tailwind-merge/pull/518) **Full Changelog**: [`v2.6.0...v3.0.0`](https://github.com/dcastil/tailwind-merge/compare/v2.6.0...v3.0.0) Thanks to [@brandonmcconnell](https://github.com/brandonmcconnell), [@manavm1990](https://github.com/manavm1990), [@langy](https://github.com/langy), [@jamesreaco](https://github.com/jamesreaco), [@roboflow](https://github.com/roboflow), [@syntaxfm](https://github.com/syntaxfm), [@getsentry](https://github.com/getsentry), [@codecov](https://github.com/codecov), [@sourcegraph](https://github.com/sourcegraph) and a private sponsor for sponsoring tailwind-merge! ❤️ node-tailwind-merge-3.3.1/docs/configuration.md000066400000000000000000000420131502210756000214700ustar00rootroot00000000000000# Configuration ## Installation The tailwind-merge package is hosted on npm under the name [`tailwind-merge`](https://www.npmjs.com/package/tailwind-merge). There are lots of package managers for installing packages hosted on npm. Here are installation instructions for the most popular ones: [npm](https://npmjs.com), [yarn](https://yarnpkg.com), [pnpm](https://pnpm.io) and [bun](https://bun.sh). ```sh npm add tailwind-merge yarn add tailwind-merge pnpm add tailwind-merge bun add tailwind-merge ``` ## Basic usage If you're using Tailwind CSS without any extra config, you can use [`twMerge`](./api-reference.md#twmerge) right away. You can safely stop reading the documentation here. ## Usage with custom Tailwind config If you're using a custom Tailwind config, you may need to configure tailwind-merge as well to merge classes properly. The default [`twMerge`](./api-reference.md#twmerge) function is configured in a way that you can still use it if all the following points apply to your Tailwind config: - Only using color names which don't clash with other Tailwind class names - Only deviating by number values from number-based Tailwind classes - Only using font-family classes which don't clash with default font-weight classes - Sticking to default Tailwind config for everything else If some of these points don't apply to you, you can test whether `twMerge` still works as intended with your custom classes. Otherwise, you need create your own custom merge function by either extending the default tailwind-merge config or using a completely custom one. The tailwind-merge config is different from the Tailwind config because it's expected to be shipped and run in the browser as opposed to the Tailwind config which is meant to run at build-time. Be careful in case you're using your Tailwind config directly to configure tailwind-merge in your client-side code because that could result in an unnecessarily large bundle size. ### Shape of tailwind-merge config The tailwind-merge config is an object with a few keys. ```ts const tailwindMergeConfig = { // ↓ Set how many values should be stored in cache. cacheSize: 500, // ↓ Optional prefix from Tailwind config prefix: 'tw', theme: { // Theme scales are defined here }, classGroups: { // Class groups are defined here }, conflictingClassGroups: { // Conflicts between class groups are defined here }, conflictingClassGroupModifiers: { // Conflicts between postfix modifier of a class group and another class group are defined here }, orderSensitiveModifiers: [ // Modifiers whose order among multiple modifiers should be preserved because their order // changes which element gets targeted. ], } ``` ### Class groups The library uses a concept of _class groups_ which is an array of Tailwind classes which all modify the same CSS property. E.g. here is the position class group. ```ts const positionClassGroup = ['static', 'fixed', 'absolute', 'relative', 'sticky'] ``` tailwind-merge resolves conflicts between classes in a class group and only keeps the last one passed to the merge function call. ```ts twMerge('static sticky relative') // → 'relative' ``` Tailwind classes often share the beginning of the class name, so elements in a class group can also be an object with values of the same shape as a class group (yes, the shape is recursive). In the object each key is joined with all the elements in the corresponding array with a dash (`-`) in between. E.g. here is the overflow class group which results in the classes `overflow-auto`, `overflow-hidden`, `overflow-visible` and `overflow-scroll`. ```ts const overflowClassGroup = [{ overflow: ['auto', 'hidden', 'visible', 'scroll'] }] ``` Sometimes it isn't possible to enumerate all elements in a class group. Think of a Tailwind class which allows arbitrary values. In this scenario you can use a validator function which takes a _class part_ and returns a boolean indicating whether a class is part of a class group. E.g. here is the fill class group. ```ts const isArbitraryValue = (classPart: string) => /^\[.+\]$/.test(classPart) const fillClassGroup = [{ fill: ['current', isArbitraryValue] }] ``` Because the function is under the `fill` key, it will only get called for classes which start with `fill-`. Also, the function only gets passed the part of the class name which comes after `fill-`, this way you can use the same function in multiple class groups. tailwind-merge exports its own [validators](./api-reference.md#validators), so you don't need to recreate them. You can use an empty string (`''`) as a class part if you want to indicate that the preceding part was the end. This is useful for defining elements which are marked as `DEFAULT` in the Tailwind config. ```ts // ↓ Resolves to filter and filter-none const filterClassGroup = [{ filter: ['', 'none'] }] ``` Each class group is defined under its ID in the `classGroups` object in the config. This ID is only used internally, and the only thing that matters is that it is unique among all class groups. ### Conflicting class groups Sometimes there are conflicts across Tailwind classes which are more complex than "remove all those other classes when a class from this group is present in the class list string". One example is the combination of the classes `px-3` (setting `padding-left` and `padding-right`) and `pr-4` (setting `padding-right`). If they are passed to `twMerge` as `pr-4 px-3`, you most likely intend to apply `padding-left` and `padding-right` from the `px-3` class and want `pr-4` to be removed, indicating that both these classes should belong to a single class group. But if they are passed to `twMerge` as `px-3 pr-4`, you want to set the `padding-right` from `pr-4` but still want to apply the `padding-left` from `px-3`, so `px-3` shouldn't be removed when inserting the classes in this order, indicating they shouldn't be in the same class group. To summarize, `px-3` should stand in conflict with `pr-4`, but `pr-4` should not stand in conflict with `px-3`. To achieve this, we need to define asymmetric conflicts across class groups. This is what the `conflictingClassGroups` object in the tailwind-merge config is for. You define a key in it which is the ID of a class group which _creates_ a conflict and the value is an array of IDs of class group which _receive_ a conflict. ```ts const conflictingClassGroups = { px: ['pr', 'pl'], } ``` If a class group _creates_ a conflict, it means that if it appears in a class list string passed to `twMerge`, all preceding class groups in the string which _receive_ the conflict will be removed. When we think of our example, the `px` class group creates a conflict which is received by the class groups `pr` and `pl`. This way `px-3` removes a preceding `pr-4`, but not the other way around. ### Postfix modifiers conflicting with class groups Tailwind CSS allows postfix modifiers for some classes. E.g. you can set font-size and line-height together with `text-lg/7` with `/7` being the postfix modifier. This means that any line-height classes preceding a font-size class with a modifier should be removed. For this tailwind-merge has the `conflictingClassGroupModifiers` object in its config with the same shape as `conflictingClassGroups` explained in the [section above](#conflicting-class-groups). This time the key is the ID of a class group whose modifier _creates_ a conflict and the value is an array of IDs of class groups which _receive_ the conflict. ```ts const conflictingClassGroupModifiers = { 'font-size': ['leading'], } ``` ### Order-sensitive modifiers In Tailwind CSS, not all modifiers behave the same when you stack them. In most cases the order of modifiers doesn't matter. E.g. `hover:focus:bg-red-500` and `focus:hover:bg-red-500` behave the same and in the context of tailwind-merge, you'd want them both to override each other. tailwind-merge sorts the modifiers internally to be able to override classes with the same modifiers, even if they are in a different order. However, there are some modifiers where the order matters, e.g. the direct children modifier `*`. The class `*:hover:text-red-500` modifies the text color of a child if that particular child is hovered, but the class `hover:*:text-red-500` modifies the text color of all direct children if the parent is hovered. In this case, you would want tailwind-merge to preserve both classes although they have the same modifiers, just in a different order. To know which modifiers are order-sensitive, tailwind-merge has the `orderSensitiveModifiers` property in its config. `twMerge` is pre-configured with all the order-sensitive modifiers that Tailwind CSS has by default. You'll only need to configure this property if you add your own order-sensitive modifiers or change the meaning of the default order-sensitive modifiers. ### Theme In the Tailwind config you can modify your theme variable namespace to add classes with custom values. tailwind-merge follows the same naming scheme as Tailwind CSS for its theme scales: | Tailwind CSS namespace | tailwind-merge theme key | | ---------------------- | ------------------------ | | `--color-*` | `color` | | `--font-*` | `font` | | `--text-*` | `text` | | `--font-weight-*` | `font-weight` | | `--tracking-*` | `tracking` | | `--leading-*` | `leading` | | `--breakpoint-*` | `breakpoint` | | `--container-*` | `container` | | `--spacing-*` | `spacing` | | `--radius-*` | `radius` | | `--shadow-*` | `shadow` | | `--inset-shadow-*` | `inset-shadow` | | `--drop-shadow-*` | `drop-shadow` | | `--blur-*` | `blur` | | `--perspective-*` | `perspective` | | `--aspect-*` | `aspect` | | `--ease-*` | `ease` | | `--animate-*` | `animate` | If you modified one of the theme namespaces in your Tailwind config, you need to add the variable names to the `theme` object in tailwind-merge as well so that tailwind-merge knows about them. E.g. let's say you added the variable `--text-huge-af: 100px` to your Tailwind config which enables classes like `text-huge-af`. To make sure that tailwind-merge merges these classes correctly, you need to configure tailwind-merge like this: ```ts import { extendTailwindMerge } from 'tailwind-merge' const twMerge = extendTailwindMerge({ extend: { theme: { // ↓ `text` is the key of the namespace `--text-*` // ↓ `huge-af` is the variable name in the namespace text: ['huge-af'], }, }, }) ``` ### Extending the tailwind-merge config If you only need to slightly modify the default tailwind-merge config, [`extendTailwindMerge`](./api-reference.md#extendtailwindmerge) is the easiest way to extend the config. You provide it a `configExtension` object which gets [merged](./api-reference.md#mergeconfigs) with the default config. Therefore, all keys here are optional. ```ts import { extendTailwindMerge } from 'tailwind-merge' const twMerge = extendTailwindMerge<'foo' | 'bar' | 'baz'>({ // ↓ Override elements from the default config // It has the same shape as the `extend` object, so we're going to skip it here. override: {}, // ↓ Extend values from the default config extend: { // ↓ Add values to existing theme scale or create a new one theme: { spacing: ['sm', 'md', 'lg'], }, // ↓ Add values to existing class groups or define new ones classGroups: { foo: ['foo', 'foo-2', { 'bar-baz': ['', '1', '2'] }], bar: [{ qux: ['auto', (value) => Number(value) >= 1000] }], baz: ['baz-sm', 'baz-md', 'baz-lg'], }, // ↓ Here you can define additional conflicts across class groups conflictingClassGroups: { foo: ['bar'], }, // ↓ Define conflicts between postfix modifiers and class groups conflictingClassGroupModifiers: { baz: ['bar'], }, // ↓ Define order-sensitive modifiers orderSensitiveModifiers: ['my-order-sensitive-modifier'], }, }) ``` > [!Note] > The function `extendTailwindMerge` computes a large data structure based on the config passed to it. I recommend to call it only once and store the result in a top-level variable instead of calling it inline within another repeatedly called function. ### TypeScript types for `extendTailwindMerge` If you're using TypeScript, you'll notice that all the places in the `configExtension` object where class group IDs and theme group IDs are used are typed strictly so that you're only allowed to use IDs which are defined in the default config of tailwind-merge. The strict TypeScript types are meant as a safety net to prevent you from making typos in your config and to give you auto-completion for IDs. In case you want to define new class groups or theme objects, you need to add the IDs as a generic argument to `extendTailwindMerge`: ```ts import { extendTailwindMerge } from 'tailwind-merge' type AdditionalClassGroupIDs = 'class-a' | 'class-b' type AdditionalThemeGroupIDs = 'theme-c' | 'theme-d' const twMerge = extendTailwindMerge< // ↓ Add additional class group IDs as the first generic argument AdditionalClassGroupIDs, // ↓ Optionally, you can add additional theme group IDs as the second generic argument AdditionalThemeGroupIDs >({ extend: { theme: { // ↓ Works because we defined 'theme-c' as additional theme group ID 'theme-c': […], // ↓ Works because we defined 'theme-d' as additional theme group ID 'theme-d': […], }, classGroups: { // ↓ Works because it's part of the default additional class group IDs shadow: […], // ↓ Works because we defined 'class-a' as additional class group ID 'class-a': […], // ↓ Works because we defined 'class-b' as additional class group ID 'class-b': […], // ↓ Type […] is not assignable to type […]. // Object literal may only specify known properties, and ''not-defined'' does not exist in type […]. ts(2322) 'not-defined': [], }, }, }) ``` If those strict TypeScript types for IDs are too restrictive for you, you can also allow any strings as IDs by using the `string` type as generic argument. ```ts import { extendTailwindMerge } from 'tailwind-merge' const twMerge = extendTailwindMerge(/* anything goes here */) ``` ### Using completely custom tailwind-merge config If you need to modify the tailwind-merge config and need more control than [`extendTailwindMerge`](./api-reference.md#extendtailwindmerge) gives you or don't want to use the default config (and tree-shake it out of your bundle), you can use [`createTailwindMerge`](./api-reference.md#createtailwindmerge). The function takes a callback which returns the config you want to use and returns a custom `twMerge` function. ```ts import { createTailwindMerge } from 'tailwind-merge' const twMerge = createTailwindMerge(() => ({ cacheSize: 500, theme: {}, classGroups: { foo: ['foo', 'foo-2', { 'bar-baz': ['', '1', '2'] }], bar: [{ qux: ['auto', (value) => Number(value) >= 1000] }], baz: ['baz-sm', 'baz-md', 'baz-lg'], }, conflictingClassGroups: { foo: ['bar'], }, conflictingClassGroupModifiers: { baz: ['bar'], }, orderSensitiveModifiers: [], })) ``` > [!Note] > The function `createTailwindMerge` computes a large data structure based on the config passed to it. I recommend to call it only once and store the result in a top-level variable instead of calling it inline within another repeatedly called function. The callback passed to `createTailwindMerge` will be called when `twMerge` is called the first time, so you don't need to worry about the computations in it affecting app startup performance in case you aren't using tailwind-merge at app startup. ### Using tailwind-merge plugins You can use both [`extendTailwindMerge`](./api-reference.md#extendtailwindmerge) and [`createTailwindMerge`](./api-reference.md#createtailwindmerge) with third-party plugins. Just add them as arguments after your config. ```ts import { extendTailwindMerge, createTailwindMerge } from 'tailwind-merge' import { withMagic } from 'tailwind-merge-magic-plugin' import { withMoreMagic } from 'tailwind-merge-more-magic-plugin' // With your own config const twMerge1 = extendTailwindMerge({ … }, withMagic, withMoreMagic) // Only using plugin with default config const twMerge2 = extendTailwindMerge(withMagic, withMoreMagic) // Using `createTailwindMerge` const twMerge3 = createTailwindMerge(() => ({ … }), withMagic, withMoreMagic) ``` --- Next: [Recipes](./recipes.md) Previous: [Limitations](./limitations.md) [Back to overview](./README.md) node-tailwind-merge-3.3.1/docs/contributing.md000066400000000000000000000003231502210756000213260ustar00rootroot00000000000000# Contributing Please see [CONTRIBUTING](../.github/CONTRIBUTING.md) for details. --- Next: [Similar packages](./similar-packages.md) Previous: [Versioning](./versioning.md) [Back to overview](./README.md) node-tailwind-merge-3.3.1/docs/features.md000066400000000000000000000145541502210756000204500ustar00rootroot00000000000000# Features ## Merging behavior tailwind-merge is built to be intuitive. It follows a set of rules to determine which class wins when there are conflicts. Here is a brief overview of its conflict resolution. ### Last conflicting class wins ```ts twMerge('p-5 p-2 p-4') // → 'p-4' ``` ### Allows refinements ```ts twMerge('p-3 px-5') // → 'p-3 px-5' twMerge('inset-x-4 right-4') // → 'inset-x-4 right-4' ``` ### Resolves non-trivial conflicts ```ts twMerge('inset-x-px -inset-1') // → '-inset-1' twMerge('bottom-auto inset-y-6') // → 'inset-y-6' twMerge('inline block') // → 'block' ``` ### Supports modifiers and stacked modifiers ```ts twMerge('p-2 hover:p-4') // → 'p-2 hover:p-4' twMerge('hover:p-2 hover:p-4') // → 'hover:p-4' twMerge('hover:focus:p-2 focus:hover:p-4') // → 'focus:hover:p-4' ``` tailwind-merge knows when the order of standard modifiers matters and when not and resolves conflicts accordingly. ### Supports arbitrary values ```ts twMerge('bg-black bg-(--my-color) bg-[color:var(--mystery-var)]') // → 'bg-[color:var(--mystery-var)]' twMerge('grid-cols-[1fr,auto] grid-cols-2') // → 'grid-cols-2' ``` > [!Note] > Labels necessary in ambiguous cases > > When using arbitrary values in ambiguous classes like `text-[calc(var(--rebecca)-1rem)]` tailwind-merge looks at the arbitrary value for clues to determine what type of class it is. In this case, like in most ambiguous classes, it would try to figure out whether `calc(var(--rebecca)-1rem)` is a length (making it a font-size class) or a color (making it a text-color class). For lengths it takes clues into account like the presence of the `calc()` function or a digit followed by a length unit like `1rem`. > > But it isn't always possible to figure out the type by looking at the arbitrary value. E.g. in the class `text-[theme(myCustomScale.rebecca)]` tailwind-merge can't know the type of the arbitrary value and will default to a text-color class. To make tailwind-merge understand the correct type of the arbitrary value in those cases, you can use CSS data type labels [which are used by Tailwind CSS to disambiguate classes](https://tailwindcss.com/docs/adding-custom-styles#resolving-ambiguities): `text-[length:theme(myCustomScale.rebecca)]`. ### Supports arbitrary properties ```ts twMerge('[mask-type:luminance] [mask-type:alpha]') // → '[mask-type:alpha]' twMerge('[--scroll-offset:56px] lg:[--scroll-offset:44px]') // → '[--scroll-offset:56px] lg:[--scroll-offset:44px]' // Don't do this! twMerge('[padding:1rem] p-8') // → '[padding:1rem] p-8' ``` > [!Note] > tailwind-merge does not resolve conflicts between arbitrary properties and their matching Tailwind classes to keep the bundle size small. ### Supports arbitrary variants ```ts twMerge('[&:nth-child(3)]:py-0 [&:nth-child(3)]:py-4') // → '[&:nth-child(3)]:py-4' twMerge('dark:hover:[&:nth-child(3)]:py-0 hover:dark:[&:nth-child(3)]:py-4') // → 'hover:dark:[&:nth-child(3)]:py-4' // Don't do this! twMerge('[&:focus]:ring focus:ring-4') // → '[&:focus]:ring focus:ring-4' ``` > [!Note] > Similarly to arbitrary properties, tailwind-merge does not resolve conflicts between arbitrary variants and their matching predefined modifiers for bundle size reasons. The order of standard modifiers before and after an arbitrary variant in isolation (all modifiers before are one group, all modifiers after are another group) does not matter for tailwind-merge. However, it does matter whether a standard modifier is before or after an arbitrary variant both for Tailwind CSS and tailwind-merge because the resulting CSS selectors are different. ### Supports important modifier ```ts twMerge('p-3! p-4! p-5') // → 'p-4! p-5' twMerge('right-2! -inset-x-1!') // → '-inset-x-1!' ``` ### Supports postfix modifiers ```ts twMerge('text-sm leading-6 text-lg/7') // → 'text-lg/7' ``` ### Preserves non-Tailwind classes ```ts twMerge('p-5 p-2 my-non-tailwind-class p-4') // → 'my-non-tailwind-class p-4' ``` ### Supports custom colors out of the box ```ts twMerge('text-red text-secret-sauce') // → 'text-secret-sauce' ``` ## Composition tailwind-merge has some features that simplify composing class strings together. Those allow you to compose classes like in [clsx](https://www.npmjs.com/package/clsx), [classnames](https://www.npmjs.com/package/classnames) or [classix](https://www.npmjs.com/package/classix). ### Supports multiple arguments ```ts twMerge('some-class', 'another-class yet-another-class', 'so-many-classes') // → 'some-class another-class yet-another-class so-many-classes' ``` ### Supports conditional classes ```ts twMerge('some-class', undefined, null, false, 0) // → 'some-class' twMerge('my-class', false && 'not-this', null && 'also-not-this', true && 'but-this') // → 'my-class but-this' ``` ### Supports arrays and nested arrays ```ts twMerge('some-class', [undefined, ['another-class', false]], ['third-class']) // → 'some-class another-class third-class' twMerge('hi', true && ['hello', ['hey', false]], false && ['bye']) // → 'hi hello hey' ``` Why no object support? [Read here](https://github.com/dcastil/tailwind-merge/discussions/137#discussioncomment-3481605). ## Performance tailwind-merge is optimized for speed when running in the browser. This includes the speed of loading the code and the speed of running the code. ### Results are cached Results get cached by default, so you don't need to worry about wasteful re-renders. The library uses a computationally lightweight [LRU cache]() which stores up to 500 different results by default. The cache is applied after all arguments are [joined](./api-reference.md#twjoin) together to a single string. This means that if you call `twMerge` repeatedly with different arguments that result in the same string when joined, the cache will be hit. The cache size can be modified or opt-out of by using [`extendTailwindMerge`](./api-reference.md#extendtailwindmerge). ### Data structures are reused between calls Expensive computations happen upfront so that `twMerge` calls without a cache hit stay fast. ### Lazy initialization The initial computations are called lazily on the first call to `twMerge` to prevent it from impacting app startup performance if it isn't used initially. --- Next: [Limitations](./limitations.md) Previous: [What is it for](./what-is-it-for.md) [Back to overview](./README.md) node-tailwind-merge-3.3.1/docs/limitations.md000066400000000000000000000027461502210756000211660ustar00rootroot00000000000000# Limitations ## Don't use classes that look like Tailwind classes but apply different styles tailwind-merge applies some heuristics to detect the type of a class even if that particular class does not exist in the default Tailwind config. E.g. the class `text-1000xl` does not exist in Tailwind CSS by default but is treated like a `font-size` class in tailwind-merge because it starts with `text-` followed by an optional number and a T-shirt size, like all the other `font-size` classes. This behavior has the advantage that you're less likely to need to configure tailwind-merge if you're only changing or extending some scales in your Tailwind config. But it also means that tailwind-merge treats classes that look like Tailwind classes as Tailwind classes although they might not be defined in your Tailwind config. ## You need to use label in arbitrary `background-position` and `background-size` classes tailwind-merge detects the type of class by parsing the class name. When using a class like `bg-[30%_30%]`, tailwind-merge can't know whether the class is a `background-position` or `background-size` class. Therefore it is necessary to always prepend arbitrary values of `background-position` classes with the label `position:` as in `bg-[position:30%_30%]`. The same applies to `background-size` classes which need to be prepended with `length:`, `size:` or `percentage:`. --- Next: [Configuration](./configuration.md) Previous: [Features](./features.md) [Back to overview](./README.md) node-tailwind-merge-3.3.1/docs/recipes.md000066400000000000000000000105221502210756000202530ustar00rootroot00000000000000# Recipes How to configure tailwind-merge with some common patterns. ## Adding custom scale from Tailwind config to tailwind-merge config > I have a custom shadow scale with the keys 100, 200 and 300 configured in Tailwind. How do I make tailwind-merge resolve conflicts among those? We'll be able to do this by creating a custom `twMerge` function with [`extendTailwindMerge`](./api-reference.md#extendtailwindmerge). First, we need to know whether we want to override or extend the default scale. Let's say we extended the default config by adding the CSS variable `--shadow-100`, `--shadow-200` and `--shadow-300` into the `@theme` layer, meaning that the default variables like `--shadow-sm` stay the same. Then we check whether our particular theme scale is included in tailwind-merge's theme config object [here](./configuration.md#theme). Because tailwind-merge supports Tailwind's `shadow` theme scale, we can add it to the tailwind-merge config like this: ```js import { extendTailwindMerge } from 'tailwind-merge' const twMerge = extendTailwindMerge({ extend: { theme: { // We only need to define the custom scale values without the `shadow-` prefix when adding them to the theme object shadow: ['100', '200', '300'], }, }, }) ``` In the hypothetical case of the `shadow` theme scale not being supported in tailwind-merge, we would need to check out the [default config of tailwind-merge](../src/lib/default-config.ts) and search for the class group ID of the box shadow scale. After a quick search we would find that tailwind-merge is using the key `shadow` for that group. We could add our custom classes to that group like this: ```js import { extendTailwindMerge } from 'tailwind-merge' const twMerge = extendTailwindMerge({ extend: { classGroups: { // In class groups we always need to define the entire class name like `shadow-100`, `shadow-200` and `shadow-300` // `{ shadow: ['100', '200', '300'] }` is a short-hand syntax for `'shadow-100', 'shadow-200', 'shadow-300'` shadow: [{ shadow: ['100', '200', '300'] }], }, }, }) ``` Note that by using the `extend` object we're only adding our custom classes to the existing ones in the config, so `twMerge('shadow-200 shadow-lg')` will return the string `shadow-lg`. If we want to override the class instead, we need to use the `override` object instead. ## Extracting classes with Tailwind's [`@apply`](https://tailwindcss.com/docs/reusing-styles#extracting-classes-with-apply) > How do I make tailwind-merge resolve conflicts with a custom class created with `@apply`? > > ```css > .btn-primary { > @apply py-2 px-4 bg-blue-500 text-white rounded-lg hover:bg-blue-700; > } > ``` I don't recommend using Tailwind's `@apply` directive for classes that might get processed with tailwind-merge. tailwind-merge would need to be configured so that it knows about which classes `.btn-primary` is in conflict with. This means: If someone adds another Tailwind class to the `@apply` directive, the tailwind-merge config would need to get modified accordingly, keeping it in sync with the written CSS. This easy-to-miss dependency is fragile and can lead to bugs with incorrect merging behavior. Instead of creating custom CSS classes, I recommend keeping the collection of Tailwind classes in a string variable in JavaScript and access it whenever you want to apply those styles. This way you can reuse the collection of styles but don't need to touch the tailwind-merge config. ```jsx // React components with JSX syntax used in this example import { twMerge } from 'tailwind-merge' const BTN_PRIMARY_CLASSNAMES = 'py-2 px-4 bg-blue-500 text-white rounded-lg hover:bg-blue-700' function ButtonPrimary(props) { return ) } function Button({ className ...props }) { return