Passed
Push — main ( e37dd6...73e52d )
by Andrii
02:03
created

index.ts ➔ classNaming   A

Complexity

Conditions 4

Size

Total Lines 52
Code Lines 23

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 23
dl 0
loc 52
rs 9.328
c 0
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
import type { CssModule } from "./defs"
2
import type {
3
  ActionsMap,
4
  ClassNamingThis,
5
  ClassNamingCall,
6
  ClassNaming,
7
  ClassNamingContext
8
} from "./index.types"
9
import {joinWithLead, resolver, wrapper} from "./core"
10
import { emptize } from "./utils"
11
import { stackedKey, defaultCtx } from "./consts"
12
13
emptize(classNaming)
14
emptize(_classNaming)
15
16
export type { ClassNames, ClassHash, ClassNamesProperty, ClassNamed } from "./defs"
17
export default classNaming
18
export {classNamesCheck} from "./check"
19
20
/**
21
 * Makes `className` string or settle context
22
 * @example
23
 *   // To set context
24
 *   const classes = classNaming({classnames, className})
25
 * 
26
 *   // Using in Components
27
 *   <div {...classNaming(...)} data-block={`${classNaming(...)}`} />
28
 *   <Component {...{
29
 *     ...classNaming(...)},
30
 *     ...classnames
31
 *   }/>
32
 * 
33
 *   // With destructed `classnames`
34
 *   classNaming(className?, {App__Container, App__Item})} />
35
 *   
36
 *   // Toggler
37
 *   classNaming(true?, {Btn_Float: true, Btn___disabled: false})
38
39
 *   // Pipe-able
40
 *   const Cell = classNaming(className), Col1 = Cell({Column_1})
41
 *   <div {...Col1({Row_1})} />
42
 */
43
44
function classNaming<
45
  //TODO #8 `extends ReactRelated`
46
  Source extends CssModule
47
>(
48
  arg0: ClassNamingContext<Source> | (string | true | ActionsMap<Source>), 
49
  arg1?: [Extract<typeof arg0, true | string>] extends [never] ? never : ActionsMap<Source>
50
) {
51
  if (arg0 !== null && typeof arg0 === "object" && "classnames" in arg0) {
52
    const {classnames, className: cn} = arg0
53
    if (classnames !== null && typeof classnames === "object") {
54
      emptize(classnames)
55
      
56
      const className = typeof cn === "string" ? cn : undefined
57
      , host: ClassNamingCall<Source> = _classNaming.bind({
58
        classnames,
59
        className,
60
        [stackedKey]: undefined
61
      })
62
63
      return wrapper(host, className)
64
    } 
65
  } 
66
67
  return _classNaming.call(
68
    defaultCtx,
69
    //@ts-expect-error TS forgets about previous `if`
70
    arg0, // as Exclude<typeof arg0, ClassNamingContext<Source>>,
71
    arg1
72
  )
73
}
74
75
function _classNaming<
76
  //TODO #8 `extends ReactRelated`
77
  Source extends CssModule
78
>(
79
  this: ClassNamingThis<Source>,
80
  arg0?: string | true | ActionsMap<Source>,
81
  arg1?: [Extract<typeof arg0, true|string>] extends [never] ? never : ActionsMap<Source>
82
): ClassNaming<Source> {
83
  const {
84
    className,
85
    classnames,
86
    [stackedKey]: preStacked,
87
  } = this
88
  , withPropagation = arg0 === true  
89
  , source = typeof arg0 === "object" ? arg0 as ActionsMap<Source>: arg1
90
  , allowed = source && resolver(classnames, source)
91
  , withInjection = typeof arg0 !== "string" ? preStacked : joinWithLead(preStacked, arg0)
92
  , stacked = joinWithLead(withInjection, allowed)
93
  , result = joinWithLead(withPropagation && className, stacked)
94
  , host: ClassNamingCall<Source> = _classNaming.bind({classnames, className, [stackedKey]: stacked})
95
96
  emptize(classnames)
97
98
  return wrapper(
99
    host,
100
    result,
101
  )
102
}   
103
104