Remix-Design / RemixIcon

Open source neutral style icon system
https://remixicon.com
Apache License 2.0
6.67k stars 489 forks source link

Feature request: glyphMap generation for React Native/Expo #287

Open itsezc opened 3 years ago

itsezc commented 3 years ago

Currently one would have to use separate tooling to generate glyph maps for Remix Icons on React Native (Expo).

The current remixicon.glyph.json is not directly compatible with Expos glyph map structure.

Current:

{
  "24-hours-fill": {
  "path": [
      "M0 0H24V24H0z",
      "M12 13c1.657 0 3 1.343 3 3 0 .85-.353 1.616-.92 2.162L12.17 20H15v2H9v-1.724l3.693-3.555c.19-.183.307-.438.307-.721 0-.552-.448-1-1-1s-1 .448-1 1H9c0-1.657 1.343-3 3-3zm6 0v4h2v-4h2v9h-2v-3h-4v-6h2zM4 12c0 2.527 1.171 4.78 3 6.246v2.416C4.011 18.933 2 15.702 2 12h2zm8-10c5.185 0 9.449 3.947 9.95 9h-2.012C19.446 7.054 16.08 4 12 4 9.536 4 7.332 5.114 5.865 6.865L8 9H2V3l2.447 2.446C6.28 3.336 8.984 2 12 2z"
  ],
  "unicode": "",
  "glyph": "M600 550C682.85 550 750 482.85 750 400C750 357.4999999999999 732.35 319.2000000000001 704 291.9000000000001L608.5 200H750V100H450V186.2000000000001L634.65 363.9500000000001C644.15 373.1 650 385.8499999999999 650 400C650 427.6 627.6 450 600 450S550 427.6 550 400H450C450 482.85 517.15 550 600 550zM900 550V350H1000V550H1100V100H1000V250H800V550H900zM200 600C200 473.65 258.55 361 350 287.7V166.8999999999999C200.55 253.35 100 414.9 100 600H200zM600 1100C859.2499999999999 1100 1072.4499999999998 902.65 1097.5 650H996.9C972.3 847.3 803.9999999999999 1000 600 1000C476.8 1000 366.6 944.3 293.25 856.75L400 750H100V1050L222.35 927.7C314 1033.2 449.2 1100 600 1100z",
  "horizAdvX": "1200"
}

The required glyph map structure for expo:

{
  "24-hours-fill": 59905
}

where the key is the icon name and the value is either a UTF-8 character or it's character code.

It would be useful if from next release a new file named remixicon.expo.json could be appended in this format. This would make easy for one to use Remix Icons with Expo.

For reference: https://docs.expo.io/guides/icons/

itsezc commented 3 years ago

For reference:

https://github.com/ForetagInc/Encora/tree/master/components/Icon https://github.com/ForetagInc/Encora/blob/master/util/generate-remix-glyphs.ts

A quick / untested approach to solving this problem, but I would rather prefer that RemixIcon ships with the character map.

Code-Victor commented 1 month ago

Any update on this? It would be really helpful

balthild commented 2 weeks ago

You could generate the glyph map at build time. See https://docs.expo.dev/versions/latest/config/metro/#virtual-modules

npm install --save-dev entities

tsconfig.json

{
  "compilerOptions": {
    "paths": {
      "virtual:*": ["node_modules/.cache/virtual/*"]
    }
  }
}

metro.config.js

const path = require('path');
const fs = require('fs');
const { decodeXML } = require('entities');
const { getDefaultConfig } = require('expo/metro-config');

// Generate glyph map for remixicon
const nodeModules = path.resolve(__dirname, 'node_modules');

const glyphData = JSON.parse(
  fs.readFileSync(
    path.join(nodeModules, 'remixicon/fonts/remixicon.glyph.json'),
  ),
);

const glyphMap = {};
for (const [name, value] of Object.entries(glyphData)) {
  glyphMap[name] = decodeXML(value.unicode);
}

const moduleName = 'remixicon-glyph-map';
const modulePath = path.join(nodeModules, `.cache/virtual/${moduleName}.ts`);

fs.mkdirSync(path.dirname(modulePath), { recursive: true });
fs.writeFileSync(modulePath, 'export default ' + JSON.stringify(glyphMap));

/** @type {import('expo/metro-config').MetroConfig} */
const config = getDefaultConfig(__dirname);

module.exports = config;

src/components/Remix.tsx

import createIconSet from '@expo/vector-icons/createIconSet';
import { Asset } from 'expo-asset';
import fontAssetId from 'remixicon/fonts/remixicon.ttf';

import glyphMap from 'virtual:remixicon-glyph-map';

export type IconName = keyof typeof glyphMap;

const asset = Asset.fromModule(fontAssetId);

export const Remix = createIconSet(glyphMap, 'remixicon', asset.uri);