Passed
Push — main ( 3c9e73...288e05 )
by Andrii
01:55
created

src/index.ts   A

Complexity

Total Complexity 5
Complexity/F 5

Size

Lines of Code 109
Function Count 1

Duplication

Duplicated Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 66
dl 0
loc 109
rs 10
c 0
b 0
f 0
wmc 5
mnd 4
bc 4
fnc 1
bpm 4
cpm 5
noi 0

1 Function

Rating   Name   Duplication   Size   Complexity  
B index.ts ➔ classNaming 0 59 5
1
import type { ClassNamingContext, ClassNamed, ClassNamesMap, ClassHash } from "./defs"
2
import {joinWithLead, resolver, wrapper} from "./core"
3
import { emptize } from "./utils"
4
5
const stackedKey = Symbol("stacked")
6
7
emptize(classNaming)
8
9
export type { ClassNames, ClassHash, ClassNamesProperty, ClassNamed } from "./defs"
10
export default classNaming
11
export {classNamesCheck} from "./check"
12
13
/**
14
 * Makes `className` string from imported CSS
15
 * @example <div className={`${classNamingBasic({ClassName})}`} />
16
 * @example <div {...classNamingBasic({ClassName})} />
17
 * @example const cn = classNamingBasic({C1})({C2}); <div {...cn({C3})({C4})} />
18
 */
19
interface ClassNamingCall<
20
  //TODO `extends ReactRelated`
21
  Source extends ClassNamesMap
22
> {
23
/**
24
   * @example classes(true) === props.className
25
   * @example classes({class1: true, class2: false}) === "class1"
26
   * @example classes(true, {class1: true, class2: false})
27
  */
28
  (
29
    arg0?: ClassNamingContext<Source> | true | string | ActionsMap<Source>,
30
    arg1?: [Extract<typeof arg0, true|string>] extends [never]
31
    ? never 
32
    : ActionsMap<Source>
33
  ): ClassNaming<Source>
34
  // Using overloads will make error not in certain argument but on all call - 'No overload found'
35
  // (propagateClassName: true): ClassNaming<Source>
36
  // (expression: ToggleMap<Source>): ClassNaming<Source>
37
  // (propagateClassName: true, expression: ToggleMap<Source>): ClassNaming<Source>
38
}
39
40
//TODO no `className` - no first `true`
41
interface ClassNaming<Source extends ClassNamesMap> extends ClassNamed, ClassNamingCall<Source> {}
42
43
type ClassNamingThis<Source extends ClassNamesMap> = ClassNamingContext<Source> & {
44
  //TODO change to Symbol
45
  [stackedKey]: string|undefined
46
}
47
48
type ActionsMap<K extends ClassNamesMap> = {[k in keyof K]?: ClassHash|boolean}
49
// type SubMap<K extends ClassNamesMap> = {[k in keyof K]?: ClassHash}
50
// type ToggleMap<K extends ClassNamesMap> = {[k in keyof K]?: boolean}
51
52
/**
53
 * @example const classes = classNamingCtx(this.props)
54
 * @example const classes = classNamingCtx({className, classnames})
55
 * @example const classes = classNamingCtx({classnames})
56
 */
57
58
function classNaming<
59
  //TODO `extends ReactRelated`
60
  Source extends ClassNamesMap
61
>(
62
  this: void | ClassNamingThis<Source>,
63
  // arg0?: typeof this extends void ? ClassNamingContext<Source> : (true | ToggleMap<Source>),
64
  // arg1?: typeof this extends void ? never : typeof arg0 extends true ? ToggleMap<Source> : never,
65
  arg0?: ClassNamingContext<Source> | (string | true | ActionsMap<Source>),
66
  arg1?: [Extract<typeof arg0, true|string>] extends [never] ? never : ActionsMap<Source>
67
): ClassNaming<Source> {
68
  // istanbul ignore next //TODO Solve TS tricks with context
69
  const thisArg = this || {}
70
  
71
  context_assign:
72
  if (
73
    !(stackedKey in thisArg)
74
    && typeof arg0 === "object"
75
  ) {
76
    const {classnames, className} = arg0 // as ClassNamingContext<Source>
77
    if (
78
      classnames !== null && typeof classnames === "object"
79
      && (
80
        className === undefined  || typeof className === "string" 
81
      )  
82
    ) {
83
      emptize(classnames)
84
      const host: ClassNamingCall<Source> = classNaming.bind({classnames, className, [stackedKey]: undefined}) 
85
86
      return wrapper(host, className)
87
    }
88
  }
89
90
  const {
91
    className,
92
    classnames,
93
    [stackedKey]: preStacked,
94
  } = thisArg as ClassNamingThis<Source>
95
  , withPropagation = arg0 === true  
96
  , source = typeof arg0 === "object" ? arg0 as ActionsMap<Source>: arg1
97
  , allowed = source && resolver(classnames, source)
98
  , withInjection = typeof arg0 !== "string" ? preStacked : joinWithLead(preStacked, arg0)
99
  , stacked = joinWithLead(withInjection, allowed)
100
  , result = joinWithLead(withPropagation && className, stacked)
101
  , host: ClassNamingCall<Source> = classNaming.bind({classnames, className, [stackedKey]: stacked})
102
103
  classnames && emptize(classnames)
104
105
  return wrapper(
106
    host,
107
    result,
108
  )
109
}   
110
111