Renovamen / oh-vue-icons

A Vue component for importing inline SVG icons from different popular icon packs easily.
https://oh-vue-icons.js.org
Other
241 stars 21 forks source link

Alias for icons #28

Open ange007 opened 1 year ago

ange007 commented 1 year ago

Hi. Is it possible to somehow implement an icon alias to be able to use a set of icons with the same name from different sources?

Example:

import { FaQrcode, FaWifi, FaBluetoothB, FcNfcSign, RiGpsLine } from "oh-vue-icons/icons";

addIcons({
  'qr': FaQrcode, 
  'wifi': FaWifi, 
  'nfc': FcNfcSign, 
  'gps': RiGpsLine
});
<v-icon name="qr" />
<v-icon name="nfc" />
<v-icon name="gps" />
Ryomasao commented 1 year ago

I accomplished that by wrapping v-icon.

import { addIcons } from "oh-vue-icons";
import { FaFlag, MdDaterangeOutlined } from "oh-vue-icons/icons";

export const ICONS_ALIASES = {
  flag: ["fa-flag", FaFlag],
  date: ["md-daterange-outlined", MdDaterangeOutlined],
} as const;

export const ICON_NAMES = Object.keys(ICONS_ALIASES);

export const registerIcons = () => {
  const vueIcons = Object.entries(ICONS_ALIASES).map(([_, v]) => v[1]);
  addIcons(...vueIcons);
};

Icon.vue

<script setup lang="ts">
import { computed } from "vue";
import { OhVueIcon } from "oh-vue-icons";
import { ICONS_ALIASES } from "./registerIcons";

const props = 
  defineProps<{
    name: keyof typeof ICONS_ALIASES;
  }>();

// resolve actual name
const vueIconName = computed(() => ICONS_ALIASES[props.name][0]);
</script>

<template>
  <OhVueIcon :name="vueIconName" />
</template>
ange007 commented 1 year ago

Hi, @Ryomasao. I try, but for some reason it doesn't work ... Although I started doing it at the moment of moving from Webpack to Vite, maybe that is also a matter.

But for any variants always one error (even if the icon is added directly): image image

index.js

import Vue from 'vue';
import { OhVueIcon } from "oh-vue-icons";

import IconTemplate from './Template.vue';
import { registerIcons } from "@/components/oh-vue-icons/icons.ts";

registerIcons();
Vue.component('v-icon', OhVueIcon);
Vue.component('oh-icon', IconTemplate);

icons.ts

import { addIcons } from "oh-vue-icons";
import { IconType } from "oh-vue-icons/types/icons";

import { MdQrcode, MdWifi, MdBluetooth, MdNfc, MdGpsfixed } from "oh-vue-icons/icons/md";

export const ICON_SETS = {
    tags: {
        qr: MdQrcode,
        wifi: MdWifi,
        bluetooth: MdBluetooth,
        nfc: MdNfc,
        gps: MdGpsfixed,
    }
};

export const getIcon = (collection, name): IconType => {
    const collectionList = ICON_SETS[collection] ?? {};
    return collectionList[name] ?? {};
}

export const getIconName = (collection, name): string => {
    const icon = getIcon(collection, name);
    return icon?.name ?? '';
}

export const registerIcons = () => {
    let icons = [];

    for (const iconCollectionKey in ICON_SETS) {
        const iconCollection = ICON_SETS[iconCollectionKey];

        for (const iconKey in iconCollection) {
            const iconComponent = iconCollection[iconKey];

            icons.push(iconComponent);
        }
    }

    addIcons(...icons);
};

Template.vue

<template>
    <span>
        <!-- 
        <svg
            aria-hidden="true"
            :width="icon.width"
            :height="icon.height"
            :viewBox="icon.box"
            effect="true"
            fill="currentColor"
            :x="icon.minX"
            :y="icon.minY"
            class="value effect"
            v-html="icon.raw"
        /> 
        -->
        {{ iconName }}
        <v-icon name="md-qrcode" />
        <v-icon :name="iconName" />
        <!--
        <OhVueIcon name="fa-flag" />
        <OhVueIcon
            :name="iconName"
            :title="title"
            :label="label"
            :hover="hover"
            :inverse="inverse"
        />
        -->
    </span>
</template>

<script lang="ts">
    import Vue from 'vue';
    import { OhVueIcon } from "oh-vue-icons";
    import { IconType } from "oh-vue-icons/types/icons";

    import { getIcon, getIconName } from "./icons";

    export default Vue.extend({
        name: 'oh-icon',

        components: {
            OhVueIcon
        },

        props: {
            collection: String,
            name: String,

            title: String,
            label: String,
            hover: Boolean,
            inverse: Boolean,
        },

        computed: {
            icon(): IconType {
                if (!this.collection || !this.name) {
                    return null;
                }

                let icon = this.getIcon(this.collection, this.name);
                console.log(icon);

                return icon;
            },

            iconName(): string {
                if (!this.collection || !this.name) {
                    return '';
                }

                let icon = this.getIconName(this.collection, this.name);
                console.log(icon);

                return icon;
            }
        },

        setup() {
            return {
                getIcon,
                getIconName,
            }
        }
    })
</script>