@mintjamsinc/ichigojs 0.1.7 → 0.1.9

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.
@@ -9,6 +9,10 @@
9
9
  }
10
10
 
11
11
  // Copyright (c) 2025 MintJams Inc. Licensed under MIT License.
12
+ /**
13
+ * Registry for managing directive parsers.
14
+ * This class allows registering, unregistering, and finding directive parsers.
15
+ */
12
16
  class VDirectiveParserRegistry {
13
17
  /**
14
18
  * The list of registered directive parsers.
@@ -49,17 +53,31 @@
49
53
  }
50
54
 
51
55
  // Copyright (c) 2025 MintJams Inc. Licensed under MIT License.
56
+ /**
57
+ * Standard directive names used in the framework.
58
+ */
52
59
  var StandardDirectiveName;
53
60
  (function (StandardDirectiveName) {
61
+ /** Conditional rendering directives (if). */
54
62
  StandardDirectiveName["V_IF"] = "v-if";
63
+ /** Conditional rendering directives (else if). */
55
64
  StandardDirectiveName["V_ELSE_IF"] = "v-else-if";
65
+ /** Conditional rendering directives (else). */
56
66
  StandardDirectiveName["V_ELSE"] = "v-else";
67
+ /** Conditional rendering directives (show). */
57
68
  StandardDirectiveName["V_SHOW"] = "v-show";
69
+ /** List rendering directives. */
58
70
  StandardDirectiveName["V_FOR"] = "v-for";
71
+ /** Event handling directives. */
59
72
  StandardDirectiveName["V_ON"] = "v-on";
73
+ /** Attribute binding directives. */
60
74
  StandardDirectiveName["V_BIND"] = "v-bind";
75
+ /** Two-way data binding directives. */
61
76
  StandardDirectiveName["V_MODEL"] = "v-model";
77
+ /** Slot content insertion directives. */
62
78
  StandardDirectiveName["V_RESIZE"] = "v-resize";
79
+ /** Intersection observer directives. */
80
+ StandardDirectiveName["V_INTERSECTION"] = "v-intersection";
63
81
  })(StandardDirectiveName || (StandardDirectiveName = {}));
64
82
 
65
83
  // This file was generated. Do not modify manually!
@@ -6580,6 +6598,9 @@
6580
6598
  };
6581
6599
 
6582
6600
  // Copyright (c) 2025 MintJams Inc. Licensed under MIT License.
6601
+ /**
6602
+ * Utility class for analyzing JavaScript expressions to extract variable and function dependencies.
6603
+ */
6583
6604
  class ExpressionUtils {
6584
6605
  /**
6585
6606
  * Extracts variable and function names used in the expression.
@@ -6874,6 +6895,19 @@
6874
6895
  get isKey() {
6875
6896
  return (this.#attributeName === 'key');
6876
6897
  }
6898
+ /**
6899
+ * Indicates if this directive is binding the "options" attribute or any of its sub-properties (e.g., "options.intersection").
6900
+ * The "options" attribute is special and is used for passing options to certain directives like VIntersectionDirective.
6901
+ */
6902
+ get isOptions() {
6903
+ return (this.#attributeName === 'options' || this.#attributeName?.startsWith('options.') === true);
6904
+ }
6905
+ /**
6906
+ * Gets the name of the attribute being bound (e.g., "src", "class", "options", "options.intersection").
6907
+ */
6908
+ get attributeName() {
6909
+ return this.#attributeName;
6910
+ }
6877
6911
  /**
6878
6912
  * Gets the original expression string from the directive.
6879
6913
  */
@@ -6926,8 +6960,8 @@
6926
6960
  * Renders the bound attribute by evaluating the expression and updating the DOM element.
6927
6961
  */
6928
6962
  #render() {
6929
- // If this directive is binding the "key" attribute, do nothing
6930
- if (this.isKey) {
6963
+ // Do nothing for special attributes
6964
+ if (this.isKey || this.isOptions) {
6931
6965
  return;
6932
6966
  }
6933
6967
  const element = this.#vNode.node;
@@ -7371,16 +7405,47 @@
7371
7405
  }
7372
7406
 
7373
7407
  // Copyright (c) 2025 MintJams Inc. Licensed under MIT License.
7408
+ /**
7409
+ * Manages directives associated with a virtual node (VNode).
7410
+ * This class is responsible for parsing, storing, and managing the lifecycle of directives.
7411
+ * It also provides access to bindings preparers and DOM updaters from the associated directives.
7412
+ */
7374
7413
  class VDirectiveManager {
7375
7414
  /**
7376
7415
  * The virtual node to which this directive handler is associated.
7377
7416
  */
7378
7417
  #vNode;
7418
+ /**
7419
+ * The list of directives associated with the virtual node.
7420
+ * This may be undefined if there are no directives.
7421
+ */
7379
7422
  #directives;
7423
+ /**
7424
+ * The anchor comment node used for certain directives (e.g., v-if, v-for).
7425
+ * This may be undefined if no directive requires an anchor.
7426
+ */
7380
7427
  #anchorNode;
7428
+ /**
7429
+ * The list of bindings preparers from the associated directives.
7430
+ * This may be undefined if no directive provides a bindings preparer.
7431
+ */
7381
7432
  #bindingsPreparers;
7433
+ /**
7434
+ * The list of DOM updaters from the associated directives.
7435
+ * This may be undefined if no directive provides a DOM updater.
7436
+ */
7382
7437
  #domUpdaters;
7438
+ /**
7439
+ * The directive that binds the ":key" or "v-bind:key" attribute, if any.
7440
+ * This directive is special and is used for optimizing rendering of lists.
7441
+ * If no such directive exists, this is undefined.
7442
+ */
7383
7443
  #keyDirective;
7444
+ /**
7445
+ * A cache of VBindDirectives for options specific to certain directives.
7446
+ * The keys are directive names (e.g., 'options', 'options.intersection').
7447
+ */
7448
+ #optionsDirectives = {};
7384
7449
  constructor(vNode) {
7385
7450
  // Directives can only be associated with element nodes
7386
7451
  if (vNode.nodeType !== Node.ELEMENT_NODE) {
@@ -7438,6 +7503,35 @@
7438
7503
  get keyDirective() {
7439
7504
  return this.#keyDirective;
7440
7505
  }
7506
+ /**
7507
+ * Gets a record of VBindDirectives for options specific to certain directives.
7508
+ * The keys are directive names (e.g., 'options', 'options.intersection').
7509
+ */
7510
+ get optionsDirectives() {
7511
+ return this.#optionsDirectives;
7512
+ }
7513
+ /**
7514
+ * Gets the VBindDirective for options specific to the given directive name.
7515
+ * Searches in order: `:options.{directive}` -> `:options`
7516
+ *
7517
+ * @param directive The directive name (e.g., 'intersection', 'resize')
7518
+ * @returns The VBindDirective instance or undefined
7519
+ */
7520
+ optionsDirective(directive) {
7521
+ if (!this.#directives || this.#directives.length === 0) {
7522
+ return undefined;
7523
+ }
7524
+ // Search for `:options.{directive}` or `v-bind:options.{directive}` first
7525
+ const specificAttrName = `options.${directive}`;
7526
+ if (this.#optionsDirectives[specificAttrName]) {
7527
+ return this.#optionsDirectives[specificAttrName];
7528
+ }
7529
+ // Fallback: search for `:options` or `v-bind:options`
7530
+ if (this.#optionsDirectives['options']) {
7531
+ return this.#optionsDirectives['options'];
7532
+ }
7533
+ return undefined;
7534
+ }
7441
7535
  /**
7442
7536
  * Cleans up any resources used by the directive handler.
7443
7537
  */
@@ -7497,6 +7591,10 @@
7497
7591
  if (directive.name === StandardDirectiveName.V_BIND && directive.isKey) {
7498
7592
  this.#keyDirective = directive;
7499
7593
  }
7594
+ // If this is an options binding directive, cache it
7595
+ if (directive.name === StandardDirectiveName.V_BIND && directive.isOptions) {
7596
+ this.#optionsDirectives[directive.name] = directive;
7597
+ }
7500
7598
  }
7501
7599
  }
7502
7600
  // Sort directives by priority: v-for > v-if > v-else-if > v-else > v-show > others
@@ -8239,6 +8337,11 @@
8239
8337
  }
8240
8338
 
8241
8339
  // Copyright (c) 2025 MintJams Inc. Licensed under MIT License.
8340
+ /**
8341
+ * Base class for conditional directives such as v-if, v-else-if, and v-else.
8342
+ * This class manages the rendering of the associated virtual node based on the evaluation of the directive's condition.
8343
+ * It also coordinates with other related conditional directives to ensure only one block is rendered at a time.
8344
+ */
8242
8345
  class VConditionalDirective {
8243
8346
  /**
8244
8347
  * The virtual node to which this directive is applied.
@@ -8984,6 +9087,209 @@
8984
9087
  }
8985
9088
  }
8986
9089
 
9090
+ // Copyright (c) 2025 MintJams Inc. Licensed under MIT License.
9091
+ /**
9092
+ * Directive for observing element intersection with viewport or ancestor elements using IntersectionObserver.
9093
+ * The `v-intersection` directive allows you to respond to changes in an element's visibility.
9094
+ *
9095
+ * Example usage:
9096
+ * <div v-intersection="handleIntersection">Observable content</div>
9097
+ * <div v-intersection="handleIntersection" :options.intersection="{threshold: 0.5}">Observable content</div>
9098
+ *
9099
+ * The handler receives IntersectionObserverEntry array as the first argument and $ctx as the second:
9100
+ * handleIntersection(entries, $ctx) {
9101
+ * const entry = entries[0];
9102
+ * if (entry.isIntersecting) {
9103
+ * console.log('Element is visible!');
9104
+ * }
9105
+ * }
9106
+ *
9107
+ * Options can be provided via :options or :options.intersection attribute:
9108
+ * :options="{root: null, threshold: 0.5, rootMargin: '0px'}"
9109
+ * :options.intersection="{root: null, threshold: 0.5, rootMargin: '0px'}"
9110
+ *
9111
+ * This directive is useful for lazy-loading, infinite scrolling, animation triggers,
9112
+ * and other features that depend on element visibility.
9113
+ */
9114
+ class VIntersectionDirective {
9115
+ /**
9116
+ * The virtual node to which this directive is applied.
9117
+ */
9118
+ #vNode;
9119
+ /**
9120
+ * A list of variable and function names used in the directive's expression.
9121
+ */
9122
+ #dependentIdentifiers;
9123
+ /**
9124
+ * The intersection handler wrapper function.
9125
+ */
9126
+ #handlerWrapper;
9127
+ /**
9128
+ * The IntersectionObserver instance.
9129
+ */
9130
+ #intersectionObserver;
9131
+ /**
9132
+ * @param context The context for parsing the directive.
9133
+ */
9134
+ constructor(context) {
9135
+ this.#vNode = context.vNode;
9136
+ // Parse the expression to extract identifiers and create the handler wrapper
9137
+ const expression = context.attribute.value;
9138
+ if (expression) {
9139
+ this.#dependentIdentifiers = ExpressionUtils.extractIdentifiers(expression, context.vNode.vApplication.functionDependencies);
9140
+ this.#handlerWrapper = this.#createIntersectionHandlerWrapper(expression);
9141
+ }
9142
+ // Remove the directive attribute from the element
9143
+ this.#vNode.node.removeAttribute(context.attribute.name);
9144
+ }
9145
+ /**
9146
+ * @inheritdoc
9147
+ */
9148
+ get name() {
9149
+ return StandardDirectiveName.V_INTERSECTION;
9150
+ }
9151
+ /**
9152
+ * @inheritdoc
9153
+ */
9154
+ get vNode() {
9155
+ return this.#vNode;
9156
+ }
9157
+ /**
9158
+ * @inheritdoc
9159
+ */
9160
+ get needsAnchor() {
9161
+ return false;
9162
+ }
9163
+ /**
9164
+ * @inheritdoc
9165
+ */
9166
+ get bindingsPreparer() {
9167
+ return undefined;
9168
+ }
9169
+ /**
9170
+ * @inheritdoc
9171
+ */
9172
+ get domUpdater() {
9173
+ return undefined;
9174
+ }
9175
+ /**
9176
+ * @inheritdoc
9177
+ */
9178
+ get templatize() {
9179
+ return false;
9180
+ }
9181
+ /**
9182
+ * @inheritdoc
9183
+ */
9184
+ get dependentIdentifiers() {
9185
+ return this.#dependentIdentifiers ?? [];
9186
+ }
9187
+ /**
9188
+ * @inheritdoc
9189
+ */
9190
+ get onMount() {
9191
+ return undefined;
9192
+ }
9193
+ /**
9194
+ * @inheritdoc
9195
+ */
9196
+ get onMounted() {
9197
+ if (!this.#handlerWrapper) {
9198
+ return undefined;
9199
+ }
9200
+ const element = this.#vNode.node;
9201
+ const handler = this.#handlerWrapper;
9202
+ return () => {
9203
+ // Get options from :options.intersection or :options directive
9204
+ let optionsDirective = this.#vNode.directiveManager?.optionsDirective('intersection');
9205
+ // Evaluate the options expression
9206
+ let options;
9207
+ if (optionsDirective && optionsDirective.expression) {
9208
+ // Evaluate the options expression
9209
+ const identifiers = optionsDirective.dependentIdentifiers;
9210
+ const values = identifiers.map(id => this.#vNode.bindings?.get(id));
9211
+ const args = identifiers.join(", ");
9212
+ const funcBody = `return (${optionsDirective.expression});`;
9213
+ const func = new Function(args, funcBody);
9214
+ options = func(...values);
9215
+ }
9216
+ // Create IntersectionObserver and start observing
9217
+ this.#intersectionObserver = new IntersectionObserver((entries) => {
9218
+ handler(entries);
9219
+ }, options);
9220
+ this.#intersectionObserver.observe(element);
9221
+ };
9222
+ }
9223
+ /**
9224
+ * @inheritdoc
9225
+ */
9226
+ get onUpdate() {
9227
+ return undefined;
9228
+ }
9229
+ /**
9230
+ * @inheritdoc
9231
+ */
9232
+ get onUpdated() {
9233
+ return undefined;
9234
+ }
9235
+ /**
9236
+ * @inheritdoc
9237
+ */
9238
+ get onUnmount() {
9239
+ return undefined;
9240
+ }
9241
+ /**
9242
+ * @inheritdoc
9243
+ */
9244
+ get onUnmounted() {
9245
+ return undefined;
9246
+ }
9247
+ /**
9248
+ * @inheritdoc
9249
+ */
9250
+ destroy() {
9251
+ // Disconnect the IntersectionObserver when the directive is destroyed
9252
+ if (this.#intersectionObserver) {
9253
+ this.#intersectionObserver.disconnect();
9254
+ this.#intersectionObserver = undefined;
9255
+ }
9256
+ }
9257
+ /**
9258
+ * Creates a wrapper function for intersection handlers.
9259
+ * @param expression The expression string to evaluate.
9260
+ * @returns A function that handles the intersection event.
9261
+ */
9262
+ #createIntersectionHandlerWrapper(expression) {
9263
+ const identifiers = this.#dependentIdentifiers ?? [];
9264
+ const vNode = this.#vNode;
9265
+ // Return a function that handles the intersection event with proper scope
9266
+ return (entries) => {
9267
+ const bindings = vNode.bindings;
9268
+ const $ctx = {
9269
+ element: vNode.node,
9270
+ vnode: vNode,
9271
+ userData: vNode.userData
9272
+ };
9273
+ // If the expression is just a method name, call it with bindings as 'this'
9274
+ const trimmedExpr = expression.trim();
9275
+ if (identifiers.includes(trimmedExpr) && typeof bindings?.get(trimmedExpr) === 'function') {
9276
+ const methodName = trimmedExpr;
9277
+ const originalMethod = bindings?.get(methodName);
9278
+ // Call the method with bindings as 'this' context
9279
+ // Pass entries as first argument and $ctx as second argument
9280
+ return originalMethod(entries, $ctx);
9281
+ }
9282
+ // For inline expressions, evaluate normally
9283
+ // Note: inline expressions receive entries and $ctx as parameters
9284
+ const values = identifiers.map(id => vNode.bindings?.get(id));
9285
+ const args = [...identifiers, 'entries', '$ctx'].join(", ");
9286
+ const funcBody = `return (${expression});`;
9287
+ const func = new Function(args, funcBody);
9288
+ return func.call(bindings?.raw, ...values, entries, $ctx);
9289
+ };
9290
+ }
9291
+ }
9292
+
8987
9293
  // Copyright (c) 2025 MintJams Inc. Licensed under MIT License.
8988
9294
  /**
8989
9295
  * Directive for two-way data binding on form input elements.
@@ -9309,7 +9615,7 @@
9309
9615
  * @mounted="onMounted" - Called after the element is inserted into the DOM
9310
9616
  * @update="onUpdate" - Called before the element is updated
9311
9617
  * @updated="onUpdated" - Called after the element is updated
9312
- * @unmount="onUnmount" - Called before the element is removed from the DOM
9618
+ * @unmount="onUnmount" - Called before VNode cleanup begins
9313
9619
  * @unmounted="onUnmounted" - Called after VNode cleanup is complete (element reference still available)
9314
9620
  *
9315
9621
  * This directive is essential for handling user interactions and lifecycle events in your application.
@@ -9628,6 +9934,7 @@
9628
9934
  *
9629
9935
  * Example usage:
9630
9936
  * <div v-resize="handleResize">Resizable content</div>
9937
+ * <div v-resize="handleResize" :options.resize="{box: 'border-box'}">Resizable content</div>
9631
9938
  *
9632
9939
  * The handler receives ResizeObserverEntry array as the first argument and $ctx as the second:
9633
9940
  * handleResize(entries, $ctx) {
@@ -9635,6 +9942,10 @@
9635
9942
  * console.log(`Size: ${width}x${height}`);
9636
9943
  * }
9637
9944
  *
9945
+ * Options can be provided via :options or :options.resize attribute:
9946
+ * :options="{box: 'border-box'}"
9947
+ * :options.resize="{box: 'content-box'}"
9948
+ *
9638
9949
  * This directive is useful for responsive layouts, charts, and other components
9639
9950
  * that need to adapt to size changes.
9640
9951
  */
@@ -9727,11 +10038,24 @@
9727
10038
  const element = this.#vNode.node;
9728
10039
  const handler = this.#handlerWrapper;
9729
10040
  return () => {
10041
+ // Get options from :options.resize or :options directive
10042
+ let optionsDirective = this.#vNode.directiveManager?.optionsDirective('resize');
10043
+ // Evaluate the options expression
10044
+ let options;
10045
+ if (optionsDirective && optionsDirective.expression) {
10046
+ // Evaluate the options expression
10047
+ const identifiers = optionsDirective.dependentIdentifiers;
10048
+ const values = identifiers.map(id => this.#vNode.bindings?.get(id));
10049
+ const args = identifiers.join(", ");
10050
+ const funcBody = `return (${optionsDirective.expression});`;
10051
+ const func = new Function(args, funcBody);
10052
+ options = func(...values);
10053
+ }
9730
10054
  // Create ResizeObserver and start observing
9731
10055
  this.#resizeObserver = new ResizeObserver((entries) => {
9732
10056
  handler(entries);
9733
10057
  });
9734
- this.#resizeObserver.observe(element);
10058
+ this.#resizeObserver.observe(element, options);
9735
10059
  };
9736
10060
  }
9737
10061
  /**
@@ -10031,7 +10355,9 @@
10031
10355
  context.attribute.name === StandardDirectiveName.V_MODEL ||
10032
10356
  context.attribute.name.startsWith(StandardDirectiveName.V_MODEL + ".") ||
10033
10357
  // v-resize
10034
- context.attribute.name === StandardDirectiveName.V_RESIZE) {
10358
+ context.attribute.name === StandardDirectiveName.V_RESIZE ||
10359
+ // v-intersection
10360
+ context.attribute.name === StandardDirectiveName.V_INTERSECTION) {
10035
10361
  return true;
10036
10362
  }
10037
10363
  return false;
@@ -10074,6 +10400,10 @@
10074
10400
  if (context.attribute.name === StandardDirectiveName.V_RESIZE) {
10075
10401
  return new VResizeDirective(context);
10076
10402
  }
10403
+ // v-intersection
10404
+ if (context.attribute.name === StandardDirectiveName.V_INTERSECTION) {
10405
+ return new VIntersectionDirective(context);
10406
+ }
10077
10407
  throw new Error(`The attribute "${context.attribute.name}" cannot be parsed by ${this.name}.`);
10078
10408
  }
10079
10409
  }
@@ -10084,13 +10414,13 @@
10084
10414
  */
10085
10415
  var LogLevel;
10086
10416
  (function (LogLevel) {
10087
- // Debug level
10417
+ /** Debug level */
10088
10418
  LogLevel["DEBUG"] = "debug";
10089
- // Info level
10419
+ /** Info level */
10090
10420
  LogLevel["INFO"] = "info";
10091
- // Warning level
10421
+ /** Warning level */
10092
10422
  LogLevel["WARN"] = "warn";
10093
- // Error level
10423
+ /** Error level */
10094
10424
  LogLevel["ERROR"] = "error";
10095
10425
  })(LogLevel || (LogLevel = {}));
10096
10426