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 🙏

© 2026 – Pkg Stats / Ryan Hefner

@gringow/gringow-shadow

v0.2.0

Published

A HTML class for Gringow AI-powered translation tool

Readme

@gringow/gringow-shadow

npm version License: MIT

Lightweight Web Component layer for Gringow translations. Provides the <g-gringow> custom element, translation store, and language change events for vanilla JavaScript projects. This is the foundation layer used by @gringow/gringow-react.

Features

  • 🎯 Custom Element - <g-gringow> for declarative translations
  • 🗂️ Translation Store - Singleton cache manager with language awareness
  • 📡 Language Events - Type-safe language change broadcasting
  • 🪶 Zero Dependencies - Pure Web Components API
  • Framework Agnostic - Works with vanilla JS, React, Vue, etc.
  • 🔄 Smart Caching - Memoized cache fetching and lookup

Installation

# Using pnpm
pnpm add @gringow/gringow-shadow

# Using npm
npm install @gringow/gringow-shadow

# Using yarn
yarn add @gringow/gringow-shadow

Quick Start

Vanilla HTML Setup

<!DOCTYPE html>
<html lang="en">
<head>
  <meta name="gringow-cache-url" content="/gringow/gringow.json">
</head>
<body>
  <g-gringow data-cache-id="grw_abc123" data-flatten="Hello world"></g-gringow>
  
  <button id="btn-pt">Português</button>
  <button id="btn-fr">Français</button>

  <script type="module">
    import { GringowComponent, GringowStore, LanguageChangeEvent } from '@gringow/gringow-shadow'

    // Configure store
    GringowStore.cacheUrl = '/gringow/gringow.json'
    GringowStore.language = 'en-US'
    await GringowStore.fetchCache()

    // Register custom element
    GringowComponent.defaults = { store: GringowStore }
    customElements.define(GringowComponent.GRINGOW_ELEMENT_NAME, GringowComponent)

    // Handle language changes
    document.getElementById('btn-pt').onclick = () => {
      dispatchEvent(LanguageChangeEvent.create('pt-BR'))
    }
    
    document.getElementById('btn-fr').onclick = () => {
      dispatchEvent(LanguageChangeEvent.create('fr-CA'))
    }

    // Listen to language changes
    addEventListener(LanguageChangeEvent.EVENT_NAME, (event) => {
      console.log('Language changed to:', event.detail.lang)
    })
  </script>
</body>
</html>

Component API

<g-gringow> Custom Element

Declarative translation component that reads from the cache and updates on language changes.

Attributes

  • data-cache-id (required) - Cache ID from gringow.json (e.g., grw_abc123)
  • data-flatten (required) - Original flattened string used as fallback
  • data-replacements (optional) - JSON array for interpolation (e.g., '["Alice", 5]')

Example with Replacements

<!-- Cache entry: "Hello {0}, you have {1} messages" -->
<g-gringow 
  data-cache-id="grw_msg456"
  data-flatten="Hello {name}, you have {count} messages"
  data-replacements='["Alice", 5]'>
</g-gringow>
<!-- Renders: "Hello Alice, you have 5 messages" -->

GringowStore (Singleton)

Central cache manager for fetching and accessing translations.

Properties

// Cache file URL (auto-detects from <meta> or <html data-gringow-cache-url>)
GringowStore.cacheUrl: string | null

// Active language (defaults to document.documentElement.lang)
GringowStore.language: string | null

// Cached translations object
GringowStore.cache: GringowCache | null

Methods

// Fetch and memoize cache from cacheUrl
await GringowStore.fetchCache(): Promise<void>

// Get translated string for active language
GringowStore.getCacheItem(cacheId: string): string | null

// Manual cache setter
GringowStore.setCache(cache: GringowCache): void

Configuration Priority

The store resolves cacheUrl in this order:

  1. GringowStore.cacheUrl (programmatic)
  2. <meta name="gringow-cache-url" content="/path/to/cache.json">
  3. <html data-gringow-cache-url="/path/to/cache.json">

LanguageChangeEvent

Custom event for broadcasting language changes across components.

Usage

// Dispatch language change
dispatchEvent(LanguageChangeEvent.create('pt-BR'))

// Listen for changes
addEventListener(LanguageChangeEvent.EVENT_NAME, (event) => {
  console.log('New language:', event.detail.lang)
  // event.detail.lang === 'pt-BR'
})

Constants

  • LanguageChangeEvent.EVENT_NAME - 'gringow:language-change'
  • LanguageChangeEvent.create(lang: string) - Factory method for events

Advanced Examples

Dynamic Content with Interpolation

<script type="module">
  import { GringowComponent, GringowStore } from '@gringow/gringow-shadow'

  GringowStore.cacheUrl = '/gringow/gringow.json'
  GringowStore.language = 'en-US'
  await GringowStore.fetchCache()

  GringowComponent.defaults = { store: GringowStore }
  customElements.define('g-gringow', GringowComponent)

  // Dynamically create element with replacements
  const element = document.createElement('g-gringow')
  element.setAttribute('data-cache-id', 'grw_welcome')
  element.setAttribute('data-flatten', 'Welcome back, {name}!')
  element.setAttribute('data-replacements', JSON.stringify(['Alice']))
  document.body.appendChild(element)
</script>

Multiple Language Switcher

<nav>
  <button data-lang="en-US">English</button>
  <button data-lang="pt-BR">Português</button>
  <button data-lang="fr-CA">Français</button>
  <button data-lang="es-ES">Español</button>
</nav>

<main>
  <g-gringow data-cache-id="grw_title" data-flatten="Welcome"></g-gringow>
  <g-gringow data-cache-id="grw_desc" data-flatten="Choose your language"></g-gringow>
</main>

<script type="module">
  import { GringowComponent, GringowStore, LanguageChangeEvent } from '@gringow/gringow-shadow'

  // Setup
  GringowStore.cacheUrl = '/gringow/gringow.json'
  GringowStore.language = document.documentElement.lang || 'en-US'
  await GringowStore.fetchCache()

  GringowComponent.defaults = { store: GringowStore }
  customElements.define('g-gringow', GringowComponent)

  // Wire language buttons
  document.querySelectorAll('[data-lang]').forEach(btn => {
    btn.onclick = () => {
      const lang = btn.dataset.lang
      document.documentElement.lang = lang
      dispatchEvent(LanguageChangeEvent.create(lang))
    }
  })
</script>

Framework Integration (Vue/Svelte/etc)

// utils/gringow.ts
import { GringowComponent, GringowStore, LanguageChangeEvent } from '@gringow/gringow-shadow'

export async function initGringow(cacheUrl: string, initialLang: string) {
  GringowStore.cacheUrl = cacheUrl
  GringowStore.language = initialLang
  await GringowStore.fetchCache()

  GringowComponent.defaults = { store: GringowStore }
  
  if (!customElements.get('g-gringow')) {
    customElements.define('g-gringow', GringowComponent)
  }
}

export function changeLanguage(lang: string) {
  dispatchEvent(LanguageChangeEvent.create(lang))
}

Module Exports

The package provides granular exports for tree-shaking:

// Main export (all components)
import { GringowComponent, GringowStore, LanguageChangeEvent } from '@gringow/gringow-shadow'

// Individual exports
import { GringowComponent } from '@gringow/gringow-shadow/component'
import { GringowStore } from '@gringow/gringow-shadow/store'
import { LanguageChangeEvent } from '@gringow/gringow-shadow/event'

Development

# Install dependencies
pnpm install

# Build the package
pnpm run build

# Watch mode for development
pnpm run watch

Browser Compatibility

Built on Web Components standards:

  • Custom Elements v1
  • Shadow DOM v1
  • ES2020+ modules

Supported browsers: Chrome 54+, Firefox 63+, Safari 10.1+, Edge 79+

Related Packages

Resources

License

MIT © Renato Gaspar


Questions? Open an issue on GitHub