@mintjamsinc/ichigojs 0.1.32 → 0.1.34
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 +247 -36
- package/dist/ichigo.cjs.map +1 -1
- package/dist/ichigo.esm.js +247 -37
- 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 +247 -36
- package/dist/ichigo.umd.js.map +1 -1
- package/dist/ichigo.umd.min.js +1 -1
- package/dist/types/ichigo/VBindings.d.ts +7 -0
- package/dist/types/ichigo/util/ExpressionEvaluator.d.ts +100 -0
- package/dist/types/ichigo/util/ExpressionEvaluatorOptions.d.ts +20 -0
- package/dist/types/ichigo/util/ReactiveProxy.d.ts +15 -0
- package/dist/types/index.d.ts +1 -0
- package/package.json +1 -1
package/dist/ichigo.cjs
CHANGED
|
@@ -6734,6 +6734,70 @@
|
|
|
6734
6734
|
}
|
|
6735
6735
|
}
|
|
6736
6736
|
}
|
|
6737
|
+
else if (node.type === 'MemberExpression') {
|
|
6738
|
+
// Reconstruct chain parts from a MemberExpression (e.g. a.b.c)
|
|
6739
|
+
const parts = [];
|
|
6740
|
+
let cur = node;
|
|
6741
|
+
let stop = false;
|
|
6742
|
+
while (cur && !stop) {
|
|
6743
|
+
// property part (right side)
|
|
6744
|
+
if (cur.property) {
|
|
6745
|
+
if (!cur.computed && cur.property.type === 'Identifier') {
|
|
6746
|
+
parts.unshift(cur.property.name);
|
|
6747
|
+
}
|
|
6748
|
+
else if (cur.computed && cur.property.type === 'Literal') {
|
|
6749
|
+
parts.unshift(String(cur.property.value));
|
|
6750
|
+
}
|
|
6751
|
+
else if (cur.computed && cur.property.type === 'Identifier') {
|
|
6752
|
+
// e.g. obj[prop] -> include the prop identifier (it will also be added separately)
|
|
6753
|
+
parts.unshift(cur.property.name);
|
|
6754
|
+
}
|
|
6755
|
+
else {
|
|
6756
|
+
// unknown property shape (e.g. expression) — stop adding chain here
|
|
6757
|
+
// inner expressions will be visited separately by walk.full
|
|
6758
|
+
stop = true;
|
|
6759
|
+
break;
|
|
6760
|
+
}
|
|
6761
|
+
}
|
|
6762
|
+
// object part (left side)
|
|
6763
|
+
if (cur.object) {
|
|
6764
|
+
if (cur.object.type === 'Identifier') {
|
|
6765
|
+
parts.unshift(cur.object.name);
|
|
6766
|
+
break;
|
|
6767
|
+
}
|
|
6768
|
+
else if (cur.object.type === 'ThisExpression') {
|
|
6769
|
+
// For `this.x` or `this.a.b` we don't want to include 'this' itself.
|
|
6770
|
+
// Stop unwrapping here; we'll drop a leading 'this' later.
|
|
6771
|
+
break;
|
|
6772
|
+
}
|
|
6773
|
+
else if (cur.object.type === 'MemberExpression') {
|
|
6774
|
+
// continue unwrapping
|
|
6775
|
+
cur = cur.object;
|
|
6776
|
+
}
|
|
6777
|
+
else {
|
|
6778
|
+
// other object types (CallExpression, etc.) — stop here
|
|
6779
|
+
stop = true;
|
|
6780
|
+
break;
|
|
6781
|
+
}
|
|
6782
|
+
}
|
|
6783
|
+
else {
|
|
6784
|
+
break;
|
|
6785
|
+
}
|
|
6786
|
+
}
|
|
6787
|
+
if (parts.length > 0) {
|
|
6788
|
+
// Add progressive chains: 'a', 'a.b', 'a.b.c'
|
|
6789
|
+
for (let i = 0; i < parts.length; i++) {
|
|
6790
|
+
const chain = parts.slice(0, i + 1).join('.');
|
|
6791
|
+
identifiers.add(chain);
|
|
6792
|
+
// Also apply functionDependencies lookup for the chain key
|
|
6793
|
+
if (functionDependencies[chain]) {
|
|
6794
|
+
for (const dependency of functionDependencies[chain]) {
|
|
6795
|
+
identifiers.add(dependency);
|
|
6796
|
+
}
|
|
6797
|
+
}
|
|
6798
|
+
}
|
|
6799
|
+
}
|
|
6800
|
+
}
|
|
6737
6801
|
});
|
|
6738
6802
|
return Array.from(identifiers);
|
|
6739
6803
|
}
|
|
@@ -6939,6 +7003,8 @@
|
|
|
6939
7003
|
* The identifiers extracted from the expression.
|
|
6940
7004
|
*/
|
|
6941
7005
|
identifiers;
|
|
7006
|
+
// The original extracted identifiers (may include member chains like 'a.b')
|
|
7007
|
+
originalIdentifiers;
|
|
6942
7008
|
/**
|
|
6943
7009
|
* The bindings to use for evaluating the expression.
|
|
6944
7010
|
*/
|
|
@@ -6954,10 +7020,11 @@
|
|
|
6954
7020
|
/**
|
|
6955
7021
|
* Private constructor. Use ExpressionEvaluator.create() to create instances.
|
|
6956
7022
|
*/
|
|
6957
|
-
constructor(expression, bindings, identifiers, evaluatorFunc, additionalContext) {
|
|
7023
|
+
constructor(expression, bindings, identifiers, originalIdentifiers, evaluatorFunc, additionalContext) {
|
|
6958
7024
|
this.expression = expression;
|
|
6959
7025
|
this.bindings = bindings;
|
|
6960
7026
|
this.identifiers = identifiers;
|
|
7027
|
+
this.originalIdentifiers = originalIdentifiers;
|
|
6961
7028
|
this.evaluatorFunc = evaluatorFunc;
|
|
6962
7029
|
this.additionalContext = additionalContext;
|
|
6963
7030
|
}
|
|
@@ -6971,12 +7038,22 @@
|
|
|
6971
7038
|
* @returns An ExpressionEvaluator instance.
|
|
6972
7039
|
*/
|
|
6973
7040
|
static create(expression, bindings, functionDependencies, options) {
|
|
6974
|
-
// Extract identifiers from the expression
|
|
6975
|
-
const
|
|
7041
|
+
// Extract identifiers from the expression (may include member chains like 'a.b')
|
|
7042
|
+
const extractedIdentifiers = ExpressionUtils.extractIdentifiers(expression, functionDependencies);
|
|
7043
|
+
// For compilation we must only pass simple identifier names (no dots).
|
|
7044
|
+
// Use the base (left-most) segment of member chains and preserve order.
|
|
7045
|
+
const baseIdentifiers = [];
|
|
7046
|
+
for (const id of extractedIdentifiers) {
|
|
7047
|
+
const base = id.split('.')[0];
|
|
7048
|
+
if (!baseIdentifiers.includes(base)) {
|
|
7049
|
+
baseIdentifiers.push(base);
|
|
7050
|
+
}
|
|
7051
|
+
}
|
|
6976
7052
|
// Apply custom rewrite if provided (used by VOnDirective)
|
|
6977
7053
|
let processedExpression = expression;
|
|
6978
7054
|
if (options?.rewriteExpression) {
|
|
6979
|
-
|
|
7055
|
+
// Pass the original extracted identifiers (may include member chains)
|
|
7056
|
+
processedExpression = options.rewriteExpression(expression, extractedIdentifiers);
|
|
6980
7057
|
}
|
|
6981
7058
|
// Build cache key including options that affect compilation
|
|
6982
7059
|
const cacheKey = JSON.stringify({
|
|
@@ -6986,12 +7063,12 @@
|
|
|
6986
7063
|
// Check cache
|
|
6987
7064
|
let evaluatorFunc = this.cache.get(cacheKey);
|
|
6988
7065
|
if (!evaluatorFunc) {
|
|
6989
|
-
// Compile the expression
|
|
6990
|
-
evaluatorFunc = this.compileExpression(processedExpression,
|
|
7066
|
+
// Compile the expression using base identifiers (no dots)
|
|
7067
|
+
evaluatorFunc = this.compileExpression(processedExpression, baseIdentifiers, options);
|
|
6991
7068
|
// Cache the compiled function
|
|
6992
7069
|
this.cache.set(cacheKey, evaluatorFunc);
|
|
6993
7070
|
}
|
|
6994
|
-
return new ExpressionEvaluator(expression, bindings,
|
|
7071
|
+
return new ExpressionEvaluator(expression, bindings, baseIdentifiers, extractedIdentifiers, evaluatorFunc, options?.additionalContext);
|
|
6995
7072
|
}
|
|
6996
7073
|
/**
|
|
6997
7074
|
* Compiles an expression into a function.
|
|
@@ -7002,7 +7079,7 @@
|
|
|
7002
7079
|
* @returns A compiled function.
|
|
7003
7080
|
*/
|
|
7004
7081
|
static compileExpression(expression, identifiers, options) {
|
|
7005
|
-
// Build parameter list: globals first, then identifiers, then additional context
|
|
7082
|
+
// Build parameter list: globals first, then identifiers (base names), then additional context
|
|
7006
7083
|
const params = [
|
|
7007
7084
|
...Object.keys(ExpressionEvaluator.GLOBAL_WHITELIST),
|
|
7008
7085
|
...identifiers
|
|
@@ -7059,7 +7136,8 @@
|
|
|
7059
7136
|
* Gets the list of identifiers extracted from the expression.
|
|
7060
7137
|
*/
|
|
7061
7138
|
get dependentIdentifiers() {
|
|
7062
|
-
|
|
7139
|
+
// Return the original extracted identifiers (may include member chains like 'a.b')
|
|
7140
|
+
return this.originalIdentifiers;
|
|
7063
7141
|
}
|
|
7064
7142
|
/**
|
|
7065
7143
|
* Clears the expression cache.
|
|
@@ -7624,6 +7702,11 @@
|
|
|
7624
7702
|
* These objects will not be wrapped with Proxy.
|
|
7625
7703
|
*/
|
|
7626
7704
|
static rawObjects = new WeakSet();
|
|
7705
|
+
/**
|
|
7706
|
+
* A WeakMap to store the path for each proxy object.
|
|
7707
|
+
* This allows retrieving the source path of an object for computed property mapping.
|
|
7708
|
+
*/
|
|
7709
|
+
static proxyPaths = new WeakMap();
|
|
7627
7710
|
/**
|
|
7628
7711
|
* Creates a reactive proxy for the given object.
|
|
7629
7712
|
* The proxy will call the onChange callback whenever a property is modified.
|
|
@@ -7722,6 +7805,10 @@
|
|
|
7722
7805
|
pathMap.set(path, proxy);
|
|
7723
7806
|
// Track that this proxy wraps the target to prevent double-wrapping
|
|
7724
7807
|
this.proxyToTarget.set(proxy, target);
|
|
7808
|
+
// Store the path for this proxy (for computed property mapping)
|
|
7809
|
+
if (path) {
|
|
7810
|
+
this.proxyPaths.set(proxy, path);
|
|
7811
|
+
}
|
|
7725
7812
|
return proxy;
|
|
7726
7813
|
}
|
|
7727
7814
|
/**
|
|
@@ -7771,6 +7858,21 @@
|
|
|
7771
7858
|
static isRaw(obj) {
|
|
7772
7859
|
return typeof obj === 'object' && obj !== null && this.rawObjects.has(obj);
|
|
7773
7860
|
}
|
|
7861
|
+
/**
|
|
7862
|
+
* Gets the source path for a proxy object.
|
|
7863
|
+
* This is used to map computed property values back to their source paths.
|
|
7864
|
+
* For example, if a computed property returns `model.elements[0]`,
|
|
7865
|
+
* this method returns "model.elements[0]" for that object.
|
|
7866
|
+
*
|
|
7867
|
+
* @param obj The proxy object to get the path for.
|
|
7868
|
+
* @returns The source path, or undefined if not found.
|
|
7869
|
+
*/
|
|
7870
|
+
static getPath(obj) {
|
|
7871
|
+
if (typeof obj !== 'object' || obj === null) {
|
|
7872
|
+
return undefined;
|
|
7873
|
+
}
|
|
7874
|
+
return this.proxyPaths.get(obj);
|
|
7875
|
+
}
|
|
7774
7876
|
}
|
|
7775
7877
|
|
|
7776
7878
|
// Copyright (c) 2025 MintJams Inc. Licensed under MIT License.
|
|
@@ -7977,6 +8079,15 @@
|
|
|
7977
8079
|
this.#suppressOnChange = false;
|
|
7978
8080
|
}
|
|
7979
8081
|
}
|
|
8082
|
+
/**
|
|
8083
|
+
* Manually adds an identifier to the set of changed identifiers.
|
|
8084
|
+
* This is useful for computed properties that need to mark themselves as changed
|
|
8085
|
+
* without triggering a new update cycle.
|
|
8086
|
+
* @param key The identifier to mark as changed.
|
|
8087
|
+
*/
|
|
8088
|
+
markChanged(key) {
|
|
8089
|
+
this.#changes.add(key);
|
|
8090
|
+
}
|
|
7980
8091
|
}
|
|
7981
8092
|
|
|
7982
8093
|
// Copyright (c) 2025 MintJams Inc. Licensed under MIT License.
|
|
@@ -8277,12 +8388,21 @@
|
|
|
8277
8388
|
const evaluators = matches.map(match => {
|
|
8278
8389
|
const expression = match[1].trim();
|
|
8279
8390
|
const ids = ExpressionUtils.extractIdentifiers(expression, functionDependencies);
|
|
8280
|
-
//
|
|
8391
|
+
// Keep chain-style identifiers (a, a.b, a.b.c) for metadata
|
|
8281
8392
|
this.#identifiers.push(...ids.filter(id => !this.#identifiers.includes(id)));
|
|
8282
|
-
|
|
8393
|
+
// Build base parameter names (no dots), preserving order of first appearance
|
|
8394
|
+
const baseArgs = [];
|
|
8395
|
+
for (const id of ids) {
|
|
8396
|
+
const base = id.split('.')[0];
|
|
8397
|
+
if (!baseArgs.includes(base)) {
|
|
8398
|
+
baseArgs.push(base);
|
|
8399
|
+
}
|
|
8400
|
+
}
|
|
8401
|
+
const args = baseArgs.join(", ");
|
|
8283
8402
|
const funcBody = `return (${expression});`;
|
|
8284
8403
|
return {
|
|
8285
8404
|
ids,
|
|
8405
|
+
baseArgs,
|
|
8286
8406
|
func: new Function(args, funcBody)
|
|
8287
8407
|
};
|
|
8288
8408
|
});
|
|
@@ -8290,17 +8410,13 @@
|
|
|
8290
8410
|
this.#evaluate = (bindings) => {
|
|
8291
8411
|
let result = text;
|
|
8292
8412
|
evaluators.forEach((evaluator, i) => {
|
|
8293
|
-
//
|
|
8294
|
-
|
|
8295
|
-
|
|
8296
|
-
|
|
8297
|
-
if (value !== undefined) {
|
|
8413
|
+
// Build values for baseArgs (no dots) in the same order as function parameters
|
|
8414
|
+
const values = evaluator.baseArgs.map((name) => {
|
|
8415
|
+
const value = bindings.get(name);
|
|
8416
|
+
if (value !== undefined)
|
|
8298
8417
|
return value;
|
|
8299
|
-
|
|
8300
|
-
|
|
8301
|
-
if (id in GLOBAL_OBJECTS) {
|
|
8302
|
-
return GLOBAL_OBJECTS[id];
|
|
8303
|
-
}
|
|
8418
|
+
if (name in GLOBAL_OBJECTS)
|
|
8419
|
+
return GLOBAL_OBJECTS[name];
|
|
8304
8420
|
return undefined;
|
|
8305
8421
|
});
|
|
8306
8422
|
// Evaluate the expression and replace {{...}} in the text
|
|
@@ -10104,10 +10220,16 @@
|
|
|
10104
10220
|
// Evaluate the options expression
|
|
10105
10221
|
let options;
|
|
10106
10222
|
if (optionsDirective && optionsDirective.expression) {
|
|
10107
|
-
// Evaluate the options expression
|
|
10223
|
+
// Evaluate the options expression using base identifiers (no dots)
|
|
10108
10224
|
const identifiers = optionsDirective.dependentIdentifiers;
|
|
10109
|
-
const
|
|
10110
|
-
const
|
|
10225
|
+
const baseArgs = [];
|
|
10226
|
+
for (const id of identifiers) {
|
|
10227
|
+
const base = id.split('.')[0];
|
|
10228
|
+
if (!baseArgs.includes(base))
|
|
10229
|
+
baseArgs.push(base);
|
|
10230
|
+
}
|
|
10231
|
+
const values = baseArgs.map(name => this.#vNode.bindings?.get(name));
|
|
10232
|
+
const args = baseArgs.join(", ");
|
|
10111
10233
|
const funcBody = `return (${optionsDirective.expression});`;
|
|
10112
10234
|
const func = new Function(args, funcBody);
|
|
10113
10235
|
options = func(...values);
|
|
@@ -10180,8 +10302,14 @@
|
|
|
10180
10302
|
}
|
|
10181
10303
|
// For inline expressions, evaluate normally
|
|
10182
10304
|
// Note: inline expressions receive entries and $ctx as parameters
|
|
10183
|
-
const
|
|
10184
|
-
const
|
|
10305
|
+
const baseArgs = [];
|
|
10306
|
+
for (const id of identifiers) {
|
|
10307
|
+
const base = id.split('.')[0];
|
|
10308
|
+
if (!baseArgs.includes(base))
|
|
10309
|
+
baseArgs.push(base);
|
|
10310
|
+
}
|
|
10311
|
+
const values = baseArgs.map(name => vNode.bindings?.get(name));
|
|
10312
|
+
const args = [...baseArgs, 'entries', '$ctx'].join(", ");
|
|
10185
10313
|
const funcBody = `return (${expression});`;
|
|
10186
10314
|
const func = new Function(args, funcBody);
|
|
10187
10315
|
return func.call(bindings?.raw, ...values, entries, $ctx);
|
|
@@ -11004,10 +11132,16 @@
|
|
|
11004
11132
|
// Evaluate the options expression
|
|
11005
11133
|
let options;
|
|
11006
11134
|
if (optionsDirective && optionsDirective.expression) {
|
|
11007
|
-
// Evaluate the options expression
|
|
11135
|
+
// Evaluate the options expression using base identifiers (no dots)
|
|
11008
11136
|
const identifiers = optionsDirective.dependentIdentifiers;
|
|
11009
|
-
const
|
|
11010
|
-
const
|
|
11137
|
+
const baseArgs = [];
|
|
11138
|
+
for (const id of identifiers) {
|
|
11139
|
+
const base = id.split('.')[0];
|
|
11140
|
+
if (!baseArgs.includes(base))
|
|
11141
|
+
baseArgs.push(base);
|
|
11142
|
+
}
|
|
11143
|
+
const values = baseArgs.map(name => this.#vNode.bindings?.get(name));
|
|
11144
|
+
const args = baseArgs.join(", ");
|
|
11011
11145
|
const funcBody = `return (${optionsDirective.expression});`;
|
|
11012
11146
|
const func = new Function(args, funcBody);
|
|
11013
11147
|
options = func(...values);
|
|
@@ -11088,8 +11222,14 @@
|
|
|
11088
11222
|
}
|
|
11089
11223
|
// For inline expressions, evaluate normally
|
|
11090
11224
|
// Note: inline expressions receive entries, observer, options, and $ctx as parameters
|
|
11091
|
-
const
|
|
11092
|
-
const
|
|
11225
|
+
const baseArgs = [];
|
|
11226
|
+
for (const id of identifiers) {
|
|
11227
|
+
const base = id.split('.')[0];
|
|
11228
|
+
if (!baseArgs.includes(base))
|
|
11229
|
+
baseArgs.push(base);
|
|
11230
|
+
}
|
|
11231
|
+
const values = baseArgs.map(name => vNode.bindings?.get(name));
|
|
11232
|
+
const args = [...baseArgs, 'entries', 'observer', 'options', '$ctx'].join(", ");
|
|
11093
11233
|
const funcBody = `return (${expression});`;
|
|
11094
11234
|
const func = new Function(args, funcBody);
|
|
11095
11235
|
return func.call(bindings?.raw, ...values, entries, observer, options, $ctx);
|
|
@@ -11213,10 +11353,16 @@
|
|
|
11213
11353
|
// Evaluate the options expression
|
|
11214
11354
|
let options;
|
|
11215
11355
|
if (optionsDirective && optionsDirective.expression) {
|
|
11216
|
-
// Evaluate the options expression
|
|
11356
|
+
// Evaluate the options expression using base identifiers (no dots)
|
|
11217
11357
|
const identifiers = optionsDirective.dependentIdentifiers;
|
|
11218
|
-
const
|
|
11219
|
-
const
|
|
11358
|
+
const baseArgs = [];
|
|
11359
|
+
for (const id of identifiers) {
|
|
11360
|
+
const base = id.split('.')[0];
|
|
11361
|
+
if (!baseArgs.includes(base))
|
|
11362
|
+
baseArgs.push(base);
|
|
11363
|
+
}
|
|
11364
|
+
const values = baseArgs.map(name => this.#vNode.bindings?.get(name));
|
|
11365
|
+
const args = baseArgs.join(", ");
|
|
11220
11366
|
const funcBody = `return (${optionsDirective.expression});`;
|
|
11221
11367
|
const func = new Function(args, funcBody);
|
|
11222
11368
|
options = func(...values);
|
|
@@ -11289,8 +11435,14 @@
|
|
|
11289
11435
|
}
|
|
11290
11436
|
// For inline expressions, evaluate normally
|
|
11291
11437
|
// Note: inline expressions receive entries and $ctx as parameters
|
|
11292
|
-
const
|
|
11293
|
-
const
|
|
11438
|
+
const baseArgs = [];
|
|
11439
|
+
for (const id of identifiers) {
|
|
11440
|
+
const base = id.split('.')[0];
|
|
11441
|
+
if (!baseArgs.includes(base))
|
|
11442
|
+
baseArgs.push(base);
|
|
11443
|
+
}
|
|
11444
|
+
const values = baseArgs.map(name => vNode.bindings?.get(name));
|
|
11445
|
+
const args = [...baseArgs, 'entries', '$ctx'].join(", ");
|
|
11294
11446
|
const funcBody = `return (${expression});`;
|
|
11295
11447
|
const func = new Function(args, funcBody);
|
|
11296
11448
|
return func.call(bindings?.raw, ...values, entries, $ctx);
|
|
@@ -11887,6 +12039,12 @@
|
|
|
11887
12039
|
* A dictionary mapping computed property names to their dependencies.
|
|
11888
12040
|
*/
|
|
11889
12041
|
#computedDependencies;
|
|
12042
|
+
/**
|
|
12043
|
+
* A map tracking source paths for computed property values.
|
|
12044
|
+
* Maps source path (e.g., "model.elements[0]") to computed property name (e.g., "selectedElement").
|
|
12045
|
+
* This allows changes to source paths to be mapped to computed property changes.
|
|
12046
|
+
*/
|
|
12047
|
+
#computedSourcePaths = new Map();
|
|
11890
12048
|
/**
|
|
11891
12049
|
* Flag to indicate if an update is already scheduled.
|
|
11892
12050
|
*/
|
|
@@ -12124,11 +12282,45 @@
|
|
|
12124
12282
|
#update() {
|
|
12125
12283
|
// Re-evaluate computed properties that depend on changed values
|
|
12126
12284
|
this.#recomputeProperties();
|
|
12285
|
+
// Apply computed source path mappings to changes
|
|
12286
|
+
// This converts paths like "model.elements[0].executionListeners"
|
|
12287
|
+
// to "selectedElement.executionListeners" when selectedElement points to model.elements[0]
|
|
12288
|
+
this.#applyComputedPathMappings();
|
|
12127
12289
|
// Update the DOM
|
|
12128
12290
|
this.#vNode?.update();
|
|
12129
12291
|
// Clear the set of changed identifiers after the update
|
|
12130
12292
|
this.#bindings?.clearChanges();
|
|
12131
12293
|
}
|
|
12294
|
+
/**
|
|
12295
|
+
* Applies computed source path mappings to the current changes.
|
|
12296
|
+
* For each changed path, if it starts with a source path that maps to a computed property,
|
|
12297
|
+
* adds the corresponding computed property path to the changes.
|
|
12298
|
+
*/
|
|
12299
|
+
#applyComputedPathMappings() {
|
|
12300
|
+
if (this.#computedSourcePaths.size === 0 || !this.#bindings) {
|
|
12301
|
+
return;
|
|
12302
|
+
}
|
|
12303
|
+
const changes = this.#bindings.changes;
|
|
12304
|
+
const mappedPaths = [];
|
|
12305
|
+
for (const changedPath of changes) {
|
|
12306
|
+
for (const [sourcePath, computedName] of this.#computedSourcePaths) {
|
|
12307
|
+
// Check if the changed path starts with or equals the source path
|
|
12308
|
+
if (changedPath === sourcePath) {
|
|
12309
|
+
// Exact match: mark the computed property itself as changed
|
|
12310
|
+
mappedPaths.push(computedName);
|
|
12311
|
+
}
|
|
12312
|
+
else if (changedPath.startsWith(sourcePath + '.') || changedPath.startsWith(sourcePath + '[')) {
|
|
12313
|
+
// Subpath match: convert "model.elements[0].x" to "selectedElement.x"
|
|
12314
|
+
const suffix = changedPath.slice(sourcePath.length);
|
|
12315
|
+
mappedPaths.push(computedName + suffix);
|
|
12316
|
+
}
|
|
12317
|
+
}
|
|
12318
|
+
}
|
|
12319
|
+
// Add all mapped paths to the changes
|
|
12320
|
+
for (const path of mappedPaths) {
|
|
12321
|
+
this.#bindings.markChanged(path);
|
|
12322
|
+
}
|
|
12323
|
+
}
|
|
12132
12324
|
/**
|
|
12133
12325
|
* Recursively recomputes computed properties based on changed identifiers.
|
|
12134
12326
|
* @param isInitialization - If true, computes all computed properties regardless of dependencies
|
|
@@ -12186,8 +12378,26 @@
|
|
|
12186
12378
|
}
|
|
12187
12379
|
if (hasChanged) {
|
|
12188
12380
|
// Use setSilent to avoid triggering onChange during computed property updates
|
|
12381
|
+
// Then mark the computed property as changed so UI depending on it will update
|
|
12189
12382
|
this.#bindings?.setSilent(key, newValue);
|
|
12383
|
+
this.#bindings?.markChanged(key);
|
|
12190
12384
|
allChanges.add(key);
|
|
12385
|
+
// Track source path mapping for computed property values
|
|
12386
|
+
// This allows changes like "model.elements[0].x" to be mapped to "selectedElement.x"
|
|
12387
|
+
if (typeof newValue === 'object' && newValue !== null) {
|
|
12388
|
+
const sourcePath = ReactiveProxy.getPath(newValue);
|
|
12389
|
+
if (sourcePath) {
|
|
12390
|
+
// Remove old mapping for this computed property
|
|
12391
|
+
for (const [path, name] of this.#computedSourcePaths) {
|
|
12392
|
+
if (name === key) {
|
|
12393
|
+
this.#computedSourcePaths.delete(path);
|
|
12394
|
+
break;
|
|
12395
|
+
}
|
|
12396
|
+
}
|
|
12397
|
+
// Add new mapping
|
|
12398
|
+
this.#computedSourcePaths.set(sourcePath, key);
|
|
12399
|
+
}
|
|
12400
|
+
}
|
|
12191
12401
|
}
|
|
12192
12402
|
}
|
|
12193
12403
|
catch (error) {
|
|
@@ -12284,6 +12494,7 @@
|
|
|
12284
12494
|
}
|
|
12285
12495
|
}
|
|
12286
12496
|
|
|
12497
|
+
exports.ExpressionUtils = ExpressionUtils;
|
|
12287
12498
|
exports.ReactiveProxy = ReactiveProxy;
|
|
12288
12499
|
exports.VComponent = VComponent;
|
|
12289
12500
|
exports.VComponentRegistry = VComponentRegistry;
|