@mintjamsinc/ichigojs 0.1.60 → 0.1.61

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 CHANGED
@@ -8243,6 +8243,13 @@
8243
8243
  * their own alias (e.g. "file" -> "files[0]") without overwriting each other.
8244
8244
  */
8245
8245
  #localAliases = new Map();
8246
+ /**
8247
+ * Setters for writable computed properties. When a key registered here is assigned
8248
+ * through the bindings proxy (e.g. via v-model or `bindings.set`), the setter is invoked
8249
+ * instead of writing directly to the local store. The cached value of the computed property
8250
+ * is updated by the recompute cycle through `setSilent`, which bypasses this routing.
8251
+ */
8252
+ #writableComputeds = new Map();
8246
8253
  /**
8247
8254
  * Creates a new instance of VBindings.
8248
8255
  * @param parent The parent bindings, if any.
@@ -8262,6 +8269,14 @@
8262
8269
  return this.#parent?.raw[key];
8263
8270
  },
8264
8271
  set: (obj, key, value) => {
8272
+ // If this key is a writable computed, route the assignment through its setter.
8273
+ // `setSilent` (used to update the cached value during recompute) sets `suppressOnChange`,
8274
+ // which bypasses this routing so the cached value can be written directly.
8275
+ if (!this.#suppressOnChange && this.#writableComputeds.has(key)) {
8276
+ const setter = this.#writableComputeds.get(key);
8277
+ setter(value);
8278
+ return true;
8279
+ }
8265
8280
  let target = obj;
8266
8281
  if (!Reflect.has(target, key)) {
8267
8282
  for (let parent = this.#parent; parent; parent = parent.#parent) {
@@ -8448,6 +8463,16 @@
8448
8463
  this.#suppressOnChange = false;
8449
8464
  }
8450
8465
  }
8466
+ /**
8467
+ * Registers a setter for a writable computed property. When the given key is assigned
8468
+ * through the bindings proxy, the setter will be invoked instead of writing directly to
8469
+ * the local store.
8470
+ * @param key The computed property name.
8471
+ * @param setter The setter function to invoke on assignment.
8472
+ */
8473
+ registerWritableComputed(key, setter) {
8474
+ this.#writableComputeds.set(key, setter);
8475
+ }
8451
8476
  /**
8452
8477
  * Manually adds an identifier to the set of changed identifiers.
8453
8478
  * This is useful for computed properties that need to mark themselves as changed
@@ -13124,8 +13149,15 @@
13124
13149
  this.#logger = this.#logManager.getLogger('VApplication');
13125
13150
  // Analyze function dependencies
13126
13151
  this.#functionDependencies = ExpressionUtils.analyzeFunctionDependencies(options.methods || {});
13127
- // Analyze computed dependencies
13128
- this.#computedDependencies = ExpressionUtils.analyzeFunctionDependencies(options.computed || {});
13152
+ // Analyze computed dependencies based on getter functions only.
13153
+ // Writable computeds (defined as { get, set }) contribute their getter for dependency analysis.
13154
+ const computedGetters = {};
13155
+ if (options.computed) {
13156
+ for (const [key, def] of Object.entries(options.computed)) {
13157
+ computedGetters[key] = VApplication.#getComputedGetter(def);
13158
+ }
13159
+ }
13160
+ this.#computedDependencies = ExpressionUtils.analyzeFunctionDependencies(computedGetters);
13129
13161
  // Initialize watcher manager
13130
13162
  this.#watcher = new VWatcher(this.#logger);
13131
13163
  // Initialize bindings from data, computed, and methods
@@ -13268,6 +13300,26 @@
13268
13300
  }
13269
13301
  }
13270
13302
  }
13303
+ /**
13304
+ * Extracts the getter function from a computed property definition.
13305
+ * Supports both bare function form and { get, set } object form.
13306
+ */
13307
+ static #getComputedGetter(def) {
13308
+ if (typeof def === 'function') {
13309
+ return def;
13310
+ }
13311
+ return def.get;
13312
+ }
13313
+ /**
13314
+ * Extracts the setter function from a computed property definition, if any.
13315
+ * Returns undefined for read-only (function-form) computed properties.
13316
+ */
13317
+ static #getComputedSetter(def) {
13318
+ if (typeof def === 'function') {
13319
+ return undefined;
13320
+ }
13321
+ return def.set;
13322
+ }
13271
13323
  /**
13272
13324
  * Computes dependent identifiers for a given computed property and value.
13273
13325
  * This is used to track dependencies in directives like v-for.
@@ -13330,6 +13382,20 @@
13330
13382
  }
13331
13383
  }
13332
13384
  }
13385
+ // Register setters for writable computed properties so that assignments to them
13386
+ // (e.g. via v-model or direct mutation through bindings.raw) route through the user-provided
13387
+ // setter, which typically writes back to underlying reactive properties.
13388
+ if (this.#options.computed) {
13389
+ for (const [key, def] of Object.entries(this.#options.computed)) {
13390
+ const setter = VApplication.#getComputedSetter(def);
13391
+ if (setter) {
13392
+ const bindings = this.#bindings;
13393
+ this.#bindings.registerWritableComputed(key, (value) => {
13394
+ setter.call(bindings.raw, value);
13395
+ });
13396
+ }
13397
+ }
13398
+ }
13333
13399
  // Add computed properties (initialization mode)
13334
13400
  this.#recomputeProperties(true);
13335
13401
  }
@@ -13488,7 +13554,7 @@
13488
13554
  return;
13489
13555
  }
13490
13556
  // Now compute this property
13491
- const computedFn = this.#options.computed[key];
13557
+ const computedFn = VApplication.#getComputedGetter(this.#options.computed[key]);
13492
13558
  try {
13493
13559
  const oldValue = this.#bindings?.get(key);
13494
13560
  const newValue = computedFn.call(this.#bindings?.raw);