@webqit/oohtml 2.1.34 → 2.1.35

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.
Files changed (52) hide show
  1. package/.gitignore +3 -3
  2. package/LICENSE +20 -20
  3. package/README.md +733 -67
  4. package/dist/bindings-api.js +1 -1
  5. package/dist/bindings-api.js.map +3 -3
  6. package/dist/context-api.js +1 -1
  7. package/dist/context-api.js.map +3 -3
  8. package/dist/html-imports.js +1 -1
  9. package/dist/html-imports.js.map +3 -3
  10. package/dist/main.js +12 -12
  11. package/dist/main.js.map +3 -3
  12. package/dist/namespace-api.js +1 -1
  13. package/dist/namespace-api.js.map +3 -3
  14. package/dist/scoped-css.js +2 -2
  15. package/dist/scoped-css.js.map +3 -3
  16. package/dist/scoped-js.js +7 -7
  17. package/dist/scoped-js.js.map +3 -3
  18. package/package.json +76 -76
  19. package/src/bindings-api/index.js +83 -83
  20. package/src/bindings-api/targets.browser.js +10 -10
  21. package/src/context-api/HTMLContext.js +76 -157
  22. package/src/context-api/HTMLContextProvider.js +158 -0
  23. package/src/context-api/_ContextRequestEvent.js +25 -25
  24. package/src/context-api/index.js +51 -51
  25. package/src/context-api/targets.browser.js +9 -9
  26. package/src/{html-modules/HTMLExportsManager.js → html-imports/_HTMLExportsManager.js} +185 -199
  27. package/src/html-imports/_HTMLImportElement.js +211 -213
  28. package/src/{html-modules/_HTMLImportsContext.js → html-imports/_HTMLImportsProvider.js} +122 -114
  29. package/src/html-imports/index.js +197 -88
  30. package/src/html-imports/targets.browser.js +9 -9
  31. package/src/index.js +30 -32
  32. package/src/namespace-api/index.js +144 -144
  33. package/src/namespace-api/targets.browser.js +10 -10
  34. package/src/scoped-css/index.js +45 -45
  35. package/src/scoped-css/targets.browser.js +10 -10
  36. package/src/scoped-js/Compiler.js +297 -297
  37. package/src/scoped-js/index.js +112 -112
  38. package/src/scoped-js/targets.browser.js +10 -10
  39. package/src/targets.browser.js +9 -9
  40. package/src/util.js +34 -34
  41. package/test/bindings-api.test.js +42 -42
  42. package/test/imports.test.js +221 -221
  43. package/test/index.js +50 -50
  44. package/test/modules.test.js +200 -200
  45. package/test/namespace-api.test.js +51 -51
  46. package/test/scoped-css.test.js +31 -31
  47. package/test/scoped-js.test.js +29 -29
  48. package/dist/html-modules.js +0 -2
  49. package/dist/html-modules.js.map +0 -7
  50. package/src/context-api/HTMLContextManager.js +0 -77
  51. package/src/html-modules/index.js +0 -131
  52. package/src/html-modules/targets.browser.js +0 -10
@@ -1,214 +1,212 @@
1
-
2
- /**
3
- * @imports
4
- */
5
- import { HTMLContextManager } from '../context-api/index.js';
6
- import _HTMLImportsContext from '../html-modules/_HTMLImportsContext.js';
7
- import { _ } from '../util.js';
8
-
9
- /**
10
- * Creates the HTMLImportElement class.
11
- *
12
- * @param Object config
13
- *
14
- * @return HTMLImportElement
15
- */
16
- export default function( config ) {
17
- const window = this, { realdom } = window.webqit;
18
- const BaseElement = config.import.tagName.includes( '-' ) ? window.HTMLElement : class {};
19
- return class HTMLImportElement extends BaseElement {
20
-
21
- /**
22
- * @instance
23
- *
24
- * @param HTMLElement node
25
- *
26
- * @returns
27
- */
28
- static instance( node ) {
29
- if ( config.import.tagName.includes( '-' ) && ( node instanceof this ) ) return node;
30
- return _( node ).get( 'import::instance' ) || new this( node );;
31
- }
32
-
33
- /**
34
- * @constructor
35
- */
36
- constructor( ...args ) {
37
- super();
38
- // --------
39
- const el = args[ 0 ] || this;
40
- _( el ).set( 'import::instance', this );
41
- Object.defineProperty( this, 'el', { get: () => el, configurable: false } );
42
-
43
- const priv = {};
44
- Object.defineProperty( this, '#', { get: () => priv, configurable: false } );
45
- priv.slottedElements = new Set;
46
-
47
- priv.setAnchorNode = anchorNode => {
48
- priv.anchorNode = anchorNode;
49
- _( anchorNode ).set( 'anchoredNode@imports', this.el );
50
- };
51
-
52
- priv.importRequest = ( callback, signal = null ) => {
53
- const detail = priv.moduleRef && !priv.moduleRef.includes( '#' ) && !priv.moduleRef.includes( '.' ) ? `${ priv.moduleRef }#default` : priv.moduleRef;
54
- const request = _HTMLImportsContext.createRequest( { detail, live: signal && true, signal } );
55
- HTMLContextManager.instance( this.el.isConnected ? this.el.parentNode : priv.anchorNode.parentNode ).ask( request, response => {
56
- callback( ( response instanceof Set ? new Set( response ) : response ) || [] );
57
- } );
58
- };
59
-
60
- priv.hydrate = ( anchorNode, slottedElements ) => {
61
- // ----------------
62
- priv.moduleRef = ( this.el.getAttribute( config.import.attr.moduleref ) || '' ).trim();
63
- priv.setAnchorNode( anchorNode );
64
- priv.autoRestore( () => {
65
- slottedElements.forEach( slottedElement => {
66
- priv.slottedElements.add( slottedElement );
67
- _( slottedElement ).set( 'slot@imports', this.el );
68
- } );
69
- } );
70
- // ----------------
71
- priv.hydrationImportRequest = new AbortController;
72
- priv.importRequest( modules => {
73
- if ( priv.originalsRemapped ) { return this.fill( modules ); }
74
- const identifiersMap = [ ...modules ].map( module => ( { el: module, exportId: module.getAttribute( config.export.attr.exportid ) || '#default', tagName: module.tagName, } ) );
75
- slottedElements.forEach( slottedElement => {
76
- const tagName = slottedElement.tagName, exportId = slottedElement.getAttribute( config.export.attr.exportid ) || '#default';
77
- const originalsMatch = identifiersMap.filter( moduleIdentifiers => tagName === moduleIdentifiers.tagName && exportId === moduleIdentifiers.exportId );
78
- if ( originalsMatch.length !== 1 ) return;
79
- _( slottedElement ).set( 'original@imports', originalsMatch[ 0 ].el );
80
- } );
81
- priv.originalsRemapped = true;
82
- }, priv.hydrationImportRequest.signal );
83
- };
84
-
85
- priv.autoRestore = ( callback = null ) => {
86
- priv.autoRestoreRealtime?.disconnect();
87
- if ( callback ) callback();
88
- if ( !priv.slottedElements.size ) {
89
- priv.anchorNode.replaceWith( this.el );
90
- return;
91
- }
92
- const autoRestoreRealtime = realdom.realtime( window.document ).observe( [ ...priv.slottedElements ], record => {
93
- record.exits.forEach( outgoingNode => {
94
- _( outgoingNode ).delete( 'slot@imports' );
95
- priv.slottedElements.delete( outgoingNode );
96
- } );
97
- if ( !priv.slottedElements.size ) {
98
- autoRestoreRealtime.disconnect();
99
- // At this point, ignore if this is a removal involving the whole parent node
100
- if ( !record.target.isConnected ) return;
101
- priv.anchorNode.replaceWith( this.el );
102
- }
103
- }, { subtree: true, timing: 'sync', generation: 'exits' } );
104
- priv.autoRestoreRealtime = autoRestoreRealtime;
105
- };
106
-
107
- priv.connectedCallback = () => {
108
- // In case this is DOM node relocation or induced reinsertion into the DOM
109
- if ( priv.slottedElements.size ) throw new Error( `Illegal reinsertion into the DOM; import slot is not empty!` );
110
- // Totally initialize this instance?
111
- if ( !priv.anchorNode ) { priv.setAnchorNode( this.createAnchorNode() ); }
112
- if ( priv.moduleRefRealtime ) return;
113
- priv.moduleRefRealtime = realdom.realtime( this.el ).attr( config.import.attr.moduleref, ( record, { signal } ) => {
114
- priv.moduleRef = record.value;
115
- ;
116
- // Below, we ignore first restore from hydration
117
- priv.importRequest( modules => !priv.hydrationImportRequest && this.fill( modules ), signal );
118
- }, { live: true, timing: 'sync', lifecycleSignals: true } );
119
- // Must come after
120
- priv.hydrationImportRequest?.abort();
121
- priv.hydrationImportRequest = null;
122
- };
123
-
124
- priv.disconnectedCallback = () => {
125
- priv.hydrationImportRequest?.abort();
126
- priv.hydrationImportRequest = null;
127
- if ( priv.anchorNode.isConnected ) return;
128
- priv.moduleRefRealtime?.disconnect();
129
- priv.moduleRefRealtime = null;
130
- };
131
- }
132
-
133
- /**
134
- * Creates the slot's anchor node.
135
- *
136
- * @return Element
137
- */
138
- createAnchorNode() {
139
- if ( !config.isomorphic ) { return window.document.createTextNode( '' ) }
140
- return window.document.createComment( this.el.outerHTML );
141
- }
142
-
143
- /**
144
- * Fills the slot with slottableElements
145
- *
146
- * @param Iterable slottableElements
147
- *
148
- * @return void
149
- */
150
- fill( slottableElements ) {
151
- if ( Array.isArray( slottableElements ) ) { slottableElements = new Set( slottableElements ) }
152
- this[ '#' ].autoRestore( () => {
153
- this[ '#' ].slottedElements.forEach( slottedElement => {
154
- const slottedElementOriginal = _( slottedElement ).get( 'original@imports' );
155
- // If still available in source, simply leave unchanged
156
- // otherwise remove it from slot... to reflect this change
157
- if ( slottableElements.has( slottedElementOriginal ) ) {
158
- slottableElements.delete( slottedElementOriginal );
159
- } else {
160
- this[ '#' ].slottedElements.delete( slottedElement );
161
- // This removal will not be caught
162
- slottedElement.remove();
163
- }
164
- } );
165
- // Make sure anchor node is what's in place...
166
- // not the import element itslef - but all only when we have slottableElements.size
167
- if ( this.el.isConnected && slottableElements.size ) {
168
- this.el.replaceWith( this[ '#' ].anchorNode );
169
- }
170
- // Insert slottables now
171
- slottableElements.forEach( slottableElement => {
172
- // Clone each slottable element and give it a reference to its original
173
- const slottableElementClone = slottableElement.cloneNode( true );
174
- // The folllowing references must be set before adding to DODM
175
- if ( !slottableElementClone.hasAttribute( config.export.attr.exportid ) ) {
176
- slottableElementClone.toggleAttribute( config.export.attr.exportid, true );
177
- }
178
- _( slottableElementClone ).set( 'original@imports', slottableElement );
179
- _( slottableElementClone ).set( 'slot@imports', this.el );
180
- this[ '#' ].slottedElements.add( slottableElementClone );
181
- this[ '#' ].anchorNode.before( slottableElementClone );
182
- } );
183
- } );
184
- }
185
-
186
- /**
187
- * Empty slot.
188
- *
189
- * @return void
190
- */
191
- empty() { this[ '#' ].slottedElements.forEach( slottedElement => slottedElement.remove() ); }
192
-
193
- /**
194
- * Returns the slot's anchorNode.
195
- *
196
- * @return array
197
- */
198
- get anchorNode() { return this[ '#' ].anchorNode; }
199
-
200
- /**
201
- * Returns the slot's module reference, if any.
202
- *
203
- * @return string
204
- */
205
- get moduleRef() { return this[ '#' ].moduleRef; }
206
-
207
- /**
208
- * Returns the slot's slotted elements.
209
- *
210
- * @return array
211
- */
212
- get slottedElements() { return this[ '#' ].slottedElements; }
213
- }
1
+
2
+ /**
3
+ * @imports
4
+ */
5
+ import { HTMLContext } from '../context-api/index.js';
6
+ import _HTMLImportsContext from './_HTMLImportsProvider.js';
7
+ import { _ } from '../util.js';
8
+
9
+ /**
10
+ * Creates the HTMLImportElement class.
11
+ *
12
+ * @param Object config
13
+ *
14
+ * @return HTMLImportElement
15
+ */
16
+ export default function( config ) {
17
+ const window = this, { realdom } = window.webqit;
18
+ const BaseElement = config.import.tagName.includes( '-' ) ? window.HTMLElement : class {};
19
+ return class HTMLImportElement extends BaseElement {
20
+
21
+ /**
22
+ * @instance
23
+ *
24
+ * @param HTMLElement node
25
+ *
26
+ * @returns
27
+ */
28
+ static instance( node ) {
29
+ if ( config.import.tagName.includes( '-' ) && ( node instanceof this ) ) return node;
30
+ return _( node ).get( 'import::instance' ) || new this( node );;
31
+ }
32
+
33
+ /**
34
+ * @constructor
35
+ */
36
+ constructor( ...args ) {
37
+ super();
38
+ // --------
39
+ const el = args[ 0 ] || this;
40
+ _( el ).set( 'import::instance', this );
41
+ Object.defineProperty( this, 'el', { get: () => el, configurable: false } );
42
+
43
+ const priv = {};
44
+ Object.defineProperty( this, '#', { get: () => priv, configurable: false } );
45
+ priv.slottedElements = new Set;
46
+
47
+ priv.setAnchorNode = anchorNode => {
48
+ priv.anchorNode = anchorNode;
49
+ _( anchorNode ).set( 'anchoredNode@imports', this.el );
50
+ };
51
+
52
+ priv.importRequest = ( callback, signal = null ) => {
53
+ const request = _HTMLImportsContext.createRequest( { detail: priv.moduleRef, live: signal && true, signal } );
54
+ HTMLContext.instance( this.el.isConnected ? this.el.parentNode : priv.anchorNode.parentNode ).request( request, response => {
55
+ callback( ( response instanceof window.HTMLTemplateElement ? [ ...response.content.children ] : response && [ response ] ) || [] );
56
+ } );
57
+ };
58
+
59
+ priv.hydrate = ( anchorNode, slottedElements ) => {
60
+ // ----------------
61
+ priv.moduleRef = ( this.el.getAttribute( config.import.attr.moduleref ) || '' ).trim();
62
+ priv.setAnchorNode( anchorNode );
63
+ priv.autoRestore( () => {
64
+ slottedElements.forEach( slottedElement => {
65
+ priv.slottedElements.add( slottedElement );
66
+ _( slottedElement ).set( 'slot@imports', this.el );
67
+ } );
68
+ } );
69
+ // ----------------
70
+ priv.hydrationImportRequest = new AbortController;
71
+ priv.importRequest( modules => {
72
+ if ( priv.originalsRemapped ) { return this.fill( modules ); }
73
+ const identifiersMap = modules.map( module => ( { el: module, exportId: module.getAttribute( config.export.attr.exportid ), tagName: module.tagName, } ) );
74
+ slottedElements.forEach( slottedElement => {
75
+ const tagName = slottedElement.tagName, exportId = slottedElement.getAttribute( config.export.attr.exportid );
76
+ const originalsMatch = identifiersMap.filter( moduleIdentifiers => tagName === moduleIdentifiers.tagName && exportId === moduleIdentifiers.exportId );
77
+ if ( originalsMatch.length !== 1 ) return;
78
+ _( slottedElement ).set( 'original@imports', originalsMatch[ 0 ].el );
79
+ } );
80
+ priv.originalsRemapped = true;
81
+ }, priv.hydrationImportRequest.signal );
82
+ };
83
+
84
+ priv.autoRestore = ( callback = null ) => {
85
+ priv.autoRestoreRealtime?.disconnect();
86
+ if ( callback ) callback();
87
+ if ( !priv.slottedElements.size ) {
88
+ priv.anchorNode.replaceWith( this.el );
89
+ return;
90
+ }
91
+ const autoRestoreRealtime = realdom.realtime( window.document ).observe( [ ...priv.slottedElements ], record => {
92
+ record.exits.forEach( outgoingNode => {
93
+ _( outgoingNode ).delete( 'slot@imports' );
94
+ priv.slottedElements.delete( outgoingNode );
95
+ } );
96
+ if ( !priv.slottedElements.size ) {
97
+ autoRestoreRealtime.disconnect();
98
+ // At this point, ignore if this is a removal involving the whole parent node
99
+ if ( !record.target.isConnected ) return;
100
+ priv.anchorNode.replaceWith( this.el );
101
+ }
102
+ }, { subtree: true, timing: 'sync', generation: 'exits' } );
103
+ priv.autoRestoreRealtime = autoRestoreRealtime;
104
+ };
105
+
106
+ priv.connectedCallback = () => {
107
+ // In case this is DOM node relocation or induced reinsertion into the DOM
108
+ if ( priv.slottedElements.size ) throw new Error( `Illegal reinsertion into the DOM; import slot is not empty!` );
109
+ // Totally initialize this instance?
110
+ if ( !priv.anchorNode ) { priv.setAnchorNode( this.createAnchorNode() ); }
111
+ if ( priv.moduleRefRealtime ) return;
112
+ priv.moduleRefRealtime = realdom.realtime( this.el ).attr( config.import.attr.moduleref, ( record, { signal } ) => {
113
+ priv.moduleRef = record.value;
114
+ // Below, we ignore first restore from hydration
115
+ priv.importRequest( modules => !priv.hydrationImportRequest && this.fill( modules ), signal );
116
+ }, { live: true, timing: 'sync', lifecycleSignals: true } );
117
+ // Must come after
118
+ priv.hydrationImportRequest?.abort();
119
+ priv.hydrationImportRequest = null;
120
+ };
121
+
122
+ priv.disconnectedCallback = () => {
123
+ priv.hydrationImportRequest?.abort();
124
+ priv.hydrationImportRequest = null;
125
+ if ( priv.anchorNode.isConnected ) return;
126
+ priv.moduleRefRealtime?.disconnect();
127
+ priv.moduleRefRealtime = null;
128
+ };
129
+ }
130
+
131
+ /**
132
+ * Creates the slot's anchor node.
133
+ *
134
+ * @return Element
135
+ */
136
+ createAnchorNode() {
137
+ if ( !config.isomorphic ) { return window.document.createTextNode( '' ) }
138
+ return window.document.createComment( this.el.outerHTML );
139
+ }
140
+
141
+ /**
142
+ * Fills the slot with slottableElements
143
+ *
144
+ * @param Iterable slottableElements
145
+ *
146
+ * @return void
147
+ */
148
+ fill( slottableElements ) {
149
+ if ( Array.isArray( slottableElements ) ) { slottableElements = new Set( slottableElements ) }
150
+ this[ '#' ].autoRestore( () => {
151
+ this[ '#' ].slottedElements.forEach( slottedElement => {
152
+ const slottedElementOriginal = _( slottedElement ).get( 'original@imports' );
153
+ // If still available in source, simply leave unchanged
154
+ // otherwise remove it from slot... to reflect this change
155
+ if ( slottableElements.has( slottedElementOriginal ) ) {
156
+ slottableElements.delete( slottedElementOriginal );
157
+ } else {
158
+ this[ '#' ].slottedElements.delete( slottedElement );
159
+ // This removal will not be caught
160
+ slottedElement.remove();
161
+ }
162
+ } );
163
+ // Make sure anchor node is what's in place...
164
+ // not the import element itslef - but all only when we have slottableElements.size
165
+ if ( this.el.isConnected && slottableElements.size ) {
166
+ this.el.replaceWith( this[ '#' ].anchorNode );
167
+ }
168
+ // Insert slottables now
169
+ slottableElements.forEach( slottableElement => {
170
+ // Clone each slottable element and give it a reference to its original
171
+ const slottableElementClone = slottableElement.cloneNode( true );
172
+ // The folllowing references must be set before adding to DODM
173
+ if ( !slottableElementClone.hasAttribute( config.export.attr.exportid ) ) {
174
+ slottableElementClone.toggleAttribute( config.export.attr.exportid, true );
175
+ }
176
+ _( slottableElementClone ).set( 'original@imports', slottableElement );
177
+ _( slottableElementClone ).set( 'slot@imports', this.el );
178
+ this[ '#' ].slottedElements.add( slottableElementClone );
179
+ this[ '#' ].anchorNode.before( slottableElementClone );
180
+ } );
181
+ } );
182
+ }
183
+
184
+ /**
185
+ * Empty slot.
186
+ *
187
+ * @return void
188
+ */
189
+ empty() { this[ '#' ].slottedElements.forEach( slottedElement => slottedElement.remove() ); }
190
+
191
+ /**
192
+ * Returns the slot's anchorNode.
193
+ *
194
+ * @return array
195
+ */
196
+ get anchorNode() { return this[ '#' ].anchorNode; }
197
+
198
+ /**
199
+ * Returns the slot's module reference, if any.
200
+ *
201
+ * @return string
202
+ */
203
+ get moduleRef() { return this[ '#' ].moduleRef; }
204
+
205
+ /**
206
+ * Returns the slot's slotted elements.
207
+ *
208
+ * @return array
209
+ */
210
+ get slottedElements() { return this[ '#' ].slottedElements; }
211
+ }
214
212
  }