index.tsx 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. import './index.less';
  2. import type { PropType } from 'vue';
  3. import {
  4. defineComponent,
  5. ref,
  6. watch,
  7. onMounted,
  8. nextTick,
  9. unref,
  10. computed,
  11. CSSProperties,
  12. } from 'vue';
  13. import Iconify from '@purge-icons/generated';
  14. import { isString } from '/@/utils/is';
  15. import { propTypes } from '/@/utils/propTypes';
  16. export default defineComponent({
  17. name: 'GIcon',
  18. props: {
  19. // icon name
  20. icon: propTypes.string,
  21. // icon color
  22. color: propTypes.string,
  23. // icon size
  24. size: {
  25. type: [String, Number] as PropType<string | number>,
  26. default: 16,
  27. },
  28. prefix: propTypes.string.def(''),
  29. },
  30. setup(props, { attrs }) {
  31. const elRef = ref<ElRef>(null);
  32. const getIconRef = computed(() => {
  33. const { icon, prefix } = props;
  34. return `${prefix ? prefix + ':' : ''}${icon}`;
  35. });
  36. const update = async () => {
  37. const el = unref(elRef);
  38. if (el) {
  39. await nextTick();
  40. const icon = unref(getIconRef);
  41. const svg = Iconify.renderSVG(icon, {});
  42. if (svg) {
  43. el.textContent = '';
  44. el.appendChild(svg);
  45. } else {
  46. const span = document.createElement('span');
  47. span.className = 'iconify';
  48. span.dataset.icon = icon;
  49. el.textContent = '';
  50. el.appendChild(span);
  51. }
  52. }
  53. };
  54. const wrapStyleRef = computed(
  55. (): CSSProperties => {
  56. const { size, color } = props;
  57. let fs = size;
  58. if (isString(size)) {
  59. fs = parseInt(size, 10);
  60. }
  61. return {
  62. fontSize: `${fs}px`,
  63. color,
  64. display: 'inline-flex',
  65. };
  66. }
  67. );
  68. watch(() => props.icon, update, { flush: 'post' });
  69. onMounted(update);
  70. return () => (
  71. <div ref={elRef} class={[attrs.class, 'app-iconify anticon']} style={unref(wrapStyleRef)} />
  72. );
  73. },
  74. });