@mintjamsinc/ichigojs 0.1.9 → 0.1.10

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 CHANGED
@@ -16,9 +16,10 @@ A simple and intuitive reactive framework. Lightweight, fast, and user-friendly
16
16
  - 📦 **Lightweight** - Minimal bundle size
17
17
  - 🚀 **High Performance** - Efficient batched updates via microtask queue
18
18
  - 💪 **TypeScript** - Written in TypeScript with full type support
19
- - 🎨 **Directives** - `v-if`, `v-for`, `v-show`, `v-bind`, `v-on`, `v-model`, `v-resize`, `v-intersection`
19
+ - 🎨 **Directives** - `v-if`, `v-for`, `v-show`, `v-bind`, `v-on`, `v-model`, `v-resize`, `v-intersection`, `v-performance`
20
20
  - 📐 **Resize Observer** - Monitor element size changes with `v-resize` directive
21
21
  - 👁️ **Intersection Observer** - Detect element visibility with `v-intersection` directive
22
+ - ⚡ **Performance Observer** - Monitor performance metrics with `v-performance` directive
22
23
 
23
24
  ## Installation
24
25
 
@@ -272,6 +273,56 @@ You can also use `:options` for generic options:
272
273
  - Perfect for lazy loading, infinite scroll, and animation triggers
273
274
  - Access to element, VNode, and userData via `$ctx`
274
275
 
276
+ #### v-performance
277
+
278
+ Monitor performance metrics using PerformanceObserver:
279
+
280
+ ```html
281
+ <div v-performance="onPerformance">
282
+ Performance monitoring
283
+ </div>
284
+ ```
285
+
286
+ ```javascript
287
+ methods: {
288
+ onPerformance(entries, observer, options, $ctx) {
289
+ entries.getEntries().forEach(entry => {
290
+ console.log(`${entry.name}: ${entry.duration}ms`);
291
+ });
292
+
293
+ // Access dropped entries count if available
294
+ if (options?.droppedEntriesCount) {
295
+ console.log(`Dropped: ${options.droppedEntriesCount}`);
296
+ }
297
+ }
298
+ }
299
+ ```
300
+
301
+ **With custom options:**
302
+
303
+ ```html
304
+ <div v-performance="onPerformance"
305
+ :options.performance="{entryTypes: ['measure', 'mark']}">
306
+ Observe only measures and marks
307
+ </div>
308
+ ```
309
+
310
+ You can also use `:options` for generic options:
311
+
312
+ ```html
313
+ <div v-performance="onPerformance"
314
+ :options="{type: 'navigation', buffered: true}">
315
+ Performance monitoring
316
+ </div>
317
+ ```
318
+
319
+ **Features:**
320
+ - Native PerformanceObserver API for monitoring performance metrics
321
+ - Custom entry types and options via `:options.performance` or `:options`
322
+ - Automatic cleanup in destroy phase
323
+ - Monitor marks, measures, navigation, resource timing, and more
324
+ - Access to element, VNode, and userData via `$ctx`
325
+
275
326
  #### Lifecycle Hooks
276
327
 
277
328
  Lifecycle hooks allow you to run code at specific stages of an element's lifecycle. Each hook receives a **lifecycle context** (`$ctx`) with access to the element, VNode, and userData storage.
@@ -68,10 +68,12 @@ var StandardDirectiveName;
68
68
  StandardDirectiveName["V_BIND"] = "v-bind";
69
69
  /** Two-way data binding directives. */
70
70
  StandardDirectiveName["V_MODEL"] = "v-model";
71
- /** Slot content insertion directives. */
71
+ /** Resize observer directives. */
72
72
  StandardDirectiveName["V_RESIZE"] = "v-resize";
73
73
  /** Intersection observer directives. */
74
74
  StandardDirectiveName["V_INTERSECTION"] = "v-intersection";
75
+ /** Performance observer directives. */
76
+ StandardDirectiveName["V_PERFORMANCE"] = "v-performance";
75
77
  })(StandardDirectiveName || (StandardDirectiveName = {}));
76
78
 
77
79
  // This file was generated. Do not modify manually!
@@ -9921,6 +9923,220 @@ class VOnDirective {
9921
9923
  }
9922
9924
  }
9923
9925
 
9926
+ // Copyright (c) 2025 MintJams Inc. Licensed under MIT License.
9927
+ /**
9928
+ * Directive for observing performance metrics using PerformanceObserver.
9929
+ * The `v-performance` directive allows you to monitor various performance entries.
9930
+ *
9931
+ * Example usage:
9932
+ * <div v-performance="handlePerformance">Performance monitoring</div>
9933
+ * <div v-performance="handlePerformance" :options.performance="{entryTypes: ['measure']}">Performance monitoring</div>
9934
+ *
9935
+ * By default (without options), it observes 'mark' and 'measure' entry types.
9936
+ *
9937
+ * The handler receives PerformanceObserverEntryList, PerformanceObserver, options (with droppedEntriesCount), and $ctx as arguments:
9938
+ * handlePerformance(entries, observer, options, $ctx) {
9939
+ * entries.getEntries().forEach(entry => {
9940
+ * console.log(`${entry.name}: ${entry.duration}ms`);
9941
+ * });
9942
+ * if (options?.droppedEntriesCount) {
9943
+ * console.log(`Dropped entries: ${options.droppedEntriesCount}`);
9944
+ * }
9945
+ * }
9946
+ *
9947
+ * Options can be provided via :options or :options.performance attribute:
9948
+ * :options="{entryTypes: ['measure', 'mark']}"
9949
+ * :options.performance="{type: 'navigation', buffered: true}"
9950
+ *
9951
+ * This directive is useful for performance monitoring, profiling, and identifying
9952
+ * performance bottlenecks in your application.
9953
+ */
9954
+ class VPerformanceDirective {
9955
+ /**
9956
+ * The virtual node to which this directive is applied.
9957
+ */
9958
+ #vNode;
9959
+ /**
9960
+ * A list of variable and function names used in the directive's expression.
9961
+ */
9962
+ #dependentIdentifiers;
9963
+ /**
9964
+ * The performance handler wrapper function.
9965
+ */
9966
+ #handlerWrapper;
9967
+ /**
9968
+ * The PerformanceObserver instance.
9969
+ */
9970
+ #performanceObserver;
9971
+ /**
9972
+ * @param context The context for parsing the directive.
9973
+ */
9974
+ constructor(context) {
9975
+ this.#vNode = context.vNode;
9976
+ // Parse the expression to extract identifiers and create the handler wrapper
9977
+ const expression = context.attribute.value;
9978
+ if (expression) {
9979
+ this.#dependentIdentifiers = ExpressionUtils.extractIdentifiers(expression, context.vNode.vApplication.functionDependencies);
9980
+ this.#handlerWrapper = this.#createPerformanceHandlerWrapper(expression);
9981
+ }
9982
+ // Remove the directive attribute from the element
9983
+ this.#vNode.node.removeAttribute(context.attribute.name);
9984
+ }
9985
+ /**
9986
+ * @inheritdoc
9987
+ */
9988
+ get name() {
9989
+ return StandardDirectiveName.V_PERFORMANCE;
9990
+ }
9991
+ /**
9992
+ * @inheritdoc
9993
+ */
9994
+ get vNode() {
9995
+ return this.#vNode;
9996
+ }
9997
+ /**
9998
+ * @inheritdoc
9999
+ */
10000
+ get needsAnchor() {
10001
+ return false;
10002
+ }
10003
+ /**
10004
+ * @inheritdoc
10005
+ */
10006
+ get bindingsPreparer() {
10007
+ return undefined;
10008
+ }
10009
+ /**
10010
+ * @inheritdoc
10011
+ */
10012
+ get domUpdater() {
10013
+ return undefined;
10014
+ }
10015
+ /**
10016
+ * @inheritdoc
10017
+ */
10018
+ get templatize() {
10019
+ return false;
10020
+ }
10021
+ /**
10022
+ * @inheritdoc
10023
+ */
10024
+ get dependentIdentifiers() {
10025
+ return this.#dependentIdentifiers ?? [];
10026
+ }
10027
+ /**
10028
+ * @inheritdoc
10029
+ */
10030
+ get onMount() {
10031
+ return undefined;
10032
+ }
10033
+ /**
10034
+ * @inheritdoc
10035
+ */
10036
+ get onMounted() {
10037
+ if (!this.#handlerWrapper) {
10038
+ return undefined;
10039
+ }
10040
+ const handler = this.#handlerWrapper;
10041
+ return () => {
10042
+ // Get options from :options.performance or :options directive
10043
+ let optionsDirective = this.#vNode.directiveManager?.optionsDirective('performance');
10044
+ // Evaluate the options expression
10045
+ let options;
10046
+ if (optionsDirective && optionsDirective.expression) {
10047
+ // Evaluate the options expression
10048
+ const identifiers = optionsDirective.dependentIdentifiers;
10049
+ const values = identifiers.map(id => this.#vNode.bindings?.get(id));
10050
+ const args = identifiers.join(", ");
10051
+ const funcBody = `return (${optionsDirective.expression});`;
10052
+ const func = new Function(args, funcBody);
10053
+ options = func(...values);
10054
+ }
10055
+ // Create PerformanceObserver and start observing
10056
+ // Note: The callback receives a third argument 'options' with droppedEntriesCount in modern browsers
10057
+ // TypeScript's type definition only includes 2 arguments, so we use type assertion
10058
+ this.#performanceObserver = new PerformanceObserver(((...args) => {
10059
+ const [entries, observer, callbackOptions] = args;
10060
+ handler(entries, observer, callbackOptions);
10061
+ }));
10062
+ // If no options provided, use default: observe marks and measures
10063
+ if (!options) {
10064
+ options = { entryTypes: ['mark', 'measure'] };
10065
+ }
10066
+ // Start observing with options
10067
+ this.#performanceObserver.observe(options);
10068
+ };
10069
+ }
10070
+ /**
10071
+ * @inheritdoc
10072
+ */
10073
+ get onUpdate() {
10074
+ return undefined;
10075
+ }
10076
+ /**
10077
+ * @inheritdoc
10078
+ */
10079
+ get onUpdated() {
10080
+ return undefined;
10081
+ }
10082
+ /**
10083
+ * @inheritdoc
10084
+ */
10085
+ get onUnmount() {
10086
+ return undefined;
10087
+ }
10088
+ /**
10089
+ * @inheritdoc
10090
+ */
10091
+ get onUnmounted() {
10092
+ return undefined;
10093
+ }
10094
+ /**
10095
+ * @inheritdoc
10096
+ */
10097
+ destroy() {
10098
+ // Disconnect the PerformanceObserver when the directive is destroyed
10099
+ if (this.#performanceObserver) {
10100
+ this.#performanceObserver.disconnect();
10101
+ this.#performanceObserver = undefined;
10102
+ }
10103
+ }
10104
+ /**
10105
+ * Creates a wrapper function for performance handlers.
10106
+ * @param expression The expression string to evaluate.
10107
+ * @returns A function that handles the performance event.
10108
+ */
10109
+ #createPerformanceHandlerWrapper(expression) {
10110
+ const identifiers = this.#dependentIdentifiers ?? [];
10111
+ const vNode = this.#vNode;
10112
+ // Return a function that handles the performance event with proper scope
10113
+ return (entries, observer, options) => {
10114
+ const bindings = vNode.bindings;
10115
+ const $ctx = {
10116
+ element: vNode.node,
10117
+ vnode: vNode,
10118
+ userData: vNode.userData
10119
+ };
10120
+ // If the expression is just a method name, call it with bindings as 'this'
10121
+ const trimmedExpr = expression.trim();
10122
+ if (identifiers.includes(trimmedExpr) && typeof bindings?.get(trimmedExpr) === 'function') {
10123
+ const methodName = trimmedExpr;
10124
+ const originalMethod = bindings?.get(methodName);
10125
+ // Call the method with bindings as 'this' context
10126
+ // Pass entries, observer, options, and $ctx as arguments
10127
+ return originalMethod(entries, observer, options, $ctx);
10128
+ }
10129
+ // For inline expressions, evaluate normally
10130
+ // Note: inline expressions receive entries, observer, options, and $ctx as parameters
10131
+ const values = identifiers.map(id => vNode.bindings?.get(id));
10132
+ const args = [...identifiers, 'entries', 'observer', 'options', '$ctx'].join(", ");
10133
+ const funcBody = `return (${expression});`;
10134
+ const func = new Function(args, funcBody);
10135
+ return func.call(bindings?.raw, ...values, entries, observer, options, $ctx);
10136
+ };
10137
+ }
10138
+ }
10139
+
9924
10140
  // Copyright (c) 2025 MintJams Inc. Licensed under MIT License.
9925
10141
  /**
9926
10142
  * Directive for observing element resize events using ResizeObserver.
@@ -10351,7 +10567,9 @@ class VStandardDirectiveParser {
10351
10567
  // v-resize
10352
10568
  context.attribute.name === StandardDirectiveName.V_RESIZE ||
10353
10569
  // v-intersection
10354
- context.attribute.name === StandardDirectiveName.V_INTERSECTION) {
10570
+ context.attribute.name === StandardDirectiveName.V_INTERSECTION ||
10571
+ // v-performance
10572
+ context.attribute.name === StandardDirectiveName.V_PERFORMANCE) {
10355
10573
  return true;
10356
10574
  }
10357
10575
  return false;
@@ -10398,6 +10616,10 @@ class VStandardDirectiveParser {
10398
10616
  if (context.attribute.name === StandardDirectiveName.V_INTERSECTION) {
10399
10617
  return new VIntersectionDirective(context);
10400
10618
  }
10619
+ // v-performance
10620
+ if (context.attribute.name === StandardDirectiveName.V_PERFORMANCE) {
10621
+ return new VPerformanceDirective(context);
10622
+ }
10401
10623
  throw new Error(`The attribute "${context.attribute.name}" cannot be parsed by ${this.name}.`);
10402
10624
  }
10403
10625
  }