mirror of
https://github.com/lucide-icons/lucide.git
synced 2026-11-14 13:58:21 +00:00
Add copy name
This commit is contained in:
@@ -36,15 +36,12 @@ const selectionOptionAction = computed(() => props.options.find(option => option
|
||||
|
||||
function onClick(event) {
|
||||
selectionOptionAction.value()
|
||||
console.log(event);
|
||||
|
||||
|
||||
emit('click', event)
|
||||
}
|
||||
|
||||
function onOptionClick(event, option) {
|
||||
console.log(event, option);
|
||||
|
||||
if(!props.callOptionOnClick) {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -3,13 +3,14 @@ import { computed, ref } from 'vue';
|
||||
import { startCase, camelCase } from 'lodash-es'
|
||||
import ButtonMenu from '../base/ButtonMenu.vue'
|
||||
import { useIconStyleContext } from '../../composables/useIconStyle';
|
||||
import useConfetti from '../../composables/useConfetti';
|
||||
|
||||
const props = defineProps<{
|
||||
name: string
|
||||
popoverPosition?: 'top' | 'bottom'
|
||||
}>()
|
||||
const { size, color, strokeWidth } = useIconStyleContext()
|
||||
const animate = ref(false)
|
||||
const { animate, confetti } = useConfetti()
|
||||
const componentName = computed(() => {
|
||||
return startCase(camelCase(props.name)).replace(/\s/g, '')
|
||||
})
|
||||
@@ -75,14 +76,6 @@ function copyAngular() {
|
||||
|
||||
navigator.clipboard.writeText(code)
|
||||
}
|
||||
|
||||
function confetti(e) {
|
||||
animate.value = true;
|
||||
|
||||
setTimeout(function () {
|
||||
animate.value = false;
|
||||
}, 1000);
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
import { ref } from 'vue';
|
||||
import ButtonMenu from '../base/ButtonMenu.vue'
|
||||
import { useIconStyleContext } from '../../composables/useIconStyle';
|
||||
import useConfetti from '../../composables/useConfetti';
|
||||
|
||||
const allowedAttrs = [
|
||||
'xmlns',
|
||||
@@ -25,15 +26,7 @@ const props = defineProps<{
|
||||
|
||||
const { size } = useIconStyleContext()
|
||||
|
||||
const animate = ref(false)
|
||||
|
||||
function confetti() {
|
||||
animate.value = true;
|
||||
|
||||
setTimeout(function () {
|
||||
animate.value = false;
|
||||
}, 1000);
|
||||
}
|
||||
const { animate, confetti } = useConfetti()
|
||||
|
||||
function getSVGIcon() {
|
||||
const svg = document.querySelector('#previewer svg')
|
||||
|
||||
@@ -1,6 +1,31 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, useSlots } from 'vue';
|
||||
import createLucideIcon from 'lucide-vue-next/src/createLucideIcon'
|
||||
import { copy } from '../../../data/iconNodes'
|
||||
import useConfetti from '../../composables/useConfetti';
|
||||
const { animate, confetti } = useConfetti()
|
||||
const slots = useSlots()
|
||||
|
||||
const copiedText = computed(() => slots.default?.()[0].children)
|
||||
|
||||
function copyText() {
|
||||
navigator.clipboard.writeText(copiedText.value)
|
||||
|
||||
confetti()
|
||||
}
|
||||
|
||||
const Copy = createLucideIcon('ChevronUp', copy)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<h1 class="icon-name">
|
||||
<h1
|
||||
class="icon-name confetti-button"
|
||||
:class="{animate}"
|
||||
data-confetti-text="Copied!"
|
||||
@click="copyText"
|
||||
>
|
||||
<slot />
|
||||
<Copy :size="20" class="copy-icon"/>
|
||||
</h1>
|
||||
</template>
|
||||
|
||||
@@ -13,11 +38,38 @@
|
||||
padding: 2px 8px;
|
||||
border-radius: 8px;
|
||||
width: auto;
|
||||
display: inline-block;
|
||||
display: inline-flex;
|
||||
margin-left: -8px;
|
||||
}
|
||||
|
||||
.icon-name:hover {
|
||||
background-color: var(--vp-c-bg-alt);
|
||||
}
|
||||
|
||||
.icon-name:hover .copy-icon {
|
||||
opacity: .9;
|
||||
}
|
||||
|
||||
.icon-name:before,
|
||||
.icon-name:after {
|
||||
left: unset !important;
|
||||
right: -20%;
|
||||
}
|
||||
|
||||
.icon-name:before {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.copy-icon {
|
||||
opacity: 0;
|
||||
margin-left: 12px;
|
||||
margin-top: 6px;
|
||||
transition:ease .3s opacity;
|
||||
}
|
||||
|
||||
.icon-name:hover .copy-icon:hover {
|
||||
opacity: .6;
|
||||
}
|
||||
</style>
|
||||
|
||||
<style src="./confetti.css" />
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Transition name="drawer">
|
||||
<Transition name="drawer" appear>
|
||||
<div class="overlay-container" v-if="props.icon">
|
||||
<div class="overlay-panel">
|
||||
<nav class="overlay-menu">
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, defineAsyncComponent } from 'vue'
|
||||
import type { IconEntity, Category } from '../../types'
|
||||
import IconDetailOverlay from './IconDetailOverlay.vue'
|
||||
import useSearch from '../../composables/useSearch'
|
||||
import InputSearch from '../base/InputSearch.vue'
|
||||
import useSearchInput from '../../composables/useSearchInput'
|
||||
@@ -13,7 +12,7 @@ const props = defineProps<{
|
||||
categories: Category[]
|
||||
}>()
|
||||
|
||||
const activeIconName = ref('')
|
||||
const activeIconName = ref(null)
|
||||
const { searchInput, searchQuery, searchQueryThrottled } = useSearchInput()
|
||||
|
||||
const isSearching = computed(() => !!searchQuery.value)
|
||||
@@ -55,6 +54,10 @@ const activeIcon = computed(() =>
|
||||
const NoResults = defineAsyncComponent(() =>
|
||||
import('./NoResults.vue')
|
||||
)
|
||||
|
||||
const IconDetailOverlay = defineAsyncComponent(() =>
|
||||
import('./IconDetailOverlay.vue')
|
||||
)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -78,7 +81,11 @@ const NoResults = defineAsyncComponent(() =>
|
||||
:activeIconName="activeIconName"
|
||||
@setActiveIcon="setActiveIconName"
|
||||
/>
|
||||
<IconDetailOverlay :icon="activeIcon" @close="setActiveIconName('')"/>
|
||||
<IconDetailOverlay
|
||||
v-if="activeIconName != null"
|
||||
:icon="activeIcon"
|
||||
@close="setActiveIconName('')"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
import { ref, computed, watch, defineAsyncComponent } from 'vue'
|
||||
import type { IconEntity } from '../../types'
|
||||
import { useMediaQuery, useOffsetPagination } from '@vueuse/core'
|
||||
import IconDetailOverlay from './IconDetailOverlay.vue'
|
||||
import IconGrid from './IconGrid.vue'
|
||||
import InputSearch from '../base/InputSearch.vue'
|
||||
import useSearch from '../../composables/useSearch'
|
||||
@@ -14,7 +13,7 @@ const props = defineProps<{
|
||||
icons: IconEntity[]
|
||||
}>()
|
||||
|
||||
const activeIconName = ref('')
|
||||
const activeIconName = ref(null)
|
||||
|
||||
const isExtraLargeScreen = useMediaQuery('(min-width: 1440px)');
|
||||
const isLargeScreen = useMediaQuery('(min-width: 1280px)');
|
||||
@@ -59,9 +58,7 @@ function setActiveIconName(name: string) {
|
||||
activeIconName.value = name
|
||||
}
|
||||
|
||||
const activeIcon = computed(() =>
|
||||
props.icons.find((icon) => icon.name === activeIconName.value)
|
||||
)
|
||||
const activeIcon = computed(() => props.icons.find((icon) => icon.name === activeIconName.value))
|
||||
|
||||
watch(searchQueryThrottled, (searchString) => {
|
||||
currentPage.value = 1
|
||||
@@ -70,6 +67,11 @@ watch(searchQueryThrottled, (searchString) => {
|
||||
const NoResults = defineAsyncComponent(() =>
|
||||
import('./NoResults.vue')
|
||||
)
|
||||
|
||||
const IconDetailOverlay = defineAsyncComponent(() =>
|
||||
import('./IconDetailOverlay.vue')
|
||||
)
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -93,7 +95,11 @@ const NoResults = defineAsyncComponent(() =>
|
||||
@setActiveIcon="setActiveIconName"
|
||||
/>
|
||||
<EndOfPage @end-of-page="next" class="bottom-page"/>
|
||||
<IconDetailOverlay :icon="activeIcon" @close="setActiveIconName('')"/>
|
||||
<IconDetailOverlay
|
||||
v-if="activeIconName != null"
|
||||
:icon="activeIcon"
|
||||
@close="setActiveIconName('')"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
.search-bar {
|
||||
margin-bottom: 16px;
|
||||
position: sticky;
|
||||
z-index: 30;
|
||||
z-index: 10;
|
||||
top: 48px;
|
||||
padding-top: 24px;
|
||||
margin-top: -32px;
|
||||
|
||||
@@ -15,11 +15,13 @@
|
||||
content: "";
|
||||
display: block;
|
||||
width: 140%;
|
||||
max-width: 160px;
|
||||
height: 100%;
|
||||
left: -20%;
|
||||
z-index: -1000;
|
||||
transition: all ease-in-out 0.5s;
|
||||
background-repeat: no-repeat;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.confetti-button:before {
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
import { ref } from "vue";
|
||||
|
||||
export default function useConfetti() {
|
||||
const animate = ref(false)
|
||||
|
||||
function confetti() {
|
||||
animate.value = true;
|
||||
|
||||
setTimeout(function () {
|
||||
animate.value = false;
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
return {
|
||||
animate,
|
||||
confetti
|
||||
}
|
||||
}
|
||||
+13
-19
@@ -2,25 +2,19 @@ import Fuse from "fuse.js";
|
||||
import { getAllData } from "../.vitepress/lib/icons";
|
||||
import { IconEntity } from "../.vitepress/theme/types";
|
||||
|
||||
const getRelatedIcons = (name:string, icons: IconEntity[]) => {
|
||||
const index = new Fuse(icons, {
|
||||
threshold: 1,
|
||||
keys: [
|
||||
{ name: 'name', weight: 3 },
|
||||
{ name: 'tags', weight: 2 },
|
||||
{ name: 'categories', weight: 1 },
|
||||
],
|
||||
// TODO: This should be ordered by relevance
|
||||
const getRelatedIcons = (currentIcon:IconEntity, icons: IconEntity[]) => {
|
||||
return icons.filter((icon) => {
|
||||
const { name: iconName, tags, categories } = icon;
|
||||
const isNameRelated = iconName.includes(currentIcon.name);
|
||||
|
||||
const hasRelatedTags = tags?.some((tag) => currentIcon?.tags?.includes(tag));
|
||||
const hasRelatedCategories = categories?.some((category) =>
|
||||
currentIcon?.categories?.includes(category)
|
||||
);
|
||||
|
||||
return isNameRelated || hasRelatedTags || hasRelatedCategories;
|
||||
});
|
||||
|
||||
return index
|
||||
.search(name)
|
||||
.map((result) => result.item)
|
||||
.slice(0, 85)
|
||||
.map(({ name, iconNode }: IconEntity) => ({
|
||||
name,
|
||||
iconNode
|
||||
}))
|
||||
|
||||
}
|
||||
|
||||
export default {
|
||||
@@ -28,7 +22,7 @@ export default {
|
||||
const icons = await getAllData()
|
||||
|
||||
return icons.map((iconEntity) => {
|
||||
const relatedIcons = getRelatedIcons(iconEntity.name, icons)
|
||||
const relatedIcons = getRelatedIcons(iconEntity, icons)
|
||||
const params = {
|
||||
...iconEntity,
|
||||
relatedIcons
|
||||
|
||||
Reference in New Issue
Block a user