This repository has been archived by the owner on Sep 16, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
focus.aspect.ts
85 lines (69 loc) · 1.98 KB
/
focus.aspect.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
import { OnEvent, trackValue, ValueTracker } from '@proc7ts/fun-events';
import { noop } from '@proc7ts/primitives';
import { Supply } from '@proc7ts/supply';
import { builtInAspect } from '../../applied-aspect';
import { InAspect, InAspect__symbol } from '../../aspect';
import { InControl } from '../../control';
import { InElement } from '../../element.control';
/**
* @internal
*/
const InFocus__aspect: InAspect<InFocus | null> = {
applyTo<TValue>(control: InControl<TValue>): InAspect.Applied<TValue, InFocus | null> {
return builtInAspect(control, InFocus, ctrl => {
const element = ctrl.aspect(InElement);
return element && new InControlFocus(element);
});
},
};
/**
* Input focus aspect.
*
* This is a value tracker of element focus flag. Or `null` when {@link InElement} aspect is absent.
*
* @category Aspect
*/
export abstract class InFocus extends ValueTracker<boolean> {
static get [InAspect__symbol](): InAspect<InFocus | null> {
return InFocus__aspect;
}
}
/**
* @internal
*/
class InControlFocus extends InFocus {
private readonly _it: ValueTracker<boolean>;
constructor(inElement: InElement<any>) {
super();
const { element, events } = inElement;
const owner: DocumentOrShadowRoot = element.getRootNode
? (element.getRootNode() as unknown as DocumentOrShadowRoot)
: element.ownerDocument;
this._it = trackValue(owner.activeElement === element);
this.supply.needs(inElement);
events.on('focus')(() => (this._it.it = true));
events.on('blur')(() => (this._it.it = false));
this.on({
receive(ctx, newValue) {
ctx.onRecurrent(noop);
if (newValue) {
element.focus();
} else {
element.blur();
}
},
});
}
get supply(): Supply {
return this._it.supply;
}
get it(): boolean {
return this._it.it;
}
set it(value: boolean) {
this._it.it = value;
}
get on(): OnEvent<[boolean, boolean]> {
return this._it.on;
}
}