1
1
import { ObjectDictionary } from "@opticss/util" ;
2
- import { Style , Block , isBlock , isBlockClass , isState } from './index' ;
3
-
4
- import { BlockPath } from "../BlockSyntax" ;
5
- import { CssBlockError } from "../errors" ;
6
2
7
3
export abstract class Inheritable <
8
- Self extends Inheritable < Self , Parent , Child > ,
9
- Parent extends Inheritable < any , any , Self > | null = null ,
10
- Child extends Inheritable < any , Self , any > | null = null
4
+ Self extends Inheritable < Self , Root , Parent , Child > ,
5
+ Root extends Inheritable < any , Root , null , any > | null ,
6
+ Parent extends Inheritable < any , Root , any , Self > | null ,
7
+ Child extends Inheritable < any , Root , Self , any > | null
11
8
> {
12
9
13
10
protected _name : string ;
14
11
protected _base : Self | undefined ;
15
- public _block : Block ;
12
+ protected _root : Root | Self ;
16
13
protected _baseName : string ;
17
14
protected _parent : Parent | undefined ;
18
15
protected _children : Map < string , Child > = new Map ;
@@ -23,21 +20,26 @@ export abstract class Inheritable<
23
20
*/
24
21
protected abstract newChild ( name : string ) : Child ;
25
22
26
- // TODO: Currently only ever returns itself if is a style. Need to get it to look other things up.
27
- public lookup ( path : string | BlockPath ) : Style | undefined {
28
- path = new BlockPath ( path ) ;
29
- if ( isBlockClass ( this ) || isState ( this ) ) return this ;
30
- return undefined ;
31
- }
23
+ // // TODO: Currently only ever returns itself if is a style. Need to get it to look other things up.
24
+ // public lookup(path: string | BlockPath): Self | Child | Descendants | undefined {
25
+ // path = new BlockPath(path);
26
+ // let res: Self | Child | Descendants | null = this.asSelf();
27
+ // for (let part of path.tokens()) {
28
+ // res = res.resolveChild(part);
29
+ // if (!res) { break; }
30
+ // }
31
+ // return res ? res : undefined;
32
+ // }
32
33
33
34
/**
34
35
* Inheritable constructor
35
36
* @param name Name for this Inheritable instance.
36
37
* @param parent The parent Inheritable of this node.
37
38
*/
38
- constructor ( name : string , parent ?: Parent , ) {
39
+ constructor ( name : string , parent ?: Parent , root ?: Root ) {
39
40
this . _name = name ;
40
41
this . _parent = parent ;
42
+ this . _root = root || this . asSelf ( ) ;
41
43
}
42
44
43
45
public get name ( ) : string { return this . _name ; }
@@ -73,11 +75,8 @@ export abstract class Inheritable<
73
75
* traverse parents and return the base block object.
74
76
* @returns The base block in this container tree.
75
77
*/
76
- public get block ( ) : Block {
77
- if ( isBlock ( this ) ) { return this . _block = this ; }
78
- if ( this . _block !== undefined ) { return this . _block ; }
79
- if ( this . parent ) { return this . _block = this . parent . block ; }
80
- throw new CssBlockError ( "Tried to access `block` on an orphaned `Style`" ) ;
78
+ public get block ( ) : Root | Self {
79
+ return this . _root ;
81
80
}
82
81
83
82
setBase ( baseName : string , base : Self ) {
@@ -117,6 +116,19 @@ export abstract class Inheritable<
117
116
return state || null ;
118
117
}
119
118
119
+ // /**
120
+ // * Find the closest common ancestor Block between two Styles
121
+ // * TODO: I think there is a more efficient way to do this.
122
+ // * @param relative Style to compare ancestry with.
123
+ // * @returns The Style's common Block ancestor, or null.
124
+ // */
125
+ // commonAncestor(relative: Style<Child>): Style<Child> | null {
126
+ // let blockChain = new Set(...this.block.rootClass.resolveInheritance()); // lol
127
+ // blockChain.add(this.block.rootClass);
128
+ // let common = [relative.block.rootClass, ...relative.block.rootClass.resolveInheritance()].filter(b => blockChain.has(b));
129
+ // return common.length ? common[0] as Style<Child> : null;
130
+ // }
131
+
120
132
/**
121
133
* Given a parent that is a base class of this style, retrieve this style's
122
134
* base style from it, if it exists. This method does not traverse into base styles.
@@ -141,6 +153,10 @@ export abstract class Inheritable<
141
153
return [ ...this . _children . values ( ) ] ;
142
154
}
143
155
156
+ protected childrenMap ( ) : Map < string , Child > {
157
+ return new Map ( this . _children ) ;
158
+ }
159
+
144
160
// TODO: Cache this maybe? Convert entire model to only use hash?...
145
161
protected childrenHash ( ) : ObjectDictionary < Child > {
146
162
let out = { } ;
@@ -150,29 +166,10 @@ export abstract class Inheritable<
150
166
return out ;
151
167
}
152
168
153
- }
154
-
155
- export abstract class Source <
156
- Self extends Inheritable < Self , null , Child > ,
157
- Child extends Inheritable < Child , Self , any >
158
- > extends Inheritable < Self , null , Child > {
159
- public parent : null ;
160
- protected _children : Map < string , Child > ;
161
- }
162
-
163
- export abstract class Node <
164
- Self extends Inheritable < Self , Parent , Child > ,
165
- Parent extends Inheritable < Parent , any , Self > ,
166
- Child extends Inheritable < Child , Self , any >
167
- > extends Inheritable < Self , Parent , Child > {
168
- public parent : Parent ;
169
- protected _children : Map < string , Child > ;
170
- }
169
+ // TypeScript can't figure out that `this` is the `Self` so this private
170
+ // method casts it in a few places where it's needed.
171
+ private asSelf ( ) : Self {
172
+ return < Self > < any > this ;
173
+ }
171
174
172
- export abstract class Sink <
173
- Self extends Inheritable < Self , Parent , null > ,
174
- Parent extends Inheritable < any , any , Self >
175
- > extends Inheritable < Self , Parent , null > {
176
- public parent : Parent ;
177
- protected _children : Map < string , null > ;
178
175
}
0 commit comments