icons.vue 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. <script setup lang="ts">
  2. import { computed, ref } from 'vue'
  3. import clipboardCopy from 'clipboard-copy'
  4. import { ElMessage } from 'element-plus'
  5. import * as Icons from '@element-plus/icons-vue'
  6. import { useLang } from '../../composables/lang'
  7. import localeData from '../../../i18n/component/icons.json'
  8. import IconCategories from './icons-categories.json'
  9. import type { DefineComponent } from 'vue'
  10. type CategoriesItem = {
  11. name: string
  12. icons: DefineComponent[]
  13. }
  14. const lang = useLang()
  15. const locale = computed(() => localeData[lang.value])
  16. const copyIcon = ref(true)
  17. const copyContent = async content => {
  18. try {
  19. await clipboardCopy(content)
  20. ElMessage({
  21. showClose: true,
  22. message: locale.value['copy-success'],
  23. type: 'success',
  24. })
  25. } catch {
  26. ElMessage({
  27. showClose: true,
  28. message: locale.value['copy-error'],
  29. type: 'error',
  30. })
  31. }
  32. }
  33. const copySvgIcon = async (name, refs) => {
  34. if (copyIcon.value) {
  35. await copyContent(`<el-icon><${name} /></el-icon>`)
  36. } else {
  37. const content = refs[name]?.[0].querySelector('svg')?.outerHTML ?? ''
  38. await copyContent(content)
  39. }
  40. }
  41. const categories = ref<CategoriesItem[]>([])
  42. const iconMap = new Map(Object.entries(Icons))
  43. IconCategories.categories.forEach(o => {
  44. const result: CategoriesItem = {
  45. name: o.name,
  46. icons: [],
  47. }
  48. o.items.forEach(i => {
  49. const icon = iconMap.get(i)
  50. if (icon) {
  51. result.icons.push(icon)
  52. iconMap.delete(i)
  53. }
  54. })
  55. categories.value.push(result)
  56. })
  57. categories.value.push({ name: 'Other', icons: Array.from(iconMap.values()) })
  58. </script>
  59. <template>
  60. <div style="text-align: right">
  61. <el-switch v-model="copyIcon" active-text="Copy icon code" inactive-text="Copy SVG content" />
  62. </div>
  63. <div v-for="item in categories" :key="item.name" class="demo-icon-item">
  64. <div class="demo-icon-title">{{ item.name }}</div>
  65. <ul class="demo-icon-list">
  66. <li v-for="component in item.icons" :key="component.name" :ref="component.name" class="icon-item" @click="copySvgIcon(component.name, $refs)">
  67. <span class="demo-svg-icon">
  68. <ElIcon :size="20">
  69. <component :is="component" />
  70. </ElIcon>
  71. <span class="icon-name">{{ component.name }}</span>
  72. </span>
  73. </li>
  74. </ul>
  75. </div>
  76. </template>
  77. <style scoped lang="scss">
  78. .demo-icon {
  79. &-item {
  80. margin-top: 24px;
  81. &:first-child {
  82. margin-top: 0;
  83. }
  84. }
  85. &-title {
  86. font-weight: 400;
  87. font-size: 18px;
  88. line-height: 26px;
  89. }
  90. &-list {
  91. overflow: hidden;
  92. list-style: none;
  93. padding: 0 !important;
  94. border-top: 1px solid var(--el-border-color);
  95. border-left: 1px solid var(--el-border-color);
  96. border-radius: 4px;
  97. display: grid;
  98. grid-template-columns: repeat(7, 1fr);
  99. .icon-item {
  100. text-align: center;
  101. color: var(--el-text-color-regular);
  102. height: 90px;
  103. font-size: 13px;
  104. border-right: 1px solid var(--el-border-color);
  105. border-bottom: 1px solid var(--el-border-color);
  106. transition: background-color var(--el-transition-duration);
  107. &:hover {
  108. background-color: var(--el-border-color-extra-light);
  109. .el-icon {
  110. color: var(--brand-color-light);
  111. }
  112. color: var(--brand-color-light);
  113. }
  114. .demo-svg-icon {
  115. display: flex;
  116. flex-direction: column;
  117. align-items: center;
  118. justify-content: center;
  119. height: 100%;
  120. cursor: pointer;
  121. .icon-name {
  122. margin-top: 8px;
  123. }
  124. }
  125. }
  126. }
  127. }
  128. </style>