GL Icon Set
Version: 1.0.2
Package:@gift-card-market/gl-icon-set
Last Updated: January 16, 2026
A React library (with Web Component support) for displaying a geolocated category icon set with customizable titles/descriptions and a "Buy Now" button connected to Gift Card Market.
Table of Contents
Features
- Geolocated icon set: categories with normal/active icons, can fetch results based on user location.
- Customizable titles, colors, subtitles (supports HTML in the
titlefield). - Buy Now button with customizable text, color, and visibility.
- Can pass pre-defined results (
results) or request configuration for the library to call the API automatically. - Control API via ref (
GlIconSetHandle) and via controller helpers (disableCategory,enableCategory, etc.). - Supports Web Component for embedding in non-React pages.
- Written in TypeScript, built with tsup + Tailwind CSS.
Requirements
- React:
^18.0.0or^19.0.0. - Peer dependencies (install in your app):
npm install react react-dom react-slick slick-carousel @heroicons/react
- Node / npm: follow the version used to build in the repo (not strictly required, but Node 18+ is recommended).
Installation
1. Configure GitHub Packages (if package is still hosted on GitHub)
From package.json, the package is published to GitHub Packages with:
"publishConfig": {
"registry": "https://npm.pkg.github.com/@Gift-Card-Market",
"access": "public"
}
You need to configure npm to read from this registry:
- Create a GitHub Personal Access Token with
read:packagesscope at: https://github.com/settings/tokens - Login:
npm login --registry=https://npm.pkg.github.com --scope=@gift-card-market
Or add to your project's .npmrc file:
@gift-card-market:registry=https://npm.pkg.github.com
//npm.pkg.github.com/:_authToken=YOUR_GITHUB_TOKEN
2. Install the package
npm install @gift-card-market/gl-icon-set
3. Import CSS
// GL Icon Set styles
import '@gift-card-market/gl-icon-set/style.css';
// slick-carousel styles
import 'slick-carousel/slick/slick.css';
import 'slick-carousel/slick/slick-theme.css';
Quick Start with React
Basic Example
import '@gift-card-market/gl-dynamic-image/dist/style.css';
import { type CategoryConfig, GlIconSet, type GlIconSetHandle } from '@gift-card-market/gl-icon-set';
import '@gift-card-market/gl-icon-set/style.css';
import 'slick-carousel/slick/slick.css';
import 'slick-carousel/slick/slick-theme.css';
import { useRef } from 'react';
const data: CategoryConfig[] = [
{
id: 'celebrate-summer',
name: 'Celebrate Summer',
iconUrl: 'https://dev.giftcardmarket.com/wp-content/uploads/2025/07/sun.svg',
activeIconUrl: 'https://dev.giftcardmarket.com/wp-content/uploads/2025/07/sun-active.svg',
title: 'Lets Go <strong style="color: rgb(252, 191, 0);">Summer</strong>',
subtitle: 'Get ready for summer with our top gift card picks!',
active: true,
request: {
term: 'brunch',
program: 'restaurant',
},
},
{
id: 'local-choice-cards',
name: 'Local Choice Cards',
iconUrl: 'https://dev.giftcardmarket.com/wp-content/uploads/2025/07/choice.svg',
activeIconUrl: 'https://dev.giftcardmarket.com/wp-content/uploads/2025/07/choice-active.svg',
title: 'An Option for <strong style="color: rgb(238, 61, 132);">Any Preference</strong>',
subtitle: "Not sure what to gift, or want something more universal? We've got cards for any local preference.",
active: true,
results: [
{
name: 'Local Restaurants Card',
image: 'https://dev.giftcardmarket.com/wp-content/uploads/2025/07/gcm-choice-restaurants-v2.webp',
},
{
name: 'Local Spas Card',
image: 'https://dev.giftcardmarket.com/wp-content/uploads/2025/07/gcm-choice-spas-v2.webp',
},
{
name: 'Local Salons Card',
image: 'https://dev.giftcardmarket.com/wp-content/uploads/2025/07/gcm-choice-salons-v2.webp',
},
{
name: 'Local Home Services Card',
image: 'https://dev.giftcardmarket.com/wp-content/uploads/2025/07/gcm-choice-home-v2.webp',
},
{
name: 'Local Auto Services Card',
image: 'https://dev.giftcardmarket.com/wp-content/uploads/2025/07/gcm-choice-auto-v2.webp',
},
{
name: 'Local Personal Services Card',
image: 'https://dev.giftcardmarket.com/wp-content/uploads/2025/07/gcm-choice-personal-v2.webp',
},
],
},
{
id: 'restaurants',
name: 'Restaurants',
iconUrl: 'https://dev.giftcardmarket.com/wp-content/uploads/2025/07/restaurant.svg',
activeIconUrl: 'https://dev.giftcardmarket.com/wp-content/uploads/2025/07/restaurant-active.svg',
title: 'Mouthwatering <strong style="color: rgb(238, 61, 132);">Eats</strong>',
subtitle: 'The absolute local favorites, one text away.',
active: true,
request: {
term: 'restaurants',
program: 'restaurant',
},
},
{
id: 'spas-salons',
name: 'Spas & Salons',
iconUrl: 'https://dev.giftcardmarket.com/wp-content/uploads/2025/07/spa.svg',
activeIconUrl: 'https://dev.giftcardmarket.com/wp-content/uploads/2025/07/spa-active.svg',
title: 'Pamper & <strong style="color: rgb(108, 198, 177);">Relax</strong>',
subtitle: 'The absolute local favorites, one text away.',
active: true,
request: {
term: 'spas+salons',
program: 'spa',
},
},
{
id: 'best-sellers',
name: 'Best-Sellers',
iconUrl: 'https://dev.giftcardmarket.com/wp-content/uploads/2025/07/best-sellers.svg',
activeIconUrl: 'https://dev.giftcardmarket.com/wp-content/uploads/2025/07/best-sellers-active.svg',
title: 'The Cream of <strong style="color: rgb(238, 61, 132);">the Crop</strong>',
subtitle: 'The absolute local favorites, one text away.',
active: true,
request: {
term: 'best+sellers',
program: 'restaurant;spa;serviceprovider',
},
},
{
id: 'home-services',
name: 'Home Services',
iconUrl: 'https://dev.giftcardmarket.com/wp-content/uploads/2025/07/home.svg',
activeIconUrl: 'https://dev.giftcardmarket.com/wp-content/uploads/2025/07/home-active.svg',
title: 'Gift <strong style="color: rgb(108, 198, 177);">Peace of Mind</strong>',
subtitle: 'The absolute local favorites, one text away.',
active: true,
request: {
term: 'home+services',
program: 'serviceprovider',
},
},
{
id: 'auto-services',
name: 'Auto Services',
iconUrl: 'https://dev.giftcardmarket.com/wp-content/uploads/2025/07/car.svg',
activeIconUrl: 'https://dev.giftcardmarket.com/wp-content/uploads/2025/07/car-active.svg',
title: 'Gift <strong style="color: rgb(238, 61, 132);">Peace of Mind</strong>',
subtitle: 'The absolute local favorites, one text away.',
active: true,
request: {
term: 'auto+services',
program: 'serviceprovider',
},
},
{
id: 'personal-services',
name: 'Personal Services',
iconUrl: 'https://dev.giftcardmarket.com/wp-content/uploads/2025/07/personal.svg',
activeIconUrl: 'https://dev.giftcardmarket.com/wp-content/uploads/2025/07/personal-active.svg',
title: 'Gift <strong style="color: rgb(108, 198, 177);">Convenience</strong>',
subtitle: 'The absolute local favorites, one text away.',
active: true,
request: {
term: 'personal+services',
program: 'serviceprovider',
},
},
];
export default function IconSetPage() {
const ref = useRef<GlIconSetHandle | null>(null);
return (
<GlIconSet
ref={ref}
buttonConfig={{
buyNowText: 'Buy Now',
buyNowColor: '#ee3d84',
buyNowVisible: true,
themeColor: '#ee3d84',
buyNowTextColor: '#ffffff',
}}
categories={data}
maxCategories={8}
environment={'production'}
jwt={YOUR_JWT_TOKEN}
/>
);
}
Using ref (GlIconSetHandle) for control
function Toolbar() {
const ref = useRef<GlIconSetHandle | null>(null);
return (
<>
<button onClick={() => ref.current?.refresh()}>Refresh</button>
<button onClick={() => ref.current?.reset()}>Reset</button>
<button onClick={() => ref.current?.disableCategory('restaurants')}>
Disable restaurants
</button>
<button onClick={() => ref.current?.enableCategory('restaurants')}>
Enable restaurants
</button>
<button
onClick={async () => {
const results = await ref.current?.getResults();
console.log('Current results:', results);
}}
>
Log results
</button>
<GlIconSet
ref={ref}
jwt="YOUR_JWT_TOKEN"
environment="production"
categories={categories}
/>
</>
);
}
Detailed API
Props GlIconSet
The actual type is defined in glIconSetPros.ts. Summary:
| Prop | Type | Required | Description |
|---|---|---|---|
jwt | string | ✅ | JWT for calling Gift Card Market API. Access the following link to see instructions for obtaining JWT (access_token). |
environment | string (e.g., 'development', 'production', etc.) | ✅ | Backend environment; used to map to the corresponding domain. |
categories | CategoryConfig[] | ✅ | List of categories to display. |
buttonConfig | ButtonProps | ❌ | Customize Buy Now button and theme. If not provided, defaults will be used. |
maxCategories | number | ❌ | Maximum number of categories to display. Default is 8. |
Note: in the component, if
categories.lengthis greater thanmaxCategories(or8if not provided), the array will be sliced.
CategoryConfig
Defined in categoryConfig.ts (abbreviated):
export type BusinessInfo = {
name: string;
image: string;
};
export type CategoryConfig = {
id: string;
name: string;
iconUrl: string;
activeIconUrl: string;
title: string; // can contain HTML (see demo/main.tsx)
subtitle: string;
titleColor?: string;
subtitleColor?: string;
active?: boolean;
request?: {
term: string;
program: string;
};
results?: BusinessInfo[];
};
Typical usage patterns:
- With
request: the library will automatically call the API to fetch results based ontermandprogram. - With
results: you provide a pre-defined list of businesses (gift cards, merchants, etc.).
ButtonProps (buttonConfig)
In GlIconSet.tsx, there is a default configuration:
const configurationDefault = {
themeColor: '#0052cc',
buyNowText: 'Buy Now',
buyNowColor: '#0052cc',
buyNowTextColor: '#ffffff',
buyNowVisible: true,
};
The ButtonProps type is defined correspondingly in glIconSetPros.ts (summary):
buyNowVisible: boolean– show/hide the Buy Now button.buyNowText: string– button text.buyNowColor: string– button background color.buyNowTextColor?: string– text color.themeColor: string– main theme color of the component.
When you pass buttonConfig, any field not provided will use the default value.
GlIconSetHandle (ref API)
Full definition in glIconSetHandle.ts. Main methods:
refresh(): void– refresh the current results/state.reset(): void– reset to initial state (categories as initial).disableCategory(categoryId: string): void– disable a category.enableCategory(categoryId: string): void– re-enable a category.addCategory(config: CategoryConfig): void– add a new category to the list.removeCategory(categoryId: string): void– remove a category by id.getResults(): Promise<CategoryConfig[]> | undefined– get current results (async). Returnsundefinedif handle is not ready.searchCategory(categoryId: string): Promise<CategoryConfig[]> | undefined– trigger search for a specific category.
IconSetEvents (Event bus)
The file iconSetEvents.ts defines event names such as:
gl:iconset-readygl:category-clickedgl:buynow-clickedgl:errorgl:location-acquiredgl:location-deniedgl:category-loadedgl:search-complete
You can listen to these in both React and vanilla JS:
useEffect(() => {
const handler = (event: any) => {
console.log('Icon set event:', event.type, event.detail);
};
window.addEventListener('gl:buynow-clicked', handler);
return () => window.removeEventListener('gl:buynow-clicked', handler);
}, []);
The specific payload in event.detail depends on GeolocatedSetComponent – see the file src/components/GeolocatedSetComponent.tsx for the exact structure (merchant, categoryId, etc.).