@webqit/oohtml 4.5.8 → 4.5.10
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/data-binding.js +0 -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 +1 -2
- package/dist/main.js.map +2 -2
- package/dist/main.lite.js +1 -2
- package/dist/main.lite.js.map +2 -2
- package/package.json +1 -1
- package/src/data-binding/index.js +0 -1
- package/src/html-imports/HTMLImportsContext.js +47 -48
- package/src/html-imports/HTMLModule.js +85 -85
- package/src/html-imports/_HTMLImportElement.js +88 -88
|
@@ -12,12 +12,12 @@ import { _wq, env } from '../util.js';
|
|
|
12
12
|
*
|
|
13
13
|
* @return HTMLImportElement
|
|
14
14
|
*/
|
|
15
|
-
export default function() {
|
|
15
|
+
export default function () {
|
|
16
16
|
const { window } = env, { webqit } = window, { realdom, oohtml: { configs } } = webqit;
|
|
17
|
-
if (
|
|
18
|
-
const BaseElement = configs.HTML_IMPORTS.elements.import.includes(
|
|
17
|
+
if (webqit.HTMLImportElement) return webqit.HTMLImportElement;
|
|
18
|
+
const BaseElement = configs.HTML_IMPORTS.elements.import.includes('-') ? window.HTMLElement : class { };
|
|
19
19
|
class HTMLImportElement extends BaseElement {
|
|
20
|
-
|
|
20
|
+
|
|
21
21
|
/**
|
|
22
22
|
* @instance
|
|
23
23
|
*
|
|
@@ -25,23 +25,23 @@ export default function() {
|
|
|
25
25
|
*
|
|
26
26
|
* @returns
|
|
27
27
|
*/
|
|
28
|
-
static instance(
|
|
29
|
-
if (
|
|
30
|
-
return _wq(
|
|
28
|
+
static instance(node) {
|
|
29
|
+
if (configs.HTML_IMPORTS.elements.import.includes('-') && (node instanceof this)) return node;
|
|
30
|
+
return _wq(node).get('import::instance') || new this(node);
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
/**
|
|
34
34
|
* @constructor
|
|
35
35
|
*/
|
|
36
|
-
constructor(
|
|
36
|
+
constructor(...args) {
|
|
37
37
|
super();
|
|
38
38
|
// --------
|
|
39
|
-
const el = args[
|
|
40
|
-
_wq(
|
|
41
|
-
Object.defineProperty(
|
|
39
|
+
const el = args[0] || this;
|
|
40
|
+
_wq(el).set('import::instance', this);
|
|
41
|
+
Object.defineProperty(this, 'el', { get: () => el, configurable: false });
|
|
42
42
|
|
|
43
43
|
const priv = {};
|
|
44
|
-
Object.defineProperty(
|
|
44
|
+
Object.defineProperty(this, '#', { get: () => priv, configurable: false });
|
|
45
45
|
priv.slottedElements = new Set;
|
|
46
46
|
|
|
47
47
|
priv.setAnchorNode = anchorNode => {
|
|
@@ -50,21 +50,21 @@ export default function() {
|
|
|
50
50
|
};
|
|
51
51
|
|
|
52
52
|
priv.live = callback => {
|
|
53
|
-
if (
|
|
53
|
+
if (priv.liveImportsRealtime) throw new Error(`Import element already in live mode.`);
|
|
54
54
|
const parentNode = this.el.isConnected ? this.el.parentNode : priv.anchorNode.parentNode;
|
|
55
|
-
priv.liveImportsRealtime = realdom.realtime(
|
|
55
|
+
priv.liveImportsRealtime = realdom.realtime(this.el).attr(configs.HTML_IMPORTS.attr.ref, (record, { signal }) => {
|
|
56
56
|
priv.moduleRef = record.value;
|
|
57
|
-
const moduleRef = priv.moduleRef.includes(
|
|
58
|
-
const request = { ...HTMLImportsContext.createRequest(
|
|
59
|
-
parentNode[
|
|
60
|
-
callback(
|
|
61
|
-
Array.isArray(
|
|
62
|
-
)
|
|
63
|
-
}
|
|
64
|
-
}, { live: true, timing: 'sync', lifecycleSignals: true }
|
|
65
|
-
priv.autoDestroyRealtime = realdom.realtime(
|
|
57
|
+
const moduleRef = priv.moduleRef.includes('#') ? priv.moduleRef : `${priv.moduleRef}#`/* for live children */;
|
|
58
|
+
const request = { ...HTMLImportsContext.createRequest(moduleRef), live: signal && true, signal, diff: !moduleRef.endsWith('#') };
|
|
59
|
+
parentNode[configs.CONTEXT_API.api.contexts].request(request, response => {
|
|
60
|
+
callback((response instanceof window.HTMLTemplateElement ? [...response.content.children] : (
|
|
61
|
+
Array.isArray(response) ? response : response && [response]
|
|
62
|
+
)) || []);
|
|
63
|
+
});
|
|
64
|
+
}, { live: true, timing: 'sync', lifecycleSignals: true });
|
|
65
|
+
priv.autoDestroyRealtime = realdom.realtime(window.document).track(parentNode, () => {
|
|
66
66
|
priv.die();
|
|
67
|
-
}, { subtree: 'cross-roots', timing: 'sync', generation: 'exits' }
|
|
67
|
+
}, { subtree: 'cross-roots', timing: 'sync', generation: 'exits' });
|
|
68
68
|
};
|
|
69
69
|
|
|
70
70
|
priv.die = () => {
|
|
@@ -73,58 +73,58 @@ export default function() {
|
|
|
73
73
|
priv.liveImportsRealtime = null;
|
|
74
74
|
};
|
|
75
75
|
|
|
76
|
-
priv.hydrate = (
|
|
77
|
-
anchorNode.replaceWith(
|
|
78
|
-
priv.live(
|
|
76
|
+
priv.hydrate = (anchorNode, slottedElements) => {
|
|
77
|
+
anchorNode.replaceWith(priv.setAnchorNode(this.createAnchorNode()));
|
|
78
|
+
priv.live(fragments => {
|
|
79
79
|
// The default action
|
|
80
|
-
if (
|
|
80
|
+
if (priv.originalsRemapped) return this.fill(fragments);
|
|
81
81
|
// Initial remap action
|
|
82
|
-
const identifiersMap = fragments.map(
|
|
83
|
-
slottedElements.forEach(
|
|
84
|
-
const tagName = slottedElement.tagName, fragmentDef = slottedElement.getAttribute(
|
|
85
|
-
const originalsMatch = (
|
|
86
|
-
if (
|
|
87
|
-
_wq(
|
|
88
|
-
priv.slottedElements.add(
|
|
89
|
-
}
|
|
82
|
+
const identifiersMap = fragments.map((fragment, i) => ({ el: fragment, fragmentDef: fragment.getAttribute(configs.HTML_IMPORTS.attr.fragmentdef) || '', tagName: fragment.tagName, i }));
|
|
83
|
+
slottedElements.forEach((slottedElement, i) => {
|
|
84
|
+
const tagName = slottedElement.tagName, fragmentDef = slottedElement.getAttribute(configs.HTML_IMPORTS.attr.fragmentdef) || '';
|
|
85
|
+
const originalsMatch = (i++, identifiersMap.find(fragmentIdentifiers => fragmentIdentifiers.tagName === tagName && fragmentIdentifiers.fragmentDef === fragmentDef && fragmentIdentifiers.i === i));
|
|
86
|
+
if (originalsMatch) _wq(slottedElement).set('original@imports', originalsMatch.el); // Or should we throw integrity error here?
|
|
87
|
+
_wq(slottedElement).set('slot@imports', this.el);
|
|
88
|
+
priv.slottedElements.add(slottedElement);
|
|
89
|
+
});
|
|
90
90
|
priv.originalsRemapped = true;
|
|
91
91
|
});
|
|
92
92
|
};
|
|
93
93
|
|
|
94
|
-
priv.autoRestore = (
|
|
94
|
+
priv.autoRestore = (callback = null) => {
|
|
95
95
|
priv.autoRestoreRealtime?.disconnect();
|
|
96
|
-
if (
|
|
96
|
+
if (callback) callback();
|
|
97
97
|
const restore = () => {
|
|
98
98
|
if (this.el.isConnected) return;
|
|
99
|
-
this.el.setAttribute(
|
|
99
|
+
this.el.setAttribute('data-nodecount', 0);
|
|
100
100
|
priv.internalMutation = true;
|
|
101
|
-
priv.anchorNode.replaceWith(
|
|
101
|
+
priv.anchorNode.replaceWith(this.el);
|
|
102
102
|
priv.internalMutation = false;
|
|
103
|
-
priv.setAnchorNode(
|
|
103
|
+
priv.setAnchorNode(null);
|
|
104
104
|
};
|
|
105
|
-
if (
|
|
106
|
-
const autoRestoreRealtime = realdom.realtime(
|
|
107
|
-
record.exits.forEach(
|
|
108
|
-
_wq(
|
|
109
|
-
priv.slottedElements.delete(
|
|
110
|
-
}
|
|
111
|
-
if (
|
|
105
|
+
if (!priv.slottedElements.size) return restore();
|
|
106
|
+
const autoRestoreRealtime = realdom.realtime(priv.anchorNode.parentNode).observe([...priv.slottedElements], record => {
|
|
107
|
+
record.exits.forEach(outgoingNode => {
|
|
108
|
+
_wq(outgoingNode).delete('slot@imports');
|
|
109
|
+
priv.slottedElements.delete(outgoingNode);
|
|
110
|
+
});
|
|
111
|
+
if (!priv.slottedElements.size) {
|
|
112
112
|
autoRestoreRealtime.disconnect();
|
|
113
113
|
// At this point, ignore if this is a removal involving the whole parent node
|
|
114
|
-
if (
|
|
114
|
+
if (!record.target.isConnected) return;
|
|
115
115
|
restore();
|
|
116
116
|
}
|
|
117
|
-
}, { subtree: 'cross-roots', timing: 'sync', generation: 'exits' }
|
|
117
|
+
}, { subtree: 'cross-roots', timing: 'sync', generation: 'exits' });
|
|
118
118
|
priv.autoRestoreRealtime = autoRestoreRealtime;
|
|
119
119
|
};
|
|
120
120
|
|
|
121
121
|
priv.connectedCallback = () => {
|
|
122
|
-
if (
|
|
123
|
-
priv.live(
|
|
122
|
+
if (priv.internalMutation) return;
|
|
123
|
+
priv.live(fragments => this.fill(fragments));
|
|
124
124
|
};
|
|
125
125
|
|
|
126
126
|
priv.disconnectedCallback = () => {
|
|
127
|
-
if (
|
|
127
|
+
if (priv.internalMutation) return;
|
|
128
128
|
priv.die();
|
|
129
129
|
};
|
|
130
130
|
}
|
|
@@ -135,11 +135,11 @@ export default function() {
|
|
|
135
135
|
* @return Element
|
|
136
136
|
*/
|
|
137
137
|
createAnchorNode() {
|
|
138
|
-
if (
|
|
139
|
-
const escapeElement = window.document.createElement(
|
|
138
|
+
if (window.webqit.env !== 'server') { return window.document.createTextNode('') }
|
|
139
|
+
const escapeElement = window.document.createElement('div');
|
|
140
140
|
escapeElement.textContent = this.el.outerHTML;
|
|
141
|
-
const anchorNode = window.document.createComment(
|
|
142
|
-
_wq(
|
|
141
|
+
const anchorNode = window.document.createComment(escapeElement.innerHTML);
|
|
142
|
+
_wq(anchorNode).set('isAnchorNode', true);
|
|
143
143
|
return anchorNode;
|
|
144
144
|
}
|
|
145
145
|
|
|
@@ -150,49 +150,49 @@ export default function() {
|
|
|
150
150
|
*
|
|
151
151
|
* @return void
|
|
152
152
|
*/
|
|
153
|
-
fill(
|
|
154
|
-
if (!this.el.isConnected && (!this[
|
|
153
|
+
fill(slottableElements, r) {
|
|
154
|
+
if (!this.el.isConnected && (!this['#'].anchorNode || !this['#'].anchorNode.isConnected)) {
|
|
155
155
|
// LiveImports must be responding to an event that just removed the subtree from DOM
|
|
156
156
|
return;
|
|
157
157
|
}
|
|
158
|
-
if (
|
|
158
|
+
if (Array.isArray(slottableElements)) { slottableElements = new Set(slottableElements) }
|
|
159
159
|
// This state must be set before the diffing below and the serialization done at createAnchorNode()
|
|
160
|
-
this.el.setAttribute(
|
|
161
|
-
this[
|
|
162
|
-
this[
|
|
163
|
-
const slottedElementOriginal = _wq(
|
|
160
|
+
this.el.setAttribute('data-nodecount', slottableElements.size);
|
|
161
|
+
this['#'].autoRestore(() => {
|
|
162
|
+
this['#'].slottedElements.forEach(slottedElement => {
|
|
163
|
+
const slottedElementOriginal = _wq(slottedElement).get('original@imports');
|
|
164
164
|
// If still available in source, simply leave unchanged
|
|
165
165
|
// otherwise remove it from slot... to reflect this change
|
|
166
|
-
if (
|
|
167
|
-
slottableElements.delete(
|
|
166
|
+
if (slottableElements.has(slottedElementOriginal)) {
|
|
167
|
+
slottableElements.delete(slottedElementOriginal);
|
|
168
168
|
} else {
|
|
169
|
-
this[
|
|
169
|
+
this['#'].slottedElements.delete(slottedElement);
|
|
170
170
|
// This removal will not be caught
|
|
171
171
|
slottedElement.remove();
|
|
172
172
|
}
|
|
173
|
-
}
|
|
173
|
+
});
|
|
174
174
|
// Make sure anchor node is what's in place...
|
|
175
175
|
// not the import element itslef - but all only when we have slottableElements.size
|
|
176
|
-
if (
|
|
177
|
-
const newAnchorNode = this[
|
|
178
|
-
this[
|
|
179
|
-
this.el.replaceWith(
|
|
180
|
-
this[
|
|
176
|
+
if (slottableElements.size && this.el.isConnected) {
|
|
177
|
+
const newAnchorNode = this['#'].setAnchorNode(this.createAnchorNode());
|
|
178
|
+
this['#'].internalMutation = true;
|
|
179
|
+
this.el.replaceWith(newAnchorNode);
|
|
180
|
+
this['#'].internalMutation = false;
|
|
181
181
|
}
|
|
182
182
|
// Insert slottables now
|
|
183
|
-
slottableElements.forEach(
|
|
183
|
+
slottableElements.forEach(slottableElement => {
|
|
184
184
|
// Clone each slottable element and give it a reference to its original
|
|
185
|
-
const slottableElementClone = slottableElement.cloneNode(
|
|
185
|
+
const slottableElementClone = slottableElement.cloneNode(true);
|
|
186
186
|
// The folllowing references must be set before adding to DODM
|
|
187
|
-
if (
|
|
188
|
-
slottableElementClone.toggleAttribute(
|
|
187
|
+
if (!slottableElementClone.hasAttribute(configs.HTML_IMPORTS.attr.fragmentdef)) {
|
|
188
|
+
slottableElementClone.toggleAttribute(configs.HTML_IMPORTS.attr.fragmentdef, true);
|
|
189
189
|
}
|
|
190
|
-
_wq(
|
|
191
|
-
_wq(
|
|
192
|
-
this[
|
|
193
|
-
this[
|
|
194
|
-
}
|
|
195
|
-
}
|
|
190
|
+
_wq(slottableElementClone).set('original@imports', slottableElement);
|
|
191
|
+
_wq(slottableElementClone).set('slot@imports', this.el);
|
|
192
|
+
this['#'].slottedElements.add(slottableElementClone);
|
|
193
|
+
this['#'].anchorNode.before(slottableElementClone);
|
|
194
|
+
});
|
|
195
|
+
});
|
|
196
196
|
}
|
|
197
197
|
|
|
198
198
|
/**
|
|
@@ -200,30 +200,30 @@ export default function() {
|
|
|
200
200
|
*
|
|
201
201
|
* @return void
|
|
202
202
|
*/
|
|
203
|
-
empty() { this[
|
|
203
|
+
empty() { this['#'].slottedElements.forEach(slottedElement => slottedElement.remove()); }
|
|
204
204
|
|
|
205
205
|
/**
|
|
206
206
|
* Returns the slot's anchorNode.
|
|
207
207
|
*
|
|
208
208
|
* @return array
|
|
209
209
|
*/
|
|
210
|
-
get anchorNode() { return this[
|
|
210
|
+
get anchorNode() { return this['#'].anchorNode; }
|
|
211
211
|
|
|
212
212
|
/**
|
|
213
213
|
* Returns the slot's module reference, if any.
|
|
214
214
|
*
|
|
215
215
|
* @return string
|
|
216
216
|
*/
|
|
217
|
-
get moduleRef() { return this[
|
|
217
|
+
get moduleRef() { return this['#'].moduleRef; }
|
|
218
218
|
|
|
219
219
|
/**
|
|
220
220
|
* Returns the slot's slotted elements.
|
|
221
221
|
*
|
|
222
222
|
* @return array
|
|
223
223
|
*/
|
|
224
|
-
get slottedElements() { return this[
|
|
224
|
+
get slottedElements() { return this['#'].slottedElements; }
|
|
225
225
|
}
|
|
226
|
-
if (
|
|
226
|
+
if (configs.HTML_IMPORTS.elements.import.includes('-')) { customElements.define(configs.HTML_IMPORTS.elements.import, HTMLImportElement); }
|
|
227
227
|
webqit.HTMLImportElement = HTMLImportElement;
|
|
228
228
|
return HTMLImportElement;
|
|
229
229
|
}
|