Skip to content

Commit

Permalink
feat(Icon): add support for Morpheme Icons
Browse files Browse the repository at this point in the history
  • Loading branch information
gravitano committed Jun 21, 2023
1 parent f21a806 commit 0b0870b
Show file tree
Hide file tree
Showing 5 changed files with 165 additions and 10 deletions.
1 change: 1 addition & 0 deletions packages/icon/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
"@heroicons/vue": "^1.0.6",
"@iconify/vue": "^3.2.1",
"@morpheme/theme": "^1.0.0-beta.9",
"@morphemeicons/vue": "^0.2.0",
"vue": "^3.3.4"
},
"devDependencies": {
Expand Down
53 changes: 53 additions & 0 deletions packages/icon/src/Icon.stories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,3 +78,56 @@ export const DarkMode: Story = (args) => ({
</div>
`,
});

export const MorphemeIcons: Story = (args) => ({
components: {Icon},
setup() {
return {args};
},
template: `
<p class="font-medium mb-2">Default Collection</p>
<Icon v-bind='args' name="ri:home-line" />
<Icon v-bind='args' name="ic:round-local-activity" />
<Icon v-bind='args' name="ph:activity-bold" />
<p class="font-medium mb-2 mt-5">PascalCase</p>
<Icon v-bind='args' name="remix:HomeLine" />
<Icon v-bind='args' name="untitled:ActivityHeart" />
<Icon v-bind='args' name="iconsax:outline/Add" />
<Icon v-bind='args' name="iconsax:bulk/Add" />
<Icon v-bind='args' name="iconsax:broken/Add" />
<Icon v-bind='args' name="iconsax:linear/Add" />
<Icon v-bind='args' name="iconsax:solid/Add" />
<Icon v-bind='args' name="iconsax:twotone/Add" />
<p class="font-medium mb-2 mt-5">PascalCase with suffix <code>Icon</code></p>
<Icon v-bind='args' name="remix:HomeLine" />
<Icon v-bind='args' name="untitled:ActivityHeart" />
<Icon v-bind='args' name="iconsax:outline/Add" />
<Icon v-bind='args' name="iconsax:bulk/Add" />
<Icon v-bind='args' name="iconsax:broken/Add" />
<Icon v-bind='args' name="iconsax:linear/Add" />
<Icon v-bind='args' name="iconsax:solid/Add" />
<Icon v-bind='args' name="iconsax:twotone/Add" />
<p class="font-medium mb-2 mt-5">HypenCase</p>
<Icon v-bind='args' name="remix:home-line" />
<Icon v-bind='args' name="untitled:activity-heart" />
<Icon v-bind='args' name="iconsax:outline/add" />
<Icon v-bind='args' name="iconsax:bulk/add" />
<Icon v-bind='args' name="iconsax:broken/add" />
<Icon v-bind='args' name="iconsax:linear/add" />
<Icon v-bind='args' name="iconsax:solid/add" />
<Icon v-bind='args' name="iconsax:twotone/add" />
<p class="font-medium mb-2 mt-5">HypenCase with suffix <code>icon</code></p>
<Icon v-bind='args' name="remix:home-line-icon" />
<Icon v-bind='args' name="untitled:activity-heart-icon" />
<Icon v-bind='args' name="iconsax:outline/add-icon" />
<Icon v-bind='args' name="iconsax:bulk/add-icon" />
<Icon v-bind='args' name="iconsax:broken/add-icon" />
<Icon v-bind='args' name="iconsax:linear/add-icon" />
<Icon v-bind='args' name="iconsax:solid/add-icon" />
<Icon v-bind='args' name="iconsax:twotone/add-icon" />
`,
});
97 changes: 90 additions & 7 deletions packages/icon/src/Icon.vue
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<script setup lang="ts">
import {Icon as Iconify} from '@iconify/vue/dist/offline';
import {loadIcon} from '@iconify/vue';
import {computed, ref, watch} from 'vue';
import {type DefaultSizes, defaultSizes} from '@morpheme/theme/defaultTheme';
import { Icon as Iconify } from '@iconify/vue/dist/offline';
import { loadIcon } from '@iconify/vue';
import { computed, ref, watch } from 'vue';
import { type DefaultSizes, defaultSizes } from '@morpheme/theme/defaultTheme';
export type Props = {
name: string;
Expand All @@ -16,9 +16,85 @@ const props = withDefaults(defineProps<Props>(), {
const isFetching = ref(false);
const icon = ref();
const isMorphemeIcons = computed(() => {
return props.name.startsWith('untitled:') || props.name.startsWith('remix:') || props.name.startsWith('iconsax:') || props.name.startsWith('vuesax:')
})
function normalizeName(name: string) {
name = name.replace('untitled:', '')
.replace('remix:', '')
.replace('iconsax:', '')
.replace('vuesax:', '')
.replace('-icon', '')
return toPascalCase(name) + 'Icon'
}
function toPascalCase(string: string) {
return `${string}`
.toLowerCase()
.replace(new RegExp(/[-_]+/, 'g'), ' ')
.replace(new RegExp(/[^\w\s]/, 'g'), '')
.replace(
new RegExp(/\s+(.)(\w*)/, 'g'),
($1, $2, $3) => `${$2.toUpperCase() + $3}`
)
.replace(new RegExp(/\w/), s => s.toUpperCase());
}
async function loadIconComponent() {
isFetching.value = true;
icon.value = await loadIcon(props.name).catch(() => {});
if (props.name.startsWith('untitled:')) {
const icons = await import('@morphemeicons/vue/untitled/esm/index')
icon.value = (icons as any)[normalizeName(props.name)];
}
else if (props.name.startsWith('remix:')) {
const icons = await import('@morphemeicons/vue/remix/esm/index')
icon.value = (icons as any)[normalizeName(props.name)];
}
else if (props.name.startsWith('iconsax') || props.name.startsWith('vuesax')) {
const [, name] = props.name.split(':')
const [variant, iconName] = name.split('/')
switch (variant) {
case 'outline': {
const icons = await import('@morphemeicons/vue/iconsax/outline/esm/index')
icon.value = (icons as any)[normalizeName(iconName)];
}
break;
case 'bulk': {
const icons = await import('@morphemeicons/vue/iconsax/bulk/esm/index')
icon.value = (icons as any)[normalizeName(iconName)];
}
break;
case 'broken': {
const icons = await import('@morphemeicons/vue/iconsax/broken/esm/index')
icon.value = (icons as any)[normalizeName(iconName)];
}
break;
case 'linear': {
const icons = await import('@morphemeicons/vue/iconsax/linear/esm/index')
icon.value = (icons as any)[normalizeName(iconName)];
}
break;
case 'solid': {
const icons = await import('@morphemeicons/vue/iconsax/solid/esm/index')
icon.value = (icons as any)[normalizeName(iconName)];
}
break;
case 'twotone': {
const icons = await import('@morphemeicons/vue/iconsax/twotone/esm/index')
icon.value = (icons as any)[normalizeName(iconName)];
}
break;
default:
console.error(`Variant ${variant} is not supported`)
break;
}
}
else {
icon.value = await loadIcon(props.name).catch(() => { });
}
isFetching.value = false;
}
Expand All @@ -31,8 +107,8 @@ const classes = computed(() => {
const style = computed(() => {
if (!defaultSizes.includes(String(props.size))) {
return {
width: props.size,
height: props.size,
width: props.size,
height: props.size,
};
}
return {}
Expand All @@ -47,6 +123,13 @@ const ariaProps = {

<template>
<span v-if="isFetching" :class="classes" :style="style" v-bind="ariaProps" />
<component
v-else-if="isMorphemeIcons"
:is="icon"
:class="classes"
:style="style"
v-bind="ariaProps"
/>
<Iconify
v-else-if="icon"
:icon="icon"
Expand Down
19 changes: 16 additions & 3 deletions packages/icon/vite.config.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {defineConfig} from 'vite';
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import {resolve} from 'path';
import { resolve } from 'path';

// https://vitejs.dev/config/
export default defineConfig({
Expand All @@ -16,7 +16,20 @@ export default defineConfig({
formats: ['es', 'cjs', 'iife', 'umd'],
},
rollupOptions: {
external: ['vue', '@iconify/vue', '@iconify/vue/dist/offline'],
external: [
'vue',
'@iconify/vue',
'@iconify/vue/dist/offline',
'@morphemeicons/vue',
'@morphemeicons/vue/untitled/esm/index',
'@morphemeicons/vue/remix/esm/index',
'@morphemeicons/vue/iconsax/outline/esm/index',
'@morphemeicons/vue/iconsax/bulk/esm/index',
'@morphemeicons/vue/iconsax/broken/esm/index',
'@morphemeicons/vue/iconsax/solid/esm/index',
'@morphemeicons/vue/iconsax/twotone/esm/index',
'@morphemeicons/vue/iconsax/linear/esm/index',
],
output: {
globals: {
vue: 'Vue',
Expand Down
5 changes: 5 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2721,6 +2721,11 @@
resolved "https://registry.yarnpkg.com/@morpheme/design-tokens/-/design-tokens-0.1.0-alpha.5.tgz#024ed7315dd229c52dbde4a31fdb23777f2c4556"
integrity sha512-CcPxUfBzl1bXQlpKOWs1j2nqLZeJfp75oQSXaqn2DXRZaCw+iBYtNRko8UcuovOe6/ruIWueiQ/0sBSJHechlw==

"@morphemeicons/vue@^0.2.0":
version "0.2.0"
resolved "https://registry.yarnpkg.com/@morphemeicons/vue/-/vue-0.2.0.tgz#ebce8215aff7a484a1de034b02db090dfe060a1a"
integrity sha512-4FBTs1nPR0Yxwfdj9M62YAAWvB10x0am1pNHp0SLxzi9XA0MsBOwQtORtqj6dPhWr9OYW0llxxyCosYuVvPh5Q==

"@mrmlnc/readdir-enhanced@^2.2.1":
version "2.2.1"
resolved "https://registry.yarnpkg.com/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz#524af240d1a360527b730475ecfa1344aa540dde"
Expand Down

0 comments on commit 0b0870b

Please sign in to comment.