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 🙏

© 2025 – Pkg Stats / Ryan Hefner

igloo-d2c-components

v1.0.13

Published

Reusable component library with tenant-aware theming for B2C applications

Readme

D2C Component Library

Reusable React component library with centralized tenant themes and tenant-aware theming for B2C applications.

📋 Table of Contents


🎯 Overview

The D2C Component Library provides reusable, tenant-aware UI components with centralized theme management. All tenant themes are defined in one place, ensuring consistency across all applications.

Key Highlights

  • 🎨 Centralized Themes - All tenant themes (Igloo, CIMB, AmmetLife) in one library
  • 🧩 Tenant-Aware Components - Automatically adapt to tenant branding
  • 📦 ES2015 Compatible - Works with older webpack configurations
  • 🔧 Unminified Output - Better debugging and tree-shaking
  • 📖 Full TypeScript Support - Complete type definitions
  • Tree-Shakeable - Import only what you need

✨ Features

Centralized Theme System

  • Single source of truth for all tenant themes
  • Type-safe theme access with TypeScript
  • Dynamic theme loading with getTenantTheme()
  • ~585 lines of code removed from consuming apps
  • Easy to maintain - update once, reflects everywhere

Available Themes

| Tenant | Theme Export | Description | |--------|-------------|-------------| | Igloo | iglooTheme | Default insurance brand | | CIMB | cimbTheme | Banking partner theme | | AmmetLife | ammetlifeTheme | Life insurance partner |

Components

  • Button - Tenant-themed button component
  • Card - Card with tenant accent border
  • Banner - Promotional banner with gradients

Hooks

  • useTenantTheme() - Access tenant theme and ID
  • useTenantId() - Get current tenant ID
  • useIsTenant() - Check tenant match

Utilities

  • getTenantTheme() - Get theme by tenant ID
  • isValidTenantId() - Validate tenant ID
  • getThemeColor() - Extract colors from theme
  • createThemeCSSVariables() - Generate CSS variables

📦 Installation

Option 1: Local Development (Recommended for Development)

Perfect for active development when working on the library.

# 1. Build the library
cd /path/to/d2c-component-library
yarn install
yarn build

# 2. In consuming app (b2c-web-demo)
cd /path/to/b2c-web-demo

# Add to package.json:
{
  "dependencies": {
    "igloo-d2c-components": "file:../d2c-component-library"
  }
}

# Install
yarn install

Workflow:

# Make changes to library
cd d2c-component-library
# ... edit files ...
yarn build

# Update consuming app
cd ../b2c-web-demo
yarn install  # Copies updated build

Option 2: NPM Registry (Production)

For production deployments and CI/CD.

Install:

yarn add igloo-d2c-components
# or
npm install igloo-d2c-components

Configure authentication (if using private registry):

# For npm
export NPM_AUTH_TOKEN="your-npm-token"

# For GitLab Package Registry
export GITLAB_NPM_TOKEN="glpat-your-token"

🚀 Quick Start

1. Import Pre-built Themes (Recommended)

import {
  TenantThemeProvider,
  iglooTheme,
  cimbTheme,
  ammetlifeTheme
} from 'igloo-d2c-components'

function App() {
  return (
    <TenantThemeProvider tenantId="igloo" theme={iglooTheme}>
      <YourApp />
    </TenantThemeProvider>
  )
}

2. Dynamic Theme Loading

import { TenantThemeProvider, getTenantTheme } from 'igloo-d2c-components'

function App({ tenantId }) {
  const theme = getTenantTheme(tenantId) // 'igloo', 'cimb', or 'ammetlife'

  return (
    <TenantThemeProvider tenantId={tenantId} theme={theme}>
      <YourApp />
    </TenantThemeProvider>
  )
}

3. Use Components

import { Button, Card, Banner } from 'igloo-d2c-components'

function MyPage() {
  return (
    <div>
      {/* Tenant-themed button */}
      <Button tenantColored variant="contained">
        Click Me
      </Button>

      {/* Tenant-themed card */}
      <Card
        title="My Card"
        content="Card content"
        tenantAccent
      />

      {/* Tenant-themed banner */}
      <Banner
        title="Welcome"
        description="Get started today"
        gradient
      />
    </div>
  )
}

🎨 Centralized Themes

Why Centralized Themes?

Before (❌ Old Way):

// In each consuming app - duplicated code
const iglooTheme = {
  palette: {
    primary: { main: '#5656F6', dark: '#1300A9', ... },
    // ... 60+ lines per tenant
  }
}

After (✅ New Way):

// Import from library - single source of truth
import { iglooTheme } from 'igloo-d2c-components'

Available Theme Exports

import {
  // Individual themes
  iglooTheme,      // Igloo brand theme
  cimbTheme,       // CIMB bank theme
  ammetlifeTheme,  // AmmetLife insurance theme

  // Theme registry
  tenantThemes,    // { igloo: iglooTheme, cimb: cimbTheme, ... }

  // Utility functions
  getTenantTheme,  // (tenantId: TenantId) => TenantThemeConfig
  isValidTenantId, // (id: string) => boolean
  getAvailableTenants, // () => TenantId[]
} from 'igloo-d2c-components'

Theme Structure

Each theme includes:

interface TenantThemeConfig {
  palette: {
    // Core palettes
    primary: { main, dark, light, bright, plain, border }
    secondary: { dim, dark, main, bright, mediumBright, light, lighter }
    tertiary: { dim, dark, main, light, bright }
    natural: { dim, dark, main, light, bright, granite }

    // Product-specific colors
    motor: { main, light, bright }
    car: { main, light, darkAI }
    travel: { main, light }
    health: { main, light? }
    life: { main, light }
    pet: { main }

    // CIMB-specific (optional)
    paCimb?: { main, light, bright, buttonBg }
  }
  typography: {
    fontFamily: string
  }
  logo: string
  favicon: string
}

Using Themes

In Tenant Configuration:

// config/tenants/igloo.ts
import { iglooTheme } from 'igloo-d2c-components'

const iglooConfig: TenantConfig = {
  id: 'igloo',
  theme: iglooTheme, // ✨ That's it!
  // ... other config
}

Dynamic Loading:

import { getTenantTheme, isValidTenantId } from 'igloo-d2c-components'

function loadTheme(tenantId: string) {
  if (isValidTenantId(tenantId)) {
    return getTenantTheme(tenantId)
  }
  throw new Error(`Invalid tenant: ${tenantId}`)
}

In Components:

import { useTenantTheme } from 'igloo-d2c-components'

function MyComponent() {
  const { theme, tenantId } = useTenantTheme()

  return (
    <div style={{
      backgroundColor: theme.palette.primary.main,
      color: theme.palette.primary.bright
    }}>
      Current tenant: {tenantId}
    </div>
  )
}

Theme Benefits

  • Single source of truth - Update in one place
  • Type-safe - Full TypeScript support
  • Consistent - Same themes across all apps
  • Maintainable - Easy to update and extend
  • Scalable - Add new tenants easily

📚 Components

Button

Tenant-aware button component based on MUI Button.

import { Button } from 'igloo-d2c-components'

// Tenant-colored button
<Button tenantColored variant="contained">
  Tenant Colored Button
</Button>

// Standard MUI button
<Button color="primary" variant="outlined">
  Default Button
</Button>

Props:

  • tenantColored?: boolean - Use tenant primary color
  • variant?: 'text' | 'outlined' | 'contained' - Button variant
  • All MUI ButtonProps

Card

Tenant-aware card component based on MUI Card.

import { Card } from 'igloo-d2c-components'

<Card
  title="Card Title"
  content="Card content goes here"
  actions={<Button>Action</Button>}
  tenantAccent
/>

Props:

  • title?: React.ReactNode - Card title
  • content?: React.ReactNode - Card content
  • actions?: React.ReactNode - Card actions
  • tenantAccent?: boolean - Add tenant-colored top border
  • headerAction?: React.ReactNode - Action in header
  • All MUI CardProps

Banner

Promotional banner with tenant theming.

import { Banner } from 'igloo-d2c-components'

<Banner
  title="Special Offer"
  description="Limited time only"
  action={<Button>Learn More</Button>}
  gradient
/>

Props:

  • title: string - Banner title (required)
  • description?: string - Banner description
  • action?: React.ReactNode - Action button/element
  • gradient?: boolean - Use gradient background (default: true)
  • All MUI BoxProps

🎨 Hooks & Utilities

Hooks

useTenantTheme()

Access tenant theme configuration and ID.

import { useTenantTheme } from 'igloo-d2c-components'

function MyComponent() {
  const { theme, tenantId } = useTenantTheme()
  const primaryColor = theme.palette.primary.main

  return <div style={{ color: primaryColor }}>...</div>
}

useTenantId()

Get current tenant ID.

import { useTenantId } from 'igloo-d2c-components'

function MyComponent() {
  const tenantId = useTenantId() // 'igloo' | 'cimb' | 'ammetlife'
  return <div>Current tenant: {tenantId}</div>
}

useIsTenant()

Check if current tenant matches a specific ID.

import { useIsTenant } from 'igloo-d2c-components'

function MyComponent() {
  const isCIMB = useIsTenant('cimb')

  if (isCIMB) {
    return <CIMBSpecificFeature />
  }

  return <DefaultFeature />
}

Utility Functions

getTenantTheme()

Get theme configuration by tenant ID.

import { getTenantTheme } from 'igloo-d2c-components'

const theme = getTenantTheme('igloo')
console.log(theme.palette.primary.main) // '#5656F6'

Throws: Error if tenant ID is invalid

isValidTenantId()

Type guard to check if a string is a valid tenant ID.

import { isValidTenantId } from 'igloo-d2c-components'

if (isValidTenantId(userInput)) {
  const theme = getTenantTheme(userInput) // Type-safe!
}

getAvailableTenants()

Get list of all available tenant IDs.

import { getAvailableTenants } from 'igloo-d2c-components'

const tenants = getAvailableTenants()
// ['igloo', 'cimb', 'ammetlife']

getThemeColor()

Extract color from theme using dot notation.

import { getThemeColor } from 'igloo-d2c-components'

const color = getThemeColor(theme, 'primary.main', '#000')
// Returns theme.palette.primary.main or '#000' if not found

createThemeCSSVariables()

Create CSS variables from theme.

import { createThemeCSSVariables } from 'igloo-d2c-components'

const vars = createThemeCSSVariables(theme, '--my-app')
// { '--my-app-primary-main': '#5656F6', ... }

🔧 Development

Prerequisites

  • Node.js: >=16.20.0 <=18.x
  • Yarn: ^1.22.0 (recommended) or npm

Check your version:

node --version  # Should be 16.20.0 - 18.x
yarn --version  # Should be 1.22.x

Setup

# Clone the repository
git clone https://gitlab.iglooinsure.com/axinan/fe/d2c-component-library.git
cd d2c-component-library

# Install dependencies
yarn install

Build Commands

# Production build
yarn build

# Development mode (watch)
yarn dev

# Clean build artifacts
yarn clean

# Clean and rebuild
yarn clean && yarn build

Code Quality

# Lint code
yarn lint

# Type check
yarn type-check

Build Output

The library outputs unminified code targeting ES2015 for maximum compatibility:

dist/
├── cjs/
│   ├── index.js          # CommonJS bundle (unminified, ES2015)
│   └── index.js.map      # Source map
├── esm/
│   ├── index.js          # ES Module bundle (unminified, ES2015)
│   └── index.js.map      # Source map
└── types/
    └── index.d.ts        # TypeScript definitions

Why unminified?

  • ✅ Consuming apps handle minification
  • ✅ Better debugging experience
  • ✅ Better tree-shaking
  • ✅ No impact on final bundle size

Why ES2015?

  • ✅ Maximum compatibility with older webpack configs
  • ✅ No babel-loader required in consuming apps
  • ✅ Optional chaining (?.) transpiled to verbose checks
  • ✅ Works with webpack 4+

Project Structure

d2c-component-library/
├── src/
│   ├── components/          # Component implementations
│   │   ├── Button/
│   │   ├── Card/
│   │   └── Banner/
│   ├── context/
│   │   └── TenantThemeContext.tsx
│   ├── themes/
│   │   └── index.ts        # ⭐ Centralized theme definitions
│   ├── types/
│   │   └── tenant.ts       # TypeScript types
│   ├── utils/
│   │   └── theme.ts        # Theme utilities
│   └── index.ts            # Main exports
├── dist/                    # Build output (generated)
├── examples/
│   └── usage-example.tsx
├── .storybook/             # Storybook configuration
├── rollup.config.cjs       # Rollup build config
├── tsconfig.json           # TypeScript config
├── package.json
├── README.md               # This file
└── CHANGELOG.md            # Version history

📦 Publishing

Prerequisites

  1. Ensure clean working directory:

    git status  # Should be clean
  2. Update version in package.json:

    {
      "version": "1.0.7"
    }
  3. Update CHANGELOG.md: Document changes in the new version section

  4. Build the library:

    yarn build

Publishing to NPM

Set up NPM token:

# Get token from https://www.npmjs.com/settings/YOUR_USERNAME/tokens
export NPM_AUTH_TOKEN="npm_your_actual_token"

# Or add to ~/.npmrc globally
//registry.npmjs.org/:_authToken=npm_your_token

Publish:

# Automated script with safety checks
./publish-to-npm.sh

# Or manual
yarn build
npm publish --access public

Publishing to GitLab Package Registry

Set up GitLab token:

# Get token from https://gitlab.com/-/profile/personal_access_tokens
# Scopes: api, read_registry, write_registry
export GITLAB_NPM_TOKEN="glpat-your-token"

Configure .npmrc for GitLab:

@igloo:registry=https://gitlab.com/api/v4/projects/YOUR_PROJECT_ID/packages/npm/
//gitlab.com/api/v4/projects/YOUR_PROJECT_ID/packages/npm/:_authToken=${GITLAB_NPM_TOKEN}

Publish:

yarn build
npm publish

CI/CD Publishing

The library includes a GitLab CI/CD configuration (.gitlab-ci.yml) that automatically:

  1. Runs on main branch or tags
  2. Lints and type-checks code
  3. Builds the library
  4. Publishes to registry (if tag)

Trigger CI/CD publish:

# Create and push a tag
git tag v1.0.7
git push origin v1.0.7

Version Management

Semantic Versioning:

  • Major (1.0.0 → 2.0.0): Breaking changes
  • Minor (1.0.0 → 1.1.0): New features, backwards compatible
  • Patch (1.0.0 → 1.0.1): Bug fixes

Update version:

# Manually in package.json
"version": "1.0.7"

# Or using npm version
npm version patch  # 1.0.6 → 1.0.7
npm version minor  # 1.0.6 → 1.1.0
npm version major  # 1.0.6 → 2.0.0

Post-Publishing

After publishing:

  1. Tag the release:

    git tag v1.0.7
    git push origin v1.0.7
  2. Update consuming apps:

    cd ../b2c-web-demo
    yarn upgrade igloo-d2c-components@latest
  3. Announce the release to the team


📖 Storybook

The library includes Storybook for component documentation and testing.

Running Storybook

# Start Storybook dev server
yarn storybook
# Opens at http://localhost:6006

# Build static Storybook
yarn build-storybook
# Output in storybook-static/

Storybook Features

  • Component Playground - Interactive component testing
  • Props Documentation - Auto-generated from TypeScript
  • Theme Switching - Test with different tenant themes
  • Responsive Design - Test different viewports
  • Accessibility - Built-in a11y addon

Adding Stories

Create a .stories.tsx file next to your component:

// src/components/MyComponent/MyComponent.stories.tsx
import type { Meta, StoryObj } from '@storybook/react'
import { TenantThemeProvider, iglooTheme } from '../../index'
import { MyComponent } from './MyComponent'

const meta: Meta<typeof MyComponent> = {
  title: 'Components/MyComponent',
  component: MyComponent,
  decorators: [
    (Story) => (
      <TenantThemeProvider tenantId="igloo" theme={iglooTheme}>
        <Story />
      </TenantThemeProvider>
    ),
  ],
}

export default meta
type Story = StoryObj<typeof MyComponent>

export const Default: Story = {
  args: {
    prop1: 'value1',
  },
}

🔬 Technical Details

Build Configuration

Rollup Configuration (rollup.config.cjs):

{
  input: 'src/index.ts',
  output: [
    {
      file: 'dist/cjs/index.js',
      format: 'cjs',
      sourcemap: true,
      exports: 'named',
      banner: '"use client"',
    },
    {
      file: 'dist/esm/index.js',
      format: 'esm',
      sourcemap: true,
      exports: 'named',
      banner: '"use client"',
    },
  ],
  plugins: [
    peerDepsExternal(),
    resolve(),
    commonjs(),
    typescript({
      tsconfig: './tsconfig.json',
      compilerOptions: {
        declaration: false,
        target: 'ES2015', // For compatibility
      },
    }),
    // NO terser() - libraries should not be minified
  ],
}

TypeScript Configuration

Target: ES2015 for maximum compatibility Module: ESNext for tree-shaking Strict: Enabled for type safety

Peer Dependencies

{
  "peerDependencies": {
    "@emotion/react": "^11.11.4",
    "@emotion/styled": "^11.11.5",
    "@mui/icons-material": "^5.15.20",
    "@mui/material": "^5.15.20",
    "@mui/styles": "^5.15.20",
    "react": "^17.0.0",
    "react-dom": "^17.0.0"
  }
}

Package Exports

{
  "main": "dist/cjs/index.js",
  "module": "dist/esm/index.js",
  "types": "dist/types/index.d.ts",
  "files": ["dist", "README.md"]
}

🐛 Troubleshooting

Webpack Module Parse Error

Error:

Module parse failed: Unexpected token

Cause: Webpack can't parse the library output.

Solution:

  1. Check library build target: The library should be built with ES2015 target (✅ already configured)
  2. Rebuild library:
    cd d2c-component-library
    yarn clean && yarn build
  3. Reinstall in consuming app:
    cd ../b2c-web-demo
    rm -rf node_modules/igloo-d2c-components
    yarn install

Prevention: The library is configured to output ES2015 JavaScript which is compatible with webpack 4+. Modern syntax like optional chaining (?.) is transpiled to verbose null checks.

Theme Not Found Error

Error:

Theme not found for tenant: xxx

Solution: Use valid tenant IDs: 'igloo', 'cimb', or 'ammetlife'.

import { isValidTenantId, getTenantTheme } from 'igloo-d2c-components'

if (isValidTenantId(tenantId)) {
  const theme = getTenantTheme(tenantId)
} else {
  console.error('Invalid tenant ID:', tenantId)
}

TypeScript Errors with Imports

Error:

Module '"igloo-d2c-components"' has no exported member 'iglooTheme'

Solution:

  1. Rebuild the library:

    cd d2c-component-library
    yarn build
  2. Reinstall in consuming app:

    cd ../b2c-web-demo
    yarn remove igloo-d2c-components
    yarn add igloo-d2c-components@file:../d2c-component-library
  3. Restart TypeScript server in your IDE:

    • VS Code: Cmd+Shift+P → "TypeScript: Restart TS Server"

Build Failures

Error: Build fails with memory issues

Solution:

export NODE_OPTIONS="--max-old-space-size=4096"
yarn build

Error: Type errors during build

Solution:

# Check types first
yarn type-check

# Fix any type errors, then build
yarn build

Missing Peer Dependencies

Warning: peer dependency "react" not installed

Solution: Install peer dependencies in consuming app:

yarn add react@17 react-dom@17 @mui/material@5 @emotion/react @emotion/styled

🎯 Best Practices

For Library Development

  1. Always build before testing - Run yarn build after changes
  2. Use ES2015 features - Avoid ES2020+ syntax
  3. Test in consuming apps - Test changes in b2c-web-demo
  4. Update CHANGELOG - Document all changes
  5. Version appropriately - Follow semantic versioning

For Library Usage

  1. Wrap with TenantThemeProvider - Required for theming to work
  2. Use pre-built themes - Import iglooTheme, cimbTheme, ammetlifeTheme
  3. Use tenantColored prop - For tenant-specific styling
  4. Maintain type safety - Use provided TypeScript types
  5. Extend via composition - Don't modify library components

For Theme Management

  1. Update themes in library - Not in consuming apps
  2. Test all tenants - When changing theme structure
  3. Document breaking changes - If theme interface changes
  4. Version bump - Increment version after theme changes

🤝 Contributing

Getting Started

  1. Fork the repository
  2. Create a feature branch:
    git checkout -b feature/my-new-feature
  3. Make your changes
  4. Test thoroughly:
    yarn lint
    yarn type-check
    yarn build
  5. Test in consuming app:
    cd ../b2c-web-demo
    yarn install
    yarn start-igloo-dev
  6. Commit your changes:
    git commit -m "feat: add new feature"
  7. Push to branch:
    git push origin feature/my-new-feature
  8. Create a Pull Request

Commit Message Format

Follow Conventional Commits:

<type>(<scope>): <description>

[optional body]

[optional footer]

Types:

  • feat: New feature
  • fix: Bug fix
  • docs: Documentation changes
  • style: Code style changes (formatting)
  • refactor: Code refactoring
  • test: Test additions/changes
  • chore: Maintenance tasks

Examples:

feat(themes): add new tenant theme
fix(Button): correct hover state color
docs: update installation guide
chore: bump version to 1.0.7

Adding a New Tenant

  1. Add theme to src/themes/index.ts:

    export const newTenantTheme: TenantThemeConfig = {
      palette: { /* ... */ },
      typography: { /* ... */ },
      logo: '/assets/new-tenant/logo.svg',
      favicon: 'https://...',
    }
    
    export const tenantThemes: Record<TenantId, TenantThemeConfig> = {
      igloo: iglooTheme,
      cimb: cimbTheme,
      ammetlife: ammetlifeTheme,
      newtenant: newTenantTheme, // Add here
    }
  2. Update TenantId type in src/types/tenant.ts:

    export type TenantId = 'igloo' | 'cimb' | 'ammetlife' | 'newtenant'
  3. Build and test:

    yarn build
    cd ../b2c-web-demo
    yarn install
  4. Update documentation and CHANGELOG


📄 License

MIT


👥 Team

Frontend Engineering Team - Axinan/Igloo


🔗 Links

  • Repository: https://gitlab.iglooinsure.com/axinan/fe/d2c-component-library
  • NPM Package: https://www.npmjs.com/package/igloo-d2c-components
  • Consuming App: https://gitlab.iglooinsure.com/axinan/fe/b2c-web-demo
  • Issue Tracker: https://gitlab.iglooinsure.com/axinan/fe/d2c-component-library/-/issues

📝 Quick Reference

Installation

# Local development
yarn add igloo-d2c-components@file:../d2c-component-library

# Production
yarn add igloo-d2c-components@latest

Import Themes

import { iglooTheme, cimbTheme, ammetlifeTheme, getTenantTheme } from 'igloo-d2c-components'

Import Components

import { Button, Card, Banner, TenantThemeProvider } from 'igloo-d2c-components'

Import Hooks

import { useTenantTheme, useTenantId, useIsTenant } from 'igloo-d2c-components'

Build & Publish

# Build
yarn build

# Publish to NPM
./publish-to-npm.sh

# Publish to GitLab
npm publish

Version: 1.0.6 Last Updated: November 12, 2025 Node.js: >=16.20.0 <=18.x Target: ES2015 Output: Unminified

For version history, see CHANGELOG.md