diff --git a/src/lib/class-group-utils.ts b/src/lib/class-group-utils.ts index 23efc78..94184ae 100644 --- a/src/lib/class-group-utils.ts +++ b/src/lib/class-group-utils.ts @@ -1,10 +1,10 @@ import { + AnyClassGroupIds, + AnyConfig, + AnyThemeGroupIds, ClassGroup, ClassValidator, Config, - GenericClassGroupIds, - GenericConfig, - GenericThemeGroupIds, ThemeGetter, ThemeObject, } from './types' @@ -12,17 +12,17 @@ import { export interface ClassPartObject { nextPart: Map validators: ClassValidatorObject[] - classGroupId?: GenericClassGroupIds + classGroupId?: AnyClassGroupIds } interface ClassValidatorObject { - classGroupId: GenericClassGroupIds + classGroupId: AnyClassGroupIds validator: ClassValidator } const CLASS_PART_SEPARATOR = '-' -export const createClassGroupUtils = (config: GenericConfig) => { +export const createClassGroupUtils = (config: AnyConfig) => { const classMap = createClassMap(config) const { conflictingClassGroups, conflictingClassGroupModifiers } = config @@ -38,7 +38,7 @@ export const createClassGroupUtils = (config: GenericConfig) => { } const getConflictingClassGroupIds = ( - classGroupId: GenericClassGroupIds, + classGroupId: AnyClassGroupIds, hasPostfixModifier: boolean, ) => { const conflicts = conflictingClassGroups[classGroupId] || [] @@ -59,7 +59,7 @@ export const createClassGroupUtils = (config: GenericConfig) => { const getGroupRecursive = ( classParts: string[], classPartObject: ClassPartObject, -): GenericClassGroupIds | undefined => { +): AnyClassGroupIds | undefined => { if (classParts.length === 0) { return classPartObject.classGroupId } @@ -103,7 +103,7 @@ const getGroupIdForArbitraryProperty = (className: string) => { /** * Exported for testing only */ -export const createClassMap = (config: Config) => { +export const createClassMap = (config: Config) => { const { theme, prefix } = config const classMap: ClassPartObject = { nextPart: new Map(), @@ -123,10 +123,10 @@ export const createClassMap = (config: Config, + classGroup: ClassGroup, classPartObject: ClassPartObject, - classGroupId: GenericClassGroupIds, - theme: ThemeObject, + classGroupId: AnyClassGroupIds, + theme: ThemeObject, ) => { classGroup.forEach((classDefinition) => { if (typeof classDefinition === 'string') { @@ -187,9 +187,9 @@ const isThemeGetter = (func: ClassValidator | ThemeGetter): func is ThemeGetter (func as ThemeGetter).isThemeGetter const getPrefixedClassGroupEntries = ( - classGroupEntries: Array<[classGroupId: string, classGroup: ClassGroup]>, + classGroupEntries: Array<[classGroupId: string, classGroup: ClassGroup]>, prefix: string | undefined, -): Array<[classGroupId: string, classGroup: ClassGroup]> => { +): Array<[classGroupId: string, classGroup: ClassGroup]> => { if (!prefix) { return classGroupEntries } diff --git a/src/lib/config-utils.ts b/src/lib/config-utils.ts index 1eb9fa0..a31c092 100644 --- a/src/lib/config-utils.ts +++ b/src/lib/config-utils.ts @@ -1,11 +1,11 @@ import { createClassGroupUtils } from './class-group-utils' import { createLruCache } from './lru-cache' import { createParseClassName } from './parse-class-name' -import { GenericConfig } from './types' +import { AnyConfig } from './types' export type ConfigUtils = ReturnType -export const createConfigUtils = (config: GenericConfig) => ({ +export const createConfigUtils = (config: AnyConfig) => ({ cache: createLruCache(config.cacheSize), parseClassName: createParseClassName(config), ...createClassGroupUtils(config), diff --git a/src/lib/create-tailwind-merge.ts b/src/lib/create-tailwind-merge.ts index 2acab95..59b9538 100644 --- a/src/lib/create-tailwind-merge.ts +++ b/src/lib/create-tailwind-merge.ts @@ -1,10 +1,10 @@ import { createConfigUtils } from './config-utils' import { mergeClassList } from './merge-classlist' import { ClassNameValue, twJoin } from './tw-join' -import { GenericConfig } from './types' +import { AnyConfig } from './types' -type CreateConfigFirst = () => GenericConfig -type CreateConfigSubsequent = (config: GenericConfig) => GenericConfig +type CreateConfigFirst = () => AnyConfig +type CreateConfigSubsequent = (config: AnyConfig) => AnyConfig type TailwindMerge = (...classLists: ClassNameValue[]) => string type ConfigUtils = ReturnType @@ -20,7 +20,7 @@ export function createTailwindMerge( function initTailwindMerge(classList: string) { const config = createConfigRest.reduce( (previousConfig, createConfigCurrent) => createConfigCurrent(previousConfig), - createConfigFirst() as GenericConfig, + createConfigFirst() as AnyConfig, ) configUtils = createConfigUtils(config) diff --git a/src/lib/extend-tailwind-merge.ts b/src/lib/extend-tailwind-merge.ts index dd12f95..6d06891 100644 --- a/src/lib/extend-tailwind-merge.ts +++ b/src/lib/extend-tailwind-merge.ts @@ -1,9 +1,9 @@ import { createTailwindMerge } from './create-tailwind-merge' import { getDefaultConfig } from './default-config' import { mergeConfigs } from './merge-configs' -import { ConfigExtension, DefaultClassGroupIds, DefaultThemeGroupIds, GenericConfig } from './types' +import { AnyConfig, ConfigExtension, DefaultClassGroupIds, DefaultThemeGroupIds } from './types' -type CreateConfigSubsequent = (config: GenericConfig) => GenericConfig +type CreateConfigSubsequent = (config: AnyConfig) => AnyConfig export const extendTailwindMerge = < AdditionalClassGroupIds extends string = never, diff --git a/src/lib/merge-configs.ts b/src/lib/merge-configs.ts index f0dda49..dd28c88 100644 --- a/src/lib/merge-configs.ts +++ b/src/lib/merge-configs.ts @@ -1,11 +1,11 @@ -import { ConfigExtension, GenericConfig } from './types' +import { AnyConfig, ConfigExtension } from './types' /** * @param baseConfig Config where other config will be merged into. This object will be mutated. * @param configExtension Partial config to merge into the `baseConfig`. */ export const mergeConfigs = ( - baseConfig: GenericConfig, + baseConfig: AnyConfig, { cacheSize, prefix, diff --git a/src/lib/parse-class-name.ts b/src/lib/parse-class-name.ts index 049bb31..9fd428e 100644 --- a/src/lib/parse-class-name.ts +++ b/src/lib/parse-class-name.ts @@ -1,8 +1,8 @@ -import { GenericConfig } from './types' +import { AnyConfig } from './types' export const IMPORTANT_MODIFIER = '!' -export const createParseClassName = (config: GenericConfig) => { +export const createParseClassName = (config: AnyConfig) => { const { separator, experimentalParseClassName } = config const isSeparatorSingleCharacter = separator.length === 1 const firstSeparatorCharacter = separator[0] diff --git a/src/lib/types.ts b/src/lib/types.ts index 171191c..2fc5e42 100644 --- a/src/lib/types.ts +++ b/src/lib/types.ts @@ -1,8 +1,14 @@ +/** + * Type the tailwind-merge configuration adheres to. + */ export interface Config - extends ConfigStatic, - ConfigGroups {} + extends ConfigStaticPart, + ConfigGroupsPart {} -interface ConfigStatic { +/** + * The static part of the tailwind-merge configuration. When merging multiple configurations, the properties of this interface are always overridden. + */ +interface ConfigStaticPart { /** * Integer indicating size of LRU cache used for memoizing results. * - Cache might be up to twice as big as `cacheSize` @@ -75,7 +81,10 @@ export interface ExperimentalParsedClassName { maybePostfixModifierPosition: number | undefined } -interface ConfigGroups { +/** + * The dynamic part of the tailwind-merge configuration. When merging multiple configurations, the user can choose to either override or extend the properties of this interface. + */ +interface ConfigGroupsPart { /** * Theme scales used in classGroups. * The keys are the same as in the Tailwind config but the values are sometimes defined more broadly. @@ -109,10 +118,13 @@ interface ConfigGroups } +/** + * Type of the configuration object that can be passed to `extendTailwindMerge`. + */ export interface ConfigExtension - extends Partial { - override?: PartialPartial> - extend?: PartialPartial> + extends Partial { + override?: PartialPartial> + extend?: PartialPartial> } type PartialPartial = { @@ -131,7 +143,7 @@ type ClassDefinition = | ClassObject export type ClassValidator = (classPart: string) => boolean export interface ThemeGetter { - (theme: ThemeObject): ClassGroup + (theme: ThemeObject): ClassGroup isThemeGetter: true } type ClassObject = Record< @@ -139,10 +151,16 @@ type ClassObject = Record< readonly ClassDefinition[] > -// Hack from https://stackoverflow.com/questions/56687668/a-way-to-disable-type-argument-inference-in-generics/56688073#56688073 +/** + * Hack from https://stackoverflow.com/questions/56687668/a-way-to-disable-type-argument-inference-in-generics/56688073#56688073 + * + * Could be replaced with NoInfer utility type from TypeScript (https://www.typescriptlang.org/docs/handbook/utility-types.html#noinfertype), but that is only supported in TypeScript 5.4 or higher, so I should wait some time before using it. + */ export type NoInfer = [T][T extends any ? 0 : never] /** + * Theme group IDs included in the default configuration of tailwind-merge. + * * If you want to use a scale that is not supported in the `ThemeObject` type, * consider using `classGroups` instead of `theme`. * @@ -176,6 +194,9 @@ export type DefaultThemeGroupIds = | 'spacing' | 'translate' +/** + * Class group IDs included in the default configuration of tailwind-merge. + */ export type DefaultClassGroupIds = | 'accent' | 'align-content' @@ -458,7 +479,10 @@ export type DefaultClassGroupIds = | 'will-change' | 'z' -export type GenericClassGroupIds = string -export type GenericThemeGroupIds = string +export type AnyClassGroupIds = string +export type AnyThemeGroupIds = string -export type GenericConfig = Config +/** + * type of the tailwind-merge configuration that allows for any possible configuration. + */ +export type AnyConfig = Config