Skip to content

Commit 824f97d

Browse files
author
Andrii Kirmas
committed
Add option to propagate to nested components
1 parent f829369 commit 824f97d

File tree

3 files changed

+72
-26
lines changed

3 files changed

+72
-26
lines changed

src/ctx.test.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,4 +88,14 @@ describe(classNamingCtx.name, () => {
8888
className: "App class1 hash4"
8989
}))
9090
})
91+
92+
it("for component", () => expect(classNamingCtx(
93+
{classNames},
94+
{withClassNames: true}
95+
)(
96+
false
97+
)).toStrictEqual({
98+
className: "",
99+
classNames
100+
}))
91101
})

src/ctx.ts

Lines changed: 61 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
1-
import type { Falsy, ToggleMap, ClassValue, ClassNamer, ClassNamed } from "./defs"
1+
import type { Falsy, ToggleMap, ClassValue, ClassNamer, ClassNamed, ClassNamesMap } from "./defs"
22
import { emptize, stringifyClassNamed, truthyKeys } from "./utils"
33

4+
emptize(classNamer)
5+
6+
//TODO no `className` - no first `true`
47
interface tClassNaming<ClassKeys extends string> {
58
/**
69
* @example classes(true) === props.className
@@ -17,7 +20,7 @@ interface tClassNaming<ClassKeys extends string> {
1720
: ToggleMap<ClassKeys>
1821
) | ClassKeys | Falsy,
1922
...expressions: (ClassKeys | Falsy)[]
20-
) : ClassNamed
23+
) : ClassNamed & {classNames?: ClassNamesMap<ClassKeys>}
2124
}
2225

2326
export default classNamingCtx
@@ -27,20 +30,44 @@ export default classNamingCtx
2730
* @example const classes = classNamingCtx({className, classNames})
2831
* @example const classes = classNamingCtx({classNames})
2932
*/
30-
function classNamingCtx<ClassKeys extends string>(ctx: ClassNamer<ClassKeys>): tClassNaming<ClassKeys> {
31-
emptize(ctx.classNames)
33+
function classNamingCtx<ClassKeys extends string/*, withClassNames extends boolean = false*/>(
34+
{classNames, className}: ClassNamer<ClassKeys>,
35+
options?: ClassNamerOptions//<withClassNames>
36+
): tClassNaming<ClassKeys> {
37+
emptize(classNames)
3238

33-
return classNamer.bind(ctx) as tClassNaming<ClassKeys>
39+
return classNamer.bind({classNames, className, ...options}) as tClassNaming<ClassKeys>
3440
}
3541

42+
// type get<T, K> = K extends keyof T ? T[K] : never
43+
44+
type ClassNamerOptions<
45+
// withClassNames extends undefined|boolean = undefined|boolean
46+
> = Partial<{
47+
withClassNames: boolean //withClassNames
48+
// withSelf: boolean
49+
}>
50+
3651
function classNamer<ClassKeys extends string>(
37-
this: ClassNamer<ClassKeys>,
52+
this: ClassNamer<ClassKeys> & ClassNamerOptions,
3853
arg0: true | ToggleMap<ClassKeys> | ClassKeys,
3954
arg1?: ToggleMap<ClassKeys> | ClassKeys,
4055
...args: (ClassKeys | Falsy)[]
41-
): ClassNamed {
42-
const {className, classNames} = this
43-
const withPropagation = arg0 === true
56+
): ClassNamed
57+
& Partial<Pick<typeof this, "classNames">>
58+
// & (
59+
// [Extract<get<typeof this, "withClassNames">, true>] extends [never]
60+
// ? EmptyObject
61+
// : Pick<typeof this, "classNames">
62+
// )
63+
{
64+
const {
65+
className: _propagated,
66+
classNames,
67+
withClassNames,
68+
// withSelf
69+
} = this
70+
, withPropagation = arg0 === true
4471
, allowed: ClassKeys[] = truthyKeys(arg0 === true ? false : arg0)
4572
//@ts-expect-error
4673
.concat(truthyKeys(arg1))
@@ -51,6 +78,8 @@ function classNamer<ClassKeys extends string>(
5178
Boolean
5279
)
5380

81+
emptize(classNames)
82+
5483
for (let i = allowed.length; i--;) {
5584
const key = allowed[i]
5685
, hash: ClassValue = classNames[key]
@@ -61,20 +90,28 @@ function classNamer<ClassKeys extends string>(
6190
}
6291

6392
const allowedString = allowed.join(" ")
64-
, propagated = withPropagation && className || ""
65-
, $return = {
66-
className: `${
67-
propagated
68-
}${
69-
propagated && allowedString
70-
? " "
71-
: ""
72-
}${
73-
allowedString
74-
}`
75-
}
76-
77-
stringifyClassNamed($return)
93+
, propagated = withPropagation && _propagated || ""
94+
95+
//TODO Consider undefined|empty|never for type error
96+
, className = `${
97+
propagated
98+
}${
99+
propagated && allowedString
100+
? " "
101+
: ""
102+
}${
103+
allowedString
104+
}`
105+
78106

79-
return $return
107+
if (!withClassNames) {
108+
return stringifyClassNamed({
109+
className
110+
})
111+
} else {
112+
return stringifyClassNamed({
113+
className,
114+
classNames
115+
})
116+
}
80117
}

src/index.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
/** TBD
2-
* 1. `typeof classNaming === "function"` falls <div className={classNaming()} />
3-
* 2. <div {...{false, undefined, null}}/> falls attributes
2+
* 1. <div {...{false, undefined, null}}/> falls attributes
43
*/
54
export type { ClassNames } from "./defs"
65
import { EMPTY_OBJECT } from "./consts"

0 commit comments

Comments
 (0)