Skip to content

Commit

Permalink
Drop: Use clsx instead of @techor/one-linear
Browse files Browse the repository at this point in the history
  • Loading branch information
BenSeage committed Nov 1, 2023
1 parent c97de2f commit c0b4e39
Show file tree
Hide file tree
Showing 6 changed files with 99 additions and 90 deletions.
2 changes: 1 addition & 1 deletion packages/class-variant/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,6 @@
"react": ">= 16.8.0"
},
"dependencies": {
"@techor/one-liner": "^2.2.10"
"clsx": "^2.0.0"
}
}
162 changes: 86 additions & 76 deletions packages/class-variant/src/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import line from '@techor/one-liner'
import clsx from 'clsx'

type Param<T> = string
| string[]
Expand All @@ -21,102 +21,101 @@ function cv<T extends Record<string, string | number | boolean>>(firstParam: Tem
function cv<T extends Record<string, string | number | boolean>>(firstParam: TemplateStringsArray | Param<T>, ...params: Array<Param<T>>): ReturnType<T> {
return function getClassNames(valueByProp: T = {} as any) {
const mergedValueByProp = Object.assign({}, getClassNames['default'], valueByProp)
const isTemplateLiteral = Array.isArray(firstParam) && 'raw' in firstParam
const classesConditions: [string, Record<string, string | number | boolean>][] = []
const valuesByProp: Record<string, Record<string, string>> = {}
const classes: string[] = []
const isShowByClasses: Record<string, boolean> = {}
const classesByBooleanProp: Record<string, string> = {}
const handledParams = []
const handleParam = (param: Param<T>) => {
switch (typeof param) {
case 'object':
if (typeof param === 'object') {
if (Array.isArray(param)) {
const newClassesByCondition = param[1]
if (newClassesByCondition && typeof newClassesByCondition === 'object') {
handledParams.push(param)
if (Array.isArray(param)) {
const newClassesByCondition = param[1]
if (newClassesByCondition && typeof newClassesByCondition === 'object') {
const keys = Object.keys(newClassesByCondition)

const keys = Object.keys(newClassesByCondition)

let duplicated = false
for (const eachClassesByCondition of classesConditions) {
const entries = Object.entries(eachClassesByCondition[1])
if (
entries.length === keys.length
&& entries.every(([key, value]) => keys.includes(key) && newClassesByCondition[key] === value)
) {
duplicated = true
eachClassesByCondition[0] = param[0]
break
}
}

if (!duplicated) {
classesConditions.push(param as any)
let duplicated = false
for (const eachClassesByCondition of classesConditions) {
const entries = Object.entries(eachClassesByCondition[1])
if (
entries.length === keys.length
&& entries.every(([key, value]) => keys.includes(key) && newClassesByCondition[key] === value)
) {
duplicated = true
eachClassesByCondition[0] = param[0]
break
}
}

if (!duplicated) {
classesConditions.push(param as any)
}
} else {
const keys = Object.keys(param)
if (keys.length) {
switch (typeof param[keys[0]]) {
case 'object':
case 'string':
handledParams.push(param)

for (const eachProp of keys) {
const value = param[eachProp]
switch (typeof value) {
case 'object':
if (eachProp in valuesByProp) {
const classesByPropValue = valuesByProp[eachProp]
for (const eachPropValue in value) {
classesByPropValue[eachPropValue] = value[eachPropValue] as string
}
} else {
valuesByProp[eachProp] = value
classes.push(clsx(param))
}
} else {
const keys = Object.keys(param)
if (keys.length) {
switch (typeof param[keys[0]]) {
case 'object':
case 'boolean':
case 'string':
for (const eachProp of keys) {
const value = param[eachProp]
switch (typeof value) {
case 'object':
if (eachProp in valuesByProp) {
const classesByPropValue = valuesByProp[eachProp]
for (const eachPropValue in value) {
classesByPropValue[eachPropValue] = value[eachPropValue] as string
}
break
case 'string':
classesByBooleanProp[eachProp] = value
break
}
} else {
valuesByProp[eachProp] = value
}
break
case 'boolean':
isShowByClasses[eachProp] = value
break
case 'string':
classesByBooleanProp[eachProp] = value
break
}
break
}
} else {
handledParams.push(param)
}
}
break
}
}
}
break
case 'function':
// eslint-disable-next-line no-case-declarations
const transformedParam = param(mergedValueByProp)
if (typeof transformedParam === 'object') {
handledParams.push(param)
handleParam(transformedParam)
}
handleParam(param(mergedValueByProp))
break
case 'string':
classes.push(param)
break
}
}

if (Array.isArray(firstParam) && 'raw' in firstParam) {
handleParam(firstParam)
if (isTemplateLiteral) {
for (let i = 0; ; i++) {
const currentParams = i % 2 ? params : firstParam
const index = Math.trunc(i / 2)
if (currentParams.length <= index)
break

handleParam(currentParams[index] as any)
}
} else {
handleParam(firstParam as any)
params.forEach(handleParam)
}
for (const eachParam of params) {
handleParam(eachParam)

const classNames: string[] = []
const firstClassName = classes.filter(eachClass => eachClass).join(isTemplateLiteral ? '' : ' ')
if (firstClassName) {
classNames.push(firstClassName)
}

const classNames = [
line(
handledParams.includes(firstParam)
? ''
: firstParam,
...params.map(eachParam => handledParams.includes(eachParam)
? ''
: typeof eachParam === 'function'
? eachParam(mergedValueByProp) || ''
: eachParam)
)
]

for (const eachClassesByCondition of classesConditions) {
if (
Object.entries(eachClassesByCondition[1]).every(([prop, value]) => {
Expand All @@ -142,8 +141,19 @@ function cv<T extends Record<string, string | number | boolean>>(firstParam: Tem
classNames.push(classesByBooleanProp[eachProp])
}
}

for (const eachClasses in isShowByClasses) {
const isShow = isShowByClasses[eachClasses]
if (isShow) {
classNames.push(eachClasses)
}
}

return line(classNames)
let result = classNames.join(' ')
if (isTemplateLiteral) {
result = result.trim().replace(/\n/g, ' ').replace(/ +/g, ' ')
}
return result
}
}

Expand Down
6 changes: 3 additions & 3 deletions packages/class-variant/tests/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@ test('normal function', () => {
size: 'sm'
}

expect(normalBtn()).toBe('inline-flex rounded top:30 left:40 r:5 font:semibold bg:blue fg:white bg:blue-55:hover text:14 p:5|15')
expect(normalBtn({ intent: 'secondary', size: 'sm', color: 'red', disabled: true })).toBe('inline-flex rounded top:30 left:40 r:5 font:semibold color:red bg:white fg:slate-30 bg:slate-90:hover text:14 p:5|15 opacity:.5')
expect(normalBtn({ intent: 'primary', size: 'md', color: 'red' })).toBe('inline-flex rounded top:30 left:40 r:5 font:semibold color:red uppercase bg:blue fg:white bg:blue-55:hover text:16 p:10|25')
expect(normalBtn()).toBe('inline-flex rounded top:30 left:40 font:semibold bg:blue fg:white bg:blue-55:hover text:14 p:5|15 r:5')
expect(normalBtn({ intent: 'secondary', size: 'sm', color: 'red', disabled: true })).toBe('inline-flex rounded top:30 left:40 font:semibold color:red bg:white fg:slate-30 bg:slate-90:hover text:14 p:5|15 opacity:.5 r:5')
expect(normalBtn({ intent: 'primary', size: 'md', color: 'red' })).toBe('inline-flex rounded top:30 left:40 font:semibold color:red uppercase bg:blue fg:white bg:blue-55:hover text:16 p:10|25 r:5')
})

test('literal function', () => {
Expand Down
2 changes: 1 addition & 1 deletion packages/react/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@
"@master/css": "workspace:^",
"class-variant": "workspace:^",
"theme-service": "workspace:^",
"@techor/one-liner": "^2.2.10"
"clsx": "^2.0.0"
},
"devDependencies": {
"util": "^0.12.5"
Expand Down
4 changes: 2 additions & 2 deletions packages/react/src/styled.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { forwardRef } from 'react'
import cv from 'class-variant'
import line from '@techor/one-liner'
import clsx from 'clsx'

type baseType<E> = string
| string[]
Expand Down Expand Up @@ -163,7 +163,7 @@ function handle<K extends IntrinsicElementsKeys | React.ComponentType<any>, E ex
}

// @ts-ignore
return <Tag ref={ref} {...newProps} className={line(classNames, props.className)} />
return <Tag ref={ref} {...newProps} className={clsx(classNames, props.className)} />
}) as any as MasterExoticComponent<K, E>

component.displayName = displayName
Expand Down
13 changes: 6 additions & 7 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit c0b4e39

Please sign in to comment.