initial commit

This commit is contained in:
rodolfomartinez 2026-02-02 14:17:16 -05:00
parent e468202f95
commit 423b9a25fb
24 changed files with 6670 additions and 0 deletions

View file

@ -0,0 +1,827 @@
# CLAUDE.md — Maple Icons WordPress Plugin
## Quick Reference
| Document | When to Reference |
|----------|-------------------|
| **CLAUDE.md** (this file) | Architecture, file structure, build order |
| **SECURITY.md** | Writing ANY PHP code (same patterns as Maple Local Fonts) |
---
## Project Overview
Build a WordPress plugin called **Maple Icons** that:
1. Fetches open-source icon sets from CDN and stores them locally
2. Provides preset icon sets: Heroicons, Lucide, Feather, Phosphor, Material
3. Only ONE icon set can be active at a time (though multiple can be downloaded)
4. Offers a Gutenberg block "Maple Icons" for inserting icons
5. Icons use `currentColor` to inherit text color from Global Styles
**Key principle:** Download once, serve locally. Zero runtime external requests after initial fetch.
---
## Requirements
- **Minimum PHP:** 7.4
- **Minimum WordPress:** 6.5 (for block.json apiVersion 3 and Global Styles)
- **License:** GPL-2.0-or-later
---
## Preset Icon Sets
All icons fetched from jsdelivr CDN with pinned versions:
| Set | Package | Version | Styles | ~Icons | viewBox |
|-----|---------|---------|--------|--------|---------|
| Heroicons | `heroicons` | 2.1.1 | outline, solid, mini | 290 | 24×24 |
| Lucide | `lucide-static` | 0.303.0 | icons | 1,400 | 24×24 |
| Feather | `feather-icons` | 4.29.1 | icons | 280 | 24×24 |
| Phosphor | `@phosphor-icons/core` | 2.1.1 | regular, bold, light, thin, fill, duotone | 1,200× styles | 256×256 (normalize) |
| Material | `@material-design-icons/svg` | 0.14.13 | filled, outlined, round, sharp, two-tone | 2,500 | 24×24 |
### CDN URL Patterns
```
Heroicons: https://cdn.jsdelivr.net/npm/heroicons@2.1.1/24/outline/{name}.svg
Lucide: https://cdn.jsdelivr.net/npm/lucide-static@0.303.0/icons/{name}.svg
Feather: https://cdn.jsdelivr.net/npm/feather-icons@4.29.1/dist/icons/{name}.svg
Phosphor: https://cdn.jsdelivr.net/npm/@phosphor-icons/core@2.1.1/assets/{style}/{name}.svg
Material: https://cdn.jsdelivr.net/npm/@material-design-icons/svg@0.14.13/{style}/{name}.svg
```
### SVG Normalization Required
| Set | Issue | Fix |
|-----|-------|-----|
| Phosphor | viewBox="0 0 256 256" | Normalize to 24×24 |
| Material | `fill="#000000"` hardcoded | Replace with `currentColor` |
| All | May have XML declarations, comments | Strip during save |
---
## User Flow
```
Admin visits Settings → Maple Icons (or plugin action link)
Sees list of preset icon sets with Download/Delete buttons
Clicks "Download" on Heroicons → progress bar → icons saved locally
Clicks "Set Active" to make Heroicons the active set
User inserts "Maple Icons" block in Gutenberg editor
Block shows + button → click → icon picker modal with search
User searches/filters → selects icon → SVG inserted inline
SVG uses currentColor → inherits from Global Styles
All icons served from local storage (wp-content/maple-icons/)
```
---
## File Structure
```
maple-icons-wp/
├── maple-icons.php # Main plugin file
├── index.php # Silence is golden
├── uninstall.php # Clean removal
├── readme.txt # WordPress.org readme
├── package.json # Block build config
├── includes/
│ ├── index.php
│ ├── class-mi-icon-sets.php # Preset icon set definitions
│ ├── class-mi-icon-registry.php # Icon management & search
│ ├── class-mi-downloader.php # CDN fetch & local storage
│ ├── class-mi-admin-page.php # Settings page
│ └── class-mi-ajax-handler.php # AJAX handlers
├── presets/ # Bundled manifests (icon names, tags)
│ ├── index.php
│ ├── heroicons.json
│ ├── lucide.json
│ ├── feather.json
│ ├── phosphor.json
│ └── material.json
├── build/ # Compiled block assets (generated)
│ ├── index.php
│ ├── index.js
│ ├── index.asset.php
│ └── style-index.css
├── src/ # Block source (for development)
│ ├── index.js # Block registration
│ ├── edit.js # Editor component
│ ├── save.js # Save component (inline SVG)
│ ├── icon-picker.js # Icon selection modal
│ ├── editor.scss # Editor-only styles
│ └── block.json # Block metadata
├── assets/
│ ├── index.php
│ ├── admin.css # Settings page styles
│ └── admin.js # Settings page JS (download progress, etc.)
└── languages/
├── index.php
└── maple-icons.pot
```
### Local Icon Storage
Icons are stored in:
```
wp-content/maple-icons/{set-slug}/{style}/{icon-name}.svg
```
Example:
```
wp-content/maple-icons/heroicons/outline/academic-cap.svg
wp-content/maple-icons/heroicons/solid/academic-cap.svg
wp-content/maple-icons/lucide/icons/activity.svg
wp-content/maple-icons/phosphor/regular/airplane.svg
```
Using `wp-content/maple-icons/` (not uploads) to avoid cleanup plugin interference.
---
## Class Responsibilities
### MI_Icon_Sets
Static definitions of all preset icon sets.
```php
class MI_Icon_Sets {
public static function get_all(): array;
public static function get(string $slug): ?array;
public static function get_cdn_url(string $slug, string $style, string $name): string;
public static function get_manifest_path(string $slug): string;
}
```
Returns structure:
```php
[
'slug' => 'heroicons',
'name' => 'Heroicons',
'version' => '2.1.1',
'license' => 'MIT',
'url' => 'https://heroicons.com',
'cdn_base' => 'https://cdn.jsdelivr.net/npm/heroicons@2.1.1/',
'styles' => [
'outline' => ['path' => '24/outline', 'label' => 'Outline'],
'solid' => ['path' => '24/solid', 'label' => 'Solid'],
'mini' => ['path' => '20/solid', 'label' => 'Mini'],
],
'default_style' => 'outline',
'viewbox' => '0 0 24 24',
'normalize' => false, // true for Phosphor (256→24)
'color_fix' => false, // true for Material (replace hardcoded colors)
]
```
### MI_Icon_Registry
Manages downloaded sets and provides icon search/retrieval.
```php
class MI_Icon_Registry {
public function get_downloaded_sets(): array;
public function get_active_set(): ?string;
public function set_active(string $slug): bool;
public function is_downloaded(string $slug): bool;
public function get_icons_for_set(string $slug, string $style): array;
public function search_icons(string $query, int $limit = 50): array;
public function get_icon_svg(string $slug, string $style, string $name): string|WP_Error;
public function delete_set(string $slug): bool;
}
```
### MI_Downloader
Handles fetching icons from CDN and storing locally.
```php
class MI_Downloader {
public function download_set(string $slug, callable $progress_callback = null): array|WP_Error;
public function download_icon(string $slug, string $style, string $name): string|WP_Error;
private function normalize_svg(string $svg, array $set_config): string;
private function get_local_path(string $slug, string $style, string $name): string;
}
```
### MI_Admin_Page
Settings page under Settings → Maple Icons.
- List all preset icon sets
- Show download status (downloaded/not downloaded)
- Download button with progress indicator
- Delete button for downloaded sets
- Radio buttons to select active set
- Preview sample icons from each downloaded set
### MI_Ajax_Handler
AJAX endpoints:
- `mi_download_set` — Download an icon set from CDN
- `mi_delete_set` — Delete a downloaded icon set
- `mi_set_active` — Set the active icon set
- `mi_search_icons` — Search icons in active set (for block picker)
- `mi_get_icon_svg` — Get specific icon SVG (for block)
---
## Settings Storage
```php
// Option name: maple_icons_settings
[
'active_set' => 'heroicons', // Slug of active set, or empty string
'downloaded_sets' => [
'heroicons' => [
'version' => '2.1.1',
'downloaded_at' => '2024-01-15 10:30:00',
'icon_count' => 876, // Total across all styles
],
'lucide' => [
'version' => '0.303.0',
'downloaded_at' => '2024-01-15 11:00:00',
'icon_count' => 1400,
],
],
]
```
---
## Manifest Format (presets/*.json)
Each preset ships with a manifest listing all icons:
```json
{
"slug": "heroicons",
"name": "Heroicons",
"version": "2.1.1",
"icons": [
{
"name": "academic-cap",
"tags": ["education", "graduation", "school", "hat"],
"category": "objects",
"styles": ["outline", "solid", "mini"]
},
{
"name": "adjustments-horizontal",
"tags": ["settings", "controls", "sliders"],
"category": "ui",
"styles": ["outline", "solid", "mini"]
}
]
}
```
Manifests are bundled with the plugin to avoid runtime dependency on jsdelivr API.
---
## Gutenberg Block Architecture
### Block Registration (block.json)
```json
{
"$schema": "https://schemas.wp.org/trunk/block.json",
"apiVersion": 3,
"name": "jetrails/maple-icons",
"version": "1.0.0",
"title": "Maple Icons",
"category": "design",
"icon": "star-filled",
"description": "Insert an icon from your downloaded icon sets.",
"keywords": ["icon", "svg", "symbol", "maple"],
"textdomain": "maple-icons",
"attributes": {
"iconSet": {
"type": "string",
"default": ""
},
"iconStyle": {
"type": "string",
"default": ""
},
"iconName": {
"type": "string",
"default": ""
},
"iconSVG": {
"type": "string",
"default": ""
},
"size": {
"type": "number",
"default": 24
},
"label": {
"type": "string",
"default": ""
},
"strokeWidth": {
"type": "number",
"default": 0
},
"strokeColor": {
"type": "string",
"default": ""
}
},
"supports": {
"html": false,
"align": ["left", "center", "right"],
"color": {
"text": true,
"background": true,
"gradients": true
},
"spacing": {
"margin": true,
"padding": true
},
"shadow": true
},
"editorScript": "file:./index.js",
"editorStyle": "file:./style-index.css"
}
```
### Block Style Controls (Inspector Panel)
The block sidebar will include these controls:
**Icon Settings:**
- Icon picker button (change icon)
- Size slider (8-256px, default 24)
- Accessibility label text input
**Color Settings (via WordPress supports):**
- Icon color (text color) — inherited by SVG via `currentColor`
- Background color
- Gradient support
**Stroke Settings (custom panel):**
- Stroke width slider (0-10px)
- Stroke color picker
**Spacing (via WordPress supports):**
- Padding controls
- Margin controls
**Effects:**
- Drop shadow presets (via WordPress `shadow` support)
### Style Application
```jsx
// In edit.js and save.js, compute styles:
const iconStyles = {
width: `${size}px`,
height: `${size}px`,
display: 'inline-flex',
alignItems: 'center',
justifyContent: 'center',
};
// Stroke is applied via CSS filter or SVG manipulation
const svgStyles = strokeWidth > 0 ? {
filter: `drop-shadow(0 0 0 ${strokeColor})`,
WebkitTextStroke: `${strokeWidth}px ${strokeColor}`,
} : {};
// Note: For true SVG stroke, we modify the SVG's stroke attribute
// This is handled in the SVG wrapper, not CSS
```
### SVG Stroke Handling
For stroke on SVG icons, we wrap the SVG output:
```jsx
// The SVG itself uses currentColor for fill/stroke
// Additional stroke effect applied via CSS or inline style
<span
className="wp-block-maple-icon__svg"
style={{
// Apply stroke via paint-order and stroke properties
'--mi-stroke-width': strokeWidth ? `${strokeWidth}px` : undefined,
'--mi-stroke-color': strokeColor || undefined,
}}
dangerouslySetInnerHTML={{ __html: iconSVG }}
/>
```
With CSS:
```css
.wp-block-maple-icon__svg svg {
stroke: var(--mi-stroke-color, currentColor);
stroke-width: var(--mi-stroke-width, 0);
paint-order: stroke fill;
}
```
### Block Behavior
**Initial State (no icon selected):**
- Shows + button placeholder
- Click opens icon picker modal
**With icon selected:**
- Displays inline SVG
- Sidebar shows: size control, accessibility label, change icon button
**Icon Picker Modal:**
- Search input (filters as you type)
- Style selector dropdown (if set has multiple styles)
- Grid of icon thumbnails
- Click to select → SVG fetched and stored in attributes
### Save Output (save.js)
```jsx
export default function save({ attributes }) {
const { iconSVG, size, label } = attributes;
if (!iconSVG) {
return null;
}
const blockProps = useBlockProps.save({
className: 'wp-block-maple-icon',
style: {
width: `${size}px`,
height: `${size}px`,
display: 'inline-flex',
},
});
return (
<span {...blockProps}>
<span
dangerouslySetInnerHTML={{ __html: iconSVG }}
role={label ? 'img' : 'presentation'}
aria-label={label || undefined}
aria-hidden={!label ? 'true' : undefined}
/>
</span>
);
}
```
---
## Download Process
### Batch Download Flow
1. User clicks "Download" for an icon set
2. Frontend disables button, shows progress bar
3. AJAX request to `mi_download_set`
4. Backend:
a. Load manifest from `presets/{slug}.json`
b. Create local directory structure
c. For each icon in manifest:
- Fetch SVG from CDN
- Normalize (viewBox, currentColor)
- Save to local filesystem
d. Update settings with download info
5. Return success with icon count
6. Frontend updates UI to show "Downloaded" state
### Batching Strategy
To avoid timeouts and memory issues:
- Process icons in batches of 50
- Use streaming/chunked approach
- Allow resume on failure (track progress in transient)
```php
// Download in batches
$batch_size = 50;
$icons = $manifest['icons'];
$total = count($icons);
for ($i = 0; $i < $total; $i += $batch_size) {
$batch = array_slice($icons, $i, $batch_size);
foreach ($batch as $icon) {
// Download each icon in batch
}
// Update progress transient
set_transient('mi_download_progress_' . $slug, [
'completed' => min($i + $batch_size, $total),
'total' => $total,
], HOUR_IN_SECONDS);
}
```
---
## SVG Sanitization
Same approach as original CLAUDE.md — strict allowlist of SVG elements and attributes.
```php
function mi_sanitize_svg($svg) {
$allowed_tags = [
'svg' => ['xmlns', 'viewbox', 'width', 'height', 'fill', 'stroke', ...],
'path' => ['d', 'fill', 'stroke', 'stroke-width', ...],
'circle' => ['cx', 'cy', 'r', 'fill', 'stroke', ...],
'rect' => ['x', 'y', 'width', 'height', 'rx', 'ry', ...],
'line' => ['x1', 'y1', 'x2', 'y2', ...],
'polyline' => ['points', ...],
'polygon' => ['points', ...],
'ellipse' => ['cx', 'cy', 'rx', 'ry', ...],
'g' => ['fill', 'stroke', 'transform', ...],
];
// Remove dangerous content
$svg = preg_replace('/<script\b[^>]*>.*?<\/script>/is', '', $svg);
$svg = preg_replace('/\son\w+\s*=/i', ' data-removed=', $svg);
return wp_kses($svg, $allowed_tags);
}
```
### SVG Normalization
```php
function mi_normalize_svg($svg, $set_config) {
// 1. Strip XML declaration
$svg = preg_replace('/<\?xml[^>]*\?>/i', '', $svg);
// 2. Strip comments
$svg = preg_replace('/<!--.*?-->/s', '', $svg);
// 3. Normalize viewBox for Phosphor (256 → 24)
if ($set_config['normalize']) {
$svg = preg_replace('/viewBox=["\']0 0 256 256["\']/', 'viewBox="0 0 24 24"', $svg);
}
// 4. Fix hardcoded colors for Material
if ($set_config['color_fix']) {
$svg = preg_replace('/fill=["\']#[0-9a-fA-F]{3,6}["\']/', 'fill="currentColor"', $svg);
$svg = preg_replace('/fill=["\']black["\']/', 'fill="currentColor"', $svg);
}
// 5. Ensure currentColor is used
// Most sets already use currentColor, but double-check
// 6. Remove width/height attributes (let CSS control)
$svg = preg_replace('/\s(width|height)=["\'][^"\']*["\']/', '', $svg);
return trim($svg);
}
```
---
## Admin Settings Page UI
```
┌─────────────────────────────────────────────────────────────────┐
│ Maple Icons │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ICON SETS │
│ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ ◉ Heroicons ✓ Downloaded │ │
│ │ 290 icons · Outline, Solid, Mini · MIT │ │
│ │ [Preview: ⚙ 🏠 👤 ✉ 🔔 ⭐] │ │
│ │ [Delete] │ │
│ ├─────────────────────────────────────────────────────────────┤ │
│ │ ○ Lucide ✓ Downloaded │ │
│ │ 1,400 icons · Icons · ISC │ │
│ │ [Preview: ⚙ 📁 📄 💾 🖨 ⬇] │ │
│ │ [Delete] │ │
│ ├─────────────────────────────────────────────────────────────┤ │
│ │ ○ Feather Not downloaded │ │
│ │ 280 icons · Icons · MIT │ │
│ │ [Download] │ │
│ ├─────────────────────────────────────────────────────────────┤ │
│ │ ○ Phosphor Not downloaded │ │
│ │ 7,200 icons · 6 styles · MIT │ │
│ │ [Download] │ │
│ ├─────────────────────────────────────────────────────────────┤ │
│ │ ○ Material Not downloaded │ │
│ │ 2,500 icons · 5 styles · Apache 2.0 │ │
│ │ [Download] │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │
│ ◉ = Active icon set (used in Maple Icons block) │
│ │
│ ─────────────────────────────────────────────────────────────── │
│ │
│ USAGE │
│ 1. Download one or more icon sets above │
│ 2. Select which set should be active (radio button) │
│ 3. Insert icons using the "Maple Icons" block in the editor │
│ 4. Icons inherit your theme's text color automatically │
│ │
└─────────────────────────────────────────────────────────────────┘
```
---
## Icon Picker Modal (Block Editor)
```
┌─────────────────────────────────────────────────────────────────┐
│ Select Icon [X] │
├─────────────────────────────────────────────────────────────────┤
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ 🔍 Search icons... │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │
│ Style: [Outline ▼] │
│ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ ┌───┐ ┌───┐ ┌───┐ ┌───┐ ┌───┐ ┌───┐ ┌───┐ ┌───┐ │ │
│ │ │ ⚙ │ │ 🏠 │ │ 👤 │ │ ✉ │ │ 🔔 │ │ ⭐ │ │ ❤ │ │ 🔍 │ │ │
│ │ └───┘ └───┘ └───┘ └───┘ └───┘ └───┘ └───┘ └───┘ │ │
│ │ cog home user mail bell star heart search │ │
│ │ │ │
│ │ ┌───┐ ┌───┐ ┌───┐ ┌───┐ ┌───┐ ┌───┐ ┌───┐ ┌───┐ │ │
│ │ │ + │ │ ✓ │ │ ✕ │ │ ⬆ │ │ ⬇ │ │ ◀ │ │ ▶ │ │ ↻ │ │ │
│ │ └───┘ └───┘ └───┘ └───┘ └───┘ └───┘ └───┘ └───┘ │ │
│ │ plus check x up down left right refresh │ │
│ │ │ │
│ │ [Load More...] │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │
│ Selected: arrow-right │
│ │
│ [Cancel] [Insert Icon] │
└─────────────────────────────────────────────────────────────────┘
```
---
## Build Order
### Phase 1: Foundation
1. `maple-icons.php` — Plugin header, constants, autoloader, activation hook
2. `index.php` files in ALL directories
3. `includes/class-mi-icon-sets.php` — Static preset definitions
### Phase 2: Download Infrastructure
4. `includes/class-mi-downloader.php` — CDN fetch, normalize, store
5. `includes/class-mi-icon-registry.php` — Downloaded set management
6. `includes/class-mi-ajax-handler.php` — Download/delete/activate endpoints
7. Create manifest files: `presets/*.json`
### Phase 3: Admin Interface
8. `includes/class-mi-admin-page.php` — Settings page
9. `assets/admin.css` — Settings page styles
10. `assets/admin.js` — Download progress, AJAX handlers
### Phase 4: Gutenberg Block
11. `src/block.json` — Block metadata
12. `src/index.js` — Block registration
13. `src/edit.js` — Editor component
14. `src/save.js` — Save component
15. `src/icon-picker.js` — Modal component
16. `src/editor.scss` — Editor styles
17. `package.json` + build
### Phase 5: Cleanup & Polish
18. `uninstall.php` — Clean removal
19. `readme.txt` — WordPress.org readme
20. Testing
---
## Constants
```php
define('MI_VERSION', '1.0.0');
define('MI_PLUGIN_DIR', plugin_dir_path(__FILE__));
define('MI_PLUGIN_URL', plugin_dir_url(__FILE__));
define('MI_PLUGIN_BASENAME', plugin_basename(__FILE__));
define('MI_ICONS_DIR', WP_CONTENT_DIR . '/maple-icons/');
define('MI_ICONS_URL', content_url('/maple-icons/'));
define('MI_PRESETS_DIR', MI_PLUGIN_DIR . 'presets/');
// Limits
define('MI_DOWNLOAD_BATCH_SIZE', 50);
define('MI_SEARCH_LIMIT', 50);
define('MI_DOWNLOAD_TIMEOUT', 10); // Per-icon timeout in seconds
```
---
## Security Checklist
Reference SECURITY.md for full details. Key points:
- [ ] ABSPATH check on every PHP file
- [ ] index.php in every directory
- [ ] Nonce verification FIRST in every AJAX handler
- [ ] Capability check SECOND (`manage_options` for settings, `edit_posts` for block)
- [ ] Validate icon set slugs against preset allowlist
- [ ] Validate style slugs against set's defined styles
- [ ] Sanitize all SVG content before storage
- [ ] Validate file paths (prevent path traversal)
- [ ] Use `wp_remote_get()` for CDN requests
- [ ] Escape all output
---
## WordPress Hooks Used
```php
// Activation/Deactivation
register_activation_hook(__FILE__, 'mi_activate');
register_deactivation_hook(__FILE__, 'mi_deactivate');
// Block registration
add_action('init', 'mi_register_block');
// Admin menu
add_action('admin_menu', 'mi_register_settings_page');
// Admin assets (settings page only)
add_action('admin_enqueue_scripts', 'mi_enqueue_admin_assets');
// Plugin action links (Settings link in plugin list)
add_filter('plugin_action_links_' . MI_PLUGIN_BASENAME, 'mi_add_action_links');
// AJAX handlers (admin only)
add_action('wp_ajax_mi_download_set', 'mi_ajax_download_set');
add_action('wp_ajax_mi_delete_set', 'mi_ajax_delete_set');
add_action('wp_ajax_mi_set_active', 'mi_ajax_set_active');
add_action('wp_ajax_mi_search_icons', 'mi_ajax_search_icons');
add_action('wp_ajax_mi_get_icon_svg', 'mi_ajax_get_icon_svg');
// WooCommerce HPOS compatibility
add_action('before_woocommerce_init', 'mi_declare_hpos_compatibility');
```
---
## Compatibility Notes
### WooCommerce HPOS
Declare compatibility (we don't touch orders):
```php
add_action('before_woocommerce_init', function() {
if (class_exists(\Automattic\WooCommerce\Utilities\FeaturesUtil::class)) {
\Automattic\WooCommerce\Utilities\FeaturesUtil::declare_compatibility(
'custom_order_tables',
__FILE__,
true
);
}
});
```
### Caching Plugins
Icons stored locally means no cache issues. SVG is inline in post_content.
### Wordfence
CDN requests only happen during admin download action, using standard `wp_remote_get()`.
### LearnDash / WPForms
No interference — we only add a block, no frontend hooks.
---
## Testing Checklist
### Download Flow
- [ ] Download Heroicons → all icons saved locally
- [ ] Download progress shows correctly
- [ ] Download Lucide (large set) → doesn't timeout
- [ ] Delete downloaded set → files removed
- [ ] Switch active set → setting persists
### Block Editor
- [ ] Insert Maple Icons block → shows placeholder
- [ ] Click + → opens icon picker
- [ ] Search filters icons correctly
- [ ] Style dropdown works (for sets with multiple styles)
- [ ] Select icon → SVG appears in editor
- [ ] Save post → icon persists
- [ ] Frontend → icon displays correctly
- [ ] Change text color in Global Styles → icon color changes
### Security
- [ ] Download without nonce → 403
- [ ] Download as non-admin → 403
- [ ] Invalid set slug → rejected
- [ ] Path traversal attempt → rejected
### Edge Cases
- [ ] No sets downloaded → block shows helpful message
- [ ] Active set deleted → block handles gracefully
- [ ] CDN unreachable during download → appropriate error
- [ ] Partial download failure → can retry/resume

View file

@ -0,0 +1,621 @@
# SECURITY.md — Maple Local Fonts Security Requirements
## Overview
This document covers all security requirements for the Maple Local Fonts plugin. Reference this when writing ANY PHP code.
---
## ABSPATH Check (Every PHP File)
Every PHP file MUST start with this check. No exceptions.
```php
<?php
if (!defined('ABSPATH')) {
exit;
}
```
---
## Silence is Golden Files
Create `index.php` in EVERY directory:
```php
<?php
// Silence is golden.
if (!defined('ABSPATH')) {
exit;
}
```
**Required locations:**
- `/maple-local-fonts/index.php`
- `/maple-local-fonts/includes/index.php`
- `/maple-local-fonts/assets/index.php`
- `/maple-local-fonts/languages/index.php`
---
## OWASP Compliance
### A1 - Injection Prevention
**SQL Injection:**
```php
// NEVER do this
$wpdb->query("SELECT * FROM table WHERE id = " . $_POST['id']);
// ALWAYS do this
$wpdb->get_results($wpdb->prepare(
"SELECT * FROM %i WHERE id = %d",
$table_name,
absint($_POST['id'])
));
```
**Note:** This plugin should rarely need direct SQL. Use WordPress APIs (`get_posts`, `wp_insert_post`, etc.) which handle escaping internally.
### A2 - Authentication
All admin actions require capability check:
```php
if (!current_user_can('edit_theme_options')) {
wp_die('Unauthorized', 'Error', ['response' => 403]);
}
```
### A3 - Sensitive Data
- No API keys (Google Fonts CSS2 API is public)
- No user credentials stored
- No PII collected
### A5 - Broken Access Control
**Order of checks for ALL AJAX handlers:**
```php
public function handle_ajax_action() {
// 1. Nonce verification FIRST
if (!check_ajax_referer('mlf_action_name', 'nonce', false)) {
wp_send_json_error(['message' => 'Security check failed'], 403);
}
// 2. Capability check SECOND
if (!current_user_can('edit_theme_options')) {
wp_send_json_error(['message' => 'Unauthorized'], 403);
}
// 3. Input validation THIRD
// ... validate all inputs ...
// 4. Process request
// ... actual logic ...
}
```
### A7 - Cross-Site Scripting (XSS)
**Escape ALL output:**
```php
// HTML content
echo esc_html($font_name);
// HTML attributes
echo '<input value="' . esc_attr($font_name) . '">';
// URLs
echo '<a href="' . esc_url($url) . '">';
// JavaScript data
wp_localize_script('mlf-admin', 'mlfData', [
'fontName' => esc_js($font_name), // Or let wp_localize_script handle it
]);
// Translatable strings with variables
printf(
esc_html__('Installed: %s', 'maple-local-fonts'),
esc_html($font_name)
);
```
**Never trust input for output:**
```php
// WRONG - XSS vulnerability
echo '<div>' . $_POST['font_name'] . '</div>';
// RIGHT - sanitize input, escape output
$font_name = sanitize_text_field($_POST['font_name']);
echo '<div>' . esc_html($font_name) . '</div>';
```
### A8 - Insecure Deserialization
```php
// NEVER use unserialize() on external data
$data = unserialize($_POST['data']); // DANGEROUS
// Use JSON instead
$data = json_decode(sanitize_text_field($_POST['data']), true);
if (json_last_error() !== JSON_ERROR_NONE) {
wp_send_json_error(['message' => 'Invalid data format']);
}
```
### A9 - Vulnerable Components
- No external PHP libraries
- Use only WordPress core functions
- Keep dependencies to zero
---
## Nonce Implementation
### Creating Nonces
**In admin page form:**
```php
wp_nonce_field('mlf_download_font', 'mlf_nonce');
```
**For AJAX (via wp_localize_script):**
```php
wp_localize_script('mlf-admin', 'mlfData', [
'ajaxUrl' => admin_url('admin-ajax.php'),
'nonce' => wp_create_nonce('mlf_download_font'),
]);
```
### Verifying Nonces
**AJAX handler:**
```php
// Returns false on failure, doesn't die (we handle response ourselves)
if (!check_ajax_referer('mlf_download_font', 'nonce', false)) {
wp_send_json_error(['message' => 'Security check failed'], 403);
}
```
**Form submission:**
```php
if (!wp_verify_nonce($_POST['mlf_nonce'], 'mlf_download_font')) {
wp_die('Security check failed');
}
```
### Nonce Names
Use consistent, descriptive nonce action names:
| Action | Nonce Name |
|--------|------------|
| Download font | `mlf_download_font` |
| Delete font | `mlf_delete_font` |
| Update settings | `mlf_update_settings` |
---
## Input Validation
### Font Name Validation
```php
$font_name = isset($_POST['font_name']) ? sanitize_text_field($_POST['font_name']) : '';
// Strict allowlist pattern - alphanumeric, spaces, hyphens only
if (!preg_match('/^[a-zA-Z0-9\s\-]+$/', $font_name)) {
wp_send_json_error(['message' => 'Invalid font name: only letters, numbers, spaces, and hyphens allowed']);
}
// Length limit
if (strlen($font_name) > 100) {
wp_send_json_error(['message' => 'Font name too long']);
}
// Not empty
if (empty($font_name)) {
wp_send_json_error(['message' => 'Font name required']);
}
```
### Weight Validation
```php
$weights = isset($_POST['weights']) ? (array) $_POST['weights'] : [];
// Convert to integers
$weights = array_map('absint', $weights);
// Strict allowlist
$allowed_weights = [100, 200, 300, 400, 500, 600, 700, 800, 900];
$weights = array_intersect($weights, $allowed_weights);
// Must have at least one
if (empty($weights)) {
wp_send_json_error(['message' => 'At least one weight required']);
}
```
### Style Validation
```php
$styles = isset($_POST['styles']) ? (array) $_POST['styles'] : [];
// Strict allowlist - only these two values ever
$allowed_styles = ['normal', 'italic'];
$styles = array_filter($styles, function($style) use ($allowed_styles) {
return in_array($style, $allowed_styles, true);
});
// Must have at least one
if (empty($styles)) {
wp_send_json_error(['message' => 'At least one style required']);
}
```
### Font Family ID Validation (for delete)
```php
$font_id = isset($_POST['font_id']) ? absint($_POST['font_id']) : 0;
if ($font_id < 1) {
wp_send_json_error(['message' => 'Invalid font ID']);
}
// Verify it exists and is a font family
$font = get_post($font_id);
if (!$font || $font->post_type !== 'wp_font_family') {
wp_send_json_error(['message' => 'Font not found']);
}
// Verify it's one we imported (not a theme font)
if (get_post_meta($font_id, '_mlf_imported', true) !== '1') {
wp_send_json_error(['message' => 'Cannot delete theme fonts']);
}
```
---
## File Operation Security
### Path Traversal Prevention
```php
/**
* Validate that a path is within the WordPress fonts directory.
* Prevents path traversal attacks.
*
* @param string $path Full path to validate
* @return bool True if path is safe, false otherwise
*/
function mlf_validate_font_path($path) {
$font_dir = wp_get_font_dir();
$fonts_path = wp_normalize_path(trailingslashit($font_dir['path']));
// Resolve to real path (handles ../ etc)
$real_path = realpath($path);
// If realpath fails, file doesn't exist yet - validate the directory
if ($real_path === false) {
$dir = dirname($path);
$real_dir = realpath($dir);
if ($real_dir === false) {
return false;
}
$real_path = wp_normalize_path($real_dir . '/' . basename($path));
} else {
$real_path = wp_normalize_path($real_path);
}
// Must be within fonts directory
return strpos($real_path, $fonts_path) === 0;
}
```
### Filename Sanitization
```php
/**
* Sanitize and validate a font filename.
*
* @param string $filename The filename to validate
* @return string|false Sanitized filename or false if invalid
*/
function mlf_sanitize_font_filename($filename) {
// WordPress sanitization first
$filename = sanitize_file_name($filename);
// Must have .woff2 extension
if (pathinfo($filename, PATHINFO_EXTENSION) !== 'woff2') {
return false;
}
// No path components
if ($filename !== basename($filename)) {
return false;
}
// Reasonable length
if (strlen($filename) > 200) {
return false;
}
return $filename;
}
```
### Safe File Writing
```php
/**
* Safely write a font file to the fonts directory.
*
* @param string $filename Sanitized filename
* @param string $content File content
* @return string|WP_Error File path on success, WP_Error on failure
*/
function mlf_write_font_file($filename, $content) {
// Validate filename
$safe_filename = mlf_sanitize_font_filename($filename);
if ($safe_filename === false) {
return new WP_Error('invalid_filename', 'Invalid filename');
}
// Get fonts directory
$font_dir = wp_get_font_dir();
$destination = trailingslashit($font_dir['path']) . $safe_filename;
// Validate path
if (!mlf_validate_font_path($destination)) {
return new WP_Error('invalid_path', 'Invalid file path');
}
// Ensure directory exists
if (!wp_mkdir_p($font_dir['path'])) {
return new WP_Error('mkdir_failed', 'Could not create fonts directory');
}
// Write file
global $wp_filesystem;
if (empty($wp_filesystem)) {
require_once ABSPATH . 'wp-admin/includes/file.php';
WP_Filesystem();
}
if (!$wp_filesystem->put_contents($destination, $content, FS_CHMOD_FILE)) {
return new WP_Error('write_failed', 'Could not write font file');
}
return $destination;
}
```
### Safe File Deletion
```php
/**
* Safely delete a font file.
*
* @param string $path Full path to the file
* @return bool True on success, false on failure
*/
function mlf_delete_font_file($path) {
// Validate path is within fonts directory
if (!mlf_validate_font_path($path)) {
return false;
}
// Must be a .woff2 file
if (pathinfo($path, PATHINFO_EXTENSION) !== 'woff2') {
return false;
}
// File must exist
if (!file_exists($path)) {
return true; // Already gone, that's fine
}
return wp_delete_file($path);
}
```
---
## HTTP Request Security
### Outbound Requests (Google Fonts)
```php
$response = wp_remote_get($url, [
'timeout' => 15,
'sslverify' => true, // Always verify SSL
'user-agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
]);
// Check for errors
if (is_wp_error($response)) {
// Log error, return gracefully
error_log('MLF: Google Fonts request failed - ' . $response->get_error_message());
return new WP_Error('request_failed', 'Could not connect to Google Fonts');
}
// Check HTTP status
$status = wp_remote_retrieve_response_code($response);
if ($status !== 200) {
return new WP_Error('http_error', 'Google Fonts returned status ' . $status);
}
// Get body
$body = wp_remote_retrieve_body($response);
if (empty($body)) {
return new WP_Error('empty_response', 'Empty response from Google Fonts');
}
```
### URL Validation (Google Fonts only)
```php
/**
* Validate that a URL is a legitimate Google Fonts URL.
*
* @param string $url URL to validate
* @return bool True if valid Google Fonts URL
*/
function mlf_is_valid_google_fonts_url($url) {
$parsed = wp_parse_url($url);
if (!$parsed || !isset($parsed['host'])) {
return false;
}
// Only allow Google Fonts domains
$allowed_hosts = [
'fonts.googleapis.com',
'fonts.gstatic.com',
];
return in_array($parsed['host'], $allowed_hosts, true);
}
```
---
## AJAX Handler Complete Template
```php
<?php
if (!defined('ABSPATH')) {
exit;
}
class MLF_Ajax_Handler {
public function __construct() {
add_action('wp_ajax_mlf_download_font', [$this, 'handle_download']);
add_action('wp_ajax_mlf_delete_font', [$this, 'handle_delete']);
// NEVER add wp_ajax_nopriv_ - admin only functionality
}
/**
* Handle font download AJAX request.
*/
public function handle_download() {
// 1. NONCE CHECK
if (!check_ajax_referer('mlf_download_font', 'nonce', false)) {
wp_send_json_error(['message' => 'Security check failed'], 403);
}
// 2. CAPABILITY CHECK
if (!current_user_can('edit_theme_options')) {
wp_send_json_error(['message' => 'Unauthorized'], 403);
}
// 3. INPUT VALIDATION
$font_name = isset($_POST['font_name']) ? sanitize_text_field($_POST['font_name']) : '';
if (empty($font_name) || !preg_match('/^[a-zA-Z0-9\s\-]+$/', $font_name) || strlen($font_name) > 100) {
wp_send_json_error(['message' => 'Invalid font name']);
}
$weights = isset($_POST['weights']) ? array_map('absint', (array) $_POST['weights']) : [];
$weights = array_intersect($weights, [100, 200, 300, 400, 500, 600, 700, 800, 900]);
if (empty($weights)) {
wp_send_json_error(['message' => 'At least one weight required']);
}
$styles = isset($_POST['styles']) ? (array) $_POST['styles'] : [];
$styles = array_intersect($styles, ['normal', 'italic']);
if (empty($styles)) {
wp_send_json_error(['message' => 'At least one style required']);
}
// 4. PROCESS REQUEST
try {
$downloader = new MLF_Font_Downloader();
$result = $downloader->download($font_name, $weights, $styles);
if (is_wp_error($result)) {
wp_send_json_error(['message' => $result->get_error_message()]);
}
wp_send_json_success([
'message' => sprintf('Successfully installed %s', esc_html($font_name)),
'font_id' => $result,
]);
} catch (Exception $e) {
error_log('MLF Download Error: ' . $e->getMessage());
wp_send_json_error(['message' => 'An unexpected error occurred']);
}
}
/**
* Handle font deletion AJAX request.
*/
public function handle_delete() {
// 1. NONCE CHECK
if (!check_ajax_referer('mlf_delete_font', 'nonce', false)) {
wp_send_json_error(['message' => 'Security check failed'], 403);
}
// 2. CAPABILITY CHECK
if (!current_user_can('edit_theme_options')) {
wp_send_json_error(['message' => 'Unauthorized'], 403);
}
// 3. INPUT VALIDATION
$font_id = isset($_POST['font_id']) ? absint($_POST['font_id']) : 0;
if ($font_id < 1) {
wp_send_json_error(['message' => 'Invalid font ID']);
}
// Verify font exists and is ours
$font = get_post($font_id);
if (!$font || $font->post_type !== 'wp_font_family') {
wp_send_json_error(['message' => 'Font not found']);
}
if (get_post_meta($font_id, '_mlf_imported', true) !== '1') {
wp_send_json_error(['message' => 'Cannot delete theme fonts']);
}
// 4. PROCESS REQUEST
try {
$registry = new MLF_Font_Registry();
$result = $registry->delete_font($font_id);
if (is_wp_error($result)) {
wp_send_json_error(['message' => $result->get_error_message()]);
}
wp_send_json_success(['message' => 'Font deleted successfully']);
} catch (Exception $e) {
error_log('MLF Delete Error: ' . $e->getMessage());
wp_send_json_error(['message' => 'An unexpected error occurred']);
}
}
}
```
---
## Security Checklist
Before committing any code:
- [ ] ABSPATH check at top of every PHP file
- [ ] index.php exists in every directory
- [ ] All AJAX handlers verify nonce first
- [ ] All AJAX handlers check capability second
- [ ] All user input sanitized with appropriate function
- [ ] All user input validated against allowlists where applicable
- [ ] All output escaped with appropriate function
- [ ] File paths validated to prevent traversal
- [ ] No direct SQL queries (use WordPress APIs)
- [ ] No `unserialize()` on user input
- [ ] No `eval()` or similar dynamic execution
- [ ] External URLs validated before use
- [ ] Error messages don't expose sensitive info

View file

@ -0,0 +1,560 @@
# WORDPRESS_COMPATIBILITY.md — WordPress & Plugin Compatibility
## Overview
This document covers compatibility requirements for WordPress core systems and popular plugins. Reference this when building the font registry class and integration points.
---
## WordPress Version Requirements
**Minimum: WordPress 6.5**
WordPress 6.5 introduced the Font Library API which this plugin depends on. Earlier versions will not work.
```php
// Check on activation
register_activation_hook(__FILE__, function() {
if (version_compare(get_bloginfo('version'), '6.5', '<')) {
deactivate_plugins(plugin_basename(__FILE__));
wp_die(
'Maple Local Fonts requires WordPress 6.5 or higher for Font Library support.',
'Plugin Activation Error',
['back_link' => true]
);
}
});
// Also check on admin init (in case WP was downgraded)
add_action('admin_init', function() {
if (version_compare(get_bloginfo('version'), '6.5', '<')) {
deactivate_plugins(plugin_basename(__FILE__));
add_action('admin_notices', function() {
echo '<div class="error"><p>Maple Local Fonts has been deactivated. It requires WordPress 6.5 or higher.</p></div>';
});
}
});
```
---
## WordPress Font Library API
### How It Works
WordPress 6.5+ stores fonts using custom post types:
| Post Type | Purpose |
|-----------|---------|
| `wp_font_family` | Font family (e.g., "Open Sans") |
| `wp_font_face` | Individual weight/style variant (child of family) |
Fonts are stored in `wp-content/fonts/` by default.
### Getting the Fonts Directory
```php
// ALWAYS use this function, never hardcode paths
$font_dir = wp_get_font_dir();
// Returns:
[
'path' => '/var/www/html/wp-content/fonts',
'url' => 'https://example.com/wp-content/fonts',
'subdir' => '',
'basedir' => '/var/www/html/wp-content/fonts',
'baseurl' => 'https://example.com/wp-content/fonts',
]
```
### Registering a Font Family
```php
/**
* Register a font family with WordPress Font Library.
*
* @param string $font_name Display name (e.g., "Open Sans")
* @param string $font_slug Slug (e.g., "open-sans")
* @param array $files Array of downloaded file data
* @return int|WP_Error Font family post ID or error
*/
function mlf_register_font_family($font_name, $font_slug, $files) {
// Check if font already exists
$existing = get_posts([
'post_type' => 'wp_font_family',
'name' => $font_slug,
'posts_per_page' => 1,
'post_status' => 'publish',
]);
if (!empty($existing)) {
return new WP_Error('font_exists', 'Font family already installed');
}
// Build font family settings
$font_family_settings = [
'name' => $font_name,
'slug' => $font_slug,
'fontFamily' => sprintf('"%s", sans-serif', $font_name),
'fontFace' => [],
];
// Add each font face
foreach ($files as $file) {
$font_dir = wp_get_font_dir();
$relative_path = str_replace($font_dir['path'], '', $file['path']);
$font_family_settings['fontFace'][] = [
'fontFamily' => $font_name,
'fontWeight' => $file['weight'],
'fontStyle' => $file['style'],
'src' => 'file:.' . $font_dir['basedir'] . $relative_path,
];
}
// Create font family post
$family_id = wp_insert_post([
'post_type' => 'wp_font_family',
'post_title' => $font_name,
'post_name' => $font_slug,
'post_status' => 'publish',
'post_content' => wp_json_encode($font_family_settings),
]);
if (is_wp_error($family_id)) {
return $family_id;
}
// Mark as imported by our plugin (for identification)
update_post_meta($family_id, '_mlf_imported', '1');
update_post_meta($family_id, '_mlf_import_date', current_time('mysql'));
// Create font face posts (children)
foreach ($files as $file) {
$font_dir = wp_get_font_dir();
$face_settings = [
'fontFamily' => $font_name,
'fontWeight' => $file['weight'],
'fontStyle' => $file['style'],
'src' => 'file:.' . $font_dir['baseurl'] . '/' . basename($file['path']),
];
wp_insert_post([
'post_type' => 'wp_font_face',
'post_parent' => $family_id,
'post_status' => 'publish',
'post_content' => wp_json_encode($face_settings),
]);
}
// Clear font caches
delete_transient('wp_font_library_fonts');
return $family_id;
}
```
### Deleting a Font Family
```php
/**
* Delete a font family and its files.
*
* @param int $family_id Font family post ID
* @return bool|WP_Error True on success, error on failure
*/
function mlf_delete_font_family($family_id) {
$family = get_post($family_id);
if (!$family || $family->post_type !== 'wp_font_family') {
return new WP_Error('not_found', 'Font family not found');
}
// Verify it's one we imported
if (get_post_meta($family_id, '_mlf_imported', true) !== '1') {
return new WP_Error('not_ours', 'Cannot delete fonts not imported by this plugin');
}
// Get font faces
$faces = get_children([
'post_parent' => $family_id,
'post_type' => 'wp_font_face',
]);
$font_dir = wp_get_font_dir();
// Delete font face files and posts
foreach ($faces as $face) {
$settings = json_decode($face->post_content, true);
if (isset($settings['src'])) {
// Convert file:. URL to path
$src = $settings['src'];
$src = str_replace('file:.', '', $src);
// Handle both URL and path formats
if (strpos($src, $font_dir['baseurl']) !== false) {
$file_path = str_replace($font_dir['baseurl'], $font_dir['path'], $src);
} else {
$file_path = $font_dir['path'] . '/' . basename($src);
}
// Validate path before deletion
if (mlf_validate_font_path($file_path) && file_exists($file_path)) {
wp_delete_file($file_path);
}
}
wp_delete_post($face->ID, true);
}
// Delete family post
wp_delete_post($family_id, true);
// Clear caches
delete_transient('wp_font_library_fonts');
return true;
}
```
### Listing Installed Fonts
```php
/**
* Get all fonts imported by this plugin.
*
* @return array Array of font data
*/
function mlf_get_imported_fonts() {
$fonts = get_posts([
'post_type' => 'wp_font_family',
'posts_per_page' => 100,
'post_status' => 'publish',
'meta_key' => '_mlf_imported',
'meta_value' => '1',
]);
$result = [];
foreach ($fonts as $font) {
$settings = json_decode($font->post_content, true);
// Get variants
$faces = get_children([
'post_parent' => $font->ID,
'post_type' => 'wp_font_face',
]);
$variants = [];
foreach ($faces as $face) {
$face_settings = json_decode($face->post_content, true);
$variants[] = [
'weight' => $face_settings['fontWeight'] ?? '400',
'style' => $face_settings['fontStyle'] ?? 'normal',
];
}
$result[] = [
'id' => $font->ID,
'name' => $settings['name'] ?? $font->post_title,
'slug' => $settings['slug'] ?? $font->post_name,
'variants' => $variants,
'import_date' => get_post_meta($font->ID, '_mlf_import_date', true),
];
}
return $result;
}
```
---
## Gutenberg FSE Integration
### How Fonts Appear in the Editor
Once registered via the Font Library API, fonts automatically appear in:
1. **Global Styles** → Typography → Font dropdown
2. **Block settings** → Typography → Font dropdown (when per-block typography is enabled)
No additional integration code is needed — WordPress handles this automatically.
### Theme.json Compatibility
**DO NOT:**
- Directly modify theme.json
- Filter `wp_theme_json_data_theme` to inject fonts (let Font Library handle it)
- Override global styles CSS directly
**DO:**
- Use the Font Library API (post types)
- Let WordPress generate CSS custom properties
- Trust the system
### CSS Custom Properties
When a font is applied in Global Styles, WordPress generates:
```css
body {
--wp--preset--font-family--open-sans: "Open Sans", sans-serif;
}
```
And applies it:
```css
body {
font-family: var(--wp--preset--font-family--open-sans);
}
```
Our plugin doesn't need to touch this — it's automatic.
---
## WooCommerce Compatibility
### HPOS (High-Performance Order Storage)
WooCommerce's HPOS moves order data from post meta to custom tables. We must declare compatibility.
```php
// Declare HPOS compatibility
add_action('before_woocommerce_init', function() {
if (class_exists(\Automattic\WooCommerce\Utilities\FeaturesUtil::class)) {
\Automattic\WooCommerce\Utilities\FeaturesUtil::declare_compatibility(
'custom_order_tables',
__FILE__,
true
);
}
});
```
### Why We're Compatible
Our plugin:
- Does NOT interact with orders at all
- Does NOT query wp_posts for order data
- Does NOT use wp_postmeta for order data
- Only uses wp_font_family and wp_font_face post types
We're inherently compatible because we don't touch WooCommerce data.
### Frontend Considerations
**DO NOT:**
- Override `.woocommerce` class styles
- Override `.wc-block-*` styles
- Target cart/checkout elements specifically
**DO:**
- Let WooCommerce elements inherit from body/heading fonts
- Let global styles cascade naturally
WooCommerce product titles, descriptions, and other text will naturally inherit the fonts set via Global Styles. No special handling needed.
---
## Wordfence Compatibility
### Potential Concerns
1. **Outbound requests** to Google Fonts during import
2. **AJAX endpoints** for admin actions
3. **File operations** in wp-content
### Why We're Compatible
**Outbound Requests:**
- Only occur during admin import (user-initiated action)
- Target well-known domains (fonts.googleapis.com, fonts.gstatic.com)
- Use standard `wp_remote_get()` which Wordfence allows
- No runtime external requests on frontend
**AJAX Endpoints:**
- Use standard `admin-ajax.php` (not custom endpoints)
- Include proper nonces
- Follow WordPress patterns that Wordfence expects
**File Operations:**
- Write only to `wp-content/fonts/` (WordPress default directory)
- Use WordPress Filesystem API
- Don't create executable files
### Testing with Wordfence
Test these scenarios with Wordfence active:
- [ ] Learning Mode: Import should succeed
- [ ] Enabled Mode: Import should succeed
- [ ] Rate Limiting: Admin AJAX not blocked
- [ ] Firewall: No false positives on font download
---
## LearnDash Compatibility
### Overview
LearnDash is a WordPress LMS that uses:
- Custom post types (courses, lessons, topics, quizzes)
- Custom templates
- Focus Mode (distraction-free learning)
### Why We're Compatible
Our plugin:
- Doesn't touch LearnDash post types
- Doesn't modify LearnDash templates
- Doesn't inject CSS on frontend
- Lets Global Styles cascade to LearnDash content
LearnDash course content, lesson text, and quiz questions will inherit the fonts set in Global Styles automatically.
### Focus Mode Consideration
LearnDash Focus Mode uses its own template. Fonts set via Global Styles will apply because:
- Focus Mode still loads theme.json styles
- CSS custom properties cascade to all content
- No special handling needed
**DO NOT:**
- Target `.learndash-*` classes specifically
- Override Focus Mode styles
- Inject custom CSS for LearnDash
---
## WPForms Compatibility
### Overview
WPForms renders forms via shortcodes and blocks. Form styling is handled by WPForms.
### Why We're Compatible
- Form labels and text inherit from body font
- We don't override `.wpforms-*` classes
- No JavaScript conflicts (we have no frontend JS)
### Consideration
If a user wants form text in a different font, they should use WPForms' built-in styling options or custom CSS — not expect our plugin to handle it.
---
## General Best Practices
### What We Hook Into
```php
// Admin menu
add_action('admin_menu', [$this, 'register_menu']);
// Admin assets (only on our page)
add_action('admin_enqueue_scripts', [$this, 'enqueue_admin_assets']);
// AJAX handlers
add_action('wp_ajax_mlf_download_font', [$this, 'handle_download']);
add_action('wp_ajax_mlf_delete_font', [$this, 'handle_delete']);
// WooCommerce HPOS compatibility
add_action('before_woocommerce_init', [$this, 'declare_hpos_compatibility']);
```
### What We DON'T Hook Into
```php
// NO frontend hooks
// add_action('wp_enqueue_scripts', ...); // DON'T DO THIS
// add_action('wp_head', ...); // DON'T DO THIS
// add_action('wp_footer', ...); // DON'T DO THIS
// NO theme modification hooks
// add_filter('wp_theme_json_data_theme', ...); // Let Font Library handle it
// NO WooCommerce hooks
// add_action('woocommerce_*', ...); // DON'T DO THIS
// NO content filters
// add_filter('the_content', ...); // DON'T DO THIS
```
---
## Conflict Debugging
If a user reports a conflict, check:
### 1. Plugin Load Order
Our plugin should load with default priority. Check if another plugin is:
- Modifying the Font Library
- Overriding font CSS
- Filtering theme.json
### 2. CSS Specificity
If fonts aren't applying:
- Check browser DevTools for CSS cascade
- Look for more specific selectors overriding global styles
- Check for `!important` declarations
### 3. Cache Issues
Font changes not appearing:
- Clear browser cache
- Clear any caching plugins (WP Rocket, W3TC, etc.)
- Clear CDN cache if applicable
- WordPress transients: `delete_transient('wp_font_library_fonts')`
### 4. JavaScript Errors
If admin page isn't working:
- Check browser console for JS errors
- Look for conflicts with other admin scripts
- Verify jQuery isn't being dequeued
---
## Compatibility Checklist
Before releasing:
### WordPress Core
- [ ] Works on WordPress 6.5
- [ ] Works on WordPress 6.6+
- [ ] Font Library API integration works
- [ ] Fonts appear in Global Styles
- [ ] Fonts apply correctly on frontend
### WooCommerce
- [ ] HPOS compatibility declared
- [ ] No errors in WooCommerce status page
- [ ] Product pages render correctly with custom fonts
- [ ] Cart/Checkout not affected
### Wordfence
- [ ] Import works with firewall enabled
- [ ] No blocked requests
- [ ] No false positive security alerts
### LearnDash
- [ ] Course content inherits fonts
- [ ] Focus Mode renders correctly
- [ ] No JavaScript conflicts
### WPForms
- [ ] Forms render correctly
- [ ] No styling conflicts
### Other
- [ ] No PHP errors in debug.log
- [ ] No JavaScript errors in console
- [ ] Admin page loads correctly
- [ ] No memory issues during import

View file

@ -0,0 +1,294 @@
/**
* Maple Icons - Admin Styles
*
* @package MapleIcons
*/
/* Admin page wrapper */
.mi-admin-wrap {
max-width: 1200px;
}
.mi-admin-intro {
background: #fff;
border: 1px solid #c3c4c7;
border-left: 4px solid #2271b1;
padding: 12px 16px;
margin: 20px 0;
}
.mi-admin-intro p {
margin: 0;
font-size: 14px;
}
/* Icon sets grid */
.mi-sets-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
gap: 20px;
margin: 20px 0;
}
/* Individual set card */
.mi-set-card {
background: #fff;
border: 1px solid #c3c4c7;
border-radius: 4px;
padding: 20px;
position: relative;
transition: border-color 0.2s, box-shadow 0.2s;
}
.mi-set-card:hover {
border-color: #2271b1;
}
.mi-set-card.mi-set-active {
border-color: #00a32a;
box-shadow: 0 0 0 1px #00a32a;
}
.mi-set-card.mi-set-downloading {
opacity: 0.8;
pointer-events: none;
}
/* Card header */
.mi-set-header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 12px;
}
.mi-set-name {
margin: 0;
font-size: 16px;
font-weight: 600;
color: #1d2327;
}
/* Badges */
.mi-badge {
display: inline-block;
padding: 2px 8px;
font-size: 11px;
font-weight: 600;
text-transform: uppercase;
border-radius: 3px;
}
.mi-badge-active {
background: #00a32a;
color: #fff;
}
.mi-badge-downloaded {
background: #dcdcde;
color: #50575e;
}
/* Set metadata */
.mi-set-meta {
display: flex;
flex-direction: column;
gap: 4px;
margin-bottom: 12px;
font-size: 13px;
color: #50575e;
}
.mi-set-count {
font-weight: 600;
color: #1d2327;
}
/* External link */
.mi-set-link {
display: inline-block;
margin-bottom: 16px;
font-size: 13px;
text-decoration: none;
}
.mi-set-link:hover {
text-decoration: underline;
}
/* Action buttons */
.mi-set-actions {
display: flex;
gap: 8px;
flex-wrap: wrap;
}
.mi-set-actions .button {
flex: 1;
text-align: center;
}
.mi-delete-btn {
color: #d63638 !important;
border-color: #d63638 !important;
}
.mi-delete-btn:hover {
background: #d63638 !important;
color: #fff !important;
}
/* Progress bar */
.mi-set-progress {
margin-top: 16px;
}
.mi-progress-bar {
height: 8px;
background: #dcdcde;
border-radius: 4px;
overflow: hidden;
margin-bottom: 8px;
}
.mi-progress-fill {
height: 100%;
background: #2271b1;
border-radius: 4px;
width: 0;
transition: width 0.3s ease;
}
.mi-progress-text {
font-size: 12px;
color: #50575e;
}
/* Messages */
.mi-set-message {
margin-top: 12px;
padding: 8px 12px;
border-radius: 4px;
font-size: 13px;
}
.mi-set-message.mi-message-success {
background: #edfaef;
border: 1px solid #00a32a;
color: #00450c;
}
.mi-set-message.mi-message-error {
background: #fcf0f1;
border: 1px solid #d63638;
color: #8a1f22;
}
.mi-set-message.mi-message-info {
background: #f0f6fc;
border: 1px solid #2271b1;
color: #135e96;
}
/* Usage section */
.mi-admin-usage,
.mi-admin-info {
background: #fff;
border: 1px solid #c3c4c7;
border-radius: 4px;
padding: 20px;
margin: 20px 0;
}
.mi-admin-usage h2,
.mi-admin-info h2 {
margin-top: 0;
font-size: 16px;
border-bottom: 1px solid #c3c4c7;
padding-bottom: 10px;
}
.mi-admin-usage ol {
margin: 16px 0 0;
padding-left: 24px;
}
.mi-admin-usage li {
margin-bottom: 8px;
font-size: 14px;
}
.mi-admin-info p {
font-size: 14px;
margin-bottom: 12px;
}
.mi-admin-info p:last-child {
margin-bottom: 0;
}
.mi-admin-info code {
background: #f0f0f1;
padding: 2px 6px;
border-radius: 3px;
font-size: 12px;
}
/* Loading spinner */
.mi-spinner {
display: inline-block;
width: 16px;
height: 16px;
border: 2px solid #c3c4c7;
border-top-color: #2271b1;
border-radius: 50%;
animation: mi-spin 0.8s linear infinite;
margin-right: 8px;
vertical-align: middle;
}
@keyframes mi-spin {
to {
transform: rotate(360deg);
}
}
/* Button loading state */
.button.mi-loading {
position: relative;
color: transparent !important;
}
.button.mi-loading::after {
content: '';
position: absolute;
top: 50%;
left: 50%;
width: 14px;
height: 14px;
margin: -7px 0 0 -7px;
border: 2px solid currentColor;
border-top-color: transparent;
border-radius: 50%;
animation: mi-spin 0.8s linear infinite;
}
.button-primary.mi-loading::after {
border-color: rgba(255, 255, 255, 0.3);
border-top-color: #fff;
}
/* Responsive adjustments */
@media screen and (max-width: 782px) {
.mi-sets-grid {
grid-template-columns: 1fr;
}
.mi-set-actions {
flex-direction: column;
}
.mi-set-actions .button {
width: 100%;
}
}

View file

@ -0,0 +1,255 @@
/**
* Maple Icons - Admin JavaScript
*
* @package MapleIcons
*/
(function($) {
'use strict';
/**
* Show message on a card.
*
* @param {jQuery} $card The card element.
* @param {string} message The message text.
* @param {string} type Message type: success, error, info.
*/
function showMessage($card, message, type) {
var $message = $card.find('.mi-set-message');
$message
.removeClass('mi-message-success mi-message-error mi-message-info')
.addClass('mi-message-' + type)
.text(message)
.show();
// Auto-hide success messages after 5 seconds.
if (type === 'success') {
setTimeout(function() {
$message.fadeOut();
}, 5000);
}
}
/**
* Hide message on a card.
*
* @param {jQuery} $card The card element.
*/
function hideMessage($card) {
$card.find('.mi-set-message').hide();
}
/**
* Show progress bar.
*
* @param {jQuery} $card The card element.
*/
function showProgress($card) {
$card.find('.mi-set-progress').show();
$card.find('.mi-set-actions').hide();
}
/**
* Hide progress bar.
*
* @param {jQuery} $card The card element.
*/
function hideProgress($card) {
$card.find('.mi-set-progress').hide();
$card.find('.mi-set-actions').show();
}
/**
* Update progress bar.
*
* @param {jQuery} $card The card element.
* @param {number} percentage Progress percentage (0-100).
* @param {string} text Progress text.
*/
function updateProgress($card, percentage, text) {
$card.find('.mi-progress-fill').css('width', percentage + '%');
$card.find('.mi-progress-text').text(text);
}
/**
* Poll download progress.
*
* @param {string} slug Icon set slug.
* @param {jQuery} $card The card element.
*/
function pollProgress(slug, $card) {
$.ajax({
url: miAdmin.ajaxUrl,
type: 'POST',
data: {
action: 'mi_get_progress',
nonce: miAdmin.nonce,
slug: slug
},
success: function(response) {
if (response.success && response.data.downloading) {
var percentage = response.data.percentage || 0;
var text = response.data.completed + ' / ' + response.data.total + ' icons';
updateProgress($card, percentage, text);
// Continue polling if still downloading.
setTimeout(function() {
pollProgress(slug, $card);
}, 1000);
}
}
});
}
/**
* Handle download button click.
*/
$(document).on('click', '.mi-download-btn', function(e) {
e.preventDefault();
var $btn = $(this);
var $card = $btn.closest('.mi-set-card');
var slug = $btn.data('slug');
if ($btn.hasClass('mi-loading')) {
return;
}
$btn.addClass('mi-loading');
$card.addClass('mi-set-downloading');
hideMessage($card);
showProgress($card);
updateProgress($card, 0, miAdmin.strings.downloading);
// Start polling for progress.
setTimeout(function() {
pollProgress(slug, $card);
}, 500);
$.ajax({
url: miAdmin.ajaxUrl,
type: 'POST',
data: {
action: 'mi_download_set',
nonce: miAdmin.nonce,
slug: slug
},
success: function(response) {
hideProgress($card);
$btn.removeClass('mi-loading');
$card.removeClass('mi-set-downloading');
if (response.success) {
showMessage($card, response.data.message || miAdmin.strings.downloadSuccess, 'success');
// Reload page to update UI state.
setTimeout(function() {
location.reload();
}, 1500);
} else {
showMessage($card, response.data.message || miAdmin.strings.downloadError, 'error');
}
},
error: function() {
hideProgress($card);
$btn.removeClass('mi-loading');
$card.removeClass('mi-set-downloading');
showMessage($card, miAdmin.strings.downloadError, 'error');
}
});
});
/**
* Handle delete button click.
*/
$(document).on('click', '.mi-delete-btn', function(e) {
e.preventDefault();
var $btn = $(this);
var $card = $btn.closest('.mi-set-card');
var slug = $btn.data('slug');
if ($btn.hasClass('mi-loading')) {
return;
}
if (!confirm(miAdmin.strings.confirmDelete)) {
return;
}
$btn.addClass('mi-loading');
hideMessage($card);
$.ajax({
url: miAdmin.ajaxUrl,
type: 'POST',
data: {
action: 'mi_delete_set',
nonce: miAdmin.nonce,
slug: slug
},
success: function(response) {
$btn.removeClass('mi-loading');
if (response.success) {
showMessage($card, response.data.message || miAdmin.strings.deleteSuccess, 'success');
// Reload page to update UI state.
setTimeout(function() {
location.reload();
}, 1500);
} else {
showMessage($card, response.data.message || miAdmin.strings.deleteError, 'error');
}
},
error: function() {
$btn.removeClass('mi-loading');
showMessage($card, miAdmin.strings.deleteError, 'error');
}
});
});
/**
* Handle activate button click.
*/
$(document).on('click', '.mi-activate-btn, .mi-deactivate-btn', function(e) {
e.preventDefault();
var $btn = $(this);
var $card = $btn.closest('.mi-set-card');
var slug = $btn.data('slug');
if ($btn.hasClass('mi-loading')) {
return;
}
$btn.addClass('mi-loading');
hideMessage($card);
$.ajax({
url: miAdmin.ajaxUrl,
type: 'POST',
data: {
action: 'mi_set_active',
nonce: miAdmin.nonce,
slug: slug
},
success: function(response) {
$btn.removeClass('mi-loading');
if (response.success) {
showMessage($card, response.data.message || miAdmin.strings.activateSuccess, 'success');
// Reload page to update UI state.
setTimeout(function() {
location.reload();
}, 1000);
} else {
showMessage($card, response.data.message || miAdmin.strings.activateError, 'error');
}
},
error: function() {
$btn.removeClass('mi-loading');
showMessage($card, miAdmin.strings.activateError, 'error');
}
});
});
})(jQuery);

View file

@ -0,0 +1,5 @@
<?php
// Silence is golden.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}

View file

@ -0,0 +1,224 @@
<?php
/**
* Admin Page class - Handles the settings page.
*
* @package MapleIcons
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Class MI_Admin_Page
*
* Handles the plugin settings page in WordPress admin.
*/
class MI_Admin_Page {
/**
* Constructor - Register admin hooks.
*/
public function __construct() {
add_action( 'admin_menu', array( $this, 'register_menu' ) );
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_assets' ) );
}
/**
* Register the admin menu item.
*/
public function register_menu() {
add_options_page(
__( 'Maple Icons', 'maple-icons' ),
__( 'Maple Icons', 'maple-icons' ),
'manage_options',
'maple-icons',
array( $this, 'render_page' )
);
}
/**
* Enqueue admin assets.
*
* @param string $hook_suffix The current admin page.
*/
public function enqueue_assets( $hook_suffix ) {
if ( 'settings_page_maple-icons' !== $hook_suffix ) {
return;
}
wp_enqueue_style(
'mi-admin',
MI_PLUGIN_URL . 'assets/admin.css',
array(),
MI_VERSION
);
wp_enqueue_script(
'mi-admin',
MI_PLUGIN_URL . 'assets/admin.js',
array( 'jquery' ),
MI_VERSION,
true
);
wp_localize_script(
'mi-admin',
'miAdmin',
array(
'ajaxUrl' => admin_url( 'admin-ajax.php' ),
'nonce' => wp_create_nonce( 'mi_admin_nonce' ),
'strings' => array(
'downloading' => __( 'Downloading...', 'maple-icons' ),
'deleting' => __( 'Deleting...', 'maple-icons' ),
'activating' => __( 'Activating...', 'maple-icons' ),
'confirmDelete' => __( 'Are you sure you want to delete this icon set?', 'maple-icons' ),
'downloadError' => __( 'Download failed. Please try again.', 'maple-icons' ),
'deleteError' => __( 'Delete failed. Please try again.', 'maple-icons' ),
'activateError' => __( 'Activation failed. Please try again.', 'maple-icons' ),
'downloadSuccess'=> __( 'Icon set downloaded successfully!', 'maple-icons' ),
'deleteSuccess' => __( 'Icon set deleted successfully!', 'maple-icons' ),
'activateSuccess'=> __( 'Icon set activated!', 'maple-icons' ),
),
)
);
}
/**
* Render the settings page.
*/
public function render_page() {
if ( ! current_user_can( 'manage_options' ) ) {
return;
}
$registry = MI_Icon_Registry::get_instance();
$all_sets = MI_Icon_Sets::get_all();
$downloaded = $registry->get_downloaded_sets();
$active_set = $registry->get_active_set();
?>
<div class="wrap mi-admin-wrap">
<h1><?php esc_html_e( 'Maple Icons', 'maple-icons' ); ?></h1>
<div class="mi-admin-intro">
<p><?php esc_html_e( 'Download icon sets from CDN and use them in the Gutenberg block editor. Only one icon set can be active at a time.', 'maple-icons' ); ?></p>
</div>
<div class="mi-icon-sets">
<h2><?php esc_html_e( 'Available Icon Sets', 'maple-icons' ); ?></h2>
<div class="mi-sets-grid">
<?php foreach ( $all_sets as $slug => $set ) : ?>
<?php
$is_downloaded = isset( $downloaded[ $slug ] );
$is_active = $active_set === $slug;
$icon_count = $is_downloaded ? $downloaded[ $slug ]['icon_count'] : 0;
$download_date = $is_downloaded ? $downloaded[ $slug ]['downloaded_at'] : '';
?>
<div class="mi-set-card <?php echo $is_active ? 'mi-set-active' : ''; ?> <?php echo $is_downloaded ? 'mi-set-downloaded' : ''; ?>" data-slug="<?php echo esc_attr( $slug ); ?>">
<div class="mi-set-header">
<h3 class="mi-set-name"><?php echo esc_html( $set['name'] ); ?></h3>
<?php if ( $is_active ) : ?>
<span class="mi-badge mi-badge-active"><?php esc_html_e( 'Active', 'maple-icons' ); ?></span>
<?php elseif ( $is_downloaded ) : ?>
<span class="mi-badge mi-badge-downloaded"><?php esc_html_e( 'Downloaded', 'maple-icons' ); ?></span>
<?php endif; ?>
</div>
<div class="mi-set-meta">
<span class="mi-set-license">
<?php
/* translators: %s: License name */
printf( esc_html__( 'License: %s', 'maple-icons' ), esc_html( $set['license'] ) );
?>
</span>
<span class="mi-set-styles">
<?php
/* translators: %s: Style names */
printf( esc_html__( 'Styles: %s', 'maple-icons' ), esc_html( implode( ', ', $set['styles'] ) ) );
?>
</span>
<?php if ( $is_downloaded && $icon_count > 0 ) : ?>
<span class="mi-set-count">
<?php
/* translators: %d: Number of icons */
printf( esc_html( _n( '%d icon', '%d icons', $icon_count, 'maple-icons' ) ), intval( $icon_count ) );
?>
</span>
<?php endif; ?>
</div>
<?php if ( ! empty( $set['url'] ) ) : ?>
<a href="<?php echo esc_url( $set['url'] ); ?>" class="mi-set-link" target="_blank" rel="noopener noreferrer">
<?php esc_html_e( 'View on website', 'maple-icons' ); ?> &rarr;
</a>
<?php endif; ?>
<div class="mi-set-actions">
<?php if ( ! $is_downloaded ) : ?>
<button type="button" class="button button-primary mi-download-btn" data-slug="<?php echo esc_attr( $slug ); ?>">
<?php esc_html_e( 'Download', 'maple-icons' ); ?>
</button>
<?php else : ?>
<?php if ( ! $is_active ) : ?>
<button type="button" class="button button-primary mi-activate-btn" data-slug="<?php echo esc_attr( $slug ); ?>">
<?php esc_html_e( 'Set Active', 'maple-icons' ); ?>
</button>
<?php else : ?>
<button type="button" class="button mi-deactivate-btn" data-slug="">
<?php esc_html_e( 'Deactivate', 'maple-icons' ); ?>
</button>
<?php endif; ?>
<button type="button" class="button mi-delete-btn" data-slug="<?php echo esc_attr( $slug ); ?>">
<?php esc_html_e( 'Delete', 'maple-icons' ); ?>
</button>
<?php endif; ?>
</div>
<div class="mi-set-progress" style="display: none;">
<div class="mi-progress-bar">
<div class="mi-progress-fill"></div>
</div>
<span class="mi-progress-text"></span>
</div>
<div class="mi-set-message" style="display: none;"></div>
</div>
<?php endforeach; ?>
</div>
</div>
<div class="mi-admin-usage">
<h2><?php esc_html_e( 'How to Use', 'maple-icons' ); ?></h2>
<ol>
<li><?php esc_html_e( 'Download one or more icon sets above.', 'maple-icons' ); ?></li>
<li><?php esc_html_e( 'Set one icon set as active.', 'maple-icons' ); ?></li>
<li><?php esc_html_e( 'In the Gutenberg editor, add a "Maple Icon" block.', 'maple-icons' ); ?></li>
<li><?php esc_html_e( 'Search and select an icon from your active set.', 'maple-icons' ); ?></li>
<li><?php esc_html_e( 'Customize size, color, and other settings in the block sidebar.', 'maple-icons' ); ?></li>
</ol>
</div>
<div class="mi-admin-info">
<h2><?php esc_html_e( 'About', 'maple-icons' ); ?></h2>
<p>
<?php esc_html_e( 'Maple Icons downloads SVG icons from CDN and stores them locally in your WordPress installation. Icons are sanitized for security and normalized for consistent rendering.', 'maple-icons' ); ?>
</p>
<p>
<?php esc_html_e( 'All icons use currentColor for styling, which means they automatically inherit text color from your theme or block settings.', 'maple-icons' ); ?>
</p>
<p>
<?php
printf(
/* translators: %s: Directory path */
esc_html__( 'Icons are stored in: %s', 'maple-icons' ),
'<code>' . esc_html( MI_ICONS_DIR ) . '</code>'
);
?>
</p>
</div>
</div>
<?php
}
}

View file

@ -0,0 +1,376 @@
<?php
/**
* AJAX Handler class - Handles all AJAX requests.
*
* @package MapleIcons
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Class MI_Ajax_Handler
*
* Handles all AJAX requests for the plugin.
*/
class MI_Ajax_Handler {
/**
* Constructor - Register AJAX handlers.
*/
public function __construct() {
// Admin AJAX handlers.
add_action( 'wp_ajax_mi_download_set', array( $this, 'handle_download_set' ) );
add_action( 'wp_ajax_mi_delete_set', array( $this, 'handle_delete_set' ) );
add_action( 'wp_ajax_mi_set_active', array( $this, 'handle_set_active' ) );
add_action( 'wp_ajax_mi_get_progress', array( $this, 'handle_get_progress' ) );
// Block editor AJAX handlers.
add_action( 'wp_ajax_mi_search_icons', array( $this, 'handle_search_icons' ) );
add_action( 'wp_ajax_mi_get_icon_svg', array( $this, 'handle_get_icon_svg' ) );
// No nopriv handlers - all functionality requires login.
}
/**
* Handle download set request.
*/
public function handle_download_set() {
// 1. Nonce verification.
if ( ! check_ajax_referer( 'mi_admin_nonce', 'nonce', false ) ) {
wp_send_json_error(
array( 'message' => __( 'Security check failed.', 'maple-icons' ) ),
403
);
}
// 2. Capability check.
if ( ! current_user_can( 'manage_options' ) ) {
wp_send_json_error(
array( 'message' => __( 'You do not have permission to do this.', 'maple-icons' ) ),
403
);
}
// 3. Input validation.
$slug = isset( $_POST['slug'] ) ? sanitize_key( $_POST['slug'] ) : '';
if ( empty( $slug ) ) {
wp_send_json_error(
array( 'message' => __( 'Icon set slug is required.', 'maple-icons' ) )
);
}
if ( ! MI_Icon_Sets::is_valid_slug( $slug ) ) {
wp_send_json_error(
array( 'message' => __( 'Invalid icon set.', 'maple-icons' ) )
);
}
// Check if already downloaded.
$registry = MI_Icon_Registry::get_instance();
if ( $registry->is_downloaded( $slug ) ) {
wp_send_json_error(
array( 'message' => __( 'This icon set is already downloaded.', 'maple-icons' ) )
);
}
// 4. Process download.
// Increase time limit for large downloads.
set_time_limit( 600 ); // 10 minutes.
$downloader = new MI_Downloader();
$result = $downloader->download_set( $slug );
if ( is_wp_error( $result ) ) {
wp_send_json_error(
array( 'message' => $result->get_error_message() )
);
}
if ( ! $result['success'] ) {
wp_send_json_error(
array(
'message' => sprintf(
/* translators: %1$d: downloaded count, %2$d: failed count */
__( 'Download completed with errors. %1$d downloaded, %2$d failed.', 'maple-icons' ),
$result['downloaded'],
$result['failed']
),
'errors' => array_slice( $result['errors'], 0, 10 ), // Limit errors shown.
'downloaded' => $result['downloaded'],
'failed' => $result['failed'],
)
);
}
// Mark as downloaded.
$registry->mark_downloaded( $slug, $result['downloaded'] );
// If no active set, make this one active.
if ( ! $registry->get_active_set() ) {
$registry->set_active( $slug );
}
$registry->refresh();
wp_send_json_success(
array(
'message' => sprintf(
/* translators: %d: number of icons */
__( 'Successfully downloaded %d icons.', 'maple-icons' ),
$result['downloaded']
),
'icon_count' => $result['downloaded'],
'is_active' => $registry->get_active_set() === $slug,
)
);
}
/**
* Handle delete set request.
*/
public function handle_delete_set() {
// 1. Nonce verification.
if ( ! check_ajax_referer( 'mi_admin_nonce', 'nonce', false ) ) {
wp_send_json_error(
array( 'message' => __( 'Security check failed.', 'maple-icons' ) ),
403
);
}
// 2. Capability check.
if ( ! current_user_can( 'manage_options' ) ) {
wp_send_json_error(
array( 'message' => __( 'You do not have permission to do this.', 'maple-icons' ) ),
403
);
}
// 3. Input validation.
$slug = isset( $_POST['slug'] ) ? sanitize_key( $_POST['slug'] ) : '';
if ( empty( $slug ) ) {
wp_send_json_error(
array( 'message' => __( 'Icon set slug is required.', 'maple-icons' ) )
);
}
if ( ! MI_Icon_Sets::is_valid_slug( $slug ) ) {
wp_send_json_error(
array( 'message' => __( 'Invalid icon set.', 'maple-icons' ) )
);
}
// 4. Delete the set.
$registry = MI_Icon_Registry::get_instance();
$result = $registry->delete_set( $slug );
if ( is_wp_error( $result ) ) {
wp_send_json_error(
array( 'message' => $result->get_error_message() )
);
}
wp_send_json_success(
array(
'message' => __( 'Icon set deleted successfully.', 'maple-icons' ),
)
);
}
/**
* Handle set active request.
*/
public function handle_set_active() {
// 1. Nonce verification.
if ( ! check_ajax_referer( 'mi_admin_nonce', 'nonce', false ) ) {
wp_send_json_error(
array( 'message' => __( 'Security check failed.', 'maple-icons' ) ),
403
);
}
// 2. Capability check.
if ( ! current_user_can( 'manage_options' ) ) {
wp_send_json_error(
array( 'message' => __( 'You do not have permission to do this.', 'maple-icons' ) ),
403
);
}
// 3. Input validation.
$slug = isset( $_POST['slug'] ) ? sanitize_key( $_POST['slug'] ) : '';
// Empty slug is allowed (to deactivate).
if ( ! empty( $slug ) && ! MI_Icon_Sets::is_valid_slug( $slug ) ) {
wp_send_json_error(
array( 'message' => __( 'Invalid icon set.', 'maple-icons' ) )
);
}
// 4. Set active.
$registry = MI_Icon_Registry::get_instance();
$result = $registry->set_active( $slug );
if ( is_wp_error( $result ) ) {
wp_send_json_error(
array( 'message' => $result->get_error_message() )
);
}
wp_send_json_success(
array(
'message' => empty( $slug )
? __( 'No icon set is now active.', 'maple-icons' )
: __( 'Icon set activated.', 'maple-icons' ),
'active_set' => $slug,
)
);
}
/**
* Handle get progress request.
*/
public function handle_get_progress() {
// 1. Nonce verification.
if ( ! check_ajax_referer( 'mi_admin_nonce', 'nonce', false ) ) {
wp_send_json_error(
array( 'message' => __( 'Security check failed.', 'maple-icons' ) ),
403
);
}
// 2. Capability check.
if ( ! current_user_can( 'manage_options' ) ) {
wp_send_json_error(
array( 'message' => __( 'You do not have permission to do this.', 'maple-icons' ) ),
403
);
}
// 3. Input validation.
$slug = isset( $_POST['slug'] ) ? sanitize_key( $_POST['slug'] ) : '';
if ( empty( $slug ) || ! MI_Icon_Sets::is_valid_slug( $slug ) ) {
wp_send_json_error(
array( 'message' => __( 'Invalid icon set.', 'maple-icons' ) )
);
}
// 4. Get progress.
$downloader = new MI_Downloader();
$progress = $downloader->get_progress( $slug );
if ( false === $progress ) {
wp_send_json_success(
array(
'downloading' => false,
'completed' => 0,
'total' => 0,
)
);
}
wp_send_json_success(
array(
'downloading' => true,
'completed' => $progress['completed'],
'total' => $progress['total'],
'percentage' => $progress['total'] > 0
? round( ( $progress['completed'] / $progress['total'] ) * 100 )
: 0,
)
);
}
/**
* Handle search icons request (for block editor).
*/
public function handle_search_icons() {
// 1. Nonce verification.
if ( ! check_ajax_referer( 'mi_block_nonce', 'nonce', false ) ) {
wp_send_json_error(
array( 'message' => __( 'Security check failed.', 'maple-icons' ) ),
403
);
}
// 2. Capability check (edit_posts for block usage).
if ( ! current_user_can( 'edit_posts' ) ) {
wp_send_json_error(
array( 'message' => __( 'You do not have permission to do this.', 'maple-icons' ) ),
403
);
}
// 3. Input validation.
$query = isset( $_POST['query'] ) ? sanitize_text_field( $_POST['query'] ) : '';
$style = isset( $_POST['style'] ) ? sanitize_key( $_POST['style'] ) : '';
$limit = isset( $_POST['limit'] ) ? absint( $_POST['limit'] ) : MI_SEARCH_LIMIT;
$offset = isset( $_POST['offset'] ) ? absint( $_POST['offset'] ) : 0;
// Limit the limit.
if ( $limit > 100 ) {
$limit = 100;
}
// 4. Search.
$registry = MI_Icon_Registry::get_instance();
$results = $registry->search_icons( $query, $style, $limit, $offset );
wp_send_json_success( $results );
}
/**
* Handle get icon SVG request (for block editor).
*/
public function handle_get_icon_svg() {
// 1. Nonce verification.
if ( ! check_ajax_referer( 'mi_block_nonce', 'nonce', false ) ) {
wp_send_json_error(
array( 'message' => __( 'Security check failed.', 'maple-icons' ) ),
403
);
}
// 2. Capability check.
if ( ! current_user_can( 'edit_posts' ) ) {
wp_send_json_error(
array( 'message' => __( 'You do not have permission to do this.', 'maple-icons' ) ),
403
);
}
// 3. Input validation.
$slug = isset( $_POST['set'] ) ? sanitize_key( $_POST['set'] ) : '';
$style = isset( $_POST['style'] ) ? sanitize_key( $_POST['style'] ) : '';
$name = isset( $_POST['name'] ) ? sanitize_file_name( $_POST['name'] ) : '';
if ( empty( $slug ) || empty( $style ) || empty( $name ) ) {
wp_send_json_error(
array( 'message' => __( 'Missing required parameters.', 'maple-icons' ) )
);
}
// 4. Get SVG.
$registry = MI_Icon_Registry::get_instance();
$svg = $registry->get_icon_svg( $slug, $style, $name );
if ( is_wp_error( $svg ) ) {
wp_send_json_error(
array( 'message' => $svg->get_error_message() )
);
}
wp_send_json_success(
array(
'svg' => $svg,
'set' => $slug,
'style' => $style,
'name' => $name,
)
);
}
}

View file

@ -0,0 +1,505 @@
<?php
/**
* Downloader class - Handles fetching icons from CDN and storing locally.
*
* @package MapleIcons
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Class MI_Downloader
*
* Downloads icon sets from CDN and stores them locally.
*/
class MI_Downloader {
/**
* Allowed SVG elements for sanitization.
*
* @var array
*/
private static $allowed_svg_elements = array(
'svg' => array(
'xmlns' => true,
'viewbox' => true,
'width' => true,
'height' => true,
'fill' => true,
'stroke' => true,
'stroke-width' => true,
'stroke-linecap' => true,
'stroke-linejoin' => true,
'class' => true,
'aria-hidden' => true,
'role' => true,
'focusable' => true,
'style' => true,
),
'path' => array(
'd' => true,
'fill' => true,
'stroke' => true,
'stroke-width' => true,
'stroke-linecap' => true,
'stroke-linejoin' => true,
'fill-rule' => true,
'clip-rule' => true,
'opacity' => true,
'fill-opacity' => true,
'stroke-opacity' => true,
),
'circle' => array(
'cx' => true,
'cy' => true,
'r' => true,
'fill' => true,
'stroke' => true,
'stroke-width' => true,
'opacity' => true,
),
'rect' => array(
'x' => true,
'y' => true,
'width' => true,
'height' => true,
'rx' => true,
'ry' => true,
'fill' => true,
'stroke' => true,
'stroke-width' => true,
'opacity' => true,
),
'line' => array(
'x1' => true,
'y1' => true,
'x2' => true,
'y2' => true,
'stroke' => true,
'stroke-width' => true,
'stroke-linecap' => true,
'opacity' => true,
),
'polyline' => array(
'points' => true,
'fill' => true,
'stroke' => true,
'stroke-width' => true,
'stroke-linecap' => true,
'stroke-linejoin' => true,
'opacity' => true,
),
'polygon' => array(
'points' => true,
'fill' => true,
'stroke' => true,
'stroke-width' => true,
'opacity' => true,
),
'ellipse' => array(
'cx' => true,
'cy' => true,
'rx' => true,
'ry' => true,
'fill' => true,
'stroke' => true,
'stroke-width' => true,
'opacity' => true,
),
'g' => array(
'fill' => true,
'stroke' => true,
'stroke-width' => true,
'transform' => true,
'opacity' => true,
),
'defs' => array(),
'clippath' => array(
'id' => true,
),
'use' => array(
'href' => true,
'xlink:href' => true,
),
);
/**
* Download an entire icon set.
*
* @param string $slug Icon set slug.
* @param callable|null $progress_callback Optional progress callback.
* @return array|WP_Error Download results or error.
*/
public function download_set( $slug, $progress_callback = null ) {
// Validate slug.
if ( ! MI_Icon_Sets::is_valid_slug( $slug ) ) {
return new WP_Error(
'invalid_set',
__( 'Invalid icon set.', 'maple-icons' )
);
}
$set_config = MI_Icon_Sets::get( $slug );
$manifest = MI_Icon_Sets::load_manifest( $slug );
if ( is_wp_error( $manifest ) ) {
return $manifest;
}
// Create base directory.
$base_dir = MI_ICONS_DIR . $slug;
if ( ! $this->ensure_directory( $base_dir ) ) {
return new WP_Error(
'directory_error',
__( 'Could not create icon directory.', 'maple-icons' )
);
}
// Create style directories.
foreach ( $set_config['styles'] as $style_slug => $style_config ) {
$style_dir = $base_dir . '/' . $style_slug;
if ( ! $this->ensure_directory( $style_dir ) ) {
return new WP_Error(
'directory_error',
__( 'Could not create style directory.', 'maple-icons' )
);
}
}
$icons = isset( $manifest['icons'] ) ? $manifest['icons'] : array();
$total_icons = count( $icons );
$downloaded = 0;
$failed = 0;
$errors = array();
$total_to_download = 0;
// Calculate total icons to download (icon × styles).
foreach ( $icons as $icon ) {
$icon_styles = isset( $icon['styles'] ) ? $icon['styles'] : array_keys( $set_config['styles'] );
$total_to_download += count( $icon_styles );
}
// Initialize progress transient.
set_transient(
'mi_download_progress_' . $slug,
array(
'completed' => 0,
'total' => $total_to_download,
'status' => 'downloading',
),
HOUR_IN_SECONDS
);
$current = 0;
// Download each icon.
foreach ( $icons as $icon ) {
$icon_name = $icon['name'];
$icon_styles = isset( $icon['styles'] ) ? $icon['styles'] : array_keys( $set_config['styles'] );
foreach ( $icon_styles as $style ) {
if ( ! isset( $set_config['styles'][ $style ] ) ) {
continue;
}
$result = $this->download_icon( $slug, $style, $icon_name );
if ( is_wp_error( $result ) ) {
$failed++;
$errors[] = sprintf( '%s/%s: %s', $style, $icon_name, $result->get_error_message() );
} else {
$downloaded++;
}
$current++;
// Update progress.
set_transient(
'mi_download_progress_' . $slug,
array(
'completed' => $current,
'total' => $total_to_download,
'status' => 'downloading',
),
HOUR_IN_SECONDS
);
// Call progress callback if provided.
if ( is_callable( $progress_callback ) ) {
call_user_func( $progress_callback, $current, $total_to_download );
}
// Allow some breathing room for the server.
if ( 0 === $current % MI_DOWNLOAD_BATCH_SIZE ) {
usleep( 100000 ); // 100ms pause every batch.
}
}
}
// Clear progress transient.
delete_transient( 'mi_download_progress_' . $slug );
return array(
'success' => $failed === 0,
'downloaded' => $downloaded,
'failed' => $failed,
'total' => $total_to_download,
'errors' => $errors,
);
}
/**
* Download a single icon from CDN.
*
* @param string $slug Icon set slug.
* @param string $style Style slug.
* @param string $name Icon name.
* @return string|WP_Error Local file path or error.
*/
public function download_icon( $slug, $style, $name ) {
// Validate inputs.
if ( ! MI_Icon_Sets::is_valid_slug( $slug ) ) {
return new WP_Error( 'invalid_set', __( 'Invalid icon set.', 'maple-icons' ) );
}
if ( ! MI_Icon_Sets::is_valid_style( $slug, $style ) ) {
return new WP_Error( 'invalid_style', __( 'Invalid icon style.', 'maple-icons' ) );
}
// Validate icon name (only allow alphanumeric, hyphens, underscores).
if ( ! preg_match( '/^[a-z0-9\-_]+$/i', $name ) ) {
return new WP_Error( 'invalid_name', __( 'Invalid icon name.', 'maple-icons' ) );
}
$cdn_url = MI_Icon_Sets::get_cdn_url( $slug, $style, $name );
$local_path = MI_Icon_Sets::get_local_path( $slug, $style, $name );
// Check if already downloaded.
if ( file_exists( $local_path ) ) {
return $local_path;
}
// Fetch from CDN.
$response = wp_remote_get(
$cdn_url,
array(
'timeout' => MI_DOWNLOAD_TIMEOUT,
'sslverify' => true,
)
);
if ( is_wp_error( $response ) ) {
return $response;
}
$status_code = wp_remote_retrieve_response_code( $response );
if ( 200 !== $status_code ) {
return new WP_Error(
'cdn_error',
sprintf(
/* translators: %d: HTTP status code */
__( 'CDN returned status %d.', 'maple-icons' ),
$status_code
)
);
}
$svg_content = wp_remote_retrieve_body( $response );
if ( empty( $svg_content ) ) {
return new WP_Error( 'empty_response', __( 'Empty response from CDN.', 'maple-icons' ) );
}
// Get set config for normalization.
$set_config = MI_Icon_Sets::get( $slug );
// Normalize and sanitize SVG.
$svg_content = $this->normalize_svg( $svg_content, $set_config );
$svg_content = $this->sanitize_svg( $svg_content );
if ( empty( $svg_content ) ) {
return new WP_Error( 'invalid_svg', __( 'Invalid or empty SVG content.', 'maple-icons' ) );
}
// Ensure directory exists.
$dir = dirname( $local_path );
if ( ! $this->ensure_directory( $dir ) ) {
return new WP_Error( 'directory_error', __( 'Could not create directory.', 'maple-icons' ) );
}
// Write file.
global $wp_filesystem;
if ( empty( $wp_filesystem ) ) {
require_once ABSPATH . 'wp-admin/includes/file.php';
WP_Filesystem();
}
if ( ! $wp_filesystem->put_contents( $local_path, $svg_content, FS_CHMOD_FILE ) ) {
return new WP_Error( 'write_error', __( 'Could not write SVG file.', 'maple-icons' ) );
}
return $local_path;
}
/**
* Normalize SVG content based on set configuration.
*
* @param string $svg SVG content.
* @param array $set_config Icon set configuration.
* @return string Normalized SVG content.
*/
private function normalize_svg( $svg, $set_config ) {
// Strip XML declaration.
$svg = preg_replace( '/<\?xml[^>]*\?>/i', '', $svg );
// Strip DOCTYPE.
$svg = preg_replace( '/<!DOCTYPE[^>]*>/i', '', $svg );
// Strip comments.
$svg = preg_replace( '/<!--.*?-->/s', '', $svg );
// Strip title and desc elements.
$svg = preg_replace( '/<title[^>]*>.*?<\/title>/is', '', $svg );
$svg = preg_replace( '/<desc[^>]*>.*?<\/desc>/is', '', $svg );
// Normalize viewBox for Phosphor (256 → 24).
if ( ! empty( $set_config['normalize'] ) ) {
$svg = preg_replace(
'/viewBox=["\']0\s+0\s+256\s+256["\']/i',
'viewBox="0 0 24 24"',
$svg
);
}
// Fix hardcoded colors for Material.
if ( ! empty( $set_config['color_fix'] ) ) {
// Replace hardcoded hex colors.
$svg = preg_replace( '/fill=["\']#[0-9a-fA-F]{3,6}["\']/', 'fill="currentColor"', $svg );
$svg = preg_replace( '/fill=["\']black["\']/', 'fill="currentColor"', $svg );
$svg = preg_replace( '/fill=["\']rgb\([^)]+\)["\']/', 'fill="currentColor"', $svg );
// Same for stroke.
$svg = preg_replace( '/stroke=["\']#[0-9a-fA-F]{3,6}["\']/', 'stroke="currentColor"', $svg );
$svg = preg_replace( '/stroke=["\']black["\']/', 'stroke="currentColor"', $svg );
}
// Remove width/height attributes (let CSS control size).
$svg = preg_replace( '/\s(width|height)=["\'][^"\']*["\']/i', '', $svg );
// Ensure there's no leading/trailing whitespace.
$svg = trim( $svg );
return $svg;
}
/**
* Sanitize SVG content to remove potentially dangerous elements.
*
* @param string $svg SVG content.
* @return string Sanitized SVG content.
*/
private function sanitize_svg( $svg ) {
// Remove script tags.
$svg = preg_replace( '/<script\b[^>]*>.*?<\/script>/is', '', $svg );
// Remove event handlers.
$svg = preg_replace( '/\s+on\w+\s*=/i', ' data-removed=', $svg );
// Remove javascript: URLs.
$svg = preg_replace( '/javascript:/i', 'removed:', $svg );
// Remove data: URLs (except for certain safe uses).
$svg = preg_replace( '/data:[^"\'>\s]+/i', 'removed:', $svg );
// Use WordPress kses with our allowed tags.
$svg = wp_kses( $svg, self::$allowed_svg_elements );
// Verify it's still a valid SVG.
if ( strpos( $svg, '<svg' ) === false || strpos( $svg, '</svg>' ) === false ) {
return '';
}
return $svg;
}
/**
* Ensure a directory exists, creating it if necessary.
*
* @param string $dir Directory path.
* @return bool True if directory exists or was created.
*/
private function ensure_directory( $dir ) {
if ( file_exists( $dir ) ) {
return is_dir( $dir );
}
return wp_mkdir_p( $dir );
}
/**
* Delete all icons for a set.
*
* @param string $slug Icon set slug.
* @return bool True on success.
*/
public function delete_set( $slug ) {
if ( ! MI_Icon_Sets::is_valid_slug( $slug ) ) {
return false;
}
$set_dir = MI_ICONS_DIR . $slug;
// Validate the path is within our icons directory.
$real_path = realpath( $set_dir );
$allowed_base = realpath( MI_ICONS_DIR );
if ( false === $real_path || false === $allowed_base ) {
// Directory doesn't exist, nothing to delete.
return true;
}
if ( strpos( $real_path, $allowed_base ) !== 0 ) {
// Path traversal attempt.
return false;
}
// Recursively delete the directory.
return $this->delete_directory( $set_dir );
}
/**
* Recursively delete a directory.
*
* @param string $dir Directory path.
* @return bool True on success.
*/
private function delete_directory( $dir ) {
if ( ! is_dir( $dir ) ) {
return true;
}
$files = array_diff( scandir( $dir ), array( '.', '..' ) );
foreach ( $files as $file ) {
$path = $dir . '/' . $file;
if ( is_dir( $path ) ) {
$this->delete_directory( $path );
} else {
wp_delete_file( $path );
}
}
return rmdir( $dir );
}
/**
* Get download progress for a set.
*
* @param string $slug Icon set slug.
* @return array|false Progress data or false if not downloading.
*/
public function get_progress( $slug ) {
return get_transient( 'mi_download_progress_' . $slug );
}
}

View file

@ -0,0 +1,416 @@
<?php
/**
* Icon Registry class - Manages downloaded sets and provides icon search/retrieval.
*
* @package MapleIcons
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Class MI_Icon_Registry
*
* Manages downloaded icon sets and provides search/retrieval functionality.
*/
class MI_Icon_Registry {
/**
* Singleton instance.
*
* @var MI_Icon_Registry|null
*/
private static $instance = null;
/**
* Cached settings.
*
* @var array|null
*/
private $settings = null;
/**
* Get singleton instance.
*
* @return MI_Icon_Registry
*/
public static function get_instance() {
if ( null === self::$instance ) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Constructor.
*/
private function __construct() {
$this->load_settings();
}
/**
* Load settings from database.
*/
private function load_settings() {
$this->settings = get_option(
'maple_icons_settings',
array(
'active_set' => '',
'downloaded_sets' => array(),
)
);
}
/**
* Save settings to database.
*
* @return bool True on success.
*/
private function save_settings() {
return update_option( 'maple_icons_settings', $this->settings );
}
/**
* Get all downloaded sets.
*
* @return array Array of downloaded set data.
*/
public function get_downloaded_sets() {
return isset( $this->settings['downloaded_sets'] ) ? $this->settings['downloaded_sets'] : array();
}
/**
* Get the active set slug.
*
* @return string|null Active set slug or null if none.
*/
public function get_active_set() {
$active = isset( $this->settings['active_set'] ) ? $this->settings['active_set'] : '';
return ! empty( $active ) ? $active : null;
}
/**
* Set the active icon set.
*
* @param string $slug Icon set slug.
* @return bool|WP_Error True on success, error on failure.
*/
public function set_active( $slug ) {
// Allow empty string to deactivate.
if ( empty( $slug ) ) {
$this->settings['active_set'] = '';
return $this->save_settings();
}
// Validate slug.
if ( ! MI_Icon_Sets::is_valid_slug( $slug ) ) {
return new WP_Error( 'invalid_set', __( 'Invalid icon set.', 'maple-icons' ) );
}
// Check if downloaded.
if ( ! $this->is_downloaded( $slug ) ) {
return new WP_Error( 'not_downloaded', __( 'Icon set is not downloaded.', 'maple-icons' ) );
}
$this->settings['active_set'] = $slug;
return $this->save_settings();
}
/**
* Check if a set is downloaded.
*
* @param string $slug Icon set slug.
* @return bool True if downloaded.
*/
public function is_downloaded( $slug ) {
$downloaded = $this->get_downloaded_sets();
return isset( $downloaded[ $slug ] );
}
/**
* Mark a set as downloaded.
*
* @param string $slug Icon set slug.
* @param int $icon_count Number of icons downloaded.
* @return bool True on success.
*/
public function mark_downloaded( $slug, $icon_count ) {
if ( ! MI_Icon_Sets::is_valid_slug( $slug ) ) {
return false;
}
$set_config = MI_Icon_Sets::get( $slug );
$this->settings['downloaded_sets'][ $slug ] = array(
'version' => $set_config['version'],
'downloaded_at' => current_time( 'mysql' ),
'icon_count' => $icon_count,
);
return $this->save_settings();
}
/**
* Remove a set from downloaded list.
*
* @param string $slug Icon set slug.
* @return bool True on success.
*/
public function unmark_downloaded( $slug ) {
if ( isset( $this->settings['downloaded_sets'][ $slug ] ) ) {
unset( $this->settings['downloaded_sets'][ $slug ] );
}
// If this was the active set, clear it.
if ( $this->settings['active_set'] === $slug ) {
$this->settings['active_set'] = '';
}
return $this->save_settings();
}
/**
* Get all icons for a set and style.
*
* @param string $slug Icon set slug.
* @param string $style Style slug.
* @return array Array of icon data.
*/
public function get_icons_for_set( $slug, $style ) {
if ( ! MI_Icon_Sets::is_valid_slug( $slug ) ) {
return array();
}
if ( ! MI_Icon_Sets::is_valid_style( $slug, $style ) ) {
return array();
}
// Load manifest.
$manifest = MI_Icon_Sets::load_manifest( $slug );
if ( is_wp_error( $manifest ) ) {
return array();
}
$icons = isset( $manifest['icons'] ) ? $manifest['icons'] : array();
$result = array();
foreach ( $icons as $icon ) {
$icon_styles = isset( $icon['styles'] ) ? $icon['styles'] : array_keys( MI_Icon_Sets::get( $slug )['styles'] );
// Only include if this icon has the requested style.
if ( in_array( $style, $icon_styles, true ) ) {
$result[] = array(
'name' => $icon['name'],
'tags' => isset( $icon['tags'] ) ? $icon['tags'] : array(),
'category' => isset( $icon['category'] ) ? $icon['category'] : '',
);
}
}
return $result;
}
/**
* Search icons in the active set.
*
* @param string $query Search query.
* @param string $style Optional style filter.
* @param int $limit Maximum results.
* @param int $offset Offset for pagination.
* @return array Search results.
*/
public function search_icons( $query = '', $style = '', $limit = MI_SEARCH_LIMIT, $offset = 0 ) {
$active_set = $this->get_active_set();
if ( ! $active_set ) {
return array(
'icons' => array(),
'total' => 0,
);
}
$set_config = MI_Icon_Sets::get( $active_set );
if ( ! $set_config ) {
return array(
'icons' => array(),
'total' => 0,
);
}
// Default to first style if not specified.
if ( empty( $style ) ) {
$style = $set_config['default_style'];
}
// Validate style.
if ( ! MI_Icon_Sets::is_valid_style( $active_set, $style ) ) {
$style = $set_config['default_style'];
}
// Load manifest.
$manifest = MI_Icon_Sets::load_manifest( $active_set );
if ( is_wp_error( $manifest ) ) {
return array(
'icons' => array(),
'total' => 0,
);
}
$icons = isset( $manifest['icons'] ) ? $manifest['icons'] : array();
$query = strtolower( trim( $query ) );
$results = array();
foreach ( $icons as $icon ) {
$icon_styles = isset( $icon['styles'] ) ? $icon['styles'] : array_keys( $set_config['styles'] );
// Skip if this icon doesn't have the requested style.
if ( ! in_array( $style, $icon_styles, true ) ) {
continue;
}
// If no query, include all.
if ( empty( $query ) ) {
$results[] = $icon;
continue;
}
// Search in name.
if ( strpos( strtolower( $icon['name'] ), $query ) !== false ) {
$results[] = $icon;
continue;
}
// Search in tags.
if ( isset( $icon['tags'] ) && is_array( $icon['tags'] ) ) {
foreach ( $icon['tags'] as $tag ) {
if ( strpos( strtolower( $tag ), $query ) !== false ) {
$results[] = $icon;
break;
}
}
}
}
$total = count( $results );
// Apply offset and limit.
$results = array_slice( $results, $offset, $limit );
// Format results.
$formatted = array();
foreach ( $results as $icon ) {
$formatted[] = array(
'name' => $icon['name'],
'tags' => isset( $icon['tags'] ) ? $icon['tags'] : array(),
'category' => isset( $icon['category'] ) ? $icon['category'] : '',
'set' => $active_set,
'style' => $style,
);
}
return array(
'icons' => $formatted,
'total' => $total,
'set' => $active_set,
'style' => $style,
'styles' => MI_Icon_Sets::get_style_labels( $active_set ),
);
}
/**
* Get SVG content for a specific icon.
*
* @param string $slug Icon set slug.
* @param string $style Style slug.
* @param string $name Icon name.
* @return string|WP_Error SVG content or error.
*/
public function get_icon_svg( $slug, $style, $name ) {
// Validate inputs.
if ( ! MI_Icon_Sets::is_valid_slug( $slug ) ) {
return new WP_Error( 'invalid_set', __( 'Invalid icon set.', 'maple-icons' ) );
}
if ( ! MI_Icon_Sets::is_valid_style( $slug, $style ) ) {
return new WP_Error( 'invalid_style', __( 'Invalid icon style.', 'maple-icons' ) );
}
// Validate icon name.
if ( ! preg_match( '/^[a-z0-9\-_]+$/i', $name ) ) {
return new WP_Error( 'invalid_name', __( 'Invalid icon name.', 'maple-icons' ) );
}
$local_path = MI_Icon_Sets::get_local_path( $slug, $style, $name );
// Validate path is within icons directory (prevent path traversal).
$real_path = realpath( $local_path );
$allowed_base = realpath( MI_ICONS_DIR );
if ( false === $real_path ) {
return new WP_Error( 'not_found', __( 'Icon not found.', 'maple-icons' ) );
}
if ( false === $allowed_base || strpos( $real_path, $allowed_base ) !== 0 ) {
return new WP_Error( 'invalid_path', __( 'Invalid icon path.', 'maple-icons' ) );
}
if ( ! file_exists( $real_path ) ) {
return new WP_Error( 'not_found', __( 'Icon not found.', 'maple-icons' ) );
}
$svg = file_get_contents( $real_path ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents
if ( false === $svg ) {
return new WP_Error( 'read_error', __( 'Could not read icon file.', 'maple-icons' ) );
}
return $svg;
}
/**
* Delete a downloaded set.
*
* @param string $slug Icon set slug.
* @return bool|WP_Error True on success, error on failure.
*/
public function delete_set( $slug ) {
if ( ! MI_Icon_Sets::is_valid_slug( $slug ) ) {
return new WP_Error( 'invalid_set', __( 'Invalid icon set.', 'maple-icons' ) );
}
if ( ! $this->is_downloaded( $slug ) ) {
return new WP_Error( 'not_downloaded', __( 'Icon set is not downloaded.', 'maple-icons' ) );
}
// Delete files.
$downloader = new MI_Downloader();
$deleted = $downloader->delete_set( $slug );
if ( ! $deleted ) {
return new WP_Error( 'delete_error', __( 'Could not delete icon files.', 'maple-icons' ) );
}
// Update settings.
$this->unmark_downloaded( $slug );
return true;
}
/**
* Get info about a downloaded set.
*
* @param string $slug Icon set slug.
* @return array|null Set info or null if not downloaded.
*/
public function get_downloaded_info( $slug ) {
$downloaded = $this->get_downloaded_sets();
return isset( $downloaded[ $slug ] ) ? $downloaded[ $slug ] : null;
}
/**
* Refresh settings from database.
*/
public function refresh() {
$this->load_settings();
}
}

View file

@ -0,0 +1,328 @@
<?php
/**
* Icon Sets class - Static definitions of all preset icon sets.
*
* @package MapleIcons
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Class MI_Icon_Sets
*
* Provides static definitions and utilities for preset icon sets.
*/
class MI_Icon_Sets {
/**
* Get all available preset icon sets.
*
* @return array Array of icon set configurations.
*/
public static function get_all() {
return array(
'heroicons' => array(
'slug' => 'heroicons',
'name' => 'Heroicons',
'version' => '2.1.1',
'license' => 'MIT',
'url' => 'https://heroicons.com',
'cdn_base' => 'https://cdn.jsdelivr.net/npm/heroicons@2.1.1/',
'styles' => array(
'outline' => array(
'path' => '24/outline',
'label' => 'Outline',
),
'solid' => array(
'path' => '24/solid',
'label' => 'Solid',
),
'mini' => array(
'path' => '20/solid',
'label' => 'Mini',
),
),
'default_style' => 'outline',
'viewbox' => '0 0 24 24',
'normalize' => false,
'color_fix' => false,
'description' => 'Beautiful hand-crafted SVG icons by the makers of Tailwind CSS.',
'icon_count' => 292,
),
'lucide' => array(
'slug' => 'lucide',
'name' => 'Lucide',
'version' => '0.303.0',
'license' => 'ISC',
'url' => 'https://lucide.dev',
'cdn_base' => 'https://cdn.jsdelivr.net/npm/lucide-static@0.303.0/',
'styles' => array(
'icons' => array(
'path' => 'icons',
'label' => 'Default',
),
),
'default_style' => 'icons',
'viewbox' => '0 0 24 24',
'normalize' => false,
'color_fix' => false,
'description' => 'Beautiful & consistent icon toolkit made by the community.',
'icon_count' => 1411,
),
'feather' => array(
'slug' => 'feather',
'name' => 'Feather',
'version' => '4.29.1',
'license' => 'MIT',
'url' => 'https://feathericons.com',
'cdn_base' => 'https://cdn.jsdelivr.net/npm/feather-icons@4.29.1/',
'styles' => array(
'icons' => array(
'path' => 'dist/icons',
'label' => 'Default',
),
),
'default_style' => 'icons',
'viewbox' => '0 0 24 24',
'normalize' => false,
'color_fix' => false,
'description' => 'Simply beautiful open source icons.',
'icon_count' => 287,
),
'phosphor' => array(
'slug' => 'phosphor',
'name' => 'Phosphor',
'version' => '2.1.1',
'license' => 'MIT',
'url' => 'https://phosphoricons.com',
'cdn_base' => 'https://cdn.jsdelivr.net/npm/@phosphor-icons/core@2.1.1/',
'styles' => array(
'regular' => array(
'path' => 'assets/regular',
'label' => 'Regular',
),
'bold' => array(
'path' => 'assets/bold',
'label' => 'Bold',
),
'light' => array(
'path' => 'assets/light',
'label' => 'Light',
),
'thin' => array(
'path' => 'assets/thin',
'label' => 'Thin',
),
'fill' => array(
'path' => 'assets/fill',
'label' => 'Fill',
),
'duotone' => array(
'path' => 'assets/duotone',
'label' => 'Duotone',
),
),
'default_style' => 'regular',
'viewbox' => '0 0 256 256',
'normalize' => true, // Needs viewBox normalization to 24x24.
'color_fix' => false,
'description' => 'A flexible icon family for interfaces, diagrams, presentations, and more.',
'icon_count' => 1248,
),
'material' => array(
'slug' => 'material',
'name' => 'Material Design Icons',
'version' => '0.14.13',
'license' => 'Apache-2.0',
'url' => 'https://fonts.google.com/icons',
'cdn_base' => 'https://cdn.jsdelivr.net/npm/@material-design-icons/svg@0.14.13/',
'styles' => array(
'filled' => array(
'path' => 'filled',
'label' => 'Filled',
),
'outlined' => array(
'path' => 'outlined',
'label' => 'Outlined',
),
'round' => array(
'path' => 'round',
'label' => 'Round',
),
'sharp' => array(
'path' => 'sharp',
'label' => 'Sharp',
),
'two-tone' => array(
'path' => 'two-tone',
'label' => 'Two Tone',
),
),
'default_style' => 'filled',
'viewbox' => '0 0 24 24',
'normalize' => false,
'color_fix' => true, // Needs hardcoded color replacement.
'description' => 'Material Design Icons by Google. Beautiful, delightful, and easy to use.',
'icon_count' => 2189,
),
);
}
/**
* Get a specific icon set by slug.
*
* @param string $slug Icon set slug.
* @return array|null Icon set configuration or null if not found.
*/
public static function get( $slug ) {
$sets = self::get_all();
return isset( $sets[ $slug ] ) ? $sets[ $slug ] : null;
}
/**
* Get all available set slugs.
*
* @return array Array of set slugs.
*/
public static function get_slugs() {
return array_keys( self::get_all() );
}
/**
* Validate that a slug is a valid preset.
*
* @param string $slug Slug to validate.
* @return bool True if valid, false otherwise.
*/
public static function is_valid_slug( $slug ) {
return in_array( $slug, self::get_slugs(), true );
}
/**
* Validate that a style is valid for a given set.
*
* @param string $slug Icon set slug.
* @param string $style Style slug.
* @return bool True if valid, false otherwise.
*/
public static function is_valid_style( $slug, $style ) {
$set = self::get( $slug );
if ( ! $set ) {
return false;
}
return isset( $set['styles'][ $style ] );
}
/**
* Get the CDN URL for a specific icon.
*
* @param string $slug Icon set slug.
* @param string $style Style slug.
* @param string $name Icon name.
* @return string|null CDN URL or null if invalid.
*/
public static function get_cdn_url( $slug, $style, $name ) {
$set = self::get( $slug );
if ( ! $set || ! isset( $set['styles'][ $style ] ) ) {
return null;
}
$style_config = $set['styles'][ $style ];
return $set['cdn_base'] . $style_config['path'] . '/' . $name . '.svg';
}
/**
* Get the local file path for a specific icon.
*
* @param string $slug Icon set slug.
* @param string $style Style slug.
* @param string $name Icon name.
* @return string Local file path.
*/
public static function get_local_path( $slug, $style, $name ) {
return MI_ICONS_DIR . $slug . '/' . $style . '/' . $name . '.svg';
}
/**
* Get the local URL for a specific icon.
*
* @param string $slug Icon set slug.
* @param string $style Style slug.
* @param string $name Icon name.
* @return string Local URL.
*/
public static function get_local_url( $slug, $style, $name ) {
return MI_ICONS_URL . $slug . '/' . $style . '/' . $name . '.svg';
}
/**
* Get the manifest file path for a set.
*
* @param string $slug Icon set slug.
* @return string Manifest file path.
*/
public static function get_manifest_path( $slug ) {
return MI_PRESETS_DIR . $slug . '.json';
}
/**
* Load and parse a manifest file.
*
* @param string $slug Icon set slug.
* @return array|WP_Error Manifest data or error.
*/
public static function load_manifest( $slug ) {
$path = self::get_manifest_path( $slug );
if ( ! file_exists( $path ) ) {
return new WP_Error(
'manifest_not_found',
sprintf(
/* translators: %s: Icon set name */
__( 'Manifest file not found for %s.', 'maple-icons' ),
$slug
)
);
}
$content = file_get_contents( $path ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents
if ( false === $content ) {
return new WP_Error(
'manifest_read_error',
__( 'Could not read manifest file.', 'maple-icons' )
);
}
$manifest = json_decode( $content, true );
if ( json_last_error() !== JSON_ERROR_NONE ) {
return new WP_Error(
'manifest_parse_error',
__( 'Could not parse manifest file.', 'maple-icons' )
);
}
return $manifest;
}
/**
* Get style labels for a set.
*
* @param string $slug Icon set slug.
* @return array Array of style labels.
*/
public static function get_style_labels( $slug ) {
$set = self::get( $slug );
if ( ! $set ) {
return array();
}
$labels = array();
foreach ( $set['styles'] as $style_slug => $style_config ) {
$labels[ $style_slug ] = $style_config['label'];
}
return $labels;
}
}

View file

@ -0,0 +1,5 @@
<?php
// Silence is golden.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}

View file

@ -0,0 +1,5 @@
<?php
// Silence is golden.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}

View file

@ -0,0 +1,5 @@
<?php
// Silence is golden.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}

View file

@ -0,0 +1,230 @@
<?php
/**
* Plugin Name: Maple Icons
* Plugin URI: https://jetrails.com/maple-icons
* Description: Insert beautiful open-source icons into your content with a Gutenberg block. Download icon sets from CDN and serve locally.
* Version: 1.0.0
* Requires at least: 6.5
* Requires PHP: 7.4
* Author: JetRails
* Author URI: https://jetrails.com
* License: GPL-2.0-or-later
* License URI: https://www.gnu.org/licenses/gpl-2.0.html
* Text Domain: maple-icons
* Domain Path: /languages
*
* @package MapleIcons
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Plugin constants.
*/
define( 'MI_VERSION', '1.0.0' );
define( 'MI_PLUGIN_FILE', __FILE__ );
define( 'MI_PLUGIN_DIR', plugin_dir_path( __FILE__ ) );
define( 'MI_PLUGIN_URL', plugin_dir_url( __FILE__ ) );
define( 'MI_PLUGIN_BASENAME', plugin_basename( __FILE__ ) );
define( 'MI_ICONS_DIR', WP_CONTENT_DIR . '/maple-icons/' );
define( 'MI_ICONS_URL', content_url( '/maple-icons/' ) );
define( 'MI_PRESETS_DIR', MI_PLUGIN_DIR . 'presets/' );
// Limits.
define( 'MI_DOWNLOAD_BATCH_SIZE', 50 );
define( 'MI_SEARCH_LIMIT', 50 );
define( 'MI_DOWNLOAD_TIMEOUT', 10 );
/**
* Autoloader for plugin classes.
*
* @param string $class_name The class name to load.
*/
function mi_autoloader( $class_name ) {
// Only handle our classes.
if ( strpos( $class_name, 'MI_' ) !== 0 ) {
return;
}
// Convert class name to filename.
$class_file = 'class-' . strtolower( str_replace( '_', '-', $class_name ) ) . '.php';
$class_path = MI_PLUGIN_DIR . 'includes/' . $class_file;
if ( file_exists( $class_path ) ) {
require_once $class_path;
}
}
spl_autoload_register( 'mi_autoloader' );
/**
* Plugin activation hook.
*/
function mi_activate() {
// Check WordPress version.
if ( version_compare( get_bloginfo( 'version' ), '6.5', '<' ) ) {
deactivate_plugins( MI_PLUGIN_BASENAME );
wp_die(
esc_html__( 'Maple Icons requires WordPress 6.5 or higher.', 'maple-icons' ),
esc_html__( 'Plugin Activation Error', 'maple-icons' ),
array( 'back_link' => true )
);
}
// Create icons directory if it doesn't exist.
if ( ! file_exists( MI_ICONS_DIR ) ) {
wp_mkdir_p( MI_ICONS_DIR );
}
// Initialize default settings.
$default_settings = array(
'active_set' => '',
'downloaded_sets' => array(),
);
if ( false === get_option( 'maple_icons_settings' ) ) {
add_option( 'maple_icons_settings', $default_settings );
}
// Flush rewrite rules.
flush_rewrite_rules();
}
register_activation_hook( MI_PLUGIN_FILE, 'mi_activate' );
/**
* Plugin deactivation hook.
*/
function mi_deactivate() {
// Clean up transients.
global $wpdb;
$wpdb->query(
"DELETE FROM {$wpdb->options} WHERE option_name LIKE '_transient_mi_%' OR option_name LIKE '_transient_timeout_mi_%'"
);
flush_rewrite_rules();
}
register_deactivation_hook( MI_PLUGIN_FILE, 'mi_deactivate' );
/**
* Check WordPress version on admin init (in case WP was downgraded).
*/
function mi_check_wp_version() {
if ( version_compare( get_bloginfo( 'version' ), '6.5', '<' ) ) {
deactivate_plugins( MI_PLUGIN_BASENAME );
add_action( 'admin_notices', 'mi_wp_version_notice' );
}
}
add_action( 'admin_init', 'mi_check_wp_version' );
/**
* Display admin notice for WordPress version requirement.
*/
function mi_wp_version_notice() {
echo '<div class="error"><p>';
esc_html_e( 'Maple Icons has been deactivated. It requires WordPress 6.5 or higher.', 'maple-icons' );
echo '</p></div>';
}
/**
* Initialize the plugin.
*/
function mi_init() {
// Load text domain.
load_plugin_textdomain( 'maple-icons', false, dirname( MI_PLUGIN_BASENAME ) . '/languages' );
// Register the Gutenberg block.
mi_register_block();
}
add_action( 'init', 'mi_init' );
/**
* Register the Maple Icons Gutenberg block.
*/
function mi_register_block() {
// Check if build directory exists.
$block_path = MI_PLUGIN_DIR . 'build';
if ( ! file_exists( $block_path ) ) {
return;
}
register_block_type( $block_path );
}
/**
* Enqueue block editor assets.
*/
function mi_enqueue_block_assets() {
// Only load in block editor.
if ( ! is_admin() ) {
return;
}
$screen = get_current_screen();
if ( ! $screen || ! $screen->is_block_editor() ) {
return;
}
// Localize script data for the block editor.
$active_set = '';
$settings = get_option( 'maple_icons_settings', array() );
if ( ! empty( $settings['active_set'] ) ) {
$active_set = $settings['active_set'];
}
wp_localize_script(
'maple-icon-editor-script',
'miBlock',
array(
'ajaxUrl' => admin_url( 'admin-ajax.php' ),
'nonce' => wp_create_nonce( 'mi_block_nonce' ),
'activeSet' => $active_set,
'settingsUrl' => admin_url( 'options-general.php?page=maple-icons' ),
)
);
}
add_action( 'enqueue_block_editor_assets', 'mi_enqueue_block_assets' );
/**
* Initialize admin functionality.
*/
function mi_admin_init() {
// Initialize admin page.
new MI_Admin_Page();
// Initialize AJAX handler.
new MI_Ajax_Handler();
}
add_action( 'admin_init', 'mi_admin_init' );
/**
* Add settings link to plugin action links.
*
* @param array $links Plugin action links.
* @return array Modified action links.
*/
function mi_add_action_links( $links ) {
$settings_link = sprintf(
'<a href="%s">%s</a>',
admin_url( 'options-general.php?page=maple-icons' ),
__( 'Settings', 'maple-icons' )
);
array_unshift( $links, $settings_link );
return $links;
}
add_filter( 'plugin_action_links_' . MI_PLUGIN_BASENAME, 'mi_add_action_links' );
/**
* Declare WooCommerce HPOS compatibility.
*/
function mi_declare_hpos_compatibility() {
if ( class_exists( \Automattic\WooCommerce\Utilities\FeaturesUtil::class ) ) {
\Automattic\WooCommerce\Utilities\FeaturesUtil::declare_compatibility(
'custom_order_tables',
MI_PLUGIN_FILE,
true
);
}
}
add_action( 'before_woocommerce_init', 'mi_declare_hpos_compatibility' );

View file

@ -0,0 +1,293 @@
{
"slug": "feather",
"name": "Feather",
"version": "4.29.1",
"icons": [
{"name": "activity", "tags": ["pulse", "health", "action", "motion"], "category": "health", "styles": ["icons"]},
{"name": "airplay", "tags": ["stream", "cast", "mirroring"], "category": "devices", "styles": ["icons"]},
{"name": "alert-circle", "tags": ["warning", "alert", "danger"], "category": "alerts", "styles": ["icons"]},
{"name": "alert-octagon", "tags": ["warning", "alert", "danger", "stop"], "category": "alerts", "styles": ["icons"]},
{"name": "alert-triangle", "tags": ["warning", "alert", "danger"], "category": "alerts", "styles": ["icons"]},
{"name": "align-center", "tags": ["text", "alignment", "center"], "category": "text", "styles": ["icons"]},
{"name": "align-justify", "tags": ["text", "alignment", "justify"], "category": "text", "styles": ["icons"]},
{"name": "align-left", "tags": ["text", "alignment", "left"], "category": "text", "styles": ["icons"]},
{"name": "align-right", "tags": ["text", "alignment", "right"], "category": "text", "styles": ["icons"]},
{"name": "anchor", "tags": ["link", "nav", "navigation"], "category": "navigation", "styles": ["icons"]},
{"name": "aperture", "tags": ["camera", "photo", "lens"], "category": "photography", "styles": ["icons"]},
{"name": "archive", "tags": ["box", "storage", "backup"], "category": "files", "styles": ["icons"]},
{"name": "arrow-down", "tags": ["direction", "down"], "category": "arrows", "styles": ["icons"]},
{"name": "arrow-down-circle", "tags": ["direction", "down", "circle"], "category": "arrows", "styles": ["icons"]},
{"name": "arrow-down-left", "tags": ["direction", "diagonal"], "category": "arrows", "styles": ["icons"]},
{"name": "arrow-down-right", "tags": ["direction", "diagonal"], "category": "arrows", "styles": ["icons"]},
{"name": "arrow-left", "tags": ["direction", "back", "previous"], "category": "arrows", "styles": ["icons"]},
{"name": "arrow-left-circle", "tags": ["direction", "back", "circle"], "category": "arrows", "styles": ["icons"]},
{"name": "arrow-right", "tags": ["direction", "forward", "next"], "category": "arrows", "styles": ["icons"]},
{"name": "arrow-right-circle", "tags": ["direction", "forward", "circle"], "category": "arrows", "styles": ["icons"]},
{"name": "arrow-up", "tags": ["direction", "up"], "category": "arrows", "styles": ["icons"]},
{"name": "arrow-up-circle", "tags": ["direction", "up", "circle"], "category": "arrows", "styles": ["icons"]},
{"name": "arrow-up-left", "tags": ["direction", "diagonal"], "category": "arrows", "styles": ["icons"]},
{"name": "arrow-up-right", "tags": ["direction", "diagonal"], "category": "arrows", "styles": ["icons"]},
{"name": "at-sign", "tags": ["email", "mention", "at"], "category": "communication", "styles": ["icons"]},
{"name": "award", "tags": ["achievement", "badge", "trophy"], "category": "objects", "styles": ["icons"]},
{"name": "bar-chart", "tags": ["analytics", "statistics", "graph"], "category": "charts", "styles": ["icons"]},
{"name": "bar-chart-2", "tags": ["analytics", "statistics", "graph"], "category": "charts", "styles": ["icons"]},
{"name": "battery", "tags": ["power", "energy", "charge"], "category": "devices", "styles": ["icons"]},
{"name": "battery-charging", "tags": ["power", "energy", "charge"], "category": "devices", "styles": ["icons"]},
{"name": "bell", "tags": ["notification", "alert", "alarm"], "category": "notifications", "styles": ["icons"]},
{"name": "bell-off", "tags": ["notification", "mute", "silent"], "category": "notifications", "styles": ["icons"]},
{"name": "bluetooth", "tags": ["wireless", "connection"], "category": "connectivity", "styles": ["icons"]},
{"name": "bold", "tags": ["text", "format", "strong"], "category": "text", "styles": ["icons"]},
{"name": "book", "tags": ["read", "library", "education"], "category": "objects", "styles": ["icons"]},
{"name": "book-open", "tags": ["read", "library", "education"], "category": "objects", "styles": ["icons"]},
{"name": "bookmark", "tags": ["save", "favorite", "tag"], "category": "actions", "styles": ["icons"]},
{"name": "box", "tags": ["package", "container", "storage"], "category": "objects", "styles": ["icons"]},
{"name": "briefcase", "tags": ["work", "job", "business"], "category": "objects", "styles": ["icons"]},
{"name": "calendar", "tags": ["date", "schedule", "event"], "category": "time", "styles": ["icons"]},
{"name": "camera", "tags": ["photo", "picture", "image"], "category": "devices", "styles": ["icons"]},
{"name": "camera-off", "tags": ["photo", "disabled", "off"], "category": "devices", "styles": ["icons"]},
{"name": "cast", "tags": ["stream", "broadcast", "chromecast"], "category": "devices", "styles": ["icons"]},
{"name": "check", "tags": ["done", "complete", "success"], "category": "actions", "styles": ["icons"]},
{"name": "check-circle", "tags": ["done", "complete", "success"], "category": "actions", "styles": ["icons"]},
{"name": "check-square", "tags": ["done", "complete", "checkbox"], "category": "actions", "styles": ["icons"]},
{"name": "chevron-down", "tags": ["expand", "dropdown", "arrow"], "category": "arrows", "styles": ["icons"]},
{"name": "chevron-left", "tags": ["back", "previous", "arrow"], "category": "arrows", "styles": ["icons"]},
{"name": "chevron-right", "tags": ["forward", "next", "arrow"], "category": "arrows", "styles": ["icons"]},
{"name": "chevron-up", "tags": ["collapse", "up", "arrow"], "category": "arrows", "styles": ["icons"]},
{"name": "chevrons-down", "tags": ["expand", "more", "double"], "category": "arrows", "styles": ["icons"]},
{"name": "chevrons-left", "tags": ["back", "previous", "double"], "category": "arrows", "styles": ["icons"]},
{"name": "chevrons-right", "tags": ["forward", "next", "double"], "category": "arrows", "styles": ["icons"]},
{"name": "chevrons-up", "tags": ["collapse", "less", "double"], "category": "arrows", "styles": ["icons"]},
{"name": "chrome", "tags": ["browser", "google", "web"], "category": "brands", "styles": ["icons"]},
{"name": "circle", "tags": ["shape", "dot", "record"], "category": "shapes", "styles": ["icons"]},
{"name": "clipboard", "tags": ["copy", "paste", "board"], "category": "actions", "styles": ["icons"]},
{"name": "clock", "tags": ["time", "watch", "schedule"], "category": "time", "styles": ["icons"]},
{"name": "cloud", "tags": ["weather", "storage", "sky"], "category": "weather", "styles": ["icons"]},
{"name": "cloud-drizzle", "tags": ["weather", "rain", "drizzle"], "category": "weather", "styles": ["icons"]},
{"name": "cloud-lightning", "tags": ["weather", "storm", "thunder"], "category": "weather", "styles": ["icons"]},
{"name": "cloud-off", "tags": ["weather", "offline", "disconnect"], "category": "weather", "styles": ["icons"]},
{"name": "cloud-rain", "tags": ["weather", "rain", "precipitation"], "category": "weather", "styles": ["icons"]},
{"name": "cloud-snow", "tags": ["weather", "snow", "winter"], "category": "weather", "styles": ["icons"]},
{"name": "code", "tags": ["programming", "development", "html"], "category": "development", "styles": ["icons"]},
{"name": "codepen", "tags": ["brand", "code", "development"], "category": "brands", "styles": ["icons"]},
{"name": "codesandbox", "tags": ["brand", "code", "development"], "category": "brands", "styles": ["icons"]},
{"name": "coffee", "tags": ["drink", "cup", "cafe"], "category": "objects", "styles": ["icons"]},
{"name": "columns", "tags": ["layout", "grid", "table"], "category": "layout", "styles": ["icons"]},
{"name": "command", "tags": ["keyboard", "mac", "key"], "category": "devices", "styles": ["icons"]},
{"name": "compass", "tags": ["navigation", "direction", "explore"], "category": "navigation", "styles": ["icons"]},
{"name": "copy", "tags": ["duplicate", "clone", "clipboard"], "category": "actions", "styles": ["icons"]},
{"name": "corner-down-left", "tags": ["arrow", "return", "enter"], "category": "arrows", "styles": ["icons"]},
{"name": "corner-down-right", "tags": ["arrow", "direction"], "category": "arrows", "styles": ["icons"]},
{"name": "corner-left-down", "tags": ["arrow", "direction"], "category": "arrows", "styles": ["icons"]},
{"name": "corner-left-up", "tags": ["arrow", "direction"], "category": "arrows", "styles": ["icons"]},
{"name": "corner-right-down", "tags": ["arrow", "direction"], "category": "arrows", "styles": ["icons"]},
{"name": "corner-right-up", "tags": ["arrow", "direction"], "category": "arrows", "styles": ["icons"]},
{"name": "corner-up-left", "tags": ["arrow", "direction"], "category": "arrows", "styles": ["icons"]},
{"name": "corner-up-right", "tags": ["arrow", "direction"], "category": "arrows", "styles": ["icons"]},
{"name": "cpu", "tags": ["processor", "chip", "computer"], "category": "devices", "styles": ["icons"]},
{"name": "credit-card", "tags": ["payment", "card", "money"], "category": "commerce", "styles": ["icons"]},
{"name": "crop", "tags": ["image", "edit", "resize"], "category": "editing", "styles": ["icons"]},
{"name": "crosshair", "tags": ["target", "focus", "aim"], "category": "ui", "styles": ["icons"]},
{"name": "database", "tags": ["storage", "data", "server"], "category": "development", "styles": ["icons"]},
{"name": "delete", "tags": ["remove", "backspace", "erase"], "category": "actions", "styles": ["icons"]},
{"name": "disc", "tags": ["cd", "music", "record"], "category": "media", "styles": ["icons"]},
{"name": "divide", "tags": ["math", "division", "split"], "category": "math", "styles": ["icons"]},
{"name": "divide-circle", "tags": ["math", "division", "split"], "category": "math", "styles": ["icons"]},
{"name": "divide-square", "tags": ["math", "division", "split"], "category": "math", "styles": ["icons"]},
{"name": "dollar-sign", "tags": ["money", "currency", "payment"], "category": "commerce", "styles": ["icons"]},
{"name": "download", "tags": ["save", "export", "download"], "category": "actions", "styles": ["icons"]},
{"name": "download-cloud", "tags": ["save", "cloud", "download"], "category": "actions", "styles": ["icons"]},
{"name": "dribbble", "tags": ["brand", "design", "social"], "category": "brands", "styles": ["icons"]},
{"name": "droplet", "tags": ["water", "liquid", "drop"], "category": "weather", "styles": ["icons"]},
{"name": "edit", "tags": ["pencil", "write", "modify"], "category": "actions", "styles": ["icons"]},
{"name": "edit-2", "tags": ["pencil", "write", "modify"], "category": "actions", "styles": ["icons"]},
{"name": "edit-3", "tags": ["pencil", "write", "modify"], "category": "actions", "styles": ["icons"]},
{"name": "external-link", "tags": ["link", "open", "new window"], "category": "actions", "styles": ["icons"]},
{"name": "eye", "tags": ["view", "visible", "show"], "category": "actions", "styles": ["icons"]},
{"name": "eye-off", "tags": ["hide", "invisible", "hidden"], "category": "actions", "styles": ["icons"]},
{"name": "facebook", "tags": ["brand", "social", "network"], "category": "brands", "styles": ["icons"]},
{"name": "fast-forward", "tags": ["media", "skip", "forward"], "category": "media", "styles": ["icons"]},
{"name": "feather", "tags": ["brand", "logo", "icon"], "category": "brands", "styles": ["icons"]},
{"name": "figma", "tags": ["brand", "design", "tool"], "category": "brands", "styles": ["icons"]},
{"name": "file", "tags": ["document", "page", "paper"], "category": "files", "styles": ["icons"]},
{"name": "file-minus", "tags": ["document", "remove", "delete"], "category": "files", "styles": ["icons"]},
{"name": "file-plus", "tags": ["document", "add", "new"], "category": "files", "styles": ["icons"]},
{"name": "file-text", "tags": ["document", "text", "content"], "category": "files", "styles": ["icons"]},
{"name": "film", "tags": ["video", "movie", "cinema"], "category": "media", "styles": ["icons"]},
{"name": "filter", "tags": ["funnel", "sort", "filter"], "category": "actions", "styles": ["icons"]},
{"name": "flag", "tags": ["report", "mark", "country"], "category": "objects", "styles": ["icons"]},
{"name": "folder", "tags": ["directory", "files", "organize"], "category": "files", "styles": ["icons"]},
{"name": "folder-minus", "tags": ["directory", "remove", "delete"], "category": "files", "styles": ["icons"]},
{"name": "folder-plus", "tags": ["directory", "add", "new"], "category": "files", "styles": ["icons"]},
{"name": "framer", "tags": ["brand", "design", "tool"], "category": "brands", "styles": ["icons"]},
{"name": "frown", "tags": ["sad", "unhappy", "emoji"], "category": "emoji", "styles": ["icons"]},
{"name": "gift", "tags": ["present", "reward", "surprise"], "category": "objects", "styles": ["icons"]},
{"name": "git-branch", "tags": ["version", "control", "code"], "category": "development", "styles": ["icons"]},
{"name": "git-commit", "tags": ["version", "control", "code"], "category": "development", "styles": ["icons"]},
{"name": "git-merge", "tags": ["version", "control", "code"], "category": "development", "styles": ["icons"]},
{"name": "git-pull-request", "tags": ["version", "control", "code"], "category": "development", "styles": ["icons"]},
{"name": "github", "tags": ["brand", "code", "repository"], "category": "brands", "styles": ["icons"]},
{"name": "gitlab", "tags": ["brand", "code", "repository"], "category": "brands", "styles": ["icons"]},
{"name": "globe", "tags": ["world", "earth", "web"], "category": "objects", "styles": ["icons"]},
{"name": "grid", "tags": ["layout", "squares", "dashboard"], "category": "layout", "styles": ["icons"]},
{"name": "hard-drive", "tags": ["storage", "disk", "data"], "category": "devices", "styles": ["icons"]},
{"name": "hash", "tags": ["tag", "hashtag", "number"], "category": "communication", "styles": ["icons"]},
{"name": "headphones", "tags": ["audio", "music", "listen"], "category": "devices", "styles": ["icons"]},
{"name": "heart", "tags": ["love", "favorite", "like"], "category": "objects", "styles": ["icons"]},
{"name": "help-circle", "tags": ["question", "help", "support"], "category": "actions", "styles": ["icons"]},
{"name": "hexagon", "tags": ["shape", "polygon", "6"], "category": "shapes", "styles": ["icons"]},
{"name": "home", "tags": ["house", "main", "dashboard"], "category": "navigation", "styles": ["icons"]},
{"name": "image", "tags": ["picture", "photo", "gallery"], "category": "media", "styles": ["icons"]},
{"name": "inbox", "tags": ["email", "messages", "mail"], "category": "communication", "styles": ["icons"]},
{"name": "info", "tags": ["information", "help", "about"], "category": "actions", "styles": ["icons"]},
{"name": "instagram", "tags": ["brand", "social", "photo"], "category": "brands", "styles": ["icons"]},
{"name": "italic", "tags": ["text", "format", "style"], "category": "text", "styles": ["icons"]},
{"name": "key", "tags": ["password", "security", "lock"], "category": "security", "styles": ["icons"]},
{"name": "layers", "tags": ["stack", "levels", "depth"], "category": "design", "styles": ["icons"]},
{"name": "layout", "tags": ["grid", "template", "design"], "category": "layout", "styles": ["icons"]},
{"name": "life-buoy", "tags": ["help", "support", "rescue"], "category": "objects", "styles": ["icons"]},
{"name": "link", "tags": ["url", "chain", "connect"], "category": "actions", "styles": ["icons"]},
{"name": "link-2", "tags": ["url", "chain", "connect"], "category": "actions", "styles": ["icons"]},
{"name": "linkedin", "tags": ["brand", "social", "professional"], "category": "brands", "styles": ["icons"]},
{"name": "list", "tags": ["menu", "items", "bullet"], "category": "text", "styles": ["icons"]},
{"name": "loader", "tags": ["loading", "spinner", "wait"], "category": "ui", "styles": ["icons"]},
{"name": "lock", "tags": ["security", "private", "password"], "category": "security", "styles": ["icons"]},
{"name": "log-in", "tags": ["login", "signin", "enter"], "category": "actions", "styles": ["icons"]},
{"name": "log-out", "tags": ["logout", "signout", "exit"], "category": "actions", "styles": ["icons"]},
{"name": "mail", "tags": ["email", "message", "envelope"], "category": "communication", "styles": ["icons"]},
{"name": "map", "tags": ["location", "navigation", "directions"], "category": "maps", "styles": ["icons"]},
{"name": "map-pin", "tags": ["location", "marker", "place"], "category": "maps", "styles": ["icons"]},
{"name": "maximize", "tags": ["fullscreen", "expand", "resize"], "category": "actions", "styles": ["icons"]},
{"name": "maximize-2", "tags": ["fullscreen", "expand", "resize"], "category": "actions", "styles": ["icons"]},
{"name": "meh", "tags": ["neutral", "emoji", "face"], "category": "emoji", "styles": ["icons"]},
{"name": "menu", "tags": ["hamburger", "navigation", "bars"], "category": "navigation", "styles": ["icons"]},
{"name": "message-circle", "tags": ["chat", "comment", "conversation"], "category": "communication", "styles": ["icons"]},
{"name": "message-square", "tags": ["chat", "comment", "conversation"], "category": "communication", "styles": ["icons"]},
{"name": "mic", "tags": ["microphone", "audio", "record"], "category": "media", "styles": ["icons"]},
{"name": "mic-off", "tags": ["microphone", "mute", "silent"], "category": "media", "styles": ["icons"]},
{"name": "minimize", "tags": ["collapse", "shrink", "resize"], "category": "actions", "styles": ["icons"]},
{"name": "minimize-2", "tags": ["collapse", "shrink", "resize"], "category": "actions", "styles": ["icons"]},
{"name": "minus", "tags": ["subtract", "remove", "delete"], "category": "math", "styles": ["icons"]},
{"name": "minus-circle", "tags": ["subtract", "remove", "delete"], "category": "math", "styles": ["icons"]},
{"name": "minus-square", "tags": ["subtract", "remove", "delete"], "category": "math", "styles": ["icons"]},
{"name": "monitor", "tags": ["screen", "display", "desktop"], "category": "devices", "styles": ["icons"]},
{"name": "moon", "tags": ["dark", "night", "theme"], "category": "weather", "styles": ["icons"]},
{"name": "more-horizontal", "tags": ["menu", "options", "dots"], "category": "ui", "styles": ["icons"]},
{"name": "more-vertical", "tags": ["menu", "options", "dots"], "category": "ui", "styles": ["icons"]},
{"name": "mouse-pointer", "tags": ["cursor", "click", "select"], "category": "ui", "styles": ["icons"]},
{"name": "move", "tags": ["drag", "reorder", "arrows"], "category": "actions", "styles": ["icons"]},
{"name": "music", "tags": ["audio", "sound", "note"], "category": "media", "styles": ["icons"]},
{"name": "navigation", "tags": ["direction", "arrow", "location"], "category": "navigation", "styles": ["icons"]},
{"name": "navigation-2", "tags": ["direction", "arrow", "location"], "category": "navigation", "styles": ["icons"]},
{"name": "octagon", "tags": ["shape", "stop", "polygon"], "category": "shapes", "styles": ["icons"]},
{"name": "package", "tags": ["box", "delivery", "shipping"], "category": "objects", "styles": ["icons"]},
{"name": "paperclip", "tags": ["attachment", "file", "clip"], "category": "actions", "styles": ["icons"]},
{"name": "pause", "tags": ["media", "stop", "wait"], "category": "media", "styles": ["icons"]},
{"name": "pause-circle", "tags": ["media", "stop", "wait"], "category": "media", "styles": ["icons"]},
{"name": "pen-tool", "tags": ["design", "draw", "vector"], "category": "design", "styles": ["icons"]},
{"name": "percent", "tags": ["discount", "math", "percentage"], "category": "math", "styles": ["icons"]},
{"name": "phone", "tags": ["call", "contact", "mobile"], "category": "communication", "styles": ["icons"]},
{"name": "phone-call", "tags": ["call", "ringing", "incoming"], "category": "communication", "styles": ["icons"]},
{"name": "phone-forwarded", "tags": ["call", "forward", "redirect"], "category": "communication", "styles": ["icons"]},
{"name": "phone-incoming", "tags": ["call", "receive", "answer"], "category": "communication", "styles": ["icons"]},
{"name": "phone-missed", "tags": ["call", "missed", "unanswered"], "category": "communication", "styles": ["icons"]},
{"name": "phone-off", "tags": ["call", "hang up", "end"], "category": "communication", "styles": ["icons"]},
{"name": "phone-outgoing", "tags": ["call", "dial", "outbound"], "category": "communication", "styles": ["icons"]},
{"name": "pie-chart", "tags": ["analytics", "statistics", "data"], "category": "charts", "styles": ["icons"]},
{"name": "play", "tags": ["media", "start", "video"], "category": "media", "styles": ["icons"]},
{"name": "play-circle", "tags": ["media", "start", "video"], "category": "media", "styles": ["icons"]},
{"name": "plus", "tags": ["add", "create", "new"], "category": "math", "styles": ["icons"]},
{"name": "plus-circle", "tags": ["add", "create", "new"], "category": "math", "styles": ["icons"]},
{"name": "plus-square", "tags": ["add", "create", "new"], "category": "math", "styles": ["icons"]},
{"name": "pocket", "tags": ["save", "bookmark", "read later"], "category": "brands", "styles": ["icons"]},
{"name": "power", "tags": ["on", "off", "shutdown"], "category": "devices", "styles": ["icons"]},
{"name": "printer", "tags": ["print", "document", "paper"], "category": "devices", "styles": ["icons"]},
{"name": "radio", "tags": ["audio", "broadcast", "music"], "category": "media", "styles": ["icons"]},
{"name": "refresh-ccw", "tags": ["reload", "sync", "update"], "category": "actions", "styles": ["icons"]},
{"name": "refresh-cw", "tags": ["reload", "sync", "update"], "category": "actions", "styles": ["icons"]},
{"name": "repeat", "tags": ["loop", "replay", "refresh"], "category": "media", "styles": ["icons"]},
{"name": "rewind", "tags": ["media", "back", "previous"], "category": "media", "styles": ["icons"]},
{"name": "rotate-ccw", "tags": ["undo", "rotate", "turn"], "category": "actions", "styles": ["icons"]},
{"name": "rotate-cw", "tags": ["redo", "rotate", "turn"], "category": "actions", "styles": ["icons"]},
{"name": "rss", "tags": ["feed", "subscribe", "blog"], "category": "communication", "styles": ["icons"]},
{"name": "save", "tags": ["disk", "floppy", "store"], "category": "actions", "styles": ["icons"]},
{"name": "scissors", "tags": ["cut", "trim", "edit"], "category": "actions", "styles": ["icons"]},
{"name": "search", "tags": ["find", "magnify", "look"], "category": "actions", "styles": ["icons"]},
{"name": "send", "tags": ["message", "email", "submit"], "category": "communication", "styles": ["icons"]},
{"name": "server", "tags": ["hosting", "database", "backend"], "category": "devices", "styles": ["icons"]},
{"name": "settings", "tags": ["gear", "cog", "preferences"], "category": "ui", "styles": ["icons"]},
{"name": "share", "tags": ["social", "send", "forward"], "category": "actions", "styles": ["icons"]},
{"name": "share-2", "tags": ["social", "send", "network"], "category": "actions", "styles": ["icons"]},
{"name": "shield", "tags": ["security", "protection", "safe"], "category": "security", "styles": ["icons"]},
{"name": "shield-off", "tags": ["security", "unprotected", "unsafe"], "category": "security", "styles": ["icons"]},
{"name": "shopping-bag", "tags": ["shop", "purchase", "buy"], "category": "commerce", "styles": ["icons"]},
{"name": "shopping-cart", "tags": ["shop", "cart", "ecommerce"], "category": "commerce", "styles": ["icons"]},
{"name": "shuffle", "tags": ["random", "mix", "music"], "category": "media", "styles": ["icons"]},
{"name": "sidebar", "tags": ["layout", "panel", "navigation"], "category": "layout", "styles": ["icons"]},
{"name": "skip-back", "tags": ["media", "previous", "rewind"], "category": "media", "styles": ["icons"]},
{"name": "skip-forward", "tags": ["media", "next", "forward"], "category": "media", "styles": ["icons"]},
{"name": "slack", "tags": ["brand", "chat", "communication"], "category": "brands", "styles": ["icons"]},
{"name": "slash", "tags": ["ban", "cancel", "disabled"], "category": "ui", "styles": ["icons"]},
{"name": "sliders", "tags": ["settings", "controls", "adjust"], "category": "ui", "styles": ["icons"]},
{"name": "smartphone", "tags": ["phone", "mobile", "device"], "category": "devices", "styles": ["icons"]},
{"name": "smile", "tags": ["happy", "emoji", "face"], "category": "emoji", "styles": ["icons"]},
{"name": "speaker", "tags": ["audio", "sound", "volume"], "category": "media", "styles": ["icons"]},
{"name": "square", "tags": ["shape", "box", "rectangle"], "category": "shapes", "styles": ["icons"]},
{"name": "star", "tags": ["favorite", "rating", "bookmark"], "category": "objects", "styles": ["icons"]},
{"name": "stop-circle", "tags": ["media", "stop", "end"], "category": "media", "styles": ["icons"]},
{"name": "sun", "tags": ["light", "day", "brightness"], "category": "weather", "styles": ["icons"]},
{"name": "sunrise", "tags": ["morning", "dawn", "sun"], "category": "weather", "styles": ["icons"]},
{"name": "sunset", "tags": ["evening", "dusk", "sun"], "category": "weather", "styles": ["icons"]},
{"name": "tablet", "tags": ["device", "ipad", "screen"], "category": "devices", "styles": ["icons"]},
{"name": "tag", "tags": ["label", "category", "price"], "category": "commerce", "styles": ["icons"]},
{"name": "target", "tags": ["goal", "aim", "focus"], "category": "ui", "styles": ["icons"]},
{"name": "terminal", "tags": ["console", "command", "code"], "category": "development", "styles": ["icons"]},
{"name": "thermometer", "tags": ["temperature", "weather", "health"], "category": "weather", "styles": ["icons"]},
{"name": "thumbs-down", "tags": ["dislike", "bad", "negative"], "category": "actions", "styles": ["icons"]},
{"name": "thumbs-up", "tags": ["like", "good", "positive"], "category": "actions", "styles": ["icons"]},
{"name": "toggle-left", "tags": ["switch", "off", "disable"], "category": "ui", "styles": ["icons"]},
{"name": "toggle-right", "tags": ["switch", "on", "enable"], "category": "ui", "styles": ["icons"]},
{"name": "tool", "tags": ["wrench", "settings", "repair"], "category": "objects", "styles": ["icons"]},
{"name": "trash", "tags": ["delete", "remove", "bin"], "category": "actions", "styles": ["icons"]},
{"name": "trash-2", "tags": ["delete", "remove", "bin"], "category": "actions", "styles": ["icons"]},
{"name": "trello", "tags": ["brand", "project", "kanban"], "category": "brands", "styles": ["icons"]},
{"name": "trending-down", "tags": ["chart", "decrease", "analytics"], "category": "charts", "styles": ["icons"]},
{"name": "trending-up", "tags": ["chart", "increase", "analytics"], "category": "charts", "styles": ["icons"]},
{"name": "triangle", "tags": ["shape", "polygon", "warning"], "category": "shapes", "styles": ["icons"]},
{"name": "truck", "tags": ["delivery", "shipping", "transport"], "category": "objects", "styles": ["icons"]},
{"name": "tv", "tags": ["television", "screen", "display"], "category": "devices", "styles": ["icons"]},
{"name": "twitch", "tags": ["brand", "streaming", "gaming"], "category": "brands", "styles": ["icons"]},
{"name": "twitter", "tags": ["brand", "social", "network"], "category": "brands", "styles": ["icons"]},
{"name": "type", "tags": ["text", "font", "typography"], "category": "text", "styles": ["icons"]},
{"name": "umbrella", "tags": ["weather", "rain", "protection"], "category": "weather", "styles": ["icons"]},
{"name": "underline", "tags": ["text", "format", "style"], "category": "text", "styles": ["icons"]},
{"name": "unlock", "tags": ["security", "open", "access"], "category": "security", "styles": ["icons"]},
{"name": "upload", "tags": ["export", "send", "share"], "category": "actions", "styles": ["icons"]},
{"name": "upload-cloud", "tags": ["export", "cloud", "share"], "category": "actions", "styles": ["icons"]},
{"name": "user", "tags": ["person", "account", "profile"], "category": "users", "styles": ["icons"]},
{"name": "user-check", "tags": ["person", "verified", "approved"], "category": "users", "styles": ["icons"]},
{"name": "user-minus", "tags": ["person", "remove", "unfriend"], "category": "users", "styles": ["icons"]},
{"name": "user-plus", "tags": ["person", "add", "invite"], "category": "users", "styles": ["icons"]},
{"name": "user-x", "tags": ["person", "delete", "remove"], "category": "users", "styles": ["icons"]},
{"name": "users", "tags": ["people", "team", "group"], "category": "users", "styles": ["icons"]},
{"name": "video", "tags": ["camera", "film", "record"], "category": "media", "styles": ["icons"]},
{"name": "video-off", "tags": ["camera", "disabled", "mute"], "category": "media", "styles": ["icons"]},
{"name": "voicemail", "tags": ["message", "audio", "phone"], "category": "communication", "styles": ["icons"]},
{"name": "volume", "tags": ["sound", "audio", "speaker"], "category": "media", "styles": ["icons"]},
{"name": "volume-1", "tags": ["sound", "audio", "low"], "category": "media", "styles": ["icons"]},
{"name": "volume-2", "tags": ["sound", "audio", "high"], "category": "media", "styles": ["icons"]},
{"name": "volume-x", "tags": ["mute", "silent", "no sound"], "category": "media", "styles": ["icons"]},
{"name": "watch", "tags": ["time", "wearable", "clock"], "category": "devices", "styles": ["icons"]},
{"name": "wifi", "tags": ["wireless", "internet", "connection"], "category": "connectivity", "styles": ["icons"]},
{"name": "wifi-off", "tags": ["wireless", "offline", "disconnect"], "category": "connectivity", "styles": ["icons"]},
{"name": "wind", "tags": ["weather", "air", "breeze"], "category": "weather", "styles": ["icons"]},
{"name": "x", "tags": ["close", "cancel", "remove"], "category": "actions", "styles": ["icons"]},
{"name": "x-circle", "tags": ["close", "cancel", "error"], "category": "actions", "styles": ["icons"]},
{"name": "x-octagon", "tags": ["close", "stop", "error"], "category": "actions", "styles": ["icons"]},
{"name": "x-square", "tags": ["close", "cancel", "remove"], "category": "actions", "styles": ["icons"]},
{"name": "youtube", "tags": ["brand", "video", "streaming"], "category": "brands", "styles": ["icons"]},
{"name": "zap", "tags": ["lightning", "power", "energy"], "category": "objects", "styles": ["icons"]},
{"name": "zap-off", "tags": ["lightning", "disabled", "off"], "category": "objects", "styles": ["icons"]},
{"name": "zoom-in", "tags": ["magnify", "enlarge", "plus"], "category": "actions", "styles": ["icons"]},
{"name": "zoom-out", "tags": ["magnify", "shrink", "minus"], "category": "actions", "styles": ["icons"]}
]
}

View file

@ -0,0 +1,295 @@
{
"slug": "heroicons",
"name": "Heroicons",
"version": "2.1.1",
"icons": [
{"name": "academic-cap", "tags": ["education", "graduation", "school", "hat", "learning"], "category": "objects", "styles": ["outline", "solid", "mini"]},
{"name": "adjustments-horizontal", "tags": ["settings", "controls", "sliders", "options", "configuration"], "category": "ui", "styles": ["outline", "solid", "mini"]},
{"name": "adjustments-vertical", "tags": ["settings", "controls", "sliders", "options", "configuration"], "category": "ui", "styles": ["outline", "solid", "mini"]},
{"name": "archive-box", "tags": ["storage", "box", "container", "archive"], "category": "objects", "styles": ["outline", "solid", "mini"]},
{"name": "archive-box-arrow-down", "tags": ["download", "storage", "archive", "save"], "category": "actions", "styles": ["outline", "solid", "mini"]},
{"name": "archive-box-x-mark", "tags": ["delete", "remove", "archive", "cancel"], "category": "actions", "styles": ["outline", "solid", "mini"]},
{"name": "arrow-down", "tags": ["direction", "navigation", "down", "move"], "category": "arrows", "styles": ["outline", "solid", "mini"]},
{"name": "arrow-down-circle", "tags": ["direction", "navigation", "down", "circle"], "category": "arrows", "styles": ["outline", "solid", "mini"]},
{"name": "arrow-down-left", "tags": ["direction", "navigation", "diagonal"], "category": "arrows", "styles": ["outline", "solid", "mini"]},
{"name": "arrow-down-on-square", "tags": ["download", "save", "import"], "category": "actions", "styles": ["outline", "solid", "mini"]},
{"name": "arrow-down-on-square-stack", "tags": ["download", "save", "multiple"], "category": "actions", "styles": ["outline", "solid", "mini"]},
{"name": "arrow-down-right", "tags": ["direction", "navigation", "diagonal"], "category": "arrows", "styles": ["outline", "solid", "mini"]},
{"name": "arrow-down-tray", "tags": ["download", "save", "import"], "category": "actions", "styles": ["outline", "solid", "mini"]},
{"name": "arrow-left", "tags": ["direction", "navigation", "back", "previous"], "category": "arrows", "styles": ["outline", "solid", "mini"]},
{"name": "arrow-left-circle", "tags": ["direction", "navigation", "back", "circle"], "category": "arrows", "styles": ["outline", "solid", "mini"]},
{"name": "arrow-left-end-on-rectangle", "tags": ["logout", "exit", "leave"], "category": "actions", "styles": ["outline", "solid", "mini"]},
{"name": "arrow-left-start-on-rectangle", "tags": ["login", "enter", "signin"], "category": "actions", "styles": ["outline", "solid", "mini"]},
{"name": "arrow-long-down", "tags": ["direction", "navigation", "long"], "category": "arrows", "styles": ["outline", "solid", "mini"]},
{"name": "arrow-long-left", "tags": ["direction", "navigation", "long", "back"], "category": "arrows", "styles": ["outline", "solid", "mini"]},
{"name": "arrow-long-right", "tags": ["direction", "navigation", "long", "forward"], "category": "arrows", "styles": ["outline", "solid", "mini"]},
{"name": "arrow-long-up", "tags": ["direction", "navigation", "long"], "category": "arrows", "styles": ["outline", "solid", "mini"]},
{"name": "arrow-path", "tags": ["refresh", "reload", "sync", "repeat"], "category": "actions", "styles": ["outline", "solid", "mini"]},
{"name": "arrow-path-rounded-square", "tags": ["refresh", "reload", "sync"], "category": "actions", "styles": ["outline", "solid", "mini"]},
{"name": "arrow-right", "tags": ["direction", "navigation", "forward", "next"], "category": "arrows", "styles": ["outline", "solid", "mini"]},
{"name": "arrow-right-circle", "tags": ["direction", "navigation", "forward", "circle"], "category": "arrows", "styles": ["outline", "solid", "mini"]},
{"name": "arrow-right-end-on-rectangle", "tags": ["login", "enter", "signin"], "category": "actions", "styles": ["outline", "solid", "mini"]},
{"name": "arrow-right-start-on-rectangle", "tags": ["logout", "exit", "leave"], "category": "actions", "styles": ["outline", "solid", "mini"]},
{"name": "arrow-top-right-on-square", "tags": ["external", "link", "open", "new window"], "category": "actions", "styles": ["outline", "solid", "mini"]},
{"name": "arrow-trending-down", "tags": ["chart", "decrease", "analytics", "down"], "category": "charts", "styles": ["outline", "solid", "mini"]},
{"name": "arrow-trending-up", "tags": ["chart", "increase", "analytics", "up"], "category": "charts", "styles": ["outline", "solid", "mini"]},
{"name": "arrow-up", "tags": ["direction", "navigation", "up", "move"], "category": "arrows", "styles": ["outline", "solid", "mini"]},
{"name": "arrow-up-circle", "tags": ["direction", "navigation", "up", "circle"], "category": "arrows", "styles": ["outline", "solid", "mini"]},
{"name": "arrow-up-left", "tags": ["direction", "navigation", "diagonal"], "category": "arrows", "styles": ["outline", "solid", "mini"]},
{"name": "arrow-up-on-square", "tags": ["upload", "share", "export"], "category": "actions", "styles": ["outline", "solid", "mini"]},
{"name": "arrow-up-on-square-stack", "tags": ["upload", "share", "multiple"], "category": "actions", "styles": ["outline", "solid", "mini"]},
{"name": "arrow-up-right", "tags": ["direction", "navigation", "diagonal"], "category": "arrows", "styles": ["outline", "solid", "mini"]},
{"name": "arrow-up-tray", "tags": ["upload", "export", "share"], "category": "actions", "styles": ["outline", "solid", "mini"]},
{"name": "arrow-uturn-down", "tags": ["undo", "return", "back"], "category": "arrows", "styles": ["outline", "solid", "mini"]},
{"name": "arrow-uturn-left", "tags": ["undo", "return", "back"], "category": "arrows", "styles": ["outline", "solid", "mini"]},
{"name": "arrow-uturn-right", "tags": ["redo", "forward"], "category": "arrows", "styles": ["outline", "solid", "mini"]},
{"name": "arrow-uturn-up", "tags": ["return", "back"], "category": "arrows", "styles": ["outline", "solid", "mini"]},
{"name": "arrows-pointing-in", "tags": ["minimize", "collapse", "shrink"], "category": "actions", "styles": ["outline", "solid", "mini"]},
{"name": "arrows-pointing-out", "tags": ["maximize", "expand", "fullscreen"], "category": "actions", "styles": ["outline", "solid", "mini"]},
{"name": "arrows-right-left", "tags": ["swap", "exchange", "transfer"], "category": "arrows", "styles": ["outline", "solid", "mini"]},
{"name": "arrows-up-down", "tags": ["sort", "reorder", "move"], "category": "arrows", "styles": ["outline", "solid", "mini"]},
{"name": "at-symbol", "tags": ["email", "at", "mention", "contact"], "category": "communication", "styles": ["outline", "solid", "mini"]},
{"name": "backspace", "tags": ["delete", "remove", "erase", "keyboard"], "category": "actions", "styles": ["outline", "solid", "mini"]},
{"name": "backward", "tags": ["media", "rewind", "previous"], "category": "media", "styles": ["outline", "solid", "mini"]},
{"name": "banknotes", "tags": ["money", "cash", "payment", "currency"], "category": "commerce", "styles": ["outline", "solid", "mini"]},
{"name": "bars-2", "tags": ["menu", "hamburger", "navigation"], "category": "ui", "styles": ["outline", "solid", "mini"]},
{"name": "bars-3", "tags": ["menu", "hamburger", "navigation"], "category": "ui", "styles": ["outline", "solid", "mini"]},
{"name": "bars-3-bottom-left", "tags": ["menu", "text", "align left"], "category": "ui", "styles": ["outline", "solid", "mini"]},
{"name": "bars-3-bottom-right", "tags": ["menu", "text", "align right"], "category": "ui", "styles": ["outline", "solid", "mini"]},
{"name": "bars-3-center-left", "tags": ["menu", "text", "align"], "category": "ui", "styles": ["outline", "solid", "mini"]},
{"name": "bars-4", "tags": ["menu", "list", "navigation"], "category": "ui", "styles": ["outline", "solid", "mini"]},
{"name": "bars-arrow-down", "tags": ["sort", "descending", "order"], "category": "actions", "styles": ["outline", "solid", "mini"]},
{"name": "bars-arrow-up", "tags": ["sort", "ascending", "order"], "category": "actions", "styles": ["outline", "solid", "mini"]},
{"name": "battery-0", "tags": ["power", "energy", "empty"], "category": "devices", "styles": ["outline", "solid", "mini"]},
{"name": "battery-50", "tags": ["power", "energy", "half"], "category": "devices", "styles": ["outline", "solid", "mini"]},
{"name": "battery-100", "tags": ["power", "energy", "full"], "category": "devices", "styles": ["outline", "solid", "mini"]},
{"name": "beaker", "tags": ["science", "lab", "chemistry", "experiment"], "category": "objects", "styles": ["outline", "solid", "mini"]},
{"name": "bell", "tags": ["notification", "alert", "alarm", "ring"], "category": "communication", "styles": ["outline", "solid", "mini"]},
{"name": "bell-alert", "tags": ["notification", "alert", "alarm", "warning"], "category": "communication", "styles": ["outline", "solid", "mini"]},
{"name": "bell-slash", "tags": ["notification", "mute", "silent", "off"], "category": "communication", "styles": ["outline", "solid", "mini"]},
{"name": "bell-snooze", "tags": ["notification", "snooze", "delay", "later"], "category": "communication", "styles": ["outline", "solid", "mini"]},
{"name": "bolt", "tags": ["lightning", "power", "energy", "electric"], "category": "objects", "styles": ["outline", "solid", "mini"]},
{"name": "bolt-slash", "tags": ["lightning", "power", "off", "disabled"], "category": "objects", "styles": ["outline", "solid", "mini"]},
{"name": "book-open", "tags": ["read", "education", "learning", "library"], "category": "objects", "styles": ["outline", "solid", "mini"]},
{"name": "bookmark", "tags": ["save", "favorite", "tag", "mark"], "category": "actions", "styles": ["outline", "solid", "mini"]},
{"name": "bookmark-slash", "tags": ["unsave", "remove", "unbookmark"], "category": "actions", "styles": ["outline", "solid", "mini"]},
{"name": "bookmark-square", "tags": ["save", "favorite", "square"], "category": "actions", "styles": ["outline", "solid", "mini"]},
{"name": "briefcase", "tags": ["work", "job", "business", "career"], "category": "objects", "styles": ["outline", "solid", "mini"]},
{"name": "bug-ant", "tags": ["bug", "debug", "error", "insect"], "category": "development", "styles": ["outline", "solid", "mini"]},
{"name": "building-library", "tags": ["library", "institution", "government"], "category": "buildings", "styles": ["outline", "solid", "mini"]},
{"name": "building-office", "tags": ["office", "work", "business", "company"], "category": "buildings", "styles": ["outline", "solid", "mini"]},
{"name": "building-office-2", "tags": ["office", "skyscraper", "business"], "category": "buildings", "styles": ["outline", "solid", "mini"]},
{"name": "building-storefront", "tags": ["shop", "store", "retail", "commerce"], "category": "buildings", "styles": ["outline", "solid", "mini"]},
{"name": "cake", "tags": ["birthday", "celebration", "party", "dessert"], "category": "objects", "styles": ["outline", "solid", "mini"]},
{"name": "calculator", "tags": ["math", "calculate", "numbers", "finance"], "category": "objects", "styles": ["outline", "solid", "mini"]},
{"name": "calendar", "tags": ["date", "schedule", "event", "time"], "category": "objects", "styles": ["outline", "solid", "mini"]},
{"name": "calendar-days", "tags": ["date", "schedule", "month", "planner"], "category": "objects", "styles": ["outline", "solid", "mini"]},
{"name": "camera", "tags": ["photo", "picture", "image", "photography"], "category": "devices", "styles": ["outline", "solid", "mini"]},
{"name": "chart-bar", "tags": ["analytics", "statistics", "graph", "data"], "category": "charts", "styles": ["outline", "solid", "mini"]},
{"name": "chart-bar-square", "tags": ["analytics", "statistics", "graph"], "category": "charts", "styles": ["outline", "solid", "mini"]},
{"name": "chart-pie", "tags": ["analytics", "statistics", "pie chart", "data"], "category": "charts", "styles": ["outline", "solid", "mini"]},
{"name": "chat-bubble-bottom-center", "tags": ["message", "chat", "comment", "conversation"], "category": "communication", "styles": ["outline", "solid", "mini"]},
{"name": "chat-bubble-bottom-center-text", "tags": ["message", "chat", "text", "comment"], "category": "communication", "styles": ["outline", "solid", "mini"]},
{"name": "chat-bubble-left", "tags": ["message", "chat", "comment"], "category": "communication", "styles": ["outline", "solid", "mini"]},
{"name": "chat-bubble-left-ellipsis", "tags": ["message", "typing", "chat"], "category": "communication", "styles": ["outline", "solid", "mini"]},
{"name": "chat-bubble-left-right", "tags": ["conversation", "chat", "discuss"], "category": "communication", "styles": ["outline", "solid", "mini"]},
{"name": "chat-bubble-oval-left", "tags": ["message", "chat", "bubble"], "category": "communication", "styles": ["outline", "solid", "mini"]},
{"name": "chat-bubble-oval-left-ellipsis", "tags": ["message", "typing", "chat"], "category": "communication", "styles": ["outline", "solid", "mini"]},
{"name": "check", "tags": ["done", "complete", "success", "tick"], "category": "ui", "styles": ["outline", "solid", "mini"]},
{"name": "check-badge", "tags": ["verified", "approved", "certified"], "category": "ui", "styles": ["outline", "solid", "mini"]},
{"name": "check-circle", "tags": ["done", "complete", "success", "approved"], "category": "ui", "styles": ["outline", "solid", "mini"]},
{"name": "chevron-double-down", "tags": ["expand", "more", "navigation"], "category": "arrows", "styles": ["outline", "solid", "mini"]},
{"name": "chevron-double-left", "tags": ["previous", "back", "navigation"], "category": "arrows", "styles": ["outline", "solid", "mini"]},
{"name": "chevron-double-right", "tags": ["next", "forward", "navigation"], "category": "arrows", "styles": ["outline", "solid", "mini"]},
{"name": "chevron-double-up", "tags": ["collapse", "less", "navigation"], "category": "arrows", "styles": ["outline", "solid", "mini"]},
{"name": "chevron-down", "tags": ["expand", "dropdown", "more"], "category": "arrows", "styles": ["outline", "solid", "mini"]},
{"name": "chevron-left", "tags": ["previous", "back", "navigation"], "category": "arrows", "styles": ["outline", "solid", "mini"]},
{"name": "chevron-right", "tags": ["next", "forward", "navigation"], "category": "arrows", "styles": ["outline", "solid", "mini"]},
{"name": "chevron-up", "tags": ["collapse", "less", "close"], "category": "arrows", "styles": ["outline", "solid", "mini"]},
{"name": "chevron-up-down", "tags": ["sort", "select", "dropdown"], "category": "arrows", "styles": ["outline", "solid", "mini"]},
{"name": "circle-stack", "tags": ["database", "storage", "data", "layers"], "category": "development", "styles": ["outline", "solid", "mini"]},
{"name": "clipboard", "tags": ["copy", "paste", "clipboard"], "category": "actions", "styles": ["outline", "solid", "mini"]},
{"name": "clipboard-document", "tags": ["copy", "document", "paste"], "category": "actions", "styles": ["outline", "solid", "mini"]},
{"name": "clipboard-document-check", "tags": ["copy", "done", "verified"], "category": "actions", "styles": ["outline", "solid", "mini"]},
{"name": "clipboard-document-list", "tags": ["list", "tasks", "checklist"], "category": "actions", "styles": ["outline", "solid", "mini"]},
{"name": "clock", "tags": ["time", "schedule", "watch", "hour"], "category": "objects", "styles": ["outline", "solid", "mini"]},
{"name": "cloud", "tags": ["weather", "storage", "sky", "upload"], "category": "objects", "styles": ["outline", "solid", "mini"]},
{"name": "cloud-arrow-down", "tags": ["download", "cloud", "sync"], "category": "actions", "styles": ["outline", "solid", "mini"]},
{"name": "cloud-arrow-up", "tags": ["upload", "cloud", "sync"], "category": "actions", "styles": ["outline", "solid", "mini"]},
{"name": "code-bracket", "tags": ["code", "development", "programming"], "category": "development", "styles": ["outline", "solid", "mini"]},
{"name": "code-bracket-square", "tags": ["code", "development", "programming"], "category": "development", "styles": ["outline", "solid", "mini"]},
{"name": "cog", "tags": ["settings", "gear", "configuration", "options"], "category": "ui", "styles": ["outline", "solid", "mini"]},
{"name": "cog-6-tooth", "tags": ["settings", "gear", "configuration"], "category": "ui", "styles": ["outline", "solid", "mini"]},
{"name": "cog-8-tooth", "tags": ["settings", "gear", "configuration"], "category": "ui", "styles": ["outline", "solid", "mini"]},
{"name": "command-line", "tags": ["terminal", "console", "cli", "code"], "category": "development", "styles": ["outline", "solid", "mini"]},
{"name": "computer-desktop", "tags": ["desktop", "monitor", "screen", "pc"], "category": "devices", "styles": ["outline", "solid", "mini"]},
{"name": "cpu-chip", "tags": ["processor", "chip", "hardware", "computer"], "category": "devices", "styles": ["outline", "solid", "mini"]},
{"name": "credit-card", "tags": ["payment", "card", "money", "finance"], "category": "commerce", "styles": ["outline", "solid", "mini"]},
{"name": "cube", "tags": ["3d", "box", "shape", "object"], "category": "objects", "styles": ["outline", "solid", "mini"]},
{"name": "cube-transparent", "tags": ["3d", "box", "transparent"], "category": "objects", "styles": ["outline", "solid", "mini"]},
{"name": "currency-bangladeshi", "tags": ["money", "currency", "taka"], "category": "commerce", "styles": ["outline", "solid", "mini"]},
{"name": "currency-dollar", "tags": ["money", "currency", "usd", "dollar"], "category": "commerce", "styles": ["outline", "solid", "mini"]},
{"name": "currency-euro", "tags": ["money", "currency", "eur", "euro"], "category": "commerce", "styles": ["outline", "solid", "mini"]},
{"name": "currency-pound", "tags": ["money", "currency", "gbp", "pound"], "category": "commerce", "styles": ["outline", "solid", "mini"]},
{"name": "currency-rupee", "tags": ["money", "currency", "inr", "rupee"], "category": "commerce", "styles": ["outline", "solid", "mini"]},
{"name": "currency-yen", "tags": ["money", "currency", "jpy", "yen"], "category": "commerce", "styles": ["outline", "solid", "mini"]},
{"name": "cursor-arrow-rays", "tags": ["cursor", "click", "pointer"], "category": "ui", "styles": ["outline", "solid", "mini"]},
{"name": "cursor-arrow-ripple", "tags": ["cursor", "click", "pointer"], "category": "ui", "styles": ["outline", "solid", "mini"]},
{"name": "device-phone-mobile", "tags": ["phone", "mobile", "smartphone"], "category": "devices", "styles": ["outline", "solid", "mini"]},
{"name": "device-tablet", "tags": ["tablet", "ipad", "device"], "category": "devices", "styles": ["outline", "solid", "mini"]},
{"name": "document", "tags": ["file", "document", "page", "paper"], "category": "files", "styles": ["outline", "solid", "mini"]},
{"name": "document-arrow-down", "tags": ["download", "file", "document"], "category": "files", "styles": ["outline", "solid", "mini"]},
{"name": "document-arrow-up", "tags": ["upload", "file", "document"], "category": "files", "styles": ["outline", "solid", "mini"]},
{"name": "document-chart-bar", "tags": ["report", "analytics", "document"], "category": "files", "styles": ["outline", "solid", "mini"]},
{"name": "document-check", "tags": ["verified", "approved", "document"], "category": "files", "styles": ["outline", "solid", "mini"]},
{"name": "document-duplicate", "tags": ["copy", "duplicate", "clone"], "category": "files", "styles": ["outline", "solid", "mini"]},
{"name": "document-magnifying-glass", "tags": ["search", "find", "document"], "category": "files", "styles": ["outline", "solid", "mini"]},
{"name": "document-minus", "tags": ["remove", "delete", "document"], "category": "files", "styles": ["outline", "solid", "mini"]},
{"name": "document-plus", "tags": ["add", "new", "create", "document"], "category": "files", "styles": ["outline", "solid", "mini"]},
{"name": "document-text", "tags": ["file", "text", "document", "content"], "category": "files", "styles": ["outline", "solid", "mini"]},
{"name": "ellipsis-horizontal", "tags": ["more", "menu", "options", "dots"], "category": "ui", "styles": ["outline", "solid", "mini"]},
{"name": "ellipsis-horizontal-circle", "tags": ["more", "menu", "options"], "category": "ui", "styles": ["outline", "solid", "mini"]},
{"name": "ellipsis-vertical", "tags": ["more", "menu", "options", "dots"], "category": "ui", "styles": ["outline", "solid", "mini"]},
{"name": "envelope", "tags": ["email", "mail", "message", "letter"], "category": "communication", "styles": ["outline", "solid", "mini"]},
{"name": "envelope-open", "tags": ["email", "mail", "read", "open"], "category": "communication", "styles": ["outline", "solid", "mini"]},
{"name": "exclamation-circle", "tags": ["warning", "alert", "error", "danger"], "category": "ui", "styles": ["outline", "solid", "mini"]},
{"name": "exclamation-triangle", "tags": ["warning", "alert", "caution", "danger"], "category": "ui", "styles": ["outline", "solid", "mini"]},
{"name": "eye", "tags": ["view", "visible", "show", "watch"], "category": "ui", "styles": ["outline", "solid", "mini"]},
{"name": "eye-dropper", "tags": ["color", "picker", "dropper", "design"], "category": "design", "styles": ["outline", "solid", "mini"]},
{"name": "eye-slash", "tags": ["hide", "invisible", "hidden", "privacy"], "category": "ui", "styles": ["outline", "solid", "mini"]},
{"name": "face-frown", "tags": ["sad", "unhappy", "emoji", "emotion"], "category": "emoji", "styles": ["outline", "solid", "mini"]},
{"name": "face-smile", "tags": ["happy", "smile", "emoji", "emotion"], "category": "emoji", "styles": ["outline", "solid", "mini"]},
{"name": "film", "tags": ["video", "movie", "media", "cinema"], "category": "media", "styles": ["outline", "solid", "mini"]},
{"name": "finger-print", "tags": ["security", "identity", "biometric", "auth"], "category": "security", "styles": ["outline", "solid", "mini"]},
{"name": "fire", "tags": ["flame", "hot", "trending", "popular"], "category": "objects", "styles": ["outline", "solid", "mini"]},
{"name": "flag", "tags": ["report", "mark", "flag", "bookmark"], "category": "objects", "styles": ["outline", "solid", "mini"]},
{"name": "folder", "tags": ["directory", "folder", "files", "organize"], "category": "files", "styles": ["outline", "solid", "mini"]},
{"name": "folder-arrow-down", "tags": ["download", "folder", "save"], "category": "files", "styles": ["outline", "solid", "mini"]},
{"name": "folder-minus", "tags": ["remove", "folder", "delete"], "category": "files", "styles": ["outline", "solid", "mini"]},
{"name": "folder-open", "tags": ["open", "folder", "browse"], "category": "files", "styles": ["outline", "solid", "mini"]},
{"name": "folder-plus", "tags": ["add", "folder", "new", "create"], "category": "files", "styles": ["outline", "solid", "mini"]},
{"name": "forward", "tags": ["media", "next", "skip"], "category": "media", "styles": ["outline", "solid", "mini"]},
{"name": "funnel", "tags": ["filter", "sort", "funnel"], "category": "ui", "styles": ["outline", "solid", "mini"]},
{"name": "gif", "tags": ["image", "animation", "gif", "media"], "category": "media", "styles": ["outline", "solid", "mini"]},
{"name": "gift", "tags": ["present", "gift", "reward", "surprise"], "category": "objects", "styles": ["outline", "solid", "mini"]},
{"name": "gift-top", "tags": ["present", "gift", "reward"], "category": "objects", "styles": ["outline", "solid", "mini"]},
{"name": "globe-alt", "tags": ["world", "earth", "internet", "web"], "category": "objects", "styles": ["outline", "solid", "mini"]},
{"name": "globe-americas", "tags": ["world", "earth", "americas"], "category": "objects", "styles": ["outline", "solid", "mini"]},
{"name": "globe-asia-australia", "tags": ["world", "earth", "asia"], "category": "objects", "styles": ["outline", "solid", "mini"]},
{"name": "globe-europe-africa", "tags": ["world", "earth", "europe"], "category": "objects", "styles": ["outline", "solid", "mini"]},
{"name": "hand-raised", "tags": ["stop", "hand", "halt", "wait"], "category": "gestures", "styles": ["outline", "solid", "mini"]},
{"name": "hand-thumb-down", "tags": ["dislike", "thumbs down", "bad"], "category": "gestures", "styles": ["outline", "solid", "mini"]},
{"name": "hand-thumb-up", "tags": ["like", "thumbs up", "good", "approve"], "category": "gestures", "styles": ["outline", "solid", "mini"]},
{"name": "hashtag", "tags": ["tag", "hashtag", "topic", "social"], "category": "communication", "styles": ["outline", "solid", "mini"]},
{"name": "heart", "tags": ["love", "favorite", "like", "heart"], "category": "objects", "styles": ["outline", "solid", "mini"]},
{"name": "home", "tags": ["house", "home", "main", "dashboard"], "category": "navigation", "styles": ["outline", "solid", "mini"]},
{"name": "home-modern", "tags": ["house", "home", "building"], "category": "buildings", "styles": ["outline", "solid", "mini"]},
{"name": "identification", "tags": ["id", "card", "identity", "badge"], "category": "objects", "styles": ["outline", "solid", "mini"]},
{"name": "inbox", "tags": ["mail", "inbox", "messages"], "category": "communication", "styles": ["outline", "solid", "mini"]},
{"name": "inbox-arrow-down", "tags": ["receive", "inbox", "download"], "category": "communication", "styles": ["outline", "solid", "mini"]},
{"name": "inbox-stack", "tags": ["inbox", "messages", "stack"], "category": "communication", "styles": ["outline", "solid", "mini"]},
{"name": "information-circle", "tags": ["info", "help", "about", "details"], "category": "ui", "styles": ["outline", "solid", "mini"]},
{"name": "key", "tags": ["password", "security", "access", "lock"], "category": "security", "styles": ["outline", "solid", "mini"]},
{"name": "language", "tags": ["translate", "language", "international"], "category": "communication", "styles": ["outline", "solid", "mini"]},
{"name": "lifebuoy", "tags": ["help", "support", "rescue", "assistance"], "category": "objects", "styles": ["outline", "solid", "mini"]},
{"name": "light-bulb", "tags": ["idea", "light", "bulb", "creative"], "category": "objects", "styles": ["outline", "solid", "mini"]},
{"name": "link", "tags": ["url", "link", "chain", "connect"], "category": "ui", "styles": ["outline", "solid", "mini"]},
{"name": "list-bullet", "tags": ["list", "bullet", "items", "menu"], "category": "ui", "styles": ["outline", "solid", "mini"]},
{"name": "lock-closed", "tags": ["security", "lock", "private", "protected"], "category": "security", "styles": ["outline", "solid", "mini"]},
{"name": "lock-open", "tags": ["unlock", "open", "access"], "category": "security", "styles": ["outline", "solid", "mini"]},
{"name": "magnifying-glass", "tags": ["search", "find", "zoom", "look"], "category": "ui", "styles": ["outline", "solid", "mini"]},
{"name": "magnifying-glass-circle", "tags": ["search", "find", "explore"], "category": "ui", "styles": ["outline", "solid", "mini"]},
{"name": "magnifying-glass-minus", "tags": ["zoom out", "search", "minus"], "category": "ui", "styles": ["outline", "solid", "mini"]},
{"name": "magnifying-glass-plus", "tags": ["zoom in", "search", "plus"], "category": "ui", "styles": ["outline", "solid", "mini"]},
{"name": "map", "tags": ["location", "map", "directions", "navigate"], "category": "maps", "styles": ["outline", "solid", "mini"]},
{"name": "map-pin", "tags": ["location", "pin", "marker", "place"], "category": "maps", "styles": ["outline", "solid", "mini"]},
{"name": "megaphone", "tags": ["announce", "broadcast", "marketing"], "category": "communication", "styles": ["outline", "solid", "mini"]},
{"name": "microphone", "tags": ["audio", "voice", "record", "speak"], "category": "media", "styles": ["outline", "solid", "mini"]},
{"name": "minus", "tags": ["subtract", "remove", "minus", "decrease"], "category": "ui", "styles": ["outline", "solid", "mini"]},
{"name": "minus-circle", "tags": ["remove", "delete", "minus"], "category": "ui", "styles": ["outline", "solid", "mini"]},
{"name": "moon", "tags": ["dark", "night", "mode", "theme"], "category": "objects", "styles": ["outline", "solid", "mini"]},
{"name": "musical-note", "tags": ["music", "audio", "sound", "note"], "category": "media", "styles": ["outline", "solid", "mini"]},
{"name": "newspaper", "tags": ["news", "article", "blog", "press"], "category": "objects", "styles": ["outline", "solid", "mini"]},
{"name": "no-symbol", "tags": ["ban", "prohibited", "forbidden", "block"], "category": "ui", "styles": ["outline", "solid", "mini"]},
{"name": "paint-brush", "tags": ["design", "art", "paint", "brush"], "category": "design", "styles": ["outline", "solid", "mini"]},
{"name": "paper-airplane", "tags": ["send", "message", "email", "submit"], "category": "communication", "styles": ["outline", "solid", "mini"]},
{"name": "paper-clip", "tags": ["attachment", "clip", "attach", "file"], "category": "ui", "styles": ["outline", "solid", "mini"]},
{"name": "pause", "tags": ["media", "pause", "stop", "wait"], "category": "media", "styles": ["outline", "solid", "mini"]},
{"name": "pause-circle", "tags": ["media", "pause", "stop"], "category": "media", "styles": ["outline", "solid", "mini"]},
{"name": "pencil", "tags": ["edit", "write", "pencil", "modify"], "category": "actions", "styles": ["outline", "solid", "mini"]},
{"name": "pencil-square", "tags": ["edit", "write", "compose"], "category": "actions", "styles": ["outline", "solid", "mini"]},
{"name": "phone", "tags": ["call", "phone", "contact", "mobile"], "category": "communication", "styles": ["outline", "solid", "mini"]},
{"name": "phone-arrow-down-left", "tags": ["incoming", "call", "receive"], "category": "communication", "styles": ["outline", "solid", "mini"]},
{"name": "phone-arrow-up-right", "tags": ["outgoing", "call", "dial"], "category": "communication", "styles": ["outline", "solid", "mini"]},
{"name": "phone-x-mark", "tags": ["hang up", "end call", "decline"], "category": "communication", "styles": ["outline", "solid", "mini"]},
{"name": "photo", "tags": ["image", "picture", "photo", "gallery"], "category": "media", "styles": ["outline", "solid", "mini"]},
{"name": "play", "tags": ["media", "play", "start", "video"], "category": "media", "styles": ["outline", "solid", "mini"]},
{"name": "play-circle", "tags": ["media", "play", "video"], "category": "media", "styles": ["outline", "solid", "mini"]},
{"name": "play-pause", "tags": ["media", "toggle", "play", "pause"], "category": "media", "styles": ["outline", "solid", "mini"]},
{"name": "plus", "tags": ["add", "create", "new", "plus"], "category": "ui", "styles": ["outline", "solid", "mini"]},
{"name": "plus-circle", "tags": ["add", "create", "new"], "category": "ui", "styles": ["outline", "solid", "mini"]},
{"name": "power", "tags": ["on", "off", "power", "shutdown"], "category": "ui", "styles": ["outline", "solid", "mini"]},
{"name": "presentation-chart-bar", "tags": ["presentation", "chart", "analytics"], "category": "charts", "styles": ["outline", "solid", "mini"]},
{"name": "presentation-chart-line", "tags": ["presentation", "chart", "analytics"], "category": "charts", "styles": ["outline", "solid", "mini"]},
{"name": "printer", "tags": ["print", "printer", "document"], "category": "devices", "styles": ["outline", "solid", "mini"]},
{"name": "puzzle-piece", "tags": ["plugin", "extension", "puzzle", "addon"], "category": "objects", "styles": ["outline", "solid", "mini"]},
{"name": "qr-code", "tags": ["qr", "code", "scan", "barcode"], "category": "objects", "styles": ["outline", "solid", "mini"]},
{"name": "question-mark-circle", "tags": ["help", "question", "support", "faq"], "category": "ui", "styles": ["outline", "solid", "mini"]},
{"name": "queue-list", "tags": ["list", "queue", "playlist"], "category": "ui", "styles": ["outline", "solid", "mini"]},
{"name": "radio", "tags": ["radio", "audio", "broadcast"], "category": "media", "styles": ["outline", "solid", "mini"]},
{"name": "receipt-percent", "tags": ["discount", "sale", "coupon"], "category": "commerce", "styles": ["outline", "solid", "mini"]},
{"name": "receipt-refund", "tags": ["refund", "return", "money back"], "category": "commerce", "styles": ["outline", "solid", "mini"]},
{"name": "rectangle-group", "tags": ["layout", "grid", "components"], "category": "ui", "styles": ["outline", "solid", "mini"]},
{"name": "rectangle-stack", "tags": ["layers", "stack", "cards"], "category": "ui", "styles": ["outline", "solid", "mini"]},
{"name": "rocket-launch", "tags": ["launch", "startup", "rocket", "deploy"], "category": "objects", "styles": ["outline", "solid", "mini"]},
{"name": "rss", "tags": ["feed", "rss", "subscribe", "blog"], "category": "communication", "styles": ["outline", "solid", "mini"]},
{"name": "scale", "tags": ["balance", "justice", "legal", "weight"], "category": "objects", "styles": ["outline", "solid", "mini"]},
{"name": "scissors", "tags": ["cut", "scissors", "trim", "edit"], "category": "actions", "styles": ["outline", "solid", "mini"]},
{"name": "server", "tags": ["server", "hosting", "database", "backend"], "category": "devices", "styles": ["outline", "solid", "mini"]},
{"name": "server-stack", "tags": ["servers", "hosting", "infrastructure"], "category": "devices", "styles": ["outline", "solid", "mini"]},
{"name": "share", "tags": ["share", "send", "social", "forward"], "category": "actions", "styles": ["outline", "solid", "mini"]},
{"name": "shield-check", "tags": ["security", "protected", "verified", "safe"], "category": "security", "styles": ["outline", "solid", "mini"]},
{"name": "shield-exclamation", "tags": ["security", "warning", "alert"], "category": "security", "styles": ["outline", "solid", "mini"]},
{"name": "shopping-bag", "tags": ["shop", "bag", "purchase", "buy"], "category": "commerce", "styles": ["outline", "solid", "mini"]},
{"name": "shopping-cart", "tags": ["cart", "shop", "ecommerce", "buy"], "category": "commerce", "styles": ["outline", "solid", "mini"]},
{"name": "signal", "tags": ["wifi", "signal", "connection", "network"], "category": "devices", "styles": ["outline", "solid", "mini"]},
{"name": "signal-slash", "tags": ["no signal", "offline", "disconnected"], "category": "devices", "styles": ["outline", "solid", "mini"]},
{"name": "sparkles", "tags": ["magic", "sparkle", "new", "ai"], "category": "objects", "styles": ["outline", "solid", "mini"]},
{"name": "speaker-wave", "tags": ["audio", "sound", "volume", "speaker"], "category": "media", "styles": ["outline", "solid", "mini"]},
{"name": "speaker-x-mark", "tags": ["mute", "silent", "no sound"], "category": "media", "styles": ["outline", "solid", "mini"]},
{"name": "square-2-stack", "tags": ["copy", "duplicate", "stack"], "category": "ui", "styles": ["outline", "solid", "mini"]},
{"name": "square-3-stack-3d", "tags": ["layers", "3d", "stack"], "category": "ui", "styles": ["outline", "solid", "mini"]},
{"name": "squares-2x2", "tags": ["grid", "layout", "dashboard"], "category": "ui", "styles": ["outline", "solid", "mini"]},
{"name": "squares-plus", "tags": ["add", "widget", "new"], "category": "ui", "styles": ["outline", "solid", "mini"]},
{"name": "star", "tags": ["favorite", "star", "rating", "bookmark"], "category": "objects", "styles": ["outline", "solid", "mini"]},
{"name": "stop", "tags": ["media", "stop", "end"], "category": "media", "styles": ["outline", "solid", "mini"]},
{"name": "stop-circle", "tags": ["media", "stop", "end"], "category": "media", "styles": ["outline", "solid", "mini"]},
{"name": "sun", "tags": ["light", "day", "bright", "theme"], "category": "objects", "styles": ["outline", "solid", "mini"]},
{"name": "swatch", "tags": ["color", "palette", "design", "theme"], "category": "design", "styles": ["outline", "solid", "mini"]},
{"name": "table-cells", "tags": ["table", "grid", "spreadsheet", "data"], "category": "ui", "styles": ["outline", "solid", "mini"]},
{"name": "tag", "tags": ["label", "tag", "category", "price"], "category": "commerce", "styles": ["outline", "solid", "mini"]},
{"name": "ticket", "tags": ["ticket", "event", "pass", "coupon"], "category": "objects", "styles": ["outline", "solid", "mini"]},
{"name": "trash", "tags": ["delete", "remove", "trash", "bin"], "category": "actions", "styles": ["outline", "solid", "mini"]},
{"name": "trophy", "tags": ["award", "winner", "achievement", "prize"], "category": "objects", "styles": ["outline", "solid", "mini"]},
{"name": "truck", "tags": ["delivery", "shipping", "truck", "transport"], "category": "objects", "styles": ["outline", "solid", "mini"]},
{"name": "tv", "tags": ["television", "tv", "screen", "display"], "category": "devices", "styles": ["outline", "solid", "mini"]},
{"name": "user", "tags": ["person", "user", "account", "profile"], "category": "users", "styles": ["outline", "solid", "mini"]},
{"name": "user-circle", "tags": ["avatar", "profile", "account"], "category": "users", "styles": ["outline", "solid", "mini"]},
{"name": "user-group", "tags": ["team", "group", "users", "people"], "category": "users", "styles": ["outline", "solid", "mini"]},
{"name": "user-minus", "tags": ["remove user", "unfriend", "delete"], "category": "users", "styles": ["outline", "solid", "mini"]},
{"name": "user-plus", "tags": ["add user", "invite", "new user"], "category": "users", "styles": ["outline", "solid", "mini"]},
{"name": "users", "tags": ["people", "team", "community"], "category": "users", "styles": ["outline", "solid", "mini"]},
{"name": "variable", "tags": ["code", "variable", "math", "programming"], "category": "development", "styles": ["outline", "solid", "mini"]},
{"name": "video-camera", "tags": ["video", "camera", "record", "film"], "category": "media", "styles": ["outline", "solid", "mini"]},
{"name": "video-camera-slash", "tags": ["video off", "camera off", "mute"], "category": "media", "styles": ["outline", "solid", "mini"]},
{"name": "view-columns", "tags": ["columns", "layout", "grid"], "category": "ui", "styles": ["outline", "solid", "mini"]},
{"name": "view-finder-circle", "tags": ["focus", "target", "aim"], "category": "ui", "styles": ["outline", "solid", "mini"]},
{"name": "wallet", "tags": ["money", "payment", "wallet", "finance"], "category": "commerce", "styles": ["outline", "solid", "mini"]},
{"name": "wifi", "tags": ["wireless", "internet", "connection", "network"], "category": "devices", "styles": ["outline", "solid", "mini"]},
{"name": "window", "tags": ["browser", "window", "app"], "category": "ui", "styles": ["outline", "solid", "mini"]},
{"name": "wrench", "tags": ["tools", "settings", "repair", "fix"], "category": "objects", "styles": ["outline", "solid", "mini"]},
{"name": "wrench-screwdriver", "tags": ["tools", "settings", "repair"], "category": "objects", "styles": ["outline", "solid", "mini"]},
{"name": "x-circle", "tags": ["close", "cancel", "remove", "delete"], "category": "ui", "styles": ["outline", "solid", "mini"]},
{"name": "x-mark", "tags": ["close", "cancel", "remove", "x"], "category": "ui", "styles": ["outline", "solid", "mini"]}
]
}

View file

@ -0,0 +1,5 @@
<?php
// Silence is golden.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}

View file

@ -0,0 +1,357 @@
{
"slug": "lucide",
"name": "Lucide",
"version": "0.303.0",
"icons": [
{"name": "accessibility", "tags": ["wheelchair", "disabled", "handicap"], "category": "accessibility", "styles": ["icons"]},
{"name": "activity", "tags": ["pulse", "health", "heart"], "category": "medical", "styles": ["icons"]},
{"name": "air-vent", "tags": ["ventilation", "hvac", "climate"], "category": "home", "styles": ["icons"]},
{"name": "airplay", "tags": ["stream", "cast", "screen"], "category": "devices", "styles": ["icons"]},
{"name": "alarm-clock", "tags": ["time", "wake", "alert"], "category": "time", "styles": ["icons"]},
{"name": "album", "tags": ["music", "photos", "collection"], "category": "media", "styles": ["icons"]},
{"name": "alert-circle", "tags": ["warning", "error", "danger"], "category": "alerts", "styles": ["icons"]},
{"name": "alert-octagon", "tags": ["warning", "stop", "error"], "category": "alerts", "styles": ["icons"]},
{"name": "alert-triangle", "tags": ["warning", "caution", "error"], "category": "alerts", "styles": ["icons"]},
{"name": "align-center", "tags": ["text", "format", "paragraph"], "category": "text", "styles": ["icons"]},
{"name": "align-center-horizontal", "tags": ["layout", "distribute"], "category": "layout", "styles": ["icons"]},
{"name": "align-center-vertical", "tags": ["layout", "distribute"], "category": "layout", "styles": ["icons"]},
{"name": "align-end-horizontal", "tags": ["layout", "distribute"], "category": "layout", "styles": ["icons"]},
{"name": "align-end-vertical", "tags": ["layout", "distribute"], "category": "layout", "styles": ["icons"]},
{"name": "align-horizontal-distribute-center", "tags": ["layout", "spacing"], "category": "layout", "styles": ["icons"]},
{"name": "align-horizontal-distribute-end", "tags": ["layout", "spacing"], "category": "layout", "styles": ["icons"]},
{"name": "align-horizontal-distribute-start", "tags": ["layout", "spacing"], "category": "layout", "styles": ["icons"]},
{"name": "align-horizontal-justify-center", "tags": ["layout", "justify"], "category": "layout", "styles": ["icons"]},
{"name": "align-horizontal-justify-end", "tags": ["layout", "justify"], "category": "layout", "styles": ["icons"]},
{"name": "align-horizontal-justify-start", "tags": ["layout", "justify"], "category": "layout", "styles": ["icons"]},
{"name": "align-horizontal-space-around", "tags": ["layout", "spacing"], "category": "layout", "styles": ["icons"]},
{"name": "align-horizontal-space-between", "tags": ["layout", "spacing"], "category": "layout", "styles": ["icons"]},
{"name": "align-justify", "tags": ["text", "format", "paragraph"], "category": "text", "styles": ["icons"]},
{"name": "align-left", "tags": ["text", "format", "paragraph"], "category": "text", "styles": ["icons"]},
{"name": "align-right", "tags": ["text", "format", "paragraph"], "category": "text", "styles": ["icons"]},
{"name": "align-start-horizontal", "tags": ["layout", "distribute"], "category": "layout", "styles": ["icons"]},
{"name": "align-start-vertical", "tags": ["layout", "distribute"], "category": "layout", "styles": ["icons"]},
{"name": "align-vertical-distribute-center", "tags": ["layout", "spacing"], "category": "layout", "styles": ["icons"]},
{"name": "align-vertical-distribute-end", "tags": ["layout", "spacing"], "category": "layout", "styles": ["icons"]},
{"name": "align-vertical-distribute-start", "tags": ["layout", "spacing"], "category": "layout", "styles": ["icons"]},
{"name": "align-vertical-justify-center", "tags": ["layout", "justify"], "category": "layout", "styles": ["icons"]},
{"name": "align-vertical-justify-end", "tags": ["layout", "justify"], "category": "layout", "styles": ["icons"]},
{"name": "align-vertical-justify-start", "tags": ["layout", "justify"], "category": "layout", "styles": ["icons"]},
{"name": "align-vertical-space-around", "tags": ["layout", "spacing"], "category": "layout", "styles": ["icons"]},
{"name": "align-vertical-space-between", "tags": ["layout", "spacing"], "category": "layout", "styles": ["icons"]},
{"name": "anchor", "tags": ["link", "marine", "ship"], "category": "navigation", "styles": ["icons"]},
{"name": "angry", "tags": ["emoji", "emotion", "face"], "category": "emoji", "styles": ["icons"]},
{"name": "annoyed", "tags": ["emoji", "emotion", "face"], "category": "emoji", "styles": ["icons"]},
{"name": "aperture", "tags": ["camera", "lens", "photo"], "category": "photography", "styles": ["icons"]},
{"name": "app-window", "tags": ["application", "program", "software"], "category": "development", "styles": ["icons"]},
{"name": "apple", "tags": ["fruit", "food", "healthy"], "category": "food", "styles": ["icons"]},
{"name": "archive", "tags": ["box", "storage", "files"], "category": "files", "styles": ["icons"]},
{"name": "archive-restore", "tags": ["unarchive", "restore", "files"], "category": "files", "styles": ["icons"]},
{"name": "archive-x", "tags": ["delete", "remove", "files"], "category": "files", "styles": ["icons"]},
{"name": "armchair", "tags": ["furniture", "seat", "chair"], "category": "furniture", "styles": ["icons"]},
{"name": "arrow-big-down", "tags": ["direction", "down", "navigation"], "category": "arrows", "styles": ["icons"]},
{"name": "arrow-big-down-dash", "tags": ["direction", "down", "end"], "category": "arrows", "styles": ["icons"]},
{"name": "arrow-big-left", "tags": ["direction", "left", "back"], "category": "arrows", "styles": ["icons"]},
{"name": "arrow-big-left-dash", "tags": ["direction", "left", "start"], "category": "arrows", "styles": ["icons"]},
{"name": "arrow-big-right", "tags": ["direction", "right", "forward"], "category": "arrows", "styles": ["icons"]},
{"name": "arrow-big-right-dash", "tags": ["direction", "right", "end"], "category": "arrows", "styles": ["icons"]},
{"name": "arrow-big-up", "tags": ["direction", "up", "navigation"], "category": "arrows", "styles": ["icons"]},
{"name": "arrow-big-up-dash", "tags": ["direction", "up", "start"], "category": "arrows", "styles": ["icons"]},
{"name": "arrow-down", "tags": ["direction", "down"], "category": "arrows", "styles": ["icons"]},
{"name": "arrow-down-circle", "tags": ["direction", "down", "circle"], "category": "arrows", "styles": ["icons"]},
{"name": "arrow-down-from-line", "tags": ["download", "export"], "category": "arrows", "styles": ["icons"]},
{"name": "arrow-down-left", "tags": ["direction", "diagonal"], "category": "arrows", "styles": ["icons"]},
{"name": "arrow-down-left-from-circle", "tags": ["direction", "exit"], "category": "arrows", "styles": ["icons"]},
{"name": "arrow-down-right", "tags": ["direction", "diagonal"], "category": "arrows", "styles": ["icons"]},
{"name": "arrow-down-right-from-circle", "tags": ["direction", "exit"], "category": "arrows", "styles": ["icons"]},
{"name": "arrow-down-to-dot", "tags": ["direction", "target"], "category": "arrows", "styles": ["icons"]},
{"name": "arrow-down-to-line", "tags": ["download", "bottom"], "category": "arrows", "styles": ["icons"]},
{"name": "arrow-left", "tags": ["direction", "back", "previous"], "category": "arrows", "styles": ["icons"]},
{"name": "arrow-left-circle", "tags": ["direction", "back", "circle"], "category": "arrows", "styles": ["icons"]},
{"name": "arrow-left-from-line", "tags": ["exit", "leave"], "category": "arrows", "styles": ["icons"]},
{"name": "arrow-left-right", "tags": ["swap", "exchange", "horizontal"], "category": "arrows", "styles": ["icons"]},
{"name": "arrow-left-to-line", "tags": ["start", "beginning"], "category": "arrows", "styles": ["icons"]},
{"name": "arrow-right", "tags": ["direction", "forward", "next"], "category": "arrows", "styles": ["icons"]},
{"name": "arrow-right-circle", "tags": ["direction", "forward", "circle"], "category": "arrows", "styles": ["icons"]},
{"name": "arrow-right-from-line", "tags": ["exit", "export"], "category": "arrows", "styles": ["icons"]},
{"name": "arrow-right-to-line", "tags": ["end", "finish"], "category": "arrows", "styles": ["icons"]},
{"name": "arrow-up", "tags": ["direction", "up"], "category": "arrows", "styles": ["icons"]},
{"name": "arrow-up-circle", "tags": ["direction", "up", "circle"], "category": "arrows", "styles": ["icons"]},
{"name": "arrow-up-down", "tags": ["sort", "reorder", "vertical"], "category": "arrows", "styles": ["icons"]},
{"name": "arrow-up-from-dot", "tags": ["direction", "source"], "category": "arrows", "styles": ["icons"]},
{"name": "arrow-up-from-line", "tags": ["upload", "export"], "category": "arrows", "styles": ["icons"]},
{"name": "arrow-up-left", "tags": ["direction", "diagonal"], "category": "arrows", "styles": ["icons"]},
{"name": "arrow-up-right", "tags": ["direction", "diagonal", "external"], "category": "arrows", "styles": ["icons"]},
{"name": "arrow-up-to-line", "tags": ["upload", "top"], "category": "arrows", "styles": ["icons"]},
{"name": "asterisk", "tags": ["star", "required", "note"], "category": "symbols", "styles": ["icons"]},
{"name": "at-sign", "tags": ["email", "mention", "at"], "category": "communication", "styles": ["icons"]},
{"name": "atom", "tags": ["science", "physics", "nuclear"], "category": "science", "styles": ["icons"]},
{"name": "award", "tags": ["achievement", "badge", "medal"], "category": "awards", "styles": ["icons"]},
{"name": "axe", "tags": ["tool", "chop", "wood"], "category": "tools", "styles": ["icons"]},
{"name": "baby", "tags": ["child", "infant", "kid"], "category": "people", "styles": ["icons"]},
{"name": "backpack", "tags": ["bag", "school", "travel"], "category": "objects", "styles": ["icons"]},
{"name": "badge", "tags": ["label", "tag", "verified"], "category": "ui", "styles": ["icons"]},
{"name": "badge-alert", "tags": ["warning", "notification"], "category": "ui", "styles": ["icons"]},
{"name": "badge-check", "tags": ["verified", "approved", "done"], "category": "ui", "styles": ["icons"]},
{"name": "badge-dollar-sign", "tags": ["money", "price", "cost"], "category": "commerce", "styles": ["icons"]},
{"name": "badge-help", "tags": ["question", "support", "info"], "category": "ui", "styles": ["icons"]},
{"name": "badge-info", "tags": ["information", "details", "about"], "category": "ui", "styles": ["icons"]},
{"name": "badge-minus", "tags": ["remove", "subtract", "delete"], "category": "ui", "styles": ["icons"]},
{"name": "badge-percent", "tags": ["discount", "sale", "offer"], "category": "commerce", "styles": ["icons"]},
{"name": "badge-plus", "tags": ["add", "new", "create"], "category": "ui", "styles": ["icons"]},
{"name": "badge-x", "tags": ["remove", "delete", "cancel"], "category": "ui", "styles": ["icons"]},
{"name": "baggage-claim", "tags": ["airport", "luggage", "travel"], "category": "travel", "styles": ["icons"]},
{"name": "ban", "tags": ["block", "forbidden", "prohibited"], "category": "ui", "styles": ["icons"]},
{"name": "banana", "tags": ["fruit", "food", "healthy"], "category": "food", "styles": ["icons"]},
{"name": "banknote", "tags": ["money", "cash", "currency"], "category": "commerce", "styles": ["icons"]},
{"name": "bar-chart", "tags": ["analytics", "statistics", "graph"], "category": "charts", "styles": ["icons"]},
{"name": "bar-chart-2", "tags": ["analytics", "statistics", "graph"], "category": "charts", "styles": ["icons"]},
{"name": "bar-chart-3", "tags": ["analytics", "statistics", "graph"], "category": "charts", "styles": ["icons"]},
{"name": "bar-chart-4", "tags": ["analytics", "statistics", "graph"], "category": "charts", "styles": ["icons"]},
{"name": "bar-chart-big", "tags": ["analytics", "statistics", "graph"], "category": "charts", "styles": ["icons"]},
{"name": "bar-chart-horizontal", "tags": ["analytics", "statistics", "graph"], "category": "charts", "styles": ["icons"]},
{"name": "bar-chart-horizontal-big", "tags": ["analytics", "statistics", "graph"], "category": "charts", "styles": ["icons"]},
{"name": "battery", "tags": ["power", "energy", "charge"], "category": "devices", "styles": ["icons"]},
{"name": "battery-charging", "tags": ["power", "energy", "charge"], "category": "devices", "styles": ["icons"]},
{"name": "battery-full", "tags": ["power", "energy", "full"], "category": "devices", "styles": ["icons"]},
{"name": "battery-low", "tags": ["power", "energy", "low"], "category": "devices", "styles": ["icons"]},
{"name": "battery-medium", "tags": ["power", "energy", "half"], "category": "devices", "styles": ["icons"]},
{"name": "battery-warning", "tags": ["power", "energy", "alert"], "category": "devices", "styles": ["icons"]},
{"name": "beaker", "tags": ["science", "lab", "chemistry"], "category": "science", "styles": ["icons"]},
{"name": "bean", "tags": ["food", "vegetable", "seed"], "category": "food", "styles": ["icons"]},
{"name": "bean-off", "tags": ["food", "allergy", "no"], "category": "food", "styles": ["icons"]},
{"name": "bed", "tags": ["sleep", "hotel", "rest"], "category": "furniture", "styles": ["icons"]},
{"name": "bed-double", "tags": ["sleep", "hotel", "bedroom"], "category": "furniture", "styles": ["icons"]},
{"name": "bed-single", "tags": ["sleep", "hotel", "bedroom"], "category": "furniture", "styles": ["icons"]},
{"name": "beer", "tags": ["drink", "alcohol", "bar"], "category": "food", "styles": ["icons"]},
{"name": "bell", "tags": ["notification", "alert", "alarm"], "category": "notifications", "styles": ["icons"]},
{"name": "bell-dot", "tags": ["notification", "alert", "new"], "category": "notifications", "styles": ["icons"]},
{"name": "bell-minus", "tags": ["notification", "remove", "mute"], "category": "notifications", "styles": ["icons"]},
{"name": "bell-off", "tags": ["notification", "mute", "silent"], "category": "notifications", "styles": ["icons"]},
{"name": "bell-plus", "tags": ["notification", "add", "subscribe"], "category": "notifications", "styles": ["icons"]},
{"name": "bell-ring", "tags": ["notification", "alert", "ringing"], "category": "notifications", "styles": ["icons"]},
{"name": "bike", "tags": ["bicycle", "cycling", "transport"], "category": "transportation", "styles": ["icons"]},
{"name": "binary", "tags": ["code", "programming", "data"], "category": "development", "styles": ["icons"]},
{"name": "bluetooth", "tags": ["wireless", "connection", "device"], "category": "connectivity", "styles": ["icons"]},
{"name": "bluetooth-connected", "tags": ["wireless", "paired", "device"], "category": "connectivity", "styles": ["icons"]},
{"name": "bluetooth-off", "tags": ["wireless", "disabled", "device"], "category": "connectivity", "styles": ["icons"]},
{"name": "bluetooth-searching", "tags": ["wireless", "scanning", "device"], "category": "connectivity", "styles": ["icons"]},
{"name": "bold", "tags": ["text", "format", "strong"], "category": "text", "styles": ["icons"]},
{"name": "bomb", "tags": ["explosive", "danger", "warning"], "category": "objects", "styles": ["icons"]},
{"name": "bone", "tags": ["skeleton", "body", "medical"], "category": "medical", "styles": ["icons"]},
{"name": "book", "tags": ["read", "library", "education"], "category": "education", "styles": ["icons"]},
{"name": "book-copy", "tags": ["duplicate", "clone", "library"], "category": "education", "styles": ["icons"]},
{"name": "book-down", "tags": ["download", "save", "library"], "category": "education", "styles": ["icons"]},
{"name": "book-key", "tags": ["password", "secret", "secure"], "category": "education", "styles": ["icons"]},
{"name": "book-lock", "tags": ["private", "secure", "protected"], "category": "education", "styles": ["icons"]},
{"name": "book-marked", "tags": ["bookmark", "saved", "reading"], "category": "education", "styles": ["icons"]},
{"name": "book-minus", "tags": ["remove", "delete", "library"], "category": "education", "styles": ["icons"]},
{"name": "book-open", "tags": ["read", "library", "education"], "category": "education", "styles": ["icons"]},
{"name": "book-open-check", "tags": ["read", "complete", "done"], "category": "education", "styles": ["icons"]},
{"name": "book-plus", "tags": ["add", "new", "library"], "category": "education", "styles": ["icons"]},
{"name": "book-up", "tags": ["upload", "export", "library"], "category": "education", "styles": ["icons"]},
{"name": "book-x", "tags": ["remove", "cancel", "library"], "category": "education", "styles": ["icons"]},
{"name": "bookmark", "tags": ["save", "favorite", "tag"], "category": "actions", "styles": ["icons"]},
{"name": "bookmark-minus", "tags": ["remove", "unsave", "tag"], "category": "actions", "styles": ["icons"]},
{"name": "bookmark-plus", "tags": ["add", "save", "tag"], "category": "actions", "styles": ["icons"]},
{"name": "bot", "tags": ["robot", "ai", "automation"], "category": "development", "styles": ["icons"]},
{"name": "box", "tags": ["package", "container", "storage"], "category": "objects", "styles": ["icons"]},
{"name": "box-select", "tags": ["selection", "area", "region"], "category": "ui", "styles": ["icons"]},
{"name": "boxes", "tags": ["packages", "inventory", "storage"], "category": "objects", "styles": ["icons"]},
{"name": "braces", "tags": ["code", "curly", "programming"], "category": "development", "styles": ["icons"]},
{"name": "brackets", "tags": ["code", "array", "programming"], "category": "development", "styles": ["icons"]},
{"name": "brain", "tags": ["mind", "thinking", "intelligence"], "category": "medical", "styles": ["icons"]},
{"name": "briefcase", "tags": ["work", "job", "business"], "category": "business", "styles": ["icons"]},
{"name": "brush", "tags": ["paint", "art", "design"], "category": "design", "styles": ["icons"]},
{"name": "bug", "tags": ["insect", "error", "debug"], "category": "development", "styles": ["icons"]},
{"name": "building", "tags": ["office", "company", "business"], "category": "buildings", "styles": ["icons"]},
{"name": "building-2", "tags": ["office", "company", "business"], "category": "buildings", "styles": ["icons"]},
{"name": "bus", "tags": ["transport", "vehicle", "travel"], "category": "transportation", "styles": ["icons"]},
{"name": "cable", "tags": ["wire", "connection", "plug"], "category": "devices", "styles": ["icons"]},
{"name": "cake", "tags": ["birthday", "celebration", "party"], "category": "food", "styles": ["icons"]},
{"name": "calculator", "tags": ["math", "calculate", "numbers"], "category": "tools", "styles": ["icons"]},
{"name": "calendar", "tags": ["date", "schedule", "event"], "category": "time", "styles": ["icons"]},
{"name": "calendar-check", "tags": ["date", "done", "confirmed"], "category": "time", "styles": ["icons"]},
{"name": "calendar-clock", "tags": ["date", "time", "schedule"], "category": "time", "styles": ["icons"]},
{"name": "calendar-days", "tags": ["date", "month", "schedule"], "category": "time", "styles": ["icons"]},
{"name": "camera", "tags": ["photo", "picture", "image"], "category": "devices", "styles": ["icons"]},
{"name": "camera-off", "tags": ["photo", "disabled", "no"], "category": "devices", "styles": ["icons"]},
{"name": "car", "tags": ["vehicle", "transport", "drive"], "category": "transportation", "styles": ["icons"]},
{"name": "check", "tags": ["done", "complete", "success"], "category": "ui", "styles": ["icons"]},
{"name": "check-check", "tags": ["done", "verified", "double"], "category": "ui", "styles": ["icons"]},
{"name": "check-circle", "tags": ["done", "complete", "success"], "category": "ui", "styles": ["icons"]},
{"name": "check-circle-2", "tags": ["done", "complete", "success"], "category": "ui", "styles": ["icons"]},
{"name": "check-square", "tags": ["done", "checkbox", "task"], "category": "ui", "styles": ["icons"]},
{"name": "chevron-down", "tags": ["arrow", "expand", "dropdown"], "category": "arrows", "styles": ["icons"]},
{"name": "chevron-left", "tags": ["arrow", "back", "previous"], "category": "arrows", "styles": ["icons"]},
{"name": "chevron-right", "tags": ["arrow", "forward", "next"], "category": "arrows", "styles": ["icons"]},
{"name": "chevron-up", "tags": ["arrow", "collapse", "up"], "category": "arrows", "styles": ["icons"]},
{"name": "chevrons-down", "tags": ["arrows", "expand", "more"], "category": "arrows", "styles": ["icons"]},
{"name": "chevrons-left", "tags": ["arrows", "back", "first"], "category": "arrows", "styles": ["icons"]},
{"name": "chevrons-right", "tags": ["arrows", "forward", "last"], "category": "arrows", "styles": ["icons"]},
{"name": "chevrons-up", "tags": ["arrows", "collapse", "less"], "category": "arrows", "styles": ["icons"]},
{"name": "circle", "tags": ["shape", "dot", "record"], "category": "shapes", "styles": ["icons"]},
{"name": "clipboard", "tags": ["copy", "paste", "board"], "category": "actions", "styles": ["icons"]},
{"name": "clipboard-check", "tags": ["done", "verified", "complete"], "category": "actions", "styles": ["icons"]},
{"name": "clipboard-copy", "tags": ["copy", "duplicate", "paste"], "category": "actions", "styles": ["icons"]},
{"name": "clipboard-list", "tags": ["tasks", "checklist", "todo"], "category": "actions", "styles": ["icons"]},
{"name": "clock", "tags": ["time", "watch", "schedule"], "category": "time", "styles": ["icons"]},
{"name": "cloud", "tags": ["weather", "storage", "sky"], "category": "weather", "styles": ["icons"]},
{"name": "cloud-download", "tags": ["download", "save", "sync"], "category": "actions", "styles": ["icons"]},
{"name": "cloud-off", "tags": ["offline", "disconnect", "no"], "category": "weather", "styles": ["icons"]},
{"name": "cloud-upload", "tags": ["upload", "sync", "backup"], "category": "actions", "styles": ["icons"]},
{"name": "code", "tags": ["programming", "html", "development"], "category": "development", "styles": ["icons"]},
{"name": "code-2", "tags": ["programming", "brackets", "development"], "category": "development", "styles": ["icons"]},
{"name": "coffee", "tags": ["drink", "cup", "cafe"], "category": "food", "styles": ["icons"]},
{"name": "cog", "tags": ["settings", "gear", "config"], "category": "ui", "styles": ["icons"]},
{"name": "command", "tags": ["keyboard", "mac", "shortcut"], "category": "devices", "styles": ["icons"]},
{"name": "compass", "tags": ["navigation", "direction", "explore"], "category": "navigation", "styles": ["icons"]},
{"name": "copy", "tags": ["duplicate", "clipboard", "clone"], "category": "actions", "styles": ["icons"]},
{"name": "credit-card", "tags": ["payment", "card", "money"], "category": "commerce", "styles": ["icons"]},
{"name": "crop", "tags": ["image", "edit", "resize"], "category": "editing", "styles": ["icons"]},
{"name": "database", "tags": ["storage", "data", "server"], "category": "development", "styles": ["icons"]},
{"name": "delete", "tags": ["remove", "trash", "erase"], "category": "actions", "styles": ["icons"]},
{"name": "download", "tags": ["save", "export", "arrow"], "category": "actions", "styles": ["icons"]},
{"name": "download-cloud", "tags": ["save", "sync", "backup"], "category": "actions", "styles": ["icons"]},
{"name": "edit", "tags": ["pencil", "write", "modify"], "category": "actions", "styles": ["icons"]},
{"name": "edit-2", "tags": ["pencil", "write", "modify"], "category": "actions", "styles": ["icons"]},
{"name": "edit-3", "tags": ["pencil", "write", "modify"], "category": "actions", "styles": ["icons"]},
{"name": "external-link", "tags": ["link", "open", "new window"], "category": "actions", "styles": ["icons"]},
{"name": "eye", "tags": ["view", "visible", "show"], "category": "actions", "styles": ["icons"]},
{"name": "eye-off", "tags": ["hide", "invisible", "hidden"], "category": "actions", "styles": ["icons"]},
{"name": "file", "tags": ["document", "page", "paper"], "category": "files", "styles": ["icons"]},
{"name": "file-plus", "tags": ["document", "add", "new"], "category": "files", "styles": ["icons"]},
{"name": "file-text", "tags": ["document", "text", "content"], "category": "files", "styles": ["icons"]},
{"name": "filter", "tags": ["funnel", "sort", "search"], "category": "actions", "styles": ["icons"]},
{"name": "flag", "tags": ["report", "mark", "country"], "category": "objects", "styles": ["icons"]},
{"name": "folder", "tags": ["directory", "files", "organize"], "category": "files", "styles": ["icons"]},
{"name": "folder-open", "tags": ["directory", "browse", "explore"], "category": "files", "styles": ["icons"]},
{"name": "folder-plus", "tags": ["directory", "add", "new"], "category": "files", "styles": ["icons"]},
{"name": "gift", "tags": ["present", "reward", "surprise"], "category": "objects", "styles": ["icons"]},
{"name": "globe", "tags": ["world", "earth", "web"], "category": "objects", "styles": ["icons"]},
{"name": "grid", "tags": ["layout", "squares", "dashboard"], "category": "layout", "styles": ["icons"]},
{"name": "hash", "tags": ["tag", "hashtag", "number"], "category": "communication", "styles": ["icons"]},
{"name": "heart", "tags": ["love", "favorite", "like"], "category": "objects", "styles": ["icons"]},
{"name": "help-circle", "tags": ["question", "help", "support"], "category": "ui", "styles": ["icons"]},
{"name": "home", "tags": ["house", "main", "dashboard"], "category": "navigation", "styles": ["icons"]},
{"name": "image", "tags": ["picture", "photo", "gallery"], "category": "media", "styles": ["icons"]},
{"name": "inbox", "tags": ["email", "messages", "mail"], "category": "communication", "styles": ["icons"]},
{"name": "info", "tags": ["information", "help", "about"], "category": "ui", "styles": ["icons"]},
{"name": "key", "tags": ["password", "security", "lock"], "category": "security", "styles": ["icons"]},
{"name": "layers", "tags": ["stack", "levels", "depth"], "category": "design", "styles": ["icons"]},
{"name": "layout", "tags": ["grid", "template", "design"], "category": "layout", "styles": ["icons"]},
{"name": "link", "tags": ["url", "chain", "connect"], "category": "actions", "styles": ["icons"]},
{"name": "list", "tags": ["menu", "items", "bullet"], "category": "text", "styles": ["icons"]},
{"name": "loader", "tags": ["loading", "spinner", "wait"], "category": "ui", "styles": ["icons"]},
{"name": "loader-2", "tags": ["loading", "spinner", "wait"], "category": "ui", "styles": ["icons"]},
{"name": "lock", "tags": ["security", "private", "password"], "category": "security", "styles": ["icons"]},
{"name": "log-in", "tags": ["login", "signin", "enter"], "category": "actions", "styles": ["icons"]},
{"name": "log-out", "tags": ["logout", "signout", "exit"], "category": "actions", "styles": ["icons"]},
{"name": "mail", "tags": ["email", "message", "envelope"], "category": "communication", "styles": ["icons"]},
{"name": "map", "tags": ["location", "navigation", "directions"], "category": "maps", "styles": ["icons"]},
{"name": "map-pin", "tags": ["location", "marker", "place"], "category": "maps", "styles": ["icons"]},
{"name": "maximize", "tags": ["fullscreen", "expand", "resize"], "category": "actions", "styles": ["icons"]},
{"name": "maximize-2", "tags": ["fullscreen", "expand", "resize"], "category": "actions", "styles": ["icons"]},
{"name": "menu", "tags": ["hamburger", "navigation", "bars"], "category": "navigation", "styles": ["icons"]},
{"name": "message-circle", "tags": ["chat", "comment", "conversation"], "category": "communication", "styles": ["icons"]},
{"name": "message-square", "tags": ["chat", "comment", "conversation"], "category": "communication", "styles": ["icons"]},
{"name": "mic", "tags": ["microphone", "audio", "record"], "category": "media", "styles": ["icons"]},
{"name": "mic-off", "tags": ["microphone", "mute", "silent"], "category": "media", "styles": ["icons"]},
{"name": "minimize", "tags": ["collapse", "shrink", "resize"], "category": "actions", "styles": ["icons"]},
{"name": "minimize-2", "tags": ["collapse", "shrink", "resize"], "category": "actions", "styles": ["icons"]},
{"name": "minus", "tags": ["subtract", "remove", "delete"], "category": "math", "styles": ["icons"]},
{"name": "minus-circle", "tags": ["subtract", "remove", "delete"], "category": "math", "styles": ["icons"]},
{"name": "monitor", "tags": ["screen", "display", "desktop"], "category": "devices", "styles": ["icons"]},
{"name": "moon", "tags": ["dark", "night", "theme"], "category": "weather", "styles": ["icons"]},
{"name": "more-horizontal", "tags": ["menu", "options", "dots"], "category": "ui", "styles": ["icons"]},
{"name": "more-vertical", "tags": ["menu", "options", "dots"], "category": "ui", "styles": ["icons"]},
{"name": "move", "tags": ["drag", "reorder", "arrows"], "category": "actions", "styles": ["icons"]},
{"name": "music", "tags": ["audio", "sound", "note"], "category": "media", "styles": ["icons"]},
{"name": "navigation", "tags": ["direction", "arrow", "location"], "category": "navigation", "styles": ["icons"]},
{"name": "package", "tags": ["box", "delivery", "shipping"], "category": "objects", "styles": ["icons"]},
{"name": "paperclip", "tags": ["attachment", "file", "clip"], "category": "actions", "styles": ["icons"]},
{"name": "pause", "tags": ["media", "stop", "wait"], "category": "media", "styles": ["icons"]},
{"name": "pencil", "tags": ["edit", "write", "draw"], "category": "actions", "styles": ["icons"]},
{"name": "phone", "tags": ["call", "contact", "mobile"], "category": "communication", "styles": ["icons"]},
{"name": "pie-chart", "tags": ["analytics", "statistics", "data"], "category": "charts", "styles": ["icons"]},
{"name": "play", "tags": ["media", "start", "video"], "category": "media", "styles": ["icons"]},
{"name": "play-circle", "tags": ["media", "start", "video"], "category": "media", "styles": ["icons"]},
{"name": "plus", "tags": ["add", "create", "new"], "category": "math", "styles": ["icons"]},
{"name": "plus-circle", "tags": ["add", "create", "new"], "category": "math", "styles": ["icons"]},
{"name": "power", "tags": ["on", "off", "shutdown"], "category": "devices", "styles": ["icons"]},
{"name": "printer", "tags": ["print", "document", "paper"], "category": "devices", "styles": ["icons"]},
{"name": "refresh-ccw", "tags": ["reload", "sync", "update"], "category": "actions", "styles": ["icons"]},
{"name": "refresh-cw", "tags": ["reload", "sync", "update"], "category": "actions", "styles": ["icons"]},
{"name": "repeat", "tags": ["loop", "replay", "refresh"], "category": "media", "styles": ["icons"]},
{"name": "rotate-ccw", "tags": ["undo", "rotate", "turn"], "category": "actions", "styles": ["icons"]},
{"name": "rotate-cw", "tags": ["redo", "rotate", "turn"], "category": "actions", "styles": ["icons"]},
{"name": "rss", "tags": ["feed", "subscribe", "blog"], "category": "communication", "styles": ["icons"]},
{"name": "save", "tags": ["disk", "floppy", "store"], "category": "actions", "styles": ["icons"]},
{"name": "scissors", "tags": ["cut", "trim", "edit"], "category": "actions", "styles": ["icons"]},
{"name": "search", "tags": ["find", "magnify", "look"], "category": "actions", "styles": ["icons"]},
{"name": "send", "tags": ["message", "email", "submit"], "category": "communication", "styles": ["icons"]},
{"name": "server", "tags": ["hosting", "database", "backend"], "category": "devices", "styles": ["icons"]},
{"name": "settings", "tags": ["gear", "cog", "preferences"], "category": "ui", "styles": ["icons"]},
{"name": "settings-2", "tags": ["sliders", "controls", "adjust"], "category": "ui", "styles": ["icons"]},
{"name": "share", "tags": ["social", "send", "forward"], "category": "actions", "styles": ["icons"]},
{"name": "share-2", "tags": ["social", "send", "network"], "category": "actions", "styles": ["icons"]},
{"name": "shield", "tags": ["security", "protection", "safe"], "category": "security", "styles": ["icons"]},
{"name": "shopping-bag", "tags": ["shop", "purchase", "buy"], "category": "commerce", "styles": ["icons"]},
{"name": "shopping-cart", "tags": ["shop", "cart", "ecommerce"], "category": "commerce", "styles": ["icons"]},
{"name": "shuffle", "tags": ["random", "mix", "music"], "category": "media", "styles": ["icons"]},
{"name": "skip-back", "tags": ["media", "previous", "rewind"], "category": "media", "styles": ["icons"]},
{"name": "skip-forward", "tags": ["media", "next", "forward"], "category": "media", "styles": ["icons"]},
{"name": "slash", "tags": ["ban", "cancel", "disabled"], "category": "ui", "styles": ["icons"]},
{"name": "sliders", "tags": ["settings", "controls", "adjust"], "category": "ui", "styles": ["icons"]},
{"name": "smartphone", "tags": ["phone", "mobile", "device"], "category": "devices", "styles": ["icons"]},
{"name": "smile", "tags": ["happy", "emoji", "face"], "category": "emoji", "styles": ["icons"]},
{"name": "sparkles", "tags": ["magic", "new", "ai"], "category": "objects", "styles": ["icons"]},
{"name": "speaker", "tags": ["audio", "sound", "volume"], "category": "media", "styles": ["icons"]},
{"name": "star", "tags": ["favorite", "rating", "bookmark"], "category": "objects", "styles": ["icons"]},
{"name": "stop-circle", "tags": ["media", "stop", "end"], "category": "media", "styles": ["icons"]},
{"name": "sun", "tags": ["light", "day", "brightness"], "category": "weather", "styles": ["icons"]},
{"name": "table", "tags": ["data", "grid", "spreadsheet"], "category": "data", "styles": ["icons"]},
{"name": "tablet", "tags": ["device", "ipad", "screen"], "category": "devices", "styles": ["icons"]},
{"name": "tag", "tags": ["label", "category", "price"], "category": "commerce", "styles": ["icons"]},
{"name": "target", "tags": ["goal", "aim", "focus"], "category": "ui", "styles": ["icons"]},
{"name": "terminal", "tags": ["console", "command", "code"], "category": "development", "styles": ["icons"]},
{"name": "thumbs-down", "tags": ["dislike", "bad", "negative"], "category": "actions", "styles": ["icons"]},
{"name": "thumbs-up", "tags": ["like", "good", "positive"], "category": "actions", "styles": ["icons"]},
{"name": "toggle-left", "tags": ["switch", "off", "disable"], "category": "ui", "styles": ["icons"]},
{"name": "toggle-right", "tags": ["switch", "on", "enable"], "category": "ui", "styles": ["icons"]},
{"name": "trash", "tags": ["delete", "remove", "bin"], "category": "actions", "styles": ["icons"]},
{"name": "trash-2", "tags": ["delete", "remove", "bin"], "category": "actions", "styles": ["icons"]},
{"name": "trending-down", "tags": ["chart", "decrease", "analytics"], "category": "charts", "styles": ["icons"]},
{"name": "trending-up", "tags": ["chart", "increase", "analytics"], "category": "charts", "styles": ["icons"]},
{"name": "triangle", "tags": ["shape", "polygon", "warning"], "category": "shapes", "styles": ["icons"]},
{"name": "truck", "tags": ["delivery", "shipping", "transport"], "category": "transportation", "styles": ["icons"]},
{"name": "tv", "tags": ["television", "screen", "display"], "category": "devices", "styles": ["icons"]},
{"name": "type", "tags": ["text", "font", "typography"], "category": "text", "styles": ["icons"]},
{"name": "umbrella", "tags": ["weather", "rain", "protection"], "category": "weather", "styles": ["icons"]},
{"name": "underline", "tags": ["text", "format", "style"], "category": "text", "styles": ["icons"]},
{"name": "undo", "tags": ["back", "reverse", "history"], "category": "actions", "styles": ["icons"]},
{"name": "unlock", "tags": ["security", "open", "access"], "category": "security", "styles": ["icons"]},
{"name": "upload", "tags": ["export", "send", "share"], "category": "actions", "styles": ["icons"]},
{"name": "upload-cloud", "tags": ["export", "sync", "backup"], "category": "actions", "styles": ["icons"]},
{"name": "user", "tags": ["person", "account", "profile"], "category": "users", "styles": ["icons"]},
{"name": "user-check", "tags": ["person", "verified", "approved"], "category": "users", "styles": ["icons"]},
{"name": "user-minus", "tags": ["person", "remove", "unfriend"], "category": "users", "styles": ["icons"]},
{"name": "user-plus", "tags": ["person", "add", "invite"], "category": "users", "styles": ["icons"]},
{"name": "user-x", "tags": ["person", "delete", "remove"], "category": "users", "styles": ["icons"]},
{"name": "users", "tags": ["people", "team", "group"], "category": "users", "styles": ["icons"]},
{"name": "video", "tags": ["camera", "film", "record"], "category": "media", "styles": ["icons"]},
{"name": "video-off", "tags": ["camera", "disabled", "mute"], "category": "media", "styles": ["icons"]},
{"name": "volume", "tags": ["sound", "audio", "speaker"], "category": "media", "styles": ["icons"]},
{"name": "volume-1", "tags": ["sound", "audio", "low"], "category": "media", "styles": ["icons"]},
{"name": "volume-2", "tags": ["sound", "audio", "high"], "category": "media", "styles": ["icons"]},
{"name": "volume-x", "tags": ["mute", "silent", "no sound"], "category": "media", "styles": ["icons"]},
{"name": "wallet", "tags": ["money", "payment", "finance"], "category": "commerce", "styles": ["icons"]},
{"name": "wifi", "tags": ["wireless", "internet", "connection"], "category": "connectivity", "styles": ["icons"]},
{"name": "wifi-off", "tags": ["wireless", "offline", "disconnect"], "category": "connectivity", "styles": ["icons"]},
{"name": "x", "tags": ["close", "cancel", "remove"], "category": "actions", "styles": ["icons"]},
{"name": "x-circle", "tags": ["close", "cancel", "error"], "category": "actions", "styles": ["icons"]},
{"name": "zap", "tags": ["lightning", "power", "energy"], "category": "objects", "styles": ["icons"]},
{"name": "zap-off", "tags": ["lightning", "disabled", "off"], "category": "objects", "styles": ["icons"]},
{"name": "zoom-in", "tags": ["magnify", "enlarge", "plus"], "category": "actions", "styles": ["icons"]},
{"name": "zoom-out", "tags": ["magnify", "shrink", "minus"], "category": "actions", "styles": ["icons"]}
]
}

View file

@ -0,0 +1,455 @@
{
"name": "Material Symbols",
"slug": "material",
"version": "latest",
"license": "Apache-2.0",
"url": "https://fonts.google.com/icons",
"styles": ["outlined", "rounded", "sharp"],
"defaultStyle": "outlined",
"viewBox": "0 0 24 24",
"cdn": {
"base": "https://cdn.jsdelivr.net/npm/@material-symbols/svg-400@0.14.5",
"pattern": "{style}/{name}.svg"
},
"icons": [
{"name": "home", "tags": ["house", "residence", "building"]},
{"name": "search", "tags": ["find", "magnify", "lookup"]},
{"name": "settings", "tags": ["cog", "gear", "preferences", "config"]},
{"name": "menu", "tags": ["hamburger", "navigation", "bars"]},
{"name": "close", "tags": ["x", "dismiss", "cancel", "remove"]},
{"name": "check", "tags": ["tick", "done", "complete", "success"]},
{"name": "add", "tags": ["plus", "new", "create"]},
{"name": "remove", "tags": ["minus", "subtract", "delete"]},
{"name": "edit", "tags": ["pencil", "modify", "change"]},
{"name": "delete", "tags": ["trash", "bin", "remove"]},
{"name": "favorite", "tags": ["heart", "love", "like"]},
{"name": "star", "tags": ["rating", "bookmark", "featured"]},
{"name": "share", "tags": ["social", "send", "distribute"]},
{"name": "person", "tags": ["user", "profile", "account"]},
{"name": "people", "tags": ["users", "group", "team"]},
{"name": "mail", "tags": ["email", "envelope", "message"]},
{"name": "call", "tags": ["phone", "telephone", "contact"]},
{"name": "chat", "tags": ["message", "conversation", "bubble"]},
{"name": "notifications", "tags": ["bell", "alert", "alarm"]},
{"name": "calendar_today", "tags": ["date", "schedule", "event"]},
{"name": "schedule", "tags": ["time", "clock", "watch"]},
{"name": "location_on", "tags": ["pin", "map", "place", "marker"]},
{"name": "directions", "tags": ["navigate", "route", "arrow"]},
{"name": "photo", "tags": ["image", "picture", "gallery"]},
{"name": "camera", "tags": ["photo", "capture", "snapshot"]},
{"name": "videocam", "tags": ["video", "movie", "record"]},
{"name": "mic", "tags": ["microphone", "audio", "voice"]},
{"name": "volume_up", "tags": ["sound", "speaker", "audio"]},
{"name": "volume_off", "tags": ["mute", "silent", "quiet"]},
{"name": "play_arrow", "tags": ["start", "begin", "media"]},
{"name": "pause", "tags": ["stop", "hold", "media"]},
{"name": "stop", "tags": ["end", "halt", "media"]},
{"name": "skip_next", "tags": ["forward", "next", "media"]},
{"name": "skip_previous", "tags": ["back", "previous", "media"]},
{"name": "replay", "tags": ["repeat", "refresh", "again"]},
{"name": "shuffle", "tags": ["random", "mix", "media"]},
{"name": "folder", "tags": ["directory", "file", "storage"]},
{"name": "folder_open", "tags": ["directory", "file", "open"]},
{"name": "file_copy", "tags": ["document", "duplicate", "clone"]},
{"name": "attach_file", "tags": ["attachment", "paperclip", "document"]},
{"name": "cloud", "tags": ["weather", "storage", "upload"]},
{"name": "cloud_upload", "tags": ["upload", "save", "storage"]},
{"name": "cloud_download", "tags": ["download", "save", "storage"]},
{"name": "download", "tags": ["save", "arrow", "get"]},
{"name": "upload", "tags": ["send", "arrow", "put"]},
{"name": "sync", "tags": ["refresh", "update", "reload"]},
{"name": "refresh", "tags": ["reload", "update", "sync"]},
{"name": "lock", "tags": ["security", "password", "secure"]},
{"name": "lock_open", "tags": ["unlock", "open", "access"]},
{"name": "visibility", "tags": ["eye", "view", "show"]},
{"name": "visibility_off", "tags": ["eye", "hide", "hidden"]},
{"name": "key", "tags": ["password", "access", "security"]},
{"name": "shield", "tags": ["security", "protect", "safe"]},
{"name": "verified", "tags": ["check", "approved", "trusted"]},
{"name": "warning", "tags": ["alert", "caution", "danger"]},
{"name": "error", "tags": ["alert", "problem", "issue"]},
{"name": "info", "tags": ["information", "help", "about"]},
{"name": "help", "tags": ["question", "support", "info"]},
{"name": "lightbulb", "tags": ["idea", "tip", "suggestion"]},
{"name": "thumb_up", "tags": ["like", "approve", "good"]},
{"name": "thumb_down", "tags": ["dislike", "reject", "bad"]},
{"name": "mood", "tags": ["emoji", "face", "happy"]},
{"name": "sentiment_satisfied", "tags": ["happy", "smile", "positive"]},
{"name": "sentiment_dissatisfied", "tags": ["sad", "unhappy", "negative"]},
{"name": "shopping_cart", "tags": ["cart", "buy", "purchase", "ecommerce"]},
{"name": "shopping_bag", "tags": ["bag", "buy", "purchase", "retail"]},
{"name": "store", "tags": ["shop", "retail", "business"]},
{"name": "payments", "tags": ["money", "card", "credit"]},
{"name": "credit_card", "tags": ["payment", "money", "bank"]},
{"name": "account_balance", "tags": ["bank", "finance", "money"]},
{"name": "receipt", "tags": ["invoice", "bill", "payment"]},
{"name": "local_shipping", "tags": ["delivery", "truck", "shipping"]},
{"name": "inventory", "tags": ["stock", "warehouse", "storage"]},
{"name": "work", "tags": ["briefcase", "job", "business"]},
{"name": "business", "tags": ["building", "company", "office"]},
{"name": "apartment", "tags": ["building", "home", "residence"]},
{"name": "school", "tags": ["education", "learning", "building"]},
{"name": "restaurant", "tags": ["food", "dining", "eat"]},
{"name": "local_cafe", "tags": ["coffee", "drink", "cup"]},
{"name": "local_bar", "tags": ["drink", "cocktail", "alcohol"]},
{"name": "fitness_center", "tags": ["gym", "exercise", "workout"]},
{"name": "sports", "tags": ["athletics", "game", "activity"]},
{"name": "directions_car", "tags": ["car", "vehicle", "auto", "drive"]},
{"name": "directions_bus", "tags": ["bus", "transit", "transport"]},
{"name": "directions_bike", "tags": ["bicycle", "cycling", "bike"]},
{"name": "directions_walk", "tags": ["walk", "pedestrian", "foot"]},
{"name": "flight", "tags": ["plane", "airplane", "travel"]},
{"name": "train", "tags": ["rail", "transit", "transport"]},
{"name": "subway", "tags": ["metro", "underground", "transit"]},
{"name": "keyboard", "tags": ["type", "input", "keys"]},
{"name": "mouse", "tags": ["cursor", "click", "input"]},
{"name": "computer", "tags": ["desktop", "pc", "monitor"]},
{"name": "laptop", "tags": ["computer", "notebook", "device"]},
{"name": "smartphone", "tags": ["phone", "mobile", "device"]},
{"name": "tablet", "tags": ["ipad", "device", "screen"]},
{"name": "watch", "tags": ["time", "wearable", "smartwatch"]},
{"name": "headphones", "tags": ["audio", "music", "listen"]},
{"name": "speaker", "tags": ["audio", "sound", "music"]},
{"name": "tv", "tags": ["television", "screen", "display"]},
{"name": "print", "tags": ["printer", "document", "paper"]},
{"name": "scanner", "tags": ["scan", "copy", "document"]},
{"name": "usb", "tags": ["cable", "port", "connect"]},
{"name": "bluetooth", "tags": ["wireless", "connect", "pair"]},
{"name": "wifi", "tags": ["wireless", "internet", "network"]},
{"name": "signal_cellular_alt", "tags": ["mobile", "network", "bars"]},
{"name": "battery_full", "tags": ["power", "charge", "energy"]},
{"name": "battery_low", "tags": ["power", "charge", "low"]},
{"name": "power", "tags": ["on", "off", "switch"]},
{"name": "bolt", "tags": ["lightning", "flash", "power"]},
{"name": "brightness_high", "tags": ["sun", "light", "display"]},
{"name": "brightness_low", "tags": ["dim", "dark", "display"]},
{"name": "dark_mode", "tags": ["night", "moon", "theme"]},
{"name": "light_mode", "tags": ["day", "sun", "theme"]},
{"name": "thermostat", "tags": ["temperature", "climate", "heat"]},
{"name": "ac_unit", "tags": ["cooling", "air", "snowflake"]},
{"name": "wb_sunny", "tags": ["sun", "weather", "bright"]},
{"name": "cloud_queue", "tags": ["weather", "cloudy", "sky"]},
{"name": "water_drop", "tags": ["rain", "liquid", "droplet"]},
{"name": "air", "tags": ["wind", "breeze", "weather"]},
{"name": "eco", "tags": ["leaf", "nature", "green"]},
{"name": "park", "tags": ["tree", "nature", "outdoor"]},
{"name": "pets", "tags": ["paw", "animal", "dog"]},
{"name": "bug_report", "tags": ["insect", "issue", "debug"]},
{"name": "code", "tags": ["programming", "developer", "brackets"]},
{"name": "terminal", "tags": ["console", "command", "shell"]},
{"name": "data_object", "tags": ["json", "braces", "code"]},
{"name": "database", "tags": ["storage", "data", "server"]},
{"name": "dns", "tags": ["server", "network", "domain"]},
{"name": "storage", "tags": ["disk", "save", "memory"]},
{"name": "memory", "tags": ["ram", "chip", "hardware"]},
{"name": "developer_board", "tags": ["circuit", "hardware", "tech"]},
{"name": "build", "tags": ["wrench", "tool", "construct"]},
{"name": "construction", "tags": ["tools", "work", "build"]},
{"name": "handyman", "tags": ["tools", "repair", "fix"]},
{"name": "science", "tags": ["flask", "chemistry", "lab"]},
{"name": "biotech", "tags": ["dna", "genetics", "science"]},
{"name": "psychology", "tags": ["brain", "mind", "mental"]},
{"name": "medical_services", "tags": ["health", "hospital", "doctor"]},
{"name": "healing", "tags": ["bandage", "medical", "health"]},
{"name": "medication", "tags": ["pill", "drug", "pharmacy"]},
{"name": "vaccines", "tags": ["syringe", "injection", "medical"]},
{"name": "accessibility", "tags": ["person", "handicap", "access"]},
{"name": "elderly", "tags": ["senior", "old", "person"]},
{"name": "child_care", "tags": ["baby", "kid", "infant"]},
{"name": "family", "tags": ["people", "group", "parents"]},
{"name": "wc", "tags": ["toilet", "bathroom", "restroom"]},
{"name": "smoking_rooms", "tags": ["cigarette", "smoke", "tobacco"]},
{"name": "no_smoking", "tags": ["prohibited", "ban", "cigarette"]},
{"name": "language", "tags": ["globe", "world", "international"]},
{"name": "translate", "tags": ["language", "convert", "localize"]},
{"name": "font_download", "tags": ["typography", "text", "typeface"]},
{"name": "format_bold", "tags": ["text", "typography", "b"]},
{"name": "format_italic", "tags": ["text", "typography", "i"]},
{"name": "format_underlined", "tags": ["text", "typography", "u"]},
{"name": "format_strikethrough", "tags": ["text", "delete", "cross"]},
{"name": "format_size", "tags": ["text", "font", "typography"]},
{"name": "format_color_text", "tags": ["color", "font", "typography"]},
{"name": "format_color_fill", "tags": ["bucket", "paint", "color"]},
{"name": "format_align_left", "tags": ["text", "paragraph", "align"]},
{"name": "format_align_center", "tags": ["text", "paragraph", "align"]},
{"name": "format_align_right", "tags": ["text", "paragraph", "align"]},
{"name": "format_align_justify", "tags": ["text", "paragraph", "align"]},
{"name": "format_list_bulleted", "tags": ["list", "ul", "bullets"]},
{"name": "format_list_numbered", "tags": ["list", "ol", "numbers"]},
{"name": "format_quote", "tags": ["quotation", "blockquote", "cite"]},
{"name": "format_indent_increase", "tags": ["indent", "tab", "spacing"]},
{"name": "format_indent_decrease", "tags": ["outdent", "tab", "spacing"]},
{"name": "link", "tags": ["url", "chain", "hyperlink"]},
{"name": "link_off", "tags": ["unlink", "broken", "disconnect"]},
{"name": "image", "tags": ["photo", "picture", "media"]},
{"name": "insert_photo", "tags": ["image", "picture", "add"]},
{"name": "add_photo_alternate", "tags": ["image", "upload", "new"]},
{"name": "crop", "tags": ["image", "resize", "cut"]},
{"name": "rotate_left", "tags": ["image", "turn", "ccw"]},
{"name": "rotate_right", "tags": ["image", "turn", "cw"]},
{"name": "flip", "tags": ["mirror", "image", "reflect"]},
{"name": "filter", "tags": ["image", "effect", "adjust"]},
{"name": "tune", "tags": ["adjust", "settings", "sliders"]},
{"name": "palette", "tags": ["color", "paint", "art"]},
{"name": "brush", "tags": ["paint", "draw", "art"]},
{"name": "create", "tags": ["pencil", "edit", "write"]},
{"name": "draw", "tags": ["pencil", "sketch", "art"]},
{"name": "gesture", "tags": ["hand", "draw", "touch"]},
{"name": "shape_line", "tags": ["line", "draw", "shape"]},
{"name": "rectangle", "tags": ["square", "shape", "box"]},
{"name": "circle", "tags": ["shape", "round", "ellipse"]},
{"name": "hexagon", "tags": ["shape", "polygon", "six"]},
{"name": "pentagon", "tags": ["shape", "polygon", "five"]},
{"name": "change_history", "tags": ["triangle", "shape", "arrow"]},
{"name": "category", "tags": ["shapes", "organize", "sort"]},
{"name": "grid_view", "tags": ["layout", "tiles", "gallery"]},
{"name": "view_list", "tags": ["layout", "rows", "lines"]},
{"name": "view_module", "tags": ["layout", "grid", "blocks"]},
{"name": "view_agenda", "tags": ["layout", "cards", "list"]},
{"name": "dashboard", "tags": ["layout", "widgets", "overview"]},
{"name": "widgets", "tags": ["components", "blocks", "modules"]},
{"name": "layers", "tags": ["stack", "overlap", "design"]},
{"name": "aspect_ratio", "tags": ["resize", "scale", "dimensions"]},
{"name": "zoom_in", "tags": ["magnify", "enlarge", "plus"]},
{"name": "zoom_out", "tags": ["shrink", "reduce", "minus"]},
{"name": "fullscreen", "tags": ["expand", "maximize", "enlarge"]},
{"name": "fullscreen_exit", "tags": ["shrink", "minimize", "reduce"]},
{"name": "center_focus_strong", "tags": ["target", "aim", "focus"]},
{"name": "filter_center_focus", "tags": ["camera", "focus", "center"]},
{"name": "panorama", "tags": ["wide", "image", "photo"]},
{"name": "photo_library", "tags": ["gallery", "images", "album"]},
{"name": "collections", "tags": ["gallery", "photos", "album"]},
{"name": "slideshow", "tags": ["presentation", "play", "images"]},
{"name": "movie", "tags": ["film", "video", "cinema"]},
{"name": "theaters", "tags": ["cinema", "film", "drama"]},
{"name": "music_note", "tags": ["audio", "song", "melody"]},
{"name": "album", "tags": ["music", "record", "disc"]},
{"name": "radio", "tags": ["music", "broadcast", "audio"]},
{"name": "equalizer", "tags": ["audio", "levels", "music"]},
{"name": "graphic_eq", "tags": ["audio", "visualizer", "music"]},
{"name": "mic_none", "tags": ["microphone", "record", "audio"]},
{"name": "record_voice_over", "tags": ["speak", "voice", "narrate"]},
{"name": "hearing", "tags": ["ear", "listen", "audio"]},
{"name": "closed_caption", "tags": ["subtitles", "cc", "text"]},
{"name": "subtitles", "tags": ["cc", "captions", "text"]},
{"name": "hd", "tags": ["quality", "high", "resolution"]},
{"name": "4k", "tags": ["quality", "ultra", "resolution"]},
{"name": "speed", "tags": ["fast", "gauge", "performance"]},
{"name": "timer", "tags": ["clock", "countdown", "stopwatch"]},
{"name": "hourglass_empty", "tags": ["time", "wait", "loading"]},
{"name": "hourglass_full", "tags": ["time", "complete", "done"]},
{"name": "access_time", "tags": ["clock", "time", "schedule"]},
{"name": "alarm", "tags": ["clock", "alert", "reminder"]},
{"name": "alarm_on", "tags": ["clock", "active", "set"]},
{"name": "alarm_off", "tags": ["clock", "disabled", "silent"]},
{"name": "snooze", "tags": ["sleep", "delay", "alarm"]},
{"name": "event", "tags": ["calendar", "date", "schedule"]},
{"name": "event_available", "tags": ["calendar", "free", "open"]},
{"name": "event_busy", "tags": ["calendar", "occupied", "booked"]},
{"name": "today", "tags": ["calendar", "now", "current"]},
{"name": "date_range", "tags": ["calendar", "period", "span"]},
{"name": "update", "tags": ["refresh", "sync", "reload"]},
{"name": "history", "tags": ["time", "past", "clock"]},
{"name": "restore", "tags": ["undo", "back", "recover"]},
{"name": "undo", "tags": ["back", "reverse", "arrow"]},
{"name": "redo", "tags": ["forward", "repeat", "arrow"]},
{"name": "content_copy", "tags": ["copy", "duplicate", "clipboard"]},
{"name": "content_cut", "tags": ["scissors", "cut", "clipboard"]},
{"name": "content_paste", "tags": ["clipboard", "paste", "insert"]},
{"name": "select_all", "tags": ["checkbox", "all", "select"]},
{"name": "save", "tags": ["disk", "floppy", "store"]},
{"name": "save_as", "tags": ["disk", "export", "store"]},
{"name": "draft", "tags": ["document", "edit", "paper"]},
{"name": "note", "tags": ["paper", "memo", "text"]},
{"name": "note_add", "tags": ["document", "new", "create"]},
{"name": "description", "tags": ["document", "file", "text"]},
{"name": "article", "tags": ["document", "text", "news"]},
{"name": "newspaper", "tags": ["news", "article", "media"]},
{"name": "feed", "tags": ["rss", "news", "stream"]},
{"name": "rss_feed", "tags": ["news", "subscribe", "blog"]},
{"name": "bookmark", "tags": ["save", "favorite", "tag"]},
{"name": "bookmark_border", "tags": ["save", "favorite", "outline"]},
{"name": "bookmarks", "tags": ["saved", "favorites", "collection"]},
{"name": "label", "tags": ["tag", "category", "badge"]},
{"name": "sell", "tags": ["tag", "price", "sale"]},
{"name": "loyalty", "tags": ["heart", "tag", "reward"]},
{"name": "new_releases", "tags": ["starburst", "badge", "new"]},
{"name": "stars", "tags": ["rating", "favorite", "best"]},
{"name": "grade", "tags": ["star", "rating", "review"]},
{"name": "military_tech", "tags": ["medal", "badge", "award"]},
{"name": "emoji_events", "tags": ["trophy", "award", "winner"]},
{"name": "workspace_premium", "tags": ["badge", "crown", "premium"]},
{"name": "verified_user", "tags": ["shield", "check", "secure"]},
{"name": "admin_panel_settings", "tags": ["shield", "gear", "admin"]},
{"name": "manage_accounts", "tags": ["user", "settings", "admin"]},
{"name": "supervised_user_circle", "tags": ["admin", "user", "manage"]},
{"name": "group", "tags": ["people", "team", "users"]},
{"name": "group_add", "tags": ["people", "team", "invite"]},
{"name": "group_remove", "tags": ["people", "team", "delete"]},
{"name": "person_add", "tags": ["user", "invite", "new"]},
{"name": "person_remove", "tags": ["user", "delete", "remove"]},
{"name": "face", "tags": ["emoji", "person", "avatar"]},
{"name": "sentiment_very_satisfied", "tags": ["happy", "joy", "smile"]},
{"name": "sentiment_neutral", "tags": ["meh", "okay", "face"]},
{"name": "sentiment_very_dissatisfied", "tags": ["angry", "upset", "mad"]},
{"name": "mood_bad", "tags": ["sad", "unhappy", "frown"]},
{"name": "sick", "tags": ["ill", "unwell", "face"]},
{"name": "masks", "tags": ["theater", "drama", "comedy"]},
{"name": "cake", "tags": ["birthday", "celebration", "party"]},
{"name": "celebration", "tags": ["party", "confetti", "event"]},
{"name": "card_giftcard", "tags": ["gift", "present", "voucher"]},
{"name": "redeem", "tags": ["gift", "box", "present"]},
{"name": "volunteer_activism", "tags": ["heart", "hand", "donate"]},
{"name": "handshake", "tags": ["deal", "agreement", "partner"]},
{"name": "diversity_3", "tags": ["people", "team", "group"]},
{"name": "public", "tags": ["globe", "world", "earth"]},
{"name": "travel_explore", "tags": ["globe", "search", "world"]},
{"name": "flag", "tags": ["country", "nation", "report"]},
{"name": "tour", "tags": ["flag", "marker", "location"]},
{"name": "place", "tags": ["pin", "location", "marker"]},
{"name": "my_location", "tags": ["gps", "target", "current"]},
{"name": "near_me", "tags": ["location", "arrow", "nearby"]},
{"name": "explore", "tags": ["compass", "navigate", "discover"]},
{"name": "navigation", "tags": ["arrow", "direction", "gps"]},
{"name": "map", "tags": ["location", "geography", "atlas"]},
{"name": "satellite", "tags": ["space", "orbit", "map"]},
{"name": "terrain", "tags": ["mountain", "landscape", "map"]},
{"name": "layers_clear", "tags": ["stack", "remove", "design"]},
{"name": "streetview", "tags": ["map", "360", "view"]},
{"name": "traffic", "tags": ["signal", "light", "road"]},
{"name": "alt_route", "tags": ["path", "alternative", "direction"]},
{"name": "merge", "tags": ["combine", "join", "arrows"]},
{"name": "call_split", "tags": ["fork", "divide", "arrows"]},
{"name": "compare_arrows", "tags": ["swap", "exchange", "switch"]},
{"name": "swap_horiz", "tags": ["exchange", "switch", "horizontal"]},
{"name": "swap_vert", "tags": ["exchange", "switch", "vertical"]},
{"name": "import_export", "tags": ["arrows", "transfer", "data"]},
{"name": "arrow_upward", "tags": ["up", "direction", "top"]},
{"name": "arrow_downward", "tags": ["down", "direction", "bottom"]},
{"name": "arrow_forward", "tags": ["right", "direction", "next"]},
{"name": "arrow_back", "tags": ["left", "direction", "previous"]},
{"name": "north", "tags": ["up", "direction", "compass"]},
{"name": "south", "tags": ["down", "direction", "compass"]},
{"name": "east", "tags": ["right", "direction", "compass"]},
{"name": "west", "tags": ["left", "direction", "compass"]},
{"name": "expand_more", "tags": ["down", "chevron", "dropdown"]},
{"name": "expand_less", "tags": ["up", "chevron", "collapse"]},
{"name": "chevron_right", "tags": ["arrow", "right", "next"]},
{"name": "chevron_left", "tags": ["arrow", "left", "previous"]},
{"name": "unfold_more", "tags": ["expand", "vertical", "arrows"]},
{"name": "unfold_less", "tags": ["collapse", "vertical", "arrows"]},
{"name": "first_page", "tags": ["start", "beginning", "arrow"]},
{"name": "last_page", "tags": ["end", "final", "arrow"]},
{"name": "subdirectory_arrow_right", "tags": ["nested", "child", "sub"]},
{"name": "subdirectory_arrow_left", "tags": ["nested", "parent", "back"]},
{"name": "trending_up", "tags": ["arrow", "growth", "increase"]},
{"name": "trending_down", "tags": ["arrow", "decline", "decrease"]},
{"name": "trending_flat", "tags": ["arrow", "stable", "neutral"]},
{"name": "show_chart", "tags": ["graph", "line", "analytics"]},
{"name": "bar_chart", "tags": ["graph", "statistics", "analytics"]},
{"name": "pie_chart", "tags": ["graph", "statistics", "donut"]},
{"name": "bubble_chart", "tags": ["graph", "data", "visualization"]},
{"name": "scatter_plot", "tags": ["graph", "data", "points"]},
{"name": "analytics", "tags": ["chart", "data", "statistics"]},
{"name": "insights", "tags": ["chart", "data", "analysis"]},
{"name": "leaderboard", "tags": ["chart", "ranking", "bars"]},
{"name": "table_chart", "tags": ["spreadsheet", "data", "grid"]},
{"name": "table_view", "tags": ["grid", "data", "spreadsheet"]},
{"name": "table_rows", "tags": ["grid", "horizontal", "data"]},
{"name": "view_column", "tags": ["grid", "vertical", "layout"]},
{"name": "view_week", "tags": ["calendar", "columns", "schedule"]},
{"name": "view_day", "tags": ["calendar", "single", "schedule"]},
{"name": "timeline", "tags": ["history", "time", "events"]},
{"name": "account_tree", "tags": ["hierarchy", "org", "structure"]},
{"name": "hub", "tags": ["network", "nodes", "connected"]},
{"name": "workspaces", "tags": ["circles", "venn", "overlap"]},
{"name": "token", "tags": ["chip", "badge", "tag"]},
{"name": "api", "tags": ["code", "integration", "connect"]},
{"name": "extension", "tags": ["puzzle", "plugin", "addon"]},
{"name": "integration_instructions", "tags": ["code", "embed", "api"]},
{"name": "webhook", "tags": ["api", "callback", "hook"]},
{"name": "javascript", "tags": ["code", "programming", "js"]},
{"name": "css", "tags": ["code", "style", "web"]},
{"name": "html", "tags": ["code", "web", "markup"]},
{"name": "php", "tags": ["code", "programming", "web"]},
{"name": "deployed_code", "tags": ["box", "package", "release"]},
{"name": "package_2", "tags": ["box", "delivery", "shipping"]},
{"name": "inventory_2", "tags": ["box", "storage", "stock"]},
{"name": "move_to_inbox", "tags": ["archive", "box", "download"]},
{"name": "outbox", "tags": ["send", "upload", "mail"]},
{"name": "inbox", "tags": ["mail", "receive", "box"]},
{"name": "all_inbox", "tags": ["mail", "messages", "combined"]},
{"name": "mark_email_read", "tags": ["mail", "open", "check"]},
{"name": "mark_email_unread", "tags": ["mail", "new", "dot"]},
{"name": "drafts", "tags": ["mail", "edit", "compose"]},
{"name": "send", "tags": ["mail", "submit", "arrow"]},
{"name": "forward_to_inbox", "tags": ["mail", "forward", "arrow"]},
{"name": "reply", "tags": ["mail", "respond", "arrow"]},
{"name": "reply_all", "tags": ["mail", "respond", "group"]},
{"name": "mark_as_unread", "tags": ["mail", "new", "notification"]},
{"name": "markunread_mailbox", "tags": ["mail", "mailbox", "new"]},
{"name": "contact_mail", "tags": ["email", "person", "address"]},
{"name": "contact_phone", "tags": ["call", "person", "number"]},
{"name": "contacts", "tags": ["people", "address", "book"]},
{"name": "perm_contact_calendar", "tags": ["person", "schedule", "date"]},
{"name": "badge", "tags": ["id", "name", "tag"]},
{"name": "assignment", "tags": ["clipboard", "task", "document"]},
{"name": "assignment_ind", "tags": ["person", "task", "assign"]},
{"name": "assignment_turned_in", "tags": ["task", "done", "check"]},
{"name": "assignment_late", "tags": ["task", "overdue", "warning"]},
{"name": "assignment_return", "tags": ["task", "back", "arrow"]},
{"name": "task", "tags": ["checkbox", "todo", "done"]},
{"name": "task_alt", "tags": ["check", "circle", "done"]},
{"name": "checklist", "tags": ["tasks", "todo", "list"]},
{"name": "fact_check", "tags": ["clipboard", "verify", "check"]},
{"name": "rule", "tags": ["check", "cross", "decision"]},
{"name": "done", "tags": ["check", "complete", "success"]},
{"name": "done_all", "tags": ["check", "double", "complete"]},
{"name": "done_outline", "tags": ["check", "circle", "complete"]},
{"name": "check_circle", "tags": ["done", "success", "complete"]},
{"name": "check_box", "tags": ["done", "tick", "checked"]},
{"name": "check_box_outline_blank", "tags": ["empty", "unchecked", "box"]},
{"name": "indeterminate_check_box", "tags": ["partial", "minus", "box"]},
{"name": "radio_button_checked", "tags": ["selected", "option", "circle"]},
{"name": "radio_button_unchecked", "tags": ["empty", "option", "circle"]},
{"name": "toggle_on", "tags": ["switch", "enabled", "active"]},
{"name": "toggle_off", "tags": ["switch", "disabled", "inactive"]},
{"name": "add_circle", "tags": ["plus", "new", "create"]},
{"name": "remove_circle", "tags": ["minus", "delete", "subtract"]},
{"name": "cancel", "tags": ["x", "close", "remove"]},
{"name": "highlight_off", "tags": ["x", "remove", "circle"]},
{"name": "do_not_disturb", "tags": ["minus", "block", "circle"]},
{"name": "block", "tags": ["prohibited", "ban", "stop"]},
{"name": "not_interested", "tags": ["circle", "slash", "disabled"]},
{"name": "report", "tags": ["octagon", "warning", "flag"]},
{"name": "report_problem", "tags": ["triangle", "warning", "alert"]},
{"name": "priority_high", "tags": ["exclamation", "important", "alert"]},
{"name": "new_label", "tags": ["tag", "badge", "add"]},
{"name": "fiber_new", "tags": ["badge", "new", "fresh"]},
{"name": "auto_awesome", "tags": ["sparkle", "magic", "ai"]},
{"name": "auto_fix_high", "tags": ["wand", "magic", "auto"]},
{"name": "flare", "tags": ["light", "sparkle", "shine"]},
{"name": "flash_on", "tags": ["lightning", "power", "camera"]},
{"name": "flash_off", "tags": ["lightning", "disabled", "camera"]},
{"name": "flash_auto", "tags": ["lightning", "auto", "camera"]},
{"name": "highlight", "tags": ["marker", "pen", "text"]},
{"name": "colorize", "tags": ["eyedropper", "pick", "color"]},
{"name": "opacity", "tags": ["transparent", "drop", "alpha"]},
{"name": "gradient", "tags": ["color", "blend", "fade"]},
{"name": "texture", "tags": ["pattern", "surface", "material"]},
{"name": "vignette", "tags": ["photo", "effect", "fade"]},
{"name": "blur_on", "tags": ["effect", "focus", "soft"]},
{"name": "blur_off", "tags": ["sharp", "clear", "focus"]},
{"name": "hdr_on", "tags": ["photo", "range", "dynamic"]},
{"name": "filter_vintage", "tags": ["flower", "retro", "effect"]},
{"name": "filter_drama", "tags": ["cloud", "weather", "sky"]},
{"name": "filter_frames", "tags": ["border", "photo", "frame"]},
{"name": "monochrome_photos", "tags": ["bw", "grayscale", "filter"]},
{"name": "photo_filter", "tags": ["star", "effect", "image"]},
{"name": "looks", "tags": ["sparkle", "enhance", "effect"]},
{"name": "straighten", "tags": ["rotate", "align", "level"]},
{"name": "transform", "tags": ["resize", "scale", "edit"]},
{"name": "style", "tags": ["format", "design", "appearance"]},
{"name": "format_paint", "tags": ["brush", "style", "copy"]}
]
}

View file

@ -0,0 +1,418 @@
{
"slug": "phosphor",
"name": "Phosphor",
"version": "2.1.1",
"icons": [
{"name": "activity", "tags": ["pulse", "health", "heart"], "category": "health", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "address-book", "tags": ["contacts", "directory", "people"], "category": "office", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "airplane", "tags": ["flight", "travel", "plane"], "category": "travel", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "airplane-in-flight", "tags": ["flight", "travel", "plane"], "category": "travel", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "airplane-landing", "tags": ["flight", "arrival", "plane"], "category": "travel", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "airplane-takeoff", "tags": ["flight", "departure", "plane"], "category": "travel", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "alarm", "tags": ["clock", "time", "alert"], "category": "time", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "alien", "tags": ["space", "ufo", "extraterrestrial"], "category": "objects", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "align-bottom", "tags": ["layout", "vertical", "align"], "category": "design", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "align-center-horizontal", "tags": ["layout", "horizontal", "align"], "category": "design", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "align-center-vertical", "tags": ["layout", "vertical", "align"], "category": "design", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "align-left", "tags": ["text", "format", "paragraph"], "category": "text", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "align-right", "tags": ["text", "format", "paragraph"], "category": "text", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "align-top", "tags": ["layout", "vertical", "align"], "category": "design", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "anchor", "tags": ["marine", "ship", "link"], "category": "objects", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "aperture", "tags": ["camera", "lens", "photo"], "category": "media", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "archive", "tags": ["box", "storage", "files"], "category": "files", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "archive-box", "tags": ["storage", "container", "files"], "category": "files", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "armchair", "tags": ["furniture", "seat", "chair"], "category": "furniture", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "arrow-arc-left", "tags": ["direction", "curved", "back"], "category": "arrows", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "arrow-arc-right", "tags": ["direction", "curved", "forward"], "category": "arrows", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "arrow-bend-double-up-left", "tags": ["direction", "turn", "back"], "category": "arrows", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "arrow-bend-double-up-right", "tags": ["direction", "turn", "forward"], "category": "arrows", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "arrow-bend-down-left", "tags": ["direction", "turn", "corner"], "category": "arrows", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "arrow-bend-down-right", "tags": ["direction", "turn", "corner"], "category": "arrows", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "arrow-bend-left-down", "tags": ["direction", "turn", "corner"], "category": "arrows", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "arrow-bend-left-up", "tags": ["direction", "turn", "corner"], "category": "arrows", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "arrow-bend-right-down", "tags": ["direction", "turn", "corner"], "category": "arrows", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "arrow-bend-right-up", "tags": ["direction", "turn", "corner"], "category": "arrows", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "arrow-bend-up-left", "tags": ["direction", "turn", "corner"], "category": "arrows", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "arrow-bend-up-right", "tags": ["direction", "turn", "corner"], "category": "arrows", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "arrow-circle-down", "tags": ["direction", "download", "circle"], "category": "arrows", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "arrow-circle-down-left", "tags": ["direction", "diagonal", "circle"], "category": "arrows", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "arrow-circle-down-right", "tags": ["direction", "diagonal", "circle"], "category": "arrows", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "arrow-circle-left", "tags": ["direction", "back", "circle"], "category": "arrows", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "arrow-circle-right", "tags": ["direction", "forward", "circle"], "category": "arrows", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "arrow-circle-up", "tags": ["direction", "upload", "circle"], "category": "arrows", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "arrow-circle-up-left", "tags": ["direction", "diagonal", "circle"], "category": "arrows", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "arrow-circle-up-right", "tags": ["direction", "diagonal", "circle"], "category": "arrows", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "arrow-clockwise", "tags": ["refresh", "reload", "sync"], "category": "arrows", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "arrow-counter-clockwise", "tags": ["undo", "back", "history"], "category": "arrows", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "arrow-down", "tags": ["direction", "down", "download"], "category": "arrows", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "arrow-down-left", "tags": ["direction", "diagonal"], "category": "arrows", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "arrow-down-right", "tags": ["direction", "diagonal"], "category": "arrows", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "arrow-fat-down", "tags": ["direction", "down", "bold"], "category": "arrows", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "arrow-fat-left", "tags": ["direction", "left", "bold"], "category": "arrows", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "arrow-fat-right", "tags": ["direction", "right", "bold"], "category": "arrows", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "arrow-fat-up", "tags": ["direction", "up", "bold"], "category": "arrows", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "arrow-left", "tags": ["direction", "back", "previous"], "category": "arrows", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "arrow-line-down", "tags": ["direction", "download", "end"], "category": "arrows", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "arrow-line-left", "tags": ["direction", "start", "begin"], "category": "arrows", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "arrow-line-right", "tags": ["direction", "end", "finish"], "category": "arrows", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "arrow-line-up", "tags": ["direction", "upload", "top"], "category": "arrows", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "arrow-right", "tags": ["direction", "forward", "next"], "category": "arrows", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "arrow-square-down", "tags": ["direction", "download", "square"], "category": "arrows", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "arrow-square-left", "tags": ["direction", "back", "square"], "category": "arrows", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "arrow-square-right", "tags": ["direction", "forward", "square"], "category": "arrows", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "arrow-square-up", "tags": ["direction", "upload", "square"], "category": "arrows", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "arrow-u-down-left", "tags": ["direction", "turn", "uturn"], "category": "arrows", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "arrow-u-down-right", "tags": ["direction", "turn", "uturn"], "category": "arrows", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "arrow-u-left-down", "tags": ["direction", "turn", "uturn"], "category": "arrows", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "arrow-u-left-up", "tags": ["direction", "turn", "uturn"], "category": "arrows", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "arrow-u-right-down", "tags": ["direction", "turn", "uturn"], "category": "arrows", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "arrow-u-right-up", "tags": ["direction", "turn", "uturn"], "category": "arrows", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "arrow-u-up-left", "tags": ["direction", "turn", "uturn"], "category": "arrows", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "arrow-u-up-right", "tags": ["direction", "turn", "uturn"], "category": "arrows", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "arrow-up", "tags": ["direction", "up", "upload"], "category": "arrows", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "arrow-up-left", "tags": ["direction", "diagonal"], "category": "arrows", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "arrow-up-right", "tags": ["direction", "diagonal", "external"], "category": "arrows", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "arrows-clockwise", "tags": ["refresh", "sync", "rotate"], "category": "arrows", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "arrows-counter-clockwise", "tags": ["refresh", "sync", "rotate"], "category": "arrows", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "arrows-down-up", "tags": ["sort", "swap", "vertical"], "category": "arrows", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "arrows-horizontal", "tags": ["resize", "horizontal", "expand"], "category": "arrows", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "arrows-in", "tags": ["collapse", "minimize", "shrink"], "category": "arrows", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "arrows-in-cardinal", "tags": ["collapse", "center", "focus"], "category": "arrows", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "arrows-in-line-horizontal", "tags": ["collapse", "horizontal"], "category": "arrows", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "arrows-in-line-vertical", "tags": ["collapse", "vertical"], "category": "arrows", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "arrows-in-simple", "tags": ["collapse", "minimize"], "category": "arrows", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "arrows-left-right", "tags": ["swap", "horizontal", "exchange"], "category": "arrows", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "arrows-merge", "tags": ["combine", "join", "merge"], "category": "arrows", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "arrows-out", "tags": ["expand", "maximize", "fullscreen"], "category": "arrows", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "arrows-out-cardinal", "tags": ["expand", "move", "directions"], "category": "arrows", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "arrows-out-line-horizontal", "tags": ["expand", "horizontal"], "category": "arrows", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "arrows-out-line-vertical", "tags": ["expand", "vertical"], "category": "arrows", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "arrows-out-simple", "tags": ["expand", "maximize"], "category": "arrows", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "arrows-split", "tags": ["fork", "divide", "branch"], "category": "arrows", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "arrows-vertical", "tags": ["resize", "vertical", "expand"], "category": "arrows", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "at", "tags": ["email", "mention", "at sign"], "category": "communication", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "atom", "tags": ["science", "physics", "nuclear"], "category": "science", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "baby", "tags": ["child", "infant", "kid"], "category": "people", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "backpack", "tags": ["bag", "school", "travel"], "category": "objects", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "bag", "tags": ["shopping", "tote", "carry"], "category": "commerce", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "bag-simple", "tags": ["shopping", "tote", "simple"], "category": "commerce", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "balloon", "tags": ["party", "celebration", "birthday"], "category": "objects", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "bank", "tags": ["finance", "money", "building"], "category": "buildings", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "barbell", "tags": ["gym", "fitness", "weight"], "category": "fitness", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "barcode", "tags": ["scan", "product", "code"], "category": "commerce", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "basket", "tags": ["shopping", "cart", "store"], "category": "commerce", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "basketball", "tags": ["sport", "ball", "game"], "category": "sports", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "bathtub", "tags": ["bathroom", "bath", "clean"], "category": "home", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "battery-charging", "tags": ["power", "energy", "charge"], "category": "devices", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "battery-charging-vertical", "tags": ["power", "energy", "charge"], "category": "devices", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "battery-empty", "tags": ["power", "energy", "empty"], "category": "devices", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "battery-full", "tags": ["power", "energy", "full"], "category": "devices", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "battery-high", "tags": ["power", "energy", "high"], "category": "devices", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "battery-low", "tags": ["power", "energy", "low"], "category": "devices", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "battery-medium", "tags": ["power", "energy", "half"], "category": "devices", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "battery-plus", "tags": ["power", "add", "charge"], "category": "devices", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "battery-vertical-empty", "tags": ["power", "energy", "empty"], "category": "devices", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "battery-vertical-full", "tags": ["power", "energy", "full"], "category": "devices", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "battery-vertical-high", "tags": ["power", "energy", "high"], "category": "devices", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "battery-vertical-low", "tags": ["power", "energy", "low"], "category": "devices", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "battery-vertical-medium", "tags": ["power", "energy", "half"], "category": "devices", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "battery-warning", "tags": ["power", "alert", "low"], "category": "devices", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "battery-warning-vertical", "tags": ["power", "alert", "low"], "category": "devices", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "bell", "tags": ["notification", "alert", "alarm"], "category": "notifications", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "bell-ringing", "tags": ["notification", "alert", "alarm"], "category": "notifications", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "bell-simple", "tags": ["notification", "alert", "simple"], "category": "notifications", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "bell-simple-ringing", "tags": ["notification", "alert", "alarm"], "category": "notifications", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "bell-simple-slash", "tags": ["notification", "mute", "off"], "category": "notifications", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "bell-simple-z", "tags": ["notification", "snooze", "sleep"], "category": "notifications", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "bell-slash", "tags": ["notification", "mute", "off"], "category": "notifications", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "bell-z", "tags": ["notification", "snooze", "sleep"], "category": "notifications", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "bluetooth", "tags": ["wireless", "connection", "device"], "category": "connectivity", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "bluetooth-connected", "tags": ["wireless", "paired", "device"], "category": "connectivity", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "bluetooth-slash", "tags": ["wireless", "disabled", "off"], "category": "connectivity", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "bluetooth-x", "tags": ["wireless", "disconnect", "error"], "category": "connectivity", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "book", "tags": ["read", "library", "education"], "category": "education", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "book-bookmark", "tags": ["saved", "favorite", "reading"], "category": "education", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "book-open", "tags": ["read", "library", "education"], "category": "education", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "book-open-text", "tags": ["read", "content", "article"], "category": "education", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "bookmark", "tags": ["save", "favorite", "tag"], "category": "actions", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "bookmark-simple", "tags": ["save", "favorite", "simple"], "category": "actions", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "bookmarks", "tags": ["saved", "favorites", "collection"], "category": "actions", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "bookmarks-simple", "tags": ["saved", "favorites", "simple"], "category": "actions", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "bounding-box", "tags": ["selection", "area", "crop"], "category": "design", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "briefcase", "tags": ["work", "job", "business"], "category": "business", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "briefcase-metal", "tags": ["work", "job", "metal"], "category": "business", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "browser", "tags": ["web", "internet", "window"], "category": "development", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "browsers", "tags": ["web", "windows", "tabs"], "category": "development", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "bug", "tags": ["insect", "error", "debug"], "category": "development", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "bug-beetle", "tags": ["insect", "beetle", "bug"], "category": "nature", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "bug-droid", "tags": ["android", "robot", "bug"], "category": "development", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "buildings", "tags": ["city", "office", "skyline"], "category": "buildings", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "calculator", "tags": ["math", "numbers", "compute"], "category": "tools", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "calendar", "tags": ["date", "schedule", "event"], "category": "time", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "calendar-blank", "tags": ["date", "schedule", "empty"], "category": "time", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "calendar-check", "tags": ["date", "done", "confirmed"], "category": "time", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "calendar-plus", "tags": ["date", "add", "new"], "category": "time", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "calendar-x", "tags": ["date", "cancel", "remove"], "category": "time", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "camera", "tags": ["photo", "picture", "image"], "category": "media", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "camera-slash", "tags": ["photo", "disabled", "off"], "category": "media", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "car", "tags": ["vehicle", "auto", "drive"], "category": "transportation", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "car-simple", "tags": ["vehicle", "auto", "simple"], "category": "transportation", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "caret-circle-down", "tags": ["arrow", "down", "circle"], "category": "arrows", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "caret-circle-left", "tags": ["arrow", "left", "circle"], "category": "arrows", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "caret-circle-right", "tags": ["arrow", "right", "circle"], "category": "arrows", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "caret-circle-up", "tags": ["arrow", "up", "circle"], "category": "arrows", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "caret-down", "tags": ["arrow", "down", "expand"], "category": "arrows", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "caret-left", "tags": ["arrow", "left", "back"], "category": "arrows", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "caret-right", "tags": ["arrow", "right", "forward"], "category": "arrows", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "caret-up", "tags": ["arrow", "up", "collapse"], "category": "arrows", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "chart-bar", "tags": ["analytics", "graph", "data"], "category": "charts", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "chart-bar-horizontal", "tags": ["analytics", "graph", "horizontal"], "category": "charts", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "chart-line", "tags": ["analytics", "graph", "trend"], "category": "charts", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "chart-line-down", "tags": ["analytics", "decrease", "trend"], "category": "charts", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "chart-line-up", "tags": ["analytics", "increase", "trend"], "category": "charts", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "chart-pie", "tags": ["analytics", "graph", "pie"], "category": "charts", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "chart-pie-slice", "tags": ["analytics", "graph", "segment"], "category": "charts", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "chat", "tags": ["message", "conversation", "talk"], "category": "communication", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "chat-centered", "tags": ["message", "conversation", "center"], "category": "communication", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "chat-centered-dots", "tags": ["message", "typing", "dots"], "category": "communication", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "chat-centered-text", "tags": ["message", "text", "conversation"], "category": "communication", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "chat-circle", "tags": ["message", "conversation", "circle"], "category": "communication", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "chat-circle-dots", "tags": ["message", "typing", "circle"], "category": "communication", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "chat-circle-text", "tags": ["message", "text", "circle"], "category": "communication", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "chat-dots", "tags": ["message", "typing", "dots"], "category": "communication", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "chat-text", "tags": ["message", "text", "conversation"], "category": "communication", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "chats", "tags": ["messages", "conversations", "multiple"], "category": "communication", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "chats-circle", "tags": ["messages", "conversations", "circles"], "category": "communication", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "check", "tags": ["done", "complete", "success"], "category": "ui", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "check-circle", "tags": ["done", "complete", "circle"], "category": "ui", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "check-square", "tags": ["done", "checkbox", "complete"], "category": "ui", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "circle", "tags": ["shape", "dot", "round"], "category": "shapes", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "circle-dashed", "tags": ["shape", "dashed", "border"], "category": "shapes", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "circle-half", "tags": ["shape", "half", "contrast"], "category": "shapes", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "circle-half-tilt", "tags": ["shape", "half", "tilt"], "category": "shapes", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "circle-notch", "tags": ["loading", "spinner", "progress"], "category": "ui", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "clipboard", "tags": ["copy", "paste", "board"], "category": "actions", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "clipboard-text", "tags": ["copy", "paste", "text"], "category": "actions", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "clock", "tags": ["time", "watch", "schedule"], "category": "time", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "clock-afternoon", "tags": ["time", "pm", "afternoon"], "category": "time", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "clock-clockwise", "tags": ["time", "rotate", "forward"], "category": "time", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "clock-counter-clockwise", "tags": ["time", "rotate", "back"], "category": "time", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "cloud", "tags": ["weather", "storage", "sky"], "category": "weather", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "cloud-arrow-down", "tags": ["download", "cloud", "save"], "category": "actions", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "cloud-arrow-up", "tags": ["upload", "cloud", "sync"], "category": "actions", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "cloud-check", "tags": ["cloud", "done", "synced"], "category": "weather", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "cloud-fog", "tags": ["weather", "fog", "mist"], "category": "weather", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "cloud-lightning", "tags": ["weather", "storm", "thunder"], "category": "weather", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "cloud-moon", "tags": ["weather", "night", "cloudy"], "category": "weather", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "cloud-rain", "tags": ["weather", "rain", "precipitation"], "category": "weather", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "cloud-slash", "tags": ["cloud", "offline", "disconnect"], "category": "weather", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "cloud-snow", "tags": ["weather", "snow", "winter"], "category": "weather", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "cloud-sun", "tags": ["weather", "day", "partly cloudy"], "category": "weather", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "cloud-warning", "tags": ["cloud", "alert", "error"], "category": "weather", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "cloud-x", "tags": ["cloud", "error", "disconnect"], "category": "weather", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "code", "tags": ["programming", "html", "brackets"], "category": "development", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "code-block", "tags": ["programming", "snippet", "code"], "category": "development", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "code-simple", "tags": ["programming", "brackets", "simple"], "category": "development", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "coffee", "tags": ["drink", "cup", "cafe"], "category": "food", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "command", "tags": ["keyboard", "mac", "shortcut"], "category": "devices", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "compass", "tags": ["navigation", "direction", "explore"], "category": "navigation", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "copy", "tags": ["duplicate", "clipboard", "clone"], "category": "actions", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "copy-simple", "tags": ["duplicate", "clone", "simple"], "category": "actions", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "credit-card", "tags": ["payment", "card", "money"], "category": "commerce", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "crop", "tags": ["image", "edit", "resize"], "category": "editing", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "cube", "tags": ["3d", "box", "shape"], "category": "shapes", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "currency-btc", "tags": ["bitcoin", "crypto", "currency"], "category": "commerce", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "currency-dollar", "tags": ["money", "usd", "currency"], "category": "commerce", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "currency-eur", "tags": ["money", "euro", "currency"], "category": "commerce", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "currency-gbp", "tags": ["money", "pound", "currency"], "category": "commerce", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "currency-jpy", "tags": ["money", "yen", "currency"], "category": "commerce", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "cursor", "tags": ["pointer", "mouse", "click"], "category": "ui", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "cursor-click", "tags": ["pointer", "click", "select"], "category": "ui", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "database", "tags": ["storage", "data", "server"], "category": "development", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "desktop", "tags": ["computer", "monitor", "screen"], "category": "devices", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "desktop-tower", "tags": ["computer", "pc", "tower"], "category": "devices", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "device-mobile", "tags": ["phone", "mobile", "smartphone"], "category": "devices", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "device-tablet", "tags": ["tablet", "ipad", "device"], "category": "devices", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "download", "tags": ["save", "export", "arrow"], "category": "actions", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "download-simple", "tags": ["save", "export", "simple"], "category": "actions", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "envelope", "tags": ["email", "mail", "message"], "category": "communication", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "envelope-open", "tags": ["email", "mail", "read"], "category": "communication", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "envelope-simple", "tags": ["email", "mail", "simple"], "category": "communication", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "eye", "tags": ["view", "visible", "show"], "category": "ui", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "eye-closed", "tags": ["hide", "invisible", "hidden"], "category": "ui", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "eye-slash", "tags": ["hide", "invisible", "hidden"], "category": "ui", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "file", "tags": ["document", "page", "paper"], "category": "files", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "file-arrow-down", "tags": ["download", "document", "save"], "category": "files", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "file-arrow-up", "tags": ["upload", "document", "export"], "category": "files", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "file-code", "tags": ["code", "programming", "document"], "category": "files", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "file-plus", "tags": ["add", "new", "document"], "category": "files", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "file-text", "tags": ["document", "text", "content"], "category": "files", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "filter", "tags": ["funnel", "sort", "search"], "category": "ui", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "flag", "tags": ["report", "mark", "country"], "category": "objects", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "folder", "tags": ["directory", "files", "organize"], "category": "files", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "folder-open", "tags": ["directory", "browse", "explore"], "category": "files", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "folder-plus", "tags": ["directory", "add", "new"], "category": "files", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "funnel", "tags": ["filter", "sort", "funnel"], "category": "ui", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "gear", "tags": ["settings", "cog", "config"], "category": "ui", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "gear-six", "tags": ["settings", "cog", "config"], "category": "ui", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "gift", "tags": ["present", "reward", "surprise"], "category": "objects", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "globe", "tags": ["world", "earth", "web"], "category": "objects", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "globe-hemisphere-east", "tags": ["world", "earth", "asia"], "category": "objects", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "globe-hemisphere-west", "tags": ["world", "earth", "americas"], "category": "objects", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "grid-four", "tags": ["layout", "grid", "squares"], "category": "layout", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "hand", "tags": ["palm", "stop", "gesture"], "category": "gestures", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "hand-pointing", "tags": ["finger", "point", "gesture"], "category": "gestures", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "hash", "tags": ["tag", "hashtag", "number"], "category": "communication", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "heart", "tags": ["love", "favorite", "like"], "category": "objects", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "heart-break", "tags": ["love", "broken", "sad"], "category": "objects", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "house", "tags": ["home", "building", "main"], "category": "buildings", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "house-simple", "tags": ["home", "building", "simple"], "category": "buildings", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "image", "tags": ["picture", "photo", "gallery"], "category": "media", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "image-square", "tags": ["picture", "photo", "square"], "category": "media", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "info", "tags": ["information", "help", "about"], "category": "ui", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "key", "tags": ["password", "security", "lock"], "category": "security", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "keyboard", "tags": ["typing", "input", "keys"], "category": "devices", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "laptop", "tags": ["computer", "notebook", "device"], "category": "devices", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "link", "tags": ["url", "chain", "connect"], "category": "ui", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "link-break", "tags": ["unlink", "disconnect", "broken"], "category": "ui", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "list", "tags": ["menu", "items", "bullet"], "category": "text", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "list-bullets", "tags": ["menu", "items", "bullet"], "category": "text", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "list-checks", "tags": ["tasks", "checklist", "todo"], "category": "text", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "list-numbers", "tags": ["menu", "items", "ordered"], "category": "text", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "lock", "tags": ["security", "private", "password"], "category": "security", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "lock-key", "tags": ["security", "password", "key"], "category": "security", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "lock-key-open", "tags": ["security", "unlocked", "open"], "category": "security", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "lock-open", "tags": ["security", "unlocked", "open"], "category": "security", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "magnifying-glass", "tags": ["search", "find", "zoom"], "category": "ui", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "magnifying-glass-minus", "tags": ["zoom out", "search", "smaller"], "category": "ui", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "magnifying-glass-plus", "tags": ["zoom in", "search", "bigger"], "category": "ui", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "map-pin", "tags": ["location", "marker", "place"], "category": "maps", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "map-trifold", "tags": ["navigation", "directions", "map"], "category": "maps", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "megaphone", "tags": ["announce", "broadcast", "marketing"], "category": "communication", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "microphone", "tags": ["audio", "voice", "record"], "category": "media", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "microphone-slash", "tags": ["audio", "mute", "off"], "category": "media", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "minus", "tags": ["subtract", "remove", "delete"], "category": "math", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "minus-circle", "tags": ["subtract", "remove", "circle"], "category": "math", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "moon", "tags": ["dark", "night", "theme"], "category": "weather", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "moon-stars", "tags": ["night", "dark", "stars"], "category": "weather", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "music-note", "tags": ["audio", "sound", "melody"], "category": "media", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "music-notes", "tags": ["audio", "sound", "melody"], "category": "media", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "navigation-arrow", "tags": ["direction", "compass", "arrow"], "category": "navigation", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "paper-plane", "tags": ["send", "message", "mail"], "category": "communication", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "paper-plane-right", "tags": ["send", "submit", "forward"], "category": "communication", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "paper-plane-tilt", "tags": ["send", "message", "tilt"], "category": "communication", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "paperclip", "tags": ["attachment", "file", "clip"], "category": "ui", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "paperclip-horizontal", "tags": ["attachment", "file", "horizontal"], "category": "ui", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "pause", "tags": ["media", "stop", "wait"], "category": "media", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "pause-circle", "tags": ["media", "stop", "circle"], "category": "media", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "pencil", "tags": ["edit", "write", "draw"], "category": "actions", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "pencil-line", "tags": ["edit", "write", "underline"], "category": "actions", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "pencil-simple", "tags": ["edit", "write", "simple"], "category": "actions", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "phone", "tags": ["call", "contact", "mobile"], "category": "communication", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "phone-call", "tags": ["call", "ringing", "incoming"], "category": "communication", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "play", "tags": ["media", "start", "video"], "category": "media", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "play-circle", "tags": ["media", "start", "circle"], "category": "media", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "plus", "tags": ["add", "create", "new"], "category": "math", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "plus-circle", "tags": ["add", "create", "circle"], "category": "math", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "power", "tags": ["on", "off", "shutdown"], "category": "devices", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "printer", "tags": ["print", "document", "paper"], "category": "devices", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "question", "tags": ["help", "support", "faq"], "category": "ui", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "rocket", "tags": ["launch", "startup", "space"], "category": "objects", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "rocket-launch", "tags": ["launch", "startup", "deploy"], "category": "objects", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "rss", "tags": ["feed", "subscribe", "blog"], "category": "communication", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "rss-simple", "tags": ["feed", "subscribe", "simple"], "category": "communication", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "scissors", "tags": ["cut", "trim", "edit"], "category": "actions", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "share", "tags": ["social", "send", "forward"], "category": "actions", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "share-network", "tags": ["social", "connect", "network"], "category": "actions", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "shield", "tags": ["security", "protection", "safe"], "category": "security", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "shield-check", "tags": ["security", "verified", "safe"], "category": "security", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "shopping-bag", "tags": ["shop", "purchase", "buy"], "category": "commerce", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "shopping-cart", "tags": ["shop", "cart", "ecommerce"], "category": "commerce", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "sign-in", "tags": ["login", "enter", "access"], "category": "actions", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "sign-out", "tags": ["logout", "exit", "leave"], "category": "actions", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "sliders", "tags": ["settings", "controls", "adjust"], "category": "ui", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "sliders-horizontal", "tags": ["settings", "controls", "horizontal"], "category": "ui", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "smiley", "tags": ["emoji", "happy", "face"], "category": "emoji", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "smiley-sad", "tags": ["emoji", "sad", "face"], "category": "emoji", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "sparkle", "tags": ["magic", "new", "shine"], "category": "objects", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "speaker-high", "tags": ["audio", "volume", "loud"], "category": "media", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "speaker-low", "tags": ["audio", "volume", "quiet"], "category": "media", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "speaker-none", "tags": ["audio", "mute", "silent"], "category": "media", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "speaker-simple-high", "tags": ["audio", "volume", "loud"], "category": "media", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "speaker-simple-low", "tags": ["audio", "volume", "quiet"], "category": "media", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "speaker-simple-none", "tags": ["audio", "mute", "silent"], "category": "media", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "speaker-simple-slash", "tags": ["audio", "mute", "off"], "category": "media", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "speaker-simple-x", "tags": ["audio", "mute", "off"], "category": "media", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "speaker-slash", "tags": ["audio", "mute", "off"], "category": "media", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "speaker-x", "tags": ["audio", "mute", "off"], "category": "media", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "spinner", "tags": ["loading", "wait", "progress"], "category": "ui", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "spinner-gap", "tags": ["loading", "wait", "progress"], "category": "ui", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "star", "tags": ["favorite", "rating", "bookmark"], "category": "objects", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "star-four", "tags": ["sparkle", "magic", "star"], "category": "objects", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "star-half", "tags": ["rating", "half", "partial"], "category": "objects", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "stop", "tags": ["media", "stop", "end"], "category": "media", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "stop-circle", "tags": ["media", "stop", "circle"], "category": "media", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "sun", "tags": ["light", "day", "brightness"], "category": "weather", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "sun-dim", "tags": ["light", "dim", "brightness"], "category": "weather", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "tag", "tags": ["label", "category", "price"], "category": "commerce", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "target", "tags": ["goal", "aim", "focus"], "category": "ui", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "terminal", "tags": ["console", "command", "code"], "category": "development", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "terminal-window", "tags": ["console", "command", "window"], "category": "development", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "text-aa", "tags": ["font", "typography", "text"], "category": "text", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "text-align-center", "tags": ["text", "format", "center"], "category": "text", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "text-align-justify", "tags": ["text", "format", "justify"], "category": "text", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "text-align-left", "tags": ["text", "format", "left"], "category": "text", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "text-align-right", "tags": ["text", "format", "right"], "category": "text", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "text-b", "tags": ["bold", "format", "strong"], "category": "text", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "text-italic", "tags": ["italic", "format", "emphasis"], "category": "text", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "text-strikethrough", "tags": ["strikethrough", "format", "delete"], "category": "text", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "text-underline", "tags": ["underline", "format", "text"], "category": "text", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "thumbs-down", "tags": ["dislike", "bad", "negative"], "category": "gestures", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "thumbs-up", "tags": ["like", "good", "positive"], "category": "gestures", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "ticket", "tags": ["event", "pass", "coupon"], "category": "objects", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "timer", "tags": ["time", "countdown", "clock"], "category": "time", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "toggle-left", "tags": ["switch", "off", "disable"], "category": "ui", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "toggle-right", "tags": ["switch", "on", "enable"], "category": "ui", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "trash", "tags": ["delete", "remove", "bin"], "category": "actions", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "trash-simple", "tags": ["delete", "remove", "simple"], "category": "actions", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "trend-down", "tags": ["chart", "decrease", "analytics"], "category": "charts", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "trend-up", "tags": ["chart", "increase", "analytics"], "category": "charts", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "trophy", "tags": ["award", "winner", "achievement"], "category": "awards", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "truck", "tags": ["delivery", "shipping", "transport"], "category": "transportation", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "tv", "tags": ["television", "screen", "display"], "category": "devices", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "upload", "tags": ["export", "send", "share"], "category": "actions", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "upload-simple", "tags": ["export", "send", "simple"], "category": "actions", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "user", "tags": ["person", "account", "profile"], "category": "users", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "user-circle", "tags": ["avatar", "profile", "account"], "category": "users", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "user-circle-gear", "tags": ["settings", "account", "config"], "category": "users", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "user-circle-minus", "tags": ["remove", "unfriend", "user"], "category": "users", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "user-circle-plus", "tags": ["add", "invite", "user"], "category": "users", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "user-focus", "tags": ["target", "focus", "user"], "category": "users", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "user-gear", "tags": ["settings", "account", "config"], "category": "users", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "user-list", "tags": ["contacts", "directory", "users"], "category": "users", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "user-minus", "tags": ["remove", "unfriend", "delete"], "category": "users", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "user-plus", "tags": ["add", "invite", "new"], "category": "users", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "user-rectangle", "tags": ["id", "card", "profile"], "category": "users", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "user-square", "tags": ["avatar", "profile", "square"], "category": "users", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "users", "tags": ["people", "team", "group"], "category": "users", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "users-four", "tags": ["people", "team", "group"], "category": "users", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "users-three", "tags": ["people", "team", "group"], "category": "users", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "video-camera", "tags": ["video", "film", "record"], "category": "media", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "video-camera-slash", "tags": ["video", "off", "mute"], "category": "media", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "wallet", "tags": ["money", "payment", "finance"], "category": "commerce", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "warning", "tags": ["alert", "error", "caution"], "category": "alerts", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "warning-circle", "tags": ["alert", "error", "circle"], "category": "alerts", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "warning-diamond", "tags": ["alert", "error", "diamond"], "category": "alerts", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "warning-octagon", "tags": ["alert", "stop", "error"], "category": "alerts", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "wifi-high", "tags": ["wireless", "internet", "strong"], "category": "connectivity", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "wifi-low", "tags": ["wireless", "internet", "weak"], "category": "connectivity", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "wifi-medium", "tags": ["wireless", "internet", "medium"], "category": "connectivity", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "wifi-none", "tags": ["wireless", "offline", "disconnect"], "category": "connectivity", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "wifi-slash", "tags": ["wireless", "offline", "disconnect"], "category": "connectivity", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "wifi-x", "tags": ["wireless", "error", "disconnect"], "category": "connectivity", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "wrench", "tags": ["tool", "settings", "repair"], "category": "tools", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "x", "tags": ["close", "cancel", "remove"], "category": "ui", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "x-circle", "tags": ["close", "cancel", "error"], "category": "ui", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]},
{"name": "x-square", "tags": ["close", "cancel", "remove"], "category": "ui", "styles": ["regular", "bold", "light", "thin", "fill", "duotone"]}
]
}

View file

@ -0,0 +1,124 @@
=== Maple Icons ===
Contributors: jetrails
Tags: icons, svg, gutenberg, block, heroicons, lucide, feather, phosphor, material
Requires at least: 6.5
Tested up to: 6.7
Stable tag: 1.0.0
Requires PHP: 7.4
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html
Insert beautiful open-source icons into your content with a Gutenberg block. Download icon sets from CDN and serve locally.
== Description ==
Maple Icons provides a simple way to insert high-quality, open-source icons into your WordPress content using the Gutenberg block editor.
= Features =
* **Multiple Icon Sets** - Choose from popular open-source icon libraries:
* Heroicons (~290 icons) - MIT License
* Lucide (~1400 icons) - ISC License
* Feather (~287 icons) - MIT License
* Phosphor (~1200 icons per style) - MIT License
* Material Symbols (~400 icons) - Apache 2.0 License
* **Local Storage** - Icons are downloaded from CDN and stored locally in your WordPress installation. No external requests are made when displaying icons on your site.
* **Gutenberg Block** - Easy-to-use block with:
* Search and filter icons
* Multiple style variants per set
* Size control (12px - 256px)
* Custom icon color
* Background color
* Padding and margin controls
* Stroke width adjustment
* Drop shadow effect
* **Performance Optimized**
* Icons are inline SVG - no additional HTTP requests
* No frontend JavaScript or CSS
* Works in RSS feeds and email
* **Accessible**
* Decorative icons automatically hidden from screen readers
* Optional accessible labels for meaningful icons
* Follows WCAG guidelines
= How It Works =
1. Go to Settings → Maple Icons
2. Download one or more icon sets
3. Set one icon set as active
4. In the Gutenberg editor, add a "Maple Icon" block
5. Search and select an icon
6. Customize size, color, and other settings
= Icon Storage =
Downloaded icons are stored in `wp-content/maple-icons/`. Each icon set is stored in its own subdirectory with the SVG files organized by style.
= Compatibility =
* WordPress 6.5+
* PHP 7.4+
* WooCommerce (HPOS compatible)
* Works with all properly coded themes
* Compatible with popular page builders that support Gutenberg blocks
== Installation ==
1. Upload the `maple-icons` folder to the `/wp-content/plugins/` directory
2. Activate the plugin through the 'Plugins' menu in WordPress
3. Go to Settings → Maple Icons to download icon sets
4. Start using the "Maple Icon" block in your content
== Frequently Asked Questions ==
= Are the icons free to use? =
Yes! All icon sets included are open-source with permissive licenses (MIT, ISC, or Apache 2.0) that allow commercial use.
= Can I use multiple icon sets? =
You can download multiple icon sets, but only one can be active at a time. The active set is what appears in the Gutenberg block icon picker.
= Where are the icons stored? =
Icons are downloaded from CDN (jsdelivr.net) and stored locally in `wp-content/maple-icons/`. Once downloaded, no external requests are made to display icons.
= How do I change the icon color? =
Icons automatically inherit the text color from your theme. You can also set a custom color in the block settings panel.
= Will icons work in RSS feeds? =
Yes! Icons are saved as inline SVG in your post content, so they work in RSS feeds, email newsletters, and anywhere else your content is displayed.
= What happens if I uninstall the plugin? =
Existing icons in your content will remain as inline SVG. However, you won't be able to add new icons or use the block settings. The downloaded icon files in `wp-content/maple-icons/` will be removed on uninstall.
= Is this plugin GDPR compliant? =
Yes. Maple Icons does not collect any user data, set cookies, or make external requests after icons are downloaded. All icon files are stored locally on your server.
== Screenshots ==
1. Settings page - Download and manage icon sets
2. Icon picker modal in Gutenberg editor
3. Block settings panel with customization options
4. Icon block rendered on the frontend
== Changelog ==
= 1.0.0 =
* Initial release
* Support for Heroicons, Lucide, Feather, Phosphor, and Material Symbols
* Gutenberg block with full customization options
* Local icon storage
== Upgrade Notice ==
= 1.0.0 =
Initial release of Maple Icons.

View file

@ -0,0 +1,5 @@
<?php
// Silence is golden.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}

View file

@ -0,0 +1,62 @@
<?php
/**
* Maple Icons Uninstall
*
* Runs when the plugin is uninstalled (deleted).
* Cleans up all plugin data including downloaded icons and settings.
*
* @package MapleIcons
*/
// Exit if not called by WordPress.
if ( ! defined( 'WP_UNINSTALL_PLUGIN' ) ) {
exit;
}
/**
* Remove plugin options.
*/
delete_option( 'maple_icons_settings' );
/**
* Remove transients.
*/
global $wpdb;
$wpdb->query(
"DELETE FROM {$wpdb->options} WHERE option_name LIKE '_transient_mi_%' OR option_name LIKE '_transient_timeout_mi_%'"
);
/**
* Remove downloaded icons directory.
*/
$icons_dir = WP_CONTENT_DIR . '/maple-icons/';
if ( is_dir( $icons_dir ) ) {
/**
* Recursively delete a directory and its contents.
*
* @param string $dir Directory path.
* @return bool True on success, false on failure.
*/
function mi_delete_directory( $dir ) {
if ( ! is_dir( $dir ) ) {
return false;
}
$files = array_diff( scandir( $dir ), array( '.', '..' ) );
foreach ( $files as $file ) {
$path = $dir . '/' . $file;
if ( is_dir( $path ) ) {
mi_delete_directory( $path );
} else {
unlink( $path );
}
}
return rmdir( $dir );
}
mi_delete_directory( $icons_dir );
}