@webqit/oohtml 4.3.4 → 4.3.5
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/dist/bindings-api.js +1 -1
- package/dist/bindings-api.js.map +2 -2
- package/dist/context-api.js +1 -1
- package/dist/context-api.js.map +2 -2
- package/dist/data-binding.js +1 -1
- package/dist/data-binding.js.map +2 -2
- package/dist/html-imports.js +1 -1
- package/dist/html-imports.js.map +2 -2
- package/dist/main.js +12 -12
- package/dist/main.js.map +2 -2
- package/dist/main.lite.js +13 -13
- package/dist/main.lite.js.map +2 -2
- package/dist/namespaced-html.js +1 -1
- package/dist/namespaced-html.js.map +2 -2
- package/dist/scoped-css.js +3 -3
- package/dist/scoped-css.js.map +2 -2
- package/package.json +1 -1
- package/src/bindings-api/index.js +83 -20
- package/src/context-api/DOMContext.js +1 -0
- package/src/context-api/DOMContexts.js +2 -27
- package/src/context-api/index.js +31 -0
- package/src/data-binding/index.js +1 -1
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* @imports
|
|
4
4
|
*/
|
|
5
5
|
import DOMBindingsContext from './DOMBindingsContext.js';
|
|
6
|
-
import { _, _init } from '../util.js';
|
|
6
|
+
import { _, _init, _splitOuter } from '../util.js';
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* @init
|
|
@@ -17,6 +17,7 @@ export default function init( $config = {} ) {
|
|
|
17
17
|
} );
|
|
18
18
|
window.webqit.DOMBindingsContext = DOMBindingsContext;
|
|
19
19
|
exposeAPIs.call( window, config );
|
|
20
|
+
realtime.call(window, config);
|
|
20
21
|
}
|
|
21
22
|
|
|
22
23
|
/**
|
|
@@ -31,23 +32,27 @@ function getBindings( config, node ) {
|
|
|
31
32
|
const bindingsObj = Object.create( null );
|
|
32
33
|
_( node ).set( 'bindings', bindingsObj );
|
|
33
34
|
Observer.observe( bindingsObj, mutations => {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
35
|
+
if ( node instanceof window.Element ) {
|
|
36
|
+
const bindingsParse = parseBindingsAttr( node.getAttribute( config.attr.bindingsreflection ) || '' );
|
|
37
|
+
const bindingsParseBefore = new Map(bindingsParse);
|
|
38
|
+
for ( const m of mutations ) {
|
|
39
|
+
if ( m.detail?.publish !== false ) {
|
|
40
|
+
if ( m.type === 'delete' ) bindingsParse.delete( m.key );
|
|
41
|
+
else bindingsParse.set( m.key, undefined );
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
if ( bindingsParse.size && bindingsParse.size !== bindingsParseBefore.size ) {
|
|
45
|
+
node.setAttribute( config.attr.bindingsreflection, `{ ${ [ ...bindingsParse.entries() ].map(([ key, value ]) => value === undefined ? key : `${ key }: ${ value }` ).join( ', ' ) } }` );
|
|
46
|
+
} else if ( !bindingsParse.size ) node.toggleAttribute( config.attr.bindingsreflection, false );
|
|
47
|
+
} else {
|
|
48
|
+
const contextsApi = node[ ctxConfig.api.contexts ];
|
|
49
|
+
for ( const m of mutations ) {
|
|
50
|
+
if ( m.type === 'delete' ) {
|
|
51
|
+
const ctx = contextsApi.find( DOMBindingsContext.kind, m.key );
|
|
52
|
+
if ( ctx ) contextsApi.detach( ctx );
|
|
53
|
+
} else if ( !contextsApi.find( DOMBindingsContext.kind, m.key ) ) {
|
|
54
|
+
contextsApi.attach( new DOMBindingsContext( m.key ) );
|
|
55
|
+
}
|
|
51
56
|
}
|
|
52
57
|
}
|
|
53
58
|
} );
|
|
@@ -90,13 +95,71 @@ function exposeAPIs( config ) {
|
|
|
90
95
|
*
|
|
91
96
|
* @return Void
|
|
92
97
|
*/
|
|
93
|
-
function applyBindings( config, target, bindings, { merge, diff, namespace } = {} ) {
|
|
98
|
+
function applyBindings( config, target, bindings, { merge, diff, publish, namespace } = {} ) {
|
|
94
99
|
const window = this, { webqit: { Observer } } = window;
|
|
95
100
|
const bindingsObj = getBindings.call( this, config, target );
|
|
96
|
-
const $params = { diff, namespace };
|
|
101
|
+
const $params = { diff, namespace, detail: { publish } };
|
|
97
102
|
const exitingKeys = merge ? [] : Observer.ownKeys( bindingsObj, $params ).filter( key => !( key in bindings ) );
|
|
98
103
|
return Observer.batch( bindingsObj, () => {
|
|
99
104
|
if ( exitingKeys.length ) { Observer.deleteProperties( bindingsObj, exitingKeys, $params ); }
|
|
100
105
|
return Observer.set( bindingsObj, bindings, $params );
|
|
101
106
|
}, $params );
|
|
102
107
|
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Performs realtime capture of elements and their attributes
|
|
111
|
+
* and their module query results; then resolves the respective import elements.
|
|
112
|
+
*
|
|
113
|
+
* @param Object config
|
|
114
|
+
*
|
|
115
|
+
* @return Void
|
|
116
|
+
*/
|
|
117
|
+
function realtime(config) {
|
|
118
|
+
const window = this, { webqit: { realdom, Observer, oohtml: { configs } } } = window;
|
|
119
|
+
// ------------
|
|
120
|
+
const attachBindingsContext = (host, key) => {
|
|
121
|
+
const contextsApi = host[configs.CONTEXT_API.api.contexts];
|
|
122
|
+
if ( !contextsApi.find( DOMBindingsContext.kind, key ) ) {
|
|
123
|
+
contextsApi.attach( new DOMBindingsContext( key ) );
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
const detachBindingsContext = (host, key) => {
|
|
127
|
+
let ctx, contextsApi = host[configs.CONTEXT_API.api.contexts];
|
|
128
|
+
while( ctx = contextsApi.find( DOMBindingsContext.kind, key ) ) contextsApi.detach(ctx);
|
|
129
|
+
};
|
|
130
|
+
// ------------
|
|
131
|
+
realdom.realtime(window.document).query( `[${window.CSS.escape(config.attr.bindingsreflection)}]`, record => {
|
|
132
|
+
record.exits.forEach( entry => detachBindingsContext( entry ) );
|
|
133
|
+
record.entrants.forEach(entry => {
|
|
134
|
+
const bindingsParse = parseBindingsAttr( entry.getAttribute( config.attr.bindingsreflection ) || '' );
|
|
135
|
+
const newData = [ ...bindingsParse.entries() ].filter(([ k, v ]) => v !== undefined );
|
|
136
|
+
if ( newData.length ) entry[ config.api.bind ]( Object.fromEntries( newData ), { merge: true, publish: false } );
|
|
137
|
+
for ( const [ key ] of bindingsParse ) {
|
|
138
|
+
attachBindingsContext( entry, key );
|
|
139
|
+
}
|
|
140
|
+
} );
|
|
141
|
+
}, { id: 'bindings:dom', live: true, subtree: 'cross-roots', timing: 'sync', eventDetails: true });
|
|
142
|
+
realdom.realtime( window.document, 'attr' ).observe( config.attr.bindingsreflection, record => {
|
|
143
|
+
const bindingsObj = getBindings.call( window, config, record.target );
|
|
144
|
+
const bindingsParse = parseBindingsAttr( record.value || '' );
|
|
145
|
+
const oldBindings = parseBindingsAttr( record.oldValue || '' );
|
|
146
|
+
for ( const key of new Set([ ...bindingsParse.keys(), ...oldBindings.keys() ]) ) {
|
|
147
|
+
if ( !oldBindings.has( key ) ) {
|
|
148
|
+
if ( bindingsParse.get( key ) !== undefined ) Observer.set( bindingsObj, key, bindingsParse.get( key ), { detail: { publish: false } } );
|
|
149
|
+
attachBindingsContext( record.target, key );
|
|
150
|
+
} else if ( !bindingsParse.has( key ) ) {
|
|
151
|
+
if ( oldBindings.get( key ) !== undefined ) Observer.deleteProperty( bindingsObj, key, { detail: { publish: false } } );
|
|
152
|
+
detachBindingsContext( record.target, key );
|
|
153
|
+
} else if ( bindingsParse.get( key ) !== oldBindings.get( key ) ) {
|
|
154
|
+
Observer.set( bindingsObj, key, bindingsParse.get( key ), { detail: { publish: false } } );
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}, { id: 'bindings:attr', subtree: 'cross-roots', timing: 'sync', newValue: true, oldValue: true } );
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
const parseBindingsAttr = str => {
|
|
161
|
+
str = str.trim();
|
|
162
|
+
return new Map(_splitOuter( str.slice(1, -1), ',' ).filter( s => s.trim() ).map( _str => {
|
|
163
|
+
return _splitOuter( _str, ':' ).map( s => s.trim() );
|
|
164
|
+
}));
|
|
165
|
+
};
|
|
@@ -120,6 +120,7 @@ export default class DOMContext {
|
|
|
120
120
|
this.subscriptions.delete( subscriptionEvent );
|
|
121
121
|
this.unsubscribed( subscriptionEvent );
|
|
122
122
|
const { target } = subscriptionEvent;
|
|
123
|
+
subscriptionEvent.meta.answered = false;
|
|
123
124
|
target.dispatchEvent( subscriptionEvent );
|
|
124
125
|
} );
|
|
125
126
|
return this;
|
|
@@ -44,7 +44,7 @@ export default class DOMContexts {
|
|
|
44
44
|
find( ...args ) {
|
|
45
45
|
return [ ...this[ '#' ].contexts ].find( ctx => {
|
|
46
46
|
if ( typeof args[ 0 ] === 'function' ) return args[ 0 ]( ctx );
|
|
47
|
-
return ctx.constructor.kind === args[ 0 ] && ( args
|
|
47
|
+
return ctx.constructor.kind === args[ 0 ] && ( !args[ 1 ] || ctx.detail === args[ 1 ] );
|
|
48
48
|
} );
|
|
49
49
|
}
|
|
50
50
|
|
|
@@ -84,32 +84,7 @@ export default class DOMContexts {
|
|
|
84
84
|
args[ args.indexOf( options ) ] = { ...options, signal: responseInstance.signal };
|
|
85
85
|
}
|
|
86
86
|
const event = new ( _DOMContextRequestEvent() )( ...args );
|
|
87
|
-
|
|
88
|
-
event.meta.target = this[ '#' ].host;
|
|
89
|
-
|
|
90
|
-
const rootNode = this[ '#' ].host.getRootNode();
|
|
91
|
-
const temp = event => {
|
|
92
|
-
event.stopImmediatePropagation();
|
|
93
|
-
// Always set thus whether answered or not
|
|
94
|
-
event.meta.target = event.target;
|
|
95
|
-
if ( event.answered ) return;
|
|
96
|
-
if ( !waitListMappings.get( rootNode ) ) { waitListMappings.set( rootNode, new Set ); }
|
|
97
|
-
if ( event.type === 'contextrequest' && event.live ) {
|
|
98
|
-
waitListMappings.get( rootNode ).add( event );
|
|
99
|
-
} else if ( event.type === 'contextclaim' ) {
|
|
100
|
-
const claims = new Set;
|
|
101
|
-
waitListMappings.get( rootNode ).forEach( subscriptionEvent => {
|
|
102
|
-
if ( !this[ '#' ].host.contains( subscriptionEvent.target ) || !event.detail.matchEvent( subscriptionEvent ) ) return;
|
|
103
|
-
waitListMappings.get( rootNode ).delete( subscriptionEvent );
|
|
104
|
-
claims.add( subscriptionEvent );
|
|
105
|
-
} );
|
|
106
|
-
return event.respondWith( claims );
|
|
107
|
-
}
|
|
108
|
-
};
|
|
109
|
-
|
|
110
|
-
rootNode.addEventListener( event.type, temp );
|
|
111
|
-
this[ '#' ].host.dispatchEvent( event );
|
|
112
|
-
rootNode.removeEventListener( event.type, temp );
|
|
87
|
+
this[ '#' ].host.dispatchEvent( event );
|
|
113
88
|
} );
|
|
114
89
|
}
|
|
115
90
|
|
package/src/context-api/index.js
CHANGED
|
@@ -21,6 +21,37 @@ export default function init( $config = {} ) {
|
|
|
21
21
|
attr: { contextname: 'contextname', },
|
|
22
22
|
api: { contexts: 'contexts', },
|
|
23
23
|
} );
|
|
24
|
+
const waitListMappings = new Map, dispatchEvent = window.EventTarget.prototype.dispatchEvent;
|
|
25
|
+
Object.defineProperty( window.EventTarget.prototype, 'dispatchEvent', { value: function( ...args ) {
|
|
26
|
+
const event = args[0], rootNode = this.getRootNode?.();
|
|
27
|
+
if ( [ 'contextclaim', 'contextrequest' ].includes( event.type ) && rootNode ) {
|
|
28
|
+
if ( event.meta ) event.meta.target = this;
|
|
29
|
+
const temp = event => {
|
|
30
|
+
event.stopImmediatePropagation();
|
|
31
|
+
// Always set this whether answered or not
|
|
32
|
+
if ( event.meta ) event.meta.target = event.target;
|
|
33
|
+
if ( event.answered ) return;
|
|
34
|
+
if ( !waitListMappings.get( rootNode ) ) waitListMappings.set( rootNode, new Set );
|
|
35
|
+
if ( event.type === 'contextrequest' && event.live ) {
|
|
36
|
+
waitListMappings.get( rootNode ).add( event );
|
|
37
|
+
} else if ( event.type === 'contextclaim' ) {
|
|
38
|
+
const claims = new Set;
|
|
39
|
+
waitListMappings.get( rootNode ).forEach( subscriptionEvent => {
|
|
40
|
+
if ( !event.target.contains( subscriptionEvent.target ) || !event.detail?.matchEvent?.( subscriptionEvent ) ) return;
|
|
41
|
+
waitListMappings.get( rootNode ).delete( subscriptionEvent );
|
|
42
|
+
claims.add( subscriptionEvent );
|
|
43
|
+
} );
|
|
44
|
+
if ( !waitListMappings.get( rootNode ).size ) waitListMappings.delete( rootNode );
|
|
45
|
+
return event.respondWith?.( claims );
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
rootNode.addEventListener( event.type, temp );
|
|
49
|
+
const returnValue = dispatchEvent.call( this, ...args );
|
|
50
|
+
rootNode.removeEventListener( event.type, temp );
|
|
51
|
+
return returnValue;
|
|
52
|
+
}
|
|
53
|
+
return dispatchEvent.call( this, ...args );
|
|
54
|
+
} } );
|
|
24
55
|
window.webqit.DOMContexts = DOMContexts;
|
|
25
56
|
window.webqit.DOMContext = DOMContext;
|
|
26
57
|
window.webqit.DOMContextRequestEvent = _DOMContextRequestEvent();
|
|
@@ -219,7 +219,7 @@ function compileInlineBindings( config, str ) {
|
|
|
219
219
|
|
|
220
220
|
if ( $import__.value && $iteratee__ ) {
|
|
221
221
|
let $existing__ = new Map;
|
|
222
|
-
this.
|
|
222
|
+
[ ...this.children ].filter( el => el.matches( '[${ config.attr.itemIndex }]' ) ).forEach( x => {
|
|
223
223
|
$existing__.set( x.getAttribute( '${ config.attr.itemIndex }' ), x );
|
|
224
224
|
} );
|
|
225
225
|
${ indices ? `let ${ indices } = -1;` : '' }
|