diff options
Diffstat (limited to 'frontend-old/node_modules/web-vitals')
143 files changed, 0 insertions, 8153 deletions
diff --git a/frontend-old/node_modules/web-vitals/LICENSE b/frontend-old/node_modules/web-vitals/LICENSE deleted file mode 100644 index 618d629..0000000 --- a/frontend-old/node_modules/web-vitals/LICENSE +++ /dev/null @@ -1,202 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright 2020 Google LLC - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - https://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/frontend-old/node_modules/web-vitals/README.md b/frontend-old/node_modules/web-vitals/README.md deleted file mode 100644 index 639684f..0000000 --- a/frontend-old/node_modules/web-vitals/README.md +++ /dev/null @@ -1,1156 +0,0 @@ -# `web-vitals` - -- [Overview](#overview) -- [Install and load the library](#installation) - - [From npm](#import-web-vitals-from-npm) - - [From a CDN](#load-web-vitals-from-a-cdn) -- [Usage](#usage) - - [Basic usage](#basic-usage) - - [Report the value on every change](#report-the-value-on-every-change) - - [Report only the delta of changes](#report-only-the-delta-of-changes) - - [Send the results to an analytics endpoint](#send-the-results-to-an-analytics-endpoint) - - [Send the results to Google Analytics](#send-the-results-to-google-analytics) - - [Send the results to Google Tag Manager](#send-the-results-to-google-tag-manager) - - [Send attribution data](#send-attribution-data) - - [Batch multiple reports together](#batch-multiple-reports-together) -- [Build options](#build-options) - - [Which build is right for you?](#which-build-is-right-for-you) -- [API](#api) - - [Types](#types) - - [Functions](#functions) - - [Rating Thresholds](#rating-thresholds) - - [Attribution](#attribution) -- [Browser Support](#browser-support) -- [Limitations](#limitations) -- [Development](#development) -- [Integrations](#integrations) -- [License](#license) - -## Overview - -The `web-vitals` library is a tiny (~2K, brotli'd), modular library for measuring all the [Web Vitals](https://web.dev/articles/vitals) metrics on real users, in a way that accurately matches how they're measured by Chrome and reported to other Google tools (e.g. [Chrome User Experience Report](https://developers.google.com/web/tools/chrome-user-experience-report), [Page Speed Insights](https://developers.google.com/speed/pagespeed/insights/), [Search Console's Speed Report](https://webmasters.googleblog.com/2019/11/search-console-speed-report.html)). - -The library supports all of the [Core Web Vitals](https://web.dev/articles/vitals#core_web_vitals) as well as a number of other metrics that are useful in diagnosing [real-user](https://web.dev/articles/user-centric-performance-metrics) performance issues. - -### Core Web Vitals - -- [Cumulative Layout Shift (CLS)](https://web.dev/articles/cls) -- [Interaction to Next Paint (INP)](https://web.dev/articles/inp) -- [Largest Contentful Paint (LCP)](https://web.dev/articles/lcp) - -### Other metrics - -- [First Contentful Paint (FCP)](https://web.dev/articles/fcp) -- [Time to First Byte (TTFB)](https://web.dev/articles/ttfb) -- [First Input Delay (FID)](https://web.dev/articles/fid) - -> [!CAUTION] -> FID is deprecated and will be removed in the next major release. - -<a name="installation"><a> -<a name="load-the-library"><a> - -## Install and load the library - -<a name="import-web-vitals-from-npm"><a> - -The `web-vitals` library uses the `buffered` flag for [PerformanceObserver](https://developer.mozilla.org/docs/Web/API/PerformanceObserver/observe), allowing it to access performance entries that occurred before the library was loaded. - -This means you do not need to load this library early in order to get accurate performance data. In general, this library should be deferred until after other user-impacting code has loaded. - -### From npm - -You can install this library from npm by running: - -```sh -npm install web-vitals -``` - -> [!NOTE] -> If you're not using npm, you can still load `web-vitals` via `<script>` tags from a CDN like [unpkg.com](https://unpkg.com). See the [load `web-vitals` from a CDN](#load-web-vitals-from-a-cdn) usage example below for details. - -There are a few different builds of the `web-vitals` library, and how you load the library depends on which build you want to use. - -For details on the difference between the builds, see <a href="#which-build-is-right-for-you">which build is right for you</a>. - -**1. The "standard" build** - -To load the "standard" build, import modules from the `web-vitals` package in your application code (as you would with any npm package and node-based build tool): - -```js -import {onLCP, onINP, onCLS} from 'web-vitals'; - -onCLS(console.log); -onINP(console.log); -onLCP(console.log); -``` - -> [!NOTE] -> In version 2, these functions were named `getXXX()` rather than `onXXX()`. They've [been renamed](https://github.com/GoogleChrome/web-vitals/pull/222) in version 3 to reduce confusion (see [#217](https://github.com/GoogleChrome/web-vitals/pull/217) for details) and will continue to be available using the `getXXX()` until at least version 4. Users are encouraged to switch to the new names, though, for future compatibility. - -<a name="attribution-build"><a> - -**2. The "attribution" build** - -Measuring the Web Vitals scores for your real users is a great first step toward optimizing the user experience. But if your scores aren't _good_, the next step is to understand why they're not good and work to improve them. - -The "attribution" build helps you do that by including additional diagnostic information with each metric to help you identify the root cause of poor performance as well as prioritize the most important things to fix. - -The "attribution" build is slightly larger than the "standard" build (by about 600 bytes, brotli'd), so while the code size is still small, it's only recommended if you're actually using these features. - -To load the "attribution" build, change any `import` statements that reference `web-vitals` to `web-vitals/attribution`: - -```diff -- import {onLCP, onINP, onCLS} from 'web-vitals'; -+ import {onLCP, onINP, onCLS} from 'web-vitals/attribution'; -``` - -Usage for each of the imported function is identical to the standard build, but when importing from the attribution build, the [metric](#metric) objects will contain an additional [`attribution`](#attribution) property. - -See [Send attribution data](#send-attribution-data) for usage examples, and the [`attribution` reference](#attribution) for details on what values are added for each metric. - -<a name="load-web-vitals-from-a-cdn"><a> - -### From a CDN - -The recommended way to use the `web-vitals` package is to install it from npm and integrate it into your build process. However, if you're not using npm, it's still possible to use `web-vitals` by requesting it from a CDN that serves npm package files. - -The following examples show how to load `web-vitals` from [unpkg.com](https://unpkg.com/browse/web-vitals/). It is also possible to load this from [jsDelivr](https://www.jsdelivr.com/package/npm/web-vitals), and [cdnjs](https://cdnjs.com/libraries/web-vitals). - -_**Important!** The [unpkg.com](https://unpkg.com), [jsDelivr](https://www.jsdelivr.com/), and [cdnjs](https://cdnjs.com) CDNs are shown here for example purposes only. `unpkg.com`, `jsDelivr`, and `cdnjs` are not affiliated with Google, and there are no guarantees that loading the library from those CDNs will continue to work in the future. Self-hosting the built files rather than loading from the CDN is better for security, reliability, and performance reasons._ - -**Load the "standard" build** _(using a module script)_ - -```html -<!-- Append the `?module` param to load the module version of `web-vitals` --> -<script type="module"> - import {onCLS, onINP, onLCP} from 'https://unpkg.com/web-vitals@4?module'; - - onCLS(console.log); - onINP(console.log); - onLCP(console.log); -</script> -``` - -**Load the "standard" build** _(using a classic script)_ - -```html -<script> - (function () { - var script = document.createElement('script'); - script.src = 'https://unpkg.com/web-vitals@4/dist/web-vitals.iife.js'; - script.onload = function () { - // When loading `web-vitals` using a classic script, all the public - // methods can be found on the `webVitals` global namespace. - webVitals.onCLS(console.log); - webVitals.onINP(console.log); - webVitals.onLCP(console.log); - }; - document.head.appendChild(script); - })(); -</script> -``` - -**Load the "attribution" build** _(using a module script)_ - -```html -<!-- Append the `?module` param to load the module version of `web-vitals` --> -<script type="module"> - import { - onCLS, - onINP, - onLCP, - } from 'https://unpkg.com/web-vitals@4/dist/web-vitals.attribution.js?module'; - - onCLS(console.log); - onINP(console.log); - onLCP(console.log); -</script> -``` - -**Load the "attribution" build** _(using a classic script)_ - -```html -<script> - (function () { - var script = document.createElement('script'); - script.src = - 'https://unpkg.com/web-vitals@4/dist/web-vitals.attribution.iife.js'; - script.onload = function () { - // When loading `web-vitals` using a classic script, all the public - // methods can be found on the `webVitals` global namespace. - webVitals.onCLS(console.log); - webVitals.onINP(console.log); - webVitals.onLCP(console.log); - }; - document.head.appendChild(script); - })(); -</script> -``` - -## Usage - -### Basic usage - -Each of the Web Vitals metrics is exposed as a single function that takes a `callback` function that will be called any time the metric value is available and ready to be reported. - -The following example measures each of the Core Web Vitals metrics and logs the result to the console once its value is ready to report. - -_(The examples below import the "standard" build, but they will work with the "attribution" build as well.)_ - -```js -import {onCLS, onINP, onLCP} from 'web-vitals'; - -onCLS(console.log); -onINP(console.log); -onLCP(console.log); -``` - -Note that some of these metrics will not report until the user has interacted with the page, switched tabs, or the page starts to unload. If you don't see the values logged to the console immediately, try reloading the page (with [preserve log](https://developer.chrome.com/docs/devtools/console/reference/#persist) enabled) or switching tabs and then switching back. - -Also, in some cases a metric callback may never be called: - -- FID and INP are not reported if the user never interacts with the page. -- CLS, FCP, FID, and LCP are not reported if the page was loaded in the background. - -In other cases, a metric callback may be called more than once: - -- CLS and INP should be reported any time the [page's `visibilityState` changes to hidden](https://developer.chrome.com/blog/page-lifecycle-api/#advice-hidden). -- All metrics are reported again (with the above exceptions) after a page is restored from the [back/forward cache](https://web.dev/articles/bfcache). - -> [!WARNING] -> Do not call any of the Web Vitals functions (e.g. `onCLS()`, `onINP()`, `onLCP()`) more than once per page load. Each of these functions creates a `PerformanceObserver` instance and registers event listeners for the lifetime of the page. While the overhead of calling these functions once is negligible, calling them repeatedly on the same page may eventually result in a memory leak. - -### Report the value on every change - -In most cases, you only want the `callback` function to be called when the metric is ready to be reported. However, it is possible to report every change (e.g. each larger layout shift as it happens) by setting `reportAllChanges` to `true` in the optional, [configuration object](#reportopts) (second parameter). - -> [!IMPORTANT] -> `reportAllChanges` only reports when the **metric changes**, not for each **input to the metric**. For example, a new layout shift that does not increase the CLS metric will not be reported even with `reportAllChanges` set to `true` because the CLS metric has not changed. Similarly, for INP, each interaction is not reported even with `reportAllChanges` set to `true`—just when an interaction causes an increase to INP. - -This can be useful when debugging, but in general using `reportAllChanges` is not needed (or recommended) for measuring these metrics in production. - -```js -import {onCLS} from 'web-vitals'; - -// Logs CLS as the value changes. -onCLS(console.log, {reportAllChanges: true}); -``` - -### Report only the delta of changes - -Some analytics providers allow you to update the value of a metric, even after you've already sent it to their servers (overwriting the previously-sent value with the same `id`). - -Other analytics providers, however, do not allow this, so instead of reporting the new value, you need to report only the delta (the difference between the current value and the last-reported value). You can then compute the total value by summing all metric deltas sent with the same ID. - -The following example shows how to use the `id` and `delta` properties: - -```js -import {onCLS, onINP, onLCP} from 'web-vitals'; - -function logDelta({name, id, delta}) { - console.log(`${name} matching ID ${id} changed by ${delta}`); -} - -onCLS(logDelta); -onINP(logDelta); -onLCP(logDelta); -``` - -> [!NOTE] -> The first time the `callback` function is called, its `value` and `delta` properties will be the same. - -In addition to using the `id` field to group multiple deltas for the same metric, it can also be used to differentiate different metrics reported on the same page. For example, after a back/forward cache restore, a new metric object is created with a new `id` (since back/forward cache restores are considered separate page visits). - -### Send the results to an analytics endpoint - -The following example measures each of the Core Web Vitals metrics and reports them to a hypothetical `/analytics` endpoint, as soon as each is ready to be sent. - -The `sendToAnalytics()` function uses the [`navigator.sendBeacon()`](https://developer.mozilla.org/docs/Web/API/Navigator/sendBeacon) method (if available), but falls back to the [`fetch()`](https://developer.mozilla.org/docs/Web/API/Fetch_API) API when not. - -```js -import {onCLS, onINP, onLCP} from 'web-vitals'; - -function sendToAnalytics(metric) { - // Replace with whatever serialization method you prefer. - // Note: JSON.stringify will likely include more data than you need. - const body = JSON.stringify(metric); - - // Use `navigator.sendBeacon()` if available, falling back to `fetch()`. - (navigator.sendBeacon && navigator.sendBeacon('/analytics', body)) || - fetch('/analytics', {body, method: 'POST', keepalive: true}); -} - -onCLS(sendToAnalytics); -onINP(sendToAnalytics); -onLCP(sendToAnalytics); -``` - -### Send the results to Google Analytics - -Google Analytics does not support reporting metric distributions in any of its built-in reports; however, if you set a unique event parameter value (in this case, the metric_id, as shown in the example below) on every metric instance that you send to Google Analytics, you can create a report yourself by first getting the data via the [Google Analytics Data API](https://developers.google.com/analytics/devguides/reporting/data/v1) or via [BigQuery export](https://support.google.com/analytics/answer/9358801) and then visualizing it any charting library you choose. - -[Google Analytics 4](https://support.google.com/analytics/answer/10089681) introduces a new Event model allowing custom parameters instead of a fixed category, action, and label. It also supports non-integer values, making it easier to measure Web Vitals metrics compared to previous versions. - -```js -import {onCLS, onINP, onLCP} from 'web-vitals'; - -function sendToGoogleAnalytics({name, delta, value, id}) { - // Assumes the global `gtag()` function exists, see: - // https://developers.google.com/analytics/devguides/collection/ga4 - gtag('event', name, { - // Built-in params: - value: delta, // Use `delta` so the value can be summed. - // Custom params: - metric_id: id, // Needed to aggregate events. - metric_value: value, // Optional. - metric_delta: delta, // Optional. - - // OPTIONAL: any additional params or debug info here. - // See: https://web.dev/articles/debug-performance-in-the-field - // metric_rating: 'good' | 'needs-improvement' | 'poor', - // debug_info: '...', - // ... - }); -} - -onCLS(sendToGoogleAnalytics); -onINP(sendToGoogleAnalytics); -onLCP(sendToGoogleAnalytics); -``` - -For details on how to query this data in [BigQuery](https://cloud.google.com/bigquery), or visualise it in [Looker Studio](https://lookerstudio.google.com/), see [Measure and debug performance with Google Analytics 4 and BigQuery](https://web.dev/articles/vitals-ga4). - -### Send the results to Google Tag Manager - -While `web-vitals` can be called directly from Google Tag Manager, using a pre-defined custom template makes this considerably easier. Some recommended templates include: - -- [Core Web Vitals](https://tagmanager.google.com/gallery/#/owners/gtm-templates-simo-ahava/templates/core-web-vitals) by [Simo Ahava](https://www.simoahava.com/). See [Track Core Web Vitals in GA4 with Google Tag Manager](https://www.simoahava.com/analytics/track-core-web-vitals-in-ga4-with-google-tag-manager/) for usage and installation instructions. -- [Web Vitals Template for Google Tag Manager](https://github.com/google-marketing-solutions/web-vitals-gtm-template) by The Google Marketing Solutions team. See the [README](https://github.com/google-marketing-solutions/web-vitals-gtm-template?tab=readme-ov-file#web-vitals-template-for-google-tag-manager) for usage and installation instructions. - -### Send attribution data - -When using the [attribution build](#attribution-build), you can send additional data to help you debug _why_ the metric values are they way they are. - -This example sends an additional `debug_target` param to Google Analytics, corresponding to the element most associated with each metric. - -```js -import {onCLS, onINP, onLCP} from 'web-vitals/attribution'; - -function sendToGoogleAnalytics({name, delta, value, id, attribution}) { - const eventParams = { - // Built-in params: - value: delta, // Use `delta` so the value can be summed. - // Custom params: - metric_id: id, // Needed to aggregate events. - metric_value: value, // Optional. - metric_delta: delta, // Optional. - }; - - switch (name) { - case 'CLS': - eventParams.debug_target = attribution.largestShiftTarget; - break; - case 'INP': - eventParams.debug_target = attribution.interactionTarget; - break; - case 'LCP': - eventParams.debug_target = attribution.element; - break; - } - - // Assumes the global `gtag()` function exists, see: - // https://developers.google.com/analytics/devguides/collection/ga4 - gtag('event', name, eventParams); -} - -onCLS(sendToGoogleAnalytics); -onINP(sendToGoogleAnalytics); -onLCP(sendToGoogleAnalytics); -``` - -> [!NOTE] -> This example relies on custom [event parameters](https://support.google.com/analytics/answer/11396839) in Google Analytics 4. - -See [Debug performance in the field](https://web.dev/articles/debug-performance-in-the-field) for more information and examples. - -### Batch multiple reports together - -Rather than reporting each individual Web Vitals metric separately, you can minimize your network usage by batching multiple metric reports together in a single network request. - -However, since not all Web Vitals metrics become available at the same time, and since not all metrics are reported on every page, you cannot simply defer reporting until all metrics are available. - -Instead, you should keep a queue of all metrics that were reported and flush the queue whenever the page is backgrounded or unloaded: - -```js -import {onCLS, onINP, onLCP} from 'web-vitals'; - -const queue = new Set(); -function addToQueue(metric) { - queue.add(metric); -} - -function flushQueue() { - if (queue.size > 0) { - // Replace with whatever serialization method you prefer. - // Note: JSON.stringify will likely include more data than you need. - const body = JSON.stringify([...queue]); - - // Use `navigator.sendBeacon()` if available, falling back to `fetch()`. - (navigator.sendBeacon && navigator.sendBeacon('/analytics', body)) || - fetch('/analytics', {body, method: 'POST', keepalive: true}); - - queue.clear(); - } -} - -onCLS(addToQueue); -onINP(addToQueue); -onLCP(addToQueue); - -// Report all available metrics whenever the page is backgrounded or unloaded. -addEventListener('visibilitychange', () => { - if (document.visibilityState === 'hidden') { - flushQueue(); - } -}); -``` - -> [!NOTE] -> See [the Page Lifecycle guide](https://developers.google.com/web/updates/2018/07/page-lifecycle-api#legacy-lifecycle-apis-to-avoid) for an explanation of why `visibilitychange` is recommended over events like `beforeunload` and `unload`. - -<a name="bundle-versions"><a> - -## Build options - -The `web-vitals` package includes both "standard" and "attribution" builds, as well as different formats of each to allow developers to choose the format that best meets their needs or integrates with their architecture. - -The following table lists all the builds distributed with the `web-vitals` package on npm. - -<table> - <tr> - <td width="35%"> - <strong>Filename</strong> <em>(all within <code>dist/*</code>)</em> - </td> - <td><strong>Export</strong></td> - <td><strong>Description</strong></td> - </tr> - <tr> - <td><code>web-vitals.js</code></td> - <td><code>pkg.module</code></td> - <td> - <p>An ES module bundle of all metric functions, without any attribution features.</p> - This is the "standard" build and is the simplest way to consume this library out of the box. - </td> - </tr> - <tr> - <td><code>web-vitals.umd.cjs</code></td> - <td><code>pkg.main</code></td> - <td> - A UMD version of the <code>web-vitals.js</code> bundle (exposed on the <code>self.webVitals.*</code> namespace). - </td> - </tr> - <tr> - <td><code>web-vitals.iife.js</code></td> - <td>--</td> - <td> - An IIFE version of the <code>web-vitals.js</code> bundle (exposed on the <code>self.webVitals.*</code> namespace). - </td> - </tr> - <tr> - <td><code>web-vitals.attribution.js</code></td> - <td>--</td> - <td> - An ES module version of all metric functions that includes <a href="#attribution-build">attribution</a> features. - </td> - </tr> - <tr> - <td><code>web-vitals.attribution.umd.cjs</code></td> - <td>--</td> - <td> - A UMD version of the <code>web-vitals.attribution.js</code> build (exposed on the <code>self.webVitals.*</code> namespace). - </td> - </tr> - </tr> - <tr> - <td><code>web-vitals.attribution.iife.js</code></td> - <td>--</td> - <td> - An IIFE version of the <code>web-vitals.attribution.js</code> build (exposed on the <code>self.webVitals.*</code> namespace). - </td> - </tr> -</table> - -<a name="which-build-is-right-for-you"><a> - -### Which build is right for you? - -Most developers will generally want to use "standard" build (via either the ES module or UMD version, depending on your bundler/build system), as it's the easiest to use out of the box and integrate into existing tools. - -However, if you'd lke to collect additional debug information to help you diagnose performance bottlenecks based on real-user issues, use the ["attribution" build](#attribution-build). - -For guidance on how to collect and use real-user data to debug performance issues, see [Debug performance in the field](https://web.dev/debug-performance-in-the-field/). - -## API - -### Types: - -#### `Metric` - -All metrics types inherit from the following base interface: - -```ts -interface Metric { - /** - * The name of the metric (in acronym form). - */ - name: 'CLS' | 'FCP' | 'FID' | 'INP' | 'LCP' | 'TTFB'; - - /** - * The current value of the metric. - */ - value: number; - - /** - * The rating as to whether the metric value is within the "good", - * "needs improvement", or "poor" thresholds of the metric. - */ - rating: 'good' | 'needs-improvement' | 'poor'; - - /** - * The delta between the current value and the last-reported value. - * On the first report, `delta` and `value` will always be the same. - */ - delta: number; - - /** - * A unique ID representing this particular metric instance. This ID can - * be used by an analytics tool to dedupe multiple values sent for the same - * metric instance, or to group multiple deltas together and calculate a - * total. It can also be used to differentiate multiple different metric - * instances sent from the same page, which can happen if the page is - * restored from the back/forward cache (in that case new metrics object - * get created). - */ - id: string; - - /** - * Any performance entries relevant to the metric value calculation. - * The array may also be empty if the metric value was not based on any - * entries (e.g. a CLS value of 0 given no layout shifts). - */ - entries: PerformanceEntry[]; - - /** - * The type of navigation. - * - * This will be the value returned by the Navigation Timing API (or - * `undefined` if the browser doesn't support that API), with the following - * exceptions: - * - 'back-forward-cache': for pages that are restored from the bfcache. - * - 'back_forward' is renamed to 'back-forward' for consistency. - * - 'prerender': for pages that were prerendered. - * - 'restore': for pages that were discarded by the browser and then - * restored by the user. - */ - navigationType: - | 'navigate' - | 'reload' - | 'back-forward' - | 'back-forward-cache' - | 'prerender' - | 'restore'; -} -``` - -Metric-specific subclasses: - -##### `CLSMetric` - -```ts -interface CLSMetric extends Metric { - name: 'CLS'; - entries: LayoutShift[]; -} -``` - -##### `FCPMetric` - -```ts -interface FCPMetric extends Metric { - name: 'FCP'; - entries: PerformancePaintTiming[]; -} -``` - -##### `FIDMetric` - -> [!CAUTION] -> This interface is deprecated and will be removed in the next major release. - -```ts -interface FIDMetric extends Metric { - name: 'FID'; - entries: PerformanceEventTiming[]; -} -``` - -##### `INPMetric` - -```ts -interface INPMetric extends Metric { - name: 'INP'; - entries: PerformanceEventTiming[]; -} -``` - -##### `LCPMetric` - -```ts -interface LCPMetric extends Metric { - name: 'LCP'; - entries: LargestContentfulPaint[]; -} -``` - -##### `TTFBMetric` - -```ts -interface TTFBMetric extends Metric { - name: 'TTFB'; - entries: PerformanceNavigationTiming[]; -} -``` - -#### `MetricRatingThresholds` - -The thresholds of metric's "good", "needs improvement", and "poor" ratings. - -- Metric values up to and including [0] are rated "good" -- Metric values up to and including [1] are rated "needs improvement" -- Metric values above [1] are "poor" - -| Metric value | Rating | -| --------------- | ------------------- | -| ≦ [0] | "good" | -| > [0] and ≦ [1] | "needs improvement" | -| > [1] | "poor" | - -```ts -type MetricRatingThresholds = [number, number]; -``` - -_See also [Rating Thresholds](#rating-thresholds)._ - -#### `ReportOpts` - -```ts -interface ReportOpts { - reportAllChanges?: boolean; - durationThreshold?: number; -} -``` - -#### `LoadState` - -The `LoadState` type is used in several of the metric [attribution objects](#attribution). - -```ts -/** - * The loading state of the document. Note: this value is similar to - * `document.readyState` but it subdivides the "interactive" state into the - * time before and after the DOMContentLoaded event fires. - * - * State descriptions: - * - `loading`: the initial document response has not yet been fully downloaded - * and parsed. This is equivalent to the corresponding `readyState` value. - * - `dom-interactive`: the document has been fully loaded and parsed, but - * scripts may not have yet finished loading and executing. - * - `dom-content-loaded`: the document is fully loaded and parsed, and all - * scripts (except `async` scripts) have loaded and finished executing. - * - `complete`: the document and all of its sub-resources have finished - * loading. This is equivalent to the corresponding `readyState` value. - */ -type LoadState = - | 'loading' - | 'dom-interactive' - | 'dom-content-loaded' - | 'complete'; -``` - -### Functions: - -#### `onCLS()` - -```ts -function onCLS(callback: (metric: CLSMetric) => void, opts?: ReportOpts): void; -``` - -Calculates the [CLS](https://web.dev/articles/cls) value for the current page and calls the `callback` function once the value is ready to be reported, along with all `layout-shift` performance entries that were used in the metric value calculation. The reported value is a [double](https://heycam.github.io/webidl/#idl-double) (corresponding to a [layout shift score](https://web.dev/articles/cls#layout_shift_score)). - -If the `reportAllChanges` [configuration option](#reportopts) is set to `true`, the `callback` function will be called as soon as the value is initially determined as well as any time the value changes throughout the page lifespan (Note [not necessarily for every layout shift](#report-the-value-on-every-change)). - -> [!IMPORTANT] -> CLS should be continually monitored for changes throughout the entire lifespan of a page—including if the user returns to the page after it's been hidden/backgrounded. However, since browsers often [will not fire additional callbacks once the user has backgrounded a page](https://developer.chrome.com/blog/page-lifecycle-api/#advice-hidden), `callback` is always called when the page's visibility state changes to hidden. As a result, the `callback` function might be called multiple times during the same page load (see [Reporting only the delta of changes](#report-only-the-delta-of-changes) for how to manage this). - -#### `onFCP()` - -```ts -function onFCP(callback: (metric: FCPMetric) => void, opts?: ReportOpts): void; -``` - -Calculates the [FCP](https://web.dev/articles/fcp) value for the current page and calls the `callback` function once the value is ready, along with the relevant `paint` performance entry used to determine the value. The reported value is a [`DOMHighResTimeStamp`](https://developer.mozilla.org/docs/Web/API/DOMHighResTimeStamp). - -#### `onFID()` - -> [!CAUTION] -> This function is deprecated and will be removed in the next major release. - -```ts -function onFID(callback: (metric: FIDMetric) => void, opts?: ReportOpts): void; -``` - -Calculates the [FID](https://web.dev/articles/fid) value for the current page and calls the `callback` function once the value is ready, along with the relevant `first-input` performance entry used to determine the value. The reported value is a [`DOMHighResTimeStamp`](https://developer.mozilla.org/docs/Web/API/DOMHighResTimeStamp). - -> [!IMPORTANT] -> Since FID is only reported after the user interacts with the page, it's possible that it will not be reported for some page loads. - -#### `onINP()` - -```ts -function onINP(callback: (metric: INPMetric) => void, opts?: ReportOpts): void; -``` - -Calculates the [INP](https://web.dev/articles/inp) value for the current page and calls the `callback` function once the value is ready, along with the `event` performance entries reported for that interaction. The reported value is a [`DOMHighResTimeStamp`](https://developer.mozilla.org/docs/Web/API/DOMHighResTimeStamp). - -A custom `durationThreshold` [configuration option](#reportopts) can optionally be passed to control what `event-timing` entries are considered for INP reporting. The default threshold is `40`, which means INP scores of less than 40 are reported as 0. Note that this will not affect your 75th percentile INP value unless that value is also less than 40 (well below the recommended [good](https://web.dev/articles/inp#what_is_a_good_inp_score) threshold). - -If the `reportAllChanges` [configuration option](#reportopts) is set to `true`, the `callback` function will be called as soon as the value is initially determined as well as any time the value changes throughout the page lifespan (Note [not necessarily for every interaction](#report-the-value-on-every-change)). - -> [!IMPORTANT] -> INP should be continually monitored for changes throughout the entire lifespan of a page—including if the user returns to the page after it's been hidden/backgrounded. However, since browsers often [will not fire additional callbacks once the user has backgrounded a page](https://developer.chrome.com/blog/page-lifecycle-api/#advice-hidden), `callback` is always called when the page's visibility state changes to hidden. As a result, the `callback` function might be called multiple times during the same page load (see [Reporting only the delta of changes](#report-only-the-delta-of-changes) for how to manage this). - -#### `onLCP()` - -```ts -function onLCP(callback: (metric: LCPMetric) => void, opts?: ReportOpts): void; -``` - -Calculates the [LCP](https://web.dev/articles/lcp) value for the current page and calls the `callback` function once the value is ready (along with the relevant `largest-contentful-paint` performance entry used to determine the value). The reported value is a [`DOMHighResTimeStamp`](https://developer.mozilla.org/docs/Web/API/DOMHighResTimeStamp). - -If the `reportAllChanges` [configuration option](#reportopts) is set to `true`, the `callback` function will be called any time a new `largest-contentful-paint` performance entry is dispatched, or once the final value of the metric has been determined. - -#### `onTTFB()` - -```ts -function onTTFB( - callback: (metric: TTFBMetric) => void, - opts?: ReportOpts, -): void; -``` - -Calculates the [TTFB](https://web.dev/articles/ttfb) value for the current page and calls the `callback` function once the page has loaded, along with the relevant `navigation` performance entry used to determine the value. The reported value is a [`DOMHighResTimeStamp`](https://developer.mozilla.org/docs/Web/API/DOMHighResTimeStamp). - -Note, this function waits until after the page is loaded to call `callback` in order to ensure all properties of the `navigation` entry are populated. This is useful if you want to report on other metrics exposed by the [Navigation Timing API](https://w3c.github.io/navigation-timing/). - -For example, the TTFB metric starts from the page's [time origin](https://www.w3.org/TR/hr-time-2/#sec-time-origin), which means it includes time spent on DNS lookup, connection negotiation, network latency, and server processing time. - -```js -import {onTTFB} from 'web-vitals'; - -onTTFB((metric) => { - // Calculate the request time by subtracting from TTFB - // everything that happened prior to the request starting. - const requestTime = metric.value - metric.entries[0].requestStart; - console.log('Request time:', requestTime); -}); -``` - -> [!NOTE] -> Browsers that do not support `navigation` entries will fall back to using `performance.timing` (with the timestamps converted from epoch time to [`DOMHighResTimeStamp`](https://developer.mozilla.org/docs/Web/API/DOMHighResTimeStamp)). This ensures code referencing these values (like in the example above) will work the same in all browsers. - -### Rating Thresholds: - -The thresholds of each metric's "good", "needs improvement", and "poor" ratings are available as [`MetricRatingThresholds`](#metricratingthresholds). - -Example: - -```ts -import {CLSThresholds, INPThresholds, LCPThresholds} from 'web-vitals'; - -console.log(CLSThresholds); // [ 0.1, 0.25 ] -console.log(INPThresholds); // [ 200, 500 ] -console.log(LCPThresholds); // [ 2500, 4000 ] -``` - -> [!NOTE] -> It's typically not necessary (or recommended) to manually calculate metric value ratings using these thresholds. Use the [`Metric['rating']`](#metric) instead. - -### Attribution: - -The following objects contain potentially-helpful debugging information that can be sent along with the metric values for the current page visit in order to help identify issues happening to real-users in the field. - -When using the attribution build, these objects are found as an `attribution` property on each metric. - -See the [attribution build](#attribution-build) section for details on how to use this feature. - -#### `CLSAttribution` - -```ts -interface CLSAttribution { - /** - * A selector identifying the first element (in document order) that - * shifted when the single largest layout shift contributing to the page's - * CLS score occurred. - */ - largestShiftTarget?: string; - /** - * The time when the single largest layout shift contributing to the page's - * CLS score occurred. - */ - largestShiftTime?: DOMHighResTimeStamp; - /** - * The layout shift score of the single largest layout shift contributing to - * the page's CLS score. - */ - largestShiftValue?: number; - /** - * The `LayoutShiftEntry` representing the single largest layout shift - * contributing to the page's CLS score. (Useful when you need more than just - * `largestShiftTarget`, `largestShiftTime`, and `largestShiftValue`). - */ - largestShiftEntry?: LayoutShift; - /** - * The first element source (in document order) among the `sources` list - * of the `largestShiftEntry` object. (Also useful when you need more than - * just `largestShiftTarget`, `largestShiftTime`, and `largestShiftValue`). - */ - largestShiftSource?: LayoutShiftAttribution; - /** - * The loading state of the document at the time when the largest layout - * shift contribution to the page's CLS score occurred (see `LoadState` - * for details). - */ - loadState?: LoadState; -} -``` - -#### `FCPAttribution` - -```ts -interface FCPAttribution { - /** - * The time from when the user initiates loading the page until when the - * browser receives the first byte of the response (a.k.a. TTFB). - */ - timeToFirstByte: number; - /** - * The delta between TTFB and the first contentful paint (FCP). - */ - firstByteToFCP: number; - /** - * The loading state of the document at the time when FCP `occurred (see - * `LoadState` for details). Ideally, documents can paint before they finish - * loading (e.g. the `loading` or `dom-interactive` phases). - */ - loadState: LoadState; - /** - * The `PerformancePaintTiming` entry corresponding to FCP. - */ - fcpEntry?: PerformancePaintTiming; - /** - * The `navigation` entry of the current page, which is useful for diagnosing - * general page load issues. This can be used to access `serverTiming` for example: - * navigationEntry?.serverTiming - */ - navigationEntry?: PerformanceNavigationTiming; -} -``` - -#### `FIDAttribution` - -> [!CAUTION] -> This interface is deprecated and will be removed in the next major release. - -```ts -interface FIDAttribution { - /** - * A selector identifying the element that the user interacted with. This - * element will be the `target` of the `event` dispatched. - */ - eventTarget: string; - /** - * The time when the user interacted. This time will match the `timeStamp` - * value of the `event` dispatched. - */ - eventTime: number; - /** - * The `type` of the `event` dispatched from the user interaction. - */ - eventType: string; - /** - * The `PerformanceEventTiming` entry corresponding to FID. - */ - eventEntry: PerformanceEventTiming; - /** - * The loading state of the document at the time when the first interaction - * occurred (see `LoadState` for details). If the first interaction occurred - * while the document was loading and executing script (e.g. usually in the - * `dom-interactive` phase) it can result in long input delays. - */ - loadState: LoadState; -} -``` - -#### `INPAttribution` - -```ts -interface INPAttribution { - /** - * A selector identifying the element that the user first interacted with - * as part of the frame where the INP candidate interaction occurred. - * If this value is an empty string, that generally means the element was - * removed from the DOM after the interaction. - */ - interactionTarget: string; - /** - * A reference to the HTML element identified by `interactionTarget`. - * NOTE: for attribution purpose, a selector identifying the element is - * typically more useful than the element itself. However, the element is - * also made available in case additional context is needed. - */ - interactionTargetElement: Node | undefined; - /** - * The time when the user first interacted during the frame where the INP - * candidate interaction occurred (if more than one interaction occurred - * within the frame, only the first time is reported). - */ - interactionTime: DOMHighResTimeStamp; - /** - * The best-guess timestamp of the next paint after the interaction. - * In general, this timestamp is the same as the `startTime + duration` of - * the event timing entry. However, since `duration` values are rounded to - * the nearest 8ms, it can sometimes appear that the paint occurred before - * processing ended (which cannot happen). This value clamps the paint time - * so it's always after `processingEnd` from the Event Timing API and - * `renderStart` from the Long Animation Frame API (where available). - * It also averages the duration values for all entries in the same - * animation frame, which should be closer to the "real" value. - */ - nextPaintTime: DOMHighResTimeStamp; - /** - * The type of interaction, based on the event type of the `event` entry - * that corresponds to the interaction (i.e. the first `event` entry - * containing an `interactionId` dispatched in a given animation frame). - * For "pointerdown", "pointerup", or "click" events this will be "pointer", - * and for "keydown" or "keyup" events this will be "keyboard". - */ - interactionType: 'pointer' | 'keyboard'; - /** - * An array of Event Timing entries that were processed within the same - * animation frame as the INP candidate interaction. - */ - processedEventEntries: PerformanceEventTiming[]; - /** - * If the browser supports the Long Animation Frame API, this array will - * include any `long-animation-frame` entries that intersect with the INP - * candidate interaction's `startTime` and the `processingEnd` time of the - * last event processed within that animation frame. If the browser does not - * support the Long Animation Frame API or no `long-animation-frame` entries - * are detect, this array will be empty. - */ - longAnimationFrameEntries: PerformanceLongAnimationFrameTiming[]; - /** - * The time from when the user interacted with the page until when the - * browser was first able to start processing event listeners for that - * interaction. This time captures the delay before event processing can - * begin due to the main thread being busy with other work. - */ - inputDelay: number; - /** - * The time from when the first event listener started running in response to - * the user interaction until when all event listener processing has finished. - */ - processingDuration: number; - /** - * The time from when the browser finished processing all event listeners for - * the user interaction until the next frame is presented on the screen and - * visible to the user. This time includes work on the main thread (such as - * `requestAnimationFrame()` callbacks, `ResizeObserver` and - * `IntersectionObserver` callbacks, and style/layout calculation) as well - * as off-main-thread work (such as compositor, GPU, and raster work). - */ - presentationDelay: number; - /** - * The loading state of the document at the time when the interaction - * corresponding to INP occurred (see `LoadState` for details). If the - * interaction occurred while the document was loading and executing script - * (e.g. usually in the `dom-interactive` phase) it can result in long delays. - */ - loadState: LoadState; -} -``` - -#### `LCPAttribution` - -```ts -interface LCPAttribution { - /** - * The element corresponding to the largest contentful paint for the page. - */ - element?: string; - /** - * The URL (if applicable) of the LCP image resource. If the LCP element - * is a text node, this value will not be set. - */ - url?: string; - /** - * The time from when the user initiates loading the page until when the - * browser receives the first byte of the response (a.k.a. TTFB). See - * [Optimize LCP](https://web.dev/articles/optimize-lcp) for details. - */ - timeToFirstByte: number; - /** - * The delta between TTFB and when the browser starts loading the LCP - * resource (if there is one, otherwise 0). See [Optimize - * LCP](https://web.dev/articles/optimize-lcp) for details. - */ - resourceLoadDelay: number; - /** - * The total time it takes to load the LCP resource itself (if there is one, - * otherwise 0). See [Optimize LCP](https://web.dev/articles/optimize-lcp) for - * details. - */ - resourceLoadDuration: number; - /** - * The delta between when the LCP resource finishes loading until the LCP - * element is fully rendered. See [Optimize - * LCP](https://web.dev/articles/optimize-lcp) for details. - */ - elementRenderDelay: number; - /** - * The `navigation` entry of the current page, which is useful for diagnosing - * general page load issues. This can be used to access `serverTiming` for example: - * navigationEntry?.serverTiming - */ - navigationEntry?: PerformanceNavigationTiming; - /** - * The `resource` entry for the LCP resource (if applicable), which is useful - * for diagnosing resource load issues. - */ - lcpResourceEntry?: PerformanceResourceTiming; - /** - * The `LargestContentfulPaint` entry corresponding to LCP. - */ - lcpEntry?: LargestContentfulPaint; -} -``` - -#### `TTFBAttribution` - -```ts -export interface TTFBAttribution { - /** - * The total time from when the user initiates loading the page to when the - * page starts to handle the request. Large values here are typically due - * to HTTP redirects, though other browser processing contributes to this - * duration as well (so even without redirect it's generally not zero). - */ - waitingDuration: number; - /** - * The total time spent checking the HTTP cache for a match. For navigations - * handled via service worker, this duration usually includes service worker - * start-up time as well as time processing `fetch` event listeners, with - * some exceptions, see: https://github.com/w3c/navigation-timing/issues/199 - */ - cacheDuration: number; - /** - * The total time to resolve the DNS for the requested domain. - */ - dnsDuration: number; - /** - * The total time to create the connection to the requested domain. - */ - connectionDuration: number; - /** - * The total time from when the request was sent until the first byte of the - * response was received. This includes network time as well as server - * processing time. - */ - requestDuration: number; - /** - * The `navigation` entry of the current page, which is useful for diagnosing - * general page load issues. This can be used to access `serverTiming` for - * example: navigationEntry?.serverTiming - */ - navigationEntry?: PerformanceNavigationTiming; -} -``` - -## Browser Support - -The `web-vitals` code has been tested and will run without error in all major browsers as well as Internet Explorer back to version 9. However, some of the APIs required to capture these metrics are currently only available in Chromium-based browsers (e.g. Chrome, Edge, Opera, Samsung Internet). - -Browser support for each function is as follows: - -- `onCLS()`: Chromium -- `onFCP()`: Chromium, Firefox, Safari -- `onFID()`: Chromium, Firefox _(Deprecated)_ -- `onINP()`: Chromium -- `onLCP()`: Chromium, Firefox -- `onTTFB()`: Chromium, Firefox, Safari - -## Limitations - -The `web-vitals` library is primarily a wrapper around the Web APIs that measure the Web Vitals metrics, which means the limitations of those APIs will mostly apply to this library as well. More details on these limitations is available in [this blog post](https://web.dev/articles/crux-and-rum-differences). - -The primary limitation of these APIs is they have no visibility into `<iframe>` content (not even same-origin iframes), which means pages that make use of iframes will likely see a difference between the data measured by this library and the data available in the Chrome User Experience Report (which does include iframe content). - -For same-origin iframes, it's possible to use the `web-vitals` library to measure metrics, but it's tricky because it requires the developer to add the library to every frame and `postMessage()` the results to the parent frame for aggregation. - -> [!NOTE] -> Given the lack of iframe support, the `onCLS()` function technically measures [DCLS](https://github.com/wicg/layout-instability#cumulative-scores) (Document Cumulative Layout Shift) rather than CLS, if the page includes iframes). - -## Development - -### Building the code - -The `web-vitals` source code is written in TypeScript. To transpile the code and build the production bundles, run the following command. - -```sh -npm run build -``` - -To build the code and watch for changes, run: - -```sh -npm run watch -``` - -### Running the tests - -The `web-vitals` code is tested in real browsers using [webdriver.io](https://webdriver.io/). Use the following command to run the tests: - -```sh -npm test -``` - -To test any of the APIs manually, you can start the test server - -```sh -npm run test:server -``` - -Then navigate to `http://localhost:9090/test/<view>`, where `<view>` is the basename of one the templates under [/test/views/](/test/views/). - -You'll likely want to combine this with `npm run watch` to ensure any changes you make are transpiled and rebuilt. - -## Integrations - -- [**Web Vitals Connector**](https://goo.gle/web-vitals-connector): Data Studio connector to create dashboards from [Web Vitals data captured in BiqQuery](https://web.dev/articles/vitals-ga4). -- [**Core Web Vitals Custom Tag template**](https://www.simoahava.com/custom-templates/core-web-vitals/): Custom GTM template tag to [add measurement handlers](https://www.simoahava.com/analytics/track-core-web-vitals-in-ga4-with-google-tag-manager/) for all Core Web Vitals metrics. -- [**`web-vitals-reporter`**](https://github.com/treosh/web-vitals-reporter): JavaScript library to batch `callback` functions and send data with a single request. - -## License - -[Apache 2.0](/LICENSE) diff --git a/frontend-old/node_modules/web-vitals/attribution.d.ts b/frontend-old/node_modules/web-vitals/attribution.d.ts deleted file mode 100644 index eef78eb..0000000 --- a/frontend-old/node_modules/web-vitals/attribution.d.ts +++ /dev/null @@ -1,16 +0,0 @@ -/* - Copyright 2022 Google LLC - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - https://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -export * from './dist/modules/attribution/index.js'; diff --git a/frontend-old/node_modules/web-vitals/attribution.js b/frontend-old/node_modules/web-vitals/attribution.js deleted file mode 100644 index 9162af8..0000000 --- a/frontend-old/node_modules/web-vitals/attribution.js +++ /dev/null @@ -1,18 +0,0 @@ -/* - Copyright 2022 Google LLC - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - https://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -// Creates the `web-vitals/attribution` import in node-based bundlers. -// This will not be needed when export maps are widely supported. -export * from './dist/web-vitals.attribution.js'; diff --git a/frontend-old/node_modules/web-vitals/dist/modules/attribution/deprecated.d.ts b/frontend-old/node_modules/web-vitals/dist/modules/attribution/deprecated.d.ts deleted file mode 100644 index e29b6dc..0000000 --- a/frontend-old/node_modules/web-vitals/dist/modules/attribution/deprecated.d.ts +++ /dev/null @@ -1,7 +0,0 @@ -export { -/** - * @deprecated Use `onINP()` instead. - */ -onFID, } from './onFID.js'; -export { FIDThresholds } from '../onFID.js'; -export * from '../types.js'; diff --git a/frontend-old/node_modules/web-vitals/dist/modules/attribution/deprecated.js b/frontend-old/node_modules/web-vitals/dist/modules/attribution/deprecated.js deleted file mode 100644 index 2132ab4..0000000 --- a/frontend-old/node_modules/web-vitals/dist/modules/attribution/deprecated.js +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright 2024 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -export { -/** - * @deprecated Use `onINP()` instead. - */ -onFID, } from './onFID.js'; -export { FIDThresholds } from '../onFID.js'; -export * from '../types.js'; diff --git a/frontend-old/node_modules/web-vitals/dist/modules/attribution/index.d.ts b/frontend-old/node_modules/web-vitals/dist/modules/attribution/index.d.ts deleted file mode 100644 index 8513e3f..0000000 --- a/frontend-old/node_modules/web-vitals/dist/modules/attribution/index.d.ts +++ /dev/null @@ -1,12 +0,0 @@ -export { onCLS } from './onCLS.js'; -export { onFCP } from './onFCP.js'; -export { onINP } from './onINP.js'; -export { onLCP } from './onLCP.js'; -export { onTTFB } from './onTTFB.js'; -export { CLSThresholds } from '../onCLS.js'; -export { FCPThresholds } from '../onFCP.js'; -export { INPThresholds } from '../onINP.js'; -export { LCPThresholds } from '../onLCP.js'; -export { TTFBThresholds } from '../onTTFB.js'; -export * from './deprecated.js'; -export * from '../types.js'; diff --git a/frontend-old/node_modules/web-vitals/dist/modules/attribution/index.js b/frontend-old/node_modules/web-vitals/dist/modules/attribution/index.js deleted file mode 100644 index 03702fc..0000000 --- a/frontend-old/node_modules/web-vitals/dist/modules/attribution/index.js +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 2022 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -export { onCLS } from './onCLS.js'; -export { onFCP } from './onFCP.js'; -export { onINP } from './onINP.js'; -export { onLCP } from './onLCP.js'; -export { onTTFB } from './onTTFB.js'; -export { CLSThresholds } from '../onCLS.js'; -export { FCPThresholds } from '../onFCP.js'; -export { INPThresholds } from '../onINP.js'; -export { LCPThresholds } from '../onLCP.js'; -export { TTFBThresholds } from '../onTTFB.js'; -export * from './deprecated.js'; -export * from '../types.js'; diff --git a/frontend-old/node_modules/web-vitals/dist/modules/attribution/onCLS.d.ts b/frontend-old/node_modules/web-vitals/dist/modules/attribution/onCLS.d.ts deleted file mode 100644 index 65e1ca9..0000000 --- a/frontend-old/node_modules/web-vitals/dist/modules/attribution/onCLS.d.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { CLSMetricWithAttribution, ReportOpts } from '../types.js'; -/** - * Calculates the [CLS](https://web.dev/articles/cls) value for the current page and - * calls the `callback` function once the value is ready to be reported, along - * with all `layout-shift` performance entries that were used in the metric - * value calculation. The reported value is a `double` (corresponding to a - * [layout shift score](https://web.dev/articles/cls#layout_shift_score)). - * - * If the `reportAllChanges` configuration option is set to `true`, the - * `callback` function will be called as soon as the value is initially - * determined as well as any time the value changes throughout the page - * lifespan. - * - * _**Important:** CLS should be continually monitored for changes throughout - * the entire lifespan of a page—including if the user returns to the page after - * it's been hidden/backgrounded. However, since browsers often [will not fire - * additional callbacks once the user has backgrounded a - * page](https://developer.chrome.com/blog/page-lifecycle-api/#advice-hidden), - * `callback` is always called when the page's visibility state changes to - * hidden. As a result, the `callback` function might be called multiple times - * during the same page load._ - */ -export declare const onCLS: (onReport: (metric: CLSMetricWithAttribution) => void, opts?: ReportOpts) => void; diff --git a/frontend-old/node_modules/web-vitals/dist/modules/attribution/onCLS.js b/frontend-old/node_modules/web-vitals/dist/modules/attribution/onCLS.js deleted file mode 100644 index 78221fa..0000000 --- a/frontend-old/node_modules/web-vitals/dist/modules/attribution/onCLS.js +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright 2022 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import { getLoadState } from '../lib/getLoadState.js'; -import { getSelector } from '../lib/getSelector.js'; -import { onCLS as unattributedOnCLS } from '../onCLS.js'; -const getLargestLayoutShiftEntry = (entries) => { - return entries.reduce((a, b) => (a && a.value > b.value ? a : b)); -}; -const getLargestLayoutShiftSource = (sources) => { - return sources.find((s) => s.node && s.node.nodeType === 1) || sources[0]; -}; -const attributeCLS = (metric) => { - // Use an empty object if no other attribution has been set. - let attribution = {}; - if (metric.entries.length) { - const largestEntry = getLargestLayoutShiftEntry(metric.entries); - if (largestEntry && largestEntry.sources && largestEntry.sources.length) { - const largestSource = getLargestLayoutShiftSource(largestEntry.sources); - if (largestSource) { - attribution = { - largestShiftTarget: getSelector(largestSource.node), - largestShiftTime: largestEntry.startTime, - largestShiftValue: largestEntry.value, - largestShiftSource: largestSource, - largestShiftEntry: largestEntry, - loadState: getLoadState(largestEntry.startTime), - }; - } - } - } - // Use Object.assign to set property to keep tsc happy. - const metricWithAttribution = Object.assign(metric, { attribution }); - return metricWithAttribution; -}; -/** - * Calculates the [CLS](https://web.dev/articles/cls) value for the current page and - * calls the `callback` function once the value is ready to be reported, along - * with all `layout-shift` performance entries that were used in the metric - * value calculation. The reported value is a `double` (corresponding to a - * [layout shift score](https://web.dev/articles/cls#layout_shift_score)). - * - * If the `reportAllChanges` configuration option is set to `true`, the - * `callback` function will be called as soon as the value is initially - * determined as well as any time the value changes throughout the page - * lifespan. - * - * _**Important:** CLS should be continually monitored for changes throughout - * the entire lifespan of a page—including if the user returns to the page after - * it's been hidden/backgrounded. However, since browsers often [will not fire - * additional callbacks once the user has backgrounded a - * page](https://developer.chrome.com/blog/page-lifecycle-api/#advice-hidden), - * `callback` is always called when the page's visibility state changes to - * hidden. As a result, the `callback` function might be called multiple times - * during the same page load._ - */ -export const onCLS = (onReport, opts) => { - unattributedOnCLS((metric) => { - const metricWithAttribution = attributeCLS(metric); - onReport(metricWithAttribution); - }, opts); -}; diff --git a/frontend-old/node_modules/web-vitals/dist/modules/attribution/onFCP.d.ts b/frontend-old/node_modules/web-vitals/dist/modules/attribution/onFCP.d.ts deleted file mode 100644 index b0b7f37..0000000 --- a/frontend-old/node_modules/web-vitals/dist/modules/attribution/onFCP.d.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { FCPMetricWithAttribution, ReportOpts } from '../types.js'; -/** - * Calculates the [FCP](https://web.dev/articles/fcp) value for the current page and - * calls the `callback` function once the value is ready, along with the - * relevant `paint` performance entry used to determine the value. The reported - * value is a `DOMHighResTimeStamp`. - */ -export declare const onFCP: (onReport: (metric: FCPMetricWithAttribution) => void, opts?: ReportOpts) => void; diff --git a/frontend-old/node_modules/web-vitals/dist/modules/attribution/onFCP.js b/frontend-old/node_modules/web-vitals/dist/modules/attribution/onFCP.js deleted file mode 100644 index 06e87f6..0000000 --- a/frontend-old/node_modules/web-vitals/dist/modules/attribution/onFCP.js +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2022 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import { getBFCacheRestoreTime } from '../lib/bfcache.js'; -import { getLoadState } from '../lib/getLoadState.js'; -import { getNavigationEntry } from '../lib/getNavigationEntry.js'; -import { onFCP as unattributedOnFCP } from '../onFCP.js'; -const attributeFCP = (metric) => { - // Use a default object if no other attribution has been set. - let attribution = { - timeToFirstByte: 0, - firstByteToFCP: metric.value, - loadState: getLoadState(getBFCacheRestoreTime()), - }; - if (metric.entries.length) { - const navigationEntry = getNavigationEntry(); - const fcpEntry = metric.entries[metric.entries.length - 1]; - if (navigationEntry) { - const activationStart = navigationEntry.activationStart || 0; - const ttfb = Math.max(0, navigationEntry.responseStart - activationStart); - attribution = { - timeToFirstByte: ttfb, - firstByteToFCP: metric.value - ttfb, - loadState: getLoadState(metric.entries[0].startTime), - navigationEntry, - fcpEntry, - }; - } - } - // Use Object.assign to set property to keep tsc happy. - const metricWithAttribution = Object.assign(metric, { attribution }); - return metricWithAttribution; -}; -/** - * Calculates the [FCP](https://web.dev/articles/fcp) value for the current page and - * calls the `callback` function once the value is ready, along with the - * relevant `paint` performance entry used to determine the value. The reported - * value is a `DOMHighResTimeStamp`. - */ -export const onFCP = (onReport, opts) => { - unattributedOnFCP((metric) => { - const metricWithAttribution = attributeFCP(metric); - onReport(metricWithAttribution); - }, opts); -}; diff --git a/frontend-old/node_modules/web-vitals/dist/modules/attribution/onFID.d.ts b/frontend-old/node_modules/web-vitals/dist/modules/attribution/onFID.d.ts deleted file mode 100644 index b910f15..0000000 --- a/frontend-old/node_modules/web-vitals/dist/modules/attribution/onFID.d.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { FIDMetricWithAttribution, ReportOpts } from '../types.js'; -/** - * Calculates the [FID](https://web.dev/articles/fid) value for the current page and - * calls the `callback` function once the value is ready, along with the - * relevant `first-input` performance entry used to determine the value. The - * reported value is a `DOMHighResTimeStamp`. - * - * _**Important:** since FID is only reported after the user interacts with the - * page, it's possible that it will not be reported for some page loads._ - */ -export declare const onFID: (onReport: (metric: FIDMetricWithAttribution) => void, opts?: ReportOpts) => void; diff --git a/frontend-old/node_modules/web-vitals/dist/modules/attribution/onFID.js b/frontend-old/node_modules/web-vitals/dist/modules/attribution/onFID.js deleted file mode 100644 index 52f1ddc..0000000 --- a/frontend-old/node_modules/web-vitals/dist/modules/attribution/onFID.js +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2022 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import { getLoadState } from '../lib/getLoadState.js'; -import { getSelector } from '../lib/getSelector.js'; -import { onFID as unattributedOnFID } from '../onFID.js'; -const attributeFID = (metric) => { - const fidEntry = metric.entries[0]; - const attribution = { - eventTarget: getSelector(fidEntry.target), - eventType: fidEntry.name, - eventTime: fidEntry.startTime, - eventEntry: fidEntry, - loadState: getLoadState(fidEntry.startTime), - }; - // Use Object.assign to set property to keep tsc happy. - const metricWithAttribution = Object.assign(metric, { attribution }); - return metricWithAttribution; -}; -/** - * Calculates the [FID](https://web.dev/articles/fid) value for the current page and - * calls the `callback` function once the value is ready, along with the - * relevant `first-input` performance entry used to determine the value. The - * reported value is a `DOMHighResTimeStamp`. - * - * _**Important:** since FID is only reported after the user interacts with the - * page, it's possible that it will not be reported for some page loads._ - */ -export const onFID = (onReport, opts) => { - unattributedOnFID((metric) => { - const metricWithAttribution = attributeFID(metric); - onReport(metricWithAttribution); - }, opts); -}; diff --git a/frontend-old/node_modules/web-vitals/dist/modules/attribution/onINP.d.ts b/frontend-old/node_modules/web-vitals/dist/modules/attribution/onINP.d.ts deleted file mode 100644 index 217faa0..0000000 --- a/frontend-old/node_modules/web-vitals/dist/modules/attribution/onINP.d.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { INPMetricWithAttribution, ReportOpts } from '../types.js'; -export declare const interactionTargetMap: Map<number, Node>; -/** - * Calculates the [INP](https://web.dev/articles/inp) value for the current - * page and calls the `callback` function once the value is ready, along with - * the `event` performance entries reported for that interaction. The reported - * value is a `DOMHighResTimeStamp`. - * - * A custom `durationThreshold` configuration option can optionally be passed to - * control what `event-timing` entries are considered for INP reporting. The - * default threshold is `40`, which means INP scores of less than 40 are - * reported as 0. Note that this will not affect your 75th percentile INP value - * unless that value is also less than 40 (well below the recommended - * [good](https://web.dev/articles/inp#what_is_a_good_inp_score) threshold). - * - * If the `reportAllChanges` configuration option is set to `true`, the - * `callback` function will be called as soon as the value is initially - * determined as well as any time the value changes throughout the page - * lifespan. - * - * _**Important:** INP should be continually monitored for changes throughout - * the entire lifespan of a page—including if the user returns to the page after - * it's been hidden/backgrounded. However, since browsers often [will not fire - * additional callbacks once the user has backgrounded a - * page](https://developer.chrome.com/blog/page-lifecycle-api/#advice-hidden), - * `callback` is always called when the page's visibility state changes to - * hidden. As a result, the `callback` function might be called multiple times - * during the same page load._ - */ -export declare const onINP: (onReport: (metric: INPMetricWithAttribution) => void, opts?: ReportOpts) => void; diff --git a/frontend-old/node_modules/web-vitals/dist/modules/attribution/onINP.js b/frontend-old/node_modules/web-vitals/dist/modules/attribution/onINP.js deleted file mode 100644 index 51df8e3..0000000 --- a/frontend-old/node_modules/web-vitals/dist/modules/attribution/onINP.js +++ /dev/null @@ -1,256 +0,0 @@ -/* - * Copyright 2022 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import { getLoadState } from '../lib/getLoadState.js'; -import { getSelector } from '../lib/getSelector.js'; -import { longestInteractionList, entryPreProcessingCallbacks, longestInteractionMap, } from '../lib/interactions.js'; -import { observe } from '../lib/observe.js'; -import { whenIdle } from '../lib/whenIdle.js'; -import { onINP as unattributedOnINP } from '../onINP.js'; -// The maximum number of previous frames for which data is kept. -// Storing data about previous frames is necessary to handle cases where event -// and LoAF entries are dispatched out of order, and so a buffer of previous -// frame data is needed to determine various bits of INP attribution once all -// the frame-related data has come in. -// In most cases this out-of-order data is only off by a frame or two, so -// keeping the most recent 50 should be more than sufficient. -const MAX_PREVIOUS_FRAMES = 50; -// A PerformanceObserver, observing new `long-animation-frame` entries. -// If this variable is defined it means the browser supports LoAF. -let loafObserver; -// A list of LoAF entries that have been dispatched and could potentially -// intersect with the INP candidate interaction. Note that periodically this -// list is cleaned up and entries that are known to not match INP are removed. -let pendingLoAFs = []; -// An array of groups of all the event timing entries that occurred within a -// particular frame. Note that periodically this array is cleaned up and entries -// that are known to not match INP are removed. -let pendingEntriesGroups = []; -// The `processingEnd` time of most recently-processed event, chronologically. -let latestProcessingEnd = 0; -// A WeakMap to look up the event-timing-entries group of a given entry. -// Note that this only maps from "important" entries: either the first input or -// those with an `interactionId`. -const entryToEntriesGroupMap = new WeakMap(); -// A mapping of interactionIds to the target Node. -export const interactionTargetMap = new Map(); -// A reference to the idle task used to clean up entries from the above -// variables. If the value is -1 it means no task is queue, and if it's -// greater than -1 the value corresponds to the idle callback handle. -let idleHandle = -1; -/** - * Adds new LoAF entries to the `pendingLoAFs` list. - */ -const handleLoAFEntries = (entries) => { - pendingLoAFs = pendingLoAFs.concat(entries); - queueCleanup(); -}; -// Get a reference to the interaction target element in case it's removed -// from the DOM later. -const saveInteractionTarget = (entry) => { - if (entry.interactionId && - entry.target && - !interactionTargetMap.has(entry.interactionId)) { - interactionTargetMap.set(entry.interactionId, entry.target); - } -}; -/** - * Groups entries that were presented within the same animation frame by - * a common `renderTime`. This function works by referencing - * `pendingEntriesGroups` and using an existing render time if one is found - * (otherwise creating a new one). This function also adds all interaction - * entries to an `entryToRenderTimeMap` WeakMap so that the "grouped" entries - * can be looked up later. - */ -const groupEntriesByRenderTime = (entry) => { - const renderTime = entry.startTime + entry.duration; - let group; - latestProcessingEnd = Math.max(latestProcessingEnd, entry.processingEnd); - // Iterate over all previous render times in reverse order to find a match. - // Go in reverse since the most likely match will be at the end. - for (let i = pendingEntriesGroups.length - 1; i >= 0; i--) { - const potentialGroup = pendingEntriesGroups[i]; - // If a group's render time is within 8ms of the entry's render time, - // assume they were part of the same frame and add it to the group. - if (Math.abs(renderTime - potentialGroup.renderTime) <= 8) { - group = potentialGroup; - group.startTime = Math.min(entry.startTime, group.startTime); - group.processingStart = Math.min(entry.processingStart, group.processingStart); - group.processingEnd = Math.max(entry.processingEnd, group.processingEnd); - group.entries.push(entry); - break; - } - } - // If there was no matching group, assume this is a new frame. - if (!group) { - group = { - startTime: entry.startTime, - processingStart: entry.processingStart, - processingEnd: entry.processingEnd, - renderTime, - entries: [entry], - }; - pendingEntriesGroups.push(group); - } - // Store the grouped render time for this entry for reference later. - if (entry.interactionId || entry.entryType === 'first-input') { - entryToEntriesGroupMap.set(entry, group); - } - queueCleanup(); -}; -const queueCleanup = () => { - // Queue cleanup of entries that are not part of any INP candidates. - if (idleHandle < 0) { - idleHandle = whenIdle(cleanupEntries); - } -}; -const cleanupEntries = () => { - // Delete any stored interaction target elements if they're not part of one - // of the 10 longest interactions. - if (interactionTargetMap.size > 10) { - interactionTargetMap.forEach((_, key) => { - if (!longestInteractionMap.has(key)) { - interactionTargetMap.delete(key); - } - }); - } - // Keep all render times that are part of a pending INP candidate or - // that occurred within the 50 most recently-dispatched groups of events. - const longestInteractionGroups = longestInteractionList.map((i) => { - return entryToEntriesGroupMap.get(i.entries[0]); - }); - const minIndex = pendingEntriesGroups.length - MAX_PREVIOUS_FRAMES; - pendingEntriesGroups = pendingEntriesGroups.filter((group, index) => { - if (index >= minIndex) - return true; - return longestInteractionGroups.includes(group); - }); - // Keep all pending LoAF entries that either: - // 1) intersect with entries in the newly cleaned up `pendingEntriesGroups` - // 2) occur after the most recently-processed event entry (for up to MAX_PREVIOUS_FRAMES) - const loafsToKeep = new Set(); - for (let i = 0; i < pendingEntriesGroups.length; i++) { - const group = pendingEntriesGroups[i]; - getIntersectingLoAFs(group.startTime, group.processingEnd).forEach((loaf) => { - loafsToKeep.add(loaf); - }); - } - const prevFrameIndexCutoff = pendingLoAFs.length - 1 - MAX_PREVIOUS_FRAMES; - // Filter `pendingLoAFs` to preserve LoAF order. - pendingLoAFs = pendingLoAFs.filter((loaf, index) => { - if (loaf.startTime > latestProcessingEnd && index > prevFrameIndexCutoff) { - return true; - } - return loafsToKeep.has(loaf); - }); - // Reset the idle callback handle so it can be queued again. - idleHandle = -1; -}; -entryPreProcessingCallbacks.push(saveInteractionTarget, groupEntriesByRenderTime); -const getIntersectingLoAFs = (start, end) => { - const intersectingLoAFs = []; - for (let i = 0, loaf; (loaf = pendingLoAFs[i]); i++) { - // If the LoAF ends before the given start time, ignore it. - if (loaf.startTime + loaf.duration < start) - continue; - // If the LoAF starts after the given end time, ignore it and all - // subsequent pending LoAFs (because they're in time order). - if (loaf.startTime > end) - break; - // Still here? If so this LoAF intersects with the interaction. - intersectingLoAFs.push(loaf); - } - return intersectingLoAFs; -}; -const attributeINP = (metric) => { - const firstEntry = metric.entries[0]; - const group = entryToEntriesGroupMap.get(firstEntry); - const processingStart = firstEntry.processingStart; - const processingEnd = group.processingEnd; - // Sort the entries in processing time order. - const processedEventEntries = group.entries.sort((a, b) => { - return a.processingStart - b.processingStart; - }); - const longAnimationFrameEntries = getIntersectingLoAFs(firstEntry.startTime, processingEnd); - // The first interaction entry may not have a target defined, so use the - // first one found in the entry list. - // TODO: when the following bug is fixed just use `firstInteractionEntry`. - // https://bugs.chromium.org/p/chromium/issues/detail?id=1367329 - // As a fallback, also check the interactionTargetMap (to account for - // cases where the element is removed from the DOM before reporting happens). - const firstEntryWithTarget = metric.entries.find((entry) => entry.target); - const interactionTargetElement = (firstEntryWithTarget && firstEntryWithTarget.target) || - interactionTargetMap.get(firstEntry.interactionId); - // Since entry durations are rounded to the nearest 8ms, we need to clamp - // the `nextPaintTime` value to be higher than the `processingEnd` or - // end time of any LoAF entry. - const nextPaintTimeCandidates = [ - firstEntry.startTime + firstEntry.duration, - processingEnd, - ].concat(longAnimationFrameEntries.map((loaf) => loaf.startTime + loaf.duration)); - const nextPaintTime = Math.max.apply(Math, nextPaintTimeCandidates); - const attribution = { - interactionTarget: getSelector(interactionTargetElement), - interactionTargetElement: interactionTargetElement, - interactionType: firstEntry.name.startsWith('key') ? 'keyboard' : 'pointer', - interactionTime: firstEntry.startTime, - nextPaintTime: nextPaintTime, - processedEventEntries: processedEventEntries, - longAnimationFrameEntries: longAnimationFrameEntries, - inputDelay: processingStart - firstEntry.startTime, - processingDuration: processingEnd - processingStart, - presentationDelay: Math.max(nextPaintTime - processingEnd, 0), - loadState: getLoadState(firstEntry.startTime), - }; - // Use Object.assign to set property to keep tsc happy. - const metricWithAttribution = Object.assign(metric, { attribution }); - return metricWithAttribution; -}; -/** - * Calculates the [INP](https://web.dev/articles/inp) value for the current - * page and calls the `callback` function once the value is ready, along with - * the `event` performance entries reported for that interaction. The reported - * value is a `DOMHighResTimeStamp`. - * - * A custom `durationThreshold` configuration option can optionally be passed to - * control what `event-timing` entries are considered for INP reporting. The - * default threshold is `40`, which means INP scores of less than 40 are - * reported as 0. Note that this will not affect your 75th percentile INP value - * unless that value is also less than 40 (well below the recommended - * [good](https://web.dev/articles/inp#what_is_a_good_inp_score) threshold). - * - * If the `reportAllChanges` configuration option is set to `true`, the - * `callback` function will be called as soon as the value is initially - * determined as well as any time the value changes throughout the page - * lifespan. - * - * _**Important:** INP should be continually monitored for changes throughout - * the entire lifespan of a page—including if the user returns to the page after - * it's been hidden/backgrounded. However, since browsers often [will not fire - * additional callbacks once the user has backgrounded a - * page](https://developer.chrome.com/blog/page-lifecycle-api/#advice-hidden), - * `callback` is always called when the page's visibility state changes to - * hidden. As a result, the `callback` function might be called multiple times - * during the same page load._ - */ -export const onINP = (onReport, opts) => { - if (!loafObserver) { - loafObserver = observe('long-animation-frame', handleLoAFEntries); - } - unattributedOnINP((metric) => { - const metricWithAttribution = attributeINP(metric); - onReport(metricWithAttribution); - }, opts); -}; diff --git a/frontend-old/node_modules/web-vitals/dist/modules/attribution/onLCP.d.ts b/frontend-old/node_modules/web-vitals/dist/modules/attribution/onLCP.d.ts deleted file mode 100644 index caa6ea7..0000000 --- a/frontend-old/node_modules/web-vitals/dist/modules/attribution/onLCP.d.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { LCPMetricWithAttribution, ReportOpts } from '../types.js'; -/** - * Calculates the [LCP](https://web.dev/articles/lcp) value for the current page and - * calls the `callback` function once the value is ready (along with the - * relevant `largest-contentful-paint` performance entry used to determine the - * value). The reported value is a `DOMHighResTimeStamp`. - * - * If the `reportAllChanges` configuration option is set to `true`, the - * `callback` function will be called any time a new `largest-contentful-paint` - * performance entry is dispatched, or once the final value of the metric has - * been determined. - */ -export declare const onLCP: (onReport: (metric: LCPMetricWithAttribution) => void, opts?: ReportOpts) => void; diff --git a/frontend-old/node_modules/web-vitals/dist/modules/attribution/onLCP.js b/frontend-old/node_modules/web-vitals/dist/modules/attribution/onLCP.js deleted file mode 100644 index 269323c..0000000 --- a/frontend-old/node_modules/web-vitals/dist/modules/attribution/onLCP.js +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright 2022 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import { getNavigationEntry } from '../lib/getNavigationEntry.js'; -import { getSelector } from '../lib/getSelector.js'; -import { onLCP as unattributedOnLCP } from '../onLCP.js'; -const attributeLCP = (metric) => { - // Use a default object if no other attribution has been set. - let attribution = { - timeToFirstByte: 0, - resourceLoadDelay: 0, - resourceLoadDuration: 0, - elementRenderDelay: metric.value, - }; - if (metric.entries.length) { - const navigationEntry = getNavigationEntry(); - if (navigationEntry) { - const activationStart = navigationEntry.activationStart || 0; - const lcpEntry = metric.entries[metric.entries.length - 1]; - const lcpResourceEntry = lcpEntry.url && - performance - .getEntriesByType('resource') - .filter((e) => e.name === lcpEntry.url)[0]; - const ttfb = Math.max(0, navigationEntry.responseStart - activationStart); - const lcpRequestStart = Math.max(ttfb, - // Prefer `requestStart` (if TOA is set), otherwise use `startTime`. - lcpResourceEntry - ? (lcpResourceEntry.requestStart || lcpResourceEntry.startTime) - - activationStart - : 0); - const lcpResponseEnd = Math.max(lcpRequestStart, lcpResourceEntry ? lcpResourceEntry.responseEnd - activationStart : 0); - const lcpRenderTime = Math.max(lcpResponseEnd, lcpEntry.startTime - activationStart); - attribution = { - element: getSelector(lcpEntry.element), - timeToFirstByte: ttfb, - resourceLoadDelay: lcpRequestStart - ttfb, - resourceLoadDuration: lcpResponseEnd - lcpRequestStart, - elementRenderDelay: lcpRenderTime - lcpResponseEnd, - navigationEntry, - lcpEntry, - }; - // Only attribution the URL and resource entry if they exist. - if (lcpEntry.url) { - attribution.url = lcpEntry.url; - } - if (lcpResourceEntry) { - attribution.lcpResourceEntry = lcpResourceEntry; - } - } - } - // Use Object.assign to set property to keep tsc happy. - const metricWithAttribution = Object.assign(metric, { attribution }); - return metricWithAttribution; -}; -/** - * Calculates the [LCP](https://web.dev/articles/lcp) value for the current page and - * calls the `callback` function once the value is ready (along with the - * relevant `largest-contentful-paint` performance entry used to determine the - * value). The reported value is a `DOMHighResTimeStamp`. - * - * If the `reportAllChanges` configuration option is set to `true`, the - * `callback` function will be called any time a new `largest-contentful-paint` - * performance entry is dispatched, or once the final value of the metric has - * been determined. - */ -export const onLCP = (onReport, opts) => { - unattributedOnLCP((metric) => { - const metricWithAttribution = attributeLCP(metric); - onReport(metricWithAttribution); - }, opts); -}; diff --git a/frontend-old/node_modules/web-vitals/dist/modules/attribution/onTTFB.d.ts b/frontend-old/node_modules/web-vitals/dist/modules/attribution/onTTFB.d.ts deleted file mode 100644 index a39d0ad..0000000 --- a/frontend-old/node_modules/web-vitals/dist/modules/attribution/onTTFB.d.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { TTFBMetricWithAttribution, ReportOpts } from '../types.js'; -/** - * Calculates the [TTFB](https://web.dev/articles/ttfb) value for the - * current page and calls the `callback` function once the page has loaded, - * along with the relevant `navigation` performance entry used to determine the - * value. The reported value is a `DOMHighResTimeStamp`. - * - * Note, this function waits until after the page is loaded to call `callback` - * in order to ensure all properties of the `navigation` entry are populated. - * This is useful if you want to report on other metrics exposed by the - * [Navigation Timing API](https://w3c.github.io/navigation-timing/). For - * example, the TTFB metric starts from the page's [time - * origin](https://www.w3.org/TR/hr-time-2/#sec-time-origin), which means it - * includes time spent on DNS lookup, connection negotiation, network latency, - * and server processing time. - */ -export declare const onTTFB: (onReport: (metric: TTFBMetricWithAttribution) => void, opts?: ReportOpts) => void; diff --git a/frontend-old/node_modules/web-vitals/dist/modules/attribution/onTTFB.js b/frontend-old/node_modules/web-vitals/dist/modules/attribution/onTTFB.js deleted file mode 100644 index cd0d6bb..0000000 --- a/frontend-old/node_modules/web-vitals/dist/modules/attribution/onTTFB.js +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright 2022 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import { onTTFB as unattributedOnTTFB } from '../onTTFB.js'; -const attributeTTFB = (metric) => { - // Use a default object if no other attribution has been set. - let attribution = { - waitingDuration: 0, - cacheDuration: 0, - dnsDuration: 0, - connectionDuration: 0, - requestDuration: 0, - }; - if (metric.entries.length) { - const navigationEntry = metric.entries[0]; - const activationStart = navigationEntry.activationStart || 0; - // Measure from workerStart or fetchStart so any service worker startup - // time is included in cacheDuration (which also includes other sw time - // anyway, that cannot be accurately split out cross-browser). - const waitEnd = Math.max((navigationEntry.workerStart || navigationEntry.fetchStart) - - activationStart, 0); - const dnsStart = Math.max(navigationEntry.domainLookupStart - activationStart, 0); - const connectStart = Math.max(navigationEntry.connectStart - activationStart, 0); - const connectEnd = Math.max(navigationEntry.connectEnd - activationStart, 0); - attribution = { - waitingDuration: waitEnd, - cacheDuration: dnsStart - waitEnd, - // dnsEnd usually equals connectStart but use connectStart over dnsEnd - // for dnsDuration in case there ever is a gap. - dnsDuration: connectStart - dnsStart, - connectionDuration: connectEnd - connectStart, - // There is often a gap between connectEnd and requestStart. Attribute - // that to requestDuration so connectionDuration remains 0 for - // service worker controlled requests were connectStart and connectEnd - // are the same. - requestDuration: metric.value - connectEnd, - navigationEntry: navigationEntry, - }; - } - // Use Object.assign to set property to keep tsc happy. - const metricWithAttribution = Object.assign(metric, { attribution }); - return metricWithAttribution; -}; -/** - * Calculates the [TTFB](https://web.dev/articles/ttfb) value for the - * current page and calls the `callback` function once the page has loaded, - * along with the relevant `navigation` performance entry used to determine the - * value. The reported value is a `DOMHighResTimeStamp`. - * - * Note, this function waits until after the page is loaded to call `callback` - * in order to ensure all properties of the `navigation` entry are populated. - * This is useful if you want to report on other metrics exposed by the - * [Navigation Timing API](https://w3c.github.io/navigation-timing/). For - * example, the TTFB metric starts from the page's [time - * origin](https://www.w3.org/TR/hr-time-2/#sec-time-origin), which means it - * includes time spent on DNS lookup, connection negotiation, network latency, - * and server processing time. - */ -export const onTTFB = (onReport, opts) => { - unattributedOnTTFB((metric) => { - const metricWithAttribution = attributeTTFB(metric); - onReport(metricWithAttribution); - }, opts); -}; diff --git a/frontend-old/node_modules/web-vitals/dist/modules/deprecated.d.ts b/frontend-old/node_modules/web-vitals/dist/modules/deprecated.d.ts deleted file mode 100644 index 84d77ae..0000000 --- a/frontend-old/node_modules/web-vitals/dist/modules/deprecated.d.ts +++ /dev/null @@ -1,5 +0,0 @@ -export { -/** - * @deprecated Use `onINP()` instead. - */ -onFID, FIDThresholds, } from './onFID.js'; diff --git a/frontend-old/node_modules/web-vitals/dist/modules/deprecated.js b/frontend-old/node_modules/web-vitals/dist/modules/deprecated.js deleted file mode 100644 index 42756b9..0000000 --- a/frontend-old/node_modules/web-vitals/dist/modules/deprecated.js +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright 2022 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -export { -/** - * @deprecated Use `onINP()` instead. - */ -onFID, FIDThresholds, } from './onFID.js'; diff --git a/frontend-old/node_modules/web-vitals/dist/modules/index.d.ts b/frontend-old/node_modules/web-vitals/dist/modules/index.d.ts deleted file mode 100644 index dfd2263..0000000 --- a/frontend-old/node_modules/web-vitals/dist/modules/index.d.ts +++ /dev/null @@ -1,7 +0,0 @@ -export { onCLS, CLSThresholds } from './onCLS.js'; -export { onFCP, FCPThresholds } from './onFCP.js'; -export { onINP, INPThresholds } from './onINP.js'; -export { onLCP, LCPThresholds } from './onLCP.js'; -export { onTTFB, TTFBThresholds } from './onTTFB.js'; -export * from './deprecated.js'; -export * from './types.js'; diff --git a/frontend-old/node_modules/web-vitals/dist/modules/index.js b/frontend-old/node_modules/web-vitals/dist/modules/index.js deleted file mode 100644 index d374950..0000000 --- a/frontend-old/node_modules/web-vitals/dist/modules/index.js +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright 2020 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -export { onCLS, CLSThresholds } from './onCLS.js'; -export { onFCP, FCPThresholds } from './onFCP.js'; -export { onINP, INPThresholds } from './onINP.js'; -export { onLCP, LCPThresholds } from './onLCP.js'; -export { onTTFB, TTFBThresholds } from './onTTFB.js'; -export * from './deprecated.js'; -export * from './types.js'; diff --git a/frontend-old/node_modules/web-vitals/dist/modules/lib/bfcache.d.ts b/frontend-old/node_modules/web-vitals/dist/modules/lib/bfcache.d.ts deleted file mode 100644 index 0870fd0..0000000 --- a/frontend-old/node_modules/web-vitals/dist/modules/lib/bfcache.d.ts +++ /dev/null @@ -1,6 +0,0 @@ -interface onBFCacheRestoreCallback { - (event: PageTransitionEvent): void; -} -export declare const getBFCacheRestoreTime: () => number; -export declare const onBFCacheRestore: (cb: onBFCacheRestoreCallback) => void; -export {}; diff --git a/frontend-old/node_modules/web-vitals/dist/modules/lib/bfcache.js b/frontend-old/node_modules/web-vitals/dist/modules/lib/bfcache.js deleted file mode 100644 index 48050e3..0000000 --- a/frontend-old/node_modules/web-vitals/dist/modules/lib/bfcache.js +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright 2020 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -let bfcacheRestoreTime = -1; -export const getBFCacheRestoreTime = () => bfcacheRestoreTime; -export const onBFCacheRestore = (cb) => { - addEventListener('pageshow', (event) => { - if (event.persisted) { - bfcacheRestoreTime = event.timeStamp; - cb(event); - } - }, true); -}; diff --git a/frontend-old/node_modules/web-vitals/dist/modules/lib/bindReporter.d.ts b/frontend-old/node_modules/web-vitals/dist/modules/lib/bindReporter.d.ts deleted file mode 100644 index 54880d6..0000000 --- a/frontend-old/node_modules/web-vitals/dist/modules/lib/bindReporter.d.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { MetricType, MetricRatingThresholds } from '../types.js'; -export declare const bindReporter: <MetricName extends "CLS" | "FCP" | "FID" | "INP" | "LCP" | "TTFB">(callback: (metric: Extract<import("../types.js").CLSMetric, { - name: MetricName; -}> | Extract<import("../types.js").FCPMetric, { - name: MetricName; -}> | Extract<import("../types.js").FIDMetric, { - name: MetricName; -}> | Extract<import("../types.js").INPMetric, { - name: MetricName; -}> | Extract<import("../types.js").LCPMetric, { - name: MetricName; -}> | Extract<import("../types.js").TTFBMetric, { - name: MetricName; -}>) => void, metric: Extract<import("../types.js").CLSMetric, { - name: MetricName; -}> | Extract<import("../types.js").FCPMetric, { - name: MetricName; -}> | Extract<import("../types.js").FIDMetric, { - name: MetricName; -}> | Extract<import("../types.js").INPMetric, { - name: MetricName; -}> | Extract<import("../types.js").LCPMetric, { - name: MetricName; -}> | Extract<import("../types.js").TTFBMetric, { - name: MetricName; -}>, thresholds: MetricRatingThresholds, reportAllChanges?: boolean) => (forceReport?: boolean) => void; diff --git a/frontend-old/node_modules/web-vitals/dist/modules/lib/bindReporter.js b/frontend-old/node_modules/web-vitals/dist/modules/lib/bindReporter.js deleted file mode 100644 index e1afbbc..0000000 --- a/frontend-old/node_modules/web-vitals/dist/modules/lib/bindReporter.js +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2020 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -const getRating = (value, thresholds) => { - if (value > thresholds[1]) { - return 'poor'; - } - if (value > thresholds[0]) { - return 'needs-improvement'; - } - return 'good'; -}; -export const bindReporter = (callback, metric, thresholds, reportAllChanges) => { - let prevValue; - let delta; - return (forceReport) => { - if (metric.value >= 0) { - if (forceReport || reportAllChanges) { - delta = metric.value - (prevValue || 0); - // Report the metric if there's a non-zero delta or if no previous - // value exists (which can happen in the case of the document becoming - // hidden when the metric value is 0). - // See: https://github.com/GoogleChrome/web-vitals/issues/14 - if (delta || prevValue === undefined) { - prevValue = metric.value; - metric.delta = delta; - metric.rating = getRating(metric.value, thresholds); - callback(metric); - } - } - } - }; -}; diff --git a/frontend-old/node_modules/web-vitals/dist/modules/lib/doubleRAF.d.ts b/frontend-old/node_modules/web-vitals/dist/modules/lib/doubleRAF.d.ts deleted file mode 100644 index 7ac0933..0000000 --- a/frontend-old/node_modules/web-vitals/dist/modules/lib/doubleRAF.d.ts +++ /dev/null @@ -1 +0,0 @@ -export declare const doubleRAF: (cb: () => unknown) => void; diff --git a/frontend-old/node_modules/web-vitals/dist/modules/lib/doubleRAF.js b/frontend-old/node_modules/web-vitals/dist/modules/lib/doubleRAF.js deleted file mode 100644 index 16da945..0000000 --- a/frontend-old/node_modules/web-vitals/dist/modules/lib/doubleRAF.js +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright 2022 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -export const doubleRAF = (cb) => { - requestAnimationFrame(() => requestAnimationFrame(() => cb())); -}; diff --git a/frontend-old/node_modules/web-vitals/dist/modules/lib/generateUniqueID.d.ts b/frontend-old/node_modules/web-vitals/dist/modules/lib/generateUniqueID.d.ts deleted file mode 100644 index a049ad9..0000000 --- a/frontend-old/node_modules/web-vitals/dist/modules/lib/generateUniqueID.d.ts +++ /dev/null @@ -1,6 +0,0 @@ -/** - * Performantly generate a unique, 30-char string by combining a version - * number, the current timestamp with a 13-digit number integer. - * @return {string} - */ -export declare const generateUniqueID: () => string; diff --git a/frontend-old/node_modules/web-vitals/dist/modules/lib/generateUniqueID.js b/frontend-old/node_modules/web-vitals/dist/modules/lib/generateUniqueID.js deleted file mode 100644 index 5fabcc6..0000000 --- a/frontend-old/node_modules/web-vitals/dist/modules/lib/generateUniqueID.js +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright 2020 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/** - * Performantly generate a unique, 30-char string by combining a version - * number, the current timestamp with a 13-digit number integer. - * @return {string} - */ -export const generateUniqueID = () => { - return `v4-${Date.now()}-${Math.floor(Math.random() * (9e12 - 1)) + 1e12}`; -}; diff --git a/frontend-old/node_modules/web-vitals/dist/modules/lib/getActivationStart.d.ts b/frontend-old/node_modules/web-vitals/dist/modules/lib/getActivationStart.d.ts deleted file mode 100644 index b9f424e..0000000 --- a/frontend-old/node_modules/web-vitals/dist/modules/lib/getActivationStart.d.ts +++ /dev/null @@ -1 +0,0 @@ -export declare const getActivationStart: () => number; diff --git a/frontend-old/node_modules/web-vitals/dist/modules/lib/getActivationStart.js b/frontend-old/node_modules/web-vitals/dist/modules/lib/getActivationStart.js deleted file mode 100644 index 6bfcd5b..0000000 --- a/frontend-old/node_modules/web-vitals/dist/modules/lib/getActivationStart.js +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright 2022 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import { getNavigationEntry } from './getNavigationEntry.js'; -export const getActivationStart = () => { - const navEntry = getNavigationEntry(); - return (navEntry && navEntry.activationStart) || 0; -}; diff --git a/frontend-old/node_modules/web-vitals/dist/modules/lib/getLoadState.d.ts b/frontend-old/node_modules/web-vitals/dist/modules/lib/getLoadState.d.ts deleted file mode 100644 index a855155..0000000 --- a/frontend-old/node_modules/web-vitals/dist/modules/lib/getLoadState.d.ts +++ /dev/null @@ -1,2 +0,0 @@ -import { LoadState } from '../types.js'; -export declare const getLoadState: (timestamp: number) => LoadState; diff --git a/frontend-old/node_modules/web-vitals/dist/modules/lib/getLoadState.js b/frontend-old/node_modules/web-vitals/dist/modules/lib/getLoadState.js deleted file mode 100644 index cac5b57..0000000 --- a/frontend-old/node_modules/web-vitals/dist/modules/lib/getLoadState.js +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2022 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import { getNavigationEntry } from './getNavigationEntry.js'; -export const getLoadState = (timestamp) => { - if (document.readyState === 'loading') { - // If the `readyState` is 'loading' there's no need to look at timestamps - // since the timestamp has to be the current time or earlier. - return 'loading'; - } - else { - const navigationEntry = getNavigationEntry(); - if (navigationEntry) { - if (timestamp < navigationEntry.domInteractive) { - return 'loading'; - } - else if (navigationEntry.domContentLoadedEventStart === 0 || - timestamp < navigationEntry.domContentLoadedEventStart) { - // If the `domContentLoadedEventStart` timestamp has not yet been - // set, or if the given timestamp is less than that value. - return 'dom-interactive'; - } - else if (navigationEntry.domComplete === 0 || - timestamp < navigationEntry.domComplete) { - // If the `domComplete` timestamp has not yet been - // set, or if the given timestamp is less than that value. - return 'dom-content-loaded'; - } - } - } - // If any of the above fail, default to loaded. This could really only - // happy if the browser doesn't support the performance timeline, which - // most likely means this code would never run anyway. - return 'complete'; -}; diff --git a/frontend-old/node_modules/web-vitals/dist/modules/lib/getNavigationEntry.d.ts b/frontend-old/node_modules/web-vitals/dist/modules/lib/getNavigationEntry.d.ts deleted file mode 100644 index af6a02b..0000000 --- a/frontend-old/node_modules/web-vitals/dist/modules/lib/getNavigationEntry.d.ts +++ /dev/null @@ -1 +0,0 @@ -export declare const getNavigationEntry: () => PerformanceNavigationTiming | void; diff --git a/frontend-old/node_modules/web-vitals/dist/modules/lib/getNavigationEntry.js b/frontend-old/node_modules/web-vitals/dist/modules/lib/getNavigationEntry.js deleted file mode 100644 index 94ac68e..0000000 --- a/frontend-old/node_modules/web-vitals/dist/modules/lib/getNavigationEntry.js +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2022 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -export const getNavigationEntry = () => { - const navigationEntry = self.performance && - performance.getEntriesByType && - performance.getEntriesByType('navigation')[0]; - // Check to ensure the `responseStart` property is present and valid. - // In some cases no value is reported by the browser (for - // privacy/security reasons), and in other cases (bugs) the value is - // negative or is larger than the current page time. Ignore these cases: - // https://github.com/GoogleChrome/web-vitals/issues/137 - // https://github.com/GoogleChrome/web-vitals/issues/162 - // https://github.com/GoogleChrome/web-vitals/issues/275 - if (navigationEntry && - navigationEntry.responseStart > 0 && - navigationEntry.responseStart < performance.now()) { - return navigationEntry; - } -}; diff --git a/frontend-old/node_modules/web-vitals/dist/modules/lib/getSelector.d.ts b/frontend-old/node_modules/web-vitals/dist/modules/lib/getSelector.d.ts deleted file mode 100644 index 494212e..0000000 --- a/frontend-old/node_modules/web-vitals/dist/modules/lib/getSelector.d.ts +++ /dev/null @@ -1 +0,0 @@ -export declare const getSelector: (node: Node | null | undefined, maxLen?: number) => string; diff --git a/frontend-old/node_modules/web-vitals/dist/modules/lib/getSelector.js b/frontend-old/node_modules/web-vitals/dist/modules/lib/getSelector.js deleted file mode 100644 index 7b18244..0000000 --- a/frontend-old/node_modules/web-vitals/dist/modules/lib/getSelector.js +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2022 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -const getName = (node) => { - const name = node.nodeName; - return node.nodeType === 1 - ? name.toLowerCase() - : name.toUpperCase().replace(/^#/, ''); -}; -export const getSelector = (node, maxLen) => { - let sel = ''; - try { - while (node && node.nodeType !== 9) { - const el = node; - const part = el.id - ? '#' + el.id - : getName(el) + - (el.classList && - el.classList.value && - el.classList.value.trim() && - el.classList.value.trim().length - ? '.' + el.classList.value.trim().replace(/\s+/g, '.') - : ''); - if (sel.length + part.length > (maxLen || 100) - 1) - return sel || part; - sel = sel ? part + '>' + sel : part; - if (el.id) - break; - node = el.parentNode; - } - } - catch (err) { - // Do nothing... - } - return sel; -}; diff --git a/frontend-old/node_modules/web-vitals/dist/modules/lib/getVisibilityWatcher.d.ts b/frontend-old/node_modules/web-vitals/dist/modules/lib/getVisibilityWatcher.d.ts deleted file mode 100644 index 0832a05..0000000 --- a/frontend-old/node_modules/web-vitals/dist/modules/lib/getVisibilityWatcher.d.ts +++ /dev/null @@ -1,3 +0,0 @@ -export declare const getVisibilityWatcher: () => { - readonly firstHiddenTime: number; -}; diff --git a/frontend-old/node_modules/web-vitals/dist/modules/lib/getVisibilityWatcher.js b/frontend-old/node_modules/web-vitals/dist/modules/lib/getVisibilityWatcher.js deleted file mode 100644 index 4a052db..0000000 --- a/frontend-old/node_modules/web-vitals/dist/modules/lib/getVisibilityWatcher.js +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright 2020 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import { onBFCacheRestore } from './bfcache.js'; -let firstHiddenTime = -1; -const initHiddenTime = () => { - // If the document is hidden when this code runs, assume it was always - // hidden and the page was loaded in the background, with the one exception - // that visibility state is always 'hidden' during prerendering, so we have - // to ignore that case until prerendering finishes (see: `prerenderingchange` - // event logic below). - return document.visibilityState === 'hidden' && !document.prerendering - ? 0 - : Infinity; -}; -const onVisibilityUpdate = (event) => { - // If the document is 'hidden' and no previous hidden timestamp has been - // set, update it based on the current event data. - if (document.visibilityState === 'hidden' && firstHiddenTime > -1) { - // If the event is a 'visibilitychange' event, it means the page was - // visible prior to this change, so the event timestamp is the first - // hidden time. - // However, if the event is not a 'visibilitychange' event, then it must - // be a 'prerenderingchange' event, and the fact that the document is - // still 'hidden' from the above check means the tab was activated - // in a background state and so has always been hidden. - firstHiddenTime = event.type === 'visibilitychange' ? event.timeStamp : 0; - // Remove all listeners now that a `firstHiddenTime` value has been set. - removeChangeListeners(); - } -}; -const addChangeListeners = () => { - addEventListener('visibilitychange', onVisibilityUpdate, true); - // IMPORTANT: when a page is prerendering, its `visibilityState` is - // 'hidden', so in order to account for cases where this module checks for - // visibility during prerendering, an additional check after prerendering - // completes is also required. - addEventListener('prerenderingchange', onVisibilityUpdate, true); -}; -const removeChangeListeners = () => { - removeEventListener('visibilitychange', onVisibilityUpdate, true); - removeEventListener('prerenderingchange', onVisibilityUpdate, true); -}; -export const getVisibilityWatcher = () => { - if (firstHiddenTime < 0) { - // If the document is hidden when this code runs, assume it was hidden - // since navigation start. This isn't a perfect heuristic, but it's the - // best we can do until an API is available to support querying past - // visibilityState. - firstHiddenTime = initHiddenTime(); - addChangeListeners(); - // Reset the time on bfcache restores. - onBFCacheRestore(() => { - // Schedule a task in order to track the `visibilityState` once it's - // had an opportunity to change to visible in all browsers. - // https://bugs.chromium.org/p/chromium/issues/detail?id=1133363 - setTimeout(() => { - firstHiddenTime = initHiddenTime(); - addChangeListeners(); - }, 0); - }); - } - return { - get firstHiddenTime() { - return firstHiddenTime; - }, - }; -}; diff --git a/frontend-old/node_modules/web-vitals/dist/modules/lib/initMetric.d.ts b/frontend-old/node_modules/web-vitals/dist/modules/lib/initMetric.d.ts deleted file mode 100644 index b14f969..0000000 --- a/frontend-old/node_modules/web-vitals/dist/modules/lib/initMetric.d.ts +++ /dev/null @@ -1,21 +0,0 @@ -export declare const initMetric: <MetricName extends "CLS" | "FCP" | "FID" | "INP" | "LCP" | "TTFB">(name: MetricName, value?: number) => { - name: MetricName; - value: number; - rating: "good"; - delta: number; - entries: (Extract<import("../types.js").CLSMetric, { - name: MetricName; - }> | Extract<import("../types.js").FCPMetric, { - name: MetricName; - }> | Extract<import("../types.js").FIDMetric, { - name: MetricName; - }> | Extract<import("../types.js").INPMetric, { - name: MetricName; - }> | Extract<import("../types.js").LCPMetric, { - name: MetricName; - }> | Extract<import("../types.js").TTFBMetric, { - name: MetricName; - }>)["entries"]; - id: string; - navigationType: "navigate" | "reload" | "back-forward" | "back-forward-cache" | "prerender" | "restore"; -}; diff --git a/frontend-old/node_modules/web-vitals/dist/modules/lib/initMetric.js b/frontend-old/node_modules/web-vitals/dist/modules/lib/initMetric.js deleted file mode 100644 index 30da54e..0000000 --- a/frontend-old/node_modules/web-vitals/dist/modules/lib/initMetric.js +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2020 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import { getBFCacheRestoreTime } from './bfcache.js'; -import { generateUniqueID } from './generateUniqueID.js'; -import { getActivationStart } from './getActivationStart.js'; -import { getNavigationEntry } from './getNavigationEntry.js'; -export const initMetric = (name, value) => { - const navEntry = getNavigationEntry(); - let navigationType = 'navigate'; - if (getBFCacheRestoreTime() >= 0) { - navigationType = 'back-forward-cache'; - } - else if (navEntry) { - if (document.prerendering || getActivationStart() > 0) { - navigationType = 'prerender'; - } - else if (document.wasDiscarded) { - navigationType = 'restore'; - } - else if (navEntry.type) { - navigationType = navEntry.type.replace(/_/g, '-'); - } - } - // Use `entries` type specific for the metric. - const entries = []; - return { - name, - value: typeof value === 'undefined' ? -1 : value, - rating: 'good', // If needed, will be updated when reported. `const` to keep the type from widening to `string`. - delta: 0, - entries, - id: generateUniqueID(), - navigationType, - }; -}; diff --git a/frontend-old/node_modules/web-vitals/dist/modules/lib/interactions.d.ts b/frontend-old/node_modules/web-vitals/dist/modules/lib/interactions.d.ts deleted file mode 100644 index 5db2b71..0000000 --- a/frontend-old/node_modules/web-vitals/dist/modules/lib/interactions.d.ts +++ /dev/null @@ -1,31 +0,0 @@ -interface Interaction { - id: number; - latency: number; - entries: PerformanceEventTiming[]; -} -interface EntryPreProcessingHook { - (entry: PerformanceEventTiming): void; -} -export declare const longestInteractionList: Interaction[]; -export declare const longestInteractionMap: Map<number, Interaction>; -export declare const DEFAULT_DURATION_THRESHOLD = 40; -export declare const resetInteractions: () => void; -/** - * Returns the estimated p98 longest interaction based on the stored - * interaction candidates and the interaction count for the current page. - */ -export declare const estimateP98LongestInteraction: () => Interaction; -/** - * A list of callback functions to run before each entry is processed. - * Exposing this list allows the attribution build to hook into the - * entry processing pipeline. - */ -export declare const entryPreProcessingCallbacks: EntryPreProcessingHook[]; -/** - * Takes a performance entry and adds it to the list of worst interactions - * if its duration is long enough to make it among the worst. If the - * entry is part of an existing interaction, it is merged and the latency - * and entries list is updated as needed. - */ -export declare const processInteractionEntry: (entry: PerformanceEventTiming) => void; -export {}; diff --git a/frontend-old/node_modules/web-vitals/dist/modules/lib/interactions.js b/frontend-old/node_modules/web-vitals/dist/modules/lib/interactions.js deleted file mode 100644 index 0466ef1..0000000 --- a/frontend-old/node_modules/web-vitals/dist/modules/lib/interactions.js +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright 2024 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import { getInteractionCount } from './polyfills/interactionCountPolyfill.js'; -// A list of longest interactions on the page (by latency) sorted so the -// longest one is first. The list is at most MAX_INTERACTIONS_TO_CONSIDER long. -export const longestInteractionList = []; -// A mapping of longest interactions by their interaction ID. -// This is used for faster lookup. -export const longestInteractionMap = new Map(); -// The default `durationThreshold` used across this library for observing -// `event` entries via PerformanceObserver. -export const DEFAULT_DURATION_THRESHOLD = 40; -// Used to store the interaction count after a bfcache restore, since p98 -// interaction latencies should only consider the current navigation. -let prevInteractionCount = 0; -/** - * Returns the interaction count since the last bfcache restore (or for the - * full page lifecycle if there were no bfcache restores). - */ -const getInteractionCountForNavigation = () => { - return getInteractionCount() - prevInteractionCount; -}; -export const resetInteractions = () => { - prevInteractionCount = getInteractionCount(); - longestInteractionList.length = 0; - longestInteractionMap.clear(); -}; -/** - * Returns the estimated p98 longest interaction based on the stored - * interaction candidates and the interaction count for the current page. - */ -export const estimateP98LongestInteraction = () => { - const candidateInteractionIndex = Math.min(longestInteractionList.length - 1, Math.floor(getInteractionCountForNavigation() / 50)); - return longestInteractionList[candidateInteractionIndex]; -}; -// To prevent unnecessary memory usage on pages with lots of interactions, -// store at most 10 of the longest interactions to consider as INP candidates. -const MAX_INTERACTIONS_TO_CONSIDER = 10; -/** - * A list of callback functions to run before each entry is processed. - * Exposing this list allows the attribution build to hook into the - * entry processing pipeline. - */ -export const entryPreProcessingCallbacks = []; -/** - * Takes a performance entry and adds it to the list of worst interactions - * if its duration is long enough to make it among the worst. If the - * entry is part of an existing interaction, it is merged and the latency - * and entries list is updated as needed. - */ -export const processInteractionEntry = (entry) => { - entryPreProcessingCallbacks.forEach((cb) => cb(entry)); - // Skip further processing for entries that cannot be INP candidates. - if (!(entry.interactionId || entry.entryType === 'first-input')) - return; - // The least-long of the 10 longest interactions. - const minLongestInteraction = longestInteractionList[longestInteractionList.length - 1]; - const existingInteraction = longestInteractionMap.get(entry.interactionId); - // Only process the entry if it's possibly one of the ten longest, - // or if it's part of an existing interaction. - if (existingInteraction || - longestInteractionList.length < MAX_INTERACTIONS_TO_CONSIDER || - entry.duration > minLongestInteraction.latency) { - // If the interaction already exists, update it. Otherwise create one. - if (existingInteraction) { - // If the new entry has a longer duration, replace the old entries, - // otherwise add to the array. - if (entry.duration > existingInteraction.latency) { - existingInteraction.entries = [entry]; - existingInteraction.latency = entry.duration; - } - else if (entry.duration === existingInteraction.latency && - entry.startTime === existingInteraction.entries[0].startTime) { - existingInteraction.entries.push(entry); - } - } - else { - const interaction = { - id: entry.interactionId, - latency: entry.duration, - entries: [entry], - }; - longestInteractionMap.set(interaction.id, interaction); - longestInteractionList.push(interaction); - } - // Sort the entries by latency (descending) and keep only the top ten. - longestInteractionList.sort((a, b) => b.latency - a.latency); - if (longestInteractionList.length > MAX_INTERACTIONS_TO_CONSIDER) { - longestInteractionList - .splice(MAX_INTERACTIONS_TO_CONSIDER) - .forEach((i) => longestInteractionMap.delete(i.id)); - } - } -}; diff --git a/frontend-old/node_modules/web-vitals/dist/modules/lib/observe.d.ts b/frontend-old/node_modules/web-vitals/dist/modules/lib/observe.d.ts deleted file mode 100644 index 1c8ba5f..0000000 --- a/frontend-old/node_modules/web-vitals/dist/modules/lib/observe.d.ts +++ /dev/null @@ -1,20 +0,0 @@ -interface PerformanceEntryMap { - 'event': PerformanceEventTiming[]; - 'first-input': PerformanceEventTiming[]; - 'layout-shift': LayoutShift[]; - 'largest-contentful-paint': LargestContentfulPaint[]; - 'long-animation-frame': PerformanceLongAnimationFrameTiming[]; - 'paint': PerformancePaintTiming[]; - 'navigation': PerformanceNavigationTiming[]; - 'resource': PerformanceResourceTiming[]; -} -/** - * Takes a performance entry type and a callback function, and creates a - * `PerformanceObserver` instance that will observe the specified entry type - * with buffering enabled and call the callback _for each entry_. - * - * This function also feature-detects entry support and wraps the logic in a - * try/catch to avoid errors in unsupporting browsers. - */ -export declare const observe: <K extends keyof PerformanceEntryMap>(type: K, callback: (entries: PerformanceEntryMap[K]) => void, opts?: PerformanceObserverInit) => PerformanceObserver | undefined; -export {}; diff --git a/frontend-old/node_modules/web-vitals/dist/modules/lib/observe.js b/frontend-old/node_modules/web-vitals/dist/modules/lib/observe.js deleted file mode 100644 index 241971d..0000000 --- a/frontend-old/node_modules/web-vitals/dist/modules/lib/observe.js +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2020 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/** - * Takes a performance entry type and a callback function, and creates a - * `PerformanceObserver` instance that will observe the specified entry type - * with buffering enabled and call the callback _for each entry_. - * - * This function also feature-detects entry support and wraps the logic in a - * try/catch to avoid errors in unsupporting browsers. - */ -export const observe = (type, callback, opts) => { - try { - if (PerformanceObserver.supportedEntryTypes.includes(type)) { - const po = new PerformanceObserver((list) => { - // Delay by a microtask to workaround a bug in Safari where the - // callback is invoked immediately, rather than in a separate task. - // See: https://github.com/GoogleChrome/web-vitals/issues/277 - Promise.resolve().then(() => { - callback(list.getEntries()); - }); - }); - po.observe(Object.assign({ - type, - buffered: true, - }, opts || {})); - return po; - } - } - catch (e) { - // Do nothing. - } - return; -}; diff --git a/frontend-old/node_modules/web-vitals/dist/modules/lib/onHidden.d.ts b/frontend-old/node_modules/web-vitals/dist/modules/lib/onHidden.d.ts deleted file mode 100644 index 1e4d041..0000000 --- a/frontend-old/node_modules/web-vitals/dist/modules/lib/onHidden.d.ts +++ /dev/null @@ -1 +0,0 @@ -export declare const onHidden: (cb: () => void) => void; diff --git a/frontend-old/node_modules/web-vitals/dist/modules/lib/onHidden.js b/frontend-old/node_modules/web-vitals/dist/modules/lib/onHidden.js deleted file mode 100644 index c78b585..0000000 --- a/frontend-old/node_modules/web-vitals/dist/modules/lib/onHidden.js +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright 2020 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -export const onHidden = (cb) => { - document.addEventListener('visibilitychange', () => { - if (document.visibilityState === 'hidden') { - cb(); - } - }); -}; diff --git a/frontend-old/node_modules/web-vitals/dist/modules/lib/polyfills/firstInputPolyfill.d.ts b/frontend-old/node_modules/web-vitals/dist/modules/lib/polyfills/firstInputPolyfill.d.ts deleted file mode 100644 index 86211bf..0000000 --- a/frontend-old/node_modules/web-vitals/dist/modules/lib/polyfills/firstInputPolyfill.d.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { FirstInputPolyfillCallback } from '../../types.js'; -/** - * Accepts a callback to be invoked once the first input delay and event - * are known. - */ -export declare const firstInputPolyfill: (onFirstInput: FirstInputPolyfillCallback) => void; -export declare const resetFirstInputPolyfill: () => void; diff --git a/frontend-old/node_modules/web-vitals/dist/modules/lib/polyfills/firstInputPolyfill.js b/frontend-old/node_modules/web-vitals/dist/modules/lib/polyfills/firstInputPolyfill.js deleted file mode 100644 index b3faa59..0000000 --- a/frontend-old/node_modules/web-vitals/dist/modules/lib/polyfills/firstInputPolyfill.js +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright 2020 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -let firstInputEvent; -let firstInputDelay; -let firstInputTimeStamp; -let callbacks; -const listenerOpts = { passive: true, capture: true }; -const startTimeStamp = new Date(); -/** - * Accepts a callback to be invoked once the first input delay and event - * are known. - */ -export const firstInputPolyfill = (onFirstInput) => { - callbacks.push(onFirstInput); - reportFirstInputDelayIfRecordedAndValid(); -}; -export const resetFirstInputPolyfill = () => { - callbacks = []; - firstInputDelay = -1; - firstInputEvent = null; - eachEventType(addEventListener); -}; -/** - * Records the first input delay and event, so subsequent events can be - * ignored. All added event listeners are then removed. - */ -const recordFirstInputDelay = (delay, event) => { - if (!firstInputEvent) { - firstInputEvent = event; - firstInputDelay = delay; - firstInputTimeStamp = new Date(); - eachEventType(removeEventListener); - reportFirstInputDelayIfRecordedAndValid(); - } -}; -/** - * Reports the first input delay and event (if they're recorded and valid) - * by running the array of callback functions. - */ -const reportFirstInputDelayIfRecordedAndValid = () => { - // In some cases the recorded delay is clearly wrong, e.g. it's negative - // or it's larger than the delta between now and initialization. - // - https://github.com/GoogleChromeLabs/first-input-delay/issues/4 - // - https://github.com/GoogleChromeLabs/first-input-delay/issues/6 - // - https://github.com/GoogleChromeLabs/first-input-delay/issues/7 - if (firstInputDelay >= 0 && - // @ts-ignore (subtracting two dates always returns a number) - firstInputDelay < firstInputTimeStamp - startTimeStamp) { - const entry = { - entryType: 'first-input', - name: firstInputEvent.type, - target: firstInputEvent.target, - cancelable: firstInputEvent.cancelable, - startTime: firstInputEvent.timeStamp, - processingStart: firstInputEvent.timeStamp + firstInputDelay, - }; - callbacks.forEach(function (callback) { - callback(entry); - }); - callbacks = []; - } -}; -/** - * Handles pointer down events, which are a special case. - * Pointer events can trigger main or compositor thread behavior. - * We differentiate these cases based on whether or not we see a - * 'pointercancel' event, which are fired when we scroll. If we're scrolling - * we don't need to report input delay since FID excludes scrolling and - * pinch/zooming. - */ -const onPointerDown = (delay, event) => { - /** - * Responds to 'pointerup' events and records a delay. If a pointer up event - * is the next event after a pointerdown event, then it's not a scroll or - * a pinch/zoom. - */ - const onPointerUp = () => { - recordFirstInputDelay(delay, event); - removePointerEventListeners(); - }; - /** - * Responds to 'pointercancel' events and removes pointer listeners. - * If a 'pointercancel' is the next event to fire after a pointerdown event, - * it means this is a scroll or pinch/zoom interaction. - */ - const onPointerCancel = () => { - removePointerEventListeners(); - }; - /** - * Removes added pointer event listeners. - */ - const removePointerEventListeners = () => { - removeEventListener('pointerup', onPointerUp, listenerOpts); - removeEventListener('pointercancel', onPointerCancel, listenerOpts); - }; - addEventListener('pointerup', onPointerUp, listenerOpts); - addEventListener('pointercancel', onPointerCancel, listenerOpts); -}; -/** - * Handles all input events and records the time between when the event - * was received by the operating system and when it's JavaScript listeners - * were able to run. - */ -const onInput = (event) => { - // Only count cancelable events, which should trigger behavior - // important to the user. - if (event.cancelable) { - // In some browsers `event.timeStamp` returns a `DOMTimeStamp` value - // (epoch time) instead of the newer `DOMHighResTimeStamp` - // (document-origin time). To check for that we assume any timestamp - // greater than 1 trillion is a `DOMTimeStamp`, and compare it using - // the `Date` object rather than `performance.now()`. - // - https://github.com/GoogleChromeLabs/first-input-delay/issues/4 - const isEpochTime = event.timeStamp > 1e12; - const now = isEpochTime ? new Date() : performance.now(); - // Input delay is the delta between when the system received the event - // (e.g. event.timeStamp) and when it could run the callback (e.g. `now`). - const delay = now - event.timeStamp; - if (event.type == 'pointerdown') { - onPointerDown(delay, event); - } - else { - recordFirstInputDelay(delay, event); - } - } -}; -/** - * Invokes the passed callback const for = each event type with t =>he - * `onInput` const and = `listenerOpts =>`. - */ -const eachEventType = (callback) => { - const eventTypes = ['mousedown', 'keydown', 'touchstart', 'pointerdown']; - eventTypes.forEach((type) => callback(type, onInput, listenerOpts)); -}; diff --git a/frontend-old/node_modules/web-vitals/dist/modules/lib/polyfills/getFirstHiddenTimePolyfill.d.ts b/frontend-old/node_modules/web-vitals/dist/modules/lib/polyfills/getFirstHiddenTimePolyfill.d.ts deleted file mode 100644 index a5dd33e..0000000 --- a/frontend-old/node_modules/web-vitals/dist/modules/lib/polyfills/getFirstHiddenTimePolyfill.d.ts +++ /dev/null @@ -1 +0,0 @@ -export declare const getFirstHiddenTime: () => number; diff --git a/frontend-old/node_modules/web-vitals/dist/modules/lib/polyfills/getFirstHiddenTimePolyfill.js b/frontend-old/node_modules/web-vitals/dist/modules/lib/polyfills/getFirstHiddenTimePolyfill.js deleted file mode 100644 index e1d41f3..0000000 --- a/frontend-old/node_modules/web-vitals/dist/modules/lib/polyfills/getFirstHiddenTimePolyfill.js +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright 2020 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -let firstHiddenTime = document.visibilityState === 'hidden' ? 0 : Infinity; -const onVisibilityChange = (event) => { - if (document.visibilityState === 'hidden') { - firstHiddenTime = event.timeStamp; - removeEventListener('visibilitychange', onVisibilityChange, true); - } -}; -// Note: do not add event listeners unconditionally (outside of polyfills). -addEventListener('visibilitychange', onVisibilityChange, true); -export const getFirstHiddenTime = () => firstHiddenTime; diff --git a/frontend-old/node_modules/web-vitals/dist/modules/lib/polyfills/interactionCountPolyfill.d.ts b/frontend-old/node_modules/web-vitals/dist/modules/lib/polyfills/interactionCountPolyfill.d.ts deleted file mode 100644 index 1ed1de3..0000000 --- a/frontend-old/node_modules/web-vitals/dist/modules/lib/polyfills/interactionCountPolyfill.d.ts +++ /dev/null @@ -1,14 +0,0 @@ -declare global { - interface Performance { - interactionCount: number; - } -} -/** - * Returns the `interactionCount` value using the native API (if available) - * or the polyfill estimate in this module. - */ -export declare const getInteractionCount: () => number; -/** - * Feature detects native support or initializes the polyfill if needed. - */ -export declare const initInteractionCountPolyfill: () => void; diff --git a/frontend-old/node_modules/web-vitals/dist/modules/lib/polyfills/interactionCountPolyfill.js b/frontend-old/node_modules/web-vitals/dist/modules/lib/polyfills/interactionCountPolyfill.js deleted file mode 100644 index f523101..0000000 --- a/frontend-old/node_modules/web-vitals/dist/modules/lib/polyfills/interactionCountPolyfill.js +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2022 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import { observe } from '../observe.js'; -let interactionCountEstimate = 0; -let minKnownInteractionId = Infinity; -let maxKnownInteractionId = 0; -const updateEstimate = (entries) => { - entries.forEach((e) => { - if (e.interactionId) { - minKnownInteractionId = Math.min(minKnownInteractionId, e.interactionId); - maxKnownInteractionId = Math.max(maxKnownInteractionId, e.interactionId); - interactionCountEstimate = maxKnownInteractionId - ? (maxKnownInteractionId - minKnownInteractionId) / 7 + 1 - : 0; - } - }); -}; -let po; -/** - * Returns the `interactionCount` value using the native API (if available) - * or the polyfill estimate in this module. - */ -export const getInteractionCount = () => { - return po ? interactionCountEstimate : performance.interactionCount || 0; -}; -/** - * Feature detects native support or initializes the polyfill if needed. - */ -export const initInteractionCountPolyfill = () => { - if ('interactionCount' in performance || po) - return; - po = observe('event', updateEstimate, { - type: 'event', - buffered: true, - durationThreshold: 0, - }); -}; diff --git a/frontend-old/node_modules/web-vitals/dist/modules/lib/runOnce.d.ts b/frontend-old/node_modules/web-vitals/dist/modules/lib/runOnce.d.ts deleted file mode 100644 index dbf917a..0000000 --- a/frontend-old/node_modules/web-vitals/dist/modules/lib/runOnce.d.ts +++ /dev/null @@ -1 +0,0 @@ -export declare const runOnce: (cb: () => void) => () => void; diff --git a/frontend-old/node_modules/web-vitals/dist/modules/lib/runOnce.js b/frontend-old/node_modules/web-vitals/dist/modules/lib/runOnce.js deleted file mode 100644 index ea00f53..0000000 --- a/frontend-old/node_modules/web-vitals/dist/modules/lib/runOnce.js +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright 2022 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -export const runOnce = (cb) => { - let called = false; - return () => { - if (!called) { - cb(); - called = true; - } - }; -}; diff --git a/frontend-old/node_modules/web-vitals/dist/modules/lib/whenActivated.d.ts b/frontend-old/node_modules/web-vitals/dist/modules/lib/whenActivated.d.ts deleted file mode 100644 index 76af10b..0000000 --- a/frontend-old/node_modules/web-vitals/dist/modules/lib/whenActivated.d.ts +++ /dev/null @@ -1 +0,0 @@ -export declare const whenActivated: (callback: () => void) => void; diff --git a/frontend-old/node_modules/web-vitals/dist/modules/lib/whenActivated.js b/frontend-old/node_modules/web-vitals/dist/modules/lib/whenActivated.js deleted file mode 100644 index c3d853f..0000000 --- a/frontend-old/node_modules/web-vitals/dist/modules/lib/whenActivated.js +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright 2022 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -export const whenActivated = (callback) => { - if (document.prerendering) { - addEventListener('prerenderingchange', () => callback(), true); - } - else { - callback(); - } -}; diff --git a/frontend-old/node_modules/web-vitals/dist/modules/lib/whenIdle.d.ts b/frontend-old/node_modules/web-vitals/dist/modules/lib/whenIdle.d.ts deleted file mode 100644 index b503b5a..0000000 --- a/frontend-old/node_modules/web-vitals/dist/modules/lib/whenIdle.d.ts +++ /dev/null @@ -1,5 +0,0 @@ -/** - * Runs the passed callback during the next idle period, or immediately - * if the browser's visibility state is (or becomes) hidden. - */ -export declare const whenIdle: (cb: () => void) => number; diff --git a/frontend-old/node_modules/web-vitals/dist/modules/lib/whenIdle.js b/frontend-old/node_modules/web-vitals/dist/modules/lib/whenIdle.js deleted file mode 100644 index bab00c6..0000000 --- a/frontend-old/node_modules/web-vitals/dist/modules/lib/whenIdle.js +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2024 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import { onHidden } from './onHidden.js'; -import { runOnce } from './runOnce.js'; -/** - * Runs the passed callback during the next idle period, or immediately - * if the browser's visibility state is (or becomes) hidden. - */ -export const whenIdle = (cb) => { - const rIC = self.requestIdleCallback || self.setTimeout; - let handle = -1; - cb = runOnce(cb); - // If the document is hidden, run the callback immediately, otherwise - // race an idle callback with the next `visibilitychange` event. - if (document.visibilityState === 'hidden') { - cb(); - } - else { - handle = rIC(cb); - onHidden(cb); - } - return handle; -}; diff --git a/frontend-old/node_modules/web-vitals/dist/modules/onCLS.d.ts b/frontend-old/node_modules/web-vitals/dist/modules/onCLS.d.ts deleted file mode 100644 index c4c56b6..0000000 --- a/frontend-old/node_modules/web-vitals/dist/modules/onCLS.d.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { CLSMetric, MetricRatingThresholds, ReportOpts } from './types.js'; -/** Thresholds for CLS. See https://web.dev/articles/cls#what_is_a_good_cls_score */ -export declare const CLSThresholds: MetricRatingThresholds; -/** - * Calculates the [CLS](https://web.dev/articles/cls) value for the current page and - * calls the `callback` function once the value is ready to be reported, along - * with all `layout-shift` performance entries that were used in the metric - * value calculation. The reported value is a `double` (corresponding to a - * [layout shift score](https://web.dev/articles/cls#layout_shift_score)). - * - * If the `reportAllChanges` configuration option is set to `true`, the - * `callback` function will be called as soon as the value is initially - * determined as well as any time the value changes throughout the page - * lifespan. - * - * _**Important:** CLS should be continually monitored for changes throughout - * the entire lifespan of a page—including if the user returns to the page after - * it's been hidden/backgrounded. However, since browsers often [will not fire - * additional callbacks once the user has backgrounded a - * page](https://developer.chrome.com/blog/page-lifecycle-api/#advice-hidden), - * `callback` is always called when the page's visibility state changes to - * hidden. As a result, the `callback` function might be called multiple times - * during the same page load._ - */ -export declare const onCLS: (onReport: (metric: CLSMetric) => void, opts?: ReportOpts) => void; diff --git a/frontend-old/node_modules/web-vitals/dist/modules/onCLS.js b/frontend-old/node_modules/web-vitals/dist/modules/onCLS.js deleted file mode 100644 index 7c75a10..0000000 --- a/frontend-old/node_modules/web-vitals/dist/modules/onCLS.js +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright 2020 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import { onBFCacheRestore } from './lib/bfcache.js'; -import { initMetric } from './lib/initMetric.js'; -import { observe } from './lib/observe.js'; -import { bindReporter } from './lib/bindReporter.js'; -import { doubleRAF } from './lib/doubleRAF.js'; -import { onHidden } from './lib/onHidden.js'; -import { runOnce } from './lib/runOnce.js'; -import { onFCP } from './onFCP.js'; -/** Thresholds for CLS. See https://web.dev/articles/cls#what_is_a_good_cls_score */ -export const CLSThresholds = [0.1, 0.25]; -/** - * Calculates the [CLS](https://web.dev/articles/cls) value for the current page and - * calls the `callback` function once the value is ready to be reported, along - * with all `layout-shift` performance entries that were used in the metric - * value calculation. The reported value is a `double` (corresponding to a - * [layout shift score](https://web.dev/articles/cls#layout_shift_score)). - * - * If the `reportAllChanges` configuration option is set to `true`, the - * `callback` function will be called as soon as the value is initially - * determined as well as any time the value changes throughout the page - * lifespan. - * - * _**Important:** CLS should be continually monitored for changes throughout - * the entire lifespan of a page—including if the user returns to the page after - * it's been hidden/backgrounded. However, since browsers often [will not fire - * additional callbacks once the user has backgrounded a - * page](https://developer.chrome.com/blog/page-lifecycle-api/#advice-hidden), - * `callback` is always called when the page's visibility state changes to - * hidden. As a result, the `callback` function might be called multiple times - * during the same page load._ - */ -export const onCLS = (onReport, opts) => { - // Set defaults - opts = opts || {}; - // Start monitoring FCP so we can only report CLS if FCP is also reported. - // Note: this is done to match the current behavior of CrUX. - onFCP(runOnce(() => { - let metric = initMetric('CLS', 0); - let report; - let sessionValue = 0; - let sessionEntries = []; - const handleEntries = (entries) => { - entries.forEach((entry) => { - // Only count layout shifts without recent user input. - if (!entry.hadRecentInput) { - const firstSessionEntry = sessionEntries[0]; - const lastSessionEntry = sessionEntries[sessionEntries.length - 1]; - // If the entry occurred less than 1 second after the previous entry - // and less than 5 seconds after the first entry in the session, - // include the entry in the current session. Otherwise, start a new - // session. - if (sessionValue && - entry.startTime - lastSessionEntry.startTime < 1000 && - entry.startTime - firstSessionEntry.startTime < 5000) { - sessionValue += entry.value; - sessionEntries.push(entry); - } - else { - sessionValue = entry.value; - sessionEntries = [entry]; - } - } - }); - // If the current session value is larger than the current CLS value, - // update CLS and the entries contributing to it. - if (sessionValue > metric.value) { - metric.value = sessionValue; - metric.entries = sessionEntries; - report(); - } - }; - const po = observe('layout-shift', handleEntries); - if (po) { - report = bindReporter(onReport, metric, CLSThresholds, opts.reportAllChanges); - onHidden(() => { - handleEntries(po.takeRecords()); - report(true); - }); - // Only report after a bfcache restore if the `PerformanceObserver` - // successfully registered. - onBFCacheRestore(() => { - sessionValue = 0; - metric = initMetric('CLS', 0); - report = bindReporter(onReport, metric, CLSThresholds, opts.reportAllChanges); - doubleRAF(() => report()); - }); - // Queue a task to report (if nothing else triggers a report first). - // This allows CLS to be reported as soon as FCP fires when - // `reportAllChanges` is true. - setTimeout(report, 0); - } - })); -}; diff --git a/frontend-old/node_modules/web-vitals/dist/modules/onFCP.d.ts b/frontend-old/node_modules/web-vitals/dist/modules/onFCP.d.ts deleted file mode 100644 index 77e4c00..0000000 --- a/frontend-old/node_modules/web-vitals/dist/modules/onFCP.d.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { FCPMetric, MetricRatingThresholds, ReportOpts } from './types.js'; -/** Thresholds for FCP. See https://web.dev/articles/fcp#what_is_a_good_fcp_score */ -export declare const FCPThresholds: MetricRatingThresholds; -/** - * Calculates the [FCP](https://web.dev/articles/fcp) value for the current page and - * calls the `callback` function once the value is ready, along with the - * relevant `paint` performance entry used to determine the value. The reported - * value is a `DOMHighResTimeStamp`. - */ -export declare const onFCP: (onReport: (metric: FCPMetric) => void, opts?: ReportOpts) => void; diff --git a/frontend-old/node_modules/web-vitals/dist/modules/onFCP.js b/frontend-old/node_modules/web-vitals/dist/modules/onFCP.js deleted file mode 100644 index f4350cf..0000000 --- a/frontend-old/node_modules/web-vitals/dist/modules/onFCP.js +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright 2020 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import { onBFCacheRestore } from './lib/bfcache.js'; -import { bindReporter } from './lib/bindReporter.js'; -import { doubleRAF } from './lib/doubleRAF.js'; -import { getActivationStart } from './lib/getActivationStart.js'; -import { getVisibilityWatcher } from './lib/getVisibilityWatcher.js'; -import { initMetric } from './lib/initMetric.js'; -import { observe } from './lib/observe.js'; -import { whenActivated } from './lib/whenActivated.js'; -/** Thresholds for FCP. See https://web.dev/articles/fcp#what_is_a_good_fcp_score */ -export const FCPThresholds = [1800, 3000]; -/** - * Calculates the [FCP](https://web.dev/articles/fcp) value for the current page and - * calls the `callback` function once the value is ready, along with the - * relevant `paint` performance entry used to determine the value. The reported - * value is a `DOMHighResTimeStamp`. - */ -export const onFCP = (onReport, opts) => { - // Set defaults - opts = opts || {}; - whenActivated(() => { - const visibilityWatcher = getVisibilityWatcher(); - let metric = initMetric('FCP'); - let report; - const handleEntries = (entries) => { - entries.forEach((entry) => { - if (entry.name === 'first-contentful-paint') { - po.disconnect(); - // Only report if the page wasn't hidden prior to the first paint. - if (entry.startTime < visibilityWatcher.firstHiddenTime) { - // The activationStart reference is used because FCP should be - // relative to page activation rather than navigation start if the - // page was prerendered. But in cases where `activationStart` occurs - // after the FCP, this time should be clamped at 0. - metric.value = Math.max(entry.startTime - getActivationStart(), 0); - metric.entries.push(entry); - report(true); - } - } - }); - }; - const po = observe('paint', handleEntries); - if (po) { - report = bindReporter(onReport, metric, FCPThresholds, opts.reportAllChanges); - // Only report after a bfcache restore if the `PerformanceObserver` - // successfully registered or the `paint` entry exists. - onBFCacheRestore((event) => { - metric = initMetric('FCP'); - report = bindReporter(onReport, metric, FCPThresholds, opts.reportAllChanges); - doubleRAF(() => { - metric.value = performance.now() - event.timeStamp; - report(true); - }); - }); - } - }); -}; diff --git a/frontend-old/node_modules/web-vitals/dist/modules/onFID.d.ts b/frontend-old/node_modules/web-vitals/dist/modules/onFID.d.ts deleted file mode 100644 index 12c24c2..0000000 --- a/frontend-old/node_modules/web-vitals/dist/modules/onFID.d.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { FIDMetric, MetricRatingThresholds, ReportOpts } from './types.js'; -/** Thresholds for FID. See https://web.dev/articles/fid#what_is_a_good_fid_score */ -export declare const FIDThresholds: MetricRatingThresholds; -/** - * Calculates the [FID](https://web.dev/articles/fid) value for the current page and - * calls the `callback` function once the value is ready, along with the - * relevant `first-input` performance entry used to determine the value. The - * reported value is a `DOMHighResTimeStamp`. - * - * _**Important:** since FID is only reported after the user interacts with the - * page, it's possible that it will not be reported for some page loads._ - */ -export declare const onFID: (onReport: (metric: FIDMetric) => void, opts?: ReportOpts) => void; diff --git a/frontend-old/node_modules/web-vitals/dist/modules/onFID.js b/frontend-old/node_modules/web-vitals/dist/modules/onFID.js deleted file mode 100644 index c656b58..0000000 --- a/frontend-old/node_modules/web-vitals/dist/modules/onFID.js +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright 2020 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import { onBFCacheRestore } from './lib/bfcache.js'; -import { bindReporter } from './lib/bindReporter.js'; -import { getVisibilityWatcher } from './lib/getVisibilityWatcher.js'; -import { initMetric } from './lib/initMetric.js'; -import { observe } from './lib/observe.js'; -import { onHidden } from './lib/onHidden.js'; -import { firstInputPolyfill, resetFirstInputPolyfill, } from './lib/polyfills/firstInputPolyfill.js'; -import { runOnce } from './lib/runOnce.js'; -import { whenActivated } from './lib/whenActivated.js'; -/** Thresholds for FID. See https://web.dev/articles/fid#what_is_a_good_fid_score */ -export const FIDThresholds = [100, 300]; -/** - * Calculates the [FID](https://web.dev/articles/fid) value for the current page and - * calls the `callback` function once the value is ready, along with the - * relevant `first-input` performance entry used to determine the value. The - * reported value is a `DOMHighResTimeStamp`. - * - * _**Important:** since FID is only reported after the user interacts with the - * page, it's possible that it will not be reported for some page loads._ - */ -export const onFID = (onReport, opts) => { - // Set defaults - opts = opts || {}; - whenActivated(() => { - const visibilityWatcher = getVisibilityWatcher(); - let metric = initMetric('FID'); - let report; - const handleEntry = (entry) => { - // Only report if the page wasn't hidden prior to the first input. - if (entry.startTime < visibilityWatcher.firstHiddenTime) { - metric.value = entry.processingStart - entry.startTime; - metric.entries.push(entry); - report(true); - } - }; - const handleEntries = (entries) => { - entries.forEach(handleEntry); - }; - const po = observe('first-input', handleEntries); - report = bindReporter(onReport, metric, FIDThresholds, opts.reportAllChanges); - if (po) { - onHidden(runOnce(() => { - handleEntries(po.takeRecords()); - po.disconnect(); - })); - onBFCacheRestore(() => { - metric = initMetric('FID'); - report = bindReporter(onReport, metric, FIDThresholds, opts.reportAllChanges); - // Browsers don't re-emit FID on bfcache restore so fake it until you make it - resetFirstInputPolyfill(); - firstInputPolyfill(handleEntry); - }); - } - }); -}; diff --git a/frontend-old/node_modules/web-vitals/dist/modules/onINP.d.ts b/frontend-old/node_modules/web-vitals/dist/modules/onINP.d.ts deleted file mode 100644 index 50c3e33..0000000 --- a/frontend-old/node_modules/web-vitals/dist/modules/onINP.d.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { INPMetric, MetricRatingThresholds, ReportOpts } from './types.js'; -/** Thresholds for INP. See https://web.dev/articles/inp#what_is_a_good_inp_score */ -export declare const INPThresholds: MetricRatingThresholds; -/** - * Calculates the [INP](https://web.dev/articles/inp) value for the current - * page and calls the `callback` function once the value is ready, along with - * the `event` performance entries reported for that interaction. The reported - * value is a `DOMHighResTimeStamp`. - * - * A custom `durationThreshold` configuration option can optionally be passed to - * control what `event-timing` entries are considered for INP reporting. The - * default threshold is `40`, which means INP scores of less than 40 are - * reported as 0. Note that this will not affect your 75th percentile INP value - * unless that value is also less than 40 (well below the recommended - * [good](https://web.dev/articles/inp#what_is_a_good_inp_score) threshold). - * - * If the `reportAllChanges` configuration option is set to `true`, the - * `callback` function will be called as soon as the value is initially - * determined as well as any time the value changes throughout the page - * lifespan. - * - * _**Important:** INP should be continually monitored for changes throughout - * the entire lifespan of a page—including if the user returns to the page after - * it's been hidden/backgrounded. However, since browsers often [will not fire - * additional callbacks once the user has backgrounded a - * page](https://developer.chrome.com/blog/page-lifecycle-api/#advice-hidden), - * `callback` is always called when the page's visibility state changes to - * hidden. As a result, the `callback` function might be called multiple times - * during the same page load._ - */ -export declare const onINP: (onReport: (metric: INPMetric) => void, opts?: ReportOpts) => void; diff --git a/frontend-old/node_modules/web-vitals/dist/modules/onINP.js b/frontend-old/node_modules/web-vitals/dist/modules/onINP.js deleted file mode 100644 index 25ce110..0000000 --- a/frontend-old/node_modules/web-vitals/dist/modules/onINP.js +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright 2022 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import { onBFCacheRestore } from './lib/bfcache.js'; -import { bindReporter } from './lib/bindReporter.js'; -import { initMetric } from './lib/initMetric.js'; -import { DEFAULT_DURATION_THRESHOLD, processInteractionEntry, estimateP98LongestInteraction, resetInteractions, } from './lib/interactions.js'; -import { observe } from './lib/observe.js'; -import { onHidden } from './lib/onHidden.js'; -import { initInteractionCountPolyfill } from './lib/polyfills/interactionCountPolyfill.js'; -import { whenActivated } from './lib/whenActivated.js'; -import { whenIdle } from './lib/whenIdle.js'; -/** Thresholds for INP. See https://web.dev/articles/inp#what_is_a_good_inp_score */ -export const INPThresholds = [200, 500]; -/** - * Calculates the [INP](https://web.dev/articles/inp) value for the current - * page and calls the `callback` function once the value is ready, along with - * the `event` performance entries reported for that interaction. The reported - * value is a `DOMHighResTimeStamp`. - * - * A custom `durationThreshold` configuration option can optionally be passed to - * control what `event-timing` entries are considered for INP reporting. The - * default threshold is `40`, which means INP scores of less than 40 are - * reported as 0. Note that this will not affect your 75th percentile INP value - * unless that value is also less than 40 (well below the recommended - * [good](https://web.dev/articles/inp#what_is_a_good_inp_score) threshold). - * - * If the `reportAllChanges` configuration option is set to `true`, the - * `callback` function will be called as soon as the value is initially - * determined as well as any time the value changes throughout the page - * lifespan. - * - * _**Important:** INP should be continually monitored for changes throughout - * the entire lifespan of a page—including if the user returns to the page after - * it's been hidden/backgrounded. However, since browsers often [will not fire - * additional callbacks once the user has backgrounded a - * page](https://developer.chrome.com/blog/page-lifecycle-api/#advice-hidden), - * `callback` is always called when the page's visibility state changes to - * hidden. As a result, the `callback` function might be called multiple times - * during the same page load._ - */ -export const onINP = (onReport, opts) => { - // Return if the browser doesn't support all APIs needed to measure INP. - if (!('PerformanceEventTiming' in self && - 'interactionId' in PerformanceEventTiming.prototype)) { - return; - } - // Set defaults - opts = opts || {}; - whenActivated(() => { - // TODO(philipwalton): remove once the polyfill is no longer needed. - initInteractionCountPolyfill(); - let metric = initMetric('INP'); - let report; - const handleEntries = (entries) => { - // Queue the `handleEntries()` callback in the next idle task. - // This is needed to increase the chances that all event entries that - // occurred between the user interaction and the next paint - // have been dispatched. Note: there is currently an experiment - // running in Chrome (EventTimingKeypressAndCompositionInteractionId) - // 123+ that if rolled out fully may make this no longer necessary. - whenIdle(() => { - entries.forEach(processInteractionEntry); - const inp = estimateP98LongestInteraction(); - if (inp && inp.latency !== metric.value) { - metric.value = inp.latency; - metric.entries = inp.entries; - report(); - } - }); - }; - const po = observe('event', handleEntries, { - // Event Timing entries have their durations rounded to the nearest 8ms, - // so a duration of 40ms would be any event that spans 2.5 or more frames - // at 60Hz. This threshold is chosen to strike a balance between usefulness - // and performance. Running this callback for any interaction that spans - // just one or two frames is likely not worth the insight that could be - // gained. - durationThreshold: opts.durationThreshold ?? DEFAULT_DURATION_THRESHOLD, - }); - report = bindReporter(onReport, metric, INPThresholds, opts.reportAllChanges); - if (po) { - // Also observe entries of type `first-input`. This is useful in cases - // where the first interaction is less than the `durationThreshold`. - po.observe({ type: 'first-input', buffered: true }); - onHidden(() => { - handleEntries(po.takeRecords()); - report(true); - }); - // Only report after a bfcache restore if the `PerformanceObserver` - // successfully registered. - onBFCacheRestore(() => { - resetInteractions(); - metric = initMetric('INP'); - report = bindReporter(onReport, metric, INPThresholds, opts.reportAllChanges); - }); - } - }); -}; diff --git a/frontend-old/node_modules/web-vitals/dist/modules/onLCP.d.ts b/frontend-old/node_modules/web-vitals/dist/modules/onLCP.d.ts deleted file mode 100644 index 44e391c..0000000 --- a/frontend-old/node_modules/web-vitals/dist/modules/onLCP.d.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { LCPMetric, MetricRatingThresholds, ReportOpts } from './types.js'; -/** Thresholds for LCP. See https://web.dev/articles/lcp#what_is_a_good_lcp_score */ -export declare const LCPThresholds: MetricRatingThresholds; -/** - * Calculates the [LCP](https://web.dev/articles/lcp) value for the current page and - * calls the `callback` function once the value is ready (along with the - * relevant `largest-contentful-paint` performance entry used to determine the - * value). The reported value is a `DOMHighResTimeStamp`. - * - * If the `reportAllChanges` configuration option is set to `true`, the - * `callback` function will be called any time a new `largest-contentful-paint` - * performance entry is dispatched, or once the final value of the metric has - * been determined. - */ -export declare const onLCP: (onReport: (metric: LCPMetric) => void, opts?: ReportOpts) => void; diff --git a/frontend-old/node_modules/web-vitals/dist/modules/onLCP.js b/frontend-old/node_modules/web-vitals/dist/modules/onLCP.js deleted file mode 100644 index 2f9d0f7..0000000 --- a/frontend-old/node_modules/web-vitals/dist/modules/onLCP.js +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright 2020 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import { onBFCacheRestore } from './lib/bfcache.js'; -import { bindReporter } from './lib/bindReporter.js'; -import { doubleRAF } from './lib/doubleRAF.js'; -import { getActivationStart } from './lib/getActivationStart.js'; -import { getVisibilityWatcher } from './lib/getVisibilityWatcher.js'; -import { initMetric } from './lib/initMetric.js'; -import { observe } from './lib/observe.js'; -import { onHidden } from './lib/onHidden.js'; -import { runOnce } from './lib/runOnce.js'; -import { whenActivated } from './lib/whenActivated.js'; -import { whenIdle } from './lib/whenIdle.js'; -/** Thresholds for LCP. See https://web.dev/articles/lcp#what_is_a_good_lcp_score */ -export const LCPThresholds = [2500, 4000]; -const reportedMetricIDs = {}; -/** - * Calculates the [LCP](https://web.dev/articles/lcp) value for the current page and - * calls the `callback` function once the value is ready (along with the - * relevant `largest-contentful-paint` performance entry used to determine the - * value). The reported value is a `DOMHighResTimeStamp`. - * - * If the `reportAllChanges` configuration option is set to `true`, the - * `callback` function will be called any time a new `largest-contentful-paint` - * performance entry is dispatched, or once the final value of the metric has - * been determined. - */ -export const onLCP = (onReport, opts) => { - // Set defaults - opts = opts || {}; - whenActivated(() => { - const visibilityWatcher = getVisibilityWatcher(); - let metric = initMetric('LCP'); - let report; - const handleEntries = (entries) => { - // If reportAllChanges is set then call this function for each entry, - // otherwise only consider the last one. - if (!opts.reportAllChanges) { - entries = entries.slice(-1); - } - entries.forEach((entry) => { - // Only report if the page wasn't hidden prior to LCP. - if (entry.startTime < visibilityWatcher.firstHiddenTime) { - // The startTime attribute returns the value of the renderTime if it is - // not 0, and the value of the loadTime otherwise. The activationStart - // reference is used because LCP should be relative to page activation - // rather than navigation start if the page was prerendered. But in cases - // where `activationStart` occurs after the LCP, this time should be - // clamped at 0. - metric.value = Math.max(entry.startTime - getActivationStart(), 0); - metric.entries = [entry]; - report(); - } - }); - }; - const po = observe('largest-contentful-paint', handleEntries); - if (po) { - report = bindReporter(onReport, metric, LCPThresholds, opts.reportAllChanges); - const stopListening = runOnce(() => { - if (!reportedMetricIDs[metric.id]) { - handleEntries(po.takeRecords()); - po.disconnect(); - reportedMetricIDs[metric.id] = true; - report(true); - } - }); - // Stop listening after input. Note: while scrolling is an input that - // stops LCP observation, it's unreliable since it can be programmatically - // generated. See: https://github.com/GoogleChrome/web-vitals/issues/75 - ['keydown', 'click'].forEach((type) => { - // Wrap in a setTimeout so the callback is run in a separate task - // to avoid extending the keyboard/click handler to reduce INP impact - // https://github.com/GoogleChrome/web-vitals/issues/383 - addEventListener(type, () => whenIdle(stopListening), { - once: true, - capture: true, - }); - }); - onHidden(stopListening); - // Only report after a bfcache restore if the `PerformanceObserver` - // successfully registered. - onBFCacheRestore((event) => { - metric = initMetric('LCP'); - report = bindReporter(onReport, metric, LCPThresholds, opts.reportAllChanges); - doubleRAF(() => { - metric.value = performance.now() - event.timeStamp; - reportedMetricIDs[metric.id] = true; - report(true); - }); - }); - } - }); -}; diff --git a/frontend-old/node_modules/web-vitals/dist/modules/onTTFB.d.ts b/frontend-old/node_modules/web-vitals/dist/modules/onTTFB.d.ts deleted file mode 100644 index 14d7e4f..0000000 --- a/frontend-old/node_modules/web-vitals/dist/modules/onTTFB.d.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { MetricRatingThresholds, ReportOpts, TTFBMetric } from './types.js'; -/** Thresholds for TTFB. See https://web.dev/articles/ttfb#what_is_a_good_ttfb_score */ -export declare const TTFBThresholds: MetricRatingThresholds; -/** - * Calculates the [TTFB](https://web.dev/articles/ttfb) value for the - * current page and calls the `callback` function once the page has loaded, - * along with the relevant `navigation` performance entry used to determine the - * value. The reported value is a `DOMHighResTimeStamp`. - * - * Note, this function waits until after the page is loaded to call `callback` - * in order to ensure all properties of the `navigation` entry are populated. - * This is useful if you want to report on other metrics exposed by the - * [Navigation Timing API](https://w3c.github.io/navigation-timing/). For - * example, the TTFB metric starts from the page's [time - * origin](https://www.w3.org/TR/hr-time-2/#sec-time-origin), which means it - * includes time spent on DNS lookup, connection negotiation, network latency, - * and server processing time. - */ -export declare const onTTFB: (onReport: (metric: TTFBMetric) => void, opts?: ReportOpts) => void; diff --git a/frontend-old/node_modules/web-vitals/dist/modules/onTTFB.js b/frontend-old/node_modules/web-vitals/dist/modules/onTTFB.js deleted file mode 100644 index 9d12af4..0000000 --- a/frontend-old/node_modules/web-vitals/dist/modules/onTTFB.js +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright 2020 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import { bindReporter } from './lib/bindReporter.js'; -import { initMetric } from './lib/initMetric.js'; -import { onBFCacheRestore } from './lib/bfcache.js'; -import { getNavigationEntry } from './lib/getNavigationEntry.js'; -import { getActivationStart } from './lib/getActivationStart.js'; -import { whenActivated } from './lib/whenActivated.js'; -/** Thresholds for TTFB. See https://web.dev/articles/ttfb#what_is_a_good_ttfb_score */ -export const TTFBThresholds = [800, 1800]; -/** - * Runs in the next task after the page is done loading and/or prerendering. - * @param callback - */ -const whenReady = (callback) => { - if (document.prerendering) { - whenActivated(() => whenReady(callback)); - } - else if (document.readyState !== 'complete') { - addEventListener('load', () => whenReady(callback), true); - } - else { - // Queue a task so the callback runs after `loadEventEnd`. - setTimeout(callback, 0); - } -}; -/** - * Calculates the [TTFB](https://web.dev/articles/ttfb) value for the - * current page and calls the `callback` function once the page has loaded, - * along with the relevant `navigation` performance entry used to determine the - * value. The reported value is a `DOMHighResTimeStamp`. - * - * Note, this function waits until after the page is loaded to call `callback` - * in order to ensure all properties of the `navigation` entry are populated. - * This is useful if you want to report on other metrics exposed by the - * [Navigation Timing API](https://w3c.github.io/navigation-timing/). For - * example, the TTFB metric starts from the page's [time - * origin](https://www.w3.org/TR/hr-time-2/#sec-time-origin), which means it - * includes time spent on DNS lookup, connection negotiation, network latency, - * and server processing time. - */ -export const onTTFB = (onReport, opts) => { - // Set defaults - opts = opts || {}; - let metric = initMetric('TTFB'); - let report = bindReporter(onReport, metric, TTFBThresholds, opts.reportAllChanges); - whenReady(() => { - const navigationEntry = getNavigationEntry(); - if (navigationEntry) { - // The activationStart reference is used because TTFB should be - // relative to page activation rather than navigation start if the - // page was prerendered. But in cases where `activationStart` occurs - // after the first byte is received, this time should be clamped at 0. - metric.value = Math.max(navigationEntry.responseStart - getActivationStart(), 0); - metric.entries = [navigationEntry]; - report(true); - // Only report TTFB after bfcache restores if a `navigation` entry - // was reported for the initial load. - onBFCacheRestore(() => { - metric = initMetric('TTFB', 0); - report = bindReporter(onReport, metric, TTFBThresholds, opts.reportAllChanges); - report(true); - }); - } - }); -}; diff --git a/frontend-old/node_modules/web-vitals/dist/modules/types.d.ts b/frontend-old/node_modules/web-vitals/dist/modules/types.d.ts deleted file mode 100644 index 080d366..0000000 --- a/frontend-old/node_modules/web-vitals/dist/modules/types.d.ts +++ /dev/null @@ -1,54 +0,0 @@ -export * from './types/base.js'; -export * from './types/polyfills.js'; -export * from './types/cls.js'; -export * from './types/fcp.js'; -export * from './types/fid.js'; -export * from './types/inp.js'; -export * from './types/lcp.js'; -export * from './types/ttfb.js'; -interface PerformanceEntryMap { - navigation: PerformanceNavigationTiming; - resource: PerformanceResourceTiming; - paint: PerformancePaintTiming; -} -declare global { - interface Document { - prerendering?: boolean; - wasDiscarded?: boolean; - } - interface Performance { - getEntriesByType<K extends keyof PerformanceEntryMap>(type: K): PerformanceEntryMap[K][]; - } - interface PerformanceObserverInit { - durationThreshold?: number; - } - interface PerformanceNavigationTiming { - activationStart?: number; - } - interface PerformanceEventTiming extends PerformanceEntry { - duration: DOMHighResTimeStamp; - interactionId: number; - } - interface LayoutShiftAttribution { - node?: Node; - previousRect: DOMRectReadOnly; - currentRect: DOMRectReadOnly; - } - interface LayoutShift extends PerformanceEntry { - value: number; - sources: LayoutShiftAttribution[]; - hadRecentInput: boolean; - } - interface LargestContentfulPaint extends PerformanceEntry { - readonly renderTime: DOMHighResTimeStamp; - readonly loadTime: DOMHighResTimeStamp; - readonly size: number; - readonly id: string; - readonly url: string; - readonly element: Element | null; - } - interface PerformanceLongAnimationFrameTiming extends PerformanceEntry { - renderStart: DOMHighResTimeStamp; - duration: DOMHighResTimeStamp; - } -} diff --git a/frontend-old/node_modules/web-vitals/dist/modules/types.js b/frontend-old/node_modules/web-vitals/dist/modules/types.js deleted file mode 100644 index 77da260..0000000 --- a/frontend-old/node_modules/web-vitals/dist/modules/types.js +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright 2020 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -export * from './types/base.js'; -export * from './types/polyfills.js'; -export * from './types/cls.js'; -export * from './types/fcp.js'; -export * from './types/fid.js'; -export * from './types/inp.js'; -export * from './types/lcp.js'; -export * from './types/ttfb.js'; diff --git a/frontend-old/node_modules/web-vitals/dist/modules/types/base.d.ts b/frontend-old/node_modules/web-vitals/dist/modules/types/base.d.ts deleted file mode 100644 index 944292b..0000000 --- a/frontend-old/node_modules/web-vitals/dist/modules/types/base.d.ts +++ /dev/null @@ -1,101 +0,0 @@ -import type { CLSMetric, CLSMetricWithAttribution } from './cls.js'; -import type { FCPMetric, FCPMetricWithAttribution } from './fcp.js'; -import type { FIDMetric, FIDMetricWithAttribution } from './fid.js'; -import type { INPMetric, INPMetricWithAttribution } from './inp.js'; -import type { LCPMetric, LCPMetricWithAttribution } from './lcp.js'; -import type { TTFBMetric, TTFBMetricWithAttribution } from './ttfb.js'; -export interface Metric { - /** - * The name of the metric (in acronym form). - */ - name: 'CLS' | 'FCP' | 'FID' | 'INP' | 'LCP' | 'TTFB'; - /** - * The current value of the metric. - */ - value: number; - /** - * The rating as to whether the metric value is within the "good", - * "needs improvement", or "poor" thresholds of the metric. - */ - rating: 'good' | 'needs-improvement' | 'poor'; - /** - * The delta between the current value and the last-reported value. - * On the first report, `delta` and `value` will always be the same. - */ - delta: number; - /** - * A unique ID representing this particular metric instance. This ID can - * be used by an analytics tool to dedupe multiple values sent for the same - * metric instance, or to group multiple deltas together and calculate a - * total. It can also be used to differentiate multiple different metric - * instances sent from the same page, which can happen if the page is - * restored from the back/forward cache (in that case new metrics object - * get created). - */ - id: string; - /** - * Any performance entries relevant to the metric value calculation. - * The array may also be empty if the metric value was not based on any - * entries (e.g. a CLS value of 0 given no layout shifts). - */ - entries: PerformanceEntry[]; - /** - * The type of navigation. - * - * This will be the value returned by the Navigation Timing API (or - * `undefined` if the browser doesn't support that API), with the following - * exceptions: - * - 'back-forward-cache': for pages that are restored from the bfcache. - * - 'back_forward' is renamed to 'back-forward' for consistency. - * - 'prerender': for pages that were prerendered. - * - 'restore': for pages that were discarded by the browser and then - * restored by the user. - */ - navigationType: 'navigate' | 'reload' | 'back-forward' | 'back-forward-cache' | 'prerender' | 'restore'; -} -/** The union of supported metric types. */ -export type MetricType = CLSMetric | FCPMetric | FIDMetric | INPMetric | LCPMetric | TTFBMetric; -/** The union of supported metric attribution types. */ -export type MetricWithAttribution = CLSMetricWithAttribution | FCPMetricWithAttribution | FIDMetricWithAttribution | INPMetricWithAttribution | LCPMetricWithAttribution | TTFBMetricWithAttribution; -/** - * The thresholds of metric's "good", "needs improvement", and "poor" ratings. - * - * - Metric values up to and including [0] are rated "good" - * - Metric values up to and including [1] are rated "needs improvement" - * - Metric values above [1] are "poor" - * - * | Metric value | Rating | - * | --------------- | ------------------- | - * | ≦ [0] | "good" | - * | > [0] and ≦ [1] | "needs improvement" | - * | > [1] | "poor" | - */ -export type MetricRatingThresholds = [number, number]; -/** - * @deprecated Use metric-specific function types instead, such as: - * `(metric: LCPMetric) => void`. If a single callback type is needed for - * multiple metrics, use `(metric: MetricType) => void`. - */ -export interface ReportCallback { - (metric: MetricType): void; -} -export interface ReportOpts { - reportAllChanges?: boolean; - durationThreshold?: number; -} -/** - * The loading state of the document. Note: this value is similar to - * `document.readyState` but it subdivides the "interactive" state into the - * time before and after the DOMContentLoaded event fires. - * - * State descriptions: - * - `loading`: the initial document response has not yet been fully downloaded - * and parsed. This is equivalent to the corresponding `readyState` value. - * - `dom-interactive`: the document has been fully loaded and parsed, but - * scripts may not have yet finished loading and executing. - * - `dom-content-loaded`: the document is fully loaded and parsed, and all - * scripts (except `async` scripts) have loaded and finished executing. - * - `complete`: the document and all of its sub-resources have finished - * loading. This is equivalent to the corresponding `readyState` value. - */ -export type LoadState = 'loading' | 'dom-interactive' | 'dom-content-loaded' | 'complete'; diff --git a/frontend-old/node_modules/web-vitals/dist/modules/types/base.js b/frontend-old/node_modules/web-vitals/dist/modules/types/base.js deleted file mode 100644 index e997715..0000000 --- a/frontend-old/node_modules/web-vitals/dist/modules/types/base.js +++ /dev/null @@ -1,16 +0,0 @@ -/* - * Copyright 2022 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -export {}; diff --git a/frontend-old/node_modules/web-vitals/dist/modules/types/cls.d.ts b/frontend-old/node_modules/web-vitals/dist/modules/types/cls.d.ts deleted file mode 100644 index f33cf17..0000000 --- a/frontend-old/node_modules/web-vitals/dist/modules/types/cls.d.ts +++ /dev/null @@ -1,55 +0,0 @@ -import type { LoadState, Metric } from './base.js'; -/** - * A CLS-specific version of the Metric object. - */ -export interface CLSMetric extends Metric { - name: 'CLS'; - entries: LayoutShift[]; -} -/** - * An object containing potentially-helpful debugging information that - * can be sent along with the CLS value for the current page visit in order - * to help identify issues happening to real-users in the field. - */ -export interface CLSAttribution { - /** - * A selector identifying the first element (in document order) that - * shifted when the single largest layout shift contributing to the page's - * CLS score occurred. - */ - largestShiftTarget?: string; - /** - * The time when the single largest layout shift contributing to the page's - * CLS score occurred. - */ - largestShiftTime?: DOMHighResTimeStamp; - /** - * The layout shift score of the single largest layout shift contributing to - * the page's CLS score. - */ - largestShiftValue?: number; - /** - * The `LayoutShiftEntry` representing the single largest layout shift - * contributing to the page's CLS score. (Useful when you need more than just - * `largestShiftTarget`, `largestShiftTime`, and `largestShiftValue`). - */ - largestShiftEntry?: LayoutShift; - /** - * The first element source (in document order) among the `sources` list - * of the `largestShiftEntry` object. (Also useful when you need more than - * just `largestShiftTarget`, `largestShiftTime`, and `largestShiftValue`). - */ - largestShiftSource?: LayoutShiftAttribution; - /** - * The loading state of the document at the time when the largest layout - * shift contribution to the page's CLS score occurred (see `LoadState` - * for details). - */ - loadState?: LoadState; -} -/** - * A CLS-specific version of the Metric object with attribution. - */ -export interface CLSMetricWithAttribution extends CLSMetric { - attribution: CLSAttribution; -} diff --git a/frontend-old/node_modules/web-vitals/dist/modules/types/cls.js b/frontend-old/node_modules/web-vitals/dist/modules/types/cls.js deleted file mode 100644 index e997715..0000000 --- a/frontend-old/node_modules/web-vitals/dist/modules/types/cls.js +++ /dev/null @@ -1,16 +0,0 @@ -/* - * Copyright 2022 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -export {}; diff --git a/frontend-old/node_modules/web-vitals/dist/modules/types/fcp.d.ts b/frontend-old/node_modules/web-vitals/dist/modules/types/fcp.d.ts deleted file mode 100644 index fa4a6e2..0000000 --- a/frontend-old/node_modules/web-vitals/dist/modules/types/fcp.d.ts +++ /dev/null @@ -1,46 +0,0 @@ -import type { LoadState, Metric } from './base.js'; -/** - * An FCP-specific version of the Metric object. - */ -export interface FCPMetric extends Metric { - name: 'FCP'; - entries: PerformancePaintTiming[]; -} -/** - * An object containing potentially-helpful debugging information that - * can be sent along with the FCP value for the current page visit in order - * to help identify issues happening to real-users in the field. - */ -export interface FCPAttribution { - /** - * The time from when the user initiates loading the page until when the - * browser receives the first byte of the response (a.k.a. TTFB). - */ - timeToFirstByte: number; - /** - * The delta between TTFB and the first contentful paint (FCP). - */ - firstByteToFCP: number; - /** - * The loading state of the document at the time when FCP `occurred (see - * `LoadState` for details). Ideally, documents can paint before they finish - * loading (e.g. the `loading` or `dom-interactive` phases). - */ - loadState: LoadState; - /** - * The `PerformancePaintTiming` entry corresponding to FCP. - */ - fcpEntry?: PerformancePaintTiming; - /** - * The `navigation` entry of the current page, which is useful for diagnosing - * general page load issues. This can be used to access `serverTiming` for example: - * navigationEntry?.serverTiming - */ - navigationEntry?: PerformanceNavigationTiming; -} -/** - * An FCP-specific version of the Metric object with attribution. - */ -export interface FCPMetricWithAttribution extends FCPMetric { - attribution: FCPAttribution; -} diff --git a/frontend-old/node_modules/web-vitals/dist/modules/types/fcp.js b/frontend-old/node_modules/web-vitals/dist/modules/types/fcp.js deleted file mode 100644 index e997715..0000000 --- a/frontend-old/node_modules/web-vitals/dist/modules/types/fcp.js +++ /dev/null @@ -1,16 +0,0 @@ -/* - * Copyright 2022 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -export {}; diff --git a/frontend-old/node_modules/web-vitals/dist/modules/types/fid.d.ts b/frontend-old/node_modules/web-vitals/dist/modules/types/fid.d.ts deleted file mode 100644 index 25c5bd7..0000000 --- a/frontend-old/node_modules/web-vitals/dist/modules/types/fid.d.ts +++ /dev/null @@ -1,46 +0,0 @@ -import type { LoadState, Metric } from './base.js'; -/** - * An FID-specific version of the Metric object. - */ -export interface FIDMetric extends Metric { - name: 'FID'; - entries: PerformanceEventTiming[]; -} -/** - * An object containing potentially-helpful debugging information that - * can be sent along with the FID value for the current page visit in order - * to help identify issues happening to real-users in the field. - */ -export interface FIDAttribution { - /** - * A selector identifying the element that the user interacted with. This - * element will be the `target` of the `event` dispatched. - */ - eventTarget: string; - /** - * The time when the user interacted. This time will match the `timeStamp` - * value of the `event` dispatched. - */ - eventTime: number; - /** - * The `type` of the `event` dispatched from the user interaction. - */ - eventType: string; - /** - * The `PerformanceEventTiming` entry corresponding to FID. - */ - eventEntry: PerformanceEventTiming; - /** - * The loading state of the document at the time when the first interaction - * occurred (see `LoadState` for details). If the first interaction occurred - * while the document was loading and executing script (e.g. usually in the - * `dom-interactive` phase) it can result in long input delays. - */ - loadState: LoadState; -} -/** - * An FID-specific version of the Metric object with attribution. - */ -export interface FIDMetricWithAttribution extends FIDMetric { - attribution: FIDAttribution; -} diff --git a/frontend-old/node_modules/web-vitals/dist/modules/types/fid.js b/frontend-old/node_modules/web-vitals/dist/modules/types/fid.js deleted file mode 100644 index e997715..0000000 --- a/frontend-old/node_modules/web-vitals/dist/modules/types/fid.js +++ /dev/null @@ -1,16 +0,0 @@ -/* - * Copyright 2022 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -export {}; diff --git a/frontend-old/node_modules/web-vitals/dist/modules/types/inp.d.ts b/frontend-old/node_modules/web-vitals/dist/modules/types/inp.d.ts deleted file mode 100644 index c60e86a..0000000 --- a/frontend-old/node_modules/web-vitals/dist/modules/types/inp.d.ts +++ /dev/null @@ -1,103 +0,0 @@ -import type { LoadState, Metric } from './base.js'; -/** - * An INP-specific version of the Metric object. - */ -export interface INPMetric extends Metric { - name: 'INP'; - entries: PerformanceEventTiming[]; -} -/** - * An object containing potentially-helpful debugging information that - * can be sent along with the INP value for the current page visit in order - * to help identify issues happening to real-users in the field. - */ -export interface INPAttribution { - /** - * A selector identifying the element that the user first interacted with - * as part of the frame where the INP candidate interaction occurred. - * If this value is an empty string, that generally means the element was - * removed from the DOM after the interaction. - */ - interactionTarget: string; - /** - * A reference to the HTML element identified by `interactionTargetSelector`. - * NOTE: for attribution purpose, a selector identifying the element is - * typically more useful than the element itself. However, the element is - * also made available in case additional context is needed. - */ - interactionTargetElement: Node | undefined; - /** - * The time when the user first interacted during the frame where the INP - * candidate interaction occurred (if more than one interaction occurred - * within the frame, only the first time is reported). - */ - interactionTime: DOMHighResTimeStamp; - /** - * The best-guess timestamp of the next paint after the interaction. - * In general, this timestamp is the same as the `startTime + duration` of - * the event timing entry. However, since `duration` values are rounded to - * the nearest 8ms, it can sometimes appear that the paint occurred before - * processing ended (which cannot happen). This value clamps the paint time - * so it's always after `processingEnd` from the Event Timing API and - * `renderStart` from the Long Animation Frame API (where available). - * It also averages the duration values for all entries in the same - * animation frame, which should be closer to the "real" value. - */ - nextPaintTime: DOMHighResTimeStamp; - /** - * The type of interaction, based on the event type of the `event` entry - * that corresponds to the interaction (i.e. the first `event` entry - * containing an `interactionId` dispatched in a given animation frame). - * For "pointerdown", "pointerup", or "click" events this will be "pointer", - * and for "keydown" or "keyup" events this will be "keyboard". - */ - interactionType: 'pointer' | 'keyboard'; - /** - * An array of Event Timing entries that were processed within the same - * animation frame as the INP candidate interaction. - */ - processedEventEntries: PerformanceEventTiming[]; - /** - * If the browser supports the Long Animation Frame API, this array will - * include any `long-animation-frame` entries that intersect with the INP - * candidate interaction's `startTime` and the `processingEnd` time of the - * last event processed within that animation frame. If the browser does not - * support the Long Animation Frame API or no `long-animation-frame` entries - * are detect, this array will be empty. - */ - longAnimationFrameEntries: PerformanceLongAnimationFrameTiming[]; - /** - * The time from when the user interacted with the page until when the - * browser was first able to start processing event listeners for that - * interaction. This time captures the delay before event processing can - * begin due to the main thread being busy with other work. - */ - inputDelay: number; - /** - * The time from when the first event listener started running in response to - * the user interaction until when all event listener processing has finished. - */ - processingDuration: number; - /** - * The time from when the browser finished processing all event listeners for - * the user interaction until the next frame is presented on the screen and - * visible to the user. This time includes work on the main thread (such as - * `requestAnimationFrame()` callbacks, `ResizeObserver` and - * `IntersectionObserver` callbacks, and style/layout calculation) as well - * as off-main-thread work (such as compositor, GPU, and raster work). - */ - presentationDelay: number; - /** - * The loading state of the document at the time when the interaction - * corresponding to INP occurred (see `LoadState` for details). If the - * interaction occurred while the document was loading and executing script - * (e.g. usually in the `dom-interactive` phase) it can result in long delays. - */ - loadState: LoadState; -} -/** - * An INP-specific version of the Metric object with attribution. - */ -export interface INPMetricWithAttribution extends INPMetric { - attribution: INPAttribution; -} diff --git a/frontend-old/node_modules/web-vitals/dist/modules/types/inp.js b/frontend-old/node_modules/web-vitals/dist/modules/types/inp.js deleted file mode 100644 index e997715..0000000 --- a/frontend-old/node_modules/web-vitals/dist/modules/types/inp.js +++ /dev/null @@ -1,16 +0,0 @@ -/* - * Copyright 2022 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -export {}; diff --git a/frontend-old/node_modules/web-vitals/dist/modules/types/lcp.d.ts b/frontend-old/node_modules/web-vitals/dist/modules/types/lcp.d.ts deleted file mode 100644 index 2e960e9..0000000 --- a/frontend-old/node_modules/web-vitals/dist/modules/types/lcp.d.ts +++ /dev/null @@ -1,69 +0,0 @@ -import type { Metric } from './base.js'; -/** - * An LCP-specific version of the Metric object. - */ -export interface LCPMetric extends Metric { - name: 'LCP'; - entries: LargestContentfulPaint[]; -} -/** - * An object containing potentially-helpful debugging information that - * can be sent along with the LCP value for the current page visit in order - * to help identify issues happening to real-users in the field. - */ -export interface LCPAttribution { - /** - * The element corresponding to the largest contentful paint for the page. - */ - element?: string; - /** - * The URL (if applicable) of the LCP image resource. If the LCP element - * is a text node, this value will not be set. - */ - url?: string; - /** - * The time from when the user initiates loading the page until when the - * browser receives the first byte of the response (a.k.a. TTFB). See - * [Optimize LCP](https://web.dev/articles/optimize-lcp) for details. - */ - timeToFirstByte: number; - /** - * The delta between TTFB and when the browser starts loading the LCP - * resource (if there is one, otherwise 0). See [Optimize - * LCP](https://web.dev/articles/optimize-lcp) for details. - */ - resourceLoadDelay: number; - /** - * The total time it takes to load the LCP resource itself (if there is one, - * otherwise 0). See [Optimize LCP](https://web.dev/articles/optimize-lcp) for - * details. - */ - resourceLoadDuration: number; - /** - * The delta between when the LCP resource finishes loading until the LCP - * element is fully rendered. See [Optimize - * LCP](https://web.dev/articles/optimize-lcp) for details. - */ - elementRenderDelay: number; - /** - * The `navigation` entry of the current page, which is useful for diagnosing - * general page load issues. This can be used to access `serverTiming` for example: - * navigationEntry?.serverTiming - */ - navigationEntry?: PerformanceNavigationTiming; - /** - * The `resource` entry for the LCP resource (if applicable), which is useful - * for diagnosing resource load issues. - */ - lcpResourceEntry?: PerformanceResourceTiming; - /** - * The `LargestContentfulPaint` entry corresponding to LCP. - */ - lcpEntry?: LargestContentfulPaint; -} -/** - * An LCP-specific version of the Metric object with attribution. - */ -export interface LCPMetricWithAttribution extends LCPMetric { - attribution: LCPAttribution; -} diff --git a/frontend-old/node_modules/web-vitals/dist/modules/types/lcp.js b/frontend-old/node_modules/web-vitals/dist/modules/types/lcp.js deleted file mode 100644 index e997715..0000000 --- a/frontend-old/node_modules/web-vitals/dist/modules/types/lcp.js +++ /dev/null @@ -1,16 +0,0 @@ -/* - * Copyright 2022 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -export {}; diff --git a/frontend-old/node_modules/web-vitals/dist/modules/types/polyfills.d.ts b/frontend-old/node_modules/web-vitals/dist/modules/types/polyfills.d.ts deleted file mode 100644 index e606728..0000000 --- a/frontend-old/node_modules/web-vitals/dist/modules/types/polyfills.d.ts +++ /dev/null @@ -1,4 +0,0 @@ -export type FirstInputPolyfillEntry = Omit<PerformanceEventTiming, 'processingEnd'>; -export interface FirstInputPolyfillCallback { - (entry: FirstInputPolyfillEntry): void; -} diff --git a/frontend-old/node_modules/web-vitals/dist/modules/types/polyfills.js b/frontend-old/node_modules/web-vitals/dist/modules/types/polyfills.js deleted file mode 100644 index e997715..0000000 --- a/frontend-old/node_modules/web-vitals/dist/modules/types/polyfills.js +++ /dev/null @@ -1,16 +0,0 @@ -/* - * Copyright 2022 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -export {}; diff --git a/frontend-old/node_modules/web-vitals/dist/modules/types/ttfb.d.ts b/frontend-old/node_modules/web-vitals/dist/modules/types/ttfb.d.ts deleted file mode 100644 index 485eeb6..0000000 --- a/frontend-old/node_modules/web-vitals/dist/modules/types/ttfb.d.ts +++ /dev/null @@ -1,59 +0,0 @@ -import type { Metric } from './base.js'; -/** - * A TTFB-specific version of the Metric object. - */ -export interface TTFBMetric extends Metric { - name: 'TTFB'; - entries: PerformanceNavigationTiming[]; -} -/** - * An object containing potentially-helpful debugging information that - * can be sent along with the TTFB value for the current page visit in order - * to help identify issues happening to real-users in the field. - * - * NOTE: these values are primarily useful for page loads not handled via - * service worker, as browsers differ in what they report when service worker - * is involved, see: https://github.com/w3c/navigation-timing/issues/199 - */ -export interface TTFBAttribution { - /** - * The total time from when the user initiates loading the page to when the - * page starts to handle the request. Large values here are typically due - * to HTTP redirects, though other browser processing contributes to this - * duration as well (so even without redirect it's generally not zero). - */ - waitingDuration: number; - /** - * The total time spent checking the HTTP cache for a match. For navigations - * handled via service worker, this duration usually includes service worker - * start-up time as well as time processing `fetch` event listeners, with - * some exceptions, see: https://github.com/w3c/navigation-timing/issues/199 - */ - cacheDuration: number; - /** - * The total time to resolve the DNS for the requested domain. - */ - dnsDuration: number; - /** - * The total time to create the connection to the requested domain. - */ - connectionDuration: number; - /** - * The total time from when the request was sent until the first byte of the - * response was received. This includes network time as well as server - * processing time. - */ - requestDuration: number; - /** - * The `navigation` entry of the current page, which is useful for diagnosing - * general page load issues. This can be used to access `serverTiming` for - * example: navigationEntry?.serverTiming - */ - navigationEntry?: PerformanceNavigationTiming; -} -/** - * A TTFB-specific version of the Metric object with attribution. - */ -export interface TTFBMetricWithAttribution extends TTFBMetric { - attribution: TTFBAttribution; -} diff --git a/frontend-old/node_modules/web-vitals/dist/modules/types/ttfb.js b/frontend-old/node_modules/web-vitals/dist/modules/types/ttfb.js deleted file mode 100644 index e997715..0000000 --- a/frontend-old/node_modules/web-vitals/dist/modules/types/ttfb.js +++ /dev/null @@ -1,16 +0,0 @@ -/* - * Copyright 2022 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -export {}; diff --git a/frontend-old/node_modules/web-vitals/dist/web-vitals.attribution.iife.js b/frontend-old/node_modules/web-vitals/dist/web-vitals.attribution.iife.js deleted file mode 100644 index 2903fda..0000000 --- a/frontend-old/node_modules/web-vitals/dist/web-vitals.attribution.iife.js +++ /dev/null @@ -1 +0,0 @@ -var webVitals=function(t){"use strict";var e,n,r=function(){var t=self.performance&&performance.getEntriesByType&&performance.getEntriesByType("navigation")[0];if(t&&t.responseStart>0&&t.responseStart<performance.now())return t},i=function(t){if("loading"===document.readyState)return"loading";var e=r();if(e){if(t<e.domInteractive)return"loading";if(0===e.domContentLoadedEventStart||t<e.domContentLoadedEventStart)return"dom-interactive";if(0===e.domComplete||t<e.domComplete)return"dom-content-loaded"}return"complete"},a=function(t){var e=t.nodeName;return 1===t.nodeType?e.toLowerCase():e.toUpperCase().replace(/^#/,"")},o=function(t,e){var n="";try{for(;t&&9!==t.nodeType;){var r=t,i=r.id?"#"+r.id:a(r)+(r.classList&&r.classList.value&&r.classList.value.trim()&&r.classList.value.trim().length?"."+r.classList.value.trim().replace(/\s+/g,"."):"");if(n.length+i.length>(e||100)-1)return n||i;if(n=n?i+">"+n:i,r.id)break;t=r.parentNode}}catch(t){}return n},c=-1,s=function(){return c},u=function(t){addEventListener("pageshow",(function(e){e.persisted&&(c=e.timeStamp,t(e))}),!0)},f=function(){var t=r();return t&&t.activationStart||0},d=function(t,e){var n=r(),i="navigate";s()>=0?i="back-forward-cache":n&&(document.prerendering||f()>0?i="prerender":document.wasDiscarded?i="restore":n.type&&(i=n.type.replace(/_/g,"-")));return{name:t,value:void 0===e?-1:e,rating:"good",delta:0,entries:[],id:"v4-".concat(Date.now(),"-").concat(Math.floor(8999999999999*Math.random())+1e12),navigationType:i}},l=function(t,e,n){try{if(PerformanceObserver.supportedEntryTypes.includes(t)){var r=new PerformanceObserver((function(t){Promise.resolve().then((function(){e(t.getEntries())}))}));return r.observe(Object.assign({type:t,buffered:!0},n||{})),r}}catch(t){}},m=function(t,e,n,r){var i,a;return function(o){e.value>=0&&(o||r)&&((a=e.value-(i||0))||void 0===i)&&(i=e.value,e.delta=a,e.rating=function(t,e){return t>e[1]?"poor":t>e[0]?"needs-improvement":"good"}(e.value,n),t(e))}},v=function(t){requestAnimationFrame((function(){return requestAnimationFrame((function(){return t()}))}))},p=function(t){document.addEventListener("visibilitychange",(function(){"hidden"===document.visibilityState&&t()}))},h=function(t){var e=!1;return function(){e||(t(),e=!0)}},g=-1,T=function(){return"hidden"!==document.visibilityState||document.prerendering?1/0:0},y=function(t){"hidden"===document.visibilityState&&g>-1&&(g="visibilitychange"===t.type?t.timeStamp:0,S())},E=function(){addEventListener("visibilitychange",y,!0),addEventListener("prerenderingchange",y,!0)},S=function(){removeEventListener("visibilitychange",y,!0),removeEventListener("prerenderingchange",y,!0)},b=function(){return g<0&&(g=T(),E(),u((function(){setTimeout((function(){g=T(),E()}),0)}))),{get firstHiddenTime(){return g}}},C=function(t){document.prerendering?addEventListener("prerenderingchange",(function(){return t()}),!0):t()},L=[1800,3e3],M=function(t,e){e=e||{},C((function(){var n,r=b(),i=d("FCP"),a=l("paint",(function(t){t.forEach((function(t){"first-contentful-paint"===t.name&&(a.disconnect(),t.startTime<r.firstHiddenTime&&(i.value=Math.max(t.startTime-f(),0),i.entries.push(t),n(!0)))}))}));a&&(n=m(t,i,L,e.reportAllChanges),u((function(r){i=d("FCP"),n=m(t,i,L,e.reportAllChanges),v((function(){i.value=performance.now()-r.timeStamp,n(!0)}))})))}))},D=[.1,.25],w=0,I=1/0,F=0,P=function(t){t.forEach((function(t){t.interactionId&&(I=Math.min(I,t.interactionId),F=Math.max(F,t.interactionId),w=F?(F-I)/7+1:0)}))},x=function(){return e?w:performance.interactionCount||0},k=function(){"interactionCount"in performance||e||(e=l("event",P,{type:"event",buffered:!0,durationThreshold:0}))},A=[],B=new Map,O=0,R=function(){var t=Math.min(A.length-1,Math.floor((x()-O)/50));return A[t]},j=[],q=function(t){if(j.forEach((function(e){return e(t)})),t.interactionId||"first-input"===t.entryType){var e=A[A.length-1],n=B.get(t.interactionId);if(n||A.length<10||t.duration>e.latency){if(n)t.duration>n.latency?(n.entries=[t],n.latency=t.duration):t.duration===n.latency&&t.startTime===n.entries[0].startTime&&n.entries.push(t);else{var r={id:t.interactionId,latency:t.duration,entries:[t]};B.set(r.id,r),A.push(r)}A.sort((function(t,e){return e.latency-t.latency})),A.length>10&&A.splice(10).forEach((function(t){return B.delete(t.id)}))}}},N=function(t){var e=self.requestIdleCallback||self.setTimeout,n=-1;return t=h(t),"hidden"===document.visibilityState?t():(n=e(t),p(t)),n},H=[200,500],V=function(t,e){"PerformanceEventTiming"in self&&"interactionId"in PerformanceEventTiming.prototype&&(e=e||{},C((function(){var n;k();var r,i=d("INP"),a=function(t){N((function(){t.forEach(q);var e=R();e&&e.latency!==i.value&&(i.value=e.latency,i.entries=e.entries,r())}))},o=l("event",a,{durationThreshold:null!==(n=e.durationThreshold)&&void 0!==n?n:40});r=m(t,i,H,e.reportAllChanges),o&&(o.observe({type:"first-input",buffered:!0}),p((function(){a(o.takeRecords()),r(!0)})),u((function(){O=x(),A.length=0,B.clear(),i=d("INP"),r=m(t,i,H,e.reportAllChanges)})))})))},W=[],z=[],U=0,_=new WeakMap,G=new Map,J=-1,K=function(t){W=W.concat(t),Q()},Q=function(){J<0&&(J=N(X))},X=function(){G.size>10&&G.forEach((function(t,e){B.has(e)||G.delete(e)}));var t=A.map((function(t){return _.get(t.entries[0])})),e=z.length-50;z=z.filter((function(n,r){return r>=e||t.includes(n)}));for(var n=new Set,r=0;r<z.length;r++){var i=z[r];et(i.startTime,i.processingEnd).forEach((function(t){n.add(t)}))}var a=W.length-1-50;W=W.filter((function(t,e){return t.startTime>U&&e>a||n.has(t)})),J=-1};j.push((function(t){t.interactionId&&t.target&&!G.has(t.interactionId)&&G.set(t.interactionId,t.target)}),(function(t){var e,n=t.startTime+t.duration;U=Math.max(U,t.processingEnd);for(var r=z.length-1;r>=0;r--){var i=z[r];if(Math.abs(n-i.renderTime)<=8){(e=i).startTime=Math.min(t.startTime,e.startTime),e.processingStart=Math.min(t.processingStart,e.processingStart),e.processingEnd=Math.max(t.processingEnd,e.processingEnd),e.entries.push(t);break}}e||(e={startTime:t.startTime,processingStart:t.processingStart,processingEnd:t.processingEnd,renderTime:n,entries:[t]},z.push(e)),(t.interactionId||"first-input"===t.entryType)&&_.set(t,e),Q()}));var Y,Z,$,tt,et=function(t,e){for(var n,r=[],i=0;n=W[i];i++)if(!(n.startTime+n.duration<t)){if(n.startTime>e)break;r.push(n)}return r},nt=[2500,4e3],rt={},it=[800,1800],at=function t(e){document.prerendering?C((function(){return t(e)})):"complete"!==document.readyState?addEventListener("load",(function(){return t(e)}),!0):setTimeout(e,0)},ot=function(t,e){e=e||{};var n=d("TTFB"),i=m(t,n,it,e.reportAllChanges);at((function(){var a=r();a&&(n.value=Math.max(a.responseStart-f(),0),n.entries=[a],i(!0),u((function(){n=d("TTFB",0),(i=m(t,n,it,e.reportAllChanges))(!0)})))}))},ct={passive:!0,capture:!0},st=new Date,ut=function(t,e){Y||(Y=e,Z=t,$=new Date,lt(removeEventListener),ft())},ft=function(){if(Z>=0&&Z<$-st){var t={entryType:"first-input",name:Y.type,target:Y.target,cancelable:Y.cancelable,startTime:Y.timeStamp,processingStart:Y.timeStamp+Z};tt.forEach((function(e){e(t)})),tt=[]}},dt=function(t){if(t.cancelable){var e=(t.timeStamp>1e12?new Date:performance.now())-t.timeStamp;"pointerdown"==t.type?function(t,e){var n=function(){ut(t,e),i()},r=function(){i()},i=function(){removeEventListener("pointerup",n,ct),removeEventListener("pointercancel",r,ct)};addEventListener("pointerup",n,ct),addEventListener("pointercancel",r,ct)}(e,t):ut(e,t)}},lt=function(t){["mousedown","keydown","touchstart","pointerdown"].forEach((function(e){return t(e,dt,ct)}))},mt=[100,300],vt=function(t,e){e=e||{},C((function(){var n,r=b(),i=d("FID"),a=function(t){t.startTime<r.firstHiddenTime&&(i.value=t.processingStart-t.startTime,i.entries.push(t),n(!0))},o=function(t){t.forEach(a)},c=l("first-input",o);n=m(t,i,mt,e.reportAllChanges),c&&(p(h((function(){o(c.takeRecords()),c.disconnect()}))),u((function(){var r;i=d("FID"),n=m(t,i,mt,e.reportAllChanges),tt=[],Z=-1,Y=null,lt(addEventListener),r=a,tt.push(r),ft()})))}))};return t.CLSThresholds=D,t.FCPThresholds=L,t.FIDThresholds=mt,t.INPThresholds=H,t.LCPThresholds=nt,t.TTFBThresholds=it,t.onCLS=function(t,e){!function(t,e){e=e||{},M(h((function(){var n,r=d("CLS",0),i=0,a=[],o=function(t){t.forEach((function(t){if(!t.hadRecentInput){var e=a[0],n=a[a.length-1];i&&t.startTime-n.startTime<1e3&&t.startTime-e.startTime<5e3?(i+=t.value,a.push(t)):(i=t.value,a=[t])}})),i>r.value&&(r.value=i,r.entries=a,n())},c=l("layout-shift",o);c&&(n=m(t,r,D,e.reportAllChanges),p((function(){o(c.takeRecords()),n(!0)})),u((function(){i=0,r=d("CLS",0),n=m(t,r,D,e.reportAllChanges),v((function(){return n()}))})),setTimeout(n,0))})))}((function(e){var n=function(t){var e,n={};if(t.entries.length){var r=t.entries.reduce((function(t,e){return t&&t.value>e.value?t:e}));if(r&&r.sources&&r.sources.length){var a=(e=r.sources).find((function(t){return t.node&&1===t.node.nodeType}))||e[0];a&&(n={largestShiftTarget:o(a.node),largestShiftTime:r.startTime,largestShiftValue:r.value,largestShiftSource:a,largestShiftEntry:r,loadState:i(r.startTime)})}}return Object.assign(t,{attribution:n})}(e);t(n)}),e)},t.onFCP=function(t,e){M((function(e){var n=function(t){var e={timeToFirstByte:0,firstByteToFCP:t.value,loadState:i(s())};if(t.entries.length){var n=r(),a=t.entries[t.entries.length-1];if(n){var o=n.activationStart||0,c=Math.max(0,n.responseStart-o);e={timeToFirstByte:c,firstByteToFCP:t.value-c,loadState:i(t.entries[0].startTime),navigationEntry:n,fcpEntry:a}}}return Object.assign(t,{attribution:e})}(e);t(n)}),e)},t.onFID=function(t,e){vt((function(e){var n=function(t){var e=t.entries[0],n={eventTarget:o(e.target),eventType:e.name,eventTime:e.startTime,eventEntry:e,loadState:i(e.startTime)};return Object.assign(t,{attribution:n})}(e);t(n)}),e)},t.onINP=function(t,e){n||(n=l("long-animation-frame",K)),V((function(e){var n=function(t){var e=t.entries[0],n=_.get(e),r=e.processingStart,a=n.processingEnd,c=n.entries.sort((function(t,e){return t.processingStart-e.processingStart})),s=et(e.startTime,a),u=t.entries.find((function(t){return t.target})),f=u&&u.target||G.get(e.interactionId),d=[e.startTime+e.duration,a].concat(s.map((function(t){return t.startTime+t.duration}))),l=Math.max.apply(Math,d),m={interactionTarget:o(f),interactionTargetElement:f,interactionType:e.name.startsWith("key")?"keyboard":"pointer",interactionTime:e.startTime,nextPaintTime:l,processedEventEntries:c,longAnimationFrameEntries:s,inputDelay:r-e.startTime,processingDuration:a-r,presentationDelay:Math.max(l-a,0),loadState:i(e.startTime)};return Object.assign(t,{attribution:m})}(e);t(n)}),e)},t.onLCP=function(t,e){!function(t,e){e=e||{},C((function(){var n,r=b(),i=d("LCP"),a=function(t){e.reportAllChanges||(t=t.slice(-1)),t.forEach((function(t){t.startTime<r.firstHiddenTime&&(i.value=Math.max(t.startTime-f(),0),i.entries=[t],n())}))},o=l("largest-contentful-paint",a);if(o){n=m(t,i,nt,e.reportAllChanges);var c=h((function(){rt[i.id]||(a(o.takeRecords()),o.disconnect(),rt[i.id]=!0,n(!0))}));["keydown","click"].forEach((function(t){addEventListener(t,(function(){return N(c)}),{once:!0,capture:!0})})),p(c),u((function(r){i=d("LCP"),n=m(t,i,nt,e.reportAllChanges),v((function(){i.value=performance.now()-r.timeStamp,rt[i.id]=!0,n(!0)}))}))}}))}((function(e){var n=function(t){var e={timeToFirstByte:0,resourceLoadDelay:0,resourceLoadDuration:0,elementRenderDelay:t.value};if(t.entries.length){var n=r();if(n){var i=n.activationStart||0,a=t.entries[t.entries.length-1],c=a.url&&performance.getEntriesByType("resource").filter((function(t){return t.name===a.url}))[0],s=Math.max(0,n.responseStart-i),u=Math.max(s,c?(c.requestStart||c.startTime)-i:0),f=Math.max(u,c?c.responseEnd-i:0),d=Math.max(f,a.startTime-i);e={element:o(a.element),timeToFirstByte:s,resourceLoadDelay:u-s,resourceLoadDuration:f-u,elementRenderDelay:d-f,navigationEntry:n,lcpEntry:a},a.url&&(e.url=a.url),c&&(e.lcpResourceEntry=c)}}return Object.assign(t,{attribution:e})}(e);t(n)}),e)},t.onTTFB=function(t,e){ot((function(e){var n=function(t){var e={waitingDuration:0,cacheDuration:0,dnsDuration:0,connectionDuration:0,requestDuration:0};if(t.entries.length){var n=t.entries[0],r=n.activationStart||0,i=Math.max((n.workerStart||n.fetchStart)-r,0),a=Math.max(n.domainLookupStart-r,0),o=Math.max(n.connectStart-r,0),c=Math.max(n.connectEnd-r,0);e={waitingDuration:i,cacheDuration:a-i,dnsDuration:o-a,connectionDuration:c-o,requestDuration:t.value-c,navigationEntry:n}}return Object.assign(t,{attribution:e})}(e);t(n)}),e)},t}({}); diff --git a/frontend-old/node_modules/web-vitals/dist/web-vitals.attribution.js b/frontend-old/node_modules/web-vitals/dist/web-vitals.attribution.js deleted file mode 100644 index 98efa73..0000000 --- a/frontend-old/node_modules/web-vitals/dist/web-vitals.attribution.js +++ /dev/null @@ -1 +0,0 @@ -var t,e,n=function(){var t=self.performance&&performance.getEntriesByType&&performance.getEntriesByType("navigation")[0];if(t&&t.responseStart>0&&t.responseStart<performance.now())return t},r=function(t){if("loading"===document.readyState)return"loading";var e=n();if(e){if(t<e.domInteractive)return"loading";if(0===e.domContentLoadedEventStart||t<e.domContentLoadedEventStart)return"dom-interactive";if(0===e.domComplete||t<e.domComplete)return"dom-content-loaded"}return"complete"},i=function(t){var e=t.nodeName;return 1===t.nodeType?e.toLowerCase():e.toUpperCase().replace(/^#/,"")},a=function(t,e){var n="";try{for(;t&&9!==t.nodeType;){var r=t,a=r.id?"#"+r.id:i(r)+(r.classList&&r.classList.value&&r.classList.value.trim()&&r.classList.value.trim().length?"."+r.classList.value.trim().replace(/\s+/g,"."):"");if(n.length+a.length>(e||100)-1)return n||a;if(n=n?a+">"+n:a,r.id)break;t=r.parentNode}}catch(t){}return n},o=-1,c=function(){return o},u=function(t){addEventListener("pageshow",(function(e){e.persisted&&(o=e.timeStamp,t(e))}),!0)},s=function(){var t=n();return t&&t.activationStart||0},f=function(t,e){var r=n(),i="navigate";c()>=0?i="back-forward-cache":r&&(document.prerendering||s()>0?i="prerender":document.wasDiscarded?i="restore":r.type&&(i=r.type.replace(/_/g,"-")));return{name:t,value:void 0===e?-1:e,rating:"good",delta:0,entries:[],id:"v4-".concat(Date.now(),"-").concat(Math.floor(8999999999999*Math.random())+1e12),navigationType:i}},d=function(t,e,n){try{if(PerformanceObserver.supportedEntryTypes.includes(t)){var r=new PerformanceObserver((function(t){Promise.resolve().then((function(){e(t.getEntries())}))}));return r.observe(Object.assign({type:t,buffered:!0},n||{})),r}}catch(t){}},l=function(t,e,n,r){var i,a;return function(o){e.value>=0&&(o||r)&&((a=e.value-(i||0))||void 0===i)&&(i=e.value,e.delta=a,e.rating=function(t,e){return t>e[1]?"poor":t>e[0]?"needs-improvement":"good"}(e.value,n),t(e))}},m=function(t){requestAnimationFrame((function(){return requestAnimationFrame((function(){return t()}))}))},p=function(t){document.addEventListener("visibilitychange",(function(){"hidden"===document.visibilityState&&t()}))},v=function(t){var e=!1;return function(){e||(t(),e=!0)}},g=-1,h=function(){return"hidden"!==document.visibilityState||document.prerendering?1/0:0},T=function(t){"hidden"===document.visibilityState&&g>-1&&(g="visibilitychange"===t.type?t.timeStamp:0,E())},y=function(){addEventListener("visibilitychange",T,!0),addEventListener("prerenderingchange",T,!0)},E=function(){removeEventListener("visibilitychange",T,!0),removeEventListener("prerenderingchange",T,!0)},S=function(){return g<0&&(g=h(),y(),u((function(){setTimeout((function(){g=h(),y()}),0)}))),{get firstHiddenTime(){return g}}},b=function(t){document.prerendering?addEventListener("prerenderingchange",(function(){return t()}),!0):t()},L=[1800,3e3],C=function(t,e){e=e||{},b((function(){var n,r=S(),i=f("FCP"),a=d("paint",(function(t){t.forEach((function(t){"first-contentful-paint"===t.name&&(a.disconnect(),t.startTime<r.firstHiddenTime&&(i.value=Math.max(t.startTime-s(),0),i.entries.push(t),n(!0)))}))}));a&&(n=l(t,i,L,e.reportAllChanges),u((function(r){i=f("FCP"),n=l(t,i,L,e.reportAllChanges),m((function(){i.value=performance.now()-r.timeStamp,n(!0)}))})))}))},M=[.1,.25],D=function(t,e){!function(t,e){e=e||{},C(v((function(){var n,r=f("CLS",0),i=0,a=[],o=function(t){t.forEach((function(t){if(!t.hadRecentInput){var e=a[0],n=a[a.length-1];i&&t.startTime-n.startTime<1e3&&t.startTime-e.startTime<5e3?(i+=t.value,a.push(t)):(i=t.value,a=[t])}})),i>r.value&&(r.value=i,r.entries=a,n())},c=d("layout-shift",o);c&&(n=l(t,r,M,e.reportAllChanges),p((function(){o(c.takeRecords()),n(!0)})),u((function(){i=0,r=f("CLS",0),n=l(t,r,M,e.reportAllChanges),m((function(){return n()}))})),setTimeout(n,0))})))}((function(e){var n=function(t){var e,n={};if(t.entries.length){var i=t.entries.reduce((function(t,e){return t&&t.value>e.value?t:e}));if(i&&i.sources&&i.sources.length){var o=(e=i.sources).find((function(t){return t.node&&1===t.node.nodeType}))||e[0];o&&(n={largestShiftTarget:a(o.node),largestShiftTime:i.startTime,largestShiftValue:i.value,largestShiftSource:o,largestShiftEntry:i,loadState:r(i.startTime)})}}return Object.assign(t,{attribution:n})}(e);t(n)}),e)},w=function(t,e){C((function(e){var i=function(t){var e={timeToFirstByte:0,firstByteToFCP:t.value,loadState:r(c())};if(t.entries.length){var i=n(),a=t.entries[t.entries.length-1];if(i){var o=i.activationStart||0,u=Math.max(0,i.responseStart-o);e={timeToFirstByte:u,firstByteToFCP:t.value-u,loadState:r(t.entries[0].startTime),navigationEntry:i,fcpEntry:a}}}return Object.assign(t,{attribution:e})}(e);t(i)}),e)},x=0,I=1/0,k=0,A=function(t){t.forEach((function(t){t.interactionId&&(I=Math.min(I,t.interactionId),k=Math.max(k,t.interactionId),x=k?(k-I)/7+1:0)}))},F=function(){return t?x:performance.interactionCount||0},P=function(){"interactionCount"in performance||t||(t=d("event",A,{type:"event",buffered:!0,durationThreshold:0}))},B=[],O=new Map,R=0,j=function(){var t=Math.min(B.length-1,Math.floor((F()-R)/50));return B[t]},q=[],H=function(t){if(q.forEach((function(e){return e(t)})),t.interactionId||"first-input"===t.entryType){var e=B[B.length-1],n=O.get(t.interactionId);if(n||B.length<10||t.duration>e.latency){if(n)t.duration>n.latency?(n.entries=[t],n.latency=t.duration):t.duration===n.latency&&t.startTime===n.entries[0].startTime&&n.entries.push(t);else{var r={id:t.interactionId,latency:t.duration,entries:[t]};O.set(r.id,r),B.push(r)}B.sort((function(t,e){return e.latency-t.latency})),B.length>10&&B.splice(10).forEach((function(t){return O.delete(t.id)}))}}},N=function(t){var e=self.requestIdleCallback||self.setTimeout,n=-1;return t=v(t),"hidden"===document.visibilityState?t():(n=e(t),p(t)),n},W=[200,500],z=function(t,e){"PerformanceEventTiming"in self&&"interactionId"in PerformanceEventTiming.prototype&&(e=e||{},b((function(){var n;P();var r,i=f("INP"),a=function(t){N((function(){t.forEach(H);var e=j();e&&e.latency!==i.value&&(i.value=e.latency,i.entries=e.entries,r())}))},o=d("event",a,{durationThreshold:null!==(n=e.durationThreshold)&&void 0!==n?n:40});r=l(t,i,W,e.reportAllChanges),o&&(o.observe({type:"first-input",buffered:!0}),p((function(){a(o.takeRecords()),r(!0)})),u((function(){R=F(),B.length=0,O.clear(),i=f("INP"),r=l(t,i,W,e.reportAllChanges)})))})))},U=[],V=[],_=0,G=new WeakMap,J=new Map,K=-1,Q=function(t){U=U.concat(t),X()},X=function(){K<0&&(K=N(Y))},Y=function(){J.size>10&&J.forEach((function(t,e){O.has(e)||J.delete(e)}));var t=B.map((function(t){return G.get(t.entries[0])})),e=V.length-50;V=V.filter((function(n,r){return r>=e||t.includes(n)}));for(var n=new Set,r=0;r<V.length;r++){var i=V[r];nt(i.startTime,i.processingEnd).forEach((function(t){n.add(t)}))}var a=U.length-1-50;U=U.filter((function(t,e){return t.startTime>_&&e>a||n.has(t)})),K=-1};q.push((function(t){t.interactionId&&t.target&&!J.has(t.interactionId)&&J.set(t.interactionId,t.target)}),(function(t){var e,n=t.startTime+t.duration;_=Math.max(_,t.processingEnd);for(var r=V.length-1;r>=0;r--){var i=V[r];if(Math.abs(n-i.renderTime)<=8){(e=i).startTime=Math.min(t.startTime,e.startTime),e.processingStart=Math.min(t.processingStart,e.processingStart),e.processingEnd=Math.max(t.processingEnd,e.processingEnd),e.entries.push(t);break}}e||(e={startTime:t.startTime,processingStart:t.processingStart,processingEnd:t.processingEnd,renderTime:n,entries:[t]},V.push(e)),(t.interactionId||"first-input"===t.entryType)&&G.set(t,e),X()}));var Z,$,tt,et,nt=function(t,e){for(var n,r=[],i=0;n=U[i];i++)if(!(n.startTime+n.duration<t)){if(n.startTime>e)break;r.push(n)}return r},rt=function(t,n){e||(e=d("long-animation-frame",Q)),z((function(e){var n=function(t){var e=t.entries[0],n=G.get(e),i=e.processingStart,o=n.processingEnd,c=n.entries.sort((function(t,e){return t.processingStart-e.processingStart})),u=nt(e.startTime,o),s=t.entries.find((function(t){return t.target})),f=s&&s.target||J.get(e.interactionId),d=[e.startTime+e.duration,o].concat(u.map((function(t){return t.startTime+t.duration}))),l=Math.max.apply(Math,d),m={interactionTarget:a(f),interactionTargetElement:f,interactionType:e.name.startsWith("key")?"keyboard":"pointer",interactionTime:e.startTime,nextPaintTime:l,processedEventEntries:c,longAnimationFrameEntries:u,inputDelay:i-e.startTime,processingDuration:o-i,presentationDelay:Math.max(l-o,0),loadState:r(e.startTime)};return Object.assign(t,{attribution:m})}(e);t(n)}),n)},it=[2500,4e3],at={},ot=function(t,e){!function(t,e){e=e||{},b((function(){var n,r=S(),i=f("LCP"),a=function(t){e.reportAllChanges||(t=t.slice(-1)),t.forEach((function(t){t.startTime<r.firstHiddenTime&&(i.value=Math.max(t.startTime-s(),0),i.entries=[t],n())}))},o=d("largest-contentful-paint",a);if(o){n=l(t,i,it,e.reportAllChanges);var c=v((function(){at[i.id]||(a(o.takeRecords()),o.disconnect(),at[i.id]=!0,n(!0))}));["keydown","click"].forEach((function(t){addEventListener(t,(function(){return N(c)}),{once:!0,capture:!0})})),p(c),u((function(r){i=f("LCP"),n=l(t,i,it,e.reportAllChanges),m((function(){i.value=performance.now()-r.timeStamp,at[i.id]=!0,n(!0)}))}))}}))}((function(e){var r=function(t){var e={timeToFirstByte:0,resourceLoadDelay:0,resourceLoadDuration:0,elementRenderDelay:t.value};if(t.entries.length){var r=n();if(r){var i=r.activationStart||0,o=t.entries[t.entries.length-1],c=o.url&&performance.getEntriesByType("resource").filter((function(t){return t.name===o.url}))[0],u=Math.max(0,r.responseStart-i),s=Math.max(u,c?(c.requestStart||c.startTime)-i:0),f=Math.max(s,c?c.responseEnd-i:0),d=Math.max(f,o.startTime-i);e={element:a(o.element),timeToFirstByte:u,resourceLoadDelay:s-u,resourceLoadDuration:f-s,elementRenderDelay:d-f,navigationEntry:r,lcpEntry:o},o.url&&(e.url=o.url),c&&(e.lcpResourceEntry=c)}}return Object.assign(t,{attribution:e})}(e);t(r)}),e)},ct=[800,1800],ut=function t(e){document.prerendering?b((function(){return t(e)})):"complete"!==document.readyState?addEventListener("load",(function(){return t(e)}),!0):setTimeout(e,0)},st=function(t,e){e=e||{};var r=f("TTFB"),i=l(t,r,ct,e.reportAllChanges);ut((function(){var a=n();a&&(r.value=Math.max(a.responseStart-s(),0),r.entries=[a],i(!0),u((function(){r=f("TTFB",0),(i=l(t,r,ct,e.reportAllChanges))(!0)})))}))},ft=function(t,e){st((function(e){var n=function(t){var e={waitingDuration:0,cacheDuration:0,dnsDuration:0,connectionDuration:0,requestDuration:0};if(t.entries.length){var n=t.entries[0],r=n.activationStart||0,i=Math.max((n.workerStart||n.fetchStart)-r,0),a=Math.max(n.domainLookupStart-r,0),o=Math.max(n.connectStart-r,0),c=Math.max(n.connectEnd-r,0);e={waitingDuration:i,cacheDuration:a-i,dnsDuration:o-a,connectionDuration:c-o,requestDuration:t.value-c,navigationEntry:n}}return Object.assign(t,{attribution:e})}(e);t(n)}),e)},dt={passive:!0,capture:!0},lt=new Date,mt=function(t,e){Z||(Z=e,$=t,tt=new Date,gt(removeEventListener),pt())},pt=function(){if($>=0&&$<tt-lt){var t={entryType:"first-input",name:Z.type,target:Z.target,cancelable:Z.cancelable,startTime:Z.timeStamp,processingStart:Z.timeStamp+$};et.forEach((function(e){e(t)})),et=[]}},vt=function(t){if(t.cancelable){var e=(t.timeStamp>1e12?new Date:performance.now())-t.timeStamp;"pointerdown"==t.type?function(t,e){var n=function(){mt(t,e),i()},r=function(){i()},i=function(){removeEventListener("pointerup",n,dt),removeEventListener("pointercancel",r,dt)};addEventListener("pointerup",n,dt),addEventListener("pointercancel",r,dt)}(e,t):mt(e,t)}},gt=function(t){["mousedown","keydown","touchstart","pointerdown"].forEach((function(e){return t(e,vt,dt)}))},ht=[100,300],Tt=function(t,e){e=e||{},b((function(){var n,r=S(),i=f("FID"),a=function(t){t.startTime<r.firstHiddenTime&&(i.value=t.processingStart-t.startTime,i.entries.push(t),n(!0))},o=function(t){t.forEach(a)},c=d("first-input",o);n=l(t,i,ht,e.reportAllChanges),c&&(p(v((function(){o(c.takeRecords()),c.disconnect()}))),u((function(){var r;i=f("FID"),n=l(t,i,ht,e.reportAllChanges),et=[],$=-1,Z=null,gt(addEventListener),r=a,et.push(r),pt()})))}))},yt=function(t,e){Tt((function(e){var n=function(t){var e=t.entries[0],n={eventTarget:a(e.target),eventType:e.name,eventTime:e.startTime,eventEntry:e,loadState:r(e.startTime)};return Object.assign(t,{attribution:n})}(e);t(n)}),e)};export{M as CLSThresholds,L as FCPThresholds,ht as FIDThresholds,W as INPThresholds,it as LCPThresholds,ct as TTFBThresholds,D as onCLS,w as onFCP,yt as onFID,rt as onINP,ot as onLCP,ft as onTTFB}; diff --git a/frontend-old/node_modules/web-vitals/dist/web-vitals.attribution.umd.cjs b/frontend-old/node_modules/web-vitals/dist/web-vitals.attribution.umd.cjs deleted file mode 100644 index 3d3a396..0000000 --- a/frontend-old/node_modules/web-vitals/dist/web-vitals.attribution.umd.cjs +++ /dev/null @@ -1 +0,0 @@ -!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).webVitals={})}(this,(function(t){"use strict";var e,n,r=function(){var t=self.performance&&performance.getEntriesByType&&performance.getEntriesByType("navigation")[0];if(t&&t.responseStart>0&&t.responseStart<performance.now())return t},i=function(t){if("loading"===document.readyState)return"loading";var e=r();if(e){if(t<e.domInteractive)return"loading";if(0===e.domContentLoadedEventStart||t<e.domContentLoadedEventStart)return"dom-interactive";if(0===e.domComplete||t<e.domComplete)return"dom-content-loaded"}return"complete"},a=function(t){var e=t.nodeName;return 1===t.nodeType?e.toLowerCase():e.toUpperCase().replace(/^#/,"")},o=function(t,e){var n="";try{for(;t&&9!==t.nodeType;){var r=t,i=r.id?"#"+r.id:a(r)+(r.classList&&r.classList.value&&r.classList.value.trim()&&r.classList.value.trim().length?"."+r.classList.value.trim().replace(/\s+/g,"."):"");if(n.length+i.length>(e||100)-1)return n||i;if(n=n?i+">"+n:i,r.id)break;t=r.parentNode}}catch(t){}return n},c=-1,s=function(){return c},u=function(t){addEventListener("pageshow",(function(e){e.persisted&&(c=e.timeStamp,t(e))}),!0)},f=function(){var t=r();return t&&t.activationStart||0},d=function(t,e){var n=r(),i="navigate";s()>=0?i="back-forward-cache":n&&(document.prerendering||f()>0?i="prerender":document.wasDiscarded?i="restore":n.type&&(i=n.type.replace(/_/g,"-")));return{name:t,value:void 0===e?-1:e,rating:"good",delta:0,entries:[],id:"v4-".concat(Date.now(),"-").concat(Math.floor(8999999999999*Math.random())+1e12),navigationType:i}},l=function(t,e,n){try{if(PerformanceObserver.supportedEntryTypes.includes(t)){var r=new PerformanceObserver((function(t){Promise.resolve().then((function(){e(t.getEntries())}))}));return r.observe(Object.assign({type:t,buffered:!0},n||{})),r}}catch(t){}},m=function(t,e,n,r){var i,a;return function(o){e.value>=0&&(o||r)&&((a=e.value-(i||0))||void 0===i)&&(i=e.value,e.delta=a,e.rating=function(t,e){return t>e[1]?"poor":t>e[0]?"needs-improvement":"good"}(e.value,n),t(e))}},p=function(t){requestAnimationFrame((function(){return requestAnimationFrame((function(){return t()}))}))},v=function(t){document.addEventListener("visibilitychange",(function(){"hidden"===document.visibilityState&&t()}))},h=function(t){var e=!1;return function(){e||(t(),e=!0)}},g=-1,T=function(){return"hidden"!==document.visibilityState||document.prerendering?1/0:0},y=function(t){"hidden"===document.visibilityState&&g>-1&&(g="visibilitychange"===t.type?t.timeStamp:0,S())},E=function(){addEventListener("visibilitychange",y,!0),addEventListener("prerenderingchange",y,!0)},S=function(){removeEventListener("visibilitychange",y,!0),removeEventListener("prerenderingchange",y,!0)},b=function(){return g<0&&(g=T(),E(),u((function(){setTimeout((function(){g=T(),E()}),0)}))),{get firstHiddenTime(){return g}}},C=function(t){document.prerendering?addEventListener("prerenderingchange",(function(){return t()}),!0):t()},L=[1800,3e3],M=function(t,e){e=e||{},C((function(){var n,r=b(),i=d("FCP"),a=l("paint",(function(t){t.forEach((function(t){"first-contentful-paint"===t.name&&(a.disconnect(),t.startTime<r.firstHiddenTime&&(i.value=Math.max(t.startTime-f(),0),i.entries.push(t),n(!0)))}))}));a&&(n=m(t,i,L,e.reportAllChanges),u((function(r){i=d("FCP"),n=m(t,i,L,e.reportAllChanges),p((function(){i.value=performance.now()-r.timeStamp,n(!0)}))})))}))},D=[.1,.25],w=0,I=1/0,x=0,F=function(t){t.forEach((function(t){t.interactionId&&(I=Math.min(I,t.interactionId),x=Math.max(x,t.interactionId),w=x?(x-I)/7+1:0)}))},P=function(){return e?w:performance.interactionCount||0},k=function(){"interactionCount"in performance||e||(e=l("event",F,{type:"event",buffered:!0,durationThreshold:0}))},A=[],B=new Map,O=0,j=function(){var t=Math.min(A.length-1,Math.floor((P()-O)/50));return A[t]},R=[],q=function(t){if(R.forEach((function(e){return e(t)})),t.interactionId||"first-input"===t.entryType){var e=A[A.length-1],n=B.get(t.interactionId);if(n||A.length<10||t.duration>e.latency){if(n)t.duration>n.latency?(n.entries=[t],n.latency=t.duration):t.duration===n.latency&&t.startTime===n.entries[0].startTime&&n.entries.push(t);else{var r={id:t.interactionId,latency:t.duration,entries:[t]};B.set(r.id,r),A.push(r)}A.sort((function(t,e){return e.latency-t.latency})),A.length>10&&A.splice(10).forEach((function(t){return B.delete(t.id)}))}}},N=function(t){var e=self.requestIdleCallback||self.setTimeout,n=-1;return t=h(t),"hidden"===document.visibilityState?t():(n=e(t),v(t)),n},H=[200,500],V=function(t,e){"PerformanceEventTiming"in self&&"interactionId"in PerformanceEventTiming.prototype&&(e=e||{},C((function(){var n;k();var r,i=d("INP"),a=function(t){N((function(){t.forEach(q);var e=j();e&&e.latency!==i.value&&(i.value=e.latency,i.entries=e.entries,r())}))},o=l("event",a,{durationThreshold:null!==(n=e.durationThreshold)&&void 0!==n?n:40});r=m(t,i,H,e.reportAllChanges),o&&(o.observe({type:"first-input",buffered:!0}),v((function(){a(o.takeRecords()),r(!0)})),u((function(){O=P(),A.length=0,B.clear(),i=d("INP"),r=m(t,i,H,e.reportAllChanges)})))})))},W=[],z=[],U=0,_=new WeakMap,G=new Map,J=-1,K=function(t){W=W.concat(t),Q()},Q=function(){J<0&&(J=N(X))},X=function(){G.size>10&&G.forEach((function(t,e){B.has(e)||G.delete(e)}));var t=A.map((function(t){return _.get(t.entries[0])})),e=z.length-50;z=z.filter((function(n,r){return r>=e||t.includes(n)}));for(var n=new Set,r=0;r<z.length;r++){var i=z[r];et(i.startTime,i.processingEnd).forEach((function(t){n.add(t)}))}var a=W.length-1-50;W=W.filter((function(t,e){return t.startTime>U&&e>a||n.has(t)})),J=-1};R.push((function(t){t.interactionId&&t.target&&!G.has(t.interactionId)&&G.set(t.interactionId,t.target)}),(function(t){var e,n=t.startTime+t.duration;U=Math.max(U,t.processingEnd);for(var r=z.length-1;r>=0;r--){var i=z[r];if(Math.abs(n-i.renderTime)<=8){(e=i).startTime=Math.min(t.startTime,e.startTime),e.processingStart=Math.min(t.processingStart,e.processingStart),e.processingEnd=Math.max(t.processingEnd,e.processingEnd),e.entries.push(t);break}}e||(e={startTime:t.startTime,processingStart:t.processingStart,processingEnd:t.processingEnd,renderTime:n,entries:[t]},z.push(e)),(t.interactionId||"first-input"===t.entryType)&&_.set(t,e),Q()}));var Y,Z,$,tt,et=function(t,e){for(var n,r=[],i=0;n=W[i];i++)if(!(n.startTime+n.duration<t)){if(n.startTime>e)break;r.push(n)}return r},nt=[2500,4e3],rt={},it=[800,1800],at=function t(e){document.prerendering?C((function(){return t(e)})):"complete"!==document.readyState?addEventListener("load",(function(){return t(e)}),!0):setTimeout(e,0)},ot=function(t,e){e=e||{};var n=d("TTFB"),i=m(t,n,it,e.reportAllChanges);at((function(){var a=r();a&&(n.value=Math.max(a.responseStart-f(),0),n.entries=[a],i(!0),u((function(){n=d("TTFB",0),(i=m(t,n,it,e.reportAllChanges))(!0)})))}))},ct={passive:!0,capture:!0},st=new Date,ut=function(t,e){Y||(Y=e,Z=t,$=new Date,lt(removeEventListener),ft())},ft=function(){if(Z>=0&&Z<$-st){var t={entryType:"first-input",name:Y.type,target:Y.target,cancelable:Y.cancelable,startTime:Y.timeStamp,processingStart:Y.timeStamp+Z};tt.forEach((function(e){e(t)})),tt=[]}},dt=function(t){if(t.cancelable){var e=(t.timeStamp>1e12?new Date:performance.now())-t.timeStamp;"pointerdown"==t.type?function(t,e){var n=function(){ut(t,e),i()},r=function(){i()},i=function(){removeEventListener("pointerup",n,ct),removeEventListener("pointercancel",r,ct)};addEventListener("pointerup",n,ct),addEventListener("pointercancel",r,ct)}(e,t):ut(e,t)}},lt=function(t){["mousedown","keydown","touchstart","pointerdown"].forEach((function(e){return t(e,dt,ct)}))},mt=[100,300],pt=function(t,e){e=e||{},C((function(){var n,r=b(),i=d("FID"),a=function(t){t.startTime<r.firstHiddenTime&&(i.value=t.processingStart-t.startTime,i.entries.push(t),n(!0))},o=function(t){t.forEach(a)},c=l("first-input",o);n=m(t,i,mt,e.reportAllChanges),c&&(v(h((function(){o(c.takeRecords()),c.disconnect()}))),u((function(){var r;i=d("FID"),n=m(t,i,mt,e.reportAllChanges),tt=[],Z=-1,Y=null,lt(addEventListener),r=a,tt.push(r),ft()})))}))};t.CLSThresholds=D,t.FCPThresholds=L,t.FIDThresholds=mt,t.INPThresholds=H,t.LCPThresholds=nt,t.TTFBThresholds=it,t.onCLS=function(t,e){!function(t,e){e=e||{},M(h((function(){var n,r=d("CLS",0),i=0,a=[],o=function(t){t.forEach((function(t){if(!t.hadRecentInput){var e=a[0],n=a[a.length-1];i&&t.startTime-n.startTime<1e3&&t.startTime-e.startTime<5e3?(i+=t.value,a.push(t)):(i=t.value,a=[t])}})),i>r.value&&(r.value=i,r.entries=a,n())},c=l("layout-shift",o);c&&(n=m(t,r,D,e.reportAllChanges),v((function(){o(c.takeRecords()),n(!0)})),u((function(){i=0,r=d("CLS",0),n=m(t,r,D,e.reportAllChanges),p((function(){return n()}))})),setTimeout(n,0))})))}((function(e){var n=function(t){var e,n={};if(t.entries.length){var r=t.entries.reduce((function(t,e){return t&&t.value>e.value?t:e}));if(r&&r.sources&&r.sources.length){var a=(e=r.sources).find((function(t){return t.node&&1===t.node.nodeType}))||e[0];a&&(n={largestShiftTarget:o(a.node),largestShiftTime:r.startTime,largestShiftValue:r.value,largestShiftSource:a,largestShiftEntry:r,loadState:i(r.startTime)})}}return Object.assign(t,{attribution:n})}(e);t(n)}),e)},t.onFCP=function(t,e){M((function(e){var n=function(t){var e={timeToFirstByte:0,firstByteToFCP:t.value,loadState:i(s())};if(t.entries.length){var n=r(),a=t.entries[t.entries.length-1];if(n){var o=n.activationStart||0,c=Math.max(0,n.responseStart-o);e={timeToFirstByte:c,firstByteToFCP:t.value-c,loadState:i(t.entries[0].startTime),navigationEntry:n,fcpEntry:a}}}return Object.assign(t,{attribution:e})}(e);t(n)}),e)},t.onFID=function(t,e){pt((function(e){var n=function(t){var e=t.entries[0],n={eventTarget:o(e.target),eventType:e.name,eventTime:e.startTime,eventEntry:e,loadState:i(e.startTime)};return Object.assign(t,{attribution:n})}(e);t(n)}),e)},t.onINP=function(t,e){n||(n=l("long-animation-frame",K)),V((function(e){var n=function(t){var e=t.entries[0],n=_.get(e),r=e.processingStart,a=n.processingEnd,c=n.entries.sort((function(t,e){return t.processingStart-e.processingStart})),s=et(e.startTime,a),u=t.entries.find((function(t){return t.target})),f=u&&u.target||G.get(e.interactionId),d=[e.startTime+e.duration,a].concat(s.map((function(t){return t.startTime+t.duration}))),l=Math.max.apply(Math,d),m={interactionTarget:o(f),interactionTargetElement:f,interactionType:e.name.startsWith("key")?"keyboard":"pointer",interactionTime:e.startTime,nextPaintTime:l,processedEventEntries:c,longAnimationFrameEntries:s,inputDelay:r-e.startTime,processingDuration:a-r,presentationDelay:Math.max(l-a,0),loadState:i(e.startTime)};return Object.assign(t,{attribution:m})}(e);t(n)}),e)},t.onLCP=function(t,e){!function(t,e){e=e||{},C((function(){var n,r=b(),i=d("LCP"),a=function(t){e.reportAllChanges||(t=t.slice(-1)),t.forEach((function(t){t.startTime<r.firstHiddenTime&&(i.value=Math.max(t.startTime-f(),0),i.entries=[t],n())}))},o=l("largest-contentful-paint",a);if(o){n=m(t,i,nt,e.reportAllChanges);var c=h((function(){rt[i.id]||(a(o.takeRecords()),o.disconnect(),rt[i.id]=!0,n(!0))}));["keydown","click"].forEach((function(t){addEventListener(t,(function(){return N(c)}),{once:!0,capture:!0})})),v(c),u((function(r){i=d("LCP"),n=m(t,i,nt,e.reportAllChanges),p((function(){i.value=performance.now()-r.timeStamp,rt[i.id]=!0,n(!0)}))}))}}))}((function(e){var n=function(t){var e={timeToFirstByte:0,resourceLoadDelay:0,resourceLoadDuration:0,elementRenderDelay:t.value};if(t.entries.length){var n=r();if(n){var i=n.activationStart||0,a=t.entries[t.entries.length-1],c=a.url&&performance.getEntriesByType("resource").filter((function(t){return t.name===a.url}))[0],s=Math.max(0,n.responseStart-i),u=Math.max(s,c?(c.requestStart||c.startTime)-i:0),f=Math.max(u,c?c.responseEnd-i:0),d=Math.max(f,a.startTime-i);e={element:o(a.element),timeToFirstByte:s,resourceLoadDelay:u-s,resourceLoadDuration:f-u,elementRenderDelay:d-f,navigationEntry:n,lcpEntry:a},a.url&&(e.url=a.url),c&&(e.lcpResourceEntry=c)}}return Object.assign(t,{attribution:e})}(e);t(n)}),e)},t.onTTFB=function(t,e){ot((function(e){var n=function(t){var e={waitingDuration:0,cacheDuration:0,dnsDuration:0,connectionDuration:0,requestDuration:0};if(t.entries.length){var n=t.entries[0],r=n.activationStart||0,i=Math.max((n.workerStart||n.fetchStart)-r,0),a=Math.max(n.domainLookupStart-r,0),o=Math.max(n.connectStart-r,0),c=Math.max(n.connectEnd-r,0);e={waitingDuration:i,cacheDuration:a-i,dnsDuration:o-a,connectionDuration:c-o,requestDuration:t.value-c,navigationEntry:n}}return Object.assign(t,{attribution:e})}(e);t(n)}),e)}})); diff --git a/frontend-old/node_modules/web-vitals/dist/web-vitals.iife.js b/frontend-old/node_modules/web-vitals/dist/web-vitals.iife.js deleted file mode 100644 index 075dee8..0000000 --- a/frontend-old/node_modules/web-vitals/dist/web-vitals.iife.js +++ /dev/null @@ -1 +0,0 @@ -var webVitals=function(e){"use strict";var n,t,r,i,o,a=-1,c=function(e){addEventListener("pageshow",(function(n){n.persisted&&(a=n.timeStamp,e(n))}),!0)},u=function(){var e=self.performance&&performance.getEntriesByType&&performance.getEntriesByType("navigation")[0];if(e&&e.responseStart>0&&e.responseStart<performance.now())return e},s=function(){var e=u();return e&&e.activationStart||0},f=function(e,n){var t=u(),r="navigate";a>=0?r="back-forward-cache":t&&(document.prerendering||s()>0?r="prerender":document.wasDiscarded?r="restore":t.type&&(r=t.type.replace(/_/g,"-")));return{name:e,value:void 0===n?-1:n,rating:"good",delta:0,entries:[],id:"v4-".concat(Date.now(),"-").concat(Math.floor(8999999999999*Math.random())+1e12),navigationType:r}},d=function(e,n,t){try{if(PerformanceObserver.supportedEntryTypes.includes(e)){var r=new PerformanceObserver((function(e){Promise.resolve().then((function(){n(e.getEntries())}))}));return r.observe(Object.assign({type:e,buffered:!0},t||{})),r}}catch(e){}},l=function(e,n,t,r){var i,o;return function(a){n.value>=0&&(a||r)&&((o=n.value-(i||0))||void 0===i)&&(i=n.value,n.delta=o,n.rating=function(e,n){return e>n[1]?"poor":e>n[0]?"needs-improvement":"good"}(n.value,t),e(n))}},p=function(e){requestAnimationFrame((function(){return requestAnimationFrame((function(){return e()}))}))},v=function(e){document.addEventListener("visibilitychange",(function(){"hidden"===document.visibilityState&&e()}))},m=function(e){var n=!1;return function(){n||(e(),n=!0)}},h=-1,g=function(){return"hidden"!==document.visibilityState||document.prerendering?1/0:0},T=function(e){"hidden"===document.visibilityState&&h>-1&&(h="visibilitychange"===e.type?e.timeStamp:0,E())},y=function(){addEventListener("visibilitychange",T,!0),addEventListener("prerenderingchange",T,!0)},E=function(){removeEventListener("visibilitychange",T,!0),removeEventListener("prerenderingchange",T,!0)},C=function(){return h<0&&(h=g(),y(),c((function(){setTimeout((function(){h=g(),y()}),0)}))),{get firstHiddenTime(){return h}}},L=function(e){document.prerendering?addEventListener("prerenderingchange",(function(){return e()}),!0):e()},S=[1800,3e3],b=function(e,n){n=n||{},L((function(){var t,r=C(),i=f("FCP"),o=d("paint",(function(e){e.forEach((function(e){"first-contentful-paint"===e.name&&(o.disconnect(),e.startTime<r.firstHiddenTime&&(i.value=Math.max(e.startTime-s(),0),i.entries.push(e),t(!0)))}))}));o&&(t=l(e,i,S,n.reportAllChanges),c((function(r){i=f("FCP"),t=l(e,i,S,n.reportAllChanges),p((function(){i.value=performance.now()-r.timeStamp,t(!0)}))})))}))},w=[.1,.25],I=0,P=1/0,A=0,F=function(e){e.forEach((function(e){e.interactionId&&(P=Math.min(P,e.interactionId),A=Math.max(A,e.interactionId),I=A?(A-P)/7+1:0)}))},M=function(){return n?I:performance.interactionCount||0},k=function(){"interactionCount"in performance||n||(n=d("event",F,{type:"event",buffered:!0,durationThreshold:0}))},D=[],B=new Map,R=0,x=function(){var e=Math.min(D.length-1,Math.floor((M()-R)/50));return D[e]},H=[],N=function(e){if(H.forEach((function(n){return n(e)})),e.interactionId||"first-input"===e.entryType){var n=D[D.length-1],t=B.get(e.interactionId);if(t||D.length<10||e.duration>n.latency){if(t)e.duration>t.latency?(t.entries=[e],t.latency=e.duration):e.duration===t.latency&&e.startTime===t.entries[0].startTime&&t.entries.push(e);else{var r={id:e.interactionId,latency:e.duration,entries:[e]};B.set(r.id,r),D.push(r)}D.sort((function(e,n){return n.latency-e.latency})),D.length>10&&D.splice(10).forEach((function(e){return B.delete(e.id)}))}}},q=function(e){var n=self.requestIdleCallback||self.setTimeout,t=-1;return e=m(e),"hidden"===document.visibilityState?e():(t=n(e),v(e)),t},O=[200,500],j=[2500,4e3],V={},_=[800,1800],z=function e(n){document.prerendering?L((function(){return e(n)})):"complete"!==document.readyState?addEventListener("load",(function(){return e(n)}),!0):setTimeout(n,0)},G={passive:!0,capture:!0},J=new Date,K=function(e,n){t||(t=n,r=e,i=new Date,W(removeEventListener),Q())},Q=function(){if(r>=0&&r<i-J){var e={entryType:"first-input",name:t.type,target:t.target,cancelable:t.cancelable,startTime:t.timeStamp,processingStart:t.timeStamp+r};o.forEach((function(n){n(e)})),o=[]}},U=function(e){if(e.cancelable){var n=(e.timeStamp>1e12?new Date:performance.now())-e.timeStamp;"pointerdown"==e.type?function(e,n){var t=function(){K(e,n),i()},r=function(){i()},i=function(){removeEventListener("pointerup",t,G),removeEventListener("pointercancel",r,G)};addEventListener("pointerup",t,G),addEventListener("pointercancel",r,G)}(n,e):K(n,e)}},W=function(e){["mousedown","keydown","touchstart","pointerdown"].forEach((function(n){return e(n,U,G)}))},X=[100,300];return e.CLSThresholds=w,e.FCPThresholds=S,e.FIDThresholds=X,e.INPThresholds=O,e.LCPThresholds=j,e.TTFBThresholds=_,e.onCLS=function(e,n){n=n||{},b(m((function(){var t,r=f("CLS",0),i=0,o=[],a=function(e){e.forEach((function(e){if(!e.hadRecentInput){var n=o[0],t=o[o.length-1];i&&e.startTime-t.startTime<1e3&&e.startTime-n.startTime<5e3?(i+=e.value,o.push(e)):(i=e.value,o=[e])}})),i>r.value&&(r.value=i,r.entries=o,t())},u=d("layout-shift",a);u&&(t=l(e,r,w,n.reportAllChanges),v((function(){a(u.takeRecords()),t(!0)})),c((function(){i=0,r=f("CLS",0),t=l(e,r,w,n.reportAllChanges),p((function(){return t()}))})),setTimeout(t,0))})))},e.onFCP=b,e.onFID=function(e,n){n=n||{},L((function(){var i,a=C(),u=f("FID"),s=function(e){e.startTime<a.firstHiddenTime&&(u.value=e.processingStart-e.startTime,u.entries.push(e),i(!0))},p=function(e){e.forEach(s)},h=d("first-input",p);i=l(e,u,X,n.reportAllChanges),h&&(v(m((function(){p(h.takeRecords()),h.disconnect()}))),c((function(){var a;u=f("FID"),i=l(e,u,X,n.reportAllChanges),o=[],r=-1,t=null,W(addEventListener),a=s,o.push(a),Q()})))}))},e.onINP=function(e,n){"PerformanceEventTiming"in self&&"interactionId"in PerformanceEventTiming.prototype&&(n=n||{},L((function(){var t;k();var r,i=f("INP"),o=function(e){q((function(){e.forEach(N);var n=x();n&&n.latency!==i.value&&(i.value=n.latency,i.entries=n.entries,r())}))},a=d("event",o,{durationThreshold:null!==(t=n.durationThreshold)&&void 0!==t?t:40});r=l(e,i,O,n.reportAllChanges),a&&(a.observe({type:"first-input",buffered:!0}),v((function(){o(a.takeRecords()),r(!0)})),c((function(){R=M(),D.length=0,B.clear(),i=f("INP"),r=l(e,i,O,n.reportAllChanges)})))})))},e.onLCP=function(e,n){n=n||{},L((function(){var t,r=C(),i=f("LCP"),o=function(e){n.reportAllChanges||(e=e.slice(-1)),e.forEach((function(e){e.startTime<r.firstHiddenTime&&(i.value=Math.max(e.startTime-s(),0),i.entries=[e],t())}))},a=d("largest-contentful-paint",o);if(a){t=l(e,i,j,n.reportAllChanges);var u=m((function(){V[i.id]||(o(a.takeRecords()),a.disconnect(),V[i.id]=!0,t(!0))}));["keydown","click"].forEach((function(e){addEventListener(e,(function(){return q(u)}),{once:!0,capture:!0})})),v(u),c((function(r){i=f("LCP"),t=l(e,i,j,n.reportAllChanges),p((function(){i.value=performance.now()-r.timeStamp,V[i.id]=!0,t(!0)}))}))}}))},e.onTTFB=function(e,n){n=n||{};var t=f("TTFB"),r=l(e,t,_,n.reportAllChanges);z((function(){var i=u();i&&(t.value=Math.max(i.responseStart-s(),0),t.entries=[i],r(!0),c((function(){t=f("TTFB",0),(r=l(e,t,_,n.reportAllChanges))(!0)})))}))},e}({}); diff --git a/frontend-old/node_modules/web-vitals/dist/web-vitals.js b/frontend-old/node_modules/web-vitals/dist/web-vitals.js deleted file mode 100644 index 357cffe..0000000 --- a/frontend-old/node_modules/web-vitals/dist/web-vitals.js +++ /dev/null @@ -1 +0,0 @@ -var e,n,t,r,i,o=-1,a=function(e){addEventListener("pageshow",(function(n){n.persisted&&(o=n.timeStamp,e(n))}),!0)},c=function(){var e=self.performance&&performance.getEntriesByType&&performance.getEntriesByType("navigation")[0];if(e&&e.responseStart>0&&e.responseStart<performance.now())return e},u=function(){var e=c();return e&&e.activationStart||0},f=function(e,n){var t=c(),r="navigate";o>=0?r="back-forward-cache":t&&(document.prerendering||u()>0?r="prerender":document.wasDiscarded?r="restore":t.type&&(r=t.type.replace(/_/g,"-")));return{name:e,value:void 0===n?-1:n,rating:"good",delta:0,entries:[],id:"v4-".concat(Date.now(),"-").concat(Math.floor(8999999999999*Math.random())+1e12),navigationType:r}},s=function(e,n,t){try{if(PerformanceObserver.supportedEntryTypes.includes(e)){var r=new PerformanceObserver((function(e){Promise.resolve().then((function(){n(e.getEntries())}))}));return r.observe(Object.assign({type:e,buffered:!0},t||{})),r}}catch(e){}},d=function(e,n,t,r){var i,o;return function(a){n.value>=0&&(a||r)&&((o=n.value-(i||0))||void 0===i)&&(i=n.value,n.delta=o,n.rating=function(e,n){return e>n[1]?"poor":e>n[0]?"needs-improvement":"good"}(n.value,t),e(n))}},l=function(e){requestAnimationFrame((function(){return requestAnimationFrame((function(){return e()}))}))},p=function(e){document.addEventListener("visibilitychange",(function(){"hidden"===document.visibilityState&&e()}))},v=function(e){var n=!1;return function(){n||(e(),n=!0)}},m=-1,h=function(){return"hidden"!==document.visibilityState||document.prerendering?1/0:0},g=function(e){"hidden"===document.visibilityState&&m>-1&&(m="visibilitychange"===e.type?e.timeStamp:0,T())},y=function(){addEventListener("visibilitychange",g,!0),addEventListener("prerenderingchange",g,!0)},T=function(){removeEventListener("visibilitychange",g,!0),removeEventListener("prerenderingchange",g,!0)},E=function(){return m<0&&(m=h(),y(),a((function(){setTimeout((function(){m=h(),y()}),0)}))),{get firstHiddenTime(){return m}}},C=function(e){document.prerendering?addEventListener("prerenderingchange",(function(){return e()}),!0):e()},b=[1800,3e3],S=function(e,n){n=n||{},C((function(){var t,r=E(),i=f("FCP"),o=s("paint",(function(e){e.forEach((function(e){"first-contentful-paint"===e.name&&(o.disconnect(),e.startTime<r.firstHiddenTime&&(i.value=Math.max(e.startTime-u(),0),i.entries.push(e),t(!0)))}))}));o&&(t=d(e,i,b,n.reportAllChanges),a((function(r){i=f("FCP"),t=d(e,i,b,n.reportAllChanges),l((function(){i.value=performance.now()-r.timeStamp,t(!0)}))})))}))},L=[.1,.25],w=function(e,n){n=n||{},S(v((function(){var t,r=f("CLS",0),i=0,o=[],c=function(e){e.forEach((function(e){if(!e.hadRecentInput){var n=o[0],t=o[o.length-1];i&&e.startTime-t.startTime<1e3&&e.startTime-n.startTime<5e3?(i+=e.value,o.push(e)):(i=e.value,o=[e])}})),i>r.value&&(r.value=i,r.entries=o,t())},u=s("layout-shift",c);u&&(t=d(e,r,L,n.reportAllChanges),p((function(){c(u.takeRecords()),t(!0)})),a((function(){i=0,r=f("CLS",0),t=d(e,r,L,n.reportAllChanges),l((function(){return t()}))})),setTimeout(t,0))})))},A=0,I=1/0,P=0,M=function(e){e.forEach((function(e){e.interactionId&&(I=Math.min(I,e.interactionId),P=Math.max(P,e.interactionId),A=P?(P-I)/7+1:0)}))},k=function(){return e?A:performance.interactionCount||0},F=function(){"interactionCount"in performance||e||(e=s("event",M,{type:"event",buffered:!0,durationThreshold:0}))},D=[],x=new Map,R=0,B=function(){var e=Math.min(D.length-1,Math.floor((k()-R)/50));return D[e]},H=[],q=function(e){if(H.forEach((function(n){return n(e)})),e.interactionId||"first-input"===e.entryType){var n=D[D.length-1],t=x.get(e.interactionId);if(t||D.length<10||e.duration>n.latency){if(t)e.duration>t.latency?(t.entries=[e],t.latency=e.duration):e.duration===t.latency&&e.startTime===t.entries[0].startTime&&t.entries.push(e);else{var r={id:e.interactionId,latency:e.duration,entries:[e]};x.set(r.id,r),D.push(r)}D.sort((function(e,n){return n.latency-e.latency})),D.length>10&&D.splice(10).forEach((function(e){return x.delete(e.id)}))}}},O=function(e){var n=self.requestIdleCallback||self.setTimeout,t=-1;return e=v(e),"hidden"===document.visibilityState?e():(t=n(e),p(e)),t},N=[200,500],j=function(e,n){"PerformanceEventTiming"in self&&"interactionId"in PerformanceEventTiming.prototype&&(n=n||{},C((function(){var t;F();var r,i=f("INP"),o=function(e){O((function(){e.forEach(q);var n=B();n&&n.latency!==i.value&&(i.value=n.latency,i.entries=n.entries,r())}))},c=s("event",o,{durationThreshold:null!==(t=n.durationThreshold)&&void 0!==t?t:40});r=d(e,i,N,n.reportAllChanges),c&&(c.observe({type:"first-input",buffered:!0}),p((function(){o(c.takeRecords()),r(!0)})),a((function(){R=k(),D.length=0,x.clear(),i=f("INP"),r=d(e,i,N,n.reportAllChanges)})))})))},_=[2500,4e3],z={},G=function(e,n){n=n||{},C((function(){var t,r=E(),i=f("LCP"),o=function(e){n.reportAllChanges||(e=e.slice(-1)),e.forEach((function(e){e.startTime<r.firstHiddenTime&&(i.value=Math.max(e.startTime-u(),0),i.entries=[e],t())}))},c=s("largest-contentful-paint",o);if(c){t=d(e,i,_,n.reportAllChanges);var m=v((function(){z[i.id]||(o(c.takeRecords()),c.disconnect(),z[i.id]=!0,t(!0))}));["keydown","click"].forEach((function(e){addEventListener(e,(function(){return O(m)}),{once:!0,capture:!0})})),p(m),a((function(r){i=f("LCP"),t=d(e,i,_,n.reportAllChanges),l((function(){i.value=performance.now()-r.timeStamp,z[i.id]=!0,t(!0)}))}))}}))},J=[800,1800],K=function e(n){document.prerendering?C((function(){return e(n)})):"complete"!==document.readyState?addEventListener("load",(function(){return e(n)}),!0):setTimeout(n,0)},Q=function(e,n){n=n||{};var t=f("TTFB"),r=d(e,t,J,n.reportAllChanges);K((function(){var i=c();i&&(t.value=Math.max(i.responseStart-u(),0),t.entries=[i],r(!0),a((function(){t=f("TTFB",0),(r=d(e,t,J,n.reportAllChanges))(!0)})))}))},U={passive:!0,capture:!0},V=new Date,W=function(e,i){n||(n=i,t=e,r=new Date,Z(removeEventListener),X())},X=function(){if(t>=0&&t<r-V){var e={entryType:"first-input",name:n.type,target:n.target,cancelable:n.cancelable,startTime:n.timeStamp,processingStart:n.timeStamp+t};i.forEach((function(n){n(e)})),i=[]}},Y=function(e){if(e.cancelable){var n=(e.timeStamp>1e12?new Date:performance.now())-e.timeStamp;"pointerdown"==e.type?function(e,n){var t=function(){W(e,n),i()},r=function(){i()},i=function(){removeEventListener("pointerup",t,U),removeEventListener("pointercancel",r,U)};addEventListener("pointerup",t,U),addEventListener("pointercancel",r,U)}(n,e):W(n,e)}},Z=function(e){["mousedown","keydown","touchstart","pointerdown"].forEach((function(n){return e(n,Y,U)}))},$=[100,300],ee=function(e,r){r=r||{},C((function(){var o,c=E(),u=f("FID"),l=function(e){e.startTime<c.firstHiddenTime&&(u.value=e.processingStart-e.startTime,u.entries.push(e),o(!0))},m=function(e){e.forEach(l)},h=s("first-input",m);o=d(e,u,$,r.reportAllChanges),h&&(p(v((function(){m(h.takeRecords()),h.disconnect()}))),a((function(){var a;u=f("FID"),o=d(e,u,$,r.reportAllChanges),i=[],t=-1,n=null,Z(addEventListener),a=l,i.push(a),X()})))}))};export{L as CLSThresholds,b as FCPThresholds,$ as FIDThresholds,N as INPThresholds,_ as LCPThresholds,J as TTFBThresholds,w as onCLS,S as onFCP,ee as onFID,j as onINP,G as onLCP,Q as onTTFB}; diff --git a/frontend-old/node_modules/web-vitals/dist/web-vitals.umd.cjs b/frontend-old/node_modules/web-vitals/dist/web-vitals.umd.cjs deleted file mode 100644 index 1f40e68..0000000 --- a/frontend-old/node_modules/web-vitals/dist/web-vitals.umd.cjs +++ /dev/null @@ -1 +0,0 @@ -!function(e,n){"object"==typeof exports&&"undefined"!=typeof module?n(exports):"function"==typeof define&&define.amd?define(["exports"],n):n((e="undefined"!=typeof globalThis?globalThis:e||self).webVitals={})}(this,(function(e){"use strict";var n,t,r,i,o,a=-1,c=function(e){addEventListener("pageshow",(function(n){n.persisted&&(a=n.timeStamp,e(n))}),!0)},u=function(){var e=self.performance&&performance.getEntriesByType&&performance.getEntriesByType("navigation")[0];if(e&&e.responseStart>0&&e.responseStart<performance.now())return e},s=function(){var e=u();return e&&e.activationStart||0},f=function(e,n){var t=u(),r="navigate";a>=0?r="back-forward-cache":t&&(document.prerendering||s()>0?r="prerender":document.wasDiscarded?r="restore":t.type&&(r=t.type.replace(/_/g,"-")));return{name:e,value:void 0===n?-1:n,rating:"good",delta:0,entries:[],id:"v4-".concat(Date.now(),"-").concat(Math.floor(8999999999999*Math.random())+1e12),navigationType:r}},d=function(e,n,t){try{if(PerformanceObserver.supportedEntryTypes.includes(e)){var r=new PerformanceObserver((function(e){Promise.resolve().then((function(){n(e.getEntries())}))}));return r.observe(Object.assign({type:e,buffered:!0},t||{})),r}}catch(e){}},l=function(e,n,t,r){var i,o;return function(a){n.value>=0&&(a||r)&&((o=n.value-(i||0))||void 0===i)&&(i=n.value,n.delta=o,n.rating=function(e,n){return e>n[1]?"poor":e>n[0]?"needs-improvement":"good"}(n.value,t),e(n))}},p=function(e){requestAnimationFrame((function(){return requestAnimationFrame((function(){return e()}))}))},v=function(e){document.addEventListener("visibilitychange",(function(){"hidden"===document.visibilityState&&e()}))},m=function(e){var n=!1;return function(){n||(e(),n=!0)}},h=-1,g=function(){return"hidden"!==document.visibilityState||document.prerendering?1/0:0},T=function(e){"hidden"===document.visibilityState&&h>-1&&(h="visibilitychange"===e.type?e.timeStamp:0,E())},y=function(){addEventListener("visibilitychange",T,!0),addEventListener("prerenderingchange",T,!0)},E=function(){removeEventListener("visibilitychange",T,!0),removeEventListener("prerenderingchange",T,!0)},C=function(){return h<0&&(h=g(),y(),c((function(){setTimeout((function(){h=g(),y()}),0)}))),{get firstHiddenTime(){return h}}},b=function(e){document.prerendering?addEventListener("prerenderingchange",(function(){return e()}),!0):e()},L=[1800,3e3],S=function(e,n){n=n||{},b((function(){var t,r=C(),i=f("FCP"),o=d("paint",(function(e){e.forEach((function(e){"first-contentful-paint"===e.name&&(o.disconnect(),e.startTime<r.firstHiddenTime&&(i.value=Math.max(e.startTime-s(),0),i.entries.push(e),t(!0)))}))}));o&&(t=l(e,i,L,n.reportAllChanges),c((function(r){i=f("FCP"),t=l(e,i,L,n.reportAllChanges),p((function(){i.value=performance.now()-r.timeStamp,t(!0)}))})))}))},w=[.1,.25],I=0,P=1/0,A=0,F=function(e){e.forEach((function(e){e.interactionId&&(P=Math.min(P,e.interactionId),A=Math.max(A,e.interactionId),I=A?(A-P)/7+1:0)}))},M=function(){return n?I:performance.interactionCount||0},k=function(){"interactionCount"in performance||n||(n=d("event",F,{type:"event",buffered:!0,durationThreshold:0}))},D=[],x=new Map,B=0,R=function(){var e=Math.min(D.length-1,Math.floor((M()-B)/50));return D[e]},H=[],N=function(e){if(H.forEach((function(n){return n(e)})),e.interactionId||"first-input"===e.entryType){var n=D[D.length-1],t=x.get(e.interactionId);if(t||D.length<10||e.duration>n.latency){if(t)e.duration>t.latency?(t.entries=[e],t.latency=e.duration):e.duration===t.latency&&e.startTime===t.entries[0].startTime&&t.entries.push(e);else{var r={id:e.interactionId,latency:e.duration,entries:[e]};x.set(r.id,r),D.push(r)}D.sort((function(e,n){return n.latency-e.latency})),D.length>10&&D.splice(10).forEach((function(e){return x.delete(e.id)}))}}},q=function(e){var n=self.requestIdleCallback||self.setTimeout,t=-1;return e=m(e),"hidden"===document.visibilityState?e():(t=n(e),v(e)),t},O=[200,500],j=[2500,4e3],V={},_=[800,1800],z=function e(n){document.prerendering?b((function(){return e(n)})):"complete"!==document.readyState?addEventListener("load",(function(){return e(n)}),!0):setTimeout(n,0)},G={passive:!0,capture:!0},J=new Date,K=function(e,n){t||(t=n,r=e,i=new Date,W(removeEventListener),Q())},Q=function(){if(r>=0&&r<i-J){var e={entryType:"first-input",name:t.type,target:t.target,cancelable:t.cancelable,startTime:t.timeStamp,processingStart:t.timeStamp+r};o.forEach((function(n){n(e)})),o=[]}},U=function(e){if(e.cancelable){var n=(e.timeStamp>1e12?new Date:performance.now())-e.timeStamp;"pointerdown"==e.type?function(e,n){var t=function(){K(e,n),i()},r=function(){i()},i=function(){removeEventListener("pointerup",t,G),removeEventListener("pointercancel",r,G)};addEventListener("pointerup",t,G),addEventListener("pointercancel",r,G)}(n,e):K(n,e)}},W=function(e){["mousedown","keydown","touchstart","pointerdown"].forEach((function(n){return e(n,U,G)}))},X=[100,300];e.CLSThresholds=w,e.FCPThresholds=L,e.FIDThresholds=X,e.INPThresholds=O,e.LCPThresholds=j,e.TTFBThresholds=_,e.onCLS=function(e,n){n=n||{},S(m((function(){var t,r=f("CLS",0),i=0,o=[],a=function(e){e.forEach((function(e){if(!e.hadRecentInput){var n=o[0],t=o[o.length-1];i&&e.startTime-t.startTime<1e3&&e.startTime-n.startTime<5e3?(i+=e.value,o.push(e)):(i=e.value,o=[e])}})),i>r.value&&(r.value=i,r.entries=o,t())},u=d("layout-shift",a);u&&(t=l(e,r,w,n.reportAllChanges),v((function(){a(u.takeRecords()),t(!0)})),c((function(){i=0,r=f("CLS",0),t=l(e,r,w,n.reportAllChanges),p((function(){return t()}))})),setTimeout(t,0))})))},e.onFCP=S,e.onFID=function(e,n){n=n||{},b((function(){var i,a=C(),u=f("FID"),s=function(e){e.startTime<a.firstHiddenTime&&(u.value=e.processingStart-e.startTime,u.entries.push(e),i(!0))},p=function(e){e.forEach(s)},h=d("first-input",p);i=l(e,u,X,n.reportAllChanges),h&&(v(m((function(){p(h.takeRecords()),h.disconnect()}))),c((function(){var a;u=f("FID"),i=l(e,u,X,n.reportAllChanges),o=[],r=-1,t=null,W(addEventListener),a=s,o.push(a),Q()})))}))},e.onINP=function(e,n){"PerformanceEventTiming"in self&&"interactionId"in PerformanceEventTiming.prototype&&(n=n||{},b((function(){var t;k();var r,i=f("INP"),o=function(e){q((function(){e.forEach(N);var n=R();n&&n.latency!==i.value&&(i.value=n.latency,i.entries=n.entries,r())}))},a=d("event",o,{durationThreshold:null!==(t=n.durationThreshold)&&void 0!==t?t:40});r=l(e,i,O,n.reportAllChanges),a&&(a.observe({type:"first-input",buffered:!0}),v((function(){o(a.takeRecords()),r(!0)})),c((function(){B=M(),D.length=0,x.clear(),i=f("INP"),r=l(e,i,O,n.reportAllChanges)})))})))},e.onLCP=function(e,n){n=n||{},b((function(){var t,r=C(),i=f("LCP"),o=function(e){n.reportAllChanges||(e=e.slice(-1)),e.forEach((function(e){e.startTime<r.firstHiddenTime&&(i.value=Math.max(e.startTime-s(),0),i.entries=[e],t())}))},a=d("largest-contentful-paint",o);if(a){t=l(e,i,j,n.reportAllChanges);var u=m((function(){V[i.id]||(o(a.takeRecords()),a.disconnect(),V[i.id]=!0,t(!0))}));["keydown","click"].forEach((function(e){addEventListener(e,(function(){return q(u)}),{once:!0,capture:!0})})),v(u),c((function(r){i=f("LCP"),t=l(e,i,j,n.reportAllChanges),p((function(){i.value=performance.now()-r.timeStamp,V[i.id]=!0,t(!0)}))}))}}))},e.onTTFB=function(e,n){n=n||{};var t=f("TTFB"),r=l(e,t,_,n.reportAllChanges);z((function(){var i=u();i&&(t.value=Math.max(i.responseStart-s(),0),t.entries=[i],r(!0),c((function(){t=f("TTFB",0),(r=l(e,t,_,n.reportAllChanges))(!0)})))}))}})); diff --git a/frontend-old/node_modules/web-vitals/package.json b/frontend-old/node_modules/web-vitals/package.json deleted file mode 100644 index b36ff46..0000000 --- a/frontend-old/node_modules/web-vitals/package.json +++ /dev/null @@ -1,174 +0,0 @@ -{ - "name": "web-vitals", - "version": "4.2.4", - "description": "Easily measure performance metrics in JavaScript", - "type": "module", - "typings": "dist/modules/index.d.ts", - "main": "dist/web-vitals.umd.cjs", - "module": "dist/web-vitals.js", - "unpkg": "dist/web-vitals.iife.js", - "exports": { - ".": { - "types": "./dist/modules/index.d.ts", - "require": "./dist/web-vitals.umd.cjs", - "default": "./dist/web-vitals.js" - }, - "./attribution": { - "types": "./dist/modules/attribution/index.d.ts", - "require": "./dist/web-vitals.attribution.umd.cjs", - "default": "./dist/web-vitals.attribution.js" - }, - "./attribution.js": { - "types": "./dist/modules/attribution/index.d.ts", - "require": "./dist/web-vitals.attribution.umd.cjs", - "default": "./dist/web-vitals.attribution.js" - }, - "./onCLS.js": { - "types": "./dist/modules/onCLS.d.ts", - "default": "./dist/modules/onCLS.js" - }, - "./onFCP.js": { - "types": "./dist/modules/onFCP.d.ts", - "default": "./dist/modules/onFCP.js" - }, - "./onFID.js": { - "types": "./dist/modules/onFID.d.ts", - "default": "./dist/modules/onFID.js" - }, - "./onINP.js": { - "types": "./dist/modules/onINP.d.ts", - "default": "./dist/modules/onINP.js" - }, - "./onLCP.js": { - "types": "./dist/modules/onLCP.d.ts", - "default": "./dist/modules/onLCP.js" - }, - "./onTTFB.js": { - "types": "./dist/modules/onTTFB.d.ts", - "default": "./dist/modules/onTTFB.js" - }, - "./attribution/onCLS.js": { - "types": "./dist/modules/attribution/onCLS.d.ts", - "default": "./dist/modules/attribution/onCLS.js" - }, - "./attribution/onFCP.js": { - "types": "./dist/modules/attribution/onFCP.d.ts", - "default": "./dist/modules/attribution/onFCP.js" - }, - "./attribution/onFID.js": { - "types": "./dist/modules/attribution/onFID.d.ts", - "default": "./dist/modules/attribution/onFID.js" - }, - "./attribution/onINP.js": { - "types": "./dist/modules/attribution/onINP.d.ts", - "default": "./dist/modules/attribution/onINP.js" - }, - "./attribution/onLCP.js": { - "types": "./dist/modules/attribution/onLCP.d.ts", - "default": "./dist/modules/attribution/onLCP.js" - }, - "./attribution/onTTFB.js": { - "types": "./dist/modules/attribution/onTTFB.d.ts", - "default": "./dist/modules/attribution/onTTFB.js" - } - }, - "files": [ - "attribution.js", - "attribution.d.ts", - "dist", - "src" - ], - "scripts": { - "build": "run-s clean build:ts build:js", - "build:ts": "tsc -b", - "build:js": "rollup -c", - "clean": "rm -rf dist tsconfig.tsbuildinfo", - "dev": "run-p watch test:server", - "format": "prettier \"**/*.{cjs,css,html,js,json,md,ts,yml,yaml}\" --write --ignore-path .gitignore", - "format:check": "prettier \"**/*.{cjs,css,html,js,json,html,md,ts,yml,yaml}\" --check --ignore-path .gitignore", - "lint": "eslint \"*.js\" \"src/**/*.ts\" \"test/**/*.js\"", - "lint:fix": "eslint --fix \"*.js\" \"src/**/*.ts\" \"test/**/*.js\"", - "postversion": "git push --follow-tags", - "release:major": "npm version major -m 'Release v%s' && npm publish", - "release:minor": "npm version minor -m 'Release v%s' && npm publish", - "release:patch": "npm version patch -m 'Release v%s' && npm publish", - "test": "npm-run-all build test:unit -p -r test:e2e test:server", - "test:e2e": "wdio wdio.conf.cjs", - "test:server": "node test/server.js", - "test:unit": "node --test test/unit/*test.js", - "start": "run-s build:ts test:server watch", - "watch": "run-p watch:*", - "watch:ts": "tsc -b -w", - "watch:js": "rollup -c -w", - "version": "run-s build", - "prepare": "husky install" - }, - "keywords": [ - "crux", - "performance", - "metrics", - "Core Web Vitals", - "CLS", - "FCP", - "FID", - "INP", - "LCP", - "TTFB" - ], - "author": { - "name": "Philip Walton", - "email": "philip@philipwalton.com", - "url": "http://philipwalton.com" - }, - "license": "Apache-2.0", - "repository": { - "type": "git", - "url": "https://github.com/GoogleChrome/web-vitals.git" - }, - "bugs": { - "url": "https://github.com/GoogleChrome/web-vitals/issues" - }, - "husky": { - "hooks": { - "pre-commit": "npm run lint" - } - }, - "prettier": { - "arrowParens": "always", - "bracketSpacing": false, - "quoteProps": "preserve", - "singleQuote": true - }, - "devDependencies": { - "@babel/core": "^7.23.6", - "@babel/preset-env": "^7.23.6", - "@rollup/plugin-babel": "^6.0.4", - "@rollup/plugin-replace": "^5.0.5", - "@rollup/plugin-terser": "^0.4.4", - "@typescript-eslint/eslint-plugin": "^6.16.0", - "@typescript-eslint/parser": "^6.16.0", - "@wdio/cli": "^8.32.3", - "@wdio/local-runner": "^8.32.3", - "@wdio/mocha-framework": "^8.32.3", - "@wdio/spec-reporter": "^8.32.2", - "body-parser": "^1.20.2", - "chromedriver": "^122.0.4", - "eslint": "^8.56.0", - "express": "^4.18.2", - "fs-extra": "^11.2.0", - "husky": "^8.0.3", - "lint-staged": "^15.2.0", - "npm-run-all": "^4.1.5", - "nunjucks": "^3.2.4", - "prettier": "^3.1.1", - "rollup": "^4.9.1", - "selenium-standalone": "^9.3.1", - "typescript": "^5.3.3", - "wdio-chromedriver-service": "^8.1.1", - "yargs": "^17.7.2" - }, - "lint-staged": { - "**/*.{js,ts}": "eslint --fix --ignore-path .gitignore", - "**/*.{cjs,css,html,js,json,html,md,ts,yml,yaml}": "prettier --write --ignore-path .gitignore" - } -} diff --git a/frontend-old/node_modules/web-vitals/src/attribution/deprecated.ts b/frontend-old/node_modules/web-vitals/src/attribution/deprecated.ts deleted file mode 100644 index 826ebfc..0000000 --- a/frontend-old/node_modules/web-vitals/src/attribution/deprecated.ts +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright 2024 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -export { - /** - * @deprecated Use `onINP()` instead. - */ - onFID, -} from './onFID.js'; - -export {FIDThresholds} from '../onFID.js'; - -export * from '../types.js'; diff --git a/frontend-old/node_modules/web-vitals/src/attribution/index.ts b/frontend-old/node_modules/web-vitals/src/attribution/index.ts deleted file mode 100644 index c036282..0000000 --- a/frontend-old/node_modules/web-vitals/src/attribution/index.ts +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 2022 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -export {onCLS} from './onCLS.js'; -export {onFCP} from './onFCP.js'; -export {onINP} from './onINP.js'; -export {onLCP} from './onLCP.js'; -export {onTTFB} from './onTTFB.js'; - -export {CLSThresholds} from '../onCLS.js'; -export {FCPThresholds} from '../onFCP.js'; -export {INPThresholds} from '../onINP.js'; -export {LCPThresholds} from '../onLCP.js'; -export {TTFBThresholds} from '../onTTFB.js'; - -export * from './deprecated.js'; -export * from '../types.js'; diff --git a/frontend-old/node_modules/web-vitals/src/attribution/onCLS.ts b/frontend-old/node_modules/web-vitals/src/attribution/onCLS.ts deleted file mode 100644 index 52e2bee..0000000 --- a/frontend-old/node_modules/web-vitals/src/attribution/onCLS.ts +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright 2022 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import {getLoadState} from '../lib/getLoadState.js'; -import {getSelector} from '../lib/getSelector.js'; -import {onCLS as unattributedOnCLS} from '../onCLS.js'; -import { - CLSAttribution, - CLSMetric, - CLSMetricWithAttribution, - ReportOpts, -} from '../types.js'; - -const getLargestLayoutShiftEntry = (entries: LayoutShift[]) => { - return entries.reduce((a, b) => (a && a.value > b.value ? a : b)); -}; - -const getLargestLayoutShiftSource = (sources: LayoutShiftAttribution[]) => { - return sources.find((s) => s.node && s.node.nodeType === 1) || sources[0]; -}; - -const attributeCLS = (metric: CLSMetric): CLSMetricWithAttribution => { - // Use an empty object if no other attribution has been set. - let attribution: CLSAttribution = {}; - - if (metric.entries.length) { - const largestEntry = getLargestLayoutShiftEntry(metric.entries); - if (largestEntry && largestEntry.sources && largestEntry.sources.length) { - const largestSource = getLargestLayoutShiftSource(largestEntry.sources); - if (largestSource) { - attribution = { - largestShiftTarget: getSelector(largestSource.node), - largestShiftTime: largestEntry.startTime, - largestShiftValue: largestEntry.value, - largestShiftSource: largestSource, - largestShiftEntry: largestEntry, - loadState: getLoadState(largestEntry.startTime), - }; - } - } - } - - // Use Object.assign to set property to keep tsc happy. - const metricWithAttribution: CLSMetricWithAttribution = Object.assign( - metric, - {attribution}, - ); - return metricWithAttribution; -}; - -/** - * Calculates the [CLS](https://web.dev/articles/cls) value for the current page and - * calls the `callback` function once the value is ready to be reported, along - * with all `layout-shift` performance entries that were used in the metric - * value calculation. The reported value is a `double` (corresponding to a - * [layout shift score](https://web.dev/articles/cls#layout_shift_score)). - * - * If the `reportAllChanges` configuration option is set to `true`, the - * `callback` function will be called as soon as the value is initially - * determined as well as any time the value changes throughout the page - * lifespan. - * - * _**Important:** CLS should be continually monitored for changes throughout - * the entire lifespan of a page—including if the user returns to the page after - * it's been hidden/backgrounded. However, since browsers often [will not fire - * additional callbacks once the user has backgrounded a - * page](https://developer.chrome.com/blog/page-lifecycle-api/#advice-hidden), - * `callback` is always called when the page's visibility state changes to - * hidden. As a result, the `callback` function might be called multiple times - * during the same page load._ - */ -export const onCLS = ( - onReport: (metric: CLSMetricWithAttribution) => void, - opts?: ReportOpts, -) => { - unattributedOnCLS((metric: CLSMetric) => { - const metricWithAttribution = attributeCLS(metric); - onReport(metricWithAttribution); - }, opts); -}; diff --git a/frontend-old/node_modules/web-vitals/src/attribution/onFCP.ts b/frontend-old/node_modules/web-vitals/src/attribution/onFCP.ts deleted file mode 100644 index 079bf91..0000000 --- a/frontend-old/node_modules/web-vitals/src/attribution/onFCP.ts +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright 2022 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import {getBFCacheRestoreTime} from '../lib/bfcache.js'; -import {getLoadState} from '../lib/getLoadState.js'; -import {getNavigationEntry} from '../lib/getNavigationEntry.js'; -import {onFCP as unattributedOnFCP} from '../onFCP.js'; -import { - FCPAttribution, - FCPMetric, - FCPMetricWithAttribution, - ReportOpts, -} from '../types.js'; - -const attributeFCP = (metric: FCPMetric): FCPMetricWithAttribution => { - // Use a default object if no other attribution has been set. - let attribution: FCPAttribution = { - timeToFirstByte: 0, - firstByteToFCP: metric.value, - loadState: getLoadState(getBFCacheRestoreTime()), - }; - - if (metric.entries.length) { - const navigationEntry = getNavigationEntry(); - const fcpEntry = metric.entries[metric.entries.length - 1]; - - if (navigationEntry) { - const activationStart = navigationEntry.activationStart || 0; - const ttfb = Math.max(0, navigationEntry.responseStart - activationStart); - - attribution = { - timeToFirstByte: ttfb, - firstByteToFCP: metric.value - ttfb, - loadState: getLoadState(metric.entries[0].startTime), - navigationEntry, - fcpEntry, - }; - } - } - - // Use Object.assign to set property to keep tsc happy. - const metricWithAttribution: FCPMetricWithAttribution = Object.assign( - metric, - {attribution}, - ); - return metricWithAttribution; -}; - -/** - * Calculates the [FCP](https://web.dev/articles/fcp) value for the current page and - * calls the `callback` function once the value is ready, along with the - * relevant `paint` performance entry used to determine the value. The reported - * value is a `DOMHighResTimeStamp`. - */ -export const onFCP = ( - onReport: (metric: FCPMetricWithAttribution) => void, - opts?: ReportOpts, -) => { - unattributedOnFCP((metric: FCPMetric) => { - const metricWithAttribution = attributeFCP(metric); - onReport(metricWithAttribution); - }, opts); -}; diff --git a/frontend-old/node_modules/web-vitals/src/attribution/onFID.ts b/frontend-old/node_modules/web-vitals/src/attribution/onFID.ts deleted file mode 100644 index ed56142..0000000 --- a/frontend-old/node_modules/web-vitals/src/attribution/onFID.ts +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2022 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import {getLoadState} from '../lib/getLoadState.js'; -import {getSelector} from '../lib/getSelector.js'; -import {onFID as unattributedOnFID} from '../onFID.js'; -import { - FIDAttribution, - FIDMetric, - FIDMetricWithAttribution, - ReportOpts, -} from '../types.js'; - -const attributeFID = (metric: FIDMetric): FIDMetricWithAttribution => { - const fidEntry = metric.entries[0]; - const attribution: FIDAttribution = { - eventTarget: getSelector(fidEntry.target), - eventType: fidEntry.name, - eventTime: fidEntry.startTime, - eventEntry: fidEntry, - loadState: getLoadState(fidEntry.startTime), - }; - - // Use Object.assign to set property to keep tsc happy. - const metricWithAttribution: FIDMetricWithAttribution = Object.assign( - metric, - {attribution}, - ); - return metricWithAttribution; -}; - -/** - * Calculates the [FID](https://web.dev/articles/fid) value for the current page and - * calls the `callback` function once the value is ready, along with the - * relevant `first-input` performance entry used to determine the value. The - * reported value is a `DOMHighResTimeStamp`. - * - * _**Important:** since FID is only reported after the user interacts with the - * page, it's possible that it will not be reported for some page loads._ - */ -export const onFID = ( - onReport: (metric: FIDMetricWithAttribution) => void, - opts?: ReportOpts, -) => { - unattributedOnFID((metric: FIDMetric) => { - const metricWithAttribution = attributeFID(metric); - onReport(metricWithAttribution); - }, opts); -}; diff --git a/frontend-old/node_modules/web-vitals/src/attribution/onINP.ts b/frontend-old/node_modules/web-vitals/src/attribution/onINP.ts deleted file mode 100644 index 0986765..0000000 --- a/frontend-old/node_modules/web-vitals/src/attribution/onINP.ts +++ /dev/null @@ -1,338 +0,0 @@ -/* - * Copyright 2022 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import {getLoadState} from '../lib/getLoadState.js'; -import {getSelector} from '../lib/getSelector.js'; -import { - longestInteractionList, - entryPreProcessingCallbacks, - longestInteractionMap, -} from '../lib/interactions.js'; -import {observe} from '../lib/observe.js'; -import {whenIdle} from '../lib/whenIdle.js'; -import {onINP as unattributedOnINP} from '../onINP.js'; -import { - INPAttribution, - INPMetric, - INPMetricWithAttribution, - ReportOpts, -} from '../types.js'; - -interface pendingEntriesGroup { - startTime: DOMHighResTimeStamp; - processingStart: DOMHighResTimeStamp; - processingEnd: DOMHighResTimeStamp; - renderTime: DOMHighResTimeStamp; - entries: PerformanceEventTiming[]; -} - -// The maximum number of previous frames for which data is kept. -// Storing data about previous frames is necessary to handle cases where event -// and LoAF entries are dispatched out of order, and so a buffer of previous -// frame data is needed to determine various bits of INP attribution once all -// the frame-related data has come in. -// In most cases this out-of-order data is only off by a frame or two, so -// keeping the most recent 50 should be more than sufficient. -const MAX_PREVIOUS_FRAMES = 50; - -// A PerformanceObserver, observing new `long-animation-frame` entries. -// If this variable is defined it means the browser supports LoAF. -let loafObserver: PerformanceObserver | undefined; - -// A list of LoAF entries that have been dispatched and could potentially -// intersect with the INP candidate interaction. Note that periodically this -// list is cleaned up and entries that are known to not match INP are removed. -let pendingLoAFs: PerformanceLongAnimationFrameTiming[] = []; - -// An array of groups of all the event timing entries that occurred within a -// particular frame. Note that periodically this array is cleaned up and entries -// that are known to not match INP are removed. -let pendingEntriesGroups: pendingEntriesGroup[] = []; - -// The `processingEnd` time of most recently-processed event, chronologically. -let latestProcessingEnd: number = 0; - -// A WeakMap to look up the event-timing-entries group of a given entry. -// Note that this only maps from "important" entries: either the first input or -// those with an `interactionId`. -const entryToEntriesGroupMap: WeakMap< - PerformanceEventTiming, - pendingEntriesGroup -> = new WeakMap(); - -// A mapping of interactionIds to the target Node. -export const interactionTargetMap: Map<number, Node> = new Map(); - -// A reference to the idle task used to clean up entries from the above -// variables. If the value is -1 it means no task is queue, and if it's -// greater than -1 the value corresponds to the idle callback handle. -let idleHandle: number = -1; - -/** - * Adds new LoAF entries to the `pendingLoAFs` list. - */ -const handleLoAFEntries = (entries: PerformanceLongAnimationFrameTiming[]) => { - pendingLoAFs = pendingLoAFs.concat(entries); - queueCleanup(); -}; - -// Get a reference to the interaction target element in case it's removed -// from the DOM later. -const saveInteractionTarget = (entry: PerformanceEventTiming) => { - if ( - entry.interactionId && - entry.target && - !interactionTargetMap.has(entry.interactionId) - ) { - interactionTargetMap.set(entry.interactionId, entry.target); - } -}; - -/** - * Groups entries that were presented within the same animation frame by - * a common `renderTime`. This function works by referencing - * `pendingEntriesGroups` and using an existing render time if one is found - * (otherwise creating a new one). This function also adds all interaction - * entries to an `entryToRenderTimeMap` WeakMap so that the "grouped" entries - * can be looked up later. - */ -const groupEntriesByRenderTime = (entry: PerformanceEventTiming) => { - const renderTime = entry.startTime + entry.duration; - let group; - - latestProcessingEnd = Math.max(latestProcessingEnd, entry.processingEnd); - - // Iterate over all previous render times in reverse order to find a match. - // Go in reverse since the most likely match will be at the end. - for (let i = pendingEntriesGroups.length - 1; i >= 0; i--) { - const potentialGroup = pendingEntriesGroups[i]; - - // If a group's render time is within 8ms of the entry's render time, - // assume they were part of the same frame and add it to the group. - if (Math.abs(renderTime - potentialGroup.renderTime) <= 8) { - group = potentialGroup; - group.startTime = Math.min(entry.startTime, group.startTime); - group.processingStart = Math.min( - entry.processingStart, - group.processingStart, - ); - group.processingEnd = Math.max(entry.processingEnd, group.processingEnd); - group.entries.push(entry); - - break; - } - } - - // If there was no matching group, assume this is a new frame. - if (!group) { - group = { - startTime: entry.startTime, - processingStart: entry.processingStart, - processingEnd: entry.processingEnd, - renderTime, - entries: [entry], - }; - - pendingEntriesGroups.push(group); - } - - // Store the grouped render time for this entry for reference later. - if (entry.interactionId || entry.entryType === 'first-input') { - entryToEntriesGroupMap.set(entry, group); - } - - queueCleanup(); -}; - -const queueCleanup = () => { - // Queue cleanup of entries that are not part of any INP candidates. - if (idleHandle < 0) { - idleHandle = whenIdle(cleanupEntries); - } -}; - -const cleanupEntries = () => { - // Delete any stored interaction target elements if they're not part of one - // of the 10 longest interactions. - if (interactionTargetMap.size > 10) { - interactionTargetMap.forEach((_, key) => { - if (!longestInteractionMap.has(key)) { - interactionTargetMap.delete(key); - } - }); - } - - // Keep all render times that are part of a pending INP candidate or - // that occurred within the 50 most recently-dispatched groups of events. - const longestInteractionGroups = longestInteractionList.map((i) => { - return entryToEntriesGroupMap.get(i.entries[0]); - }); - const minIndex = pendingEntriesGroups.length - MAX_PREVIOUS_FRAMES; - pendingEntriesGroups = pendingEntriesGroups.filter((group, index) => { - if (index >= minIndex) return true; - return longestInteractionGroups.includes(group); - }); - - // Keep all pending LoAF entries that either: - // 1) intersect with entries in the newly cleaned up `pendingEntriesGroups` - // 2) occur after the most recently-processed event entry (for up to MAX_PREVIOUS_FRAMES) - const loafsToKeep: Set<PerformanceLongAnimationFrameTiming> = new Set(); - for (let i = 0; i < pendingEntriesGroups.length; i++) { - const group = pendingEntriesGroups[i]; - getIntersectingLoAFs(group.startTime, group.processingEnd).forEach( - (loaf) => { - loafsToKeep.add(loaf); - }, - ); - } - const prevFrameIndexCutoff = pendingLoAFs.length - 1 - MAX_PREVIOUS_FRAMES; - // Filter `pendingLoAFs` to preserve LoAF order. - pendingLoAFs = pendingLoAFs.filter((loaf, index) => { - if (loaf.startTime > latestProcessingEnd && index > prevFrameIndexCutoff) { - return true; - } - - return loafsToKeep.has(loaf); - }); - - // Reset the idle callback handle so it can be queued again. - idleHandle = -1; -}; - -entryPreProcessingCallbacks.push( - saveInteractionTarget, - groupEntriesByRenderTime, -); - -const getIntersectingLoAFs = ( - start: DOMHighResTimeStamp, - end: DOMHighResTimeStamp, -) => { - const intersectingLoAFs = []; - - for (let i = 0, loaf; (loaf = pendingLoAFs[i]); i++) { - // If the LoAF ends before the given start time, ignore it. - if (loaf.startTime + loaf.duration < start) continue; - - // If the LoAF starts after the given end time, ignore it and all - // subsequent pending LoAFs (because they're in time order). - if (loaf.startTime > end) break; - - // Still here? If so this LoAF intersects with the interaction. - intersectingLoAFs.push(loaf); - } - return intersectingLoAFs; -}; - -const attributeINP = (metric: INPMetric): INPMetricWithAttribution => { - const firstEntry = metric.entries[0]; - const group = entryToEntriesGroupMap.get(firstEntry)!; - - const processingStart = firstEntry.processingStart; - const processingEnd = group.processingEnd; - - // Sort the entries in processing time order. - const processedEventEntries = group.entries.sort((a, b) => { - return a.processingStart - b.processingStart; - }); - - const longAnimationFrameEntries: PerformanceLongAnimationFrameTiming[] = - getIntersectingLoAFs(firstEntry.startTime, processingEnd); - - // The first interaction entry may not have a target defined, so use the - // first one found in the entry list. - // TODO: when the following bug is fixed just use `firstInteractionEntry`. - // https://bugs.chromium.org/p/chromium/issues/detail?id=1367329 - // As a fallback, also check the interactionTargetMap (to account for - // cases where the element is removed from the DOM before reporting happens). - const firstEntryWithTarget = metric.entries.find((entry) => entry.target); - const interactionTargetElement = - (firstEntryWithTarget && firstEntryWithTarget.target) || - interactionTargetMap.get(firstEntry.interactionId); - - // Since entry durations are rounded to the nearest 8ms, we need to clamp - // the `nextPaintTime` value to be higher than the `processingEnd` or - // end time of any LoAF entry. - const nextPaintTimeCandidates = [ - firstEntry.startTime + firstEntry.duration, - processingEnd, - ].concat( - longAnimationFrameEntries.map((loaf) => loaf.startTime + loaf.duration), - ); - - const nextPaintTime = Math.max.apply(Math, nextPaintTimeCandidates); - - const attribution: INPAttribution = { - interactionTarget: getSelector(interactionTargetElement), - interactionTargetElement: interactionTargetElement, - interactionType: firstEntry.name.startsWith('key') ? 'keyboard' : 'pointer', - interactionTime: firstEntry.startTime, - nextPaintTime: nextPaintTime, - processedEventEntries: processedEventEntries, - longAnimationFrameEntries: longAnimationFrameEntries, - inputDelay: processingStart - firstEntry.startTime, - processingDuration: processingEnd - processingStart, - presentationDelay: Math.max(nextPaintTime - processingEnd, 0), - loadState: getLoadState(firstEntry.startTime), - }; - - // Use Object.assign to set property to keep tsc happy. - const metricWithAttribution: INPMetricWithAttribution = Object.assign( - metric, - {attribution}, - ); - return metricWithAttribution; -}; - -/** - * Calculates the [INP](https://web.dev/articles/inp) value for the current - * page and calls the `callback` function once the value is ready, along with - * the `event` performance entries reported for that interaction. The reported - * value is a `DOMHighResTimeStamp`. - * - * A custom `durationThreshold` configuration option can optionally be passed to - * control what `event-timing` entries are considered for INP reporting. The - * default threshold is `40`, which means INP scores of less than 40 are - * reported as 0. Note that this will not affect your 75th percentile INP value - * unless that value is also less than 40 (well below the recommended - * [good](https://web.dev/articles/inp#what_is_a_good_inp_score) threshold). - * - * If the `reportAllChanges` configuration option is set to `true`, the - * `callback` function will be called as soon as the value is initially - * determined as well as any time the value changes throughout the page - * lifespan. - * - * _**Important:** INP should be continually monitored for changes throughout - * the entire lifespan of a page—including if the user returns to the page after - * it's been hidden/backgrounded. However, since browsers often [will not fire - * additional callbacks once the user has backgrounded a - * page](https://developer.chrome.com/blog/page-lifecycle-api/#advice-hidden), - * `callback` is always called when the page's visibility state changes to - * hidden. As a result, the `callback` function might be called multiple times - * during the same page load._ - */ -export const onINP = ( - onReport: (metric: INPMetricWithAttribution) => void, - opts?: ReportOpts, -) => { - if (!loafObserver) { - loafObserver = observe('long-animation-frame', handleLoAFEntries); - } - unattributedOnINP((metric: INPMetric) => { - const metricWithAttribution = attributeINP(metric); - onReport(metricWithAttribution); - }, opts); -}; diff --git a/frontend-old/node_modules/web-vitals/src/attribution/onLCP.ts b/frontend-old/node_modules/web-vitals/src/attribution/onLCP.ts deleted file mode 100644 index 285f319..0000000 --- a/frontend-old/node_modules/web-vitals/src/attribution/onLCP.ts +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright 2022 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import {getNavigationEntry} from '../lib/getNavigationEntry.js'; -import {getSelector} from '../lib/getSelector.js'; -import {onLCP as unattributedOnLCP} from '../onLCP.js'; -import { - LCPAttribution, - LCPMetric, - LCPMetricWithAttribution, - ReportOpts, -} from '../types.js'; - -const attributeLCP = (metric: LCPMetric): LCPMetricWithAttribution => { - // Use a default object if no other attribution has been set. - let attribution: LCPAttribution = { - timeToFirstByte: 0, - resourceLoadDelay: 0, - resourceLoadDuration: 0, - elementRenderDelay: metric.value, - }; - - if (metric.entries.length) { - const navigationEntry = getNavigationEntry(); - if (navigationEntry) { - const activationStart = navigationEntry.activationStart || 0; - const lcpEntry = metric.entries[metric.entries.length - 1]; - const lcpResourceEntry = - lcpEntry.url && - performance - .getEntriesByType('resource') - .filter((e) => e.name === lcpEntry.url)[0]; - - const ttfb = Math.max(0, navigationEntry.responseStart - activationStart); - - const lcpRequestStart = Math.max( - ttfb, - // Prefer `requestStart` (if TOA is set), otherwise use `startTime`. - lcpResourceEntry - ? (lcpResourceEntry.requestStart || lcpResourceEntry.startTime) - - activationStart - : 0, - ); - const lcpResponseEnd = Math.max( - lcpRequestStart, - lcpResourceEntry ? lcpResourceEntry.responseEnd - activationStart : 0, - ); - const lcpRenderTime = Math.max( - lcpResponseEnd, - lcpEntry.startTime - activationStart, - ); - - attribution = { - element: getSelector(lcpEntry.element), - timeToFirstByte: ttfb, - resourceLoadDelay: lcpRequestStart - ttfb, - resourceLoadDuration: lcpResponseEnd - lcpRequestStart, - elementRenderDelay: lcpRenderTime - lcpResponseEnd, - navigationEntry, - lcpEntry, - }; - - // Only attribution the URL and resource entry if they exist. - if (lcpEntry.url) { - attribution.url = lcpEntry.url; - } - if (lcpResourceEntry) { - attribution.lcpResourceEntry = lcpResourceEntry; - } - } - } - - // Use Object.assign to set property to keep tsc happy. - const metricWithAttribution: LCPMetricWithAttribution = Object.assign( - metric, - {attribution}, - ); - return metricWithAttribution; -}; - -/** - * Calculates the [LCP](https://web.dev/articles/lcp) value for the current page and - * calls the `callback` function once the value is ready (along with the - * relevant `largest-contentful-paint` performance entry used to determine the - * value). The reported value is a `DOMHighResTimeStamp`. - * - * If the `reportAllChanges` configuration option is set to `true`, the - * `callback` function will be called any time a new `largest-contentful-paint` - * performance entry is dispatched, or once the final value of the metric has - * been determined. - */ -export const onLCP = ( - onReport: (metric: LCPMetricWithAttribution) => void, - opts?: ReportOpts, -) => { - unattributedOnLCP((metric: LCPMetric) => { - const metricWithAttribution = attributeLCP(metric); - onReport(metricWithAttribution); - }, opts); -}; diff --git a/frontend-old/node_modules/web-vitals/src/attribution/onTTFB.ts b/frontend-old/node_modules/web-vitals/src/attribution/onTTFB.ts deleted file mode 100644 index 1cfd74b..0000000 --- a/frontend-old/node_modules/web-vitals/src/attribution/onTTFB.ts +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright 2022 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import {onTTFB as unattributedOnTTFB} from '../onTTFB.js'; -import { - TTFBMetric, - TTFBMetricWithAttribution, - ReportOpts, - TTFBAttribution, -} from '../types.js'; - -const attributeTTFB = (metric: TTFBMetric): TTFBMetricWithAttribution => { - // Use a default object if no other attribution has been set. - let attribution: TTFBAttribution = { - waitingDuration: 0, - cacheDuration: 0, - dnsDuration: 0, - connectionDuration: 0, - requestDuration: 0, - }; - - if (metric.entries.length) { - const navigationEntry = metric.entries[0]; - const activationStart = navigationEntry.activationStart || 0; - - // Measure from workerStart or fetchStart so any service worker startup - // time is included in cacheDuration (which also includes other sw time - // anyway, that cannot be accurately split out cross-browser). - const waitEnd = Math.max( - (navigationEntry.workerStart || navigationEntry.fetchStart) - - activationStart, - 0, - ); - const dnsStart = Math.max( - navigationEntry.domainLookupStart - activationStart, - 0, - ); - const connectStart = Math.max( - navigationEntry.connectStart - activationStart, - 0, - ); - const connectEnd = Math.max( - navigationEntry.connectEnd - activationStart, - 0, - ); - - attribution = { - waitingDuration: waitEnd, - cacheDuration: dnsStart - waitEnd, - // dnsEnd usually equals connectStart but use connectStart over dnsEnd - // for dnsDuration in case there ever is a gap. - dnsDuration: connectStart - dnsStart, - connectionDuration: connectEnd - connectStart, - // There is often a gap between connectEnd and requestStart. Attribute - // that to requestDuration so connectionDuration remains 0 for - // service worker controlled requests were connectStart and connectEnd - // are the same. - requestDuration: metric.value - connectEnd, - navigationEntry: navigationEntry, - }; - } - - // Use Object.assign to set property to keep tsc happy. - const metricWithAttribution: TTFBMetricWithAttribution = Object.assign( - metric, - {attribution}, - ); - return metricWithAttribution; -}; - -/** - * Calculates the [TTFB](https://web.dev/articles/ttfb) value for the - * current page and calls the `callback` function once the page has loaded, - * along with the relevant `navigation` performance entry used to determine the - * value. The reported value is a `DOMHighResTimeStamp`. - * - * Note, this function waits until after the page is loaded to call `callback` - * in order to ensure all properties of the `navigation` entry are populated. - * This is useful if you want to report on other metrics exposed by the - * [Navigation Timing API](https://w3c.github.io/navigation-timing/). For - * example, the TTFB metric starts from the page's [time - * origin](https://www.w3.org/TR/hr-time-2/#sec-time-origin), which means it - * includes time spent on DNS lookup, connection negotiation, network latency, - * and server processing time. - */ -export const onTTFB = ( - onReport: (metric: TTFBMetricWithAttribution) => void, - opts?: ReportOpts, -) => { - unattributedOnTTFB((metric: TTFBMetric) => { - const metricWithAttribution = attributeTTFB(metric); - onReport(metricWithAttribution); - }, opts); -}; diff --git a/frontend-old/node_modules/web-vitals/src/deprecated.ts b/frontend-old/node_modules/web-vitals/src/deprecated.ts deleted file mode 100644 index 1acc67e..0000000 --- a/frontend-old/node_modules/web-vitals/src/deprecated.ts +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright 2022 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -export { - /** - * @deprecated Use `onINP()` instead. - */ - onFID, - FIDThresholds, -} from './onFID.js'; diff --git a/frontend-old/node_modules/web-vitals/src/index.ts b/frontend-old/node_modules/web-vitals/src/index.ts deleted file mode 100644 index 6c5dc45..0000000 --- a/frontend-old/node_modules/web-vitals/src/index.ts +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright 2020 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -export {onCLS, CLSThresholds} from './onCLS.js'; -export {onFCP, FCPThresholds} from './onFCP.js'; -export {onINP, INPThresholds} from './onINP.js'; -export {onLCP, LCPThresholds} from './onLCP.js'; -export {onTTFB, TTFBThresholds} from './onTTFB.js'; - -export * from './deprecated.js'; -export * from './types.js'; diff --git a/frontend-old/node_modules/web-vitals/src/lib/bfcache.ts b/frontend-old/node_modules/web-vitals/src/lib/bfcache.ts deleted file mode 100644 index 647b731..0000000 --- a/frontend-old/node_modules/web-vitals/src/lib/bfcache.ts +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2020 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -interface onBFCacheRestoreCallback { - (event: PageTransitionEvent): void; -} - -let bfcacheRestoreTime = -1; - -export const getBFCacheRestoreTime = () => bfcacheRestoreTime; - -export const onBFCacheRestore = (cb: onBFCacheRestoreCallback) => { - addEventListener( - 'pageshow', - (event) => { - if (event.persisted) { - bfcacheRestoreTime = event.timeStamp; - cb(event); - } - }, - true, - ); -}; diff --git a/frontend-old/node_modules/web-vitals/src/lib/bindReporter.ts b/frontend-old/node_modules/web-vitals/src/lib/bindReporter.ts deleted file mode 100644 index fa73db3..0000000 --- a/frontend-old/node_modules/web-vitals/src/lib/bindReporter.ts +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2020 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import {MetricType, MetricRatingThresholds} from '../types.js'; - -const getRating = ( - value: number, - thresholds: MetricRatingThresholds, -): MetricType['rating'] => { - if (value > thresholds[1]) { - return 'poor'; - } - if (value > thresholds[0]) { - return 'needs-improvement'; - } - return 'good'; -}; - -export const bindReporter = <MetricName extends MetricType['name']>( - callback: (metric: Extract<MetricType, {name: MetricName}>) => void, - metric: Extract<MetricType, {name: MetricName}>, - thresholds: MetricRatingThresholds, - reportAllChanges?: boolean, -) => { - let prevValue: number; - let delta: number; - return (forceReport?: boolean) => { - if (metric.value >= 0) { - if (forceReport || reportAllChanges) { - delta = metric.value - (prevValue || 0); - - // Report the metric if there's a non-zero delta or if no previous - // value exists (which can happen in the case of the document becoming - // hidden when the metric value is 0). - // See: https://github.com/GoogleChrome/web-vitals/issues/14 - if (delta || prevValue === undefined) { - prevValue = metric.value; - metric.delta = delta; - metric.rating = getRating(metric.value, thresholds); - callback(metric); - } - } - } - }; -}; diff --git a/frontend-old/node_modules/web-vitals/src/lib/doubleRAF.ts b/frontend-old/node_modules/web-vitals/src/lib/doubleRAF.ts deleted file mode 100644 index c76d142..0000000 --- a/frontend-old/node_modules/web-vitals/src/lib/doubleRAF.ts +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright 2022 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -export const doubleRAF = (cb: () => unknown) => { - requestAnimationFrame(() => requestAnimationFrame(() => cb())); -}; diff --git a/frontend-old/node_modules/web-vitals/src/lib/generateUniqueID.ts b/frontend-old/node_modules/web-vitals/src/lib/generateUniqueID.ts deleted file mode 100644 index 637d013..0000000 --- a/frontend-old/node_modules/web-vitals/src/lib/generateUniqueID.ts +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright 2020 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * Performantly generate a unique, 30-char string by combining a version - * number, the current timestamp with a 13-digit number integer. - * @return {string} - */ -export const generateUniqueID = () => { - return `v4-${Date.now()}-${Math.floor(Math.random() * (9e12 - 1)) + 1e12}`; -}; diff --git a/frontend-old/node_modules/web-vitals/src/lib/getActivationStart.ts b/frontend-old/node_modules/web-vitals/src/lib/getActivationStart.ts deleted file mode 100644 index 3991c0e..0000000 --- a/frontend-old/node_modules/web-vitals/src/lib/getActivationStart.ts +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright 2022 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import {getNavigationEntry} from './getNavigationEntry.js'; - -export const getActivationStart = (): number => { - const navEntry = getNavigationEntry(); - return (navEntry && navEntry.activationStart) || 0; -}; diff --git a/frontend-old/node_modules/web-vitals/src/lib/getLoadState.ts b/frontend-old/node_modules/web-vitals/src/lib/getLoadState.ts deleted file mode 100644 index 788db0f..0000000 --- a/frontend-old/node_modules/web-vitals/src/lib/getLoadState.ts +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2022 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import {getNavigationEntry} from './getNavigationEntry.js'; -import {LoadState} from '../types.js'; - -export const getLoadState = (timestamp: number): LoadState => { - if (document.readyState === 'loading') { - // If the `readyState` is 'loading' there's no need to look at timestamps - // since the timestamp has to be the current time or earlier. - return 'loading'; - } else { - const navigationEntry = getNavigationEntry(); - if (navigationEntry) { - if (timestamp < navigationEntry.domInteractive) { - return 'loading'; - } else if ( - navigationEntry.domContentLoadedEventStart === 0 || - timestamp < navigationEntry.domContentLoadedEventStart - ) { - // If the `domContentLoadedEventStart` timestamp has not yet been - // set, or if the given timestamp is less than that value. - return 'dom-interactive'; - } else if ( - navigationEntry.domComplete === 0 || - timestamp < navigationEntry.domComplete - ) { - // If the `domComplete` timestamp has not yet been - // set, or if the given timestamp is less than that value. - return 'dom-content-loaded'; - } - } - } - // If any of the above fail, default to loaded. This could really only - // happy if the browser doesn't support the performance timeline, which - // most likely means this code would never run anyway. - return 'complete'; -}; diff --git a/frontend-old/node_modules/web-vitals/src/lib/getNavigationEntry.ts b/frontend-old/node_modules/web-vitals/src/lib/getNavigationEntry.ts deleted file mode 100644 index 19d18cf..0000000 --- a/frontend-old/node_modules/web-vitals/src/lib/getNavigationEntry.ts +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2022 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -export const getNavigationEntry = (): PerformanceNavigationTiming | void => { - const navigationEntry = - self.performance && - performance.getEntriesByType && - performance.getEntriesByType('navigation')[0]; - - // Check to ensure the `responseStart` property is present and valid. - // In some cases no value is reported by the browser (for - // privacy/security reasons), and in other cases (bugs) the value is - // negative or is larger than the current page time. Ignore these cases: - // https://github.com/GoogleChrome/web-vitals/issues/137 - // https://github.com/GoogleChrome/web-vitals/issues/162 - // https://github.com/GoogleChrome/web-vitals/issues/275 - if ( - navigationEntry && - navigationEntry.responseStart > 0 && - navigationEntry.responseStart < performance.now() - ) { - return navigationEntry; - } -}; diff --git a/frontend-old/node_modules/web-vitals/src/lib/getSelector.ts b/frontend-old/node_modules/web-vitals/src/lib/getSelector.ts deleted file mode 100644 index 4ca0bb9..0000000 --- a/frontend-old/node_modules/web-vitals/src/lib/getSelector.ts +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2022 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -const getName = (node: Node) => { - const name = node.nodeName; - return node.nodeType === 1 - ? name.toLowerCase() - : name.toUpperCase().replace(/^#/, ''); -}; - -export const getSelector = (node: Node | null | undefined, maxLen?: number) => { - let sel = ''; - - try { - while (node && node.nodeType !== 9) { - const el: Element = node as Element; - const part = el.id - ? '#' + el.id - : getName(el) + - (el.classList && - el.classList.value && - el.classList.value.trim() && - el.classList.value.trim().length - ? '.' + el.classList.value.trim().replace(/\s+/g, '.') - : ''); - if (sel.length + part.length > (maxLen || 100) - 1) return sel || part; - sel = sel ? part + '>' + sel : part; - if (el.id) break; - node = el.parentNode; - } - } catch (err) { - // Do nothing... - } - return sel; -}; diff --git a/frontend-old/node_modules/web-vitals/src/lib/getVisibilityWatcher.ts b/frontend-old/node_modules/web-vitals/src/lib/getVisibilityWatcher.ts deleted file mode 100644 index ad7b1c3..0000000 --- a/frontend-old/node_modules/web-vitals/src/lib/getVisibilityWatcher.ts +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright 2020 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import {onBFCacheRestore} from './bfcache.js'; - -let firstHiddenTime = -1; - -const initHiddenTime = () => { - // If the document is hidden when this code runs, assume it was always - // hidden and the page was loaded in the background, with the one exception - // that visibility state is always 'hidden' during prerendering, so we have - // to ignore that case until prerendering finishes (see: `prerenderingchange` - // event logic below). - return document.visibilityState === 'hidden' && !document.prerendering - ? 0 - : Infinity; -}; - -const onVisibilityUpdate = (event: Event) => { - // If the document is 'hidden' and no previous hidden timestamp has been - // set, update it based on the current event data. - if (document.visibilityState === 'hidden' && firstHiddenTime > -1) { - // If the event is a 'visibilitychange' event, it means the page was - // visible prior to this change, so the event timestamp is the first - // hidden time. - // However, if the event is not a 'visibilitychange' event, then it must - // be a 'prerenderingchange' event, and the fact that the document is - // still 'hidden' from the above check means the tab was activated - // in a background state and so has always been hidden. - firstHiddenTime = event.type === 'visibilitychange' ? event.timeStamp : 0; - - // Remove all listeners now that a `firstHiddenTime` value has been set. - removeChangeListeners(); - } -}; - -const addChangeListeners = () => { - addEventListener('visibilitychange', onVisibilityUpdate, true); - // IMPORTANT: when a page is prerendering, its `visibilityState` is - // 'hidden', so in order to account for cases where this module checks for - // visibility during prerendering, an additional check after prerendering - // completes is also required. - addEventListener('prerenderingchange', onVisibilityUpdate, true); -}; - -const removeChangeListeners = () => { - removeEventListener('visibilitychange', onVisibilityUpdate, true); - removeEventListener('prerenderingchange', onVisibilityUpdate, true); -}; - -export const getVisibilityWatcher = () => { - if (firstHiddenTime < 0) { - // If the document is hidden when this code runs, assume it was hidden - // since navigation start. This isn't a perfect heuristic, but it's the - // best we can do until an API is available to support querying past - // visibilityState. - firstHiddenTime = initHiddenTime(); - addChangeListeners(); - - // Reset the time on bfcache restores. - onBFCacheRestore(() => { - // Schedule a task in order to track the `visibilityState` once it's - // had an opportunity to change to visible in all browsers. - // https://bugs.chromium.org/p/chromium/issues/detail?id=1133363 - setTimeout(() => { - firstHiddenTime = initHiddenTime(); - addChangeListeners(); - }, 0); - }); - } - return { - get firstHiddenTime() { - return firstHiddenTime; - }, - }; -}; diff --git a/frontend-old/node_modules/web-vitals/src/lib/initMetric.ts b/frontend-old/node_modules/web-vitals/src/lib/initMetric.ts deleted file mode 100644 index 90618d8..0000000 --- a/frontend-old/node_modules/web-vitals/src/lib/initMetric.ts +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2020 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import {getBFCacheRestoreTime} from './bfcache.js'; -import {generateUniqueID} from './generateUniqueID.js'; -import {getActivationStart} from './getActivationStart.js'; -import {getNavigationEntry} from './getNavigationEntry.js'; -import {MetricType} from '../types.js'; - -export const initMetric = <MetricName extends MetricType['name']>( - name: MetricName, - value?: number, -) => { - const navEntry = getNavigationEntry(); - let navigationType: MetricType['navigationType'] = 'navigate'; - - if (getBFCacheRestoreTime() >= 0) { - navigationType = 'back-forward-cache'; - } else if (navEntry) { - if (document.prerendering || getActivationStart() > 0) { - navigationType = 'prerender'; - } else if (document.wasDiscarded) { - navigationType = 'restore'; - } else if (navEntry.type) { - navigationType = navEntry.type.replace( - /_/g, - '-', - ) as MetricType['navigationType']; - } - } - - // Use `entries` type specific for the metric. - const entries: Extract<MetricType, {name: MetricName}>['entries'] = []; - - return { - name, - value: typeof value === 'undefined' ? -1 : value, - rating: 'good' as const, // If needed, will be updated when reported. `const` to keep the type from widening to `string`. - delta: 0, - entries, - id: generateUniqueID(), - navigationType, - }; -}; diff --git a/frontend-old/node_modules/web-vitals/src/lib/interactions.ts b/frontend-old/node_modules/web-vitals/src/lib/interactions.ts deleted file mode 100644 index fbd0751..0000000 --- a/frontend-old/node_modules/web-vitals/src/lib/interactions.ts +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright 2024 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import {getInteractionCount} from './polyfills/interactionCountPolyfill.js'; - -interface Interaction { - id: number; - latency: number; - entries: PerformanceEventTiming[]; -} - -interface EntryPreProcessingHook { - (entry: PerformanceEventTiming): void; -} - -// A list of longest interactions on the page (by latency) sorted so the -// longest one is first. The list is at most MAX_INTERACTIONS_TO_CONSIDER long. -export const longestInteractionList: Interaction[] = []; - -// A mapping of longest interactions by their interaction ID. -// This is used for faster lookup. -export const longestInteractionMap: Map<number, Interaction> = new Map(); - -// The default `durationThreshold` used across this library for observing -// `event` entries via PerformanceObserver. -export const DEFAULT_DURATION_THRESHOLD = 40; - -// Used to store the interaction count after a bfcache restore, since p98 -// interaction latencies should only consider the current navigation. -let prevInteractionCount = 0; - -/** - * Returns the interaction count since the last bfcache restore (or for the - * full page lifecycle if there were no bfcache restores). - */ -const getInteractionCountForNavigation = () => { - return getInteractionCount() - prevInteractionCount; -}; - -export const resetInteractions = () => { - prevInteractionCount = getInteractionCount(); - longestInteractionList.length = 0; - longestInteractionMap.clear(); -}; - -/** - * Returns the estimated p98 longest interaction based on the stored - * interaction candidates and the interaction count for the current page. - */ -export const estimateP98LongestInteraction = () => { - const candidateInteractionIndex = Math.min( - longestInteractionList.length - 1, - Math.floor(getInteractionCountForNavigation() / 50), - ); - - return longestInteractionList[candidateInteractionIndex]; -}; - -// To prevent unnecessary memory usage on pages with lots of interactions, -// store at most 10 of the longest interactions to consider as INP candidates. -const MAX_INTERACTIONS_TO_CONSIDER = 10; - -/** - * A list of callback functions to run before each entry is processed. - * Exposing this list allows the attribution build to hook into the - * entry processing pipeline. - */ -export const entryPreProcessingCallbacks: EntryPreProcessingHook[] = []; - -/** - * Takes a performance entry and adds it to the list of worst interactions - * if its duration is long enough to make it among the worst. If the - * entry is part of an existing interaction, it is merged and the latency - * and entries list is updated as needed. - */ -export const processInteractionEntry = (entry: PerformanceEventTiming) => { - entryPreProcessingCallbacks.forEach((cb) => cb(entry)); - - // Skip further processing for entries that cannot be INP candidates. - if (!(entry.interactionId || entry.entryType === 'first-input')) return; - - // The least-long of the 10 longest interactions. - const minLongestInteraction = - longestInteractionList[longestInteractionList.length - 1]; - - const existingInteraction = longestInteractionMap.get(entry.interactionId!); - - // Only process the entry if it's possibly one of the ten longest, - // or if it's part of an existing interaction. - if ( - existingInteraction || - longestInteractionList.length < MAX_INTERACTIONS_TO_CONSIDER || - entry.duration > minLongestInteraction.latency - ) { - // If the interaction already exists, update it. Otherwise create one. - if (existingInteraction) { - // If the new entry has a longer duration, replace the old entries, - // otherwise add to the array. - if (entry.duration > existingInteraction.latency) { - existingInteraction.entries = [entry]; - existingInteraction.latency = entry.duration; - } else if ( - entry.duration === existingInteraction.latency && - entry.startTime === existingInteraction.entries[0].startTime - ) { - existingInteraction.entries.push(entry); - } - } else { - const interaction = { - id: entry.interactionId!, - latency: entry.duration, - entries: [entry], - }; - longestInteractionMap.set(interaction.id, interaction); - longestInteractionList.push(interaction); - } - - // Sort the entries by latency (descending) and keep only the top ten. - longestInteractionList.sort((a, b) => b.latency - a.latency); - if (longestInteractionList.length > MAX_INTERACTIONS_TO_CONSIDER) { - longestInteractionList - .splice(MAX_INTERACTIONS_TO_CONSIDER) - .forEach((i) => longestInteractionMap.delete(i.id)); - } - } -}; diff --git a/frontend-old/node_modules/web-vitals/src/lib/observe.ts b/frontend-old/node_modules/web-vitals/src/lib/observe.ts deleted file mode 100644 index f3127a3..0000000 --- a/frontend-old/node_modules/web-vitals/src/lib/observe.ts +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2020 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -interface PerformanceEntryMap { - 'event': PerformanceEventTiming[]; - 'first-input': PerformanceEventTiming[]; - 'layout-shift': LayoutShift[]; - 'largest-contentful-paint': LargestContentfulPaint[]; - 'long-animation-frame': PerformanceLongAnimationFrameTiming[]; - 'paint': PerformancePaintTiming[]; - 'navigation': PerformanceNavigationTiming[]; - 'resource': PerformanceResourceTiming[]; -} - -/** - * Takes a performance entry type and a callback function, and creates a - * `PerformanceObserver` instance that will observe the specified entry type - * with buffering enabled and call the callback _for each entry_. - * - * This function also feature-detects entry support and wraps the logic in a - * try/catch to avoid errors in unsupporting browsers. - */ -export const observe = <K extends keyof PerformanceEntryMap>( - type: K, - callback: (entries: PerformanceEntryMap[K]) => void, - opts?: PerformanceObserverInit, -): PerformanceObserver | undefined => { - try { - if (PerformanceObserver.supportedEntryTypes.includes(type)) { - const po = new PerformanceObserver((list) => { - // Delay by a microtask to workaround a bug in Safari where the - // callback is invoked immediately, rather than in a separate task. - // See: https://github.com/GoogleChrome/web-vitals/issues/277 - Promise.resolve().then(() => { - callback(list.getEntries() as PerformanceEntryMap[K]); - }); - }); - po.observe( - Object.assign( - { - type, - buffered: true, - }, - opts || {}, - ) as PerformanceObserverInit, - ); - return po; - } - } catch (e) { - // Do nothing. - } - return; -}; diff --git a/frontend-old/node_modules/web-vitals/src/lib/onHidden.ts b/frontend-old/node_modules/web-vitals/src/lib/onHidden.ts deleted file mode 100644 index f59d4c9..0000000 --- a/frontend-old/node_modules/web-vitals/src/lib/onHidden.ts +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright 2020 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -export const onHidden = (cb: () => void) => { - document.addEventListener('visibilitychange', () => { - if (document.visibilityState === 'hidden') { - cb(); - } - }); -}; diff --git a/frontend-old/node_modules/web-vitals/src/lib/polyfills/firstInputPolyfill.ts b/frontend-old/node_modules/web-vitals/src/lib/polyfills/firstInputPolyfill.ts deleted file mode 100644 index 804c423..0000000 --- a/frontend-old/node_modules/web-vitals/src/lib/polyfills/firstInputPolyfill.ts +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Copyright 2020 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { - FirstInputPolyfillEntry, - FirstInputPolyfillCallback, -} from '../../types.js'; - -type addOrRemoveEventListener = - | typeof addEventListener - | typeof removeEventListener; - -let firstInputEvent: Event | null; -let firstInputDelay: number; -let firstInputTimeStamp: Date; -let callbacks: FirstInputPolyfillCallback[]; - -const listenerOpts: AddEventListenerOptions = {passive: true, capture: true}; -const startTimeStamp: Date = new Date(); - -/** - * Accepts a callback to be invoked once the first input delay and event - * are known. - */ -export const firstInputPolyfill = ( - onFirstInput: FirstInputPolyfillCallback, -) => { - callbacks.push(onFirstInput); - reportFirstInputDelayIfRecordedAndValid(); -}; - -export const resetFirstInputPolyfill = () => { - callbacks = []; - firstInputDelay = -1; - firstInputEvent = null; - eachEventType(addEventListener); -}; - -/** - * Records the first input delay and event, so subsequent events can be - * ignored. All added event listeners are then removed. - */ -const recordFirstInputDelay = (delay: number, event: Event) => { - if (!firstInputEvent) { - firstInputEvent = event; - firstInputDelay = delay; - firstInputTimeStamp = new Date(); - - eachEventType(removeEventListener); - reportFirstInputDelayIfRecordedAndValid(); - } -}; - -/** - * Reports the first input delay and event (if they're recorded and valid) - * by running the array of callback functions. - */ -const reportFirstInputDelayIfRecordedAndValid = () => { - // In some cases the recorded delay is clearly wrong, e.g. it's negative - // or it's larger than the delta between now and initialization. - // - https://github.com/GoogleChromeLabs/first-input-delay/issues/4 - // - https://github.com/GoogleChromeLabs/first-input-delay/issues/6 - // - https://github.com/GoogleChromeLabs/first-input-delay/issues/7 - if ( - firstInputDelay >= 0 && - // @ts-ignore (subtracting two dates always returns a number) - firstInputDelay < firstInputTimeStamp - startTimeStamp - ) { - const entry = { - entryType: 'first-input', - name: firstInputEvent!.type, - target: firstInputEvent!.target, - cancelable: firstInputEvent!.cancelable, - startTime: firstInputEvent!.timeStamp, - processingStart: firstInputEvent!.timeStamp + firstInputDelay, - } as FirstInputPolyfillEntry; - callbacks.forEach(function (callback) { - callback(entry); - }); - callbacks = []; - } -}; - -/** - * Handles pointer down events, which are a special case. - * Pointer events can trigger main or compositor thread behavior. - * We differentiate these cases based on whether or not we see a - * 'pointercancel' event, which are fired when we scroll. If we're scrolling - * we don't need to report input delay since FID excludes scrolling and - * pinch/zooming. - */ -const onPointerDown = (delay: number, event: Event) => { - /** - * Responds to 'pointerup' events and records a delay. If a pointer up event - * is the next event after a pointerdown event, then it's not a scroll or - * a pinch/zoom. - */ - const onPointerUp = () => { - recordFirstInputDelay(delay, event); - removePointerEventListeners(); - }; - - /** - * Responds to 'pointercancel' events and removes pointer listeners. - * If a 'pointercancel' is the next event to fire after a pointerdown event, - * it means this is a scroll or pinch/zoom interaction. - */ - const onPointerCancel = () => { - removePointerEventListeners(); - }; - - /** - * Removes added pointer event listeners. - */ - const removePointerEventListeners = () => { - removeEventListener('pointerup', onPointerUp, listenerOpts); - removeEventListener('pointercancel', onPointerCancel, listenerOpts); - }; - - addEventListener('pointerup', onPointerUp, listenerOpts); - addEventListener('pointercancel', onPointerCancel, listenerOpts); -}; - -/** - * Handles all input events and records the time between when the event - * was received by the operating system and when it's JavaScript listeners - * were able to run. - */ -const onInput = (event: Event) => { - // Only count cancelable events, which should trigger behavior - // important to the user. - if (event.cancelable) { - // In some browsers `event.timeStamp` returns a `DOMTimeStamp` value - // (epoch time) instead of the newer `DOMHighResTimeStamp` - // (document-origin time). To check for that we assume any timestamp - // greater than 1 trillion is a `DOMTimeStamp`, and compare it using - // the `Date` object rather than `performance.now()`. - // - https://github.com/GoogleChromeLabs/first-input-delay/issues/4 - const isEpochTime = event.timeStamp > 1e12; - const now = isEpochTime ? new Date() : performance.now(); - - // Input delay is the delta between when the system received the event - // (e.g. event.timeStamp) and when it could run the callback (e.g. `now`). - const delay = (now as number) - event.timeStamp; - - if (event.type == 'pointerdown') { - onPointerDown(delay, event); - } else { - recordFirstInputDelay(delay, event); - } - } -}; - -/** - * Invokes the passed callback const for = each event type with t =>he - * `onInput` const and = `listenerOpts =>`. - */ -const eachEventType = (callback: addOrRemoveEventListener) => { - const eventTypes = ['mousedown', 'keydown', 'touchstart', 'pointerdown']; - eventTypes.forEach((type) => callback(type, onInput, listenerOpts)); -}; diff --git a/frontend-old/node_modules/web-vitals/src/lib/polyfills/getFirstHiddenTimePolyfill.ts b/frontend-old/node_modules/web-vitals/src/lib/polyfills/getFirstHiddenTimePolyfill.ts deleted file mode 100644 index 9d7f26a..0000000 --- a/frontend-old/node_modules/web-vitals/src/lib/polyfills/getFirstHiddenTimePolyfill.ts +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 2020 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -let firstHiddenTime = document.visibilityState === 'hidden' ? 0 : Infinity; - -const onVisibilityChange = (event: Event) => { - if (document.visibilityState === 'hidden') { - firstHiddenTime = event.timeStamp; - removeEventListener('visibilitychange', onVisibilityChange, true); - } -}; - -// Note: do not add event listeners unconditionally (outside of polyfills). -addEventListener('visibilitychange', onVisibilityChange, true); - -export const getFirstHiddenTime = () => firstHiddenTime; diff --git a/frontend-old/node_modules/web-vitals/src/lib/polyfills/interactionCountPolyfill.ts b/frontend-old/node_modules/web-vitals/src/lib/polyfills/interactionCountPolyfill.ts deleted file mode 100644 index e363376..0000000 --- a/frontend-old/node_modules/web-vitals/src/lib/polyfills/interactionCountPolyfill.ts +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2022 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import {observe} from '../observe.js'; - -declare global { - interface Performance { - interactionCount: number; - } -} - -let interactionCountEstimate = 0; -let minKnownInteractionId = Infinity; -let maxKnownInteractionId = 0; - -const updateEstimate = (entries: PerformanceEventTiming[]) => { - entries.forEach((e) => { - if (e.interactionId) { - minKnownInteractionId = Math.min(minKnownInteractionId, e.interactionId); - maxKnownInteractionId = Math.max(maxKnownInteractionId, e.interactionId); - - interactionCountEstimate = maxKnownInteractionId - ? (maxKnownInteractionId - minKnownInteractionId) / 7 + 1 - : 0; - } - }); -}; - -let po: PerformanceObserver | undefined; - -/** - * Returns the `interactionCount` value using the native API (if available) - * or the polyfill estimate in this module. - */ -export const getInteractionCount = () => { - return po ? interactionCountEstimate : performance.interactionCount || 0; -}; - -/** - * Feature detects native support or initializes the polyfill if needed. - */ -export const initInteractionCountPolyfill = () => { - if ('interactionCount' in performance || po) return; - - po = observe('event', updateEstimate, { - type: 'event', - buffered: true, - durationThreshold: 0, - } as PerformanceObserverInit); -}; diff --git a/frontend-old/node_modules/web-vitals/src/lib/runOnce.ts b/frontend-old/node_modules/web-vitals/src/lib/runOnce.ts deleted file mode 100644 index f2de2ea..0000000 --- a/frontend-old/node_modules/web-vitals/src/lib/runOnce.ts +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright 2022 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -export const runOnce = (cb: () => void) => { - let called = false; - return () => { - if (!called) { - cb(); - called = true; - } - }; -}; diff --git a/frontend-old/node_modules/web-vitals/src/lib/whenActivated.ts b/frontend-old/node_modules/web-vitals/src/lib/whenActivated.ts deleted file mode 100644 index e4046c9..0000000 --- a/frontend-old/node_modules/web-vitals/src/lib/whenActivated.ts +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright 2022 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -export const whenActivated = (callback: () => void) => { - if (document.prerendering) { - addEventListener('prerenderingchange', () => callback(), true); - } else { - callback(); - } -}; diff --git a/frontend-old/node_modules/web-vitals/src/lib/whenIdle.ts b/frontend-old/node_modules/web-vitals/src/lib/whenIdle.ts deleted file mode 100644 index 9abb30c..0000000 --- a/frontend-old/node_modules/web-vitals/src/lib/whenIdle.ts +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2024 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import {onHidden} from './onHidden.js'; -import {runOnce} from './runOnce.js'; - -/** - * Runs the passed callback during the next idle period, or immediately - * if the browser's visibility state is (or becomes) hidden. - */ -export const whenIdle = (cb: () => void): number => { - const rIC = self.requestIdleCallback || self.setTimeout; - - let handle = -1; - cb = runOnce(cb); - // If the document is hidden, run the callback immediately, otherwise - // race an idle callback with the next `visibilitychange` event. - if (document.visibilityState === 'hidden') { - cb(); - } else { - handle = rIC(cb); - onHidden(cb); - } - return handle; -}; diff --git a/frontend-old/node_modules/web-vitals/src/onCLS.ts b/frontend-old/node_modules/web-vitals/src/onCLS.ts deleted file mode 100644 index 6f78458..0000000 --- a/frontend-old/node_modules/web-vitals/src/onCLS.ts +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright 2020 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import {onBFCacheRestore} from './lib/bfcache.js'; -import {initMetric} from './lib/initMetric.js'; -import {observe} from './lib/observe.js'; -import {bindReporter} from './lib/bindReporter.js'; -import {doubleRAF} from './lib/doubleRAF.js'; -import {onHidden} from './lib/onHidden.js'; -import {runOnce} from './lib/runOnce.js'; -import {onFCP} from './onFCP.js'; -import {CLSMetric, MetricRatingThresholds, ReportOpts} from './types.js'; - -/** Thresholds for CLS. See https://web.dev/articles/cls#what_is_a_good_cls_score */ -export const CLSThresholds: MetricRatingThresholds = [0.1, 0.25]; - -/** - * Calculates the [CLS](https://web.dev/articles/cls) value for the current page and - * calls the `callback` function once the value is ready to be reported, along - * with all `layout-shift` performance entries that were used in the metric - * value calculation. The reported value is a `double` (corresponding to a - * [layout shift score](https://web.dev/articles/cls#layout_shift_score)). - * - * If the `reportAllChanges` configuration option is set to `true`, the - * `callback` function will be called as soon as the value is initially - * determined as well as any time the value changes throughout the page - * lifespan. - * - * _**Important:** CLS should be continually monitored for changes throughout - * the entire lifespan of a page—including if the user returns to the page after - * it's been hidden/backgrounded. However, since browsers often [will not fire - * additional callbacks once the user has backgrounded a - * page](https://developer.chrome.com/blog/page-lifecycle-api/#advice-hidden), - * `callback` is always called when the page's visibility state changes to - * hidden. As a result, the `callback` function might be called multiple times - * during the same page load._ - */ -export const onCLS = ( - onReport: (metric: CLSMetric) => void, - opts?: ReportOpts, -) => { - // Set defaults - opts = opts || {}; - - // Start monitoring FCP so we can only report CLS if FCP is also reported. - // Note: this is done to match the current behavior of CrUX. - onFCP( - runOnce(() => { - let metric = initMetric('CLS', 0); - let report: ReturnType<typeof bindReporter>; - - let sessionValue = 0; - let sessionEntries: LayoutShift[] = []; - - const handleEntries = (entries: LayoutShift[]) => { - entries.forEach((entry) => { - // Only count layout shifts without recent user input. - if (!entry.hadRecentInput) { - const firstSessionEntry = sessionEntries[0]; - const lastSessionEntry = sessionEntries[sessionEntries.length - 1]; - - // If the entry occurred less than 1 second after the previous entry - // and less than 5 seconds after the first entry in the session, - // include the entry in the current session. Otherwise, start a new - // session. - if ( - sessionValue && - entry.startTime - lastSessionEntry.startTime < 1000 && - entry.startTime - firstSessionEntry.startTime < 5000 - ) { - sessionValue += entry.value; - sessionEntries.push(entry); - } else { - sessionValue = entry.value; - sessionEntries = [entry]; - } - } - }); - - // If the current session value is larger than the current CLS value, - // update CLS and the entries contributing to it. - if (sessionValue > metric.value) { - metric.value = sessionValue; - metric.entries = sessionEntries; - report(); - } - }; - - const po = observe('layout-shift', handleEntries); - if (po) { - report = bindReporter( - onReport, - metric, - CLSThresholds, - opts!.reportAllChanges, - ); - - onHidden(() => { - handleEntries(po.takeRecords() as CLSMetric['entries']); - report(true); - }); - - // Only report after a bfcache restore if the `PerformanceObserver` - // successfully registered. - onBFCacheRestore(() => { - sessionValue = 0; - metric = initMetric('CLS', 0); - report = bindReporter( - onReport, - metric, - CLSThresholds, - opts!.reportAllChanges, - ); - - doubleRAF(() => report()); - }); - - // Queue a task to report (if nothing else triggers a report first). - // This allows CLS to be reported as soon as FCP fires when - // `reportAllChanges` is true. - setTimeout(report, 0); - } - }), - ); -}; diff --git a/frontend-old/node_modules/web-vitals/src/onFCP.ts b/frontend-old/node_modules/web-vitals/src/onFCP.ts deleted file mode 100644 index f2a3625..0000000 --- a/frontend-old/node_modules/web-vitals/src/onFCP.ts +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright 2020 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import {onBFCacheRestore} from './lib/bfcache.js'; -import {bindReporter} from './lib/bindReporter.js'; -import {doubleRAF} from './lib/doubleRAF.js'; -import {getActivationStart} from './lib/getActivationStart.js'; -import {getVisibilityWatcher} from './lib/getVisibilityWatcher.js'; -import {initMetric} from './lib/initMetric.js'; -import {observe} from './lib/observe.js'; -import {whenActivated} from './lib/whenActivated.js'; -import {FCPMetric, MetricRatingThresholds, ReportOpts} from './types.js'; - -/** Thresholds for FCP. See https://web.dev/articles/fcp#what_is_a_good_fcp_score */ -export const FCPThresholds: MetricRatingThresholds = [1800, 3000]; - -/** - * Calculates the [FCP](https://web.dev/articles/fcp) value for the current page and - * calls the `callback` function once the value is ready, along with the - * relevant `paint` performance entry used to determine the value. The reported - * value is a `DOMHighResTimeStamp`. - */ -export const onFCP = ( - onReport: (metric: FCPMetric) => void, - opts?: ReportOpts, -) => { - // Set defaults - opts = opts || {}; - - whenActivated(() => { - const visibilityWatcher = getVisibilityWatcher(); - let metric = initMetric('FCP'); - let report: ReturnType<typeof bindReporter>; - - const handleEntries = (entries: FCPMetric['entries']) => { - entries.forEach((entry) => { - if (entry.name === 'first-contentful-paint') { - po!.disconnect(); - - // Only report if the page wasn't hidden prior to the first paint. - if (entry.startTime < visibilityWatcher.firstHiddenTime) { - // The activationStart reference is used because FCP should be - // relative to page activation rather than navigation start if the - // page was prerendered. But in cases where `activationStart` occurs - // after the FCP, this time should be clamped at 0. - metric.value = Math.max(entry.startTime - getActivationStart(), 0); - metric.entries.push(entry); - report(true); - } - } - }); - }; - - const po = observe('paint', handleEntries); - - if (po) { - report = bindReporter( - onReport, - metric, - FCPThresholds, - opts!.reportAllChanges, - ); - - // Only report after a bfcache restore if the `PerformanceObserver` - // successfully registered or the `paint` entry exists. - onBFCacheRestore((event) => { - metric = initMetric('FCP'); - report = bindReporter( - onReport, - metric, - FCPThresholds, - opts!.reportAllChanges, - ); - - doubleRAF(() => { - metric.value = performance.now() - event.timeStamp; - report(true); - }); - }); - } - }); -}; diff --git a/frontend-old/node_modules/web-vitals/src/onFID.ts b/frontend-old/node_modules/web-vitals/src/onFID.ts deleted file mode 100644 index cde84b9..0000000 --- a/frontend-old/node_modules/web-vitals/src/onFID.ts +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright 2020 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import {onBFCacheRestore} from './lib/bfcache.js'; -import {bindReporter} from './lib/bindReporter.js'; -import {getVisibilityWatcher} from './lib/getVisibilityWatcher.js'; -import {initMetric} from './lib/initMetric.js'; -import {observe} from './lib/observe.js'; -import {onHidden} from './lib/onHidden.js'; -import { - firstInputPolyfill, - resetFirstInputPolyfill, -} from './lib/polyfills/firstInputPolyfill.js'; -import {runOnce} from './lib/runOnce.js'; -import {whenActivated} from './lib/whenActivated.js'; -import { - FIDMetric, - FirstInputPolyfillCallback, - MetricRatingThresholds, - ReportOpts, -} from './types.js'; - -/** Thresholds for FID. See https://web.dev/articles/fid#what_is_a_good_fid_score */ -export const FIDThresholds: MetricRatingThresholds = [100, 300]; - -/** - * Calculates the [FID](https://web.dev/articles/fid) value for the current page and - * calls the `callback` function once the value is ready, along with the - * relevant `first-input` performance entry used to determine the value. The - * reported value is a `DOMHighResTimeStamp`. - * - * _**Important:** since FID is only reported after the user interacts with the - * page, it's possible that it will not be reported for some page loads._ - */ -export const onFID = ( - onReport: (metric: FIDMetric) => void, - opts?: ReportOpts, -) => { - // Set defaults - opts = opts || {}; - - whenActivated(() => { - const visibilityWatcher = getVisibilityWatcher(); - let metric = initMetric('FID'); - let report: ReturnType<typeof bindReporter>; - - const handleEntry = (entry: PerformanceEventTiming) => { - // Only report if the page wasn't hidden prior to the first input. - if (entry.startTime < visibilityWatcher.firstHiddenTime) { - metric.value = entry.processingStart - entry.startTime; - metric.entries.push(entry); - report(true); - } - }; - - const handleEntries = (entries: FIDMetric['entries']) => { - entries.forEach(handleEntry); - }; - - const po = observe('first-input', handleEntries); - - report = bindReporter( - onReport, - metric, - FIDThresholds, - opts!.reportAllChanges, - ); - - if (po) { - onHidden( - runOnce(() => { - handleEntries(po.takeRecords() as FIDMetric['entries']); - po.disconnect(); - }), - ); - - onBFCacheRestore(() => { - metric = initMetric('FID'); - report = bindReporter( - onReport, - metric, - FIDThresholds, - opts!.reportAllChanges, - ); - - // Browsers don't re-emit FID on bfcache restore so fake it until you make it - resetFirstInputPolyfill(); - firstInputPolyfill(handleEntry as FirstInputPolyfillCallback); - }); - } - }); -}; diff --git a/frontend-old/node_modules/web-vitals/src/onINP.ts b/frontend-old/node_modules/web-vitals/src/onINP.ts deleted file mode 100644 index cafa6d2..0000000 --- a/frontend-old/node_modules/web-vitals/src/onINP.ts +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright 2022 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import {onBFCacheRestore} from './lib/bfcache.js'; -import {bindReporter} from './lib/bindReporter.js'; -import {initMetric} from './lib/initMetric.js'; -import { - DEFAULT_DURATION_THRESHOLD, - processInteractionEntry, - estimateP98LongestInteraction, - resetInteractions, -} from './lib/interactions.js'; -import {observe} from './lib/observe.js'; -import {onHidden} from './lib/onHidden.js'; -import {initInteractionCountPolyfill} from './lib/polyfills/interactionCountPolyfill.js'; -import {whenActivated} from './lib/whenActivated.js'; -import {whenIdle} from './lib/whenIdle.js'; - -import {INPMetric, MetricRatingThresholds, ReportOpts} from './types.js'; - -/** Thresholds for INP. See https://web.dev/articles/inp#what_is_a_good_inp_score */ -export const INPThresholds: MetricRatingThresholds = [200, 500]; - -/** - * Calculates the [INP](https://web.dev/articles/inp) value for the current - * page and calls the `callback` function once the value is ready, along with - * the `event` performance entries reported for that interaction. The reported - * value is a `DOMHighResTimeStamp`. - * - * A custom `durationThreshold` configuration option can optionally be passed to - * control what `event-timing` entries are considered for INP reporting. The - * default threshold is `40`, which means INP scores of less than 40 are - * reported as 0. Note that this will not affect your 75th percentile INP value - * unless that value is also less than 40 (well below the recommended - * [good](https://web.dev/articles/inp#what_is_a_good_inp_score) threshold). - * - * If the `reportAllChanges` configuration option is set to `true`, the - * `callback` function will be called as soon as the value is initially - * determined as well as any time the value changes throughout the page - * lifespan. - * - * _**Important:** INP should be continually monitored for changes throughout - * the entire lifespan of a page—including if the user returns to the page after - * it's been hidden/backgrounded. However, since browsers often [will not fire - * additional callbacks once the user has backgrounded a - * page](https://developer.chrome.com/blog/page-lifecycle-api/#advice-hidden), - * `callback` is always called when the page's visibility state changes to - * hidden. As a result, the `callback` function might be called multiple times - * during the same page load._ - */ -export const onINP = ( - onReport: (metric: INPMetric) => void, - opts?: ReportOpts, -) => { - // Return if the browser doesn't support all APIs needed to measure INP. - if ( - !( - 'PerformanceEventTiming' in self && - 'interactionId' in PerformanceEventTiming.prototype - ) - ) { - return; - } - - // Set defaults - opts = opts || {}; - - whenActivated(() => { - // TODO(philipwalton): remove once the polyfill is no longer needed. - initInteractionCountPolyfill(); - - let metric = initMetric('INP'); - let report: ReturnType<typeof bindReporter>; - - const handleEntries = (entries: INPMetric['entries']) => { - // Queue the `handleEntries()` callback in the next idle task. - // This is needed to increase the chances that all event entries that - // occurred between the user interaction and the next paint - // have been dispatched. Note: there is currently an experiment - // running in Chrome (EventTimingKeypressAndCompositionInteractionId) - // 123+ that if rolled out fully may make this no longer necessary. - whenIdle(() => { - entries.forEach(processInteractionEntry); - - const inp = estimateP98LongestInteraction(); - - if (inp && inp.latency !== metric.value) { - metric.value = inp.latency; - metric.entries = inp.entries; - report(); - } - }); - }; - - const po = observe('event', handleEntries, { - // Event Timing entries have their durations rounded to the nearest 8ms, - // so a duration of 40ms would be any event that spans 2.5 or more frames - // at 60Hz. This threshold is chosen to strike a balance between usefulness - // and performance. Running this callback for any interaction that spans - // just one or two frames is likely not worth the insight that could be - // gained. - durationThreshold: opts!.durationThreshold ?? DEFAULT_DURATION_THRESHOLD, - }); - - report = bindReporter( - onReport, - metric, - INPThresholds, - opts!.reportAllChanges, - ); - - if (po) { - // Also observe entries of type `first-input`. This is useful in cases - // where the first interaction is less than the `durationThreshold`. - po.observe({type: 'first-input', buffered: true}); - - onHidden(() => { - handleEntries(po.takeRecords() as INPMetric['entries']); - report(true); - }); - - // Only report after a bfcache restore if the `PerformanceObserver` - // successfully registered. - onBFCacheRestore(() => { - resetInteractions(); - - metric = initMetric('INP'); - report = bindReporter( - onReport, - metric, - INPThresholds, - opts!.reportAllChanges, - ); - }); - } - }); -}; diff --git a/frontend-old/node_modules/web-vitals/src/onLCP.ts b/frontend-old/node_modules/web-vitals/src/onLCP.ts deleted file mode 100644 index 57f0a85..0000000 --- a/frontend-old/node_modules/web-vitals/src/onLCP.ts +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright 2020 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import {onBFCacheRestore} from './lib/bfcache.js'; -import {bindReporter} from './lib/bindReporter.js'; -import {doubleRAF} from './lib/doubleRAF.js'; -import {getActivationStart} from './lib/getActivationStart.js'; -import {getVisibilityWatcher} from './lib/getVisibilityWatcher.js'; -import {initMetric} from './lib/initMetric.js'; -import {observe} from './lib/observe.js'; -import {onHidden} from './lib/onHidden.js'; -import {runOnce} from './lib/runOnce.js'; -import {whenActivated} from './lib/whenActivated.js'; -import {whenIdle} from './lib/whenIdle.js'; -import {LCPMetric, MetricRatingThresholds, ReportOpts} from './types.js'; - -/** Thresholds for LCP. See https://web.dev/articles/lcp#what_is_a_good_lcp_score */ -export const LCPThresholds: MetricRatingThresholds = [2500, 4000]; - -const reportedMetricIDs: Record<string, boolean> = {}; - -/** - * Calculates the [LCP](https://web.dev/articles/lcp) value for the current page and - * calls the `callback` function once the value is ready (along with the - * relevant `largest-contentful-paint` performance entry used to determine the - * value). The reported value is a `DOMHighResTimeStamp`. - * - * If the `reportAllChanges` configuration option is set to `true`, the - * `callback` function will be called any time a new `largest-contentful-paint` - * performance entry is dispatched, or once the final value of the metric has - * been determined. - */ -export const onLCP = ( - onReport: (metric: LCPMetric) => void, - opts?: ReportOpts, -) => { - // Set defaults - opts = opts || {}; - - whenActivated(() => { - const visibilityWatcher = getVisibilityWatcher(); - let metric = initMetric('LCP'); - let report: ReturnType<typeof bindReporter>; - - const handleEntries = (entries: LCPMetric['entries']) => { - // If reportAllChanges is set then call this function for each entry, - // otherwise only consider the last one. - if (!opts!.reportAllChanges) { - entries = entries.slice(-1); - } - - entries.forEach((entry) => { - // Only report if the page wasn't hidden prior to LCP. - if (entry.startTime < visibilityWatcher.firstHiddenTime) { - // The startTime attribute returns the value of the renderTime if it is - // not 0, and the value of the loadTime otherwise. The activationStart - // reference is used because LCP should be relative to page activation - // rather than navigation start if the page was prerendered. But in cases - // where `activationStart` occurs after the LCP, this time should be - // clamped at 0. - metric.value = Math.max(entry.startTime - getActivationStart(), 0); - metric.entries = [entry]; - report(); - } - }); - }; - - const po = observe('largest-contentful-paint', handleEntries); - - if (po) { - report = bindReporter( - onReport, - metric, - LCPThresholds, - opts!.reportAllChanges, - ); - - const stopListening = runOnce(() => { - if (!reportedMetricIDs[metric.id]) { - handleEntries(po!.takeRecords() as LCPMetric['entries']); - po!.disconnect(); - reportedMetricIDs[metric.id] = true; - report(true); - } - }); - - // Stop listening after input. Note: while scrolling is an input that - // stops LCP observation, it's unreliable since it can be programmatically - // generated. See: https://github.com/GoogleChrome/web-vitals/issues/75 - ['keydown', 'click'].forEach((type) => { - // Wrap in a setTimeout so the callback is run in a separate task - // to avoid extending the keyboard/click handler to reduce INP impact - // https://github.com/GoogleChrome/web-vitals/issues/383 - addEventListener(type, () => whenIdle(stopListening), { - once: true, - capture: true, - }); - }); - - onHidden(stopListening); - - // Only report after a bfcache restore if the `PerformanceObserver` - // successfully registered. - onBFCacheRestore((event) => { - metric = initMetric('LCP'); - report = bindReporter( - onReport, - metric, - LCPThresholds, - opts!.reportAllChanges, - ); - - doubleRAF(() => { - metric.value = performance.now() - event.timeStamp; - reportedMetricIDs[metric.id] = true; - report(true); - }); - }); - } - }); -}; diff --git a/frontend-old/node_modules/web-vitals/src/onTTFB.ts b/frontend-old/node_modules/web-vitals/src/onTTFB.ts deleted file mode 100644 index 8167a56..0000000 --- a/frontend-old/node_modules/web-vitals/src/onTTFB.ts +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright 2020 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import {bindReporter} from './lib/bindReporter.js'; -import {initMetric} from './lib/initMetric.js'; -import {onBFCacheRestore} from './lib/bfcache.js'; -import {getNavigationEntry} from './lib/getNavigationEntry.js'; -import {MetricRatingThresholds, ReportOpts, TTFBMetric} from './types.js'; -import {getActivationStart} from './lib/getActivationStart.js'; -import {whenActivated} from './lib/whenActivated.js'; - -/** Thresholds for TTFB. See https://web.dev/articles/ttfb#what_is_a_good_ttfb_score */ -export const TTFBThresholds: MetricRatingThresholds = [800, 1800]; - -/** - * Runs in the next task after the page is done loading and/or prerendering. - * @param callback - */ -const whenReady = (callback: () => void) => { - if (document.prerendering) { - whenActivated(() => whenReady(callback)); - } else if (document.readyState !== 'complete') { - addEventListener('load', () => whenReady(callback), true); - } else { - // Queue a task so the callback runs after `loadEventEnd`. - setTimeout(callback, 0); - } -}; - -/** - * Calculates the [TTFB](https://web.dev/articles/ttfb) value for the - * current page and calls the `callback` function once the page has loaded, - * along with the relevant `navigation` performance entry used to determine the - * value. The reported value is a `DOMHighResTimeStamp`. - * - * Note, this function waits until after the page is loaded to call `callback` - * in order to ensure all properties of the `navigation` entry are populated. - * This is useful if you want to report on other metrics exposed by the - * [Navigation Timing API](https://w3c.github.io/navigation-timing/). For - * example, the TTFB metric starts from the page's [time - * origin](https://www.w3.org/TR/hr-time-2/#sec-time-origin), which means it - * includes time spent on DNS lookup, connection negotiation, network latency, - * and server processing time. - */ -export const onTTFB = ( - onReport: (metric: TTFBMetric) => void, - opts?: ReportOpts, -) => { - // Set defaults - opts = opts || {}; - - let metric = initMetric('TTFB'); - let report = bindReporter( - onReport, - metric, - TTFBThresholds, - opts.reportAllChanges, - ); - - whenReady(() => { - const navigationEntry = getNavigationEntry(); - - if (navigationEntry) { - // The activationStart reference is used because TTFB should be - // relative to page activation rather than navigation start if the - // page was prerendered. But in cases where `activationStart` occurs - // after the first byte is received, this time should be clamped at 0. - metric.value = Math.max( - navigationEntry.responseStart - getActivationStart(), - 0, - ); - - metric.entries = [navigationEntry]; - report(true); - - // Only report TTFB after bfcache restores if a `navigation` entry - // was reported for the initial load. - onBFCacheRestore(() => { - metric = initMetric('TTFB', 0); - report = bindReporter( - onReport, - metric, - TTFBThresholds, - opts!.reportAllChanges, - ); - - report(true); - }); - } - }); -}; diff --git a/frontend-old/node_modules/web-vitals/src/types.ts b/frontend-old/node_modules/web-vitals/src/types.ts deleted file mode 100644 index 92c44c6..0000000 --- a/frontend-old/node_modules/web-vitals/src/types.ts +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright 2020 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -export * from './types/base.js'; -export * from './types/polyfills.js'; - -export * from './types/cls.js'; -export * from './types/fcp.js'; -export * from './types/fid.js'; -export * from './types/inp.js'; -export * from './types/lcp.js'; -export * from './types/ttfb.js'; - -// -------------------------------------------------------------------------- -// Everything below is modifications to built-in modules. -// -------------------------------------------------------------------------- - -interface PerformanceEntryMap { - navigation: PerformanceNavigationTiming; - resource: PerformanceResourceTiming; - paint: PerformancePaintTiming; -} - -// Update built-in types to be more accurate. -declare global { - interface Document { - // https://wicg.github.io/nav-speculation/prerendering.html#document-prerendering - prerendering?: boolean; - // https://wicg.github.io/page-lifecycle/#sec-api - wasDiscarded?: boolean; - } - - interface Performance { - getEntriesByType<K extends keyof PerformanceEntryMap>( - type: K, - ): PerformanceEntryMap[K][]; - } - - // https://w3c.github.io/event-timing/#sec-modifications-perf-timeline - interface PerformanceObserverInit { - durationThreshold?: number; - } - - // https://wicg.github.io/nav-speculation/prerendering.html#performance-navigation-timing-extension - interface PerformanceNavigationTiming { - activationStart?: number; - } - - // https://wicg.github.io/event-timing/#sec-performance-event-timing - interface PerformanceEventTiming extends PerformanceEntry { - duration: DOMHighResTimeStamp; - interactionId: number; - } - - // https://wicg.github.io/layout-instability/#sec-layout-shift-attribution - interface LayoutShiftAttribution { - node?: Node; - previousRect: DOMRectReadOnly; - currentRect: DOMRectReadOnly; - } - - // https://wicg.github.io/layout-instability/#sec-layout-shift - interface LayoutShift extends PerformanceEntry { - value: number; - sources: LayoutShiftAttribution[]; - hadRecentInput: boolean; - } - - // https://w3c.github.io/largest-contentful-paint/#sec-largest-contentful-paint-interface - interface LargestContentfulPaint extends PerformanceEntry { - readonly renderTime: DOMHighResTimeStamp; - readonly loadTime: DOMHighResTimeStamp; - readonly size: number; - readonly id: string; - readonly url: string; - readonly element: Element | null; - } - - // https://w3c.github.io/long-animation-frame/#sec-PerformanceLongAnimationFrameTiming - interface PerformanceLongAnimationFrameTiming extends PerformanceEntry { - renderStart: DOMHighResTimeStamp; - duration: DOMHighResTimeStamp; - } -} diff --git a/frontend-old/node_modules/web-vitals/src/types/base.ts b/frontend-old/node_modules/web-vitals/src/types/base.ts deleted file mode 100644 index f883aff..0000000 --- a/frontend-old/node_modules/web-vitals/src/types/base.ts +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Copyright 2022 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import type {CLSMetric, CLSMetricWithAttribution} from './cls.js'; -import type {FCPMetric, FCPMetricWithAttribution} from './fcp.js'; -import type {FIDMetric, FIDMetricWithAttribution} from './fid.js'; -import type {INPMetric, INPMetricWithAttribution} from './inp.js'; -import type {LCPMetric, LCPMetricWithAttribution} from './lcp.js'; -import type {TTFBMetric, TTFBMetricWithAttribution} from './ttfb.js'; - -export interface Metric { - /** - * The name of the metric (in acronym form). - */ - name: 'CLS' | 'FCP' | 'FID' | 'INP' | 'LCP' | 'TTFB'; - - /** - * The current value of the metric. - */ - value: number; - - /** - * The rating as to whether the metric value is within the "good", - * "needs improvement", or "poor" thresholds of the metric. - */ - rating: 'good' | 'needs-improvement' | 'poor'; - - /** - * The delta between the current value and the last-reported value. - * On the first report, `delta` and `value` will always be the same. - */ - delta: number; - - /** - * A unique ID representing this particular metric instance. This ID can - * be used by an analytics tool to dedupe multiple values sent for the same - * metric instance, or to group multiple deltas together and calculate a - * total. It can also be used to differentiate multiple different metric - * instances sent from the same page, which can happen if the page is - * restored from the back/forward cache (in that case new metrics object - * get created). - */ - id: string; - - /** - * Any performance entries relevant to the metric value calculation. - * The array may also be empty if the metric value was not based on any - * entries (e.g. a CLS value of 0 given no layout shifts). - */ - entries: PerformanceEntry[]; - - /** - * The type of navigation. - * - * This will be the value returned by the Navigation Timing API (or - * `undefined` if the browser doesn't support that API), with the following - * exceptions: - * - 'back-forward-cache': for pages that are restored from the bfcache. - * - 'back_forward' is renamed to 'back-forward' for consistency. - * - 'prerender': for pages that were prerendered. - * - 'restore': for pages that were discarded by the browser and then - * restored by the user. - */ - navigationType: - | 'navigate' - | 'reload' - | 'back-forward' - | 'back-forward-cache' - | 'prerender' - | 'restore'; -} - -/** The union of supported metric types. */ -export type MetricType = - | CLSMetric - | FCPMetric - | FIDMetric - | INPMetric - | LCPMetric - | TTFBMetric; - -/** The union of supported metric attribution types. */ -export type MetricWithAttribution = - | CLSMetricWithAttribution - | FCPMetricWithAttribution - | FIDMetricWithAttribution - | INPMetricWithAttribution - | LCPMetricWithAttribution - | TTFBMetricWithAttribution; - -/** - * The thresholds of metric's "good", "needs improvement", and "poor" ratings. - * - * - Metric values up to and including [0] are rated "good" - * - Metric values up to and including [1] are rated "needs improvement" - * - Metric values above [1] are "poor" - * - * | Metric value | Rating | - * | --------------- | ------------------- | - * | ≦ [0] | "good" | - * | > [0] and ≦ [1] | "needs improvement" | - * | > [1] | "poor" | - */ -export type MetricRatingThresholds = [number, number]; - -/** - * @deprecated Use metric-specific function types instead, such as: - * `(metric: LCPMetric) => void`. If a single callback type is needed for - * multiple metrics, use `(metric: MetricType) => void`. - */ -export interface ReportCallback { - (metric: MetricType): void; -} - -export interface ReportOpts { - reportAllChanges?: boolean; - durationThreshold?: number; -} - -/** - * The loading state of the document. Note: this value is similar to - * `document.readyState` but it subdivides the "interactive" state into the - * time before and after the DOMContentLoaded event fires. - * - * State descriptions: - * - `loading`: the initial document response has not yet been fully downloaded - * and parsed. This is equivalent to the corresponding `readyState` value. - * - `dom-interactive`: the document has been fully loaded and parsed, but - * scripts may not have yet finished loading and executing. - * - `dom-content-loaded`: the document is fully loaded and parsed, and all - * scripts (except `async` scripts) have loaded and finished executing. - * - `complete`: the document and all of its sub-resources have finished - * loading. This is equivalent to the corresponding `readyState` value. - */ -export type LoadState = - | 'loading' - | 'dom-interactive' - | 'dom-content-loaded' - | 'complete'; diff --git a/frontend-old/node_modules/web-vitals/src/types/cls.ts b/frontend-old/node_modules/web-vitals/src/types/cls.ts deleted file mode 100644 index c79ce4c..0000000 --- a/frontend-old/node_modules/web-vitals/src/types/cls.ts +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright 2022 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import type {LoadState, Metric} from './base.js'; - -/** - * A CLS-specific version of the Metric object. - */ -export interface CLSMetric extends Metric { - name: 'CLS'; - entries: LayoutShift[]; -} - -/** - * An object containing potentially-helpful debugging information that - * can be sent along with the CLS value for the current page visit in order - * to help identify issues happening to real-users in the field. - */ -export interface CLSAttribution { - /** - * A selector identifying the first element (in document order) that - * shifted when the single largest layout shift contributing to the page's - * CLS score occurred. - */ - largestShiftTarget?: string; - /** - * The time when the single largest layout shift contributing to the page's - * CLS score occurred. - */ - largestShiftTime?: DOMHighResTimeStamp; - /** - * The layout shift score of the single largest layout shift contributing to - * the page's CLS score. - */ - largestShiftValue?: number; - /** - * The `LayoutShiftEntry` representing the single largest layout shift - * contributing to the page's CLS score. (Useful when you need more than just - * `largestShiftTarget`, `largestShiftTime`, and `largestShiftValue`). - */ - largestShiftEntry?: LayoutShift; - /** - * The first element source (in document order) among the `sources` list - * of the `largestShiftEntry` object. (Also useful when you need more than - * just `largestShiftTarget`, `largestShiftTime`, and `largestShiftValue`). - */ - largestShiftSource?: LayoutShiftAttribution; - /** - * The loading state of the document at the time when the largest layout - * shift contribution to the page's CLS score occurred (see `LoadState` - * for details). - */ - loadState?: LoadState; -} - -/** - * A CLS-specific version of the Metric object with attribution. - */ -export interface CLSMetricWithAttribution extends CLSMetric { - attribution: CLSAttribution; -} diff --git a/frontend-old/node_modules/web-vitals/src/types/fcp.ts b/frontend-old/node_modules/web-vitals/src/types/fcp.ts deleted file mode 100644 index ef599b3..0000000 --- a/frontend-old/node_modules/web-vitals/src/types/fcp.ts +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright 2022 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import type {LoadState, Metric} from './base.js'; - -/** - * An FCP-specific version of the Metric object. - */ -export interface FCPMetric extends Metric { - name: 'FCP'; - entries: PerformancePaintTiming[]; -} - -/** - * An object containing potentially-helpful debugging information that - * can be sent along with the FCP value for the current page visit in order - * to help identify issues happening to real-users in the field. - */ -export interface FCPAttribution { - /** - * The time from when the user initiates loading the page until when the - * browser receives the first byte of the response (a.k.a. TTFB). - */ - timeToFirstByte: number; - /** - * The delta between TTFB and the first contentful paint (FCP). - */ - firstByteToFCP: number; - /** - * The loading state of the document at the time when FCP `occurred (see - * `LoadState` for details). Ideally, documents can paint before they finish - * loading (e.g. the `loading` or `dom-interactive` phases). - */ - loadState: LoadState; - /** - * The `PerformancePaintTiming` entry corresponding to FCP. - */ - fcpEntry?: PerformancePaintTiming; - /** - * The `navigation` entry of the current page, which is useful for diagnosing - * general page load issues. This can be used to access `serverTiming` for example: - * navigationEntry?.serverTiming - */ - navigationEntry?: PerformanceNavigationTiming; -} - -/** - * An FCP-specific version of the Metric object with attribution. - */ -export interface FCPMetricWithAttribution extends FCPMetric { - attribution: FCPAttribution; -} diff --git a/frontend-old/node_modules/web-vitals/src/types/fid.ts b/frontend-old/node_modules/web-vitals/src/types/fid.ts deleted file mode 100644 index 5b2dcba..0000000 --- a/frontend-old/node_modules/web-vitals/src/types/fid.ts +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright 2022 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import type {LoadState, Metric} from './base.js'; - -/** - * An FID-specific version of the Metric object. - */ -export interface FIDMetric extends Metric { - name: 'FID'; - entries: PerformanceEventTiming[]; -} - -/** - * An object containing potentially-helpful debugging information that - * can be sent along with the FID value for the current page visit in order - * to help identify issues happening to real-users in the field. - */ -export interface FIDAttribution { - /** - * A selector identifying the element that the user interacted with. This - * element will be the `target` of the `event` dispatched. - */ - eventTarget: string; - /** - * The time when the user interacted. This time will match the `timeStamp` - * value of the `event` dispatched. - */ - eventTime: number; - /** - * The `type` of the `event` dispatched from the user interaction. - */ - eventType: string; - /** - * The `PerformanceEventTiming` entry corresponding to FID. - */ - eventEntry: PerformanceEventTiming; - /** - * The loading state of the document at the time when the first interaction - * occurred (see `LoadState` for details). If the first interaction occurred - * while the document was loading and executing script (e.g. usually in the - * `dom-interactive` phase) it can result in long input delays. - */ - loadState: LoadState; -} - -/** - * An FID-specific version of the Metric object with attribution. - */ -export interface FIDMetricWithAttribution extends FIDMetric { - attribution: FIDAttribution; -} diff --git a/frontend-old/node_modules/web-vitals/src/types/inp.ts b/frontend-old/node_modules/web-vitals/src/types/inp.ts deleted file mode 100644 index c3acbd9..0000000 --- a/frontend-old/node_modules/web-vitals/src/types/inp.ts +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright 2022 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import type {LoadState, Metric} from './base.js'; - -/** - * An INP-specific version of the Metric object. - */ -export interface INPMetric extends Metric { - name: 'INP'; - entries: PerformanceEventTiming[]; -} - -/** - * An object containing potentially-helpful debugging information that - * can be sent along with the INP value for the current page visit in order - * to help identify issues happening to real-users in the field. - */ -export interface INPAttribution { - /** - * A selector identifying the element that the user first interacted with - * as part of the frame where the INP candidate interaction occurred. - * If this value is an empty string, that generally means the element was - * removed from the DOM after the interaction. - */ - interactionTarget: string; - /** - * A reference to the HTML element identified by `interactionTargetSelector`. - * NOTE: for attribution purpose, a selector identifying the element is - * typically more useful than the element itself. However, the element is - * also made available in case additional context is needed. - */ - interactionTargetElement: Node | undefined; - /** - * The time when the user first interacted during the frame where the INP - * candidate interaction occurred (if more than one interaction occurred - * within the frame, only the first time is reported). - */ - interactionTime: DOMHighResTimeStamp; - /** - * The best-guess timestamp of the next paint after the interaction. - * In general, this timestamp is the same as the `startTime + duration` of - * the event timing entry. However, since `duration` values are rounded to - * the nearest 8ms, it can sometimes appear that the paint occurred before - * processing ended (which cannot happen). This value clamps the paint time - * so it's always after `processingEnd` from the Event Timing API and - * `renderStart` from the Long Animation Frame API (where available). - * It also averages the duration values for all entries in the same - * animation frame, which should be closer to the "real" value. - */ - nextPaintTime: DOMHighResTimeStamp; - /** - * The type of interaction, based on the event type of the `event` entry - * that corresponds to the interaction (i.e. the first `event` entry - * containing an `interactionId` dispatched in a given animation frame). - * For "pointerdown", "pointerup", or "click" events this will be "pointer", - * and for "keydown" or "keyup" events this will be "keyboard". - */ - interactionType: 'pointer' | 'keyboard'; - /** - * An array of Event Timing entries that were processed within the same - * animation frame as the INP candidate interaction. - */ - processedEventEntries: PerformanceEventTiming[]; - /** - * If the browser supports the Long Animation Frame API, this array will - * include any `long-animation-frame` entries that intersect with the INP - * candidate interaction's `startTime` and the `processingEnd` time of the - * last event processed within that animation frame. If the browser does not - * support the Long Animation Frame API or no `long-animation-frame` entries - * are detect, this array will be empty. - */ - longAnimationFrameEntries: PerformanceLongAnimationFrameTiming[]; - /** - * The time from when the user interacted with the page until when the - * browser was first able to start processing event listeners for that - * interaction. This time captures the delay before event processing can - * begin due to the main thread being busy with other work. - */ - inputDelay: number; - /** - * The time from when the first event listener started running in response to - * the user interaction until when all event listener processing has finished. - */ - processingDuration: number; - /** - * The time from when the browser finished processing all event listeners for - * the user interaction until the next frame is presented on the screen and - * visible to the user. This time includes work on the main thread (such as - * `requestAnimationFrame()` callbacks, `ResizeObserver` and - * `IntersectionObserver` callbacks, and style/layout calculation) as well - * as off-main-thread work (such as compositor, GPU, and raster work). - */ - presentationDelay: number; - /** - * The loading state of the document at the time when the interaction - * corresponding to INP occurred (see `LoadState` for details). If the - * interaction occurred while the document was loading and executing script - * (e.g. usually in the `dom-interactive` phase) it can result in long delays. - */ - loadState: LoadState; -} - -/** - * An INP-specific version of the Metric object with attribution. - */ -export interface INPMetricWithAttribution extends INPMetric { - attribution: INPAttribution; -} diff --git a/frontend-old/node_modules/web-vitals/src/types/lcp.ts b/frontend-old/node_modules/web-vitals/src/types/lcp.ts deleted file mode 100644 index 4761fdd..0000000 --- a/frontend-old/node_modules/web-vitals/src/types/lcp.ts +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright 2022 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import type {Metric} from './base.js'; - -/** - * An LCP-specific version of the Metric object. - */ -export interface LCPMetric extends Metric { - name: 'LCP'; - entries: LargestContentfulPaint[]; -} - -/** - * An object containing potentially-helpful debugging information that - * can be sent along with the LCP value for the current page visit in order - * to help identify issues happening to real-users in the field. - */ -export interface LCPAttribution { - /** - * The element corresponding to the largest contentful paint for the page. - */ - element?: string; - /** - * The URL (if applicable) of the LCP image resource. If the LCP element - * is a text node, this value will not be set. - */ - url?: string; - /** - * The time from when the user initiates loading the page until when the - * browser receives the first byte of the response (a.k.a. TTFB). See - * [Optimize LCP](https://web.dev/articles/optimize-lcp) for details. - */ - timeToFirstByte: number; - /** - * The delta between TTFB and when the browser starts loading the LCP - * resource (if there is one, otherwise 0). See [Optimize - * LCP](https://web.dev/articles/optimize-lcp) for details. - */ - resourceLoadDelay: number; - /** - * The total time it takes to load the LCP resource itself (if there is one, - * otherwise 0). See [Optimize LCP](https://web.dev/articles/optimize-lcp) for - * details. - */ - resourceLoadDuration: number; - /** - * The delta between when the LCP resource finishes loading until the LCP - * element is fully rendered. See [Optimize - * LCP](https://web.dev/articles/optimize-lcp) for details. - */ - elementRenderDelay: number; - /** - * The `navigation` entry of the current page, which is useful for diagnosing - * general page load issues. This can be used to access `serverTiming` for example: - * navigationEntry?.serverTiming - */ - navigationEntry?: PerformanceNavigationTiming; - /** - * The `resource` entry for the LCP resource (if applicable), which is useful - * for diagnosing resource load issues. - */ - lcpResourceEntry?: PerformanceResourceTiming; - /** - * The `LargestContentfulPaint` entry corresponding to LCP. - */ - lcpEntry?: LargestContentfulPaint; -} - -/** - * An LCP-specific version of the Metric object with attribution. - */ -export interface LCPMetricWithAttribution extends LCPMetric { - attribution: LCPAttribution; -} diff --git a/frontend-old/node_modules/web-vitals/src/types/polyfills.ts b/frontend-old/node_modules/web-vitals/src/types/polyfills.ts deleted file mode 100644 index 14bd5ae..0000000 --- a/frontend-old/node_modules/web-vitals/src/types/polyfills.ts +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright 2022 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -export type FirstInputPolyfillEntry = Omit< - PerformanceEventTiming, - 'processingEnd' ->; - -export interface FirstInputPolyfillCallback { - (entry: FirstInputPolyfillEntry): void; -} diff --git a/frontend-old/node_modules/web-vitals/src/types/ttfb.ts b/frontend-old/node_modules/web-vitals/src/types/ttfb.ts deleted file mode 100644 index 3559084..0000000 --- a/frontend-old/node_modules/web-vitals/src/types/ttfb.ts +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright 2022 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import type {Metric} from './base.js'; - -/** - * A TTFB-specific version of the Metric object. - */ -export interface TTFBMetric extends Metric { - name: 'TTFB'; - entries: PerformanceNavigationTiming[]; -} - -/** - * An object containing potentially-helpful debugging information that - * can be sent along with the TTFB value for the current page visit in order - * to help identify issues happening to real-users in the field. - * - * NOTE: these values are primarily useful for page loads not handled via - * service worker, as browsers differ in what they report when service worker - * is involved, see: https://github.com/w3c/navigation-timing/issues/199 - */ -export interface TTFBAttribution { - /** - * The total time from when the user initiates loading the page to when the - * page starts to handle the request. Large values here are typically due - * to HTTP redirects, though other browser processing contributes to this - * duration as well (so even without redirect it's generally not zero). - */ - waitingDuration: number; - /** - * The total time spent checking the HTTP cache for a match. For navigations - * handled via service worker, this duration usually includes service worker - * start-up time as well as time processing `fetch` event listeners, with - * some exceptions, see: https://github.com/w3c/navigation-timing/issues/199 - */ - cacheDuration: number; - /** - * The total time to resolve the DNS for the requested domain. - */ - dnsDuration: number; - /** - * The total time to create the connection to the requested domain. - */ - connectionDuration: number; - /** - * The total time from when the request was sent until the first byte of the - * response was received. This includes network time as well as server - * processing time. - */ - requestDuration: number; - /** - * The `navigation` entry of the current page, which is useful for diagnosing - * general page load issues. This can be used to access `serverTiming` for - * example: navigationEntry?.serverTiming - */ - navigationEntry?: PerformanceNavigationTiming; -} - -/** - * A TTFB-specific version of the Metric object with attribution. - */ -export interface TTFBMetricWithAttribution extends TTFBMetric { - attribution: TTFBAttribution; -} |
