@mintjamsinc/ichigojs 0.1.81 → 0.1.83
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/README.md +14 -0
- package/dist/ichigo.cjs +325 -39
- package/dist/ichigo.cjs.map +1 -1
- package/dist/ichigo.esm.js +325 -39
- package/dist/ichigo.esm.js.map +1 -1
- package/dist/ichigo.esm.min.js +1 -1
- package/dist/ichigo.esm.min.js.map +1 -0
- package/dist/ichigo.min.cjs +1 -1
- package/dist/ichigo.umd.js +325 -39
- package/dist/ichigo.umd.js.map +1 -1
- package/dist/ichigo.umd.min.js +1 -1
- package/dist/ichigo.umd.min.js.map +1 -0
- package/dist/types/ichigo/ExpressionEvaluator.d.ts +118 -0
- package/dist/types/ichigo/VComponent.d.ts +2 -0
- package/dist/types/ichigo/VComponentRegistry.d.ts +2 -0
- package/dist/types/ichigo/VNode.d.ts +1 -0
- package/dist/types/ichigo/VUpdateContext.d.ts +21 -0
- package/dist/types/ichigo/components/IchigoElement.d.ts +14 -3
- package/dist/types/ichigo/directives/VBindingsPreparer.d.ts +24 -0
- package/dist/types/ichigo/directives/VDOMUpdater.d.ts +17 -0
- package/dist/types/ichigo/directives/VSlotOutletDirective.d.ts +3 -3
- package/dist/types/ichigo/directives/VStaticSlotOutletDirective.d.ts +129 -0
- package/dist/types/ichigo/util/BindingsUtils.d.ts +10 -0
- package/dist/types/ichigo/util/VLogLevel.d.ts +9 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1019,6 +1019,20 @@ defineComponent('my-badge', {
|
|
|
1019
1019
|
Use the native `<slot>` element in the component template to project content
|
|
1020
1020
|
from the parent. ichigo.js components use Light DOM.
|
|
1021
1021
|
|
|
1022
|
+
- Slot content is compiled in the **parent scope** and stays the parent's:
|
|
1023
|
+
its bindings, event handlers and the props of components inside it keep
|
|
1024
|
+
working wherever the component places it.
|
|
1025
|
+
- The content is **moved** to the `<slot>`, never copied, so a `<slot>` may sit
|
|
1026
|
+
behind a `v-if` / `v-for` in the component template (e.g. a dialog body shown
|
|
1027
|
+
only while open). Hiding the outlet takes the content out of view; showing it
|
|
1028
|
+
again brings back the same nodes.
|
|
1029
|
+
- Nodes can be in one place only: when the same slot is rendered more than
|
|
1030
|
+
once (a `<slot>` inside a `v-for`), the content goes to the outlet rendered
|
|
1031
|
+
last, and if that outlet goes away it moves to the last one remaining. For
|
|
1032
|
+
content per row, use a scoped slot (below), which renders once per outlet.
|
|
1033
|
+
- A `<slot>` that receives no content renders its own children as fallback, in
|
|
1034
|
+
the component scope.
|
|
1035
|
+
|
|
1022
1036
|
### Scoped slots
|
|
1023
1037
|
|
|
1024
1038
|
A scoped slot lets the parent supply a template for content that the component
|
package/dist/ichigo.cjs
CHANGED
|
@@ -8990,9 +8990,9 @@
|
|
|
8990
8990
|
* ```
|
|
8991
8991
|
*
|
|
8992
8992
|
* This directive is created only when a scoped template for the slot's name
|
|
8993
|
-
* exists (see {@link VSlotOutletDirective.tryCreate}); otherwise
|
|
8994
|
-
*
|
|
8995
|
-
*
|
|
8993
|
+
* exists (see {@link VSlotOutletDirective.tryCreate}); otherwise plain slot
|
|
8994
|
+
* content is moved into place by VStaticSlotOutletDirective, and a `<slot>`
|
|
8995
|
+
* with no content at all renders its fallback in the component scope.
|
|
8996
8996
|
*
|
|
8997
8997
|
* Rendering happens synchronously in onMount — before the component
|
|
8998
8998
|
* application would compile the slot's fallback children — by replacing the
|
|
@@ -9284,6 +9284,266 @@
|
|
|
9284
9284
|
}
|
|
9285
9285
|
}
|
|
9286
9286
|
|
|
9287
|
+
// Copyright (c) 2025 MintJams Inc. Licensed under MIT License.
|
|
9288
|
+
/**
|
|
9289
|
+
* Renders a static slot outlet: a `<slot>` element inside a component template
|
|
9290
|
+
* whose host element received plain slot content from the parent — child
|
|
9291
|
+
* nodes for the default slot, or elements carrying `slot="name"`:
|
|
9292
|
+
*
|
|
9293
|
+
* ```html
|
|
9294
|
+
* <!-- component template -->
|
|
9295
|
+
* <div v-if="open" class="body"><slot></slot></div>
|
|
9296
|
+
*
|
|
9297
|
+
* <!-- usage -->
|
|
9298
|
+
* <my-dialog :open="show">
|
|
9299
|
+
* <my-field :label="title"></my-field>
|
|
9300
|
+
* </my-dialog>
|
|
9301
|
+
* ```
|
|
9302
|
+
*
|
|
9303
|
+
* The slot content is the parent application's own nodes, compiled in the
|
|
9304
|
+
* parent scope; it keeps its bindings, listeners and component props only as
|
|
9305
|
+
* long as those very nodes are displayed. So the outlet MOVES them into place
|
|
9306
|
+
* and never clones them. That is what lets a `<slot>` sit behind a v-if or
|
|
9307
|
+
* v-for in the component template: the directive clones its template source,
|
|
9308
|
+
* the clone carries a fresh `<slot>`, and the outlet created for that clone
|
|
9309
|
+
* moves the live nodes in.
|
|
9310
|
+
*
|
|
9311
|
+
* Nodes can only be in one place, so when the same slot is rendered more than
|
|
9312
|
+
* once (e.g. a `<slot>` inside a v-for), the outlet rendered last receives the
|
|
9313
|
+
* content and the earlier ones are left empty. When the outlet holding the
|
|
9314
|
+
* content goes away while others remain (its row is removed), the content
|
|
9315
|
+
* moves to the last remaining one. For content per row, use a scoped slot
|
|
9316
|
+
* (`<template v-slot:name="scope">`), which renders a copy per outlet
|
|
9317
|
+
* (VSlotOutletDirective).
|
|
9318
|
+
*
|
|
9319
|
+
* The component application never compiles the moved nodes: they are placed
|
|
9320
|
+
* in onMount, after the parent VNode has taken its snapshot of the children
|
|
9321
|
+
* to compile. Components inside them belong to the parent application, which
|
|
9322
|
+
* expands them through {@link expandComponents} once they are in the document.
|
|
9323
|
+
* When the last outlet goes away (its v-if turns false) the nodes leave with
|
|
9324
|
+
* the removed clone and wait there until the next outlet moves them again;
|
|
9325
|
+
* they are not destroyed, because they are not this application's to destroy.
|
|
9326
|
+
*
|
|
9327
|
+
* Created only when the host captured content for the slot's name and no
|
|
9328
|
+
* scoped template claims it; otherwise the `<slot>` element renders its
|
|
9329
|
+
* fallback children in the component scope.
|
|
9330
|
+
*/
|
|
9331
|
+
class VStaticSlotOutletDirective {
|
|
9332
|
+
/**
|
|
9333
|
+
* The live outlets of each slot, in the order they were rendered, keyed by
|
|
9334
|
+
* the slot's node array (one per host element and slot name). The last
|
|
9335
|
+
* one holds the content.
|
|
9336
|
+
*/
|
|
9337
|
+
static #outlets = new WeakMap();
|
|
9338
|
+
/**
|
|
9339
|
+
* Marks where the `<slot>` element was, so the content can be moved back
|
|
9340
|
+
* here when a later outlet of the same slot goes away.
|
|
9341
|
+
*/
|
|
9342
|
+
#anchor;
|
|
9343
|
+
/**
|
|
9344
|
+
* Guards against double destruction.
|
|
9345
|
+
*/
|
|
9346
|
+
#destroyed = false;
|
|
9347
|
+
/**
|
|
9348
|
+
* The virtual node of the `<slot>` element (in the component application).
|
|
9349
|
+
*/
|
|
9350
|
+
#vNode;
|
|
9351
|
+
/**
|
|
9352
|
+
* The slot content: the parent application's nodes, shared with the host
|
|
9353
|
+
* element's slot cache.
|
|
9354
|
+
*/
|
|
9355
|
+
#nodes;
|
|
9356
|
+
/**
|
|
9357
|
+
* The host element's VNode in the parent application, whose children are
|
|
9358
|
+
* the VNodes of the slot content. Undefined when the host was not compiled
|
|
9359
|
+
* by an application (then there is nothing to expand).
|
|
9360
|
+
*/
|
|
9361
|
+
#hostVNode;
|
|
9362
|
+
/**
|
|
9363
|
+
* Creates a static slot outlet for the given `<slot>` VNode when the host
|
|
9364
|
+
* element captured content for its slot name. Returns undefined when there
|
|
9365
|
+
* is none, so the `<slot>` element keeps rendering its fallback content.
|
|
9366
|
+
*/
|
|
9367
|
+
static tryCreate(vNode) {
|
|
9368
|
+
const host = vNode.vApplication.hostElement;
|
|
9369
|
+
if (!host || typeof host._ichigoSlotNodes !== 'function') {
|
|
9370
|
+
return undefined;
|
|
9371
|
+
}
|
|
9372
|
+
const element = vNode.node;
|
|
9373
|
+
const nodes = host._ichigoSlotNodes(element.getAttribute('name') || 'default');
|
|
9374
|
+
if (!nodes) {
|
|
9375
|
+
return undefined;
|
|
9376
|
+
}
|
|
9377
|
+
return new VStaticSlotOutletDirective(vNode, nodes, host._ichigoHost?.vNode);
|
|
9378
|
+
}
|
|
9379
|
+
constructor(vNode, nodes, hostVNode) {
|
|
9380
|
+
this.#vNode = vNode;
|
|
9381
|
+
this.#nodes = nodes;
|
|
9382
|
+
this.#hostVNode = hostVNode;
|
|
9383
|
+
// Slot props (v-bind / :) only mean something to a scoped template.
|
|
9384
|
+
// Consume them so the generic attribute parsing does not evaluate them
|
|
9385
|
+
// on an element that is about to leave the document.
|
|
9386
|
+
const element = vNode.node;
|
|
9387
|
+
for (const attr of Array.from(element.attributes)) {
|
|
9388
|
+
if (attr.name.startsWith('v-bind:') || attr.name.startsWith(':')) {
|
|
9389
|
+
element.removeAttribute(attr.name);
|
|
9390
|
+
}
|
|
9391
|
+
}
|
|
9392
|
+
}
|
|
9393
|
+
/**
|
|
9394
|
+
* @inheritdoc
|
|
9395
|
+
*/
|
|
9396
|
+
get name() {
|
|
9397
|
+
return 'static-slot-outlet';
|
|
9398
|
+
}
|
|
9399
|
+
/**
|
|
9400
|
+
* @inheritdoc
|
|
9401
|
+
*/
|
|
9402
|
+
get vNode() {
|
|
9403
|
+
return this.#vNode;
|
|
9404
|
+
}
|
|
9405
|
+
/**
|
|
9406
|
+
* @inheritdoc
|
|
9407
|
+
*/
|
|
9408
|
+
get needsAnchor() {
|
|
9409
|
+
return false;
|
|
9410
|
+
}
|
|
9411
|
+
/**
|
|
9412
|
+
* @inheritdoc
|
|
9413
|
+
*/
|
|
9414
|
+
get bindingsPreparer() {
|
|
9415
|
+
return undefined;
|
|
9416
|
+
}
|
|
9417
|
+
/**
|
|
9418
|
+
* @inheritdoc
|
|
9419
|
+
*/
|
|
9420
|
+
get domUpdater() {
|
|
9421
|
+
return undefined;
|
|
9422
|
+
}
|
|
9423
|
+
/**
|
|
9424
|
+
* @inheritdoc
|
|
9425
|
+
*/
|
|
9426
|
+
get templatize() {
|
|
9427
|
+
return false;
|
|
9428
|
+
}
|
|
9429
|
+
/**
|
|
9430
|
+
* @inheritdoc
|
|
9431
|
+
*/
|
|
9432
|
+
get dependentIdentifiers() {
|
|
9433
|
+
return [];
|
|
9434
|
+
}
|
|
9435
|
+
/**
|
|
9436
|
+
* @inheritdoc
|
|
9437
|
+
*
|
|
9438
|
+
* Moves the slot content in place of the `<slot>` element — synchronously
|
|
9439
|
+
* during VNode construction, before the component application would
|
|
9440
|
+
* compile the slot's fallback children (which the content replaces).
|
|
9441
|
+
*/
|
|
9442
|
+
get onMount() {
|
|
9443
|
+
return () => {
|
|
9444
|
+
const slot = this.#vNode.node;
|
|
9445
|
+
while (slot.firstChild) {
|
|
9446
|
+
slot.removeChild(slot.firstChild);
|
|
9447
|
+
}
|
|
9448
|
+
this.#anchor = document.createComment('slot');
|
|
9449
|
+
slot.replaceWith(this.#anchor);
|
|
9450
|
+
let outlets = VStaticSlotOutletDirective.#outlets.get(this.#nodes);
|
|
9451
|
+
if (!outlets) {
|
|
9452
|
+
outlets = [];
|
|
9453
|
+
VStaticSlotOutletDirective.#outlets.set(this.#nodes, outlets);
|
|
9454
|
+
}
|
|
9455
|
+
outlets.push(this);
|
|
9456
|
+
this.#place();
|
|
9457
|
+
};
|
|
9458
|
+
}
|
|
9459
|
+
/**
|
|
9460
|
+
* @inheritdoc
|
|
9461
|
+
*/
|
|
9462
|
+
get onMounted() {
|
|
9463
|
+
return undefined;
|
|
9464
|
+
}
|
|
9465
|
+
/**
|
|
9466
|
+
* @inheritdoc
|
|
9467
|
+
*/
|
|
9468
|
+
get onUpdate() {
|
|
9469
|
+
return undefined;
|
|
9470
|
+
}
|
|
9471
|
+
/**
|
|
9472
|
+
* @inheritdoc
|
|
9473
|
+
*/
|
|
9474
|
+
get onUpdated() {
|
|
9475
|
+
return undefined;
|
|
9476
|
+
}
|
|
9477
|
+
/**
|
|
9478
|
+
* @inheritdoc
|
|
9479
|
+
*/
|
|
9480
|
+
get onUnmount() {
|
|
9481
|
+
return undefined;
|
|
9482
|
+
}
|
|
9483
|
+
/**
|
|
9484
|
+
* @inheritdoc
|
|
9485
|
+
*/
|
|
9486
|
+
get onUnmounted() {
|
|
9487
|
+
return undefined;
|
|
9488
|
+
}
|
|
9489
|
+
/**
|
|
9490
|
+
* @inheritdoc
|
|
9491
|
+
*
|
|
9492
|
+
* Expands the components in the slot content through the parent
|
|
9493
|
+
* application's VNodes. Called by the walk of whoever inserted this
|
|
9494
|
+
* outlet into the document (VApplication.mount, v-if, v-for), so the
|
|
9495
|
+
* content is connected by now — unless a later outlet took it, in which
|
|
9496
|
+
* case that outlet's walk expands it.
|
|
9497
|
+
*/
|
|
9498
|
+
expandComponents() {
|
|
9499
|
+
const children = this.#hostVNode?.childVNodes;
|
|
9500
|
+
if (!children) {
|
|
9501
|
+
return;
|
|
9502
|
+
}
|
|
9503
|
+
for (const child of children) {
|
|
9504
|
+
if (this.#nodes.includes(child.node)) {
|
|
9505
|
+
child.expandComponents();
|
|
9506
|
+
}
|
|
9507
|
+
}
|
|
9508
|
+
}
|
|
9509
|
+
/**
|
|
9510
|
+
* @inheritdoc
|
|
9511
|
+
*
|
|
9512
|
+
* The slot content is the parent application's; nothing to release here.
|
|
9513
|
+
*/
|
|
9514
|
+
destroy() {
|
|
9515
|
+
if (this.#destroyed) {
|
|
9516
|
+
return;
|
|
9517
|
+
}
|
|
9518
|
+
this.#destroyed = true;
|
|
9519
|
+
const outlets = VStaticSlotOutletDirective.#outlets.get(this.#nodes);
|
|
9520
|
+
if (!outlets) {
|
|
9521
|
+
return;
|
|
9522
|
+
}
|
|
9523
|
+
const index = outlets.indexOf(this);
|
|
9524
|
+
if (index === -1) {
|
|
9525
|
+
return;
|
|
9526
|
+
}
|
|
9527
|
+
const wasHolder = index === outlets.length - 1;
|
|
9528
|
+
outlets.splice(index, 1);
|
|
9529
|
+
// Hand the content to the last remaining outlet before this one's DOM
|
|
9530
|
+
// is removed (v-if / v-for destroy the VNode first, then remove it),
|
|
9531
|
+
// so removing the row that shows it does not take it out of view.
|
|
9532
|
+
const next = outlets[outlets.length - 1];
|
|
9533
|
+
if (wasHolder && next) {
|
|
9534
|
+
next.#place();
|
|
9535
|
+
next.expandComponents();
|
|
9536
|
+
}
|
|
9537
|
+
}
|
|
9538
|
+
/**
|
|
9539
|
+
* Moves the slot content right after this outlet's anchor. Moving, not
|
|
9540
|
+
* cloning: nodes shown by another outlet of the same slot leave it.
|
|
9541
|
+
*/
|
|
9542
|
+
#place() {
|
|
9543
|
+
this.#anchor?.after(...this.#nodes);
|
|
9544
|
+
}
|
|
9545
|
+
}
|
|
9546
|
+
|
|
9287
9547
|
// Copyright (c) 2025 MintJams Inc. Licensed under MIT License.
|
|
9288
9548
|
/**
|
|
9289
9549
|
* Manages directives associated with a virtual node (VNode).
|
|
@@ -9452,10 +9712,12 @@
|
|
|
9452
9712
|
const element = this.#vNode.node;
|
|
9453
9713
|
// Parse directives from attributes
|
|
9454
9714
|
const directives = [];
|
|
9455
|
-
//
|
|
9456
|
-
//
|
|
9457
|
-
//
|
|
9458
|
-
//
|
|
9715
|
+
// Slot outlet: a <slot> element (without structural directives) inside a
|
|
9716
|
+
// component whose host received content for it — a matching
|
|
9717
|
+
// <template v-slot:...> (rendered per outlet), or else plain slot
|
|
9718
|
+
// content (moved into place). This is an element-based directive,
|
|
9719
|
+
// created before the generic attribute parsing so it can consume the
|
|
9720
|
+
// slot-prop bindings (:x).
|
|
9459
9721
|
// A <slot> carrying v-if / v-for is handled structurally first; the
|
|
9460
9722
|
// outlet is then created when the clone is compiled.
|
|
9461
9723
|
if (element.tagName === 'SLOT' &&
|
|
@@ -9463,7 +9725,8 @@
|
|
|
9463
9725
|
!element.hasAttribute(StandardDirectiveName.V_IF) &&
|
|
9464
9726
|
!element.hasAttribute(StandardDirectiveName.V_ELSE_IF) &&
|
|
9465
9727
|
!element.hasAttribute(StandardDirectiveName.V_ELSE)) {
|
|
9466
|
-
const outlet = VSlotOutletDirective.tryCreate(this.#vNode)
|
|
9728
|
+
const outlet = VSlotOutletDirective.tryCreate(this.#vNode)
|
|
9729
|
+
?? VStaticSlotOutletDirective.tryCreate(this.#vNode);
|
|
9467
9730
|
if (outlet) {
|
|
9468
9731
|
directives.push(outlet);
|
|
9469
9732
|
}
|
|
@@ -9873,9 +10136,9 @@
|
|
|
9873
10136
|
*/
|
|
9874
10137
|
#fragmentRange;
|
|
9875
10138
|
/**
|
|
9876
|
-
* Set by {@link destroy}. A destroyed
|
|
9877
|
-
* list
|
|
9878
|
-
*
|
|
10139
|
+
* Set by {@link destroy}. A destroyed node also leaves its parent's child
|
|
10140
|
+
* list, but a walk that took its copy of the list before the node was
|
|
10141
|
+
* destroyed may still reach it, and must skip it.
|
|
9879
10142
|
*/
|
|
9880
10143
|
#destroyed = false;
|
|
9881
10144
|
/**
|
|
@@ -10045,7 +10308,8 @@
|
|
|
10045
10308
|
// walk runs once the subtree is in the document, which the outlet
|
|
10046
10309
|
// cannot know when it renders inside a detached v-if / v-for clone.
|
|
10047
10310
|
this.#directiveManager?.directives?.forEach(d => d.expandComponents?.());
|
|
10048
|
-
this
|
|
10311
|
+
// A copy: expanding can render and destroy clones under this node.
|
|
10312
|
+
this.#childVNodes?.slice().forEach(child => child.expandComponents());
|
|
10049
10313
|
}
|
|
10050
10314
|
/**
|
|
10051
10315
|
* The application instance associated with this virtual node.
|
|
@@ -10357,8 +10621,9 @@
|
|
|
10357
10621
|
updater.applyToDOM();
|
|
10358
10622
|
}
|
|
10359
10623
|
}
|
|
10360
|
-
// Recursively update child virtual nodes
|
|
10361
|
-
this
|
|
10624
|
+
// Recursively update child virtual nodes. A copy: an update can
|
|
10625
|
+
// destroy a v-if / v-for clone, which removes it from this list.
|
|
10626
|
+
this.#childVNodes?.slice().forEach(childVNode => {
|
|
10362
10627
|
childVNode.forceUpdate();
|
|
10363
10628
|
});
|
|
10364
10629
|
// If no directive requires template preservation, call onUpdated for directives that do not templatize
|
|
@@ -10370,7 +10635,7 @@
|
|
|
10370
10635
|
}
|
|
10371
10636
|
else if (this.#nodeType === Node.DOCUMENT_FRAGMENT_NODE) {
|
|
10372
10637
|
// For document fragments, recursively force update child VNodes
|
|
10373
|
-
this.#childVNodes?.forEach(childVNode => {
|
|
10638
|
+
this.#childVNodes?.slice().forEach(childVNode => {
|
|
10374
10639
|
childVNode.forceUpdate();
|
|
10375
10640
|
});
|
|
10376
10641
|
}
|
|
@@ -10452,6 +10717,7 @@
|
|
|
10452
10717
|
* 4. Unregister dependencies
|
|
10453
10718
|
* 5. Clean up directive manager
|
|
10454
10719
|
* 6. Call onUnmounted lifecycle hooks
|
|
10720
|
+
* 7. Leave the parent's child list
|
|
10455
10721
|
*/
|
|
10456
10722
|
destroy() {
|
|
10457
10723
|
this.#destroyed = true;
|
|
@@ -10478,9 +10744,9 @@
|
|
|
10478
10744
|
}
|
|
10479
10745
|
this.#userData.clear();
|
|
10480
10746
|
}
|
|
10481
|
-
// Recursively destroy child nodes
|
|
10747
|
+
// Recursively destroy child nodes (a copy: each one leaves this list)
|
|
10482
10748
|
if (this.#childVNodes) {
|
|
10483
|
-
for (const childVNode of this.#childVNodes) {
|
|
10749
|
+
for (const childVNode of this.#childVNodes.slice()) {
|
|
10484
10750
|
try {
|
|
10485
10751
|
childVNode.destroy();
|
|
10486
10752
|
}
|
|
@@ -10508,6 +10774,15 @@
|
|
|
10508
10774
|
d.onUnmounted?.();
|
|
10509
10775
|
});
|
|
10510
10776
|
}
|
|
10777
|
+
// Leave the parent's child list. v-if and v-for render every new clone
|
|
10778
|
+
// under the same parent VNode, so a destroyed clone left in the list
|
|
10779
|
+
// would keep its whole subtree — VNodes, DOM nodes, bindings — alive
|
|
10780
|
+
// for as long as the parent, growing with each toggle or row change.
|
|
10781
|
+
const siblings = this.#parentVNode ? this.#parentVNode.#childVNodes : undefined;
|
|
10782
|
+
const index = siblings ? siblings.indexOf(this) : -1;
|
|
10783
|
+
if (index !== -1) {
|
|
10784
|
+
siblings.splice(index, 1);
|
|
10785
|
+
}
|
|
10511
10786
|
}
|
|
10512
10787
|
}
|
|
10513
10788
|
|
|
@@ -15510,9 +15785,13 @@
|
|
|
15510
15785
|
* microtask fires, so data() can read them. A component used without any prop
|
|
15511
15786
|
* binding still mounts — with its declared defaults — instead of waiting forever.
|
|
15512
15787
|
*
|
|
15513
|
-
* Slot content is captured on the first
|
|
15514
|
-
*
|
|
15515
|
-
*
|
|
15788
|
+
* Slot content is captured on the first expansion and cached. The nodes are the
|
|
15789
|
+
* parent application's compiled nodes and are only ever moved, never cloned:
|
|
15790
|
+
* each `<slot>` outlet the component renders moves them into place
|
|
15791
|
+
* (VStaticSlotOutletDirective; scoped `<template v-slot>` content is rendered
|
|
15792
|
+
* per outlet by VSlotOutletDirective instead). A component that is moved in
|
|
15793
|
+
* the DOM (e.g. reordered by v-for) re-expands its template, and its outlets
|
|
15794
|
+
* move the same nodes into the fresh expansion.
|
|
15516
15795
|
*
|
|
15517
15796
|
* Subclasses must set the static fields _template, _props, _propOptions and
|
|
15518
15797
|
* _buildOptions before calling customElements.define(). defineComponent()
|
|
@@ -15537,12 +15816,13 @@
|
|
|
15537
15816
|
*/
|
|
15538
15817
|
#mountScheduled = false;
|
|
15539
15818
|
/**
|
|
15540
|
-
* Slot content captured on the first
|
|
15819
|
+
* Slot content captured on the first expansion. Reused on reconnection
|
|
15541
15820
|
* (v-for reorder moves the host element, which re-runs connectedCallback
|
|
15542
15821
|
* with the previously expanded template as children — not authored slot
|
|
15543
|
-
* content — so the original capture must be
|
|
15544
|
-
* `
|
|
15545
|
-
*
|
|
15822
|
+
* content — so the original capture must be used instead).
|
|
15823
|
+
* `defaultNodes` / `namedNodes` are moved into place by
|
|
15824
|
+
* VStaticSlotOutletDirective; `scopedSlots` holds `<template v-slot:...>`
|
|
15825
|
+
* children by slot name, rendered per outlet by VSlotOutletDirective.
|
|
15546
15826
|
*/
|
|
15547
15827
|
#slotCache;
|
|
15548
15828
|
/**
|
|
@@ -15560,6 +15840,18 @@
|
|
|
15560
15840
|
get _ichigoScopedSlots() {
|
|
15561
15841
|
return this.#slotCache?.scopedSlots;
|
|
15562
15842
|
}
|
|
15843
|
+
/**
|
|
15844
|
+
* The static slot content captured for the given slot name ('default'
|
|
15845
|
+
* for the unnamed slot): the parent application's nodes, moved into place
|
|
15846
|
+
* by VStaticSlotOutletDirective. Undefined when nothing was provided for
|
|
15847
|
+
* that name, in which case the outlet's fallback content renders.
|
|
15848
|
+
*/
|
|
15849
|
+
_ichigoSlotNodes(name) {
|
|
15850
|
+
const nodes = name === 'default'
|
|
15851
|
+
? this.#slotCache?.defaultNodes
|
|
15852
|
+
: this.#slotCache?.namedNodes.get(name);
|
|
15853
|
+
return nodes && nodes.length > 0 ? nodes : undefined;
|
|
15854
|
+
}
|
|
15563
15855
|
/**
|
|
15564
15856
|
* Handles RE-attachment, and nothing else.
|
|
15565
15857
|
*
|
|
@@ -15661,29 +15953,23 @@
|
|
|
15661
15953
|
}
|
|
15662
15954
|
this.#slotCache = { defaultNodes, namedNodes, scopedSlots };
|
|
15663
15955
|
}
|
|
15664
|
-
const { defaultNodes, namedNodes } = this.#slotCache;
|
|
15665
15956
|
// Clear host element so we can append the cloned template.
|
|
15666
15957
|
// (On reconnection this discards the previous expansion; the cached slot
|
|
15667
|
-
// nodes are still referenced and are moved into the fresh
|
|
15958
|
+
// nodes are still referenced and are moved into the fresh expansion by
|
|
15959
|
+
// its outlets.)
|
|
15960
|
+
// The slot nodes are NOT distributed into the template here: they are
|
|
15961
|
+
// the parent application's live, compiled nodes, and a <slot> behind a
|
|
15962
|
+
// v-if / v-for in the template is cloned with its surroundings — which
|
|
15963
|
+
// would render dead copies without their bindings, listeners or props.
|
|
15964
|
+
// They stay parked in the cache until a <slot> outlet is rendered, and
|
|
15965
|
+
// VStaticSlotOutletDirective then moves them into place.
|
|
15668
15966
|
while (this.firstChild) {
|
|
15669
15967
|
this.removeChild(this.firstChild);
|
|
15670
15968
|
}
|
|
15671
15969
|
// --- 2. Clone the component template ---
|
|
15672
15970
|
const fragment = templateEl.content.cloneNode(true);
|
|
15673
15971
|
const root = this.#findRootElement(fragment);
|
|
15674
|
-
//
|
|
15675
|
-
for (const [name, nodes] of namedNodes) {
|
|
15676
|
-
const slot = root.querySelector(`slot[name="${name}"]`);
|
|
15677
|
-
if (slot) {
|
|
15678
|
-
slot.replaceWith(...nodes);
|
|
15679
|
-
}
|
|
15680
|
-
}
|
|
15681
|
-
// --- 4. Distribute default slot content ---
|
|
15682
|
-
const defaultSlot = root.querySelector('slot:not([name])');
|
|
15683
|
-
if (defaultSlot && defaultNodes.length > 0) {
|
|
15684
|
-
defaultSlot.replaceWith(...defaultNodes);
|
|
15685
|
-
}
|
|
15686
|
-
// Attach the populated template to the host element
|
|
15972
|
+
// Attach the template to the host element
|
|
15687
15973
|
this.appendChild(root);
|
|
15688
15974
|
this.#mountRoot = root;
|
|
15689
15975
|
this._ichigoExpanded = true;
|