@mintjamsinc/ichigojs 0.1.40 → 0.1.42
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 +138 -16
- package/dist/ichigo.cjs.map +1 -1
- package/dist/ichigo.esm.js +138 -16
- 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 +138 -16
- package/dist/ichigo.umd.js.map +1 -1
- package/dist/ichigo.umd.min.js +1 -1
- package/dist/types/ichigo/util/ReactiveProxy.d.ts +41 -0
- package/package.json +1 -1
package/dist/ichigo.cjs
CHANGED
|
@@ -7816,6 +7816,13 @@
|
|
|
7816
7816
|
* This allows retrieving the source path of an object for computed property mapping.
|
|
7817
7817
|
*/
|
|
7818
7818
|
static proxyPaths = new WeakMap();
|
|
7819
|
+
/**
|
|
7820
|
+
* A Map to store path aliases.
|
|
7821
|
+
* Key: alias path (e.g., "editingNestedStep.steps")
|
|
7822
|
+
* Value: source path (e.g., "routes[0].steps[0].steps")
|
|
7823
|
+
* This allows mapping variable names to their actual source paths for dependency tracking.
|
|
7824
|
+
*/
|
|
7825
|
+
static pathAliases = new Map();
|
|
7819
7826
|
/**
|
|
7820
7827
|
* Creates a reactive proxy for the given object.
|
|
7821
7828
|
* The proxy will call the onChange callback whenever a property is modified.
|
|
@@ -7982,6 +7989,84 @@
|
|
|
7982
7989
|
}
|
|
7983
7990
|
return this.proxyPaths.get(obj);
|
|
7984
7991
|
}
|
|
7992
|
+
/**
|
|
7993
|
+
* Registers a path alias.
|
|
7994
|
+
* This is used when a variable is assigned to reference an existing reactive object.
|
|
7995
|
+
* For example, when `editingNestedStep = routes[0].steps[0]`, this creates an alias
|
|
7996
|
+
* so that changes to "routes[0].steps[0].steps" also match "editingNestedStep.steps".
|
|
7997
|
+
*
|
|
7998
|
+
* @param aliasPath The alias path (e.g., "editingNestedStep")
|
|
7999
|
+
* @param sourcePath The source path (e.g., "routes[0].steps[0]")
|
|
8000
|
+
*/
|
|
8001
|
+
static registerPathAlias(aliasPath, sourcePath) {
|
|
8002
|
+
if (aliasPath && sourcePath && aliasPath !== sourcePath) {
|
|
8003
|
+
this.pathAliases.set(aliasPath, sourcePath);
|
|
8004
|
+
}
|
|
8005
|
+
}
|
|
8006
|
+
/**
|
|
8007
|
+
* Unregisters a path alias.
|
|
8008
|
+
*
|
|
8009
|
+
* @param aliasPath The alias path to remove
|
|
8010
|
+
*/
|
|
8011
|
+
static unregisterPathAlias(aliasPath) {
|
|
8012
|
+
// Remove all aliases that start with the given path
|
|
8013
|
+
for (const key of this.pathAliases.keys()) {
|
|
8014
|
+
if (key === aliasPath || key.startsWith(aliasPath + '.') || key.startsWith(aliasPath + '[')) {
|
|
8015
|
+
this.pathAliases.delete(key);
|
|
8016
|
+
}
|
|
8017
|
+
}
|
|
8018
|
+
}
|
|
8019
|
+
/**
|
|
8020
|
+
* Resolves an alias path to its source path.
|
|
8021
|
+
* Also handles nested paths (e.g., "editingNestedStep.steps" -> "routes[0].steps[0].steps").
|
|
8022
|
+
*
|
|
8023
|
+
* @param aliasPath The alias path to resolve
|
|
8024
|
+
* @returns The source path, or undefined if no alias exists
|
|
8025
|
+
*/
|
|
8026
|
+
static resolvePathAlias(aliasPath) {
|
|
8027
|
+
// Direct match
|
|
8028
|
+
if (this.pathAliases.has(aliasPath)) {
|
|
8029
|
+
return this.pathAliases.get(aliasPath);
|
|
8030
|
+
}
|
|
8031
|
+
// Check if this is a nested path of an aliased variable
|
|
8032
|
+
// e.g., "editingNestedStep.steps" when "editingNestedStep" is aliased
|
|
8033
|
+
for (const [alias, source] of this.pathAliases.entries()) {
|
|
8034
|
+
if (aliasPath.startsWith(alias + '.') || aliasPath.startsWith(alias + '[')) {
|
|
8035
|
+
const suffix = aliasPath.substring(alias.length);
|
|
8036
|
+
return source + suffix;
|
|
8037
|
+
}
|
|
8038
|
+
}
|
|
8039
|
+
return undefined;
|
|
8040
|
+
}
|
|
8041
|
+
/**
|
|
8042
|
+
* Checks if a change path matches an identifier, considering path aliases.
|
|
8043
|
+
* For example, if "editingNestedStep" is aliased to "routes[0].steps[0]",
|
|
8044
|
+
* then a change to "routes[0].steps[0].steps" should match "editingNestedStep.steps".
|
|
8045
|
+
*
|
|
8046
|
+
* @param changePath The path that was changed (e.g., "routes[0].steps[0].steps")
|
|
8047
|
+
* @param identifier The identifier to check (e.g., "editingNestedStep.steps")
|
|
8048
|
+
* @returns True if the change path matches the identifier
|
|
8049
|
+
*/
|
|
8050
|
+
static doesChangeMatchIdentifier(changePath, identifier) {
|
|
8051
|
+
// Direct match
|
|
8052
|
+
if (changePath === identifier) {
|
|
8053
|
+
return true;
|
|
8054
|
+
}
|
|
8055
|
+
// Check if the identifier has an alias that matches
|
|
8056
|
+
const resolvedIdentifier = this.resolvePathAlias(identifier);
|
|
8057
|
+
if (resolvedIdentifier && changePath === resolvedIdentifier) {
|
|
8058
|
+
return true;
|
|
8059
|
+
}
|
|
8060
|
+
// Check if change path starts with the resolved identifier
|
|
8061
|
+
// (handles cases like array item changes)
|
|
8062
|
+
if (resolvedIdentifier) {
|
|
8063
|
+
if (changePath.startsWith(resolvedIdentifier + '.') ||
|
|
8064
|
+
changePath.startsWith(resolvedIdentifier + '[')) {
|
|
8065
|
+
return true;
|
|
8066
|
+
}
|
|
8067
|
+
}
|
|
8068
|
+
return false;
|
|
8069
|
+
}
|
|
7985
8070
|
}
|
|
7986
8071
|
|
|
7987
8072
|
// Copyright (c) 2025 MintJams Inc. Licensed under MIT License.
|
|
@@ -8049,18 +8134,48 @@
|
|
|
8049
8134
|
}
|
|
8050
8135
|
let newValue = value;
|
|
8051
8136
|
if (typeof value === 'object' && value !== null) {
|
|
8052
|
-
//
|
|
8053
|
-
|
|
8054
|
-
|
|
8055
|
-
|
|
8056
|
-
|
|
8057
|
-
|
|
8058
|
-
|
|
8059
|
-
|
|
8060
|
-
|
|
8061
|
-
|
|
8137
|
+
// Check if the value already has a path (it's an existing reactive proxy reference)
|
|
8138
|
+
const existingPath = ReactiveProxy.getPath(value);
|
|
8139
|
+
if (existingPath) {
|
|
8140
|
+
// Register a path alias so changes to the source path will match this identifier
|
|
8141
|
+
ReactiveProxy.registerPathAlias(key, existingPath);
|
|
8142
|
+
this.#logger?.debug(`Path alias registered: ${key} -> ${existingPath}`);
|
|
8143
|
+
// Keep the existing proxy as-is to preserve reactivity chain
|
|
8144
|
+
newValue = value;
|
|
8145
|
+
}
|
|
8146
|
+
else {
|
|
8147
|
+
// Before wrapping, check if any properties are existing ReactiveProxies
|
|
8148
|
+
// and register path aliases for them
|
|
8149
|
+
if (!Array.isArray(value)) {
|
|
8150
|
+
for (const propKey of Object.keys(value)) {
|
|
8151
|
+
const propValue = value[propKey];
|
|
8152
|
+
if (typeof propValue === 'object' && propValue !== null) {
|
|
8153
|
+
const propPath = ReactiveProxy.getPath(propValue);
|
|
8154
|
+
if (propPath) {
|
|
8155
|
+
// Register alias: key.propKey -> propPath
|
|
8156
|
+
ReactiveProxy.registerPathAlias(`${key}.${propKey}`, propPath);
|
|
8157
|
+
this.#logger?.debug(`Property path alias registered: ${key}.${propKey} -> ${propPath}`);
|
|
8158
|
+
}
|
|
8159
|
+
}
|
|
8160
|
+
}
|
|
8062
8161
|
}
|
|
8063
|
-
|
|
8162
|
+
// Wrap objects/arrays with reactive proxy, tracking the root key
|
|
8163
|
+
newValue = ReactiveProxy.create(value, (changedPath) => {
|
|
8164
|
+
let path = '';
|
|
8165
|
+
for (const part of changedPath?.split('.') || []) {
|
|
8166
|
+
path = path ? `${path}.${part}` : part;
|
|
8167
|
+
this.#logger?.debug(`Binding changed: ${path}`);
|
|
8168
|
+
this.#changes.add(path);
|
|
8169
|
+
}
|
|
8170
|
+
if (!this.#suppressOnChange) {
|
|
8171
|
+
this.#onChange?.(changedPath);
|
|
8172
|
+
}
|
|
8173
|
+
}, key);
|
|
8174
|
+
}
|
|
8175
|
+
}
|
|
8176
|
+
else if (value === null || value === undefined) {
|
|
8177
|
+
// When setting to null/undefined, unregister any path alias
|
|
8178
|
+
ReactiveProxy.unregisterPathAlias(key);
|
|
8064
8179
|
}
|
|
8065
8180
|
const oldValue = Reflect.get(target, key);
|
|
8066
8181
|
const result = Reflect.set(target, key, newValue);
|
|
@@ -8910,8 +9025,8 @@
|
|
|
8910
9025
|
const changes = this.bindings?.changes || [];
|
|
8911
9026
|
if (this.#nodeType === Node.TEXT_NODE && this.#textEvaluator) {
|
|
8912
9027
|
// If this is a text node with a text evaluator, update its content if needed
|
|
8913
|
-
// Check if any of the identifiers are in the changed identifiers
|
|
8914
|
-
const changed = this.#textEvaluator.identifiers.some(id => changes.
|
|
9028
|
+
// Check if any of the identifiers are in the changed identifiers (considering path aliases)
|
|
9029
|
+
const changed = this.#textEvaluator.identifiers.some(id => changes.some(change => ReactiveProxy.doesChangeMatchIdentifier(change, id)));
|
|
8915
9030
|
// If the text node has changed, update its content
|
|
8916
9031
|
if (changed) {
|
|
8917
9032
|
const text = this.#node;
|
|
@@ -8934,7 +9049,7 @@
|
|
|
8934
9049
|
}
|
|
8935
9050
|
// Prepare bindings for each preparer if relevant identifiers have changed
|
|
8936
9051
|
for (const preparer of this.#directiveManager.bindingsPreparers) {
|
|
8937
|
-
const changed = preparer.dependentIdentifiers.some(id => changes.
|
|
9052
|
+
const changed = preparer.dependentIdentifiers.some(id => changes.some(change => ReactiveProxy.doesChangeMatchIdentifier(change, id)));
|
|
8938
9053
|
if (changed) {
|
|
8939
9054
|
preparer.prepareBindings();
|
|
8940
9055
|
}
|
|
@@ -8943,7 +9058,7 @@
|
|
|
8943
9058
|
// Apply DOM updaters from directives, if any
|
|
8944
9059
|
if (this.#directiveManager?.domUpdaters) {
|
|
8945
9060
|
for (const updater of this.#directiveManager.domUpdaters) {
|
|
8946
|
-
const changed = updater.dependentIdentifiers.some(id => changes.
|
|
9061
|
+
const changed = updater.dependentIdentifiers.some(id => changes.some(change => ReactiveProxy.doesChangeMatchIdentifier(change, id)));
|
|
8947
9062
|
if (changed) {
|
|
8948
9063
|
updater.applyToDOM();
|
|
8949
9064
|
}
|
|
@@ -8951,7 +9066,7 @@
|
|
|
8951
9066
|
}
|
|
8952
9067
|
// Recursively update dependent virtual nodes
|
|
8953
9068
|
this.#dependents?.forEach(dependentNode => {
|
|
8954
|
-
const changed = dependentNode.dependentIdentifiers.some(id => changes.
|
|
9069
|
+
const changed = dependentNode.dependentIdentifiers.some(id => changes.some(change => ReactiveProxy.doesChangeMatchIdentifier(change, id)));
|
|
8955
9070
|
if (changed) {
|
|
8956
9071
|
dependentNode.update();
|
|
8957
9072
|
}
|
|
@@ -12210,6 +12325,13 @@
|
|
|
12210
12325
|
});
|
|
12211
12326
|
// Initial rendering
|
|
12212
12327
|
this.#vNode.update();
|
|
12328
|
+
// Remove v-cloak attributes after mounting
|
|
12329
|
+
// v-cloak is used to hide un-compiled template until the app is ready
|
|
12330
|
+
// Usage: Add CSS rule "[v-cloak] { display: none; }" to hide elements with v-cloak
|
|
12331
|
+
element.querySelectorAll('[v-cloak]').forEach(el => {
|
|
12332
|
+
el.removeAttribute('v-cloak');
|
|
12333
|
+
});
|
|
12334
|
+
element.removeAttribute('v-cloak');
|
|
12213
12335
|
this.#logger.info('Application mounted.');
|
|
12214
12336
|
}
|
|
12215
12337
|
/**
|