@mintjamsinc/ichigojs 0.1.82 → 0.1.84
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/ichigo.cjs +133 -10
- package/dist/ichigo.cjs.map +1 -1
- package/dist/ichigo.esm.js +133 -10
- 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 +133 -10
- 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/directives/VBindingsPreparer.d.ts +24 -0
- package/dist/types/ichigo/directives/VDOMUpdater.d.ts +17 -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/dist/ichigo.esm.js
CHANGED
|
@@ -10130,9 +10130,9 @@ class VNode {
|
|
|
10130
10130
|
*/
|
|
10131
10131
|
#fragmentRange;
|
|
10132
10132
|
/**
|
|
10133
|
-
* Set by {@link destroy}. A destroyed
|
|
10134
|
-
* list
|
|
10135
|
-
*
|
|
10133
|
+
* Set by {@link destroy}. A destroyed node also leaves its parent's child
|
|
10134
|
+
* list, but a walk that took its copy of the list before the node was
|
|
10135
|
+
* destroyed may still reach it, and must skip it.
|
|
10136
10136
|
*/
|
|
10137
10137
|
#destroyed = false;
|
|
10138
10138
|
/**
|
|
@@ -10302,7 +10302,8 @@ class VNode {
|
|
|
10302
10302
|
// walk runs once the subtree is in the document, which the outlet
|
|
10303
10303
|
// cannot know when it renders inside a detached v-if / v-for clone.
|
|
10304
10304
|
this.#directiveManager?.directives?.forEach(d => d.expandComponents?.());
|
|
10305
|
-
this
|
|
10305
|
+
// A copy: expanding can render and destroy clones under this node.
|
|
10306
|
+
this.#childVNodes?.slice().forEach(child => child.expandComponents());
|
|
10306
10307
|
}
|
|
10307
10308
|
/**
|
|
10308
10309
|
* The application instance associated with this virtual node.
|
|
@@ -10614,8 +10615,9 @@ class VNode {
|
|
|
10614
10615
|
updater.applyToDOM();
|
|
10615
10616
|
}
|
|
10616
10617
|
}
|
|
10617
|
-
// Recursively update child virtual nodes
|
|
10618
|
-
this
|
|
10618
|
+
// Recursively update child virtual nodes. A copy: an update can
|
|
10619
|
+
// destroy a v-if / v-for clone, which removes it from this list.
|
|
10620
|
+
this.#childVNodes?.slice().forEach(childVNode => {
|
|
10619
10621
|
childVNode.forceUpdate();
|
|
10620
10622
|
});
|
|
10621
10623
|
// If no directive requires template preservation, call onUpdated for directives that do not templatize
|
|
@@ -10627,7 +10629,7 @@ class VNode {
|
|
|
10627
10629
|
}
|
|
10628
10630
|
else if (this.#nodeType === Node.DOCUMENT_FRAGMENT_NODE) {
|
|
10629
10631
|
// For document fragments, recursively force update child VNodes
|
|
10630
|
-
this.#childVNodes?.forEach(childVNode => {
|
|
10632
|
+
this.#childVNodes?.slice().forEach(childVNode => {
|
|
10631
10633
|
childVNode.forceUpdate();
|
|
10632
10634
|
});
|
|
10633
10635
|
}
|
|
@@ -10709,6 +10711,7 @@ class VNode {
|
|
|
10709
10711
|
* 4. Unregister dependencies
|
|
10710
10712
|
* 5. Clean up directive manager
|
|
10711
10713
|
* 6. Call onUnmounted lifecycle hooks
|
|
10714
|
+
* 7. Leave the parent's child list
|
|
10712
10715
|
*/
|
|
10713
10716
|
destroy() {
|
|
10714
10717
|
this.#destroyed = true;
|
|
@@ -10735,9 +10738,9 @@ class VNode {
|
|
|
10735
10738
|
}
|
|
10736
10739
|
this.#userData.clear();
|
|
10737
10740
|
}
|
|
10738
|
-
// Recursively destroy child nodes
|
|
10741
|
+
// Recursively destroy child nodes (a copy: each one leaves this list)
|
|
10739
10742
|
if (this.#childVNodes) {
|
|
10740
|
-
for (const childVNode of this.#childVNodes) {
|
|
10743
|
+
for (const childVNode of this.#childVNodes.slice()) {
|
|
10741
10744
|
try {
|
|
10742
10745
|
childVNode.destroy();
|
|
10743
10746
|
}
|
|
@@ -10765,6 +10768,15 @@ class VNode {
|
|
|
10765
10768
|
d.onUnmounted?.();
|
|
10766
10769
|
});
|
|
10767
10770
|
}
|
|
10771
|
+
// Leave the parent's child list. v-if and v-for render every new clone
|
|
10772
|
+
// under the same parent VNode, so a destroyed clone left in the list
|
|
10773
|
+
// would keep its whole subtree — VNodes, DOM nodes, bindings — alive
|
|
10774
|
+
// for as long as the parent, growing with each toggle or row change.
|
|
10775
|
+
const siblings = this.#parentVNode ? this.#parentVNode.#childVNodes : undefined;
|
|
10776
|
+
const index = siblings ? siblings.indexOf(this) : -1;
|
|
10777
|
+
if (index !== -1) {
|
|
10778
|
+
siblings.splice(index, 1);
|
|
10779
|
+
}
|
|
10768
10780
|
}
|
|
10769
10781
|
}
|
|
10770
10782
|
|
|
@@ -11301,6 +11313,25 @@ class VForDirective {
|
|
|
11301
11313
|
* Previous iterations to detect changes
|
|
11302
11314
|
*/
|
|
11303
11315
|
#previousIterations = [];
|
|
11316
|
+
/**
|
|
11317
|
+
* The source array watched for writes made directly to it, and the function
|
|
11318
|
+
* that stops watching it.
|
|
11319
|
+
*
|
|
11320
|
+
* A write such as `items[1] = x` is reported as a change of "items[1]", which
|
|
11321
|
+
* does not match this directive's dependency on "items", and the row's loop
|
|
11322
|
+
* variable holds the value it was rendered with. The directive therefore
|
|
11323
|
+
* watches the array itself and refreshes the rows that were written.
|
|
11324
|
+
*/
|
|
11325
|
+
#watchedSource;
|
|
11326
|
+
#unwatchSource;
|
|
11327
|
+
/**
|
|
11328
|
+
* Positions written since the last refresh, and whether a write (such as one
|
|
11329
|
+
* to `length`) needs the whole list rendered again.
|
|
11330
|
+
*/
|
|
11331
|
+
#writtenIndexes = new Set();
|
|
11332
|
+
#writtenWhole = false;
|
|
11333
|
+
#refreshScheduled = false;
|
|
11334
|
+
#destroyed = false;
|
|
11304
11335
|
/**
|
|
11305
11336
|
* @param context The context for parsing the directive.
|
|
11306
11337
|
*/
|
|
@@ -11417,6 +11448,10 @@ class VForDirective {
|
|
|
11417
11448
|
* @inheritdoc
|
|
11418
11449
|
*/
|
|
11419
11450
|
destroy() {
|
|
11451
|
+
this.#destroyed = true;
|
|
11452
|
+
this.#unwatchSource?.();
|
|
11453
|
+
this.#unwatchSource = undefined;
|
|
11454
|
+
this.#watchedSource = undefined;
|
|
11420
11455
|
// Clean up all rendered items
|
|
11421
11456
|
// First destroy all VNodes (calls @unmount hooks), then remove from DOM
|
|
11422
11457
|
for (const { vNode } of this.#renderedItems) {
|
|
@@ -11448,6 +11483,10 @@ class VForDirective {
|
|
|
11448
11483
|
}
|
|
11449
11484
|
// Evaluate the source expression to get the data
|
|
11450
11485
|
const sourceData = this.#sourceEvaluator.evaluate();
|
|
11486
|
+
// Every row is rendered from the source below, including those written in place
|
|
11487
|
+
this.#watchSource(sourceData);
|
|
11488
|
+
this.#writtenIndexes.clear();
|
|
11489
|
+
this.#writtenWhole = false;
|
|
11451
11490
|
// Get iterations from the source data
|
|
11452
11491
|
let iterations = this.#getIterations(sourceData);
|
|
11453
11492
|
// If we don't have a key evaluator yet, try to create it
|
|
@@ -11841,6 +11880,89 @@ class VForDirective {
|
|
|
11841
11880
|
}
|
|
11842
11881
|
vNode.update();
|
|
11843
11882
|
}
|
|
11883
|
+
/**
|
|
11884
|
+
* Watches the source for writes made directly to its elements. Only a
|
|
11885
|
+
* reactive array can be written that way; anything else is not watched.
|
|
11886
|
+
*/
|
|
11887
|
+
#watchSource(source) {
|
|
11888
|
+
if (source === this.#watchedSource) {
|
|
11889
|
+
return;
|
|
11890
|
+
}
|
|
11891
|
+
this.#unwatchSource?.();
|
|
11892
|
+
this.#unwatchSource = undefined;
|
|
11893
|
+
this.#watchedSource = source;
|
|
11894
|
+
const path = Array.isArray(source) ? ReactiveProxy.getPath(source) : undefined;
|
|
11895
|
+
if (!path) {
|
|
11896
|
+
return;
|
|
11897
|
+
}
|
|
11898
|
+
this.#unwatchSource = ReactiveProxy.subscribe(source, (changedPath) => {
|
|
11899
|
+
this.#onSourceWritten(path, changedPath);
|
|
11900
|
+
});
|
|
11901
|
+
}
|
|
11902
|
+
/**
|
|
11903
|
+
* Notes a write made directly to the source array. A change below an
|
|
11904
|
+
* element (e.g. "items[1].name") is followed by the row's own bindings, and
|
|
11905
|
+
* a change of the whole array (e.g. by splice) by the usual dependency on it.
|
|
11906
|
+
*/
|
|
11907
|
+
#onSourceWritten(path, changedPath) {
|
|
11908
|
+
if (!changedPath || !changedPath.startsWith(path + '[') || !changedPath.endsWith(']')) {
|
|
11909
|
+
return;
|
|
11910
|
+
}
|
|
11911
|
+
const property = changedPath.substring(path.length + 1, changedPath.length - 1);
|
|
11912
|
+
if (property.includes(']')) {
|
|
11913
|
+
return;
|
|
11914
|
+
}
|
|
11915
|
+
if (/^\d+$/.test(property)) {
|
|
11916
|
+
this.#writtenIndexes.add(Number(property));
|
|
11917
|
+
}
|
|
11918
|
+
else {
|
|
11919
|
+
// e.g. `items.length = 0`
|
|
11920
|
+
this.#writtenWhole = true;
|
|
11921
|
+
}
|
|
11922
|
+
// Writes made together are refreshed together, after the application's update
|
|
11923
|
+
if (!this.#refreshScheduled) {
|
|
11924
|
+
this.#refreshScheduled = true;
|
|
11925
|
+
queueMicrotask(() => {
|
|
11926
|
+
this.#refreshScheduled = false;
|
|
11927
|
+
this.#refreshWritten();
|
|
11928
|
+
});
|
|
11929
|
+
}
|
|
11930
|
+
}
|
|
11931
|
+
/**
|
|
11932
|
+
* Shows the elements written since the last refresh. A row whose position or
|
|
11933
|
+
* key no longer holds is not patched; the whole list is rendered again.
|
|
11934
|
+
*/
|
|
11935
|
+
#refreshWritten() {
|
|
11936
|
+
if (this.#destroyed || (!this.#writtenWhole && this.#writtenIndexes.size === 0)) {
|
|
11937
|
+
return;
|
|
11938
|
+
}
|
|
11939
|
+
const indexes = [...this.#writtenIndexes];
|
|
11940
|
+
const whole = this.#writtenWhole;
|
|
11941
|
+
this.#writtenIndexes.clear();
|
|
11942
|
+
this.#writtenWhole = false;
|
|
11943
|
+
const source = this.#sourceEvaluator?.evaluate();
|
|
11944
|
+
if (whole || source !== this.#watchedSource || !Array.isArray(source) || source.length !== this.#renderedItems.length) {
|
|
11945
|
+
this.#render();
|
|
11946
|
+
return;
|
|
11947
|
+
}
|
|
11948
|
+
for (const index of indexes) {
|
|
11949
|
+
const rendered = this.#renderedItems[index];
|
|
11950
|
+
let context = { key: index, item: source[index], index };
|
|
11951
|
+
if (this.#evaluateKey && (this.#itemName || this.#itemDestructure)) {
|
|
11952
|
+
const itemBindings = new VBindings({
|
|
11953
|
+
parent: this.#vNode.bindings
|
|
11954
|
+
});
|
|
11955
|
+
this.#setItemBindings(itemBindings, context);
|
|
11956
|
+
context = { ...context, key: this.#evaluateKey(itemBindings) };
|
|
11957
|
+
}
|
|
11958
|
+
if (!rendered || context.key !== rendered.key) {
|
|
11959
|
+
this.#render();
|
|
11960
|
+
return;
|
|
11961
|
+
}
|
|
11962
|
+
this.#updateItemBindings(rendered.vNode, context);
|
|
11963
|
+
this.#previousIterations[index] = context;
|
|
11964
|
+
}
|
|
11965
|
+
}
|
|
11844
11966
|
/**
|
|
11845
11967
|
* Get iterations from various data types
|
|
11846
11968
|
* Supports: Arrays, Objects, Sets, Maps, Iterables, Numbers, Strings
|
|
@@ -11850,7 +11972,8 @@ class VForDirective {
|
|
|
11850
11972
|
return [];
|
|
11851
11973
|
// Array
|
|
11852
11974
|
if (Array.isArray(data)) {
|
|
11853
|
-
|
|
11975
|
+
// Array.from rather than map: a hole (e.g. after `items[5] = x` past the end) is a row of undefined
|
|
11976
|
+
return Array.from(data, (item, index) => ({
|
|
11854
11977
|
item,
|
|
11855
11978
|
index,
|
|
11856
11979
|
key: index
|