Compare commits

..

8 Commits

Author SHA1 Message Date
Karsa
6b4075b89b feat(icons): added toolbox icon (#3871)
* Added icons/toolbox.svg

* Added icons/toolbox.json
2025-12-18 11:44:47 +01:00
Jacek Tomaszewski
7a68e10b12 fix(lucide-react-native): remove icons namespace export to enable tree-shaking (#3868)
* fix(lucide-react-native): remove icons namespace export to enable tree-shaking

The `export * as icons from './icons'` statement defeats tree-shaking
because bundlers cannot determine which exports from the namespace are
actually used at build time. This causes all 1600+ icons to be included
in the final bundle even when only a few are imported.

This change removes the namespace re-export while keeping all individual
icon exports available via `export * from './icons'`.

BREAKING CHANGE: The `icons` namespace export is no longer available.
Users should import icons directly: `import { Activity } from 'lucide-react-native'`
instead of `import { icons } from 'lucide-react-native'; icons.Activity`.

* Add icons entry file to improve treeshaking

* Format code

---------

Co-authored-by: Eric Fennis <eric.fennis@gmail.com>
2025-12-18 11:44:26 +01:00
Jakob Guddas
a4531a9985 fix(react-native-web): only add className prop to parent Icon component (#3892) 2025-12-18 11:43:31 +01:00
taimar
3edcd9e0c3 fix and unify color-picker font-size (#3889) 2025-12-15 14:59:14 +01:00
Jakob Guddas
0b8f99326c fix(icons): changed paint-bucket icon (#3880)
* Updated icons/paint-bucket.svg

* Updated icons/paint-bucket.svg

* Updated icons/paint-bucket.svg

* Updated icons/paint-bucket.svg

* Updated icons/paint-bucket.json

* Updated icons/paint-bucket.json
2025-12-12 13:27:37 +01:00
Alexandru Portan
7abb61630e feat(icons): added stone icon (#3850)
* Added icons/stone.svg

* Added icons/stone.json

* Update icons/stone.json

Added suggested tags

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

* Update stone.svg

Updated based on suggested changes

* Update icons/stone.json

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Jakob Guddas <github@jguddas.de>
2025-12-12 09:26:54 +01:00
Eric Fennis
3b0d158ea1 fix(site): Small adjustments color picker and add clear button search bar (#3851)
* Small adjustments

* Format code

* format code

* Remove default value

* format code

* update yml file

* Format code

* Update docs/.vitepress/theme/components/base/Input.vue

Co-authored-by: Karsa <contact@karsa.org>

* Add extra check if null or undefined

---------

Co-authored-by: Karsa <contact@karsa.org>
2025-12-12 09:25:39 +01:00
Veles
124572c83b feat(icons): added cannabis-off icon (#3748)
* Added icons/cannabis-off.svg

* Added icons/cannabis-off.json

* fix: applied optimization by jguddas

---------

Co-authored-by: Eric Fennis <eric.fennis@gmail.com>
Co-authored-by: Karsa <contact@karsa.org>
2025-12-11 09:15:49 +01:00
47 changed files with 4715 additions and 6404 deletions

View File

@@ -1,13 +0,0 @@
import { eventHandler, setResponseHeader } from 'h3';
import releaseMeta from '../../data/releaseMetaData.json';
export default eventHandler((event) => {
setResponseHeader(event, 'Cache-Control', 'public, max-age=86400');
setResponseHeader(event, 'Access-Control-Allow-Origin', '*');
return Object.fromEntries(
Object.entries(releaseMeta).map(
([name, { createdRelease }]) => [name, createdRelease.version]
)
);
});

View File

@@ -0,0 +1,3 @@
export default eventHandler(() => {
return { nitro: 'Is Awesome! asda' };
});

View File

@@ -1,5 +1,5 @@
import { createLucideIcon } from 'lucide-react/src/lucide-react';
import { type LucideProps, type IconNode } from 'lucide-react/src/createLucideIcon';
import { type LucideProps, type IconNode } from 'lucide-react/src/types';
import { IconEntity } from '../theme/types';
import { renderToStaticMarkup } from 'react-dom/server';
import { IconContent } from './generateZip';

View File

@@ -1,23 +1,31 @@
<script setup lang="ts">
import { useData } from 'vitepress';
import { computed } from 'vue';
const props = defineProps<{
modelValue: string
id: string
}>()
modelValue: string;
id: string;
}>();
const emit = defineEmits(['update:modelValue'])
const { isDark } = useData();
const emit = defineEmits(['update:modelValue']);
const value = computed({
get: () => props.modelValue,
set: (val) => emit('update:modelValue', val)
})
get: () => {
if (props.modelValue == null || props.modelValue === 'currentColor') {
return isDark.value ? '#ffffff' : '#000000';
}
return props.modelValue;
},
set: (val) => emit('update:modelValue', val),
});
</script>
<template>
<div class="color-picker">
<div class="color-input-wrapper">
<!-- TODO: Add currentColor div if value is currentColor -->
<input
type="color"
:id="id"
@@ -33,6 +41,7 @@ const value = computed({
class="color-input-text"
aria-label="Color picker input"
v-model="value"
placeholder="[default]"
/>
</div>
</template>
@@ -45,27 +54,33 @@ const value = computed({
top: -5px;
left: -5px;
}
.color-input-wrapper {
height: 24px;
width: 24px;
overflow: hidden;
position: relative;
border-radius: 12px;
border-radius: 4px;
flex-shrink: 0;
}
.color-picker {
background: var(--color-picker-bg, var(--vp-c-bg-alt));
border-radius: 8px;
color: var(--vp-c-text-2);
padding: 4px 8px;
padding: 3px 8px 3px 3px;
height: auto;
font-size: 14px;
font-size: 13px;
text-align: left;
border: 1px solid transparent;
cursor: text;
display: flex;
align-items: center;
gap: 2px;
transition:
color 0.25s,
border-color 0.25s,
background-color 0.25s;
}
.color-input-text {
@@ -75,19 +90,22 @@ const value = computed({
border: none;
background: transparent;
color: var(--vp-c-text-1);
font-size: 14px;
font-size: 13px;
text-align: left;
border-radius: 8px;
cursor: text;
transition: border-color 0.25s, background 0.4s ease;
transition:
border-color 0.25s,
background 0.4s ease;
letter-spacing: 1px;
}
.color-picker:hover, .color-picker:focus {
.color-picker:hover,
.color-picker:focus {
border-color: var(--vp-c-brand);
background: var(--vp-c-bg-alt);
}
.color-input[value="currentColor"] {
.color-input[value='currentColor'] {
}
</style>

View File

@@ -1,22 +1,27 @@
<script setup>
import createLucideIcon from 'lucide-vue-next/src/createLucideIcon'
import { search } from '../../../data/iconNodes'
const SearchIcon = createLucideIcon('search', search)
import Icon from 'lucide-vue-next/src/Icon';
import { search } from '../../../data/iconNodes';
defineProps({
shortcut: {
type: String,
required: false
}
})
required: false,
},
});
</script>
<template>
<button class="fake-input">
<component :is="SearchIcon" class="search-icon"/>
<slot/>
<kbd v-if="shortcut" class="shortcut">{{ shortcut }}</kbd>
<Icon
:iconNode="search"
class="search-icon"
/>
<slot />
<kbd
v-if="shortcut"
class="shortcut"
>{{ shortcut }}</kbd
>
</button>
</template>
@@ -34,10 +39,14 @@ defineProps({
cursor: text;
display: flex;
gap: 12px;
transition: color 0.25s, border-color 0.25s, background-color 0.25s;
transition:
color 0.25s,
border-color 0.25s,
background-color 0.25s;
}
.fake-input:hover, .fake-input:focus {
.fake-input:hover,
.fake-input:focus {
border-color: var(--vp-c-brand);
background: var(--vp-c-bg-alt);
}

View File

@@ -5,7 +5,6 @@
</template>
<style scoped>
.icon-button {
display: inline-flex;
border: 1px solid transparent;
@@ -30,9 +29,9 @@
}
.icon-button:active {
border-color: var(--vp-button-alt-active-border);
color: var(--vp-button-alt-active-text);
background-color: var(--vp-button-alt-active-bg);
border-color: var(--vp-button-alt-active-border);
color: var(--vp-button-alt-active-text);
background-color: var(--vp-button-alt-active-bg);
}
.icon-button.active {

View File

@@ -12,6 +12,9 @@ export interface InputProps {
<script setup lang="ts">
import { ref, onMounted, nextTick, watch } from 'vue';
import Icon from 'lucide-vue-next/src/Icon';
import { x } from '../../../data/iconNodes';
import IconButton from './IconButton.vue';
const props = withDefaults(defineProps<InputProps>(), {
type: 'text',
@@ -21,7 +24,7 @@ const input = ref();
const wrapperEl = ref();
const shortcutEl = ref();
defineEmits(['change', 'input', 'update:modelValue']);
const emit = defineEmits(['change', 'input', 'update:modelValue']);
const updateShortcutSpacing = () => {
nextTick(() => {
@@ -35,6 +38,11 @@ const updateShortcutSpacing = () => {
onMounted(updateShortcutSpacing);
watch(() => props.shortcut, updateShortcutSpacing);
function onClear() {
emit('update:modelValue', '');
input.value.focus();
}
defineExpose({
focus: () => {
input.value.focus();
@@ -60,6 +68,17 @@ defineExpose({
v-bind="$attrs"
@input="$emit('update:modelValue', $event.target.value)"
/>
<IconButton
@click="onClear"
v-if="type === 'search' && modelValue"
class="clear-button"
aria-label="Clear input"
>
<Icon
:iconNode="x"
:size="20"
/>
</IconButton>
<kbd
v-if="shortcut"
class="shortcut"
@@ -73,6 +92,7 @@ defineExpose({
.input-wrapper {
position: relative;
}
.input {
justify-content: flex-start;
border: 1px solid transparent;
@@ -82,7 +102,10 @@ defineExpose({
height: 40px;
background-color: var(--vp-c-bg-alt);
font-size: 14px;
transition: border-color 0.2s ease-in-out;
transition:
color 0.25s,
border-color 0.25s,
background-color 0.25s;
}
.input.has-shortcut {
@@ -99,6 +122,14 @@ defineExpose({
padding-left: 52px;
}
.clear-button {
position: absolute;
right: 56px;
top: 9px;
padding: 4px;
transition: background-color .25s;
}
.shortcut {
position: absolute;
right: 12px;

View File

@@ -7,11 +7,8 @@ export default {
<script setup lang="ts">
import { computed, ref } from 'vue';
import Input from './Input.vue';
import createLucideIcon from 'lucide-vue-next/src/createLucideIcon';
import { search, x } from '../../../data/iconNodes';
const SearchIcon = createLucideIcon('search', search);
const XIcon = createLucideIcon('close', x);
import Icon from 'lucide-vue-next/src/Icon';
import { search } from '../../../data/iconNodes';
interface Props {
modelValue: string;
@@ -34,10 +31,6 @@ const value = computed({
get: () => props.modelValue,
set: (val) => emit('update:modelValue', val),
});
const clear = () => {
value.value = '';
};
</script>
<template>
@@ -50,26 +43,12 @@ const clear = () => {
v-model="value"
class="input-wrapper"
>
<template #startIcon>
<component
:is="SearchIcon"
<template #icon>
<Icon
:iconNode="search"
class="search-icon"
/>
</template>
<template #endIcon>
<button
class="clear-button"
type="button"
v-if="value"
>
<component
:is="XIcon"
class="x-icon"
@click="clear"
/>
</button>
</template>
</Input>
</template>
@@ -81,9 +60,7 @@ const clear = () => {
padding: 0 10px 0 12px;
width: 100%;
height: 40px;
color: var(--vp-c-text-1);
background-color: var(--vp-c-bg-alt);
transition: border-color 0.15s ease-in-out;
}
.input:hover,
@@ -93,31 +70,9 @@ const clear = () => {
}
.input-wrapper:deep(.input) {
/* padding: 12px 24px; */
padding-block: 12px;
font-size: 14px;
height: 48px;
}
.clear-button {
position: absolute;
padding: 4px;
right: 8px;
top: 8px;
width: 32px;
height: 32px;
background: transparent;
border-radius: 6px;
transition: background 0.2s ease;
}
.clear-button:hover {
background: var(--vp-button-alt-bg);
}
.input-wrapper:deep(.input)::-webkit-search-decoration,
.input-wrapper:deep(.input)::-webkit-search-cancel-button,
.input-wrapper:deep(.input)::-webkit-search-results-button,
.input-wrapper:deep(.input)::-webkit-search-results-decoration {
display: none;
}
</style>

View File

@@ -1,14 +1,15 @@
<script setup lang="ts">
import { rotateCw } from '../../../data/iconNodes'
import createLucideIcon from 'lucide-vue-next/src/createLucideIcon'
import IconButton from "./IconButton.vue";
const RotateIcon = createLucideIcon('RotateIcon', rotateCw)
import { rotateCw } from '../../../data/iconNodes';
import Icon from 'lucide-vue-next/src/Icon';
import IconButton from './IconButton.vue';
</script>
<template>
<IconButton class="reset-button">
<RotateIcon :size="20"/>
<Icon
:size="20"
:iconNode="rotateCw"
/>
</IconButton>
</template>
@@ -32,6 +33,7 @@ const RotateIcon = createLucideIcon('RotateIcon', rotateCw)
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(359deg);
}

View File

@@ -52,6 +52,7 @@
width: 20px;
height: 20px;
border-radius: 50%;
/* background-color: var(--vp-c-neutral); */
box-shadow: var(--vp-shadow-1);
}

View File

@@ -22,16 +22,16 @@ export default {
logo: '/framework-logos/svelte.svg',
label: 'Lucide documentation for Svelte',
},
{
name: 'lucide-preact',
logo: '/framework-logos/preact.svg',
label: 'Lucide documentation for Preact',
},
{
name: 'lucide-solid',
logo: '/framework-logos/solid.svg',
label: 'Lucide documentation for Solid',
},
{
name: 'lucide-preact',
logo: '/framework-logos/preact.svg',
label: 'Lucide documentation for Preact',
},
{
name: 'lucide-angular',
logo: '/framework-logos/angular.svg',
@@ -48,11 +48,6 @@ export default {
logo: '/framework-logos/react-native.svg',
label: 'Lucide documentation for React Native',
},
{
name: 'lucide-flutter',
logo: '/framework-logos/flutter.svg',
label: 'Lucide documentation for Flutter',
},
],
};
},

View File

@@ -2,45 +2,48 @@
import { useData } from 'vitepress';
import { useSessionStorage } from '@vueuse/core';
import IconButton from '../base/IconButton.vue';
// import VPDocAsideCarbonAds from 'vitepress/dist/client/theme-default/components/VPDocAsideCarbonAds.vue'
import { x } from '../../../data/iconNodes'
import createLucideIcon from 'lucide-vue-next/src/createLucideIcon';
import VPDocAsideCarbonAds from 'vitepress/dist/client/theme-default/components/VPDocAsideCarbonAds.vue';
import { x } from '../../../data/iconNodes';
import Icon from 'lucide-vue-next/src/Icon';
import { onMounted, ref } from 'vue';
const { theme } = useData()
const showAd = useSessionStorage('show-carbon-ads', true)
const carbonLoaded = ref(true)
const { theme } = useData();
const showAd = useSessionStorage('show-carbon-ads', true);
const carbonLoaded = ref(true);
defineProps<{
drawerOpen: boolean
}>()
const CloseIcon = createLucideIcon('Close', x)
drawerOpen: boolean;
}>();
onMounted(() => {
setTimeout(() => {
if (window?._carbonads == null) {
carbonLoaded.value = false
carbonLoaded.value = false;
}
}, 5000)
})
}, 5000);
});
</script>
<template>
<div
:class="{
'drawer-open': drawerOpen,
'hide-ad': !(showAd && carbonLoaded)
'hide-ad': !(showAd && carbonLoaded),
}"
class="floating-ad"
v-if="theme.carbonAds"
>
<IconButton @click="showAd = false" class="hide-button">
<component :is="CloseIcon" :size="20" absoluteStrokeWidth />
<IconButton
@click="showAd = false"
class="hide-button"
>
<Icon
:iconNode="x"
:size="20"
absoluteStrokeWidth
/>
</IconButton>
<VPDocAsideCarbonAds
:carbon-ads="theme.carbonAds"
/>
<VPDocAsideCarbonAds :carbon-ads="theme.carbonAds" />
</div>
</template>
@@ -51,7 +54,9 @@ onMounted(() => {
bottom: 32px;
width: 224px;
right: 32px;
transition: opacity 0.5s, transform 0.25s ease;
transition:
opacity 0.5s,
transform 0.25s ease;
}
.floating-ad.drawer-open {
@@ -67,8 +72,11 @@ onMounted(() => {
transform: translateY(-288px) translateX(224px);
}
.floating-ad.drawer-open, .floating-ad.hide-ad {
transition: opacity 0.25s, transform 0.5s cubic-bezier(0.19, 1, 0.22, 1);
.floating-ad.drawer-open,
.floating-ad.hide-ad {
transition:
opacity 0.25s,
transform 0.5s cubic-bezier(0.19, 1, 0.22, 1);
}
@media (min-width: 1280px) {

View File

@@ -1,70 +1,68 @@
<script setup lang="ts">
import { ref } from 'vue';
import ButtonMenu from '../base/ButtonMenu.vue'
import ButtonMenu from '../base/ButtonMenu.vue';
import { useIconStyleContext } from '../../composables/useIconStyle';
import useConfetti from '../../composables/useConfetti';
import getSVGIcon from '../../utils/getSVGIcon';
import downloadData from '../../utils/downloadData';
const downloadText = 'Download!'
const copiedText = 'Copied!'
const confettiText = ref(copiedText)
const downloadText = 'Download!';
const copiedText = 'Copied!';
const confettiText = ref(copiedText);
const props = defineProps<{
name: string
popoverPosition?: 'top' | 'bottom'
}>()
name: string;
popoverPosition?: 'top' | 'bottom';
}>();
const { size } = useIconStyleContext()
const { size } = useIconStyleContext();
const { animate, confetti } = useConfetti()
const { animate, confetti } = useConfetti();
function copySVG() {
confettiText.value = copiedText
const svgString = getSVGIcon()
confettiText.value = copiedText;
const svgString = getSVGIcon();
navigator.clipboard.writeText(svgString)
navigator.clipboard.writeText(svgString);
confetti()
confetti();
}
function copyDataUrl() {
confettiText.value = copiedText
const svgString = getSVGIcon()
confettiText.value = copiedText;
const svgString = getSVGIcon();
// Create SVG data url
const dataUrl = `data:image/svg+xml;base64,${btoa(svgString)}`
navigator.clipboard.writeText(dataUrl)
const dataUrl = `data:image/svg+xml;base64,${btoa(svgString)}`;
navigator.clipboard.writeText(dataUrl);
confetti()
confetti();
}
function downloadSVG() {
confettiText.value = downloadText
const svgString = getSVGIcon()
confettiText.value = downloadText;
const svgString = getSVGIcon();
downloadData(`${props.name}.svg`, `data:image/svg+xml;base64,${btoa(svgString)}`)
confetti()
downloadData(`${props.name}.svg`, `data:image/svg+xml;base64,${btoa(svgString)}`);
confetti();
}
function downloadPNG() {
confettiText.value = downloadText
const svgString = getSVGIcon()
confettiText.value = downloadText;
const svgString = getSVGIcon();
const canvas = document.createElement('canvas');
canvas.width = size.value;
canvas.height = size.value;
const ctx = canvas.getContext("2d");
const ctx = canvas.getContext('2d');
const image = new Image();
image.src = `data:image/svg+xml;base64,${btoa(svgString)}`;
image.onload = function() {
image.onload = function () {
ctx.drawImage(image, 0, 0);
downloadData(`${props.name}.png`, canvas.toDataURL('image/png'))
confetti()
}
downloadData(`${props.name}.png`, canvas.toDataURL('image/png'));
confetti();
};
}
</script>
<template>
@@ -75,10 +73,10 @@ function downloadPNG() {
:data-confetti-text="confettiText"
:popoverPosition="popoverPosition"
:options="[
{ text: 'Copy SVG' , onClick: copySVG },
{ text: 'Copy Data URL' , onClick: copyDataUrl },
{ text: 'Download SVG' , onClick: downloadSVG },
{ text: 'Download PNG' , onClick: downloadPNG },
{ text: 'Copy SVG', onClick: copySVG },
{ text: 'Copy Data URL', onClick: copyDataUrl },
{ text: 'Download SVG', onClick: downloadSVG },
{ text: 'Download PNG', onClick: downloadPNG },
]"
/>
</template>

View File

@@ -1,41 +1,44 @@
<script setup lang="ts">
import { computed, useSlots } from 'vue';
import createLucideIcon from 'lucide-vue-next/src/createLucideIcon'
import { copy } from '../../../data/iconNodes'
import { copy } from '../../../data/iconNodes';
import useConfetti from '../../composables/useConfetti';
const { animate, confetti } = useConfetti()
const slots = useSlots()
import Icon from 'lucide-vue-next/src/Icon';
const { animate, confetti } = useConfetti();
const slots = useSlots();
const copiedText = computed(() => slots.default?.()[0].children)
const copiedText = computed(() => slots.default?.()[0].children);
function copyText() {
navigator.clipboard.writeText(copiedText.value)
navigator.clipboard.writeText(copiedText.value);
confetti()
confetti();
}
const Copy = createLucideIcon('ChevronUp', copy)
</script>
<template>
<h1
class="icon-name confetti-button"
:class="{animate}"
:class="{ animate }"
data-confetti-text="Copied!"
@click="copyText"
>
<slot />
<Copy :size="20" class="copy-icon"/>
<Icon
:iconNode="copy"
:size="20"
class="copy-icon"
/>
</h1>
</template>
<style scoped>
@import './confetti.css';
.icon-name {
font-size: 24px;
font-weight: 500;
line-height: 32px;
transition: background ease-in .15s;;
transition: background ease-in 0.15s;
padding: 2px 8px;
border-radius: 8px;
width: auto;
@@ -48,7 +51,7 @@ const Copy = createLucideIcon('ChevronUp', copy)
}
.icon-name:hover .copy-icon {
opacity: .9;
opacity: 0.9;
}
.icon-name:before,
@@ -65,10 +68,10 @@ const Copy = createLucideIcon('ChevronUp', copy)
opacity: 0;
margin-left: 12px;
margin-top: 6px;
transition:ease .3s opacity;
transition: ease 0.3s opacity;
}
.icon-name:hover .copy-icon:hover {
opacity: .6;
opacity: 0.6;
}
</style>

View File

@@ -1,21 +0,0 @@
import { getAllData } from '../../../lib/icons';
import { getAllCategoryFiles, mapCategoryIconCount } from '../../../lib/categories';
import iconsMetaData from '../../../data/iconMetaData';
import { fetchAllReleases } from '../../../../scripts/writeReleaseMetadata.mts';
import { satisfies } from 'semver';
export default {
async load() {
const versions = await fetchAllReleases();
const mappedVersions = versions
.map((tag) => tag.replace('v', ''))
.reverse()
mappedVersions.length = 100
return {
versions: mappedVersions,
};
},
};

View File

@@ -1,5 +1,5 @@
<script setup lang="ts">
import { ref, computed, defineAsyncComponent, onMounted, watch, watchEffect } from 'vue';
import { ref, computed, defineAsyncComponent, onMounted, watch } from 'vue';
import type { IconEntity } from '../../types';
import { useElementSize, useEventListener, useVirtualList } from '@vueuse/core';
import { useRoute } from 'vitepress';
@@ -11,13 +11,9 @@ import useSearchShortcut from '../../utils/useSearchShortcut';
import StickyBar from './StickyBar.vue';
import useFetchTags from '../../composables/useFetchTags';
import useFetchCategories from '../../composables/useFetchCategories';
import useFetchVersionIcons from '../../composables/useFetchVersionIcons';
import chunkArray from '../../utils/chunkArray';
import CarbonAdOverlay from './CarbonAdOverlay.vue';
import VersionSelect from './VersionSelect.vue';
import { sort, satisfies } from 'semver';
import useSearchPlaceholder from '../../utils/useSearchPlaceholder.ts';
import { data as versionData } from './IconsOverview.data';
const ICON_SIZE = 56;
const ICON_GRID_GAP = 8;
@@ -36,15 +32,9 @@ const props = defineProps<{
}>();
const activeIconName = ref(null);
const selectedVersion = ref();
const { execute: fetchTags, data: tags } = useFetchTags();
const { execute: fetchCategories, data: categories } = useFetchCategories();
const { execute: fetchVersionIcons, data: versionIcons } = useFetchVersionIcons(selectedVersion);
watch(selectedVersion, () => {
fetchVersionIcons();
});
const overviewEl = ref<HTMLElement | null>(null);
const { width: containerWidth } = useElementSize(overviewEl);
@@ -54,31 +44,20 @@ const columnSize = computed(() => {
});
const mappedIcons = computed(() => {
let icons = props.icons;
if (tags.value != null && categories.value != null) {
icons = props.icons.map((icon) => {
const iconTags = tags.value[icon.name];
const iconCategories = categories.value?.[icon.name] ?? [];
return {
...icon,
tags: iconTags,
categories: iconCategories,
};
});
if (tags.value == null) {
return props.icons;
}
if (selectedVersion.value == null || versionIcons.value == null) {
console.log('no release info');
return props.icons.map((icon) => {
const iconTags = tags.value[icon.name];
const iconCategories = categories.value?.[icon.name] ?? [];
return icons;
}
return Object.values(versionIcons.value).filter(([name, iconNode]) => ({
name,
iconNode,
}));
return {
...icon,
tags: iconTags,
categories: iconCategories,
};
});
});
const { searchInput, searchQuery, searchQueryDebounced } = useSearchInput();
@@ -128,12 +107,6 @@ function onFocusSearchInput() {
}
}
// function onFocusVersionSelect() {
// if (releaseInfo.value == null) {
// fetchReleaseInfo();
// }
// }
const NoResults = defineAsyncComponent(() => import('./NoResults.vue'));
const IconDetailOverlay = defineAsyncComponent(() => import('./IconDetailOverlay.vue'));
@@ -156,17 +129,13 @@ function handleCloseDrawer() {
>
<StickyBar>
<InputSearch
:placeholder="`Search ${mappedIcons.length} icons ...`"
:placeholder="`Search ${icons.length} icons ...`"
v-model="searchQuery"
ref="searchInput"
:shortcut="kbdSearchShortcut"
class="input-wrapper"
@focus="onFocusSearchInput"
/>
<VersionSelect
v-model="selectedVersion"
:versions="versionData.versions"
/>
</StickyBar>
<NoResults
v-if="searchPlaceholder.isNoResults"

View File

@@ -1,75 +1,72 @@
<script setup lang="ts">
import { shallowRef, type Ref, watch, computed } from 'vue'
import { useCssVar, syncRef } from '@vueuse/core'
import { STYLE_DEFAULTS, useIconStyleContext } from '../../composables/useIconStyle'
import RangeSlider from '../base/RangeSlider.vue'
import InputField from '../base/InputField.vue'
import ColorPicker from '../base/ColorPicker.vue'
import ResetButton from '../base/ResetButton.vue'
import Switch from '../base/Switch.vue'
import { shallowRef, type Ref, watch, computed } from 'vue';
import { useCssVar, syncRef } from '@vueuse/core';
import { STYLE_DEFAULTS, useIconStyleContext } from '../../composables/useIconStyle';
import RangeSlider from '../base/RangeSlider.vue';
import InputField from '../base/InputField.vue';
import ColorPicker from '../base/ColorPicker.vue';
import ResetButton from '../base/ResetButton.vue';
import Switch from '../base/Switch.vue';
const props = defineProps<{
rootEl?: Ref<HTMLElement>
}>()
rootEl?: Ref<HTMLElement>;
}>();
const { color, strokeWidth, size, absoluteStrokeWidth } = useIconStyleContext()
const documentRef = shallowRef<HTMLElement | undefined>(typeof document !== 'undefined' ? document?.documentElement : undefined)
const { color, strokeWidth, size, absoluteStrokeWidth } = useIconStyleContext();
const documentRef = shallowRef<HTMLElement | undefined>(
typeof document !== 'undefined' ? document?.documentElement : undefined,
);
const colorCssVar = useCssVar(
'--customize-color',
props.rootEl?.value ?? documentRef.value,
{
initialValue: `${STYLE_DEFAULTS.color}`
}
)
const colorCssVar = useCssVar('--customize-color', props.rootEl?.value ?? documentRef.value, {
initialValue: `${STYLE_DEFAULTS.color}`,
});
const strokeWidthCssVar = useCssVar(
'--customize-strokeWidth',
props.rootEl?.value ?? documentRef.value,
{
initialValue: `${STYLE_DEFAULTS.strokeWidth}`
}
)
initialValue: `${STYLE_DEFAULTS.strokeWidth}`,
},
);
const sizeCssVar = useCssVar(
'--customize-size',
props.rootEl?.value ?? documentRef.value,
{
initialValue: `${STYLE_DEFAULTS.size}`
}
)
const sizeCssVar = useCssVar('--customize-size', props.rootEl?.value ?? documentRef.value, {
initialValue: `${STYLE_DEFAULTS.size}`,
});
syncRef(color, colorCssVar, { direction: 'ltr' })
syncRef(strokeWidth, strokeWidthCssVar, { direction: 'ltr' })
syncRef(size, sizeCssVar, { direction: 'ltr' })
syncRef(color, colorCssVar, { direction: 'ltr' });
syncRef(strokeWidth, strokeWidthCssVar, { direction: 'ltr' });
syncRef(size, sizeCssVar, { direction: 'ltr' });
function resetStyle () {
color.value = STYLE_DEFAULTS.color
strokeWidth.value = STYLE_DEFAULTS.strokeWidth
size.value = STYLE_DEFAULTS.size
absoluteStrokeWidth.value = STYLE_DEFAULTS.absoluteStrokeWidth
function resetStyle() {
color.value = STYLE_DEFAULTS.color;
strokeWidth.value = STYLE_DEFAULTS.strokeWidth;
size.value = STYLE_DEFAULTS.size;
absoluteStrokeWidth.value = STYLE_DEFAULTS.absoluteStrokeWidth;
}
watch(absoluteStrokeWidth, (enabled) => {
const htmlEl = document.documentElement
const htmlEl = document.documentElement;
htmlEl.classList.toggle('absolute-stroke-width', enabled)
})
htmlEl.classList.toggle('absolute-stroke-width', enabled);
});
const customizingActive = computed(() => {
return color.value !== STYLE_DEFAULTS.color
|| strokeWidth.value !== STYLE_DEFAULTS.strokeWidth
|| size.value !== STYLE_DEFAULTS.size
|| absoluteStrokeWidth.value !== STYLE_DEFAULTS.absoluteStrokeWidth
})
return (
color.value !== STYLE_DEFAULTS.color ||
strokeWidth.value !== STYLE_DEFAULTS.strokeWidth ||
size.value !== STYLE_DEFAULTS.size ||
absoluteStrokeWidth.value !== STYLE_DEFAULTS.absoluteStrokeWidth
);
});
</script>
<template>
<div class="customizer-card" :class="{ customized: customizingActive }">
<div
class="customizer-card"
:class="{ customized: customizingActive }"
>
<div class="card-header">
<h2 class="card-title">
Customizer
</h2>
<h2 class="card-title">Customizer</h2>
<ResetButton @click="resetStyle"></ResetButton>
</div>
<InputField
@@ -77,7 +74,11 @@ const customizingActive = computed(() => {
label="Color"
>
<template #display>
<ColorPicker v-model="color" id="icon-color" class="color-picker"/>
<ColorPicker
v-model="color"
id="icon-color"
class="color-picker"
/>
</template>
</InputField>
@@ -117,7 +118,7 @@ const customizingActive = computed(() => {
<InputField
id="absolute-stroke-width"
label="Absolute Stroke width"
label="Absolute stroke width"
>
<Switch
id="absolute-stroke-width"
@@ -143,6 +144,7 @@ const customizingActive = computed(() => {
font-size: 16px;
/* margin-bottom: 12px; */
}
.customizer-card {
background: var(--vp-c-bg);
padding: 12px 24px 24px;
@@ -151,7 +153,7 @@ const customizingActive = computed(() => {
position: relative;
z-index: 0;
border: 1px solid transparent;
transition: border-color .4s ease-in-out;
transition: border-color 0.4s ease-in-out;
}
.customizer-card.customized {

View File

@@ -14,7 +14,6 @@
margin-top: -32px;
width: 100%;
display: flex;
gap: 16px;
margin-bottom: 32px;
background: var(--vp-c-bg);
box-shadow: 0 16px 24px var(--vp-c-bg);

View File

@@ -1,221 +0,0 @@
<script setup lang="ts">
import { ref, computed } from 'vue';
import {
Combobox,
ComboboxInput,
ComboboxButton,
ComboboxOptions,
ComboboxOption,
} from '@headlessui/vue';
import { chevronsUpDown, check } from '../../../data/iconNodes';
import createLucideIcon from 'lucide-vue-next/src/createLucideIcon';
const model = defineModel<string | undefined>();
const props = defineProps<{
versions: string[];
}>();
let query = ref('');
let filteredVersions = computed(() =>
query.value === ''
? [...props.versions]
: props.versions.filter((version) =>
version
.toLowerCase()
.replace(/\s+/g, '')
.includes(query.value.toLowerCase().replace(/\s+/g, '')),
),
);
const emit = defineEmits(['focus']);
const ChevronUpDown = createLucideIcon('ChevronUpDown', chevronsUpDown);
const Check = createLucideIcon('Check', check);
</script>
<template>
<Combobox v-model="model">
<div class="combobox-container">
<div class="combobox-input-container">
<ComboboxInput
class="combobox-input"
placeholder="Latest version"
@change="query = $event.target.value"
@focus="emit('focus')"
/>
<ComboboxButton class="combobox-button">
<ChevronUpDown
class="icon-chevron"
aria-hidden="true"
/>
</ComboboxButton>
</div>
<ComboboxOptions class="combobox-options">
<div
v-if="versions.length === 0 && query !== ''"
class="combobox-no-results"
>
No match!
</div>
<ComboboxOption
v-for="version in filteredVersions"
as="template"
:key="version"
:value="version"
v-slot="{ selected, active }"
>
<li
class="combobox-option"
:class="{ active: active }"
>
<span
class="combobox-option-text"
:class="{ selected: selected }"
>
{{ version }}
</span>
<span
v-if="selected"
class="combobox-option-icon"
:class="{ active: active }"
>
<Check
class="icon-check"
aria-hidden="true"
/>
</span>
</li>
</ComboboxOption>
</ComboboxOptions>
</div>
</Combobox>
</template>
<style scoped>
.combobox-input-container {
position: relative;
width: 100%;
height: 48px;
min-width: 160px;
cursor: default;
overflow: hidden;
background-color: var(--vp-c-bg-alt);
text-align: left;
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
outline: none;
}
.combobox-input {
width: 100%;
border: none;
padding: 12px;
border-radius: 8px;
font-size: 0.875rem;
line-height: 1.25rem;
color: var(--vp-c-text-1);
border: 1px solid transparent;
transition: border-color 0.15s ease-in-out;
}
.combobox-input:hover,
.combobox-input:focus {
border-color: var(--vp-c-brand);
background: var(--vp-c-bg-alt);
}
.combobox-button {
position: absolute;
top: 4px;
padding: 9px 8px;
right: 0;
display: flex;
align-items: center;
padding-right: 0.5rem;
z-index: 10;
}
.icon-chevron {
height: 20px;
width: 20px;
color: #9ca3af;
}
.combobox-options {
position: absolute;
margin-top: 0.25rem;
width: 100%;
max-width: 160px;
padding: 12px;
min-width: 128px;
overflow-y: auto;
border-radius: 12px;
border: 1px solid var(--vp-c-divider);
background-color: var(--vp-c-bg-elv);
box-shadow: var(--vp-shadow-3);
transition: background-color 0.5s;
max-height: 240px;
outline: none;
right: 0;
}
.combobox-no-results {
position: relative;
cursor: default;
padding: 0.5rem 1rem;
color: #4b5563;
}
.combobox-option {
position: relative;
cursor: default;
padding: 2px 8px;
border-radius: 6px;
color: var(--vp-c-text-1);
line-height: 32px;
font-size: 14px;
font-weight: 500;
white-space: nowrap;
transition:
background-color 0.25s,
color 0.25s;
}
.combobox-option.active {
color: var(--vp-c-brand);
background-color: var(--vp-c-default-soft);
}
.combobox-option-text {
display: block;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.combobox-option-text.selected {
font-weight: 500;
}
.combobox-option-icon {
position: absolute;
right: 8px;
top: 8px;
display: flex;
align-items: center;
padding-left: 0.75rem;
color: var(--vp-c-brand) !important;
}
.combobox-option-icon.active {
color: var(--vp-c-brand) !important;
}
.icon-check {
height: 20px;
width: 20px;
}
</style>

View File

@@ -1,17 +0,0 @@
import { useFetch } from '@vueuse/core';
import { computed, Ref } from 'vue';
const useFetchVersionIcons = (version: Ref<string | undefined>) =>{
const fetchUrl = computed(() => {
if(version.value == null ) return ''
return `https://unpkg.com/lucide-static@${version.value}/icon-nodes.json`
})
return useFetch<Record<string, string>>(
fetchUrl,
{
refetch: true
}
).json();
}
export default useFetchVersionIcons;

View File

@@ -1,4 +1,4 @@
import { IconNode } from 'lucide-vue-next/src/createLucideIcon';
import { type IconNode } from 'lucide-vue-next/src/types';
import Vue from 'vue';
declare module '*.vue' {
@@ -20,5 +20,6 @@ declare module 'node:module' {
}
declare module '*.node.json' {
export default IconNode;
const value: IconNode;
export default value;
}

View File

@@ -102,10 +102,16 @@ The example below imports all ES Modules, so exercise caution when using it. Imp
### Icon Component Example
```jsx
import { icons } from 'lucide-react-native';
```tsx
import * as icons from 'lucide-react-native/icons';
const Icon = ({ name, color, size }) => {
interface IconProps {
name: keyof typeof icons;
color?: string;
size?: number;
}
const Icon = ({ name, color, size }: IconProps) => {
const LucideIcon = icons[name];
return <LucideIcon color={color} size={size} />;
@@ -116,11 +122,11 @@ export default Icon;
#### Using the Icon Component
```jsx
```tsx
import Icon from './Icon';
const App = () => {
return <Icon name="house" />;
return <Icon name="House" />;
};
export default App;

View File

@@ -9,14 +9,14 @@
"docs:build": "pnpm run /^prebuild:.*/ && vitepress build",
"docs:preview": "vitepress preview",
"build:docs": "vitepress build",
"prebuild:iconNodes": "node ./scripts/writeIconNodes.mts",
"prebuild:metaJson": "node ./scripts/writeIconMetaIndex.mts",
"prebuild:releaseJson": "node ./scripts/writeReleaseMetadata.mts",
"prebuild:categoriesJson": "node ./scripts/writeCategoriesMetadata.mts",
"prebuild:relatedIcons": "node ./scripts/writeIconRelatedIcons.mts",
"prebuild:iconDetails": "node ./scripts/writeIconDetails.mts",
"prebuild:brandStopwords": "node ./scripts/writeBrandStopwords.mts",
"postbuild:vercelJson": "node ./scripts/writeVercelOutput.mts",
"prebuild:iconNodes": "node ./scripts/writeIconNodes.mjs",
"prebuild:metaJson": "node ./scripts/writeIconMetaIndex.mjs",
"prebuild:releaseJson": "node ./scripts/writeReleaseMetadata.mjs",
"prebuild:categoriesJson": "node ./scripts/writeCategoriesMetadata.mjs",
"prebuild:relatedIcons": "node ./scripts/writeIconRelatedIcons.mjs",
"prebuild:iconDetails": "node ./scripts/writeIconDetails.mjs",
"prebuild:brandStopwords": "node ./scripts/writeBrandStopwords.mjs",
"postbuild:vercelJson": "node ./scripts/writeVercelOutput.mjs",
"dev": "npx nitropack dev",
"prebuild:api": "npx nitropack prepare",
"build:api": "npx nitropack build",

View File

@@ -42,7 +42,7 @@ const getRelatedIcons = (currentIcon, icons) => {
};
const iconsMetaDataPromises = svgFiles.map(async (iconName) => {
const metaDataFileContent = await fs.promises.readFile(`../icons/${iconName}`, 'utf-8');
const metaDataFileContent = await fs.promises.readFile(`../icons/${iconName}`);
const metaData = JSON.parse(metaDataFileContent);
const name = iconName.replace('.json', '');

View File

@@ -29,7 +29,7 @@ if (!fs.existsSync(releaseMetaDataDirectory)) {
fs.mkdirSync(releaseMetaDataDirectory);
}
export const fetchAllReleases = async () => {
const fetchAllReleases = async () => {
await git.fetch('https://github.com/lucide-icons/lucide.git', '--tags');
return Promise.all(
@@ -73,7 +73,7 @@ const comparisonsPromises = tags.map(async (tag, index) => {
const comparisons = await Promise.all(comparisonsPromises);
const newReleaseMetaData = {};
comparisons.forEach(({ tag, iconFiles, date } = {} as typeof comparisons[number]) => {
comparisons.forEach(({ tag, iconFiles, date } = {}) => {
if (tag == null) return;
iconFiles.forEach(({ status, file, renamedFile }) => {

View File

@@ -11,7 +11,7 @@ const iconMetaData = await getIconMetaData(path.resolve(scriptDir, '../../icons'
const iconAliasesRedirectRoutes = Object.entries(iconMetaData)
.filter(([, { aliases }]) => aliases?.length)
.map(([iconName, { aliases }]) => {
const aliasRouteMatches = aliases.map((alias) => typeof alias === 'string' ? alias : alias.name).join('|');
const aliasRouteMatches = aliases.map((alias) => alias.name).join('|');
return {
src: `/icons/${aliasRouteMatches}`,

14
icons/cannabis-off.json Normal file
View File

@@ -0,0 +1,14 @@
{
"$schema": "../icon.schema.json",
"contributors": [
"nickveles"
],
"tags": [
"cannabis",
"weed",
"leaf"
],
"categories": [
"nature"
]
}

18
icons/cannabis-off.svg Normal file
View File

@@ -0,0 +1,18 @@
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M12 22v-4c1.5 1.5 3.5 3 6 3 0-1.5-.5-3.5-2-5" />
<path d="M13.988 8.327C13.902 6.054 13.365 3.82 12 2a9.3 9.3 0 0 0-1.445 2.9" />
<path d="M17.375 11.725C18.882 10.53 21 7.841 21 6c-2.324 0-5.08 1.296-6.662 2.684" />
<path d="m2 2 20 20" />
<path d="M21.024 15.378A15 15 0 0 0 22 15c-.426-1.279-2.67-2.557-4.25-2.907" />
<path d="M6.995 6.992C5.714 6.4 4.29 6 3 6c0 2 2.5 5 4 6-1.5 0-4.5 1.5-5 3 3.5 1.5 6 1 6 1-1.5 1.5-2 3.5-2 5 2.5 0 4.5-1.5 6-3" />
</svg>

After

Width:  |  Height:  |  Size: 681 B

View File

@@ -9,8 +9,8 @@
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M19 12H2" />
<path d="M11 7 6 2" />
<path d="M18.992 12H2.041" />
<path d="M21.145 18.38A3.34 3.34 0 0 1 20 16.5a3.3 3.3 0 0 1-1.145 1.88c-.575.46-.855 1.02-.855 1.595A2 2 0 0 0 20 22a2 2 0 0 0 2-2.025c0-.58-.285-1.13-.855-1.595" />
<path d="m6 2 5 5" />
<path d="m8.5 4.5 2.148-2.148a1.205 1.205 0 0 1 1.704 0l7.296 7.296a1.205 1.205 0 0 1 0 1.704l-7.592 7.592a3.615 3.615 0 0 1-5.112 0l-3.888-3.888a3.615 3.615 0 0 1 0-5.112L5.67 7.33" />
</svg>

Before

Width:  |  Height:  |  Size: 613 B

After

Width:  |  Height:  |  Size: 622 B

24
icons/stone.json Normal file
View File

@@ -0,0 +1,24 @@
{
"$schema": "../icon.schema.json",
"contributors": [
"Alportan",
"karsa-mistmere"
],
"tags": [
"mineral",
"geology",
"nature",
"solid",
"pebble",
"crystal",
"ore",
"hard",
"coal",
"stone",
"rock",
"boulder"
],
"categories": [
"nature"
]
}

15
icons/stone.svg Normal file
View File

@@ -0,0 +1,15 @@
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M11.264 2.205A4 4 0 0 0 6.42 4.211l-4 8a4 4 0 0 0 1.359 5.117l6 4a4 4 0 0 0 4.438 0l6-4a4 4 0 0 0 1.576-4.592l-2-6a4 4 0 0 0-2.53-2.53z" />
<path d="M11.99 22 14 12l7.822 3.184" />
<path d="M14 12 8.47 2.302" />
</svg>

After

Width:  |  Height:  |  Size: 435 B

37
icons/toolbox.json Normal file
View File

@@ -0,0 +1,37 @@
{
"$schema": "../icon.schema.json",
"contributors": [
"karsa-mistmere"
],
"tags": [
"toolkit",
"tools",
"trunk",
"chest",
"box",
"storage",
"utility",
"utilities",
"container",
"kit",
"set",
"repair",
"fix",
"service",
"maintenance",
"mechanic",
"workshop",
"construction",
"hardware",
"equipment",
"gear",
"handyman",
"engineering",
"craft",
"diy"
],
"categories": [
"tools",
"home"
]
}

17
icons/toolbox.svg Normal file
View File

@@ -0,0 +1,17 @@
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M16 12v4" />
<path d="M16 6a2 2 0 0 1 1.414.586l4 4A2 2 0 0 1 22 12v7a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2v-7a2 2 0 0 1 .586-1.414l4-4A2 2 0 0 1 8 6z" />
<path d="M16 6V4a2 2 0 0 0-2-2h-4a2 2 0 0 0-2 2v2" />
<path d="M2 14h20" />
<path d="M8 12v4" />
</svg>

After

Width:  |  Height:  |  Size: 471 B

View File

@@ -24,11 +24,23 @@
"author": "Eric Fennis",
"amdName": "lucide-react-native",
"main": "dist/cjs/lucide-react-native.js",
"main:umd": "dist/umd/lucide-react-native.js",
"module": "dist/esm/lucide-react-native.js",
"unpkg": "dist/umd/lucide-react-native.min.js",
"typings": "dist/lucide-react-native.d.ts",
"react-native": "dist/esm/lucide-react-native.js",
"exports": {
".": {
"types": "./dist/lucide-react-native.d.ts",
"import": "./dist/esm/lucide-react-native.js",
"browser": "./dist/esm/lucide-react-native.js",
"require": "./dist/cjs/lucide-react-native.js"
},
"./icons": {
"types": "./dist/icons.d.ts",
"import": "./dist/esm/icons/index.js",
"browser": "./dist/esm/icons/index.js",
"require": "./dist/cjs/icons/index.js"
}
},
"sideEffects": false,
"files": [
"dist"

View File

@@ -5,7 +5,7 @@ import pkg from './package.json' with { type: 'json' };
const packageName = 'LucideReact';
const outputFileName = 'lucide-react-native';
const outputDir = 'dist';
const inputs = ['src/lucide-react-native.ts'];
const inputs = ['src/lucide-react-native.ts', 'src/icons/index.ts'];
const bundles = [
{
format: 'cjs',
@@ -60,6 +60,16 @@ export default [
],
plugins: [dts()],
},
{
input: inputs[1],
output: [
{
file: `dist/icons.d.ts`,
format: 'es',
},
],
plugins: [dts()],
},
{
input: `src/${outputFileName}.suffixed.ts`,
output: [

View File

@@ -31,6 +31,7 @@ const Icon = forwardRef<SVGSVGElement, IconComponentProps>(
absoluteStrokeWidth,
children,
iconNode,
className,
...rest
},
ref,
@@ -46,6 +47,7 @@ const Icon = forwardRef<SVGSVGElement, IconComponentProps>(
{
ref,
...defaultAttributes,
className,
width: size,
height: size,
...customAttrs,

View File

@@ -1,5 +1,4 @@
export * from './icons';
export * as icons from './icons';
export * from './aliases/prefixed';
export * from './types';

View File

@@ -1,5 +1,4 @@
export * from './icons';
export * as icons from './icons';
export * from './aliases/suffixed';
export * from './types';

View File

@@ -1,5 +1,4 @@
export * from './icons';
export * as icons from './icons';
export * from './aliases';
export * from './types';

9796
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff