Skip to content

Commit

Permalink
Merge branch 'main' into fix/release-tags
Browse files Browse the repository at this point in the history
  • Loading branch information
triphora authored Oct 15, 2023
2 parents 56b4313 + 950160a commit 175c18c
Show file tree
Hide file tree
Showing 34 changed files with 412 additions and 532 deletions.
11 changes: 0 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ Lucide is trying to expand the icon set as much as possible while staying faithf
- [Static (svg sprite, font, icons ..)](#static-svg-sprite-font-icons-)
- [Figma](#figma)
- [Laravel](#laravel)
- [Flutter](#flutter)
- [Svelte](#svelte)
- [Solid](#solid)
- [Hyva](#hyva)
Expand Down Expand Up @@ -200,16 +199,6 @@ composer require mallardduck/blade-lucide-icons

For more details, see the [documentation](https://github.com/mallardduck/blade-lucide-icons/blob/main/README.md).

### Flutter

Implementation of Lucide icon library for Flutter applications.

```sh
flutter pub add lucide_icons
```

For more details, see the [pub.dev](https://pub.dev/packages/lucide_icons).

### Svelte

Implementation of the lucide icon library for Svelte applications.
Expand Down
47 changes: 25 additions & 22 deletions docs/.vitepress/api/gh-icon/[...data].get.ts
Original file line number Diff line number Diff line change
@@ -1,41 +1,44 @@
import { eventHandler, setResponseHeader, defaultContentType } from 'h3'
import { renderToString, renderToStaticMarkup } from 'react-dom/server'
import { createElement } from 'react'
import { eventHandler, setResponseHeader, defaultContentType } from 'h3';
import { renderToString, renderToStaticMarkup } from 'react-dom/server';
import { createElement } from 'react';
import SvgPreview from '../../lib/SvgPreview/index.tsx';
import iconNodes from '../../data/iconNodes'
import createLucideIcon from 'lucide-react/src/createLucideIcon'
import iconNodes from '../../data/iconNodes';
import createLucideIcon from 'lucide-react/src/createLucideIcon';
import Backdrop from '../../lib/SvgPreview/Backdrop.tsx';

export default eventHandler((event) => {
const { params } = event.context
const { params } = event.context;

const [name, svgData] = params.data.split('/');
const data = svgData.slice(0, -4);
const pathData = params.data.split('/');
const data = pathData.at(-1).slice(0, -4);
const [name] = pathData;

const src = Buffer.from(data, 'base64').toString('utf8');

const children = []
const children = [];

if (name in iconNodes) {
const iconNode = iconNodes[name]
// If the icon already exists, it uses the existing icon as the backdrop.
// If the icon does not exist but an icon exists that starts with the same group name, that icon
// is used as the backdrop
const backdropName =
name in iconNodes ? name : name.split('-')[0] in iconNodes ? name.split('-')[0] : null;
if (backdropName) {
const iconNode = iconNodes[backdropName];

const LucideIcon = createLucideIcon(name, iconNode)
const svg = renderToStaticMarkup(createElement(LucideIcon))
const LucideIcon = createLucideIcon(backdropName, iconNode);
const svg = renderToStaticMarkup(createElement(LucideIcon));
const backdropString = svg.replace(/<svg[^>]*>|<\/svg>/g, '');

children.push(createElement(Backdrop, { backdropString, src }))
children.push(createElement(Backdrop, { backdropString, src }));
}

const svg = Buffer.from(
// We can't use jsx here, is not supported here by nitro.
renderToString(createElement(SvgPreview, {src, showGrid: true}, children)).replace(
/>/,
'><style>@media screen and (prefers-color-scheme: dark) { svg { stroke: #fff } }</style>'
)
renderToString(createElement(SvgPreview, { src, showGrid: true }, children))
).toString('utf8');

defaultContentType(event, 'image/svg+xml')
setResponseHeader(event, 'Cache-Control', 'public,max-age=31536000')
defaultContentType(event, 'image/svg+xml');
setResponseHeader(event, 'Cache-Control', 'public,max-age=31536000');

return svg
})
return svg;
});
117 changes: 56 additions & 61 deletions docs/.vitepress/theme/components/icons/IconsCategoryOverview.vue
Original file line number Diff line number Diff line change
@@ -1,93 +1,92 @@
<script setup lang="ts">
import { ref, computed, defineAsyncComponent } from 'vue'
import type { IconEntity, Category } from '../../types'
import useSearch from '../../composables/useSearch'
import InputSearch from '../base/InputSearch.vue'
import useSearchInput from '../../composables/useSearchInput'
import StickyBar from './StickyBar.vue'
import IconsCategory from './IconsCategory.vue'
import { useFetch } from '@vueuse/core'
import useFetchTags from '../../composables/useFetchTags'
import useFetchCategories from '../../composables/useFetchCategories'
import { ref, computed, defineAsyncComponent } from 'vue';
import type { IconEntity, Category } from '../../types';
import useSearch from '../../composables/useSearch';
import InputSearch from '../base/InputSearch.vue';
import useSearchInput from '../../composables/useSearchInput';
import StickyBar from './StickyBar.vue';
import IconsCategory from './IconsCategory.vue';
import { useFetch } from '@vueuse/core';
import useFetchTags from '../../composables/useFetchTags';
import useFetchCategories from '../../composables/useFetchCategories';
const props = defineProps<{
icons: IconEntity[]
categories: Category[]
iconCategories: Record<string, string[]>
}>()
icons: IconEntity[];
categories: Category[];
iconCategories: Record<string, string[]>;
}>();
const activeIconName = ref(null)
const { searchInput, searchQuery, searchQueryThrottled } = useSearchInput()
const activeIconName = ref(null);
const { searchInput, searchQuery, searchQueryDebounced } = useSearchInput();
const isSearching = computed(() => !!searchQuery.value)
const isSearching = computed(() => !!searchQuery.value);
function setActiveIconName(name: string) {
activeIconName.value = name
activeIconName.value = name;
}
const { execute: fetchTags, data: tags } = useFetchTags()
const { execute: fetchCategories, data: categoriesMap } = useFetchCategories()
const { execute: fetchTags, data: tags } = useFetchTags();
const { execute: fetchCategories, data: categoriesMap } = useFetchCategories();
const mappedIcons = computed(() => {
if(tags.value == null) {
return props.icons
if (tags.value == null) {
return props.icons;
}
return props.icons.map((icon) => {
const iconTags = tags.value[icon.name]
const iconCategories = categoriesMap.value?.[icon.name] ?? []
const iconTags = tags.value[icon.name];
const iconCategories = categoriesMap.value?.[icon.name] ?? [];
return {
...icon,
tags: iconTags,
categories: iconCategories,
}
})
})
};
});
});
const searchResults = useSearch(searchQuery, mappedIcons, [
{ name: 'name', weight: 2 },
{ name: 'tags', weight: 1 },
])
]);
const categories = computed(() => {
if( !props.categories?.length || !props.icons?.length ) return []
return props.categories.map(({ name, title }) => {
const categoryIcons = props.icons.filter((icon) => {
const iconCategories = props.iconCategories[icon.name]
return iconCategories?.includes(name)
if (!props.categories?.length || !props.icons?.length) return [];
return props.categories
.map(({ name, title }) => {
const categoryIcons = props.icons.filter((icon) => {
const iconCategories = props.iconCategories[icon.name];
return iconCategories?.includes(name);
});
const searchedCategoryIcons = isSearching
? categoryIcons.filter((icon) =>
searchResults.value.some((item) => item?.name === icon?.name)
)
: categoryIcons;
return {
title,
name,
icons: searchedCategoryIcons,
};
})
const searchedCategoryIcons = isSearching
? categoryIcons.filter(icon => searchResults.value.some((item) => item?.name === icon?.name))
: categoryIcons;
return {
title,
name,
icons: searchedCategoryIcons,
};
})
.filter(({ icons }) => icons.length)
})
.filter(({ icons }) => icons.length);
});
function onFocusSearchInput() {
if (tags.value == null) {
fetchTags()
fetchTags();
}
if (categoriesMap.value == null) {
fetchCategories()
fetchCategories();
}
}
const NoResults = defineAsyncComponent(() =>
import('./NoResults.vue')
)
const NoResults = defineAsyncComponent(() => import('./NoResults.vue'));
const IconDetailOverlay = defineAsyncComponent(() =>
import('./IconDetailOverlay.vue')
)
const IconDetailOverlay = defineAsyncComponent(() => import('./IconDetailOverlay.vue'));
</script>

<template>
Expand All @@ -100,11 +99,7 @@ const IconDetailOverlay = defineAsyncComponent(() =>
@focus="onFocusSearchInput"
/>
</StickyBar>
<NoResults
v-if="categories.length === 0"
:searchQuery="searchQuery"
@clear="searchQuery = ''"
/>
<NoResults v-if="categories.length === 0" :searchQuery="searchQuery" @clear="searchQuery = ''" />
<IconsCategory
v-for="category in categories"
:key="category.name"
Expand Down
Loading

0 comments on commit 175c18c

Please sign in to comment.