@jinntec/fore 3.1.2 → 3.2.0

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/fore-dev.js CHANGED
@@ -1,4 +1,4 @@
1
- /* Version: 3.1.2 - May 27, 2026 14:39:35 */
1
+ /* Version: 3.2.0 - June 9, 2026 10:50:39 */
2
2
  function t$2(t, s, r, i) {
3
3
  const n = {
4
4
  op: s,
@@ -20124,7 +20124,7 @@ class Fore {
20124
20124
  return Fore.ACTION_ELEMENTS.includes(elementName);
20125
20125
  }
20126
20126
  static get UI_ELEMENTS() {
20127
- return new Set(['FX-ALERT', 'FX-CONTROL', 'FX-DIALOG', 'FX-FILENAME', 'FX-MEDIATYPE', 'FX-GROUP', 'FX-HINT', 'FX-ITEMS', 'FX-OUTPUT', 'FX-RANGE', 'FX-REPEAT', 'FX-REPEATITEM', 'FX-REPEAT-ATTRIBUTES', 'FX-SWITCH', 'FX-SECRET', 'FX-SELECT', 'FX-SUBMIT', 'FX-TEXTAREA', 'FX-TRIGGER', 'FX-UPLOAD', 'FX-VAR']);
20127
+ return new Set(['FX-ALERT', 'FX-CONTROL', 'FX-DIALOG', 'FX-FILENAME', 'FX-MEDIATYPE', 'FX-GROUP', 'FX-HINT', 'FX-ITEMS', 'FX-INCLUDE', 'FX-OUTPUT', 'FX-RANGE', 'FX-REPEAT', 'FX-REPEATITEM', 'FX-REPEAT-ATTRIBUTES', 'FX-SWITCH', 'FX-SECRET', 'FX-SELECT', 'FX-SUBMIT', 'FX-TEXTAREA', 'FX-TRIGGER', 'FX-UPLOAD', 'FX-VAR']);
20128
20128
  }
20129
20129
 
20130
20130
  /**
@@ -25479,7 +25479,7 @@ class FxFore extends HTMLElement {
25479
25479
  this._createRepeatsFromAttributes();
25480
25480
  this.inited = true;
25481
25481
  };
25482
- this.version = 'Version: 3.1.2 - built on May 27, 2026 14:39:35';
25482
+ this.version = 'Version: 3.2.0 - built on June 9, 2026 10:50:39';
25483
25483
 
25484
25484
  /**
25485
25485
  * @type {import('./fx-model.js').FxModel}
@@ -26929,7 +26929,7 @@ class FxFore extends HTMLElement {
26929
26929
  bound.evalInContext();
26930
26930
  if (bound.nodeName !== 'FX-REPEAT') {
26931
26931
  // Do not try to get a bind for a nodeSET of a repeat. there are multiple.
26932
- bound.getModelItem().bind?.evalInContext();
26932
+ bound.getModelItem()?.bind?.evalInContext();
26933
26933
  }
26934
26934
  continue;
26935
26935
  }
@@ -26978,7 +26978,7 @@ class FxFore extends HTMLElement {
26978
26978
  }
26979
26979
  }
26980
26980
  bound.evalInContext();
26981
- bound.getModelItem().bind?.evalInContext();
26981
+ bound.getModelItem()?.bind?.evalInContext();
26982
26982
  if (!isResolvedBound(bound)) {
26983
26983
  console.warn('create-nodes: could not resolve bound after node creation, skipping', bound);
26984
26984
  continue;
@@ -29635,6 +29635,211 @@ if (!customElements.get('fx-hint')) {
29635
29635
  customElements.define('fx-hint', FxHint);
29636
29636
  }
29637
29637
 
29638
+ /**
29639
+ * <fx-include>
29640
+ *
29641
+ * Lazy light-DOM include component.
29642
+ *
29643
+ * Loads markup either from:
29644
+ * - a direct child <template>
29645
+ * - an external HTML document via @src
29646
+ *
29647
+ * Default behavior:
29648
+ * - listens for an event
29649
+ * - includes content once
29650
+ * - removes the event listener afterwards
29651
+ *
29652
+ * With @reload:
29653
+ * - listens repeatedly
29654
+ * - clears previously included content
29655
+ * - includes fresh content again
29656
+ *
29657
+ * Attributes:
29658
+ * event Event name to listen for. Defaults to "click".
29659
+ * target CSS selector for the event target. Defaults to "self".
29660
+ * Special values: self, document, window.
29661
+ * src Optional external HTML source.
29662
+ * selector Optional selector inside external HTML.
29663
+ * replace Replace <fx-include> with the included content.
29664
+ * immediate Include immediately when connected.
29665
+ * reload Re-include on every matching event.
29666
+ */
29667
+ class FxInclude extends HTMLElement {
29668
+ constructor() {
29669
+ super();
29670
+ this._listener = this._handleEvent.bind(this);
29671
+ this._eventTarget = null;
29672
+ this._loaded = false;
29673
+ this._replaced = false;
29674
+ }
29675
+ connectedCallback() {
29676
+ this.eventName = this.getAttribute('event') || 'click';
29677
+ this.targetSelector = this.getAttribute('target') || 'self';
29678
+ this.src = this.getAttribute('src');
29679
+ this.selector = this.getAttribute('selector');
29680
+ this.replace = this.hasAttribute('replace');
29681
+ this.immediate = this.hasAttribute('immediate');
29682
+ this.reload = this.hasAttribute('reload');
29683
+ if (this.immediate) {
29684
+ queueMicrotask(() => this.include());
29685
+ return;
29686
+ }
29687
+ this._bindListener();
29688
+ }
29689
+ disconnectedCallback() {
29690
+ this._unbindListener();
29691
+ }
29692
+ _bindListener() {
29693
+ const target = this._resolveEventTarget();
29694
+ if (!target) {
29695
+ this._dispatchError(`fx-include: event target not found: '${this.targetSelector}'`);
29696
+ return;
29697
+ }
29698
+ target.addEventListener(this.eventName, this._listener);
29699
+ this._eventTarget = target;
29700
+ }
29701
+ _unbindListener() {
29702
+ if (this._eventTarget && this._listener) {
29703
+ this._eventTarget.removeEventListener(this.eventName, this._listener);
29704
+ }
29705
+ this._eventTarget = null;
29706
+ }
29707
+ _resolveEventTarget() {
29708
+ if (!this.targetSelector || this.targetSelector === 'self') {
29709
+ return this;
29710
+ }
29711
+ if (this.targetSelector === 'document') {
29712
+ return document;
29713
+ }
29714
+ if (this.targetSelector === 'window') {
29715
+ return window;
29716
+ }
29717
+ const fore = this.closest('fx-fore');
29718
+ return fore?.querySelector(this.targetSelector) || document.querySelector(this.targetSelector);
29719
+ }
29720
+ async _handleEvent(event) {
29721
+ await this.include(event);
29722
+ }
29723
+ async include(triggerEvent = null) {
29724
+ if (this._replaced) {
29725
+ return;
29726
+ }
29727
+ if (this._loaded && !this.reload) {
29728
+ return;
29729
+ }
29730
+ const fragment = this.src ? await this._loadExternalFragment() : this._loadTemplateFragment();
29731
+ if (!fragment) {
29732
+ return;
29733
+ }
29734
+ if (this.replace) {
29735
+ await this._replaceSelf(fragment, triggerEvent);
29736
+ return;
29737
+ }
29738
+ this._clearIncludedContent();
29739
+ const wrapper = document.createElement('span');
29740
+ wrapper.setAttribute('data-fx-include-content', '');
29741
+ wrapper.style.display = 'contents';
29742
+ wrapper.appendChild(fragment);
29743
+ this.appendChild(wrapper);
29744
+ this._loaded = true;
29745
+ await this._initializeInsertedContent(wrapper);
29746
+ await Fore.dispatch(this, 'include-done', {
29747
+ src: this.src || null,
29748
+ included: wrapper,
29749
+ replaced: false,
29750
+ triggerEvent
29751
+ });
29752
+ if (!this.reload) {
29753
+ this._unbindListener();
29754
+ }
29755
+ }
29756
+ _loadTemplateFragment() {
29757
+ const template = this.querySelector(':scope > template');
29758
+ if (!template) {
29759
+ this._dispatchError('fx-include: no src and no direct template child found');
29760
+ return null;
29761
+ }
29762
+ return template.content.cloneNode(true);
29763
+ }
29764
+ async _loadExternalFragment() {
29765
+ const html = await Fore.loadHtml(this.src);
29766
+ if (!html) {
29767
+ this._dispatchError(`fx-include: failed to load '${this.src}'`);
29768
+ return null;
29769
+ }
29770
+ const parsed = new DOMParser().parseFromString(html, 'text/html');
29771
+ if (this.selector) {
29772
+ const selected = parsed.querySelector(this.selector);
29773
+ if (!selected) {
29774
+ this._dispatchError(`fx-include: selector '${this.selector}' not found in '${this.src}'`);
29775
+ return null;
29776
+ }
29777
+ const fragment = document.createDocumentFragment();
29778
+ fragment.appendChild(document.importNode(selected, true));
29779
+ return fragment;
29780
+ }
29781
+ const template = parsed.querySelector('template');
29782
+ if (template) {
29783
+ return document.importNode(template.content, true);
29784
+ }
29785
+ const fragment = document.createDocumentFragment();
29786
+ Array.from(parsed.body.childNodes).forEach(node => {
29787
+ fragment.appendChild(document.importNode(node, true));
29788
+ });
29789
+ return fragment;
29790
+ }
29791
+ async _replaceSelf(fragment, triggerEvent) {
29792
+ const parent = this.parentNode;
29793
+ if (!parent) {
29794
+ return;
29795
+ }
29796
+ const wrapper = document.createElement('span');
29797
+ wrapper.setAttribute('data-fx-include-replacement', '');
29798
+ wrapper.style.display = 'contents';
29799
+ wrapper.appendChild(fragment);
29800
+ this._unbindListener();
29801
+ this.replaceWith(wrapper);
29802
+ this._replaced = true;
29803
+ this._loaded = true;
29804
+ await this._initializeInsertedContent(wrapper);
29805
+ await Fore.dispatch(wrapper, 'include-done', {
29806
+ src: this.src || null,
29807
+ included: wrapper,
29808
+ replaced: true,
29809
+ triggerEvent
29810
+ });
29811
+ }
29812
+ _clearIncludedContent() {
29813
+ this.querySelectorAll(':scope > [data-fx-include-content]').forEach(node => {
29814
+ node.remove();
29815
+ });
29816
+ }
29817
+ async _initializeInsertedContent(startElement) {
29818
+ this._initForeUiDescendants(startElement);
29819
+ await Fore.refreshChildren(startElement, true);
29820
+ }
29821
+ _initForeUiDescendants(startElement) {
29822
+ Array.from(startElement.children || []).forEach(element => {
29823
+ if (element.nodeName.toUpperCase() === 'FX-FORE') {
29824
+ return;
29825
+ }
29826
+ if (Fore.isUiElement(element.nodeName) && typeof element.init === 'function') {
29827
+ element.init();
29828
+ }
29829
+ this._initForeUiDescendants(element);
29830
+ });
29831
+ }
29832
+ _dispatchError(message) {
29833
+ Fore.dispatch(this, 'error', {
29834
+ level: 'Error',
29835
+ message
29836
+ });
29837
+ }
29838
+ }
29839
+ if (!customElements.get('fx-include')) {
29840
+ customElements.define('fx-include', FxInclude);
29841
+ }
29842
+
29638
29843
  /**
29639
29844
  * todo: review placing of value. should probably work with value attribute and not allow slotted content.
29640
29845
  */
@@ -31153,6 +31358,13 @@ class FxCase extends FxContainer {
31153
31358
  }
31154
31359
  await parentNode.replaceCase(this, replacement);
31155
31360
  target = replacement;
31361
+ // Re-dispatch 'select' on the loaded replacement so its fx-action handlers fire.
31362
+ // The replacement's handlers are registered after async loading; they miss the
31363
+ // initial 'select' that triggered the load.
31364
+ if (parentNode.selectedCase === replacement) {
31365
+ await Fore.dispatch(replacement, 'select', {});
31366
+ return;
31367
+ }
31156
31368
  }
31157
31369
  ownerForm.getModel();
31158
31370
  ownerForm.addToBatchedNotifications(target);
package/dist/fore.js CHANGED
@@ -1,4 +1,4 @@
1
- /* Version: 3.1.2 - May 27, 2026 14:39:34 */
1
+ /* Version: 3.2.0 - June 9, 2026 10:50:37 */
2
2
  function t$2(t, s, r, i) {
3
3
  const n = {
4
4
  op: s,
@@ -20121,7 +20121,7 @@ class Fore {
20121
20121
  return Fore.ACTION_ELEMENTS.includes(elementName);
20122
20122
  }
20123
20123
  static get UI_ELEMENTS() {
20124
- return new Set(['FX-ALERT', 'FX-CONTROL', 'FX-DIALOG', 'FX-FILENAME', 'FX-MEDIATYPE', 'FX-GROUP', 'FX-HINT', 'FX-ITEMS', 'FX-OUTPUT', 'FX-RANGE', 'FX-REPEAT', 'FX-REPEATITEM', 'FX-REPEAT-ATTRIBUTES', 'FX-SWITCH', 'FX-SECRET', 'FX-SELECT', 'FX-SUBMIT', 'FX-TEXTAREA', 'FX-TRIGGER', 'FX-UPLOAD', 'FX-VAR']);
20124
+ return new Set(['FX-ALERT', 'FX-CONTROL', 'FX-DIALOG', 'FX-FILENAME', 'FX-MEDIATYPE', 'FX-GROUP', 'FX-HINT', 'FX-ITEMS', 'FX-INCLUDE', 'FX-OUTPUT', 'FX-RANGE', 'FX-REPEAT', 'FX-REPEATITEM', 'FX-REPEAT-ATTRIBUTES', 'FX-SWITCH', 'FX-SECRET', 'FX-SELECT', 'FX-SUBMIT', 'FX-TEXTAREA', 'FX-TRIGGER', 'FX-UPLOAD', 'FX-VAR']);
20125
20125
  }
20126
20126
 
20127
20127
  /**
@@ -25425,7 +25425,7 @@ class FxFore extends HTMLElement {
25425
25425
  this._createRepeatsFromAttributes();
25426
25426
  this.inited = true;
25427
25427
  };
25428
- this.version = 'Version: 3.1.2 - built on May 27, 2026 14:39:34';
25428
+ this.version = 'Version: 3.2.0 - built on June 9, 2026 10:50:37';
25429
25429
 
25430
25430
  /**
25431
25431
  * @type {import('./fx-model.js').FxModel}
@@ -26859,7 +26859,7 @@ class FxFore extends HTMLElement {
26859
26859
  bound.evalInContext();
26860
26860
  if (bound.nodeName !== 'FX-REPEAT') {
26861
26861
  // Do not try to get a bind for a nodeSET of a repeat. there are multiple.
26862
- bound.getModelItem().bind?.evalInContext();
26862
+ bound.getModelItem()?.bind?.evalInContext();
26863
26863
  }
26864
26864
  continue;
26865
26865
  }
@@ -26908,7 +26908,7 @@ class FxFore extends HTMLElement {
26908
26908
  }
26909
26909
  }
26910
26910
  bound.evalInContext();
26911
- bound.getModelItem().bind?.evalInContext();
26911
+ bound.getModelItem()?.bind?.evalInContext();
26912
26912
  if (!isResolvedBound(bound)) {
26913
26913
  continue;
26914
26914
  }
@@ -31053,6 +31053,13 @@ class FxCase extends FxContainer {
31053
31053
  }
31054
31054
  await parentNode.replaceCase(this, replacement);
31055
31055
  target = replacement;
31056
+ // Re-dispatch 'select' on the loaded replacement so its fx-action handlers fire.
31057
+ // The replacement's handlers are registered after async loading; they miss the
31058
+ // initial 'select' that triggered the load.
31059
+ if (parentNode.selectedCase === replacement) {
31060
+ await Fore.dispatch(replacement, 'select', {});
31061
+ return;
31062
+ }
31056
31063
  }
31057
31064
  ownerForm.getModel();
31058
31065
  ownerForm.addToBatchedNotifications(target);
package/index.js CHANGED
@@ -14,6 +14,7 @@ import './src/ui/fx-control.js';
14
14
  import './src/ui/fx-container.js';
15
15
  import './src/ui/fx-group.js';
16
16
  import './src/ui/fx-hint.js';
17
+ import './src/ui/fx-include.js';
17
18
  import './src/ui/fx-output.js';
18
19
  import './src/ui/fx-repeat.js';
19
20
  import './src/ui/fx-repeat-attributes.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jinntec/fore",
3
- "version": "3.1.2",
3
+ "version": "3.2.0",
4
4
  "description": "Fore - declarative user interfaces in plain HTML",
5
5
  "module": "./index.js",
6
6
  "publishConfig": {
package/src/fore.js CHANGED
@@ -239,6 +239,7 @@ export class Fore {
239
239
  'FX-GROUP',
240
240
  'FX-HINT',
241
241
  'FX-ITEMS',
242
+ 'FX-INCLUDE',
242
243
  'FX-OUTPUT',
243
244
  'FX-RANGE',
244
245
  'FX-REPEAT',
package/src/fx-fore.js CHANGED
@@ -1819,7 +1819,7 @@ export class FxFore extends HTMLElement {
1819
1819
  bound.evalInContext();
1820
1820
  if (bound.nodeName !== 'FX-REPEAT') {
1821
1821
  // Do not try to get a bind for a nodeSET of a repeat. there are multiple.
1822
- bound.getModelItem().bind?.evalInContext();
1822
+ bound.getModelItem()?.bind?.evalInContext();
1823
1823
  }
1824
1824
  continue;
1825
1825
  }
@@ -1878,7 +1878,7 @@ export class FxFore extends HTMLElement {
1878
1878
  }
1879
1879
 
1880
1880
  bound.evalInContext();
1881
- bound.getModelItem().bind?.evalInContext();
1881
+ bound.getModelItem()?.bind?.evalInContext();
1882
1882
 
1883
1883
  if (!isResolvedBound(bound)) {
1884
1884
  console.warn('create-nodes: could not resolve bound after node creation, skipping', bound);
package/src/ui/fx-case.js CHANGED
@@ -81,6 +81,13 @@ export class FxCase extends FxContainer {
81
81
  }
82
82
  await parentNode.replaceCase(this, replacement);
83
83
  target = replacement;
84
+ // Re-dispatch 'select' on the loaded replacement so its fx-action handlers fire.
85
+ // The replacement's handlers are registered after async loading; they miss the
86
+ // initial 'select' that triggered the load.
87
+ if (parentNode.selectedCase === replacement) {
88
+ await Fore.dispatch(replacement, 'select', {});
89
+ return;
90
+ }
84
91
  }
85
92
  const model = ownerForm.getModel();
86
93
  ownerForm.addToBatchedNotifications(target);
@@ -0,0 +1,264 @@
1
+ import { Fore } from '../fore.js';
2
+
3
+ /**
4
+ * <fx-include>
5
+ *
6
+ * Lazy light-DOM include component.
7
+ *
8
+ * Loads markup either from:
9
+ * - a direct child <template>
10
+ * - an external HTML document via @src
11
+ *
12
+ * Default behavior:
13
+ * - listens for an event
14
+ * - includes content once
15
+ * - removes the event listener afterwards
16
+ *
17
+ * With @reload:
18
+ * - listens repeatedly
19
+ * - clears previously included content
20
+ * - includes fresh content again
21
+ *
22
+ * Attributes:
23
+ * event Event name to listen for. Defaults to "click".
24
+ * target CSS selector for the event target. Defaults to "self".
25
+ * Special values: self, document, window.
26
+ * src Optional external HTML source.
27
+ * selector Optional selector inside external HTML.
28
+ * replace Replace <fx-include> with the included content.
29
+ * immediate Include immediately when connected.
30
+ * reload Re-include on every matching event.
31
+ */
32
+ export class FxInclude extends HTMLElement {
33
+ constructor() {
34
+ super();
35
+
36
+ this._listener = this._handleEvent.bind(this);
37
+ this._eventTarget = null;
38
+ this._loaded = false;
39
+ this._replaced = false;
40
+ }
41
+
42
+ connectedCallback() {
43
+ this.eventName = this.getAttribute('event') || 'click';
44
+ this.targetSelector = this.getAttribute('target') || 'self';
45
+ this.src = this.getAttribute('src');
46
+ this.selector = this.getAttribute('selector');
47
+
48
+ this.replace = this.hasAttribute('replace');
49
+ this.immediate = this.hasAttribute('immediate');
50
+ this.reload = this.hasAttribute('reload');
51
+
52
+ if (this.immediate) {
53
+ queueMicrotask(() => this.include());
54
+ return;
55
+ }
56
+
57
+ this._bindListener();
58
+ }
59
+
60
+ disconnectedCallback() {
61
+ this._unbindListener();
62
+ }
63
+
64
+ _bindListener() {
65
+ const target = this._resolveEventTarget();
66
+
67
+ if (!target) {
68
+ this._dispatchError(`fx-include: event target not found: '${this.targetSelector}'`);
69
+ return;
70
+ }
71
+
72
+ target.addEventListener(this.eventName, this._listener);
73
+ this._eventTarget = target;
74
+ }
75
+
76
+ _unbindListener() {
77
+ if (this._eventTarget && this._listener) {
78
+ this._eventTarget.removeEventListener(this.eventName, this._listener);
79
+ }
80
+
81
+ this._eventTarget = null;
82
+ }
83
+
84
+ _resolveEventTarget() {
85
+ if (!this.targetSelector || this.targetSelector === 'self') {
86
+ return this;
87
+ }
88
+
89
+ if (this.targetSelector === 'document') {
90
+ return document;
91
+ }
92
+
93
+ if (this.targetSelector === 'window') {
94
+ return window;
95
+ }
96
+
97
+ const fore = this.closest('fx-fore');
98
+
99
+ return fore?.querySelector(this.targetSelector) || document.querySelector(this.targetSelector);
100
+ }
101
+
102
+ async _handleEvent(event) {
103
+ await this.include(event);
104
+ }
105
+
106
+ async include(triggerEvent = null) {
107
+ if (this._replaced) {
108
+ return;
109
+ }
110
+
111
+ if (this._loaded && !this.reload) {
112
+ return;
113
+ }
114
+
115
+ const fragment = this.src ? await this._loadExternalFragment() : this._loadTemplateFragment();
116
+
117
+ if (!fragment) {
118
+ return;
119
+ }
120
+
121
+ if (this.replace) {
122
+ await this._replaceSelf(fragment, triggerEvent);
123
+ return;
124
+ }
125
+
126
+ this._clearIncludedContent();
127
+
128
+ const wrapper = document.createElement('span');
129
+ wrapper.setAttribute('data-fx-include-content', '');
130
+ wrapper.style.display = 'contents';
131
+ wrapper.appendChild(fragment);
132
+
133
+ this.appendChild(wrapper);
134
+
135
+ this._loaded = true;
136
+
137
+ await this._initializeInsertedContent(wrapper);
138
+
139
+ await Fore.dispatch(this, 'include-done', {
140
+ src: this.src || null,
141
+ included: wrapper,
142
+ replaced: false,
143
+ triggerEvent,
144
+ });
145
+
146
+ if (!this.reload) {
147
+ this._unbindListener();
148
+ }
149
+ }
150
+
151
+ _loadTemplateFragment() {
152
+ const template = this.querySelector(':scope > template');
153
+
154
+ if (!template) {
155
+ this._dispatchError('fx-include: no src and no direct template child found');
156
+ return null;
157
+ }
158
+
159
+ return template.content.cloneNode(true);
160
+ }
161
+
162
+ async _loadExternalFragment() {
163
+ const html = await Fore.loadHtml(this.src);
164
+
165
+ if (!html) {
166
+ this._dispatchError(`fx-include: failed to load '${this.src}'`);
167
+ return null;
168
+ }
169
+
170
+ const parsed = new DOMParser().parseFromString(html, 'text/html');
171
+
172
+ if (this.selector) {
173
+ const selected = parsed.querySelector(this.selector);
174
+
175
+ if (!selected) {
176
+ this._dispatchError(`fx-include: selector '${this.selector}' not found in '${this.src}'`);
177
+ return null;
178
+ }
179
+
180
+ const fragment = document.createDocumentFragment();
181
+ fragment.appendChild(document.importNode(selected, true));
182
+ return fragment;
183
+ }
184
+
185
+ const template = parsed.querySelector('template');
186
+
187
+ if (template) {
188
+ return document.importNode(template.content, true);
189
+ }
190
+
191
+ const fragment = document.createDocumentFragment();
192
+
193
+ Array.from(parsed.body.childNodes).forEach(node => {
194
+ fragment.appendChild(document.importNode(node, true));
195
+ });
196
+
197
+ return fragment;
198
+ }
199
+
200
+ async _replaceSelf(fragment, triggerEvent) {
201
+ const parent = this.parentNode;
202
+
203
+ if (!parent) {
204
+ return;
205
+ }
206
+
207
+ const wrapper = document.createElement('span');
208
+ wrapper.setAttribute('data-fx-include-replacement', '');
209
+ wrapper.style.display = 'contents';
210
+ wrapper.appendChild(fragment);
211
+
212
+ this._unbindListener();
213
+
214
+ this.replaceWith(wrapper);
215
+
216
+ this._replaced = true;
217
+ this._loaded = true;
218
+
219
+ await this._initializeInsertedContent(wrapper);
220
+
221
+ await Fore.dispatch(wrapper, 'include-done', {
222
+ src: this.src || null,
223
+ included: wrapper,
224
+ replaced: true,
225
+ triggerEvent,
226
+ });
227
+ }
228
+
229
+ _clearIncludedContent() {
230
+ this.querySelectorAll(':scope > [data-fx-include-content]').forEach(node => {
231
+ node.remove();
232
+ });
233
+ }
234
+
235
+ async _initializeInsertedContent(startElement) {
236
+ this._initForeUiDescendants(startElement);
237
+ await Fore.refreshChildren(startElement, true);
238
+ }
239
+
240
+ _initForeUiDescendants(startElement) {
241
+ Array.from(startElement.children || []).forEach(element => {
242
+ if (element.nodeName.toUpperCase() === 'FX-FORE') {
243
+ return;
244
+ }
245
+
246
+ if (Fore.isUiElement(element.nodeName) && typeof element.init === 'function') {
247
+ element.init();
248
+ }
249
+
250
+ this._initForeUiDescendants(element);
251
+ });
252
+ }
253
+
254
+ _dispatchError(message) {
255
+ Fore.dispatch(this, 'error', {
256
+ level: 'Error',
257
+ message,
258
+ });
259
+ }
260
+ }
261
+
262
+ if (!customElements.get('fx-include')) {
263
+ customElements.define('fx-include', FxInclude);
264
+ }