1
|
|
|
import { ClassValue, Falsy } from "../defs" |
2
|
|
|
|
3
|
|
|
type ClassNamesDirect<K extends string = string> = Record<K, ClassValue> |
4
|
|
|
// type ClassNamesToggle<K extends string = string> = Record<K, boolean> |
5
|
|
|
|
6
|
|
|
type ClassNamingContext<S extends string, U extends string> = { |
7
|
|
|
className?: undefined|string |
8
|
|
|
classnames: ClassNamesDirect<S> |
9
|
|
|
applied?: Record<U, ClassValue|boolean>[] |
10
|
|
|
} |
11
|
|
|
|
12
|
|
|
export { |
13
|
|
|
_doubleShape |
14
|
|
|
} |
15
|
|
|
|
16
|
|
|
function _doubleShape< |
17
|
|
|
// A extends {[K in Exclude<S, U>]?: boolean} | {[K in Exclude<S, U>]?: ClassValue}, |
18
|
|
|
A extends {[K in Exclude<S, U>]?: ClassValue | boolean}, |
19
|
|
|
S extends string, |
20
|
|
|
U extends string = never, |
21
|
|
|
>( |
22
|
|
|
ctx: ClassNamingContext<S, U>, |
23
|
|
|
withClassName: boolean, |
24
|
|
|
injection: undefined|string, |
25
|
|
|
...args: (Falsy | A)[] |
26
|
|
|
) { |
27
|
|
|
const {applied, classnames, className} = ctx |
28
|
|
|
//@ts-expect-error |
29
|
|
|
, nextApplied = !applied ? [] : applied.push(...args.filter(Boolean)) as Record<U | keyof A, ClassValue|boolean>[] |
30
|
|
|
|
31
|
|
|
, host = < |
32
|
|
|
// T extends {[K in Exclude<S, U | keyof A>]?: boolean} | {[K in Exclude<S, U | keyof A>]?: ClassValue} |
33
|
|
|
T extends {[K in Exclude<S, U>]?: ClassValue | boolean}, |
34
|
|
|
>( |
35
|
|
|
withClassName: boolean, |
36
|
|
|
injection: undefined|string, |
37
|
|
|
...args: (Falsy | T)[] |
38
|
|
|
) => _doubleShape( |
39
|
|
|
{classnames, className, applied: nextApplied}, |
40
|
|
|
withClassName, |
41
|
|
|
injection, |
42
|
|
|
...args |
43
|
|
|
) |
44
|
|
|
|
45
|
|
|
for (let i = args.length; i--; ) { |
46
|
|
|
const arg = args[i] |
47
|
|
|
if (!arg) { |
48
|
|
|
delete args[i] |
49
|
|
|
continue |
50
|
|
|
} |
51
|
|
|
|
52
|
|
|
const keys = Object.keys(arg) as (keyof typeof arg)[] |
53
|
|
|
for (let i = keys.length; i--;) { |
54
|
|
|
const key = keys[i] |
55
|
|
|
, v = arg[key] |
56
|
|
|
|
57
|
|
|
switch (v) { |
58
|
|
|
case undefined: |
59
|
|
|
break |
60
|
|
|
case false: |
61
|
|
|
delete keys[i] |
62
|
|
|
break |
63
|
|
|
case true: |
64
|
|
|
//@ts-expect-error |
65
|
|
|
keys[i] = classnames?.[key as unknown as S] ?? key |
66
|
|
|
break |
67
|
|
|
default: |
68
|
|
|
if (typeof v === "string") |
69
|
|
|
//@ts-expect-error |
70
|
|
|
keys[i] = v |
71
|
|
|
} |
72
|
|
|
} |
73
|
|
|
|
74
|
|
|
const chunk = keys.flat().join(" ") |
75
|
|
|
if (!chunk) |
76
|
|
|
delete args[i] |
77
|
|
|
else |
78
|
|
|
//@ts-expect-error |
79
|
|
|
args[i] = chunk |
80
|
|
|
} |
81
|
|
|
|
82
|
|
|
const calced = [ |
83
|
|
|
withClassName && className, |
84
|
|
|
injection, |
85
|
|
|
args.flat().join(" ") |
86
|
|
|
].filter(Boolean) |
87
|
|
|
.join(" ") |
88
|
|
|
|
89
|
|
|
host["className"] = calced |
90
|
|
|
|
91
|
|
|
Object.defineProperty(host, Symbol.toPrimitive, {value: () => calced}) |
92
|
|
|
|
93
|
|
|
return host |
94
|
|
|
} |