Skip to content

Commit

Permalink
#39 Remove redundant modKey. Comment delEl in favor of #30
Browse files Browse the repository at this point in the history
  • Loading branch information
Andrii Kirmas committed Mar 12, 2021
1 parent f47ce2c commit 57e0172
Show file tree
Hide file tree
Showing 6 changed files with 116 additions and 193 deletions.
6 changes: 2 additions & 4 deletions __recipes__/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,15 @@ import type {ClassHash, ReactClassNaming} from "react-classnaming"
declare module "react-classnaming" {
namespace ReactClassNaming {
interface BemOptions {
elementDelimiter: "_";
// TODO #30 elementDelimiter: "_";
modDelimiter: "-";
blockModKey: "&";
}
}
}

setOptions({
elementDelimiter: "_",
// TODO #30 elementDelimiter: "_",
modDelimiter: "-",
blockModKey: "&"
})

type CssModule = Record<
Expand Down
85 changes: 0 additions & 85 deletions __sandbox__/bem--old.ts

This file was deleted.

193 changes: 106 additions & 87 deletions __sandbox__/bem.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// import { Primitive } from "react-classnaming/ts-swiss.defs"
import type { Ever0, Extends, PartDeep } from "src/ts-swiss.types"
import type {ReactClassNaming} from "../src"
import { CssModule } from "../src/definitions.types"

it("tree2classes", () => {
Expand Down Expand Up @@ -149,50 +150,106 @@ describe("upon delimiter", () => {
})

it("query", () => {
// Can be used on #30

type Elements<
classes extends string,
b extends string,
delE extends string = "__" /*"elementDelimiter" extends keyof ReactClassNaming.BemOptions
? ReactClassNaming.BemOptions["elementDelimiter"]
: ReactClassNaming.BemOptions["$default"]["elementDelimiter"]*/,
delM extends string = "modDelimiter" extends keyof ReactClassNaming.BemOptions
? ReactClassNaming.BemOptions["modDelimiter"]
: ReactClassNaming.BemOptions["$default"]["modDelimiter"],
bModKey extends string = "$" /*"blockModKey" extends keyof ReactClassNaming.BemOptions
? ReactClassNaming.BemOptions["blockModKey"]
: ReactClassNaming.BemOptions["$default"]["blockModKey"]*/
> = classes extends `${b}${delE}${infer E}`
? Strip<E, delM>
: classes extends `${b}${delM}${string}`
? bModKey
: never

type BemQuery<
bModKey extends string,
delE extends string,
delM extends string,
classes extends string,
BE extends string,
Block extends string
> = {
[b in Block]?: boolean | (
{
[bmKey in bModKey]?: {
[
m in classes extends `${b}${delM}${infer MV}`
? MV extends `${infer M}${delM}${infer _}` ? M : MV
: never
]?: classes extends `${b}${delM}${m}${delM}${infer V}`
? false|V
: boolean
delE extends string = "__" /*"elementDelimiter" extends keyof ReactClassNaming.BemOptions
? ReactClassNaming.BemOptions["elementDelimiter"]
: ReactClassNaming.BemOptions["$default"]["elementDelimiter"]*/,
delM extends string = "modDelimiter" extends keyof ReactClassNaming.BemOptions
? ReactClassNaming.BemOptions["modDelimiter"]
: ReactClassNaming.BemOptions["$default"]["modDelimiter"],
bModKey extends string = "$" /*"blockModKey" extends keyof ReactClassNaming.BemOptions
? ReactClassNaming.BemOptions["blockModKey"]
: ReactClassNaming.BemOptions["$default"]["blockModKey"]*/
> = string extends classes ? BemInGeneral : PartDeep<{
[b in Strip<Strip<classes, delM>, delE>]: boolean
| Exclude<MVs<classes, b, bModKey>, `${string}${delM}${string}`>
| (
Extends<classes, `${b}${delE | delM}${string}`,
{
[e in Elements<classes, b>]: boolean
| Exclude<MVs<classes, b, e>, `${string}${delM}${string}`>
| (
{[m in Strip<MVs<classes, b, e>, delM>]:
false | (
Ever0<
classes extends `${b}${
e extends bModKey ? "" : `${delE}${e}`
}${delM}${m}${delM}${infer V}`
? V : never,
true
>
)
}
)
}
} & {
[e in BE extends `${b}${delE}${infer E}` ? E : never]?: boolean | {
[
m in classes extends `${b}${delE}${e}${delM}${infer M}${delM}${infer _}`
? M
: classes extends `${b}${delE}${e}${delM}${infer M}`
? M
: never
]?: classes extends `${b}${delE}${e}${delM}${m}${delM}${infer V}`
? false|V
: boolean

>
)
}>

type MVs<
classes extends string,
b extends string,
e extends string,
delE extends string = "__" /*"elementDelimiter" extends keyof ReactClassNaming.BemOptions
? ReactClassNaming.BemOptions["elementDelimiter"]
: ReactClassNaming.BemOptions["$default"]["elementDelimiter"]*/,
delM extends string = "modDelimiter" extends keyof ReactClassNaming.BemOptions
? ReactClassNaming.BemOptions["modDelimiter"]
: ReactClassNaming.BemOptions["$default"]["modDelimiter"],
bModKey extends string = "$" /*"blockModKey" extends keyof ReactClassNaming.BemOptions
? ReactClassNaming.BemOptions["blockModKey"]
: ReactClassNaming.BemOptions["$default"]["blockModKey"]*/
> = classes extends `${b}${
e extends bModKey ? "" : `${delE}${e}`
}${delM}${infer MV}` ? MV : never

type BemInGeneral = {
[block: string]: undefined | boolean | string | {
[el: string]: undefined | boolean | string
| {
[mod: string]: undefined | boolean | string
}
})
}
}
}

type BemQuerier<
ClassNames extends CssModule,
bModKey extends string = "$",
delE extends string = "__",
delM extends string = "--"
delM extends string = "--",
bModKey extends string = "$",
> =
<
// classes extends keyof ClassNames,
BE extends StripFromObj<ClassNames, delM>,
Q extends BemQuery<bModKey, delE, delM, keyof ClassNames, BE, Strip<BE, delE>>
// BE extends StripFromObj<ClassNames, delM>,
Q extends BemQuery<
keyof ClassNames,
delE,
delM,
bModKey
// BE,
// Strip<BE, delE>
>
>(arg: Q) => {[K in
{[b in keyof Q]: Q[b] extends boolean ? b : never}[keyof Q]
// | {[b in keyof Q]: Q[b] extends Primitive ? never : `${b}${delE}${keyof Q[b]}`}[keyof Q]
Expand All @@ -211,46 +268,7 @@ describe("upon delimiter", () => {
]: boolean}

//@ts-expect-error
const q: BemQuerier<ClassNames> = x => {
const $result: Record<string, undefined|boolean> = {}

for (const block in x) {
const bVal = x[block]

if (!bVal) {
//@ts-expect-error
$result[block] = bVal
continue
}

for (const el in bVal) {
//@ts-expect-error
const eVal = bVal[el]
, be = el === "$" ? block : `${block}__${el}`

if (!eVal) {
$result[be] = eVal
continue
}

$result[be] = true

for (const mod in eVal) {
const value: string|boolean = eVal[mod]
switch (typeof value) {
case "boolean":
$result[`${be}--${mod}`] = value
break
case "string":
$result[`${be}--${mod}--${value}`] = true
break
}
}
}
}

return $result
}
const q = x => x as unknown as BemQuerier<ClassNames>
, res = q({
"App": {
"Header": false,
Expand All @@ -272,24 +290,25 @@ describe("upon delimiter", () => {
})
, typeCheck: Record<string, typeof res> = {
"exact": {
//@ts-expect-error
Footer: true,
Btn: true,
App: true,
}
}

expect(res).toStrictEqual({
"App__Container": true,
"App__Container--loading": true,
"App__Container--status--error": true,
"App__Header": false,
"Btn": true,
"Btn--disabled": false,
"Btn--info--error": true,
"Btn__Icon": true,
"Btn__Icon--big": true,
"Footer": false,
})
// expect(res).toStrictEqual({
// "App__Container": true,
// "App__Container--loading": true,
// "App__Container--status--error": true,
// "App__Header": false,
// "Btn": true,
// "Btn--disabled": false,
// "Btn--info--error": true,
// "Btn__Icon": true,
// "Btn__Icon--big": true,
// "Footer": false,
// })
expect(typeCheck).toBeInstanceOf(Object)
})
})
6 changes: 2 additions & 4 deletions src/bem.core.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,8 @@ describe(bem2arr.name, () => {

describe("optioning", () => {
const defaultOpts: BemOptions = {
elementDelimiter: "__",
// TODO #30 elementDelimiter: "__",
modDelimiter: "--",
blockModKey: "$"
}

it("default", () => expect(
Expand All @@ -57,9 +56,8 @@ describe("optioning", () => {
it("set another", () => {
//TODO #29 test bem with not default options
const opts: BemOptions = {
elementDelimiter: "_",
// TODO #30 elementDelimiter: "_",
modDelimiter: "-",
blockModKey: "$"
}
setOptions(opts)

Expand Down
Loading

0 comments on commit 57e0172

Please sign in to comment.