1
|
|
|
/// <reference path="../src/global.d.ts" /> |
2
|
|
|
import type {CssIdentifiersMap as BootStrap4} from "../__typing__/bootstrap4.css" |
3
|
|
|
import type { After, Cut, Ever0, Strip, UnionToIntersection } from "../src/ts-swiss.types" |
4
|
|
|
import type { CssModule } from "definitions.types" |
5
|
|
|
|
6
|
|
|
type MergeProps<Base extends string, Result extends string> = [Result] extends [never] ? Base : [UnionToIntersection<Result>] extends [never] ? Base : Result |
7
|
|
|
|
8
|
|
|
type RootProps< |
9
|
|
|
classes extends string, |
10
|
|
|
delimiter extends string |
11
|
|
|
> = { |
12
|
|
|
[root in Strip<classes, delimiter>]: MergeProps<root, `${root}${delimiter}${Strip<Cut<classes, `${root}${delimiter}`, true>, delimiter>}`> |
13
|
|
|
}[Strip<classes, delimiter>] |
14
|
|
|
|
15
|
|
|
type MiddleProps< |
16
|
|
|
classes extends string, |
17
|
|
|
delimiter extends string |
18
|
|
|
> = { |
19
|
|
|
[root in Strip<classes, delimiter, true>]: Exclude<classes extends `${string}${delimiter}${root}` ? never : root, classes> |
20
|
|
|
}[Strip<classes, delimiter, true>] |
21
|
|
|
|
22
|
|
|
type ValuesQ< |
23
|
|
|
classes extends string, |
24
|
|
|
props extends string, |
25
|
|
|
values extends boolean|string|number, |
26
|
|
|
delimiter extends string, |
27
|
|
|
selfKey extends string |
28
|
|
|
> = ( |
29
|
|
|
false |
30
|
|
|
| values |
31
|
|
|
| {[p in props|selfKey]?: p extends selfKey ? values : After<classes, `${p}${delimiter}`>} |
32
|
|
|
| [ |
33
|
|
|
values, |
34
|
|
|
{[p in props]?: After<classes, `${p}${delimiter}`>} |
35
|
|
|
] |
36
|
|
|
) |
37
|
|
|
|
38
|
|
|
type Values< |
39
|
|
|
classes extends string, |
40
|
|
|
delimiter extends string, |
41
|
|
|
selfKey extends string |
42
|
|
|
> = ValuesQ< |
43
|
|
|
classes, |
44
|
|
|
MiddleProps<classes, delimiter>, |
45
|
|
|
Ever0<ReactClassNaming.ParseInt<Cut<classes, `${MiddleProps<classes, delimiter>}${delimiter}`>>, true>, |
46
|
|
|
delimiter, |
47
|
|
|
selfKey |
48
|
|
|
> |
49
|
|
|
|
50
|
|
|
type AtomicQuery< |
51
|
|
|
css extends CssModule, |
52
|
|
|
delimiter extends string = "delimiter" extends keyof ReactClassNaming.AtomOptions |
53
|
|
|
? ReactClassNaming.AtomOptions["delimiter"] |
54
|
|
|
: ReactClassNaming.AtomOptions["$default"]["delimiter"], |
55
|
|
|
selfKey extends string = "selfKey" extends keyof ReactClassNaming.AtomOptions |
56
|
|
|
? ReactClassNaming.AtomOptions["selfKey"] |
57
|
|
|
: ReactClassNaming.AtomOptions["$default"]["selfKey"] |
58
|
|
|
> = { |
59
|
|
|
//TODO #38 Make good values hint here and without delimiter and selfkey |
60
|
|
|
[p in RootProps<keyof css, delimiter>]?: Values<After<keyof css, `${p}${delimiter}`>, delimiter, selfKey> |
61
|
|
|
} |
62
|
|
|
|
63
|
|
|
it("atomic bootstrap4", () => { |
64
|
|
|
const check: Record<string, AtomicQuery<BootStrap4>> = { |
65
|
|
|
"1": { |
66
|
|
|
collapse: true, |
67
|
|
|
display: 1, |
68
|
|
|
"progress-bar": "animated", |
69
|
|
|
"justify-content": { |
70
|
|
|
_: "around", |
71
|
|
|
"lg": "between" |
72
|
|
|
}, |
73
|
|
|
d: ["inline", {lg: "inline-block"}] |
74
|
|
|
}, |
75
|
|
|
} |
76
|
|
|
expect(check).toBeInstanceOf(Object) |
77
|
|
|
}) |
78
|
|
|
|
79
|
|
|
it("merge values",() => { |
80
|
|
|
type Display = `${""|"lg-"|"md-"}${ |
81
|
|
|
"none" |
82
|
|
|
|`table${""|"-row"|"-cell"}` |
83
|
|
|
|"inline" |
84
|
|
|
|`${"inline-"|""}${"block"|"flex"}` |
85
|
|
|
}` |
86
|
|
|
const check: Record<string, Values<Display, "-", "_">> = { |
87
|
|
|
"1": ["block", {lg: "block"}] |
88
|
|
|
} |
89
|
|
|
expect(check).toBeInstanceOf(Object) |
90
|
|
|
}) |
91
|
|
|
|