npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@terrahq/helpers

v0.0.67

Published

These functions play a crucial role in project development, establishing identity, streamlining processes, and expediting progress. Whether it's preloading assets, integrating reCAPTCHA, or incorporating HubSpot interactions, these simple functions facili

Downloads

101

Readme

Helpers by Terra

These functions play a crucial role in project development, establishing identity, streamlining processes, and expediting progress. Whether it's preloading assets, integrating reCAPTCHA, or incorporating HubSpot interactions, these simple functions facilitate rapid development, contributing to the sustainable growth of our projects.

npm i @terrahq/helpers

Preload

Images

Under the hood it uses ImagesLoaded, This is an async await operation

Preloads images asynchronously and resolves the Promise when all images are loaded. Optionally, a callback function can be provided, which will be called after the images have preloaded. A debug option can be enabled to log information about the images that match the selector. The selector can be a class or selector: 'img' for all images. If no selector is provided, preloadImages will look for img tags by default.

import { preloadImages } from "@terrahq/helpers/preloadImages";

await preloadImages({
    selector: "img",
    callback: () => {
        console.log("All images loaded");
    },
    debug: false,
});
import { preloadImages } from "@terrahq/helpers/preloadImages";

await preloadImages({
    selector: document.querySelectorAll(".js--image"),
    callback: () => {
        console.log("All images loaded");
    },
    debug: true,
});

Videos

Under the hood it uses canplaythrough, This is an async await operation

Preloads video elements asynchronously and resolves the Promise when either all videos can play through, or the maximum time limit is reached. Optionally, a callback function can be provided, which will be called after the videos have preloaded or the time limit is reached. A debug option can be enabled to log information about the video elements that match the selector.

import { preloadVideos } from "@terrahq/helpers/preloadVideos";
await preloadVideos({
    selector: document.querySelectorAll(".js--video"),
    maxTime: 1300,
    callback: (payload) => {
        console.log("All videos are loaded");
    },
    debug: true,
});

Lottie

Under the hood it uses lottie-web , This is an async await operation

Preloads Lottie animations asynchronously and resolves the Promise when all animations are loaded. Optionally, a callback function can be provided, which will be called after all Lottie animations are loaded. A debug option can be enabled to log information about the Lottie elements being processed.

import { preloadLotties } from "@terrahq/helpers/preloadLotties";

await preloadLotties({
    debug: true,
    selector: document.querySelectorAll(".js--lottie-element"),
    callback: (payload) => {
        console.log("All lotties loaded", payload);
    },
});

Expected HTML structure for each Lottie element

<div class="js--lottie-element" data-path="filename.json" data-animType="svg" data-loop="true" data-autoplay="false" data-name="myLottie"></div>

Controlling Lottie animations via JavaScript

window.WL["myLottie"].play(); // Play the Lottie animation
window.WL["myLottie"].pause(); // Pause the Lottie animation
window.WL["myLottie"].stop(); // Stop the Lottie animation

Marketing

Hubspot

Helper to submit directly to Hubspot. Using axios. Submits form data to the HubSpot API using the specified portal ID and form ID. Optionally, a debug option can be enabled to log detailed information during the submission process, and a callback function can be provided to handle the response after the submission is completed.

  • This endpoint has a rate limit of 50 requests per 10 seconds.
  • When using this endpoint to integrate custom forms with HubSpot, keep in mind that the available endpoints do not log any API calls. Users will need to store their own logs.
  • In addition to accepting server-side HTTP requests, this endpoint will accept cross-origin AJAX (CORS) requests, allowing you to submit form data directly to HubSpot client-side using JavaScript.
  • This endpoint does not support reCAPTCHA. If reCAPTCHA has been enabled on the form, submissions will not be accepted.
import { submitToHubspot } from "@terrahq/helpers/hubspot";

const payload = {
    portalId: "YOUR_PORTAL_ID",
    formId: "YOUR_FORM_ID",
    formInputs: {
        firstName: "John",
        lastName: "Doe",
        email: "[email protected]",
    },
    callback: (result) => {
        console.log("Callback result:", result);
        if (result.success) {
            // Handle successful submission
        } else {
            // Handle submission error
        }
    },
    debug: true, // Enable debug mode
};

try {
    const submissionResult = await submitToHubspot(payload);
    console.log(submissionResult.message);
} catch (error) {
    // Handle unexpected errors during submission
    console.error("Submission error:", error.message);
}

Miscellaneous

Breakpoints

Helper function that returns all breakpoints for Terra

import { breakpoints } from "@terrahq/helpers/breakpoints";
let bk = breakpoints.reduce((target, inner) => Object.assign(target, inner), {});
console.log(bk.mobile);

TerraDebugger

Helper function to develop better testing for Developers + UX/ui, it returns breakpoint name and clickup space.

import { terraDebugger } from "@terrahq/helpers/terraDebugger";

function getQueryParam(param) {
    const urlParams = new URLSearchParams(window.location.search);
    return urlParams.has(param); // returns true if the parameter is present, otherwise false
}

var terraDebug = getQueryParam("debug");

if (terraDebug) {
    terraDebugger({ submitQA: "your_QA_app" });
}

Dig Element

Helper function designed to inspect a specified HTML element for mutations in its styles, classes, data attributes, or the structure of its children.

The function returns a Promise resolving in true or rejecting with error message.

import { digElement } from "@terrahq/helpers/digElement";

4 different ways of implementing it:

1 - Style Search

Promise.all(
    elements.map(async (element) => {
        await digElement({
            element: element,
            search: {
                type: "style",
                lookFor: ["max-height"],
            },
            intervalFrequency: 1500,
            timer: 5000,
            debug: true,
            callback: () => console.log("COMPLETED!"),
        });
    })
)
    .then(() => {
        console.log("READY");
    })
    .catch((error) => console.log(error.message));

| # | Parameter | Type | Description | | --- | ----------------- | ----------- | ----------------------------------------------------------------- | | 1 | element | HTMLElement | The element to check | | 2 | search.type | String | The type of search, in this case 'style' | | 3 | search.lookFor | Array | Array of styles properties to look for | | 4 | intervalFrequency | Number | Interval frequency in seconds | | 5 | timer | Number | The duration in seconds after which the interval will be finished | | 6 | callback | Function | A callback function to execute once the promise is resolved |

Class Search

Promise.all(
    elements.map(async (element) => {
        await digElement({
            element: element,
            search: {
                type: "class",
                lookFor: ["test-class"],
            },
            intervalFrequency: 1500,
            timer: 5000,
            debug: true,
            callback: () => console.log("COMPLETED!"),
        });
    })
)
    .then(() => {
        console.log("READY");
    })
    .catch((error) => console.log(error.message));

| # | Parameter | Type | Description | | --- | ----------------- | ----------- | ----------------------------------------------------------------- | | 1 | element | HTMLElement | The element to check | | 2 | search.type | String | The type of search, in this case 'class' | | 3 | search.lookFor | Array | Array of classes to look for | | 4 | intervalFrequency | Number | Interval frequency in seconds | | 5 | timer | Number | The duration in seconds after which the interval will be finished | | 6 | callback | Function | A callback function to execute once the promise is resolved |

Attribute Search and look for a specific value

Promise.all(
    elements.map(async (element) => {
        await digElement({
            element: element,
            search: {
                type: "class",
                attribute: "data-test",
                lookFor: ["value"],
            },
            intervalFrequency: 1500,
            timer: 5000,
            debug: true,
            callback: () => console.log("COMPLETED!"),
        });
    })
)
    .then(() => {
        console.log("READY");
    })
    .catch((error) => console.log(error.message));

Here's the information you provided in table format:

| # | Parameter | Type | Description | | --- | ----------------- | ----------- | ----------------------------------------------------------------- | | 1 | element | HTMLElement | The element to check | | 2 | search.type | String | The type of search, in this case 'class' | | 3 | search.attribute | String | The data attribute to check | | 4 | search.lookFor | Array | Array of possible values for the data attribute | | 5 | intervalFrequency | Number | Interval frequency in seconds | | 6 | timer | Number | The duration in seconds after which the interval will be finished | | 7 | callback | Function | A callback function to execute once the promise is resolved |

Search for children inside element

Promise.all(
    elements.map(async (element) => {
        await digElement({
            element: element,
            search: {
                type: "hasChildren",
            },
            intervalFrequency: 1500,
            timer: 5000,
            debug: true,
            callback: () => console.log("COMPLETED!"),
        });
    })
)
    .then(() => {
        console.log("READY");
    })
    .catch((error) => console.log(error.message));

Here's the information in table format:

| # | Parameter | Type | Description | | --- | ----------------- | ----------- | ----------------------------------------------------------------- | | 1 | element | HTMLElement | The element to check | | 2 | search.type | String | The type of search, in this case 'hasChildren' | | 3 | intervalFrequency | Number | Interval frequency in seconds | | 4 | timer | Number | The duration in seconds after which the interval will be finished | | 5 | callback | Function | A callback function to execute once the promise is resolved |


Manipulate Scroll

Helper function designed to enable/disable scrolling in your website.

import { manipulateScroll } from "@terrahq/helpers/manipulateScroll";
manipulateScroll("block");
manipulateScroll("scroll");

Get ID by Slug

Helper function designed to get the ID/s of the specified pages/post types looking by slug (it works only for WordPress projects).

import { getIDbySlug } from "@terrahq/helpers/getIDbySlug";
const payload = {
    slug: "my-page-slug",
    type: ["pages", "posts"],
    callback: () => {
        console.log("This is a callback!");
    },
    debug: true,
};

const postID = await getIDbySlug(payload);
if (postID) {
    console.log(`Found post with ID: ${postID}`);
} else {
    console.log("No post found with the specified slug.");
}

Get ID by Title

Helper function designed to get the ID/s of the specified pages/post types looking by title (it works only for WordPress projects).

import { getIDbyTitle } from "@terrahq/helpers/getIDbyTitle";
const payload = {
    title: "my-page-title",
    type: ["pages", "posts"],
    callback: () => {
        console.log("This is a callback!");
    },
    debug: true,
};

const postID = await getIDbyTitle(payload);
if (postID) {
    console.log(`Found post with ID: ${postID}`);
} else {
    console.log("No post found with the specified title.");
}

hasQueryParameter

This function checks if a specific query parameter is present in the URL of the current window location and retrieves its value if it exists. It is particularly useful for accessing and manipulating URL parameters dynamically in client-side applications.

import { hasQueryParameter } from "@terrahq/helpers/hasQueryParameter";

let result = hasQueryParameter({ name: "user" });
if (result) {
    console.log(`Query parameter 'user' has the value: ${result}`);
} else {
    console.log("Query parameter 'user' is not present in the URL.");
}

scrollYis

This function checks if the current vertical scroll position (window.scrollY) of the window is equal to a specified distance. It is typically used in scenarios where you need to verify if the window has been scrolled to a particular vertical position.

import { scrollYis } from "@terrahq/helpers/scrollYis";

if (scrollYis({ distance: 30 })) {
    console.log("The scroll position is exactly 30 pixels or more from the top.");
} else {
    console.log("The scroll position is below 30 pixels.");
}

Google Scripts Detection

This utility function, hasGoogleScripts, is designed to asynchronously check for the presence of Google Analytics and Google Tag Manager scripts on a webpage. It returns a promise that resolves with a boolean value indicating whether the specified Google scripts are detected within a given timeframe.

import { hasGoogleScripts } from "@terrahq/helpers/hasGoogleScripts";

Function Signature

async hasGoogleScripts(options = { detect: ['analytics', 'gtm'], maxTime: 5000, debug: false })

  • options: Optional configuration object.
    • detect: Array specifying which Google scripts to detect. Default is ['analytics', 'gtm']. You can also detect Google Ads by adding a 'ads' to the array.
    • maxTime: Maximum time in milliseconds to wait for script detection. Default is 5000.
    • debug: Default false, you can show the console logs with debug: true.

Usage

The function can be used with await inside an async function, or with .then() for promise handling. Here's an example using .then() for handling the detection result:

await hasGoogleScripts().then((detected) => {
    if (detected) {
        // Code to execute if the specified Google scripts are detected, e.g., load GTM
        this.loadGTM();
    } else {
        // Code to execute if the scripts are not detected within the specified time
        console.log("Google Scripts not detected");
    }
});

Recaptcha

Helper to add recaptcha v3 to forms. It has several functions. 1st Asynchronously loads the reCAPTCHA script from Google with the specified API key.

import { GET_RECAPTCHA_SCRIPT_FROM_GOOGLE } from "@terrahq/helpers/recaptcha";

var publicKey = "XXXXXXX";
var loadRecaptchaScript = await GET_RECAPTCHA_SCRIPT_FROM_GOOGLE({
    API_KEY: publicKey,
});

2nd Asynchronously retrieves a reCAPTCHA client token by executing the reCAPTCHA challenge.

import { GET_RECAPTCHA_CLIENT_TOKEN } from "@terrahq/helpers/recaptcha";

var google_access_token = await GET_RECAPTCHA_CLIENT_TOKEN({
    API_KEY: publicKey,
    action: "submit",
});

3rd Validates a Google reCAPTCHA token on the server-side using either PHP or Node.js.

import { VALIDATE_RECAPTCHA_SERVER } from "@terrahq/helpers/recaptcha";

var response_from_server = await VALIDATE_RECAPTCHA_SERVER({
    type: "node",
    postUrl: "yoursite.com/api/validate_recaptcha",
    action: "recaptcha_validate",
    google_access_token: google_access_token,
});
Note : you could use these reference as a draft, this is not production ready, samples for Node or PHP

WPCF7 Delay Recaptcha

Dynamically injects Google reCAPTCHA and required scripts into the document head, optimizing load times for Contact Form 7 forms with reCAPTCHA. Includes optional debug logging and supports a callback function post-injection.

import { wpcf7DelayRecaptcha } from "@terrahq/helpers/wpcf7DelayRecaptcha";

wpcf7DelayRecaptcha({
    scripts: {
      recaptchaScript: 'google-recaptcha-js',
      polyfill: 'wp-polyfill-js',
      recaptchaExtraScriptId: 'wpcf7-recaptcha-js-extra',
      wpcf7RecaptchaScriptId: 'wpcf7-recaptcha-js'
    },
    siteKey: 'XXXXXXX',
    debug: true,
    callback: () => {
      console.log("reCAPTCHA scripts have been successfully injected!");
    }
  });

---

## Accessible Tab Nav

It handles focus on 'skip to main content' and/or anchor to section enter keydown.

```javascript
import { accessibleTabNav } from "@terrahq/helpers/accessibleTabNav";

| # | Parameter | Type | Description | | --- | ----------------- | ------------- | ------------------------------------------------------------------------------------------- | | 1 | focusableElements | Array | It specifies which types of elements will be included as focusables within the focus target |


Trigger elements must include:

  • class: 'js--trigger-focus'

  • data-focus-target='${focusTargetID}'


Target elements must include:

  • id: '${focusTargetID}'

HTML - Example 1:

//header.php

<main id="swup">
    <button class="js--trigger-focus" data-focus-target="main-content" tabindex="1">Skip to Main Content</button>
    <div id="main-content">...</div>
    ...
</main>

HTML - Example 2:

//card-a.php

<a href="test" class="c--card-a js--trigger-focus" data-focus-target="3">
    <div class="c--card-a__ft-items">
        <h2 class="c--card-a__ft-items__title">Title</h2>
        <p class="c--card-a__ft-items__subtitle">Subtitle</p>
        <div class="c--card-a__ft-items__btn">Link</div>
    </div>
</a>

//random-module.php

<span id="3" class="js--invisible-span" style="position: relative; display:block;"></span>
<section class="">
    <div class="f--container">Content</div>
</section>

JavaScript:

accessibleTabNav();

accessibleTabNav({
    focusableElements: ["a", "button"],
});