@mintjamsinc/ichigojs 0.1.7 → 0.1.8
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 +53 -4
- package/dist/ichigo.esm.js +291 -4
- 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 +291 -4
- 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/directives/StandardDirectiveName.d.ts +2 -1
- package/dist/types/ichigo/directives/VBindDirective.d.ts +9 -0
- package/dist/types/ichigo/directives/VDirectiveManager.d.ts +18 -0
- package/dist/types/ichigo/directives/VIntersectionDirective.d.ts +91 -0
- package/dist/types/ichigo/directives/VOnDirective.d.ts +1 -1
- package/package.json +1 -1
package/dist/ichigo.umd.js
CHANGED
@@ -60,6 +60,7 @@
|
|
60
60
|
StandardDirectiveName["V_BIND"] = "v-bind";
|
61
61
|
StandardDirectiveName["V_MODEL"] = "v-model";
|
62
62
|
StandardDirectiveName["V_RESIZE"] = "v-resize";
|
63
|
+
StandardDirectiveName["V_INTERSECTION"] = "v-intersection";
|
63
64
|
})(StandardDirectiveName || (StandardDirectiveName = {}));
|
64
65
|
|
65
66
|
// This file was generated. Do not modify manually!
|
@@ -6874,6 +6875,19 @@
|
|
6874
6875
|
get isKey() {
|
6875
6876
|
return (this.#attributeName === 'key');
|
6876
6877
|
}
|
6878
|
+
/**
|
6879
|
+
* Indicates if this directive is binding the "options" attribute or any of its sub-properties (e.g., "options.intersection").
|
6880
|
+
* The "options" attribute is special and is used for passing options to certain directives like VIntersectionDirective.
|
6881
|
+
*/
|
6882
|
+
get isOptions() {
|
6883
|
+
return (this.#attributeName === 'options' || this.#attributeName?.startsWith('options.') === true);
|
6884
|
+
}
|
6885
|
+
/**
|
6886
|
+
* Gets the name of the attribute being bound (e.g., "src", "class", "options", "options.intersection").
|
6887
|
+
*/
|
6888
|
+
get attributeName() {
|
6889
|
+
return this.#attributeName;
|
6890
|
+
}
|
6877
6891
|
/**
|
6878
6892
|
* Gets the original expression string from the directive.
|
6879
6893
|
*/
|
@@ -6926,8 +6940,8 @@
|
|
6926
6940
|
* Renders the bound attribute by evaluating the expression and updating the DOM element.
|
6927
6941
|
*/
|
6928
6942
|
#render() {
|
6929
|
-
//
|
6930
|
-
if (this.isKey) {
|
6943
|
+
// Do nothing for special attributes
|
6944
|
+
if (this.isKey || this.isOptions) {
|
6931
6945
|
return;
|
6932
6946
|
}
|
6933
6947
|
const element = this.#vNode.node;
|
@@ -7371,16 +7385,47 @@
|
|
7371
7385
|
}
|
7372
7386
|
|
7373
7387
|
// Copyright (c) 2025 MintJams Inc. Licensed under MIT License.
|
7388
|
+
/**
|
7389
|
+
* Manages directives associated with a virtual node (VNode).
|
7390
|
+
* This class is responsible for parsing, storing, and managing the lifecycle of directives.
|
7391
|
+
* It also provides access to bindings preparers and DOM updaters from the associated directives.
|
7392
|
+
*/
|
7374
7393
|
class VDirectiveManager {
|
7375
7394
|
/**
|
7376
7395
|
* The virtual node to which this directive handler is associated.
|
7377
7396
|
*/
|
7378
7397
|
#vNode;
|
7398
|
+
/**
|
7399
|
+
* The list of directives associated with the virtual node.
|
7400
|
+
* This may be undefined if there are no directives.
|
7401
|
+
*/
|
7379
7402
|
#directives;
|
7403
|
+
/**
|
7404
|
+
* The anchor comment node used for certain directives (e.g., v-if, v-for).
|
7405
|
+
* This may be undefined if no directive requires an anchor.
|
7406
|
+
*/
|
7380
7407
|
#anchorNode;
|
7408
|
+
/**
|
7409
|
+
* The list of bindings preparers from the associated directives.
|
7410
|
+
* This may be undefined if no directive provides a bindings preparer.
|
7411
|
+
*/
|
7381
7412
|
#bindingsPreparers;
|
7413
|
+
/**
|
7414
|
+
* The list of DOM updaters from the associated directives.
|
7415
|
+
* This may be undefined if no directive provides a DOM updater.
|
7416
|
+
*/
|
7382
7417
|
#domUpdaters;
|
7418
|
+
/**
|
7419
|
+
* The directive that binds the ":key" or "v-bind:key" attribute, if any.
|
7420
|
+
* This directive is special and is used for optimizing rendering of lists.
|
7421
|
+
* If no such directive exists, this is undefined.
|
7422
|
+
*/
|
7383
7423
|
#keyDirective;
|
7424
|
+
/**
|
7425
|
+
* A cache of VBindDirectives for options specific to certain directives.
|
7426
|
+
* The keys are directive names (e.g., 'options', 'options.intersection').
|
7427
|
+
*/
|
7428
|
+
#optionsDirectives = {};
|
7384
7429
|
constructor(vNode) {
|
7385
7430
|
// Directives can only be associated with element nodes
|
7386
7431
|
if (vNode.nodeType !== Node.ELEMENT_NODE) {
|
@@ -7438,6 +7483,35 @@
|
|
7438
7483
|
get keyDirective() {
|
7439
7484
|
return this.#keyDirective;
|
7440
7485
|
}
|
7486
|
+
/**
|
7487
|
+
* Gets a record of VBindDirectives for options specific to certain directives.
|
7488
|
+
* The keys are directive names (e.g., 'options', 'options.intersection').
|
7489
|
+
*/
|
7490
|
+
get optionsDirectives() {
|
7491
|
+
return this.#optionsDirectives;
|
7492
|
+
}
|
7493
|
+
/**
|
7494
|
+
* Gets the VBindDirective for options specific to the given directive name.
|
7495
|
+
* Searches in order: `:options.{directive}` -> `:options`
|
7496
|
+
*
|
7497
|
+
* @param directive The directive name (e.g., 'intersection', 'resize')
|
7498
|
+
* @returns The VBindDirective instance or undefined
|
7499
|
+
*/
|
7500
|
+
optionsDirective(directive) {
|
7501
|
+
if (!this.#directives || this.#directives.length === 0) {
|
7502
|
+
return undefined;
|
7503
|
+
}
|
7504
|
+
// Search for `:options.{directive}` or `v-bind:options.{directive}` first
|
7505
|
+
const specificAttrName = `options.${directive}`;
|
7506
|
+
if (this.#optionsDirectives[specificAttrName]) {
|
7507
|
+
return this.#optionsDirectives[specificAttrName];
|
7508
|
+
}
|
7509
|
+
// Fallback: search for `:options` or `v-bind:options`
|
7510
|
+
if (this.#optionsDirectives['options']) {
|
7511
|
+
return this.#optionsDirectives['options'];
|
7512
|
+
}
|
7513
|
+
return undefined;
|
7514
|
+
}
|
7441
7515
|
/**
|
7442
7516
|
* Cleans up any resources used by the directive handler.
|
7443
7517
|
*/
|
@@ -7497,6 +7571,10 @@
|
|
7497
7571
|
if (directive.name === StandardDirectiveName.V_BIND && directive.isKey) {
|
7498
7572
|
this.#keyDirective = directive;
|
7499
7573
|
}
|
7574
|
+
// If this is an options binding directive, cache it
|
7575
|
+
if (directive.name === StandardDirectiveName.V_BIND && directive.isOptions) {
|
7576
|
+
this.#optionsDirectives[directive.name] = directive;
|
7577
|
+
}
|
7500
7578
|
}
|
7501
7579
|
}
|
7502
7580
|
// Sort directives by priority: v-for > v-if > v-else-if > v-else > v-show > others
|
@@ -8984,6 +9062,209 @@
|
|
8984
9062
|
}
|
8985
9063
|
}
|
8986
9064
|
|
9065
|
+
// Copyright (c) 2025 MintJams Inc. Licensed under MIT License.
|
9066
|
+
/**
|
9067
|
+
* Directive for observing element intersection with viewport or ancestor elements using IntersectionObserver.
|
9068
|
+
* The `v-intersection` directive allows you to respond to changes in an element's visibility.
|
9069
|
+
*
|
9070
|
+
* Example usage:
|
9071
|
+
* <div v-intersection="handleIntersection">Observable content</div>
|
9072
|
+
* <div v-intersection="handleIntersection" :options.intersection="{threshold: 0.5}">Observable content</div>
|
9073
|
+
*
|
9074
|
+
* The handler receives IntersectionObserverEntry array as the first argument and $ctx as the second:
|
9075
|
+
* handleIntersection(entries, $ctx) {
|
9076
|
+
* const entry = entries[0];
|
9077
|
+
* if (entry.isIntersecting) {
|
9078
|
+
* console.log('Element is visible!');
|
9079
|
+
* }
|
9080
|
+
* }
|
9081
|
+
*
|
9082
|
+
* Options can be provided via :options or :options.intersection attribute:
|
9083
|
+
* :options="{root: null, threshold: 0.5, rootMargin: '0px'}"
|
9084
|
+
* :options.intersection="{root: null, threshold: 0.5, rootMargin: '0px'}"
|
9085
|
+
*
|
9086
|
+
* This directive is useful for lazy-loading, infinite scrolling, animation triggers,
|
9087
|
+
* and other features that depend on element visibility.
|
9088
|
+
*/
|
9089
|
+
class VIntersectionDirective {
|
9090
|
+
/**
|
9091
|
+
* The virtual node to which this directive is applied.
|
9092
|
+
*/
|
9093
|
+
#vNode;
|
9094
|
+
/**
|
9095
|
+
* A list of variable and function names used in the directive's expression.
|
9096
|
+
*/
|
9097
|
+
#dependentIdentifiers;
|
9098
|
+
/**
|
9099
|
+
* The intersection handler wrapper function.
|
9100
|
+
*/
|
9101
|
+
#handlerWrapper;
|
9102
|
+
/**
|
9103
|
+
* The IntersectionObserver instance.
|
9104
|
+
*/
|
9105
|
+
#intersectionObserver;
|
9106
|
+
/**
|
9107
|
+
* @param context The context for parsing the directive.
|
9108
|
+
*/
|
9109
|
+
constructor(context) {
|
9110
|
+
this.#vNode = context.vNode;
|
9111
|
+
// Parse the expression to extract identifiers and create the handler wrapper
|
9112
|
+
const expression = context.attribute.value;
|
9113
|
+
if (expression) {
|
9114
|
+
this.#dependentIdentifiers = ExpressionUtils.extractIdentifiers(expression, context.vNode.vApplication.functionDependencies);
|
9115
|
+
this.#handlerWrapper = this.#createIntersectionHandlerWrapper(expression);
|
9116
|
+
}
|
9117
|
+
// Remove the directive attribute from the element
|
9118
|
+
this.#vNode.node.removeAttribute(context.attribute.name);
|
9119
|
+
}
|
9120
|
+
/**
|
9121
|
+
* @inheritdoc
|
9122
|
+
*/
|
9123
|
+
get name() {
|
9124
|
+
return StandardDirectiveName.V_INTERSECTION;
|
9125
|
+
}
|
9126
|
+
/**
|
9127
|
+
* @inheritdoc
|
9128
|
+
*/
|
9129
|
+
get vNode() {
|
9130
|
+
return this.#vNode;
|
9131
|
+
}
|
9132
|
+
/**
|
9133
|
+
* @inheritdoc
|
9134
|
+
*/
|
9135
|
+
get needsAnchor() {
|
9136
|
+
return false;
|
9137
|
+
}
|
9138
|
+
/**
|
9139
|
+
* @inheritdoc
|
9140
|
+
*/
|
9141
|
+
get bindingsPreparer() {
|
9142
|
+
return undefined;
|
9143
|
+
}
|
9144
|
+
/**
|
9145
|
+
* @inheritdoc
|
9146
|
+
*/
|
9147
|
+
get domUpdater() {
|
9148
|
+
return undefined;
|
9149
|
+
}
|
9150
|
+
/**
|
9151
|
+
* @inheritdoc
|
9152
|
+
*/
|
9153
|
+
get templatize() {
|
9154
|
+
return false;
|
9155
|
+
}
|
9156
|
+
/**
|
9157
|
+
* @inheritdoc
|
9158
|
+
*/
|
9159
|
+
get dependentIdentifiers() {
|
9160
|
+
return this.#dependentIdentifiers ?? [];
|
9161
|
+
}
|
9162
|
+
/**
|
9163
|
+
* @inheritdoc
|
9164
|
+
*/
|
9165
|
+
get onMount() {
|
9166
|
+
return undefined;
|
9167
|
+
}
|
9168
|
+
/**
|
9169
|
+
* @inheritdoc
|
9170
|
+
*/
|
9171
|
+
get onMounted() {
|
9172
|
+
if (!this.#handlerWrapper) {
|
9173
|
+
return undefined;
|
9174
|
+
}
|
9175
|
+
const element = this.#vNode.node;
|
9176
|
+
const handler = this.#handlerWrapper;
|
9177
|
+
return () => {
|
9178
|
+
// Get options from :options.intersection or :options directive
|
9179
|
+
let optionsDirective = this.#vNode.directiveManager?.optionsDirective('intersection');
|
9180
|
+
// Evaluate the options expression
|
9181
|
+
let options;
|
9182
|
+
if (optionsDirective && optionsDirective.expression) {
|
9183
|
+
// Evaluate the options expression
|
9184
|
+
const identifiers = optionsDirective.dependentIdentifiers;
|
9185
|
+
const values = identifiers.map(id => this.#vNode.bindings?.get(id));
|
9186
|
+
const args = identifiers.join(", ");
|
9187
|
+
const funcBody = `return (${optionsDirective.expression});`;
|
9188
|
+
const func = new Function(args, funcBody);
|
9189
|
+
options = func(...values);
|
9190
|
+
}
|
9191
|
+
// Create IntersectionObserver and start observing
|
9192
|
+
this.#intersectionObserver = new IntersectionObserver((entries) => {
|
9193
|
+
handler(entries);
|
9194
|
+
}, options);
|
9195
|
+
this.#intersectionObserver.observe(element);
|
9196
|
+
};
|
9197
|
+
}
|
9198
|
+
/**
|
9199
|
+
* @inheritdoc
|
9200
|
+
*/
|
9201
|
+
get onUpdate() {
|
9202
|
+
return undefined;
|
9203
|
+
}
|
9204
|
+
/**
|
9205
|
+
* @inheritdoc
|
9206
|
+
*/
|
9207
|
+
get onUpdated() {
|
9208
|
+
return undefined;
|
9209
|
+
}
|
9210
|
+
/**
|
9211
|
+
* @inheritdoc
|
9212
|
+
*/
|
9213
|
+
get onUnmount() {
|
9214
|
+
return undefined;
|
9215
|
+
}
|
9216
|
+
/**
|
9217
|
+
* @inheritdoc
|
9218
|
+
*/
|
9219
|
+
get onUnmounted() {
|
9220
|
+
return undefined;
|
9221
|
+
}
|
9222
|
+
/**
|
9223
|
+
* @inheritdoc
|
9224
|
+
*/
|
9225
|
+
destroy() {
|
9226
|
+
// Disconnect the IntersectionObserver when the directive is destroyed
|
9227
|
+
if (this.#intersectionObserver) {
|
9228
|
+
this.#intersectionObserver.disconnect();
|
9229
|
+
this.#intersectionObserver = undefined;
|
9230
|
+
}
|
9231
|
+
}
|
9232
|
+
/**
|
9233
|
+
* Creates a wrapper function for intersection handlers.
|
9234
|
+
* @param expression The expression string to evaluate.
|
9235
|
+
* @returns A function that handles the intersection event.
|
9236
|
+
*/
|
9237
|
+
#createIntersectionHandlerWrapper(expression) {
|
9238
|
+
const identifiers = this.#dependentIdentifiers ?? [];
|
9239
|
+
const vNode = this.#vNode;
|
9240
|
+
// Return a function that handles the intersection event with proper scope
|
9241
|
+
return (entries) => {
|
9242
|
+
const bindings = vNode.bindings;
|
9243
|
+
const $ctx = {
|
9244
|
+
element: vNode.node,
|
9245
|
+
vnode: vNode,
|
9246
|
+
userData: vNode.userData
|
9247
|
+
};
|
9248
|
+
// If the expression is just a method name, call it with bindings as 'this'
|
9249
|
+
const trimmedExpr = expression.trim();
|
9250
|
+
if (identifiers.includes(trimmedExpr) && typeof bindings?.get(trimmedExpr) === 'function') {
|
9251
|
+
const methodName = trimmedExpr;
|
9252
|
+
const originalMethod = bindings?.get(methodName);
|
9253
|
+
// Call the method with bindings as 'this' context
|
9254
|
+
// Pass entries as first argument and $ctx as second argument
|
9255
|
+
return originalMethod(entries, $ctx);
|
9256
|
+
}
|
9257
|
+
// For inline expressions, evaluate normally
|
9258
|
+
// Note: inline expressions receive entries and $ctx as parameters
|
9259
|
+
const values = identifiers.map(id => vNode.bindings?.get(id));
|
9260
|
+
const args = [...identifiers, 'entries', '$ctx'].join(", ");
|
9261
|
+
const funcBody = `return (${expression});`;
|
9262
|
+
const func = new Function(args, funcBody);
|
9263
|
+
return func.call(bindings?.raw, ...values, entries, $ctx);
|
9264
|
+
};
|
9265
|
+
}
|
9266
|
+
}
|
9267
|
+
|
8987
9268
|
// Copyright (c) 2025 MintJams Inc. Licensed under MIT License.
|
8988
9269
|
/**
|
8989
9270
|
* Directive for two-way data binding on form input elements.
|
@@ -9309,7 +9590,7 @@
|
|
9309
9590
|
* @mounted="onMounted" - Called after the element is inserted into the DOM
|
9310
9591
|
* @update="onUpdate" - Called before the element is updated
|
9311
9592
|
* @updated="onUpdated" - Called after the element is updated
|
9312
|
-
* @unmount="onUnmount" - Called before
|
9593
|
+
* @unmount="onUnmount" - Called before VNode cleanup begins
|
9313
9594
|
* @unmounted="onUnmounted" - Called after VNode cleanup is complete (element reference still available)
|
9314
9595
|
*
|
9315
9596
|
* This directive is essential for handling user interactions and lifecycle events in your application.
|
@@ -10031,7 +10312,9 @@
|
|
10031
10312
|
context.attribute.name === StandardDirectiveName.V_MODEL ||
|
10032
10313
|
context.attribute.name.startsWith(StandardDirectiveName.V_MODEL + ".") ||
|
10033
10314
|
// v-resize
|
10034
|
-
context.attribute.name === StandardDirectiveName.V_RESIZE
|
10315
|
+
context.attribute.name === StandardDirectiveName.V_RESIZE ||
|
10316
|
+
// v-intersection
|
10317
|
+
context.attribute.name === StandardDirectiveName.V_INTERSECTION) {
|
10035
10318
|
return true;
|
10036
10319
|
}
|
10037
10320
|
return false;
|
@@ -10074,6 +10357,10 @@
|
|
10074
10357
|
if (context.attribute.name === StandardDirectiveName.V_RESIZE) {
|
10075
10358
|
return new VResizeDirective(context);
|
10076
10359
|
}
|
10360
|
+
// v-intersection
|
10361
|
+
if (context.attribute.name === StandardDirectiveName.V_INTERSECTION) {
|
10362
|
+
return new VIntersectionDirective(context);
|
10363
|
+
}
|
10077
10364
|
throw new Error(`The attribute "${context.attribute.name}" cannot be parsed by ${this.name}.`);
|
10078
10365
|
}
|
10079
10366
|
}
|