@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.
- package/README.md +117 -18
- package/dist/ichigo.esm.js +260 -15
- package/dist/ichigo.esm.js.map +1 -1
- package/dist/ichigo.esm.min.js +1 -1
- package/dist/ichigo.esm.min.js.map +1 -1
- package/dist/ichigo.umd.js +260 -15
- package/dist/ichigo.umd.js.map +1 -1
- package/dist/ichigo.umd.min.js +1 -1
- package/dist/ichigo.umd.min.js.map +1 -1
- package/dist/types/ichigo/VNode.d.ts +15 -0
- package/dist/types/ichigo/directives/StandardDirectiveName.d.ts +2 -1
- package/dist/types/ichigo/directives/VDirective.d.ts +2 -1
- package/dist/types/ichigo/directives/VOnDirective.d.ts +1 -1
- package/dist/types/ichigo/directives/VResizeDirective.d.ts +84 -0
- package/package.json +1 -1
package/dist/ichigo.umd.js
CHANGED
@@ -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
|
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
|
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
|
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
|
9527
|
-
// This allows the method to access the DOM element and
|
9528
|
-
return originalMethod(
|
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
|
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, '
|
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,
|
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
|
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
|
-
//
|
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
|
}
|