Skip to content

Commit 0c937b4

Browse files
author
Andrii Kirmas
committed
#38 Add basic atom core
1 parent 5dc5e5a commit 0c937b4

File tree

5 files changed

+114
-5
lines changed

5 files changed

+114
-5
lines changed

__sandbox__/atom.test.ts

+12-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/// <reference path="../src/global.d.ts" />
22
import type {CssIdentifiersMap as BootStrap4} from "../__typing__/bootstrap4.css"
3-
import type { Cut, Strip, UnionToIntersection } from "../src/ts-swiss.types"
3+
import type { Cut, Ever0, Strip, UnionToIntersection } from "../src/ts-swiss.types"
44

55
type After<Str extends string, Start extends string> = Str extends `${Start}${infer End}` ? End : never
66
type StrToInt<K extends string> = K extends keyof ReactClassNaming.StrToNum ? ReactClassNaming.StrToNum[K] : K
@@ -14,7 +14,7 @@ type MiddleProps<classes extends string> = {
1414
[root in Strip<classes, "-", true>]: Exclude<classes extends `${string}-${root}` ? never : root, classes>
1515
}[Strip<classes, "-", true>]
1616

17-
type ValuesQ<classes extends string, props extends string, values extends string> = (
17+
type ValuesQ<classes extends string, props extends string, values extends boolean|string> = (
1818
false
1919
| values
2020
| {[p in props|"_"]?: p extends "_" ? values : After<classes, `${p}-`>}
@@ -27,18 +27,26 @@ type ValuesQ<classes extends string, props extends string, values extends string
2727
type Values<classes extends string> = ValuesQ<
2828
classes,
2929
MiddleProps<classes>,
30-
StrToInt<Cut<classes, `${MiddleProps<classes>}-`>>
30+
Ever0<StrToInt<Cut<classes, `${MiddleProps<classes>}-`>>, true>
3131
>
3232

3333
type AtomicQuery<classes extends string> = {
34+
//TODO #38 Make good values hint here
3435
[p in RootProps<classes>]?: Values<After<classes, `${p}-`>>
3536
}
3637

3738
it("atomic bootstrap", () => {
3839
const check: Record<string, AtomicQuery<keyof BootStrap4>> = {
3940
"1": {
41+
collapse: true,
42+
display: 1,
43+
"progress-bar": "animated",
44+
"justify-content": {
45+
_: "around",
46+
"lg": "between"
47+
},
4048
d: ["inline", {lg: "inline-block"}]
41-
}
49+
},
4250
}
4351
expect(check).toBeInstanceOf(Object)
4452
})

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
},
2828
"license": "MIT",
2929
"scripts": {
30-
"dev": "npm run jest -- --collectCoverageFrom=[] --bail=false --onlyFailures --watch",
30+
"dev": "npm run jest -- --collectCoverageFrom=[] --bail=false --watch",
3131
"test": "npm run jest --",
3232
"pretest": "jest --clearCache",
3333
"build": "npm run compile",

src/atom.core.test.ts

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import { atom2arr } from "./atom.core";
2+
3+
it("demo", () => expect(atom2arr({
4+
collapse: true,
5+
display: 1,
6+
"progress-bar": "animated",
7+
"justify-content": {
8+
_: "around",
9+
lg: "between"
10+
},
11+
d: ["inline", {lg: "inline-block"}]
12+
})).toStrictEqual([
13+
"collapse",
14+
"display-1",
15+
"progress-bar-animated",
16+
"justify-content-around",
17+
"justify-content-lg-between",
18+
"d-inline",
19+
"d-lg-inline-block"
20+
]))
21+
22+
it("falsing", () => expect(atom2arr({
23+
//@ts-expect-error
24+
"null": null,
25+
"false": false,
26+
"0": 0,
27+
//@ts-expect-error
28+
"undefined": undefined,
29+
"empty": ""
30+
})).toStrictEqual([
31+
"0-0",
32+
"undefined-undefined",
33+
"empty-"
34+
]))

src/atom.core.ts

+59
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import type {AtomInGeneral} from "./atom.types"
2+
import {EMPTY_ARRAY} from "./consts.json"
3+
4+
const {isArray: $isArray} = Array
5+
6+
const selfKey = "_"
7+
, delimiter = "-"
8+
9+
export {
10+
atom2arr
11+
}
12+
13+
function atom2arr(query: AtomInGeneral) {
14+
const classes: string[] = []
15+
16+
for (const key in query) {
17+
const value = query[key]
18+
19+
if (typeof value !== "object") {
20+
const className = value2class(key, value)
21+
className && classes.push(className)
22+
continue
23+
}
24+
25+
const subValue = value2class(key, $isArray(value) ? value[0] : false)
26+
, subQuery = object2classes(key, $isArray(value) ? value[1] : value)
27+
28+
subValue && classes.push(subValue)
29+
classes.push(...subQuery)
30+
}
31+
32+
return classes
33+
}
34+
35+
function object2classes(rootKey: string, subQuery: undefined|Record<string, boolean|number|string>) {
36+
if (!subQuery)
37+
return EMPTY_ARRAY
38+
39+
const classes: string[] = []
40+
for (const key in subQuery) {
41+
const subValue = subQuery[key]
42+
, value = key === selfKey
43+
? subValue
44+
: value2class(key, subValue)
45+
value && classes.push(`${rootKey}${delimiter}${value}`)
46+
}
47+
return classes
48+
}
49+
50+
function value2class(property: string, value: boolean|number|string) {
51+
switch (value) {
52+
case false:
53+
return
54+
case true:
55+
return property
56+
default:
57+
return `${property}${delimiter}${value}`
58+
}
59+
}

src/atom.types.ts

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
export type AtomInGeneral = {
2+
[property: string]: boolean | number | string
3+
| {[record: string]: boolean | number | string}
4+
| [
5+
boolean | number | string,
6+
{[record: string]: boolean | number | string}
7+
]
8+
}

0 commit comments

Comments
 (0)