be-hive 0.0.78 → 0.0.80

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/IDMonitor.js ADDED
@@ -0,0 +1,31 @@
1
+ export class IDMonitor {
2
+ instance;
3
+ #mut;
4
+ constructor(instance) {
5
+ this.instance = instance;
6
+ const config = { childList: true };
7
+ instance.querySelectorAll('*').forEach(item => {
8
+ const { id } = item;
9
+ if (id) {
10
+ instance.define(item, false);
11
+ }
12
+ });
13
+ this.#mut = new MutationObserver((mutationList) => {
14
+ for (const mutation of mutationList) {
15
+ const { addedNodes } = mutation;
16
+ if (addedNodes !== undefined) {
17
+ for (const addedNode of addedNodes) {
18
+ const { id } = addedNode;
19
+ if (id) {
20
+ instance.define(addedNode, false);
21
+ }
22
+ }
23
+ }
24
+ }
25
+ });
26
+ this.#mut.observe(instance, config);
27
+ }
28
+ dispose() {
29
+ this.#mut.disconnect();
30
+ }
31
+ }
package/IDMonitor.ts ADDED
@@ -0,0 +1,31 @@
1
+ import {BeHive} from './be-hive.js';
2
+ import { IHasID } from './types.js';
3
+ export class IDMonitor{
4
+ #mut: MutationObserver;
5
+ constructor(public instance: BeHive){
6
+ const config: MutationObserverInit = { childList: true};
7
+ instance.querySelectorAll('*').forEach(item => {
8
+ const {id} = item;
9
+ if(id){
10
+ instance.define(item, false);
11
+ }
12
+ })
13
+ this.#mut = new MutationObserver((mutationList: MutationRecord[]) => {
14
+ for(const mutation of mutationList){
15
+ const {addedNodes} = mutation;
16
+ if(addedNodes !== undefined){
17
+ for(const addedNode of addedNodes){
18
+ const {id} = addedNode as any as IHasID;
19
+ if(id){
20
+ instance.define(addedNode as any as IHasID, false);
21
+ }
22
+ }
23
+ }
24
+ }
25
+ });
26
+ this.#mut.observe(instance, config);
27
+ }
28
+ dispose(){
29
+ this.#mut.disconnect();
30
+ }
31
+ }
package/README.md CHANGED
@@ -70,6 +70,37 @@ If one Shadow DOM blocks an inherited behivior, child Shadow DOMs can bring it b
70
70
  }'></be-hive>
71
71
  ```
72
72
 
73
+ ## Scoped templates [TODO]
74
+
75
+ be-hive can also manage "scoped templates" -- templates contained inside be-hive elements in higher up ShadowDOM can "cascade down".
76
+
77
+ ```html
78
+ <my-element>
79
+ #shadow
80
+ <be-hive>
81
+ <template id=open-menu>
82
+ ...
83
+ </template>
84
+ </be-hive>
85
+ <my-child-element>
86
+ <be-hive>
87
+ </be-hive>
88
+ </my-child-element>
89
+ </my-element>
90
+ ```
91
+
92
+ from within my-child-element:
93
+
94
+ ```JavaScript
95
+ const openMenuTempl = await this.querySelector('be-hive').whenDefined('open-menu');
96
+ ```
97
+
98
+ Can also programmatically register template:
99
+
100
+ ```JavaScript
101
+ this.querySelector('be-hive').define(templ);
102
+ ```
103
+
73
104
  ## API
74
105
 
75
106
 
package/be-hive.js CHANGED
@@ -1,10 +1,12 @@
1
1
  export class BeHive extends HTMLElement {
2
+ #monitor;
2
3
  constructor() {
3
4
  super();
4
5
  this.registeredBehaviors = {};
5
- this.hidden = true;
6
+ this.refs = {};
6
7
  }
7
- connectedCallback() {
8
+ async connectedCallback() {
9
+ this.hidden = true;
8
10
  const overridesAttr = this.getAttribute('overrides');
9
11
  if (overridesAttr !== null) {
10
12
  this.overrides = JSON.parse(overridesAttr);
@@ -13,6 +15,13 @@ export class BeHive extends HTMLElement {
13
15
  this.overrides = {};
14
16
  }
15
17
  this.#getInheritedBehaviors();
18
+ const { IDMonitor } = await import('./IDMonitor.js');
19
+ this.#monitor = new IDMonitor(this);
20
+ }
21
+ disconnectedCallback() {
22
+ if (this.#monitor !== undefined) {
23
+ this.#monitor.dispose();
24
+ }
16
25
  }
17
26
  #getInheritedBehaviors() {
18
27
  const rn = this.getRootNode();
@@ -22,13 +31,19 @@ export class BeHive extends HTMLElement {
22
31
  const parentShadowRealm = host.getRootNode();
23
32
  const parentBeHiveInstance = parentShadowRealm.querySelector('be-hive');
24
33
  if (parentBeHiveInstance !== null) {
25
- const { registeredBehaviors } = parentBeHiveInstance;
34
+ const { registeredBehaviors, refs } = parentBeHiveInstance;
26
35
  for (const key in registeredBehaviors) {
27
36
  this.register(registeredBehaviors[key]);
28
37
  }
29
38
  parentBeHiveInstance.addEventListener('latest-behavior-changed', (e) => {
30
39
  this.register(e.detail.value);
31
40
  });
41
+ for (const id in refs) {
42
+ this.define(refs[id], true);
43
+ }
44
+ parentBeHiveInstance.addEventListener('new-ref', (e) => {
45
+ this.define(e.detail.value, true);
46
+ });
32
47
  }
33
48
  }
34
49
  register(parentInstance) {
@@ -75,6 +90,35 @@ export class BeHive extends HTMLElement {
75
90
  //this.latestBehaviors = [...this.latestBehaviors, newRegisteredBehavior];
76
91
  return newBehaviorEl;
77
92
  }
93
+ define(ref, noReplace) {
94
+ if (noReplace) {
95
+ if (this.refs[ref.id] !== undefined)
96
+ return;
97
+ }
98
+ this.refs[ref.id] = ref;
99
+ this.dispatchEvent(new CustomEvent('new-ref', {
100
+ detail: {
101
+ value: ref,
102
+ }
103
+ }));
104
+ }
105
+ get(id) {
106
+ return this.refs[id];
107
+ }
108
+ whenDefined(id) {
109
+ return new Promise(resolve => {
110
+ const ref = this.get(id);
111
+ if (ref !== undefined) {
112
+ resolve(ref);
113
+ return;
114
+ }
115
+ this.addEventListener('new-ref', e => {
116
+ const ref = e.detail.value;
117
+ if (ref.id === id)
118
+ resolve(ref);
119
+ }, { once: true });
120
+ });
121
+ }
78
122
  }
79
123
  if (!customElements.get('be-hive')) {
80
124
  customElements.define('be-hive', BeHive);
package/be-hive.ts CHANGED
@@ -1,19 +1,30 @@
1
- import {BeHiveProps, BeHiveActions, BehaviorKeys} from './types';
1
+ import {BeHiveProps, BeHiveActions, BehaviorKeys, IHasID, IDisposable} from './types';
2
2
  export class BeHive extends HTMLElement{
3
+
4
+ #monitor?: IDisposable;
3
5
  constructor(){
4
6
  super();
5
7
  this.registeredBehaviors = {};
6
- this.hidden = true;
8
+ this.refs = {};
9
+
7
10
  }
8
- connectedCallback(){
11
+ async connectedCallback(){
12
+ this.hidden = true;
9
13
  const overridesAttr = this.getAttribute('overrides');
10
14
  if(overridesAttr !== null){
11
15
  this.overrides = JSON.parse(overridesAttr);
12
16
  }else{
13
17
  this.overrides = {};
14
18
  }
15
-
16
19
  this.#getInheritedBehaviors();
20
+ const {IDMonitor} = await import('./IDMonitor.js');
21
+ this.#monitor = new IDMonitor(this);
22
+ }
23
+
24
+ disconnectedCallback(){
25
+ if(this.#monitor !== undefined){
26
+ this.#monitor.dispose();
27
+ }
17
28
  }
18
29
 
19
30
  #getInheritedBehaviors(){
@@ -23,7 +34,7 @@ export class BeHive extends HTMLElement{
23
34
  const parentShadowRealm = host.getRootNode();
24
35
  const parentBeHiveInstance = parentShadowRealm.querySelector('be-hive') as BeHiveProps & Element;
25
36
  if(parentBeHiveInstance !== null){
26
- const {registeredBehaviors} = parentBeHiveInstance;
37
+ const {registeredBehaviors, refs} = parentBeHiveInstance;
27
38
  for(const key in registeredBehaviors){
28
39
  this.register(registeredBehaviors[key]);
29
40
  }
@@ -31,6 +42,15 @@ export class BeHive extends HTMLElement{
31
42
  parentBeHiveInstance.addEventListener('latest-behavior-changed', (e: Event) => {
32
43
  this.register((<any>e).detail.value);
33
44
  });
45
+
46
+ for(const id in refs){
47
+ this.define(refs[id], true);
48
+ }
49
+
50
+ parentBeHiveInstance.addEventListener('new-ref', (e: Event) => {
51
+ this.define((<any>e).detail.value, true);
52
+ });
53
+
34
54
  }
35
55
  }
36
56
 
@@ -78,7 +98,35 @@ export class BeHive extends HTMLElement{
78
98
  return newBehaviorEl;
79
99
  }
80
100
 
101
+ define(ref: IHasID, noReplace: boolean){
102
+ if(noReplace){
103
+ if(this.refs[ref.id] !== undefined) return;
104
+ }
105
+ this.refs[ref.id] = ref;
106
+ this.dispatchEvent(new CustomEvent('new-ref', {
107
+ detail:{
108
+ value: ref,
109
+ }
110
+ }));
111
+ }
112
+
113
+ get(id: string){
114
+ return this.refs[id];
115
+ }
81
116
 
117
+ whenDefined(id: string): Promise<IHasID>{
118
+ return new Promise(resolve => {
119
+ const ref = this.get(id);
120
+ if(ref !== undefined){
121
+ resolve(ref);
122
+ return;
123
+ }
124
+ this.addEventListener('new-ref', e => {
125
+ const ref = (<any>e).detail.value as IHasID;
126
+ if(ref.id === id) resolve(ref);
127
+ }, {once: true});
128
+ });
129
+ }
82
130
  }
83
131
 
84
132
  if(!customElements.get('be-hive')){
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "be-hive",
3
- "version": "0.0.78",
3
+ "version": "0.0.80",
4
4
  "keywords": [
5
5
  "web-components",
6
6
  "web-component",
@@ -28,13 +28,13 @@
28
28
  "doc": "custom-elements-manifest analyze"
29
29
  },
30
30
  "devDependencies": {
31
- "@playwright/test": "1.27.1",
31
+ "@playwright/test": "1.29.2",
32
32
  "@skypack/package-check": "0.2.2",
33
33
  "may-it-serve": "0.0.4",
34
34
  "@custom-elements-manifest/analyzer": "0.6.4",
35
35
  "xtal-shell": "0.0.27",
36
- "be-functional": "0.0.17",
37
- "be-exportable": "0.0.50"
36
+ "be-functional": "0.0.18",
37
+ "be-exportable": "0.0.62"
38
38
  },
39
39
  "repository": {
40
40
  "type": "git",
package/types.d.ts CHANGED
@@ -15,7 +15,9 @@ export interface BeHiveProps{
15
15
  isC: boolean;
16
16
  registeredBehaviors: {[key: string]: BehaviorKeys};
17
17
  latestBehaviors: BehaviorKeys[];
18
- beSevered: boolean
18
+ refs: {[key: string]: IHasID};
19
+ beSevered: boolean;
20
+
19
21
  }
20
22
 
21
23
  export interface BeHiveActions{
@@ -27,4 +29,14 @@ export interface BeHiveActions{
27
29
 
28
30
  export interface LatestBehaviorEvent{
29
31
  value: BehaviorKeys;
30
- }
32
+ }
33
+
34
+ export interface IHasID{
35
+ id: string;
36
+ }
37
+
38
+ export interface IDisposable{
39
+ dispose(): void;
40
+ }
41
+
42
+ export type Disposable = {new(): IDisposable};