@mintjamsinc/ichigojs 0.1.3 → 0.1.4

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.
@@ -6879,6 +6879,42 @@
6879
6879
  get expression() {
6880
6880
  return this.#expression;
6881
6881
  }
6882
+ /**
6883
+ * @inheritdoc
6884
+ */
6885
+ get onMount() {
6886
+ return undefined;
6887
+ }
6888
+ /**
6889
+ * @inheritdoc
6890
+ */
6891
+ get onMounted() {
6892
+ return undefined;
6893
+ }
6894
+ /**
6895
+ * @inheritdoc
6896
+ */
6897
+ get onUpdate() {
6898
+ return undefined;
6899
+ }
6900
+ /**
6901
+ * @inheritdoc
6902
+ */
6903
+ get onUpdated() {
6904
+ return undefined;
6905
+ }
6906
+ /**
6907
+ * @inheritdoc
6908
+ */
6909
+ get onUnmount() {
6910
+ return undefined;
6911
+ }
6912
+ /**
6913
+ * @inheritdoc
6914
+ */
6915
+ get onUnmounted() {
6916
+ return undefined;
6917
+ }
6882
6918
  /**
6883
6919
  * @inheritdoc
6884
6920
  */
@@ -7637,6 +7673,11 @@
7637
7673
  * This is optional and may be undefined if there are no dependencies.
7638
7674
  */
7639
7675
  #closers;
7676
+ /**
7677
+ * Indicates whether this node has been templatized by a directive.
7678
+ * This is optional and may be undefined if the node has not been templatized.
7679
+ */
7680
+ #templatized;
7640
7681
  /**
7641
7682
  * Creates an instance of the virtual node.
7642
7683
  * @param args The initialization arguments for the virtual node.
@@ -7650,23 +7691,31 @@
7650
7691
  this.#bindings = args.bindings;
7651
7692
  this.#initDependentIdentifiers = args.dependentIdentifiers;
7652
7693
  this.#parentVNode?.addChild(this);
7653
- // If the node is a text node, check for expressions and create a text evaluator
7654
7694
  if (this.#nodeType === Node.TEXT_NODE) {
7695
+ // If the node is a text node, check for expressions and create a text evaluator
7655
7696
  const text = this.#node;
7656
7697
  // Create a text evaluator if the text contains expressions
7657
7698
  if (VTextEvaluator.containsExpression(text.data)) {
7658
7699
  this.#textEvaluator = new VTextEvaluator(text.data, this.#vApplication.functionDependencies);
7659
7700
  }
7660
7701
  }
7661
- // If the node is an element, initialize directives and child nodes
7662
- if (this.#nodeType === Node.ELEMENT_NODE && this.#node.nodeType !== Node.DOCUMENT_FRAGMENT_NODE) {
7702
+ else if (this.#nodeType === Node.ELEMENT_NODE) {
7703
+ // If the node is an element, initialize directives and child nodes
7663
7704
  this.#node;
7664
7705
  // Initialize child virtual nodes
7665
7706
  this.#childVNodes = [];
7666
7707
  // Initialize directive manager
7667
7708
  this.#directiveManager = new VDirectiveManager(this);
7668
- // For non-v-for elements, recursively create VNode instances for child nodes
7669
- if (!this.#directiveManager.directives?.some(d => d.templatize)) {
7709
+ // Determine if any directive requires template preservation
7710
+ this.#templatized = this.#directiveManager.directives?.some(d => d.templatize) ?? false;
7711
+ // If no directive requires template preservation, call onMount for directives that do not templatize
7712
+ if (!this.#templatized) {
7713
+ this.#directiveManager.directives?.forEach(d => {
7714
+ d.onMount?.();
7715
+ });
7716
+ }
7717
+ // Create child virtual nodes if template preservation is not required
7718
+ if (!this.#templatized) {
7670
7719
  for (const childNode of Array.from(this.#node.childNodes)) {
7671
7720
  new VNode({
7672
7721
  node: childNode,
@@ -7675,11 +7724,18 @@
7675
7724
  });
7676
7725
  }
7677
7726
  }
7727
+ // After creating child nodes, call onMounted for directives that do not templatize
7728
+ if (!this.#templatized) {
7729
+ // animation frame to ensure DOM is updated
7730
+ requestAnimationFrame(() => {
7731
+ this.#directiveManager?.directives?.forEach(d => {
7732
+ d.onMounted?.();
7733
+ });
7734
+ });
7735
+ }
7678
7736
  }
7679
- // If there is a parent virtual node, add this node as a dependency
7680
- if (this.#parentVNode) {
7681
- this.#closers = this.#parentVNode.addDependent(this);
7682
- }
7737
+ // Register this node as a dependent of the parent node, if any
7738
+ this.#closers = this.#parentVNode?.addDependent(this);
7683
7739
  }
7684
7740
  /**
7685
7741
  * The application instance associated with this virtual node.
@@ -7865,8 +7921,8 @@
7865
7921
  */
7866
7922
  update() {
7867
7923
  const changes = this.bindings?.changes || [];
7868
- // If this is a text node with a text evaluator, update its content if needed
7869
7924
  if (this.#nodeType === Node.TEXT_NODE && this.#textEvaluator) {
7925
+ // If this is a text node with a text evaluator, update its content if needed
7870
7926
  // Check if any of the identifiers are in the changed identifiers
7871
7927
  const changed = this.#textEvaluator.identifiers.some(id => changes.includes(id));
7872
7928
  // If the text node has changed, update its content
@@ -7874,38 +7930,52 @@
7874
7930
  const text = this.#node;
7875
7931
  text.data = this.#textEvaluator.evaluate(this.bindings);
7876
7932
  }
7877
- return;
7878
7933
  }
7879
- // Prepare new bindings using directive bindings preparers, if any
7880
- if (this.#directiveManager?.bindingsPreparers) {
7881
- // Ensure local bindings are initialized
7882
- if (!this.#bindings) {
7883
- this.#bindings = new VBindings({ parent: this.bindings });
7934
+ else if (this.#nodeType === Node.ELEMENT_NODE) {
7935
+ // If this is an element node, update directives and child nodes
7936
+ // If no directive requires template preservation, call onUpdate for directives that do not templatize
7937
+ if (!this.#templatized) {
7938
+ this.#directiveManager?.directives?.forEach(d => {
7939
+ d.onUpdate?.();
7940
+ });
7884
7941
  }
7885
- // Prepare bindings for each preparer if relevant identifiers have changed
7886
- for (const preparer of this.#directiveManager.bindingsPreparers) {
7887
- const changed = preparer.dependentIdentifiers.some(id => changes.includes(id));
7888
- if (changed) {
7889
- preparer.prepareBindings();
7942
+ // Prepare new bindings using directive bindings preparers, if any
7943
+ if (this.#directiveManager?.bindingsPreparers) {
7944
+ // Ensure local bindings are initialized
7945
+ if (!this.#bindings) {
7946
+ this.#bindings = new VBindings({ parent: this.bindings });
7947
+ }
7948
+ // Prepare bindings for each preparer if relevant identifiers have changed
7949
+ for (const preparer of this.#directiveManager.bindingsPreparers) {
7950
+ const changed = preparer.dependentIdentifiers.some(id => changes.includes(id));
7951
+ if (changed) {
7952
+ preparer.prepareBindings();
7953
+ }
7890
7954
  }
7891
7955
  }
7892
- }
7893
- // Apply DOM updaters from directives, if any
7894
- if (this.#directiveManager?.domUpdaters) {
7895
- for (const updater of this.#directiveManager.domUpdaters) {
7896
- const changed = updater.dependentIdentifiers.some(id => changes.includes(id));
7956
+ // Apply DOM updaters from directives, if any
7957
+ if (this.#directiveManager?.domUpdaters) {
7958
+ for (const updater of this.#directiveManager.domUpdaters) {
7959
+ const changed = updater.dependentIdentifiers.some(id => changes.includes(id));
7960
+ if (changed) {
7961
+ updater.applyToDOM();
7962
+ }
7963
+ }
7964
+ }
7965
+ // Recursively update dependent virtual nodes
7966
+ this.#dependents?.forEach(dependentNode => {
7967
+ const changed = dependentNode.dependentIdentifiers.some(id => changes.includes(id));
7897
7968
  if (changed) {
7898
- updater.applyToDOM();
7969
+ dependentNode.update();
7899
7970
  }
7971
+ });
7972
+ // If no directive requires template preservation, call onUpdated for directives that do not templatize
7973
+ if (!this.#templatized) {
7974
+ this.#directiveManager?.directives?.forEach(d => {
7975
+ d.onUpdated?.();
7976
+ });
7900
7977
  }
7901
7978
  }
7902
- // Recursively update dependent virtual nodes
7903
- this.#dependents?.forEach(dependentNode => {
7904
- const changed = dependentNode.dependentIdentifiers.some(id => changes.includes(id));
7905
- if (changed) {
7906
- dependentNode.update();
7907
- }
7908
- });
7909
7979
  }
7910
7980
  /**
7911
7981
  * Forces an update of the virtual node and its children, regardless of changed identifiers.
@@ -7914,33 +7984,47 @@
7914
7984
  * This is useful when an immediate update is needed, bypassing the usual change detection.
7915
7985
  */
7916
7986
  forceUpdate() {
7917
- // If this is a text node with a text evaluator, update its content if needed
7918
7987
  if (this.#nodeType === Node.TEXT_NODE && this.#textEvaluator) {
7988
+ // If this is a text node with a text evaluator, update its content if needed
7919
7989
  const text = this.#node;
7920
7990
  text.data = this.#textEvaluator.evaluate(this.bindings);
7921
- return;
7922
7991
  }
7923
- // Prepare new bindings using directive bindings preparers, if any
7924
- if (this.#directiveManager?.bindingsPreparers) {
7925
- // Ensure local bindings are initialized
7926
- if (!this.#bindings) {
7927
- this.#bindings = new VBindings({ parent: this.bindings });
7992
+ else if (this.#nodeType === Node.ELEMENT_NODE) {
7993
+ // If this is an element node, update directives and child nodes
7994
+ // If no directive requires template preservation, call onUpdate for directives that do not templatize
7995
+ if (!this.#templatized) {
7996
+ this.#directiveManager?.directives?.forEach(d => {
7997
+ d.onUpdate?.();
7998
+ });
7928
7999
  }
7929
- // Prepare bindings for each preparer if relevant identifiers have changed
7930
- for (const preparer of this.#directiveManager.bindingsPreparers) {
7931
- preparer.prepareBindings();
8000
+ // Prepare new bindings using directive bindings preparers, if any
8001
+ if (this.#directiveManager?.bindingsPreparers) {
8002
+ // Ensure local bindings are initialized
8003
+ if (!this.#bindings) {
8004
+ this.#bindings = new VBindings({ parent: this.bindings });
8005
+ }
8006
+ // Prepare bindings for each preparer if relevant identifiers have changed
8007
+ for (const preparer of this.#directiveManager.bindingsPreparers) {
8008
+ preparer.prepareBindings();
8009
+ }
7932
8010
  }
7933
- }
7934
- // Apply DOM updaters from directives, if any
7935
- if (this.#directiveManager?.domUpdaters) {
7936
- for (const updater of this.#directiveManager.domUpdaters) {
7937
- updater.applyToDOM();
8011
+ // Apply DOM updaters from directives, if any
8012
+ if (this.#directiveManager?.domUpdaters) {
8013
+ for (const updater of this.#directiveManager.domUpdaters) {
8014
+ updater.applyToDOM();
8015
+ }
8016
+ }
8017
+ // Recursively update child virtual nodes
8018
+ this.#childVNodes?.forEach(childVNode => {
8019
+ childVNode.forceUpdate();
8020
+ });
8021
+ // If no directive requires template preservation, call onUpdated for directives that do not templatize
8022
+ if (!this.#templatized) {
8023
+ this.#directiveManager?.directives?.forEach(d => {
8024
+ d.onUpdated?.();
8025
+ });
7938
8026
  }
7939
8027
  }
7940
- // Recursively update child virtual nodes
7941
- this.#childVNodes?.forEach(childVNode => {
7942
- childVNode.forceUpdate();
7943
- });
7944
8028
  }
7945
8029
  /**
7946
8030
  * Adds a child virtual node to this virtual node.
@@ -8013,6 +8097,12 @@
8013
8097
  * This method is called when the virtual node is no longer needed.
8014
8098
  */
8015
8099
  destroy() {
8100
+ // If no directive requires template preservation, call onUnmount for directives that do not templatize
8101
+ if (!this.#templatized) {
8102
+ this.#directiveManager?.directives?.forEach(d => {
8103
+ d.onUnmount?.();
8104
+ });
8105
+ }
8016
8106
  // Recursively destroy child nodes
8017
8107
  if (this.#childVNodes) {
8018
8108
  for (const childVNode of this.#childVNodes) {
@@ -8037,6 +8127,12 @@
8037
8127
  }
8038
8128
  // Clean up directive handler
8039
8129
  this.#directiveManager?.destroy();
8130
+ // If no directive requires template preservation, call onUnmounted for directives that do not templatize
8131
+ if (!this.#templatized) {
8132
+ this.#directiveManager?.directives?.forEach(d => {
8133
+ d.onUnmounted?.();
8134
+ });
8135
+ }
8040
8136
  }
8041
8137
  }
8042
8138
 
@@ -8204,6 +8300,42 @@
8204
8300
  }
8205
8301
  return this.#evaluate();
8206
8302
  }
8303
+ /**
8304
+ * @inheritdoc
8305
+ */
8306
+ get onMount() {
8307
+ return undefined;
8308
+ }
8309
+ /**
8310
+ * @inheritdoc
8311
+ */
8312
+ get onMounted() {
8313
+ return undefined;
8314
+ }
8315
+ /**
8316
+ * @inheritdoc
8317
+ */
8318
+ get onUpdate() {
8319
+ return undefined;
8320
+ }
8321
+ /**
8322
+ * @inheritdoc
8323
+ */
8324
+ get onUpdated() {
8325
+ return undefined;
8326
+ }
8327
+ /**
8328
+ * @inheritdoc
8329
+ */
8330
+ get onUnmount() {
8331
+ return undefined;
8332
+ }
8333
+ /**
8334
+ * @inheritdoc
8335
+ */
8336
+ get onUnmounted() {
8337
+ return undefined;
8338
+ }
8207
8339
  /**
8208
8340
  * @inheritdoc
8209
8341
  */
@@ -8258,8 +8390,10 @@
8258
8390
  // Not rendered, no action needed
8259
8391
  return;
8260
8392
  }
8261
- this.#renderedVNode.node.parentNode?.removeChild(this.#renderedVNode.node);
8393
+ // Destroy VNode first (calls @unmount hooks while DOM is still accessible)
8262
8394
  this.#renderedVNode.destroy();
8395
+ // Then remove from DOM
8396
+ this.#renderedVNode.node.parentNode?.removeChild(this.#renderedVNode.node);
8263
8397
  this.#renderedVNode = undefined;
8264
8398
  }
8265
8399
  /**
@@ -8488,16 +8622,56 @@
8488
8622
  get dependentIdentifiers() {
8489
8623
  return this.#dependentIdentifiers ?? [];
8490
8624
  }
8625
+ /**
8626
+ * @inheritdoc
8627
+ */
8628
+ get onMount() {
8629
+ return undefined;
8630
+ }
8631
+ /**
8632
+ * @inheritdoc
8633
+ */
8634
+ get onMounted() {
8635
+ return undefined;
8636
+ }
8637
+ /**
8638
+ * @inheritdoc
8639
+ */
8640
+ get onUpdate() {
8641
+ return undefined;
8642
+ }
8643
+ /**
8644
+ * @inheritdoc
8645
+ */
8646
+ get onUpdated() {
8647
+ return undefined;
8648
+ }
8649
+ /**
8650
+ * @inheritdoc
8651
+ */
8652
+ get onUnmount() {
8653
+ return undefined;
8654
+ }
8655
+ /**
8656
+ * @inheritdoc
8657
+ */
8658
+ get onUnmounted() {
8659
+ return undefined;
8660
+ }
8491
8661
  /**
8492
8662
  * @inheritdoc
8493
8663
  */
8494
8664
  destroy() {
8495
8665
  // Clean up all rendered items
8666
+ // First destroy all VNodes (calls @unmount hooks), then remove from DOM
8667
+ for (const vNode of this.#renderedItems.values()) {
8668
+ vNode.destroy();
8669
+ }
8670
+ // Then remove DOM nodes
8496
8671
  for (const vNode of this.#renderedItems.values()) {
8497
8672
  if (vNode.node.parentNode) {
8498
8673
  vNode.node.parentNode.removeChild(vNode.node);
8499
8674
  }
8500
- vNode.destroy();
8501
8675
  }
8502
8676
  this.#renderedItems.clear();
8503
8677
  this.#previousIterations = [];
@@ -8554,14 +8728,20 @@
8554
8728
  // Track which keys are still needed
8555
8729
  const neededKeys = new Set(newIterations.map(ctx => ctx.key));
8556
8730
  // Remove items that are no longer needed
8731
+ // First destroy VNodes (calls @unmount hooks while DOM is still accessible)
8732
+ const nodesToRemove = [];
8557
8733
  for (const [key, vNode] of this.#renderedItems) {
8558
8734
  if (!neededKeys.has(key)) {
8559
- if (vNode.node.parentNode) {
8560
- vNode.node.parentNode.removeChild(vNode.node);
8561
- }
8735
+ nodesToRemove.push(vNode);
8562
8736
  vNode.destroy();
8563
8737
  }
8564
8738
  }
8739
+ // Then remove from DOM
8740
+ for (const vNode of nodesToRemove) {
8741
+ if (vNode.node.parentNode) {
8742
+ vNode.node.parentNode.removeChild(vNode.node);
8743
+ }
8744
+ }
8565
8745
  // Add or reorder items
8566
8746
  let prevNode = anchor;
8567
8747
  for (const context of newIterations) {
@@ -8874,6 +9054,42 @@
8874
9054
  get dependentIdentifiers() {
8875
9055
  return this.#dependentIdentifiers ?? [];
8876
9056
  }
9057
+ /**
9058
+ * @inheritdoc
9059
+ */
9060
+ get onMount() {
9061
+ return undefined;
9062
+ }
9063
+ /**
9064
+ * @inheritdoc
9065
+ */
9066
+ get onMounted() {
9067
+ return undefined;
9068
+ }
9069
+ /**
9070
+ * @inheritdoc
9071
+ */
9072
+ get onUpdate() {
9073
+ return undefined;
9074
+ }
9075
+ /**
9076
+ * @inheritdoc
9077
+ */
9078
+ get onUpdated() {
9079
+ return undefined;
9080
+ }
9081
+ /**
9082
+ * @inheritdoc
9083
+ */
9084
+ get onUnmount() {
9085
+ return undefined;
9086
+ }
9087
+ /**
9088
+ * @inheritdoc
9089
+ */
9090
+ get onUnmounted() {
9091
+ return undefined;
9092
+ }
8877
9093
  /**
8878
9094
  * @inheritdoc
8879
9095
  */
@@ -9033,7 +9249,7 @@
9033
9249
 
9034
9250
  // Copyright (c) 2025 MintJams Inc. Licensed under MIT License.
9035
9251
  /**
9036
- * Directive for binding event listeners to DOM elements.
9252
+ * Directive for binding event listeners to DOM elements and lifecycle hooks.
9037
9253
  * The `v-on` directive allows you to listen to DOM events and execute specified methods when those events are triggered.
9038
9254
  * The syntax for using the `v-on` directive is `v-on:event="methodName"`, where `event` is the name of the event to listen for (e.g., `click`, `mouseover`, etc.), and `methodName` is the name of the method to be called when the event occurs.
9039
9255
  * Example usage:
@@ -9042,7 +9258,16 @@
9042
9258
  * You can also use the shorthand `@event` instead of `v-on:event`. For example, `@click="handleClick"` is equivalent to `v-on:click="handleClick"`.
9043
9259
  * The `v-on` directive supports event modifiers such as `.stop`, `.prevent`, `.capture`, `.self`, and `.once` to modify the behavior of the event listener.
9044
9260
  * For example, `v-on:click.stop="handleClick"` will stop the event from propagating up the DOM tree.
9045
- * This directive is essential for handling user interactions in your application.
9261
+ *
9262
+ * Additionally, this directive supports lifecycle hooks:
9263
+ * @mount="onMount" - Called before the element is inserted into the DOM
9264
+ * @mounted="onMounted" - Called after the element is inserted into the DOM
9265
+ * @update="onUpdate" - Called before the element is updated
9266
+ * @updated="onUpdated" - Called after the element is updated
9267
+ * @unmount="onUnmount" - Called before the element is removed from the DOM
9268
+ * @unmounted="onUnmounted" - Called after the element is removed from the DOM
9269
+ *
9270
+ * This directive is essential for handling user interactions and lifecycle events in your application.
9046
9271
  * Note that the methods referenced in the directive should be defined in the component's methods object.
9047
9272
  */
9048
9273
  class VOnDirective {
@@ -9056,10 +9281,12 @@
9056
9281
  #dependentIdentifiers;
9057
9282
  /**
9058
9283
  * The event handler wrapper function, generated once and reused.
9284
+ * For lifecycle hooks, this is a no-argument function.
9285
+ * For DOM events, this accepts an Event parameter.
9059
9286
  */
9060
9287
  #handlerWrapper;
9061
9288
  /**
9062
- * The event name (e.g., "click", "input", "keydown").
9289
+ * The event name (e.g., "click", "input", "keydown") or lifecycle hook name (e.g., "mount", "mounted").
9063
9290
  */
9064
9291
  #eventName;
9065
9292
  /**
@@ -9067,9 +9294,13 @@
9067
9294
  */
9068
9295
  #modifiers = new Set();
9069
9296
  /**
9070
- * The event listener function.
9297
+ * The event listener function for DOM events.
9071
9298
  */
9072
9299
  #listener;
9300
+ /**
9301
+ * Map of lifecycle hook names to their handler functions.
9302
+ */
9303
+ #lifecycleHooks = new Map();
9073
9304
  /**
9074
9305
  * @param context The context for parsing the directive.
9075
9306
  */
@@ -9093,10 +9324,22 @@
9093
9324
  const expression = context.attribute.value;
9094
9325
  if (expression) {
9095
9326
  this.#dependentIdentifiers = ExpressionUtils.extractIdentifiers(expression, context.vNode.vApplication.functionDependencies);
9096
- this.#handlerWrapper = this.#createHandlerWrapper(expression);
9097
9327
  }
9098
- // Create and attach the event listener
9099
- if (this.#eventName) {
9328
+ // Check if this is a lifecycle hook or a regular event
9329
+ if (this.#eventName && this.#isLifecycleHook(this.#eventName)) {
9330
+ // Create handler wrapper for lifecycle hook (no event parameter)
9331
+ if (expression) {
9332
+ const handler = this.#createLifecycleHandlerWrapper(expression);
9333
+ this.#handlerWrapper = handler;
9334
+ this.#lifecycleHooks.set(this.#eventName, handler);
9335
+ }
9336
+ }
9337
+ else if (this.#eventName) {
9338
+ // Create handler wrapper for DOM event (with event parameter)
9339
+ if (expression) {
9340
+ this.#handlerWrapper = this.#createEventHandlerWrapper(expression);
9341
+ }
9342
+ // Create and attach DOM event listener
9100
9343
  this.#attachEventListener();
9101
9344
  }
9102
9345
  // Remove the directive attribute from the element
@@ -9144,6 +9387,42 @@
9144
9387
  get dependentIdentifiers() {
9145
9388
  return this.#dependentIdentifiers ?? [];
9146
9389
  }
9390
+ /**
9391
+ * @inheritdoc
9392
+ */
9393
+ get onMount() {
9394
+ return this.#lifecycleHooks.get('mount');
9395
+ }
9396
+ /**
9397
+ * @inheritdoc
9398
+ */
9399
+ get onMounted() {
9400
+ return this.#lifecycleHooks.get('mounted');
9401
+ }
9402
+ /**
9403
+ * @inheritdoc
9404
+ */
9405
+ get onUpdate() {
9406
+ return this.#lifecycleHooks.get('update');
9407
+ }
9408
+ /**
9409
+ * @inheritdoc
9410
+ */
9411
+ get onUpdated() {
9412
+ return this.#lifecycleHooks.get('updated');
9413
+ }
9414
+ /**
9415
+ * @inheritdoc
9416
+ */
9417
+ get onUnmount() {
9418
+ return this.#lifecycleHooks.get('unmount');
9419
+ }
9420
+ /**
9421
+ * @inheritdoc
9422
+ */
9423
+ get onUnmounted() {
9424
+ return this.#lifecycleHooks.get('unmounted');
9425
+ }
9147
9426
  /**
9148
9427
  * @inheritdoc
9149
9428
  */
@@ -9220,11 +9499,48 @@
9220
9499
  element.addEventListener(eventName, this.#listener, useCapture);
9221
9500
  }
9222
9501
  /**
9223
- * Creates a wrapper function for the event handler, generated once and reused.
9502
+ * Checks if the event name is a lifecycle hook.
9503
+ * @param eventName The event name to check.
9504
+ * @returns True if the event name is a lifecycle hook, false otherwise.
9505
+ */
9506
+ #isLifecycleHook(eventName) {
9507
+ return ['mount', 'mounted', 'update', 'updated', 'unmount', 'unmounted'].includes(eventName);
9508
+ }
9509
+ /**
9510
+ * Creates a wrapper function for lifecycle hooks (with element parameter).
9511
+ * @param expression The expression string to evaluate.
9512
+ * @returns A function that handles the lifecycle hook.
9513
+ */
9514
+ #createLifecycleHandlerWrapper(expression) {
9515
+ const identifiers = this.#dependentIdentifiers ?? [];
9516
+ const vNode = this.#vNode;
9517
+ // Return a function that handles the lifecycle hook with proper scope
9518
+ return () => {
9519
+ const bindings = vNode.bindings;
9520
+ const el = vNode.node;
9521
+ // If the expression is just a method name, call it with bindings as 'this'
9522
+ const trimmedExpr = expression.trim();
9523
+ if (identifiers.includes(trimmedExpr) && typeof bindings?.get(trimmedExpr) === 'function') {
9524
+ const methodName = trimmedExpr;
9525
+ const originalMethod = bindings?.get(methodName);
9526
+ // Call the method with bindings as 'this' context and element as parameter
9527
+ // This allows the method to access the DOM element and bindings
9528
+ return originalMethod(el);
9529
+ }
9530
+ // For inline expressions, evaluate normally with element parameter
9531
+ const values = identifiers.map(id => vNode.bindings?.get(id));
9532
+ const args = [...identifiers, 'el'].join(", ");
9533
+ const funcBody = `return (${expression});`;
9534
+ const func = new Function(args, funcBody);
9535
+ return func.call(bindings?.raw, ...values, el);
9536
+ };
9537
+ }
9538
+ /**
9539
+ * Creates a wrapper function for DOM event handlers (with event parameter).
9224
9540
  * @param expression The expression string to evaluate.
9225
9541
  * @returns A function that handles the event.
9226
9542
  */
9227
- #createHandlerWrapper(expression) {
9543
+ #createEventHandlerWrapper(expression) {
9228
9544
  const identifiers = this.#dependentIdentifiers ?? [];
9229
9545
  const vNode = this.#vNode;
9230
9546
  // Return a function that handles the event with proper scope
@@ -9383,6 +9699,42 @@
9383
9699
  // Hide the element
9384
9700
  element.style.display = "none";
9385
9701
  }
9702
+ /**
9703
+ * @inheritdoc
9704
+ */
9705
+ get onMount() {
9706
+ return undefined;
9707
+ }
9708
+ /**
9709
+ * @inheritdoc
9710
+ */
9711
+ get onMounted() {
9712
+ return undefined;
9713
+ }
9714
+ /**
9715
+ * @inheritdoc
9716
+ */
9717
+ get onUpdate() {
9718
+ return undefined;
9719
+ }
9720
+ /**
9721
+ * @inheritdoc
9722
+ */
9723
+ get onUpdated() {
9724
+ return undefined;
9725
+ }
9726
+ /**
9727
+ * @inheritdoc
9728
+ */
9729
+ get onUnmount() {
9730
+ return undefined;
9731
+ }
9732
+ /**
9733
+ * @inheritdoc
9734
+ */
9735
+ get onUnmounted() {
9736
+ return undefined;
9737
+ }
9386
9738
  /**
9387
9739
  * @inheritdoc
9388
9740
  */