diff --git a/README.md b/README.md index 85ccd12..924daa0 100644 --- a/README.md +++ b/README.md @@ -32,9 +32,25 @@ import classNamingBasic from "react-classnaming/basic" const {className, classnames: {class2, class3, class4, class5}} = props -
-
-
({class5})}> +
+
+``` + +#### Chained + +```tsx +const {className, classnames: { + Column_1, Column_2, + Row_1, Row_2 +}} = props +, cn1 = classNamingBasic(className, {Column_1}) +, cn2 = classNamingBasic(className, {Column_2}) + +
, +
, +
, +
, +
``` ### From css-module or simulation @@ -46,8 +62,8 @@ import css from "./some.css" // {"class1": "hash1", "class2": "hash2"} const classNaming = classNamingCtx({className: "App", classnames: css}) -
// className="App hash1" -
// className="hash2" +
// className="App hash1" +
// className="hash2" ``` ### TS generic for props @@ -103,7 +119,7 @@ const props: ClassNames<"class2"> = {"classnames": css} const {class2} = props.classnames
-
({class1, class2})} /> +
``` ### CSS module diff --git a/src/basic.spec.tsx b/src/basic.spec.tsx index c18c71c..8bee62d 100644 --- a/src/basic.spec.tsx +++ b/src/basic.spec.tsx @@ -17,7 +17,7 @@ function Root({ classnames }}/>
({App__Footer})} + className={`${classNamingBasic({App__Footer})}`} data-classname={`${classNamingBasic({App__Footer})}`} /> @@ -114,3 +114,28 @@ it("additional type check after rename", () => {
) }) + +it("chaining", () => { + const props = {className: "Cell", classnames: classNamesCheck()} + + const {className, classnames: { + Column_1, Column_2, + Row_1, Row_2 + }} = props + , cn1 = classNamingBasic(className, {Column_1}) + , cn2 = classNamingBasic(className, {Column_2}) + + expectRender( +
, +
, +
, +
, +
+ ).toSame( +
, +
, +
, +
, +
+ ) +}) diff --git a/src/basic.ts b/src/basic.ts index b815749..3aad907 100644 --- a/src/basic.ts +++ b/src/basic.ts @@ -1,27 +1,29 @@ export type { ClassNames } from "./defs" -import { dehash, wrapper } from "./core" -import type { ClassNamesMap, ClassNamed, GetClassKeys } from "./defs" +import { dehash, wrapper, joinWithLead } from "./core" +import type { ClassNamesMap, ClassNamed, GetClassKeys, ClassValue, ReactRelated } from "./defs" export default classNamingBasic /** * Makes `className` string from imported CSS - * @example
({ClassName})} /> - * @example
+ * @example
+ * @example
+ * @example const cn = classNamingBasic({C1})({C2});
*/ -function classNamingBasic( - classnames: ClassNamesMap> -): Return extends string ? string : ClassNamed +function classNamingBasic( + classnames: ClassNamesMap> +): ClassNamingChain /** * Makes `className` string from imported CSS - * @example
({ClassName})} /> - * @example
+ * @example
+ * @example
+ * @example const cn = classNamingBasic({C1})({C2});
*/ -function classNamingBasic( +function classNamingBasic( propagatedClassName: undefined|string, - classnames: ClassNamesMap> -): Return extends string ? string : ClassNamed + classnames: ClassNamesMap> +): ClassNamingChain function classNamingBasic( arg0: undefined|string|ClassNamesMap, @@ -30,24 +32,20 @@ function classNamingBasic( const classnames = typeof arg0 === "object" ? arg0 : arg1 , className = typeof arg0 === "object" ? undefined : arg0 - return _classNaming(classnames!, className, {}) + return _classNaming(classnames!, className) } -function _classNaming>( - classnames: ClassNamesMap, - className: undefined|string, - destination: T -): T & ClassNamed { - - // TODO For propagation - // $defineProperty( - // classnames, - // "toString", - // { - // value: undefined - // } - // ) - // $assign(destination, {classnames}) - - return wrapper(className, dehash(classnames), destination) +function _classNaming( + classes: ClassNamesMap, + propagate: undefined|string, +) : ClassNamingChain { + const className = joinWithLead(propagate, dehash(classes)) + , host: ClassNamingCall = classes => _classNaming(classes, className) + + return wrapper(className, [], host) +} + +type ClassNamingChain = ClassNamingCall & { + className: string } +type ClassNamingCall = (classes: Record) => ClassNamingChain \ No newline at end of file diff --git a/src/direct.test.ts b/src/direct.test.ts deleted file mode 100644 index 12f4375..0000000 --- a/src/direct.test.ts +++ /dev/null @@ -1,58 +0,0 @@ -import { dehash, joinWithLead } from "./core"; -import { ClassValue } from "./defs"; -import {stringifyClassNamed} from "./utils" - -describe(direct.name, () => { - const output = direct({class1: undefined, class2: "hash2"}) - , className = "class1 hash2" - - it("has classNames", () => expect( - {...output} - ).toStrictEqual( - {className} - )) - it("stringable", () => expect( - `${output}` - ).toBe( - className - )) - - describe("chained", () => { - const chained = output({ - class3: undefined, class4: "hash4" - }) - , nextClassName = `${className} class3 hash4` - - it("called", () => expect({ - ...chained - }).toStrictEqual({ - className: nextClassName - })) - it("called is strigable", () => expect( - `${chained}` - ).toBe( - nextClassName - )) - it("TBD call is not allow by TS on key duplication", () => expect( - //TODO //@ts-expect-error` - `${chained({class1: undefined})}` - ).toBe( - `${nextClassName} class1` - )) - }) -}) - -type ClassNamingChain = { - className: string - (classes: Record): ClassNamingChain -} - -function direct>(classes: T, propagate?: string) { - const className = joinWithLead(propagate, dehash(classes)) - , host: ClassNamingChain = classes => direct(classes, className) - - host["className"] = className - stringifyClassNamed(host) - - return host -} \ No newline at end of file diff --git a/src/versus-classnames.test.ts b/src/versus-classnames.test.ts index a904ddd..f3cacca 100644 --- a/src/versus-classnames.test.ts +++ b/src/versus-classnames.test.ts @@ -25,9 +25,9 @@ it("usage interface", () => { const {classnames: {class2}} = props - expect( - classNamingBasic({class1, class2}) - ).toStrictEqual({ + expect({ + ...classNamingBasic({class1, class2}) + }).toStrictEqual({ //@ts-expect-error `classnames` has no possibility for type hints className: classnames_default<"whatever">("class1", "class2") }) @@ -48,3 +48,4 @@ it("css module", () => expect({ ) )) +it.todo("Does `classnames` have chainable interface?")