@mintjamsinc/ichigojs 0.1.80 → 0.1.82
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 +347 -36
- package/dist/ichigo.cjs.map +1 -1
- package/dist/ichigo.esm.js +347 -36
- package/dist/ichigo.esm.js.map +1 -1
- package/dist/ichigo.esm.min.js +1 -1
- package/dist/ichigo.min.cjs +1 -1
- package/dist/ichigo.umd.js +347 -36
- package/dist/ichigo.umd.js.map +1 -1
- package/dist/ichigo.umd.min.js +1 -1
- package/dist/types/ichigo/VNode.d.ts +11 -2
- package/dist/types/ichigo/components/IchigoElement.d.ts +14 -3
- package/dist/types/ichigo/directives/VDirective.d.ts +8 -0
- package/dist/types/ichigo/directives/VSlotOutletDirective.d.ts +7 -3
- package/dist/types/ichigo/directives/VStaticSlotOutletDirective.d.ts +129 -0
- package/package.json +1 -1
- package/dist/ichigo.esm.min.js.map +0 -1
- package/dist/ichigo.umd.min.js.map +0 -1
- package/dist/types/ichigo/ExpressionEvaluator.d.ts +0 -118
- package/dist/types/ichigo/VComponent.d.ts +0 -2
- package/dist/types/ichigo/VComponentRegistry.d.ts +0 -2
- package/dist/types/ichigo/VUpdateContext.d.ts +0 -21
- package/dist/types/ichigo/directives/VBindingsPreparer.d.ts +0 -24
- package/dist/types/ichigo/directives/VDOMUpdater.d.ts +0 -17
- package/dist/types/ichigo/util/BindingsUtils.d.ts +0 -10
- package/dist/types/ichigo/util/VLogLevel.d.ts +0 -9
package/dist/ichigo.esm.js
CHANGED
|
@@ -8984,9 +8984,9 @@ class IchigoElementRegistry {
|
|
|
8984
8984
|
* ```
|
|
8985
8985
|
*
|
|
8986
8986
|
* This directive is created only when a scoped template for the slot's name
|
|
8987
|
-
* exists (see {@link VSlotOutletDirective.tryCreate}); otherwise
|
|
8988
|
-
*
|
|
8989
|
-
*
|
|
8987
|
+
* exists (see {@link VSlotOutletDirective.tryCreate}); otherwise plain slot
|
|
8988
|
+
* content is moved into place by VStaticSlotOutletDirective, and a `<slot>`
|
|
8989
|
+
* with no content at all renders its fallback in the component scope.
|
|
8990
8990
|
*
|
|
8991
8991
|
* Rendering happens synchronously in onMount — before the component
|
|
8992
8992
|
* application would compile the slot's fallback children — by replacing the
|
|
@@ -9239,9 +9239,18 @@ class VSlotOutletDirective {
|
|
|
9239
9239
|
slot.replaceWith(fragment);
|
|
9240
9240
|
// Initial rendering
|
|
9241
9241
|
this.#contentVNode.forceUpdate();
|
|
9242
|
-
// Components in the slot content expand once it is in the document
|
|
9242
|
+
// Components in the slot content expand once it is in the document:
|
|
9243
|
+
// now, if the outlet is connected, or — when it renders inside a
|
|
9244
|
+
// detached v-if / v-for clone — through expandComponents() below, when
|
|
9245
|
+
// the directive that inserts the clone walks it.
|
|
9243
9246
|
this.#contentVNode.expandComponents();
|
|
9244
9247
|
}
|
|
9248
|
+
/**
|
|
9249
|
+
* @inheritdoc
|
|
9250
|
+
*/
|
|
9251
|
+
expandComponents() {
|
|
9252
|
+
this.#contentVNode?.expandComponents();
|
|
9253
|
+
}
|
|
9245
9254
|
/**
|
|
9246
9255
|
* Re-evaluates the slot props (component-side change) and pushes them into
|
|
9247
9256
|
* the content scope.
|
|
@@ -9269,6 +9278,266 @@ class VSlotOutletDirective {
|
|
|
9269
9278
|
}
|
|
9270
9279
|
}
|
|
9271
9280
|
|
|
9281
|
+
// Copyright (c) 2025 MintJams Inc. Licensed under MIT License.
|
|
9282
|
+
/**
|
|
9283
|
+
* Renders a static slot outlet: a `<slot>` element inside a component template
|
|
9284
|
+
* whose host element received plain slot content from the parent — child
|
|
9285
|
+
* nodes for the default slot, or elements carrying `slot="name"`:
|
|
9286
|
+
*
|
|
9287
|
+
* ```html
|
|
9288
|
+
* <!-- component template -->
|
|
9289
|
+
* <div v-if="open" class="body"><slot></slot></div>
|
|
9290
|
+
*
|
|
9291
|
+
* <!-- usage -->
|
|
9292
|
+
* <my-dialog :open="show">
|
|
9293
|
+
* <my-field :label="title"></my-field>
|
|
9294
|
+
* </my-dialog>
|
|
9295
|
+
* ```
|
|
9296
|
+
*
|
|
9297
|
+
* The slot content is the parent application's own nodes, compiled in the
|
|
9298
|
+
* parent scope; it keeps its bindings, listeners and component props only as
|
|
9299
|
+
* long as those very nodes are displayed. So the outlet MOVES them into place
|
|
9300
|
+
* and never clones them. That is what lets a `<slot>` sit behind a v-if or
|
|
9301
|
+
* v-for in the component template: the directive clones its template source,
|
|
9302
|
+
* the clone carries a fresh `<slot>`, and the outlet created for that clone
|
|
9303
|
+
* moves the live nodes in.
|
|
9304
|
+
*
|
|
9305
|
+
* Nodes can only be in one place, so when the same slot is rendered more than
|
|
9306
|
+
* once (e.g. a `<slot>` inside a v-for), the outlet rendered last receives the
|
|
9307
|
+
* content and the earlier ones are left empty. When the outlet holding the
|
|
9308
|
+
* content goes away while others remain (its row is removed), the content
|
|
9309
|
+
* moves to the last remaining one. For content per row, use a scoped slot
|
|
9310
|
+
* (`<template v-slot:name="scope">`), which renders a copy per outlet
|
|
9311
|
+
* (VSlotOutletDirective).
|
|
9312
|
+
*
|
|
9313
|
+
* The component application never compiles the moved nodes: they are placed
|
|
9314
|
+
* in onMount, after the parent VNode has taken its snapshot of the children
|
|
9315
|
+
* to compile. Components inside them belong to the parent application, which
|
|
9316
|
+
* expands them through {@link expandComponents} once they are in the document.
|
|
9317
|
+
* When the last outlet goes away (its v-if turns false) the nodes leave with
|
|
9318
|
+
* the removed clone and wait there until the next outlet moves them again;
|
|
9319
|
+
* they are not destroyed, because they are not this application's to destroy.
|
|
9320
|
+
*
|
|
9321
|
+
* Created only when the host captured content for the slot's name and no
|
|
9322
|
+
* scoped template claims it; otherwise the `<slot>` element renders its
|
|
9323
|
+
* fallback children in the component scope.
|
|
9324
|
+
*/
|
|
9325
|
+
class VStaticSlotOutletDirective {
|
|
9326
|
+
/**
|
|
9327
|
+
* The live outlets of each slot, in the order they were rendered, keyed by
|
|
9328
|
+
* the slot's node array (one per host element and slot name). The last
|
|
9329
|
+
* one holds the content.
|
|
9330
|
+
*/
|
|
9331
|
+
static #outlets = new WeakMap();
|
|
9332
|
+
/**
|
|
9333
|
+
* Marks where the `<slot>` element was, so the content can be moved back
|
|
9334
|
+
* here when a later outlet of the same slot goes away.
|
|
9335
|
+
*/
|
|
9336
|
+
#anchor;
|
|
9337
|
+
/**
|
|
9338
|
+
* Guards against double destruction.
|
|
9339
|
+
*/
|
|
9340
|
+
#destroyed = false;
|
|
9341
|
+
/**
|
|
9342
|
+
* The virtual node of the `<slot>` element (in the component application).
|
|
9343
|
+
*/
|
|
9344
|
+
#vNode;
|
|
9345
|
+
/**
|
|
9346
|
+
* The slot content: the parent application's nodes, shared with the host
|
|
9347
|
+
* element's slot cache.
|
|
9348
|
+
*/
|
|
9349
|
+
#nodes;
|
|
9350
|
+
/**
|
|
9351
|
+
* The host element's VNode in the parent application, whose children are
|
|
9352
|
+
* the VNodes of the slot content. Undefined when the host was not compiled
|
|
9353
|
+
* by an application (then there is nothing to expand).
|
|
9354
|
+
*/
|
|
9355
|
+
#hostVNode;
|
|
9356
|
+
/**
|
|
9357
|
+
* Creates a static slot outlet for the given `<slot>` VNode when the host
|
|
9358
|
+
* element captured content for its slot name. Returns undefined when there
|
|
9359
|
+
* is none, so the `<slot>` element keeps rendering its fallback content.
|
|
9360
|
+
*/
|
|
9361
|
+
static tryCreate(vNode) {
|
|
9362
|
+
const host = vNode.vApplication.hostElement;
|
|
9363
|
+
if (!host || typeof host._ichigoSlotNodes !== 'function') {
|
|
9364
|
+
return undefined;
|
|
9365
|
+
}
|
|
9366
|
+
const element = vNode.node;
|
|
9367
|
+
const nodes = host._ichigoSlotNodes(element.getAttribute('name') || 'default');
|
|
9368
|
+
if (!nodes) {
|
|
9369
|
+
return undefined;
|
|
9370
|
+
}
|
|
9371
|
+
return new VStaticSlotOutletDirective(vNode, nodes, host._ichigoHost?.vNode);
|
|
9372
|
+
}
|
|
9373
|
+
constructor(vNode, nodes, hostVNode) {
|
|
9374
|
+
this.#vNode = vNode;
|
|
9375
|
+
this.#nodes = nodes;
|
|
9376
|
+
this.#hostVNode = hostVNode;
|
|
9377
|
+
// Slot props (v-bind / :) only mean something to a scoped template.
|
|
9378
|
+
// Consume them so the generic attribute parsing does not evaluate them
|
|
9379
|
+
// on an element that is about to leave the document.
|
|
9380
|
+
const element = vNode.node;
|
|
9381
|
+
for (const attr of Array.from(element.attributes)) {
|
|
9382
|
+
if (attr.name.startsWith('v-bind:') || attr.name.startsWith(':')) {
|
|
9383
|
+
element.removeAttribute(attr.name);
|
|
9384
|
+
}
|
|
9385
|
+
}
|
|
9386
|
+
}
|
|
9387
|
+
/**
|
|
9388
|
+
* @inheritdoc
|
|
9389
|
+
*/
|
|
9390
|
+
get name() {
|
|
9391
|
+
return 'static-slot-outlet';
|
|
9392
|
+
}
|
|
9393
|
+
/**
|
|
9394
|
+
* @inheritdoc
|
|
9395
|
+
*/
|
|
9396
|
+
get vNode() {
|
|
9397
|
+
return this.#vNode;
|
|
9398
|
+
}
|
|
9399
|
+
/**
|
|
9400
|
+
* @inheritdoc
|
|
9401
|
+
*/
|
|
9402
|
+
get needsAnchor() {
|
|
9403
|
+
return false;
|
|
9404
|
+
}
|
|
9405
|
+
/**
|
|
9406
|
+
* @inheritdoc
|
|
9407
|
+
*/
|
|
9408
|
+
get bindingsPreparer() {
|
|
9409
|
+
return undefined;
|
|
9410
|
+
}
|
|
9411
|
+
/**
|
|
9412
|
+
* @inheritdoc
|
|
9413
|
+
*/
|
|
9414
|
+
get domUpdater() {
|
|
9415
|
+
return undefined;
|
|
9416
|
+
}
|
|
9417
|
+
/**
|
|
9418
|
+
* @inheritdoc
|
|
9419
|
+
*/
|
|
9420
|
+
get templatize() {
|
|
9421
|
+
return false;
|
|
9422
|
+
}
|
|
9423
|
+
/**
|
|
9424
|
+
* @inheritdoc
|
|
9425
|
+
*/
|
|
9426
|
+
get dependentIdentifiers() {
|
|
9427
|
+
return [];
|
|
9428
|
+
}
|
|
9429
|
+
/**
|
|
9430
|
+
* @inheritdoc
|
|
9431
|
+
*
|
|
9432
|
+
* Moves the slot content in place of the `<slot>` element — synchronously
|
|
9433
|
+
* during VNode construction, before the component application would
|
|
9434
|
+
* compile the slot's fallback children (which the content replaces).
|
|
9435
|
+
*/
|
|
9436
|
+
get onMount() {
|
|
9437
|
+
return () => {
|
|
9438
|
+
const slot = this.#vNode.node;
|
|
9439
|
+
while (slot.firstChild) {
|
|
9440
|
+
slot.removeChild(slot.firstChild);
|
|
9441
|
+
}
|
|
9442
|
+
this.#anchor = document.createComment('slot');
|
|
9443
|
+
slot.replaceWith(this.#anchor);
|
|
9444
|
+
let outlets = VStaticSlotOutletDirective.#outlets.get(this.#nodes);
|
|
9445
|
+
if (!outlets) {
|
|
9446
|
+
outlets = [];
|
|
9447
|
+
VStaticSlotOutletDirective.#outlets.set(this.#nodes, outlets);
|
|
9448
|
+
}
|
|
9449
|
+
outlets.push(this);
|
|
9450
|
+
this.#place();
|
|
9451
|
+
};
|
|
9452
|
+
}
|
|
9453
|
+
/**
|
|
9454
|
+
* @inheritdoc
|
|
9455
|
+
*/
|
|
9456
|
+
get onMounted() {
|
|
9457
|
+
return undefined;
|
|
9458
|
+
}
|
|
9459
|
+
/**
|
|
9460
|
+
* @inheritdoc
|
|
9461
|
+
*/
|
|
9462
|
+
get onUpdate() {
|
|
9463
|
+
return undefined;
|
|
9464
|
+
}
|
|
9465
|
+
/**
|
|
9466
|
+
* @inheritdoc
|
|
9467
|
+
*/
|
|
9468
|
+
get onUpdated() {
|
|
9469
|
+
return undefined;
|
|
9470
|
+
}
|
|
9471
|
+
/**
|
|
9472
|
+
* @inheritdoc
|
|
9473
|
+
*/
|
|
9474
|
+
get onUnmount() {
|
|
9475
|
+
return undefined;
|
|
9476
|
+
}
|
|
9477
|
+
/**
|
|
9478
|
+
* @inheritdoc
|
|
9479
|
+
*/
|
|
9480
|
+
get onUnmounted() {
|
|
9481
|
+
return undefined;
|
|
9482
|
+
}
|
|
9483
|
+
/**
|
|
9484
|
+
* @inheritdoc
|
|
9485
|
+
*
|
|
9486
|
+
* Expands the components in the slot content through the parent
|
|
9487
|
+
* application's VNodes. Called by the walk of whoever inserted this
|
|
9488
|
+
* outlet into the document (VApplication.mount, v-if, v-for), so the
|
|
9489
|
+
* content is connected by now — unless a later outlet took it, in which
|
|
9490
|
+
* case that outlet's walk expands it.
|
|
9491
|
+
*/
|
|
9492
|
+
expandComponents() {
|
|
9493
|
+
const children = this.#hostVNode?.childVNodes;
|
|
9494
|
+
if (!children) {
|
|
9495
|
+
return;
|
|
9496
|
+
}
|
|
9497
|
+
for (const child of children) {
|
|
9498
|
+
if (this.#nodes.includes(child.node)) {
|
|
9499
|
+
child.expandComponents();
|
|
9500
|
+
}
|
|
9501
|
+
}
|
|
9502
|
+
}
|
|
9503
|
+
/**
|
|
9504
|
+
* @inheritdoc
|
|
9505
|
+
*
|
|
9506
|
+
* The slot content is the parent application's; nothing to release here.
|
|
9507
|
+
*/
|
|
9508
|
+
destroy() {
|
|
9509
|
+
if (this.#destroyed) {
|
|
9510
|
+
return;
|
|
9511
|
+
}
|
|
9512
|
+
this.#destroyed = true;
|
|
9513
|
+
const outlets = VStaticSlotOutletDirective.#outlets.get(this.#nodes);
|
|
9514
|
+
if (!outlets) {
|
|
9515
|
+
return;
|
|
9516
|
+
}
|
|
9517
|
+
const index = outlets.indexOf(this);
|
|
9518
|
+
if (index === -1) {
|
|
9519
|
+
return;
|
|
9520
|
+
}
|
|
9521
|
+
const wasHolder = index === outlets.length - 1;
|
|
9522
|
+
outlets.splice(index, 1);
|
|
9523
|
+
// Hand the content to the last remaining outlet before this one's DOM
|
|
9524
|
+
// is removed (v-if / v-for destroy the VNode first, then remove it),
|
|
9525
|
+
// so removing the row that shows it does not take it out of view.
|
|
9526
|
+
const next = outlets[outlets.length - 1];
|
|
9527
|
+
if (wasHolder && next) {
|
|
9528
|
+
next.#place();
|
|
9529
|
+
next.expandComponents();
|
|
9530
|
+
}
|
|
9531
|
+
}
|
|
9532
|
+
/**
|
|
9533
|
+
* Moves the slot content right after this outlet's anchor. Moving, not
|
|
9534
|
+
* cloning: nodes shown by another outlet of the same slot leave it.
|
|
9535
|
+
*/
|
|
9536
|
+
#place() {
|
|
9537
|
+
this.#anchor?.after(...this.#nodes);
|
|
9538
|
+
}
|
|
9539
|
+
}
|
|
9540
|
+
|
|
9272
9541
|
// Copyright (c) 2025 MintJams Inc. Licensed under MIT License.
|
|
9273
9542
|
/**
|
|
9274
9543
|
* Manages directives associated with a virtual node (VNode).
|
|
@@ -9437,10 +9706,12 @@ class VDirectiveManager {
|
|
|
9437
9706
|
const element = this.#vNode.node;
|
|
9438
9707
|
// Parse directives from attributes
|
|
9439
9708
|
const directives = [];
|
|
9440
|
-
//
|
|
9441
|
-
//
|
|
9442
|
-
//
|
|
9443
|
-
//
|
|
9709
|
+
// Slot outlet: a <slot> element (without structural directives) inside a
|
|
9710
|
+
// component whose host received content for it — a matching
|
|
9711
|
+
// <template v-slot:...> (rendered per outlet), or else plain slot
|
|
9712
|
+
// content (moved into place). This is an element-based directive,
|
|
9713
|
+
// created before the generic attribute parsing so it can consume the
|
|
9714
|
+
// slot-prop bindings (:x).
|
|
9444
9715
|
// A <slot> carrying v-if / v-for is handled structurally first; the
|
|
9445
9716
|
// outlet is then created when the clone is compiled.
|
|
9446
9717
|
if (element.tagName === 'SLOT' &&
|
|
@@ -9448,7 +9719,8 @@ class VDirectiveManager {
|
|
|
9448
9719
|
!element.hasAttribute(StandardDirectiveName.V_IF) &&
|
|
9449
9720
|
!element.hasAttribute(StandardDirectiveName.V_ELSE_IF) &&
|
|
9450
9721
|
!element.hasAttribute(StandardDirectiveName.V_ELSE)) {
|
|
9451
|
-
const outlet = VSlotOutletDirective.tryCreate(this.#vNode)
|
|
9722
|
+
const outlet = VSlotOutletDirective.tryCreate(this.#vNode)
|
|
9723
|
+
?? VStaticSlotOutletDirective.tryCreate(this.#vNode);
|
|
9452
9724
|
if (outlet) {
|
|
9453
9725
|
directives.push(outlet);
|
|
9454
9726
|
}
|
|
@@ -9857,6 +10129,12 @@ class VNode {
|
|
|
9857
10129
|
* remove the entire fragment atomically.
|
|
9858
10130
|
*/
|
|
9859
10131
|
#fragmentRange;
|
|
10132
|
+
/**
|
|
10133
|
+
* Set by {@link destroy}. A destroyed clone stays in its parent's child
|
|
10134
|
+
* list (v-if / v-for render new clones under the same parent), so walks
|
|
10135
|
+
* over the children must skip it.
|
|
10136
|
+
*/
|
|
10137
|
+
#destroyed = false;
|
|
9860
10138
|
/**
|
|
9861
10139
|
* Custom element tags already reported by
|
|
9862
10140
|
* {@link VNode.#warnIfUnknownCustomElement}.
|
|
@@ -9990,19 +10268,40 @@ class VNode {
|
|
|
9990
10268
|
* Walking only {@link childVNodes} keeps the traversal inside this
|
|
9991
10269
|
* application: the internals of an expanded component were never compiled
|
|
9992
10270
|
* here, so they are not reachable and are left to their own application.
|
|
9993
|
-
*
|
|
9994
|
-
*
|
|
10271
|
+
* The one exception is content a directive rendered outside its own
|
|
10272
|
+
* children — scoped slot content — reached through
|
|
10273
|
+
* {@link VDirective.expandComponents}.
|
|
10274
|
+
*
|
|
10275
|
+
* Only connected elements are expanded. v-if / v-for call this right after
|
|
10276
|
+
* inserting a clone, but when that clone sits inside another clone that is
|
|
10277
|
+
* still detached (nested directives, or slot content rendered by an outlet
|
|
10278
|
+
* inside a component's v-if), the insertion is not into the document yet;
|
|
10279
|
+
* the outer inserter's walk reaches the same nodes once it is. A
|
|
10280
|
+
* templatized node (a v-if / v-for source) is not expanded itself, but its
|
|
10281
|
+
* rendered clones are its children and are walked.
|
|
9995
10282
|
*/
|
|
9996
10283
|
expandComponents() {
|
|
9997
|
-
if (this.#
|
|
10284
|
+
if (this.#destroyed) {
|
|
9998
10285
|
return;
|
|
9999
10286
|
}
|
|
10000
|
-
|
|
10287
|
+
// Expand only a connected element. A subtree compiled and inserted
|
|
10288
|
+
// into a still-detached clone (a v-if / v-for nested in another
|
|
10289
|
+
// clone, or in scoped slot content rendered inside one) is reached
|
|
10290
|
+
// again by the walk of whoever inserts that clone into the document —
|
|
10291
|
+
// and by then its elements are upgraded and ready to expand.
|
|
10292
|
+
// A templatized node is a template source: never expanded itself,
|
|
10293
|
+
// but its rendered clones are its child VNodes and are walked below.
|
|
10294
|
+
if (!this.#templatized && this.#nodeType === Node.ELEMENT_NODE && IchigoElementRegistry.has(this.#nodeName)) {
|
|
10001
10295
|
const element = this.#node;
|
|
10002
|
-
if (element._ichigoExpanded !== true) {
|
|
10296
|
+
if (element._ichigoExpanded !== true && element.isConnected) {
|
|
10003
10297
|
element._ichigoExpand?.();
|
|
10004
10298
|
}
|
|
10005
10299
|
}
|
|
10300
|
+
// Subtrees a directive rendered outside this VNode's children (the
|
|
10301
|
+
// scoped slot content of a <slot> outlet) are expanded here too: this
|
|
10302
|
+
// walk runs once the subtree is in the document, which the outlet
|
|
10303
|
+
// cannot know when it renders inside a detached v-if / v-for clone.
|
|
10304
|
+
this.#directiveManager?.directives?.forEach(d => d.expandComponents?.());
|
|
10006
10305
|
this.#childVNodes?.forEach(child => child.expandComponents());
|
|
10007
10306
|
}
|
|
10008
10307
|
/**
|
|
@@ -10412,6 +10711,7 @@ class VNode {
|
|
|
10412
10711
|
* 6. Call onUnmounted lifecycle hooks
|
|
10413
10712
|
*/
|
|
10414
10713
|
destroy() {
|
|
10714
|
+
this.#destroyed = true;
|
|
10415
10715
|
// If no directive requires template preservation, call onUnmount for directives that do not templatize
|
|
10416
10716
|
if (!this.#templatized) {
|
|
10417
10717
|
this.#directiveManager?.directives?.forEach(d => {
|
|
@@ -15467,9 +15767,13 @@ class VDOM {
|
|
|
15467
15767
|
* microtask fires, so data() can read them. A component used without any prop
|
|
15468
15768
|
* binding still mounts — with its declared defaults — instead of waiting forever.
|
|
15469
15769
|
*
|
|
15470
|
-
* Slot content is captured on the first
|
|
15471
|
-
*
|
|
15472
|
-
*
|
|
15770
|
+
* Slot content is captured on the first expansion and cached. The nodes are the
|
|
15771
|
+
* parent application's compiled nodes and are only ever moved, never cloned:
|
|
15772
|
+
* each `<slot>` outlet the component renders moves them into place
|
|
15773
|
+
* (VStaticSlotOutletDirective; scoped `<template v-slot>` content is rendered
|
|
15774
|
+
* per outlet by VSlotOutletDirective instead). A component that is moved in
|
|
15775
|
+
* the DOM (e.g. reordered by v-for) re-expands its template, and its outlets
|
|
15776
|
+
* move the same nodes into the fresh expansion.
|
|
15473
15777
|
*
|
|
15474
15778
|
* Subclasses must set the static fields _template, _props, _propOptions and
|
|
15475
15779
|
* _buildOptions before calling customElements.define(). defineComponent()
|
|
@@ -15494,12 +15798,13 @@ class IchigoElement extends HTMLElement {
|
|
|
15494
15798
|
*/
|
|
15495
15799
|
#mountScheduled = false;
|
|
15496
15800
|
/**
|
|
15497
|
-
* Slot content captured on the first
|
|
15801
|
+
* Slot content captured on the first expansion. Reused on reconnection
|
|
15498
15802
|
* (v-for reorder moves the host element, which re-runs connectedCallback
|
|
15499
15803
|
* with the previously expanded template as children — not authored slot
|
|
15500
|
-
* content — so the original capture must be
|
|
15501
|
-
* `
|
|
15502
|
-
*
|
|
15804
|
+
* content — so the original capture must be used instead).
|
|
15805
|
+
* `defaultNodes` / `namedNodes` are moved into place by
|
|
15806
|
+
* VStaticSlotOutletDirective; `scopedSlots` holds `<template v-slot:...>`
|
|
15807
|
+
* children by slot name, rendered per outlet by VSlotOutletDirective.
|
|
15503
15808
|
*/
|
|
15504
15809
|
#slotCache;
|
|
15505
15810
|
/**
|
|
@@ -15517,6 +15822,18 @@ class IchigoElement extends HTMLElement {
|
|
|
15517
15822
|
get _ichigoScopedSlots() {
|
|
15518
15823
|
return this.#slotCache?.scopedSlots;
|
|
15519
15824
|
}
|
|
15825
|
+
/**
|
|
15826
|
+
* The static slot content captured for the given slot name ('default'
|
|
15827
|
+
* for the unnamed slot): the parent application's nodes, moved into place
|
|
15828
|
+
* by VStaticSlotOutletDirective. Undefined when nothing was provided for
|
|
15829
|
+
* that name, in which case the outlet's fallback content renders.
|
|
15830
|
+
*/
|
|
15831
|
+
_ichigoSlotNodes(name) {
|
|
15832
|
+
const nodes = name === 'default'
|
|
15833
|
+
? this.#slotCache?.defaultNodes
|
|
15834
|
+
: this.#slotCache?.namedNodes.get(name);
|
|
15835
|
+
return nodes && nodes.length > 0 ? nodes : undefined;
|
|
15836
|
+
}
|
|
15520
15837
|
/**
|
|
15521
15838
|
* Handles RE-attachment, and nothing else.
|
|
15522
15839
|
*
|
|
@@ -15618,29 +15935,23 @@ class IchigoElement extends HTMLElement {
|
|
|
15618
15935
|
}
|
|
15619
15936
|
this.#slotCache = { defaultNodes, namedNodes, scopedSlots };
|
|
15620
15937
|
}
|
|
15621
|
-
const { defaultNodes, namedNodes } = this.#slotCache;
|
|
15622
15938
|
// Clear host element so we can append the cloned template.
|
|
15623
15939
|
// (On reconnection this discards the previous expansion; the cached slot
|
|
15624
|
-
// nodes are still referenced and are moved into the fresh
|
|
15940
|
+
// nodes are still referenced and are moved into the fresh expansion by
|
|
15941
|
+
// its outlets.)
|
|
15942
|
+
// The slot nodes are NOT distributed into the template here: they are
|
|
15943
|
+
// the parent application's live, compiled nodes, and a <slot> behind a
|
|
15944
|
+
// v-if / v-for in the template is cloned with its surroundings — which
|
|
15945
|
+
// would render dead copies without their bindings, listeners or props.
|
|
15946
|
+
// They stay parked in the cache until a <slot> outlet is rendered, and
|
|
15947
|
+
// VStaticSlotOutletDirective then moves them into place.
|
|
15625
15948
|
while (this.firstChild) {
|
|
15626
15949
|
this.removeChild(this.firstChild);
|
|
15627
15950
|
}
|
|
15628
15951
|
// --- 2. Clone the component template ---
|
|
15629
15952
|
const fragment = templateEl.content.cloneNode(true);
|
|
15630
15953
|
const root = this.#findRootElement(fragment);
|
|
15631
|
-
//
|
|
15632
|
-
for (const [name, nodes] of namedNodes) {
|
|
15633
|
-
const slot = root.querySelector(`slot[name="${name}"]`);
|
|
15634
|
-
if (slot) {
|
|
15635
|
-
slot.replaceWith(...nodes);
|
|
15636
|
-
}
|
|
15637
|
-
}
|
|
15638
|
-
// --- 4. Distribute default slot content ---
|
|
15639
|
-
const defaultSlot = root.querySelector('slot:not([name])');
|
|
15640
|
-
if (defaultSlot && defaultNodes.length > 0) {
|
|
15641
|
-
defaultSlot.replaceWith(...defaultNodes);
|
|
15642
|
-
}
|
|
15643
|
-
// Attach the populated template to the host element
|
|
15954
|
+
// Attach the template to the host element
|
|
15644
15955
|
this.appendChild(root);
|
|
15645
15956
|
this.#mountRoot = root;
|
|
15646
15957
|
this._ichigoExpanded = true;
|