@mintjamsinc/ichigojs 0.1.5 → 0.1.7

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.
@@ -59,6 +59,7 @@
59
59
  StandardDirectiveName["V_ON"] = "v-on";
60
60
  StandardDirectiveName["V_BIND"] = "v-bind";
61
61
  StandardDirectiveName["V_MODEL"] = "v-model";
62
+ StandardDirectiveName["V_RESIZE"] = "v-resize";
62
63
  })(StandardDirectiveName || (StandardDirectiveName = {}));
63
64
 
64
65
  // This file was generated. Do not modify manually!
@@ -7678,6 +7679,13 @@
7678
7679
  * This is optional and may be undefined if the node has not been templatized.
7679
7680
  */
7680
7681
  #templatized;
7682
+ /**
7683
+ * User data storage for lifecycle directives.
7684
+ * This provides a Proxy-free space where developers can store arbitrary data
7685
+ * associated with this VNode. The data is automatically cleaned up when the
7686
+ * VNode is destroyed.
7687
+ */
7688
+ #userData;
7681
7689
  /**
7682
7690
  * Creates an instance of the virtual node.
7683
7691
  * @param args The initialization arguments for the virtual node.
@@ -7889,6 +7897,18 @@
7889
7897
  this.#preparableIdentifiers = preparableIdentifiers.length === 0 ? [] : [...new Set(preparableIdentifiers)];
7890
7898
  return this.#preparableIdentifiers;
7891
7899
  }
7900
+ /**
7901
+ * Gets the user data storage for this virtual node.
7902
+ * This is lazily initialized and provides a Proxy-free space for storing
7903
+ * arbitrary data associated with lifecycle directives.
7904
+ * @returns A Map for storing user data.
7905
+ */
7906
+ get userData() {
7907
+ if (!this.#userData) {
7908
+ this.#userData = new Map();
7909
+ }
7910
+ return this.#userData;
7911
+ }
7892
7912
  /**
7893
7913
  * The DOM path of this virtual node.
7894
7914
  * This is a string representation of the path from the root to this node,
@@ -8095,6 +8115,14 @@
8095
8115
  /**
8096
8116
  * Cleans up any resources used by this virtual node.
8097
8117
  * This method is called when the virtual node is no longer needed.
8118
+ *
8119
+ * Cleanup order:
8120
+ * 1. Call onUnmount lifecycle hooks
8121
+ * 2. Auto-cleanup userData (close() on Closeable objects)
8122
+ * 3. Recursively destroy child nodes
8123
+ * 4. Unregister dependencies
8124
+ * 5. Clean up directive manager
8125
+ * 6. Call onUnmounted lifecycle hooks
8098
8126
  */
8099
8127
  destroy() {
8100
8128
  // If no directive requires template preservation, call onUnmount for directives that do not templatize
@@ -8103,6 +8131,23 @@
8103
8131
  d.onUnmount?.();
8104
8132
  });
8105
8133
  }
8134
+ // Clean up user data, calling close() on any Closeable objects
8135
+ // This happens after onUnmount but before other cleanup, allowing users to
8136
+ // perform custom cleanup in onUnmount while having automatic cleanup of userData
8137
+ if (this.#userData) {
8138
+ for (const [key, value] of this.#userData.entries()) {
8139
+ try {
8140
+ // If the value has a close() method (Closeable pattern), call it
8141
+ if (value && typeof value === 'object' && typeof value.close === 'function') {
8142
+ value.close();
8143
+ }
8144
+ }
8145
+ catch (error) {
8146
+ this.#vApplication.logManager.getLogger(this.constructor.name).error(`Error closing user data '${key}': ${error}`);
8147
+ }
8148
+ }
8149
+ this.#userData.clear();
8150
+ }
8106
8151
  // Recursively destroy child nodes
8107
8152
  if (this.#childVNodes) {
8108
8153
  for (const childVNode of this.#childVNodes) {
@@ -9265,7 +9310,7 @@
9265
9310
  * @update="onUpdate" - Called before the element is updated
9266
9311
  * @updated="onUpdated" - Called after the element is updated
9267
9312
  * @unmount="onUnmount" - Called before the element is removed from the DOM
9268
- * @unmounted="onUnmounted" - Called after the element is removed from the DOM
9313
+ * @unmounted="onUnmounted" - Called after VNode cleanup is complete (element reference still available)
9269
9314
  *
9270
9315
  * This directive is essential for handling user interactions and lifecycle events in your application.
9271
9316
  * Note that the methods referenced in the directive should be defined in the component's methods object.
@@ -9507,7 +9552,7 @@
9507
9552
  return ['mount', 'mounted', 'update', 'updated', 'unmount', 'unmounted'].includes(eventName);
9508
9553
  }
9509
9554
  /**
9510
- * Creates a wrapper function for lifecycle hooks (with element parameter).
9555
+ * Creates a wrapper function for lifecycle hooks (with context parameter).
9511
9556
  * @param expression The expression string to evaluate.
9512
9557
  * @returns A function that handles the lifecycle hook.
9513
9558
  */
@@ -9517,26 +9562,31 @@
9517
9562
  // Return a function that handles the lifecycle hook with proper scope
9518
9563
  return () => {
9519
9564
  const bindings = vNode.bindings;
9520
- const el = vNode.node;
9565
+ const $ctx = {
9566
+ element: vNode.node,
9567
+ vnode: vNode,
9568
+ userData: vNode.userData
9569
+ };
9521
9570
  // If the expression is just a method name, call it with bindings as 'this'
9522
9571
  const trimmedExpr = expression.trim();
9523
9572
  if (identifiers.includes(trimmedExpr) && typeof bindings?.get(trimmedExpr) === 'function') {
9524
9573
  const methodName = trimmedExpr;
9525
9574
  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);
9575
+ // Call the method with bindings as 'this' context and context as parameter
9576
+ // This allows the method to access the DOM element, VNode, and userData
9577
+ return originalMethod($ctx);
9529
9578
  }
9530
- // For inline expressions, evaluate normally with element parameter
9579
+ // For inline expressions, evaluate normally with $ctx parameter
9580
+ // Note: $ctx is a reserved variable name for lifecycle context
9531
9581
  const values = identifiers.map(id => vNode.bindings?.get(id));
9532
- const args = [...identifiers, 'el'].join(", ");
9582
+ const args = [...identifiers, '$ctx'].join(", ");
9533
9583
  const funcBody = `return (${expression});`;
9534
9584
  const func = new Function(args, funcBody);
9535
- return func.call(bindings?.raw, ...values, el);
9585
+ return func.call(bindings?.raw, ...values, $ctx);
9536
9586
  };
9537
9587
  }
9538
9588
  /**
9539
- * Creates a wrapper function for DOM event handlers (with event parameter).
9589
+ * Creates a wrapper function for DOM event handlers (with event and $ctx parameters).
9540
9590
  * @param expression The expression string to evaluate.
9541
9591
  * @returns A function that handles the event.
9542
9592
  */
@@ -9546,21 +9596,210 @@
9546
9596
  // Return a function that handles the event with proper scope
9547
9597
  return (event) => {
9548
9598
  const bindings = vNode.bindings;
9599
+ const $ctx = {
9600
+ element: vNode.node,
9601
+ vnode: vNode,
9602
+ userData: vNode.userData
9603
+ };
9549
9604
  // If the expression is just a method name, call it with bindings as 'this'
9550
9605
  const trimmedExpr = expression.trim();
9551
9606
  if (identifiers.includes(trimmedExpr) && typeof bindings?.get(trimmedExpr) === 'function') {
9552
9607
  const methodName = trimmedExpr;
9553
9608
  const originalMethod = bindings?.get(methodName);
9554
9609
  // Call the method with bindings as 'this' context
9555
- // This allows the method to access and modify bindings properties via 'this'
9556
- return originalMethod(event);
9610
+ // Pass event as first argument and $ctx as second argument
9611
+ return originalMethod(event, $ctx);
9557
9612
  }
9558
9613
  // For inline expressions, evaluate normally
9614
+ // Note: inline expressions receive event and $ctx as parameters
9559
9615
  const values = identifiers.map(id => vNode.bindings?.get(id));
9560
- const args = identifiers.join(", ");
9616
+ const args = [...identifiers, 'event', '$ctx'].join(", ");
9561
9617
  const funcBody = `return (${expression});`;
9562
9618
  const func = new Function(args, funcBody);
9563
- return func.call(bindings?.raw, ...values, event);
9619
+ return func.call(bindings?.raw, ...values, event, $ctx);
9620
+ };
9621
+ }
9622
+ }
9623
+
9624
+ // Copyright (c) 2025 MintJams Inc. Licensed under MIT License.
9625
+ /**
9626
+ * Directive for observing element resize events using ResizeObserver.
9627
+ * The `v-resize` directive allows you to respond to changes in an element's size.
9628
+ *
9629
+ * Example usage:
9630
+ * <div v-resize="handleResize">Resizable content</div>
9631
+ *
9632
+ * The handler receives ResizeObserverEntry array as the first argument and $ctx as the second:
9633
+ * handleResize(entries, $ctx) {
9634
+ * const { width, height } = entries[0].contentRect;
9635
+ * console.log(`Size: ${width}x${height}`);
9636
+ * }
9637
+ *
9638
+ * This directive is useful for responsive layouts, charts, and other components
9639
+ * that need to adapt to size changes.
9640
+ */
9641
+ class VResizeDirective {
9642
+ /**
9643
+ * The virtual node to which this directive is applied.
9644
+ */
9645
+ #vNode;
9646
+ /**
9647
+ * A list of variable and function names used in the directive's expression.
9648
+ */
9649
+ #dependentIdentifiers;
9650
+ /**
9651
+ * The resize handler wrapper function.
9652
+ */
9653
+ #handlerWrapper;
9654
+ /**
9655
+ * The ResizeObserver instance.
9656
+ */
9657
+ #resizeObserver;
9658
+ /**
9659
+ * @param context The context for parsing the directive.
9660
+ */
9661
+ constructor(context) {
9662
+ this.#vNode = context.vNode;
9663
+ // Parse the expression to extract identifiers and create the handler wrapper
9664
+ const expression = context.attribute.value;
9665
+ if (expression) {
9666
+ this.#dependentIdentifiers = ExpressionUtils.extractIdentifiers(expression, context.vNode.vApplication.functionDependencies);
9667
+ this.#handlerWrapper = this.#createResizeHandlerWrapper(expression);
9668
+ }
9669
+ // Remove the directive attribute from the element
9670
+ this.#vNode.node.removeAttribute(context.attribute.name);
9671
+ }
9672
+ /**
9673
+ * @inheritdoc
9674
+ */
9675
+ get name() {
9676
+ return StandardDirectiveName.V_RESIZE;
9677
+ }
9678
+ /**
9679
+ * @inheritdoc
9680
+ */
9681
+ get vNode() {
9682
+ return this.#vNode;
9683
+ }
9684
+ /**
9685
+ * @inheritdoc
9686
+ */
9687
+ get needsAnchor() {
9688
+ return false;
9689
+ }
9690
+ /**
9691
+ * @inheritdoc
9692
+ */
9693
+ get bindingsPreparer() {
9694
+ return undefined;
9695
+ }
9696
+ /**
9697
+ * @inheritdoc
9698
+ */
9699
+ get domUpdater() {
9700
+ return undefined;
9701
+ }
9702
+ /**
9703
+ * @inheritdoc
9704
+ */
9705
+ get templatize() {
9706
+ return false;
9707
+ }
9708
+ /**
9709
+ * @inheritdoc
9710
+ */
9711
+ get dependentIdentifiers() {
9712
+ return this.#dependentIdentifiers ?? [];
9713
+ }
9714
+ /**
9715
+ * @inheritdoc
9716
+ */
9717
+ get onMount() {
9718
+ return undefined;
9719
+ }
9720
+ /**
9721
+ * @inheritdoc
9722
+ */
9723
+ get onMounted() {
9724
+ if (!this.#handlerWrapper) {
9725
+ return undefined;
9726
+ }
9727
+ const element = this.#vNode.node;
9728
+ const handler = this.#handlerWrapper;
9729
+ return () => {
9730
+ // Create ResizeObserver and start observing
9731
+ this.#resizeObserver = new ResizeObserver((entries) => {
9732
+ handler(entries);
9733
+ });
9734
+ this.#resizeObserver.observe(element);
9735
+ };
9736
+ }
9737
+ /**
9738
+ * @inheritdoc
9739
+ */
9740
+ get onUpdate() {
9741
+ return undefined;
9742
+ }
9743
+ /**
9744
+ * @inheritdoc
9745
+ */
9746
+ get onUpdated() {
9747
+ return undefined;
9748
+ }
9749
+ /**
9750
+ * @inheritdoc
9751
+ */
9752
+ get onUnmount() {
9753
+ return undefined;
9754
+ }
9755
+ /**
9756
+ * @inheritdoc
9757
+ */
9758
+ get onUnmounted() {
9759
+ return undefined;
9760
+ }
9761
+ /**
9762
+ * @inheritdoc
9763
+ */
9764
+ destroy() {
9765
+ // Disconnect the ResizeObserver when the directive is destroyed
9766
+ if (this.#resizeObserver) {
9767
+ this.#resizeObserver.disconnect();
9768
+ this.#resizeObserver = undefined;
9769
+ }
9770
+ }
9771
+ /**
9772
+ * Creates a wrapper function for resize handlers.
9773
+ * @param expression The expression string to evaluate.
9774
+ * @returns A function that handles the resize event.
9775
+ */
9776
+ #createResizeHandlerWrapper(expression) {
9777
+ const identifiers = this.#dependentIdentifiers ?? [];
9778
+ const vNode = this.#vNode;
9779
+ // Return a function that handles the resize event with proper scope
9780
+ return (entries) => {
9781
+ const bindings = vNode.bindings;
9782
+ const $ctx = {
9783
+ element: vNode.node,
9784
+ vnode: vNode,
9785
+ userData: vNode.userData
9786
+ };
9787
+ // If the expression is just a method name, call it with bindings as 'this'
9788
+ const trimmedExpr = expression.trim();
9789
+ if (identifiers.includes(trimmedExpr) && typeof bindings?.get(trimmedExpr) === 'function') {
9790
+ const methodName = trimmedExpr;
9791
+ const originalMethod = bindings?.get(methodName);
9792
+ // Call the method with bindings as 'this' context
9793
+ // Pass entries as first argument and $ctx as second argument
9794
+ return originalMethod(entries, $ctx);
9795
+ }
9796
+ // For inline expressions, evaluate normally
9797
+ // Note: inline expressions receive entries and $ctx as parameters
9798
+ const values = identifiers.map(id => vNode.bindings?.get(id));
9799
+ const args = [...identifiers, 'entries', '$ctx'].join(", ");
9800
+ const funcBody = `return (${expression});`;
9801
+ const func = new Function(args, funcBody);
9802
+ return func.call(bindings?.raw, ...values, entries, $ctx);
9564
9803
  };
9565
9804
  }
9566
9805
  }
@@ -9790,7 +10029,9 @@
9790
10029
  context.attribute.name.startsWith(":") ||
9791
10030
  // v-model, v-model.<modifier>
9792
10031
  context.attribute.name === StandardDirectiveName.V_MODEL ||
9793
- context.attribute.name.startsWith(StandardDirectiveName.V_MODEL + ".")) {
10032
+ context.attribute.name.startsWith(StandardDirectiveName.V_MODEL + ".") ||
10033
+ // v-resize
10034
+ context.attribute.name === StandardDirectiveName.V_RESIZE) {
9794
10035
  return true;
9795
10036
  }
9796
10037
  return false;
@@ -9829,6 +10070,10 @@
9829
10070
  context.attribute.name.startsWith(StandardDirectiveName.V_MODEL + ".")) {
9830
10071
  return new VModelDirective(context);
9831
10072
  }
10073
+ // v-resize
10074
+ if (context.attribute.name === StandardDirectiveName.V_RESIZE) {
10075
+ return new VResizeDirective(context);
10076
+ }
9832
10077
  throw new Error(`The attribute "${context.attribute.name}" cannot be parsed by ${this.name}.`);
9833
10078
  }
9834
10079
  }