Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4b38ad99c8 | ||
|
|
078a0b2339 | ||
|
|
5d78605650 | ||
|
|
ab61fa277b | ||
|
|
bb1329e512 | ||
|
|
b5b5d95933 | ||
|
|
7b589f2b5c | ||
|
|
2d36863568 | ||
|
|
7291cbcc0f | ||
|
|
4c663b9a32 | ||
|
|
63369b1ac0 | ||
|
|
f07465f82e | ||
|
|
60d583ce4e | ||
|
|
5828ecb38f | ||
|
|
031b226ac6 | ||
|
|
35d535a477 | ||
|
|
8930dfa827 | ||
|
|
c67c9bdbfb | ||
|
|
52d7c549c3 | ||
|
|
9cb4e49849 | ||
|
|
f59db07ef9 | ||
|
|
46bcf1fa89 | ||
|
|
7d15e8466a | ||
|
|
ce2d598d96 | ||
|
|
627b4c1672 | ||
|
|
ee02505468 | ||
|
|
7c8fbb4813 | ||
|
|
7e938845f0 | ||
|
|
0d6c47d545 | ||
|
|
2f5af2ceb5 | ||
|
|
448bcc90fe | ||
|
|
2fed527c00 | ||
|
|
8fc6b70aa5 | ||
|
|
cf0e1e44ba | ||
|
|
65ef069acc | ||
|
|
7983b2a262 | ||
|
|
7ddb1e237d | ||
|
|
5ff536e139 | ||
|
|
bb7d2d9839 | ||
|
|
fc20eb6c7a | ||
|
|
d850228c3c | ||
|
|
f6cef23cd7 | ||
|
|
766c98af22 | ||
|
|
1f0f070e84 | ||
|
|
a90271b282 | ||
|
|
c81680e066 | ||
|
|
0c57f7265a | ||
|
|
f917f247e3 | ||
|
|
aef0f98a68 | ||
|
|
6e5c250af0 | ||
|
|
f37f235d78 | ||
|
|
b973e42174 | ||
|
|
ce6fb3dd6c | ||
|
|
c3262987be | ||
|
|
52ee7b3692 | ||
|
|
04ee825d6b | ||
|
|
0241b57c35 | ||
|
|
24dd855b87 | ||
|
|
4e5fce4adc | ||
|
|
ae94b5118b | ||
|
|
2dd4be802a | ||
|
|
f4fa0512d3 | ||
|
|
d1150cea7a | ||
|
|
4afccc1842 | ||
|
|
4e161a15ef | ||
|
|
76175250cd | ||
|
|
2e58e319e7 | ||
|
|
283e4b2805 | ||
|
|
db63e66333 | ||
|
|
4b3521a3e3 |
@@ -1,4 +1,4 @@
|
||||
name: Pull request tags suggestions
|
||||
name: Pull request metadata suggestions
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
@@ -6,8 +6,8 @@ on:
|
||||
- 'icons/*.json'
|
||||
|
||||
jobs:
|
||||
pull-request-tags-suggestions:
|
||||
name: Pull Request Tags Suggestions
|
||||
pull-request-metadata-suggestions:
|
||||
name: Pull Request Metadata Suggestions
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
@@ -29,7 +29,7 @@ jobs:
|
||||
run: pnpm install --frozen-lockfile
|
||||
|
||||
- name: Generate comment markup
|
||||
run: node ./scripts/suggestTags.mts
|
||||
run: node ./scripts/suggestMetaData.mts
|
||||
env:
|
||||
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
|
||||
PULL_REQUEST_NUMBER: ${{ github.event.number }}
|
||||
@@ -20,9 +20,6 @@ permissions:
|
||||
id-token: write # Required for OIDC
|
||||
contents: write
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
|
||||
jobs:
|
||||
prepare:
|
||||
if: github.repository == 'lucide-icons/lucide' && contains('["ericfennis", "karsa-mistmere", "jguddas"]', github.actor)
|
||||
@@ -74,7 +71,7 @@ jobs:
|
||||
run: pnpm install --frozen-lockfile
|
||||
|
||||
- name: Set new version
|
||||
run: pnpm --fail-if-no-match --filter ${{ matrix.package }} version --new-version ${{ needs.prepare.outputs.VERSION }} --no-git-tag-version
|
||||
run: pnpm version ${{ needs.prepare.outputs.VERSION }} --filter ${{ matrix.package }} --fail-if-no-match --no-git-tag-version
|
||||
|
||||
- name: Build
|
||||
run: pnpm --filter ${{ matrix.package }} build
|
||||
@@ -108,7 +105,7 @@ jobs:
|
||||
run: pnpm install --frozen-lockfile
|
||||
|
||||
- name: Set new version
|
||||
run: pnpm --filter lucide-static version --new-version ${{ needs.prepare.outputs.VERSION }} --no-git-tag-version
|
||||
run: pnpm version ${{ needs.prepare.outputs.VERSION }} --filter lucide-static --no-git-tag-version
|
||||
|
||||
- name: Move Font
|
||||
run: cp -r lucide-font packages/lucide-static/font
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
name: Weekly Repo Report
|
||||
on:
|
||||
workflow_dispatch:
|
||||
# Run this workflow every Monday at 07:00 UTC
|
||||
schedule:
|
||||
- cron: '0 7 * * 1'
|
||||
permissions:
|
||||
contents: read
|
||||
jobs:
|
||||
weekly-summary:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Set up Node.js environment
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 24
|
||||
|
||||
- name: Install Copilot CLI
|
||||
run: npm install -g @github/copilot
|
||||
|
||||
- name: Run the prompt
|
||||
env:
|
||||
COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
|
||||
run: |
|
||||
copilot -p "${{ vars.REPO_REPORT_PROMPT }} Write the details to summary.md" --allow-tool='shell(git:*)' --allow-tool=write --no-ask-user
|
||||
cat summary.md >> "$GITHUB_STEP_SUMMARY"
|
||||
|
||||
- name: Post report to Discord (private channel)
|
||||
env:
|
||||
DISCORD_WEBHOOK_URL: ${{ secrets.LUCIDE_DISCORD_WEBHOOK }}
|
||||
run: |
|
||||
jq -Rs '{
|
||||
embeds: [{
|
||||
title: "📊 Weekly Repo Report",
|
||||
description: (.[0:4096]),
|
||||
color: 5814783
|
||||
}]
|
||||
}' summary.md > payload.json
|
||||
curl -sS --fail -X POST \
|
||||
-H "Content-Type: application/json" \
|
||||
-d @payload.json \
|
||||
"$DISCORD_WEBHOOK_URL"
|
||||
@@ -53,6 +53,7 @@ docs/.vitepress/data/categoriesData.json
|
||||
docs/.vitepress/data/iconDetails
|
||||
docs/.vitepress/data/relatedIcons.json
|
||||
docs/.vitepress/data/brandStopwords.json
|
||||
docs/.vitepress/data/iconPopularity
|
||||
docs/.vercel
|
||||
docs/.nitro
|
||||
docs/public/og/**
|
||||
|
||||
@@ -35,7 +35,7 @@ Lucide is an open-source icon library that provides 1600+ vector (svg) files for
|
||||
| <img src="https://lucide.dev/framework-logos/js.svg" alt="JS logo" width="48"> | **`lucide`** | [](https://www.npmjs.com/package/lucide) |  | [Docs](https://lucide.dev/guide/lucide) · [Source](./packages/lucide) |
|
||||
| <img src="https://lucide.dev/framework-logos/react.svg" alt="React logo" width="48"> | **`lucide-react`** | [](https://www.npmjs.com/package/lucide-react) |  | [Docs](https://lucide.dev/guide/react) · [Source](./packages/lucide-react) |
|
||||
| <img src="https://lucide.dev/framework-logos/vue.svg" alt="Vue logo" width="48"> | **`@lucide/vue`** | [](https://www.npmjs.com/package/@lucide/vue) |  | [Docs](https://lucide.dev/guide/vue) · [Source](./packages/vue) |
|
||||
| <img src="https://lucide.dev/framework-logos/svelte.svg" alt="Svelte logo" width="48"> | **`@lucide/svelte`** | [](https://www.npmjs.com/package/@lucide/svelte) |  | [Docs](https://lucide.dev/guide/svelte) · [Source](./packages/@lucide/svelte) |
|
||||
| <img src="https://lucide.dev/framework-logos/svelte.svg" alt="Svelte logo" width="48"> | **`@lucide/svelte`** | [](https://www.npmjs.com/package/@lucide/svelte) |  | [Docs](https://lucide.dev/guide/svelte) · [Source](./packages/svelte) |
|
||||
| <img src="https://lucide.dev/framework-logos/solid.svg" alt="Solid logo" width="48"> | **`lucide-solid`** | [](https://www.npmjs.com/package/lucide-solid) |  | [Docs](https://lucide.dev/guide/solid) · [Source](./packages/lucide-solid) |
|
||||
| <img src="https://lucide.dev/framework-logos/preact.svg" alt="Preact logo" width="48"> | **`lucide-preact`** | [](https://www.npmjs.com/package/lucide-preact) |  | [Docs](https://lucide.dev/guide/preact) · [Source](./packages/lucide-preact) |
|
||||
| <img src="https://lucide.dev/framework-logos/react-native.svg" alt="React Native logo" width="48"> | **`lucide-react-native`** | [](https://www.npmjs.com/package/lucide-react-native) |  | [Docs](https://lucide.dev/guide/react-native) · [Source](./packages/lucide-react-native) |
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"$schema": "../category.schema.json",
|
||||
"title": "Navigation, Maps, and POIs",
|
||||
"title": "Navigation & Places",
|
||||
"icon": "compass"
|
||||
}
|
||||
|
||||
@@ -101,6 +101,7 @@ export default defineConfig({
|
||||
},
|
||||
{ text: 'Packages', link: '/packages' },
|
||||
{ text: 'Showcase', link: '/showcase' },
|
||||
{ text: 'Merch', link: 'https://merch.lucide.dev/' },
|
||||
],
|
||||
sidebar,
|
||||
socialLinks: [
|
||||
@@ -109,7 +110,7 @@ export default defineConfig({
|
||||
],
|
||||
footer: {
|
||||
message: 'Released under the ISC License.',
|
||||
copyright: `Copyright © ${new Date().getFullYear()} Lucide Contributors`,
|
||||
copyright: `Copyright © ${new Date().getFullYear()} Lucide Icons`,
|
||||
},
|
||||
editLink: {
|
||||
pattern: 'https://github.com/lucide-icons/lucide/edit/main/docs/:path',
|
||||
|
||||
@@ -97,7 +97,7 @@
|
||||
},
|
||||
{
|
||||
"name": "navigation",
|
||||
"title": "Navigation, Maps, and POIs"
|
||||
"title": "Navigation & Places"
|
||||
},
|
||||
{
|
||||
"name": "notifications",
|
||||
|
||||
@@ -209,5 +209,24 @@
|
||||
],
|
||||
"source": "https://github.com/shx08/strapi-lucide-icons",
|
||||
"documentation": "https://github.com/shx08/strapi-lucide-icons/blob/main/README.md"
|
||||
},
|
||||
{
|
||||
"name": "lucide-lit",
|
||||
"description": "Implementation of Lucide icons as Lit web components.",
|
||||
"icon": "/framework-logos/lit.svg",
|
||||
"shields": [
|
||||
{
|
||||
"alt": "Latest Stable Version",
|
||||
"src": "https://img.shields.io/npm/v/@gyeonghokim/lucide-lit",
|
||||
"href": "https://www.npmjs.com/package/@gyeonghokim/lucide-lit"
|
||||
},
|
||||
{
|
||||
"alt": "Total Downloads",
|
||||
"src": "https://img.shields.io/npm/dw/@gyeonghokim/lucide-lit",
|
||||
"href": "https://www.npmjs.com/package/@gyeonghokim/lucide-lit"
|
||||
}
|
||||
],
|
||||
"source": "https://github.com/GyeongHoKim/lucide-lit",
|
||||
"documentation": "https://github.com/GyeongHoKim/lucide-lit/blob/main/README.md"
|
||||
}
|
||||
]
|
||||
|
||||
@@ -24,13 +24,6 @@ const getHeadConfig = ({
|
||||
defer: '',
|
||||
},
|
||||
],
|
||||
[
|
||||
'script',
|
||||
{
|
||||
src: 'https://media.bitterbrains.com/main.js?from=LUCIDE&type=top',
|
||||
async: 'true',
|
||||
},
|
||||
],
|
||||
[
|
||||
'meta',
|
||||
{
|
||||
|
||||
@@ -72,6 +72,11 @@ export const reactNativeSidebar = [
|
||||
link: '/guide/react-native/advanced/combining-icons',
|
||||
desc: 'Combine multiple icons into one',
|
||||
},
|
||||
{
|
||||
text: 'Optimizations',
|
||||
link: '/guide/react-native/advanced/optimizations',
|
||||
desc: 'Optimizing your app for performance',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
|
||||
@@ -11,6 +11,14 @@ const { isDark } = useData();
|
||||
|
||||
const emit = defineEmits(['update:modelValue']);
|
||||
|
||||
function limitHexInput(val: string) {
|
||||
if (val.startsWith('#')) {
|
||||
return val.slice(0, 9);
|
||||
}
|
||||
|
||||
return val.slice(0, 8);
|
||||
}
|
||||
|
||||
const value = computed({
|
||||
get: () => {
|
||||
if (props.modelValue == null || props.modelValue === 'currentColor') {
|
||||
@@ -19,7 +27,7 @@ const value = computed({
|
||||
|
||||
return props.modelValue;
|
||||
},
|
||||
set: (val) => emit('update:modelValue', val),
|
||||
set: (val) => emit('update:modelValue', limitHexInput(val)),
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -41,6 +49,7 @@ const value = computed({
|
||||
class="color-input-text"
|
||||
aria-label="Color picker input"
|
||||
v-model="value"
|
||||
maxlength="9"
|
||||
placeholder="[default]"
|
||||
/>
|
||||
</div>
|
||||
@@ -91,6 +100,7 @@ const value = computed({
|
||||
background: transparent;
|
||||
color: var(--vp-c-text-1);
|
||||
font-size: 13px;
|
||||
font-family: var(--vp-font-family-mono);
|
||||
text-align: left;
|
||||
border-radius: 8px;
|
||||
cursor: text;
|
||||
|
||||
@@ -6,10 +6,10 @@ import SelectIcon from './SelectIcon.vue';
|
||||
|
||||
defineProps<{
|
||||
id?: string;
|
||||
items?: { name: string; route: string; icon: string; iconDark?: string }[];
|
||||
items?: { name: string; value: string; icon?: string; iconDark?: string }[];
|
||||
}>();
|
||||
|
||||
const selected = defineModel<{ name: string; icon: string; iconDark?: string }>();
|
||||
const selected = defineModel<{ name: string; value: string; icon?: string; iconDark?: string }>();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -19,14 +19,18 @@ const selected = defineModel<{ name: string; icon: string; iconDark?: string }>(
|
||||
class="select-button"
|
||||
:id="id"
|
||||
>
|
||||
<SelectIcon :item="selected" />
|
||||
<slot name="start-icon">
|
||||
<SelectIcon v-if="selected.icon" :item="selected" />
|
||||
</slot>
|
||||
<span class="select-text">{{ selected.name }}</span>
|
||||
<span class="select-icon">
|
||||
<Icon
|
||||
:iconNode="chevronsUpDown"
|
||||
class="chevron-icon"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
<slot name="end-icon">
|
||||
<Icon
|
||||
:iconNode="chevronsUpDown"
|
||||
class="chevron-icon"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
</slot>
|
||||
</span>
|
||||
</ListboxButton>
|
||||
|
||||
@@ -43,8 +47,9 @@ const selected = defineModel<{ name: string; icon: string; iconDark?: string }>(
|
||||
:value="item"
|
||||
as="template"
|
||||
>
|
||||
|
||||
<li :class="['select-option', { active, selected }]">
|
||||
<SelectIcon :item="item" />
|
||||
<SelectIcon v-if="item.icon" :item="item" />
|
||||
<span :class="['option-text', { selected }]">{{ item.name }}</span>
|
||||
<span
|
||||
v-if="selected"
|
||||
|
||||
@@ -2,25 +2,28 @@
|
||||
const { item } = defineProps<{
|
||||
item: {
|
||||
name: string;
|
||||
icon: string;
|
||||
icon?: string;
|
||||
iconDark?: string;
|
||||
};
|
||||
}>();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<img
|
||||
:src="item.icon"
|
||||
:class="{ 'select-item-icon': true, light: item.iconDark }"
|
||||
:alt="`${item.name} logo`"
|
||||
loading="lazy"
|
||||
/>
|
||||
<img
|
||||
v-if="item.iconDark"
|
||||
:src="item.iconDark"
|
||||
:alt="`${item.name} logo`"
|
||||
class="select-item-icon dark"
|
||||
/>
|
||||
<div v-if="item.icon || item.iconDark">
|
||||
<img
|
||||
v-if="item.icon"
|
||||
:src="item.icon"
|
||||
:class="{ 'select-item-icon': true, light: item.iconDark }"
|
||||
:alt="`${item.name} logo`"
|
||||
loading="lazy"
|
||||
/>
|
||||
<img
|
||||
v-if="item.iconDark"
|
||||
:src="item.iconDark"
|
||||
:alt="`${item.name} logo`"
|
||||
class="select-item-icon dark"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
@@ -1,90 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
import { useRouter } from 'vitepress';
|
||||
import { computed } from 'vue';
|
||||
|
||||
const router = useRouter();
|
||||
|
||||
const frameworks = [
|
||||
{
|
||||
ariaLabel: 'Get JavaScript certificates from certificates.dev',
|
||||
image: '/certificates-dev/js-certificates-dev.jpg',
|
||||
href: 'https://certificates.dev/javascript?friend=LUCIDE',
|
||||
routes: [
|
||||
'/guide/lucide/',
|
||||
'/guide/svelte/',
|
||||
'/guide/solid/',
|
||||
'/guide/astro/',
|
||||
'/guide/static/'
|
||||
],
|
||||
},
|
||||
{
|
||||
ariaLabel: 'Get React certificates from certificates.dev',
|
||||
image: '/certificates-dev/react-certificates-dev.jpg',
|
||||
href: 'https://certificates.dev/react?friend=LUCIDE',
|
||||
routes: [
|
||||
'/guide/react/',
|
||||
'/guide/react-native/',
|
||||
'/guide/preact/',
|
||||
],
|
||||
},
|
||||
{
|
||||
ariaLabel: 'Get Vue certificates from certificates.dev',
|
||||
href: 'https://certificates.dev/vuejs?friend=LUCIDE',
|
||||
image: '/certificates-dev/vue-certificates-dev.jpg',
|
||||
routes: [
|
||||
'/guide/vue/',
|
||||
],
|
||||
},
|
||||
{
|
||||
ariaLabel: 'Get Angular certificates from certificates.dev',
|
||||
href: 'https://certificates.dev/angular?friend=LUCIDE',
|
||||
image: '/certificates-dev/angular-certificates-dev.jpg',
|
||||
routes: [
|
||||
'/guide/angular/',
|
||||
],
|
||||
}
|
||||
];
|
||||
|
||||
const selected = computed(() => {
|
||||
const current = frameworks.find(({ routes }) => {
|
||||
return routes.some(route => router.route.path.startsWith(route));
|
||||
});
|
||||
|
||||
return current || frameworks[0];
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<a class="certificates-link" :href="selected.href" :aria-label="selected.ariaLabel" target="_blank" rel="noopener noreferrer">
|
||||
<img :src="selected.image" :alt="selected.ariaLabel" />
|
||||
</a>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.certificates-link {
|
||||
/* padding: 20px; */
|
||||
border-radius: 12px;
|
||||
min-height: 100px;
|
||||
text-align: center;
|
||||
line-height: 18px;
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
background-color: var(--vp-carbon-ads-bg-color);
|
||||
margin-bottom: 20px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.certificates-link img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
max-width: 100%;
|
||||
border-radius: 6px;
|
||||
transition: transform 0.3s ease, opacity 0.3s ease;
|
||||
}
|
||||
|
||||
.certificates-link:hover img {
|
||||
transform: scale(1.05);
|
||||
opacity: 0.9;
|
||||
|
||||
}
|
||||
</style>
|
||||
@@ -11,49 +11,49 @@ const { page } = useData();
|
||||
const router = useRouter();
|
||||
|
||||
const frameworks = [
|
||||
{ name: 'Vanilla', icon: '/framework-logos/js.svg', route: '/guide/lucide/' },
|
||||
{ name: 'React', icon: '/framework-logos/react.svg', route: '/guide/react/' },
|
||||
{ name: 'Vue', icon: '/framework-logos/vue.svg', route: '/guide/vue/' },
|
||||
{ name: 'Svelte', icon: '/framework-logos/svelte.svg', route: '/guide/svelte/' },
|
||||
{ name: 'Solid', icon: '/framework-logos/solid.svg', route: '/guide/solid/' },
|
||||
{ name: 'Angular', icon: '/framework-logos/angular.svg', route: '/guide/angular/' },
|
||||
{ name: 'Preact', icon: '/framework-logos/preact.svg', route: '/guide/preact/' },
|
||||
{ name: 'Vanilla', icon: '/framework-logos/js.svg', value: '/guide/lucide/' },
|
||||
{ name: 'React', icon: '/framework-logos/react.svg', value: '/guide/react/' },
|
||||
{ name: 'Vue', icon: '/framework-logos/vue.svg', value: '/guide/vue/' },
|
||||
{ name: 'Svelte', icon: '/framework-logos/svelte.svg', value: '/guide/svelte/' },
|
||||
{ name: 'Solid', icon: '/framework-logos/solid.svg', value: '/guide/solid/' },
|
||||
{ name: 'Angular', icon: '/framework-logos/angular.svg', value: '/guide/angular/' },
|
||||
{ name: 'Preact', icon: '/framework-logos/preact.svg', value: '/guide/preact/' },
|
||||
{
|
||||
name: 'React Native',
|
||||
icon: '/framework-logos/react-native.svg',
|
||||
route: '/guide/react-native/',
|
||||
value: '/guide/react-native/',
|
||||
},
|
||||
{
|
||||
name: 'Astro',
|
||||
icon: '/framework-logos/astro.svg',
|
||||
iconDark: '/framework-logos/astro-dark.svg',
|
||||
route: '/guide/astro/',
|
||||
value: '/guide/astro/',
|
||||
},
|
||||
{ name: 'Static', icon: '/framework-logos/svg.svg', route: '/guide/static/' },
|
||||
{ name: 'Static', icon: '/framework-logos/svg.svg', value: '/guide/static/' },
|
||||
];
|
||||
|
||||
const fallbackFramework = useLocalStorage('lucide-docs-fallback-framework', frameworks[1]);
|
||||
|
||||
const selected = computed(() => {
|
||||
const current = frameworks.find(({ route }) => {
|
||||
const current = frameworks.find(({ value }) => {
|
||||
if (router.route.path?.startsWith?.('/guide')) {
|
||||
const [, , framework] = router.route.path.split('/');
|
||||
const [, frameWorkRoute] = route.split('/').filter(Boolean);
|
||||
const [, frameWorkRoute] = value.split('/').filter(Boolean);
|
||||
|
||||
return framework === frameWorkRoute;
|
||||
}
|
||||
return router.route.path.split('/').slice(0, 3).join('/') === route;
|
||||
return router.route.path.split('/').slice(0, 3).join('/') === value;
|
||||
});
|
||||
|
||||
return current || fallbackFramework.value;
|
||||
return current || (fallbackFramework.value?.value ? fallbackFramework.value : frameworks[0]);
|
||||
});
|
||||
|
||||
function onSelectFramework(item: { name: string; icon: string; iconDark?: string; route: string }) {
|
||||
function onSelectFramework(item: { name: string; icon: string; iconDark?: string; value: string }) {
|
||||
fallbackFramework.value = item;
|
||||
if (item.route !== router.route.path) {
|
||||
const likeRoute = router.route.path.replace(selected.value.route, item.route);
|
||||
if (item.value !== router.route.path) {
|
||||
const likeRoute = router.route.path.replace(selected.value.value, item.value);
|
||||
|
||||
const hasRoute = sidebar[item.route]?.some((section) =>
|
||||
const hasRoute = sidebar[item.value]?.some((section) =>
|
||||
section?.items?.some(({ link }) => link === likeRoute),
|
||||
);
|
||||
|
||||
@@ -62,7 +62,7 @@ function onSelectFramework(item: { name: string; icon: string; iconDark?: string
|
||||
return;
|
||||
}
|
||||
|
||||
router.go(item.route);
|
||||
router.go(item.value);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -85,12 +85,12 @@ function onSelectFramework(item: { name: string; icon: string; iconDark?: string
|
||||
/>
|
||||
</div>
|
||||
<VPSidebarGroup
|
||||
:key="selected.route"
|
||||
:key="selected.value"
|
||||
v-if="
|
||||
page?.relativePath?.startsWith?.('guide') &&
|
||||
!page?.relativePath?.startsWith?.(selected.route.substring(1))
|
||||
!page?.relativePath?.startsWith?.(selected.value.substring(1))
|
||||
"
|
||||
:items="sidebar[selected.route]"
|
||||
:items="sidebar[selected.value]"
|
||||
/>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -188,7 +188,7 @@ const deprecatedTitle = computed(() => {
|
||||
-ms-overflow-style: none;
|
||||
scrollbar-width: none;
|
||||
scrollbar-width: thin; /* can also be normal, or none, to not render scrollbar */
|
||||
scrollbar-color: currentColor transparent; /* foreground background */
|
||||
scrollbar-color: var(--vp-c-text-4) transparent; /* foreground background */
|
||||
}
|
||||
.horizontal-scroller::-webkit-scrollbar {
|
||||
width: 0;
|
||||
|
||||
@@ -44,8 +44,12 @@ function setActiveIconName(name: string) {
|
||||
activeIconName.value = name;
|
||||
}
|
||||
|
||||
const { execute: fetchTags, data: tags } = useFetchTags();
|
||||
const { execute: fetchCategories, data: categoriesMap } = useFetchCategories();
|
||||
const { execute: fetchTags, data: tags, isFetching: isFetchingTags } = useFetchTags();
|
||||
const {
|
||||
execute: fetchCategories,
|
||||
data: categoriesMap,
|
||||
isFetching: isFetchingCategories,
|
||||
} = useFetchCategories();
|
||||
|
||||
const overviewEl = ref<HTMLElement | null>(null);
|
||||
const { width: containerWidth } = useElementSize(overviewEl);
|
||||
@@ -117,6 +121,9 @@ const categoriesList = computed(() => {
|
||||
}, []);
|
||||
});
|
||||
const searchPlaceholder = useSearchPlaceholder(searchQuery, searchResults);
|
||||
const isSearchMetadataLoading = computed(
|
||||
() => searchQuery.value.length > 0 && (tags.value == null || categoriesMap.value == null),
|
||||
);
|
||||
|
||||
const { list, containerProps, wrapperProps, scrollTo } = useVirtualList(categoriesList, {
|
||||
itemHeight: ICON_SIZE + ICON_GRID_GAP,
|
||||
@@ -135,15 +142,21 @@ onMounted(() => {
|
||||
useEventListener(window, 'scroll', containerProps.onScroll);
|
||||
});
|
||||
|
||||
function onFocusSearchInput() {
|
||||
if (tags.value == null) {
|
||||
fetchTags();
|
||||
function loadSearchMetadata() {
|
||||
if (tags.value == null && !isFetchingTags.value) {
|
||||
void fetchTags();
|
||||
}
|
||||
if (categoriesMap.value == null) {
|
||||
fetchCategories();
|
||||
if (categoriesMap.value == null && !isFetchingCategories.value) {
|
||||
void fetchCategories();
|
||||
}
|
||||
}
|
||||
|
||||
watch(searchQuery, (searchString) => {
|
||||
if (searchString !== '') {
|
||||
loadSearchMetadata();
|
||||
}
|
||||
});
|
||||
|
||||
const NoResults = defineAsyncComponent(() => import('./NoResults.vue'));
|
||||
const IconDetailOverlay = defineAsyncComponent(() => import('./IconDetailOverlay.vue'));
|
||||
|
||||
@@ -156,11 +169,11 @@ function handleCloseDrawer() {
|
||||
if (searchQueryDebounced.value) {
|
||||
url.searchParams.set('search', searchQueryDebounced.value);
|
||||
}
|
||||
|
||||
|
||||
if (selectedCategory.value) {
|
||||
url.hash = selectedCategory.value;
|
||||
}
|
||||
|
||||
|
||||
window.history.pushState({}, '', url);
|
||||
}
|
||||
</script>
|
||||
@@ -169,6 +182,7 @@ function handleCloseDrawer() {
|
||||
<div
|
||||
ref="overviewEl"
|
||||
class="overview-container"
|
||||
:class="{ 'icon-drawer-open': activeIconName }"
|
||||
>
|
||||
<StickyBar class="category-search">
|
||||
<InputSearch
|
||||
@@ -177,11 +191,11 @@ function handleCloseDrawer() {
|
||||
:shortcut="kbdSearchShortcut"
|
||||
class="input-wrapper"
|
||||
ref="searchInput"
|
||||
@focus="onFocusSearchInput"
|
||||
@focus="loadSearchMetadata"
|
||||
/>
|
||||
</StickyBar>
|
||||
<NoResults
|
||||
v-if="searchPlaceholder.isNoResults"
|
||||
v-if="searchPlaceholder.isNoResults && !isSearchMetadataLoading"
|
||||
:searchQuery="searchPlaceholder.query"
|
||||
:isBrandSearch="searchPlaceholder.isBrand"
|
||||
@clear="searchQuery = ''"
|
||||
|
||||
@@ -4,6 +4,7 @@ import type { IconEntity } from '../../types';
|
||||
import { useElementSize, useEventListener, useVirtualList } from '@vueuse/core';
|
||||
import { useRoute } from 'vitepress';
|
||||
import IconGrid from './IconGrid.vue';
|
||||
import Select from '../base/Select.vue';
|
||||
import InputSearch from '../base/InputSearch.vue';
|
||||
import useSearch from '../../composables/useSearch';
|
||||
import useSearchInput from '../../composables/useSearchInput';
|
||||
@@ -14,9 +15,26 @@ import useFetchCategories from '../../composables/useFetchCategories';
|
||||
import chunkArray from '../../utils/chunkArray';
|
||||
import CarbonAdOverlay from './CarbonAdOverlay.vue';
|
||||
import useSearchPlaceholder from '../../utils/useSearchPlaceholder.ts';
|
||||
import Icon from '@lucide/vue/src/Icon';
|
||||
import { listSortDescending } from '~/.vitepress/data/iconNodes';
|
||||
|
||||
const ICON_SIZE = 56;
|
||||
const ICON_GRID_GAP = 8;
|
||||
const SORTING = [
|
||||
{
|
||||
name: 'Popularity',
|
||||
value: 'popularity',
|
||||
},
|
||||
{
|
||||
name: 'Release date',
|
||||
value: 'release-date',
|
||||
},
|
||||
{
|
||||
name: 'Name',
|
||||
value: 'name',
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
const initialGridItems = computed(() => {
|
||||
if (containerWidth.value === 0) return 120;
|
||||
@@ -32,9 +50,14 @@ const props = defineProps<{
|
||||
}>();
|
||||
|
||||
const activeIconName = ref(null);
|
||||
const selectedSort = ref(SORTING[0])
|
||||
|
||||
const { execute: fetchTags, data: tags } = useFetchTags();
|
||||
const { execute: fetchCategories, data: categories } = useFetchCategories();
|
||||
const { execute: fetchTags, data: tags, isFetching: isFetchingTags } = useFetchTags();
|
||||
const {
|
||||
execute: fetchCategories,
|
||||
data: categories,
|
||||
isFetching: isFetchingCategories,
|
||||
} = useFetchCategories();
|
||||
|
||||
const overviewEl = ref<HTMLElement | null>(null);
|
||||
const { width: containerWidth } = useElementSize(overviewEl);
|
||||
@@ -43,12 +66,29 @@ const columnSize = computed(() => {
|
||||
return Math.floor(containerWidth.value / (ICON_SIZE + ICON_GRID_GAP));
|
||||
});
|
||||
|
||||
const sortedIcons = computed(() => {
|
||||
switch (selectedSort.value.value) {
|
||||
case 'popularity':
|
||||
return [...props.icons].sort((a, b) => (b.popularity || 0) - (a.popularity || 0));
|
||||
case 'release-date':
|
||||
return [...props.icons].sort((a, b) => {
|
||||
const aDate = a.createdRelease?.date ? new Date(a.createdRelease.date).getTime() : 0;
|
||||
const bDate = b.createdRelease?.date ? new Date(b.createdRelease.date).getTime() : 0;
|
||||
return bDate - aDate;
|
||||
});
|
||||
case 'name':
|
||||
return [...props.icons].sort((a, b) => a.name.localeCompare(b.name));
|
||||
default:
|
||||
return props.icons;
|
||||
}
|
||||
});
|
||||
|
||||
const mappedIcons = computed(() => {
|
||||
if (tags.value == null) {
|
||||
return props.icons;
|
||||
return sortedIcons.value;
|
||||
}
|
||||
|
||||
return props.icons.map((icon) => {
|
||||
return sortedIcons.value.map((icon) => {
|
||||
const iconTags = tags.value[icon.name];
|
||||
const iconCategories = categories.value?.[icon.name] ?? [];
|
||||
|
||||
@@ -68,11 +108,15 @@ const { shortcutText: kbdSearchShortcut } = useSearchShortcut(() => {
|
||||
|
||||
const searchResults = useSearch(searchQueryDebounced, mappedIcons, [
|
||||
{ name: 'name', weight: 3 },
|
||||
{ name: 'aliases', weight: 3 },
|
||||
{ name: 'aliases', weight: 8 },
|
||||
{ name: 'tags', weight: 2 },
|
||||
{ name: 'categories', weight: 1 },
|
||||
]);
|
||||
|
||||
const searchPlaceholder = useSearchPlaceholder(searchQuery, searchResults);
|
||||
const isSearchMetadataLoading = computed(
|
||||
() => searchQuery.value.length > 0 && (tags.value == null || categories.value == null),
|
||||
);
|
||||
|
||||
const chunkedIcons = computed(() => {
|
||||
return chunkArray(searchResults.value, columnSize.value);
|
||||
@@ -98,15 +142,21 @@ function setActiveIconName(name: string) {
|
||||
activeIconName.value = name;
|
||||
}
|
||||
|
||||
function onFocusSearchInput() {
|
||||
if (tags.value == null) {
|
||||
fetchTags();
|
||||
function loadSearchMetadata() {
|
||||
if (tags.value == null && !isFetchingTags.value) {
|
||||
void fetchTags();
|
||||
}
|
||||
if (categories.value == null) {
|
||||
fetchCategories();
|
||||
if (categories.value == null && !isFetchingCategories.value) {
|
||||
void fetchCategories();
|
||||
}
|
||||
}
|
||||
|
||||
watch(searchQuery, (searchString) => {
|
||||
if (searchString !== '') {
|
||||
loadSearchMetadata();
|
||||
}
|
||||
});
|
||||
|
||||
const NoResults = defineAsyncComponent(() => import('./NoResults.vue'));
|
||||
|
||||
const IconDetailOverlay = defineAsyncComponent(() => import('./IconDetailOverlay.vue'));
|
||||
@@ -124,7 +174,7 @@ function handleCloseDrawer() {
|
||||
if (searchQueryDebounced.value) {
|
||||
url.searchParams.set('search', searchQueryDebounced.value);
|
||||
}
|
||||
|
||||
|
||||
window.history.pushState({}, '', url);
|
||||
}
|
||||
</script>
|
||||
@@ -133,6 +183,7 @@ function handleCloseDrawer() {
|
||||
<div
|
||||
ref="overviewEl"
|
||||
class="overview-container"
|
||||
:class="{ 'icon-drawer-open': activeIconName }"
|
||||
>
|
||||
<StickyBar>
|
||||
<InputSearch
|
||||
@@ -141,11 +192,25 @@ function handleCloseDrawer() {
|
||||
ref="searchInput"
|
||||
:shortcut="kbdSearchShortcut"
|
||||
class="input-wrapper"
|
||||
@focus="onFocusSearchInput"
|
||||
@focus="loadSearchMetadata"
|
||||
/>
|
||||
|
||||
<Select
|
||||
id="sort-select"
|
||||
:items="SORTING"
|
||||
v-model="selectedSort"
|
||||
>
|
||||
<template #start-icon>
|
||||
<Icon
|
||||
:iconNode="listSortDescending"
|
||||
class="chevron-icon"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
</template>
|
||||
</Select>
|
||||
</StickyBar>
|
||||
<NoResults
|
||||
v-if="searchPlaceholder.isNoResults"
|
||||
v-if="searchPlaceholder.isNoResults && !isSearchMetadataLoading"
|
||||
:searchQuery="searchPlaceholder.query"
|
||||
:isBrandSearch="searchPlaceholder.isBrand"
|
||||
@clear="searchQuery = ''"
|
||||
|
||||
@@ -73,13 +73,11 @@ const customizingActive = computed(() => {
|
||||
id="icon-color"
|
||||
label="Color"
|
||||
>
|
||||
<template #display>
|
||||
<ColorPicker
|
||||
v-model="color"
|
||||
id="icon-color"
|
||||
class="color-picker"
|
||||
/>
|
||||
</template>
|
||||
<ColorPicker
|
||||
v-model="color"
|
||||
id="icon-color"
|
||||
class="color-picker"
|
||||
/>
|
||||
</InputField>
|
||||
|
||||
<InputField
|
||||
@@ -161,6 +159,6 @@ const customizingActive = computed(() => {
|
||||
}
|
||||
|
||||
.color-picker {
|
||||
margin-left: auto;
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -15,6 +15,50 @@
|
||||
margin-bottom: 32px;
|
||||
background: var(--vp-c-bg);
|
||||
box-shadow: 0 16px 24px var(--vp-c-bg);
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.search-bar :deep(.select-button) {
|
||||
padding: 11px 14px;
|
||||
background-color: var(--vp-c-bg-alt);
|
||||
color: var(--vp-c-text-2);
|
||||
flex-shrink: 0;
|
||||
flex: 1;
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.search-bar :deep(.select-button):hover,
|
||||
.search-bar :deep(.select-button):focus {
|
||||
border-color: var(--vp-c-brand);
|
||||
background: var(--vp-c-bg-alt);
|
||||
}
|
||||
|
||||
.search-bar :deep(.select-options) {
|
||||
min-width: 160px;
|
||||
}
|
||||
|
||||
.search-bar :deep(.select-option) {
|
||||
padding-right: 36px;
|
||||
padding-left: 8px;
|
||||
}
|
||||
|
||||
.search-bar :deep(.select-icon) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.search-bar :deep(.select-button) .select-text {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@media (min-width: 640px) {
|
||||
.search-bar :deep(.select-button) {
|
||||
padding: 11px 16px 11px 16px;
|
||||
}
|
||||
|
||||
.search-bar :deep(.select-button) .select-text {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 960px) {
|
||||
|
||||
@@ -20,16 +20,6 @@ const useSearch = <T>(
|
||||
return index.value.search(query.value).map((result) => result.item);
|
||||
}
|
||||
|
||||
if (keys.length !== 0) {
|
||||
const mainKey = keys[0].name;
|
||||
|
||||
return collection.value.sort((a, b) => {
|
||||
const aString = a[mainKey as keyof T] as string;
|
||||
const bString = b[mainKey as keyof T] as string;
|
||||
return aString.localeCompare(bString);
|
||||
});
|
||||
}
|
||||
|
||||
return collection.value;
|
||||
});
|
||||
|
||||
|
||||
@@ -12,7 +12,6 @@ import { CATEGORY_VIEW_CONTEXT, categoryViewContext } from './composables/useCat
|
||||
import { EXTERNAL_LIBS_CONTEXT, externalLibContext } from './composables/useExternalLibs';
|
||||
import FrameworkSelect from './components/guide/FrameworkSelect.vue';
|
||||
import SnackPlayer from './components/editors/SnackPlayer.vue';
|
||||
import CertificatesLink from './components/guide/CertificatesLink.vue';
|
||||
|
||||
const theme: Partial<Theme> = {
|
||||
extends: DefaultTheme,
|
||||
@@ -23,7 +22,6 @@ const theme: Partial<Theme> = {
|
||||
'sidebar-nav-after': () => h(IconsSidebarNavAfter),
|
||||
'home-hero-image': () => h(HomeHeroIconsCard),
|
||||
'home-hero-actions-after': () => h(HomeHeroAfter),
|
||||
'aside-ads-before': () => h(CertificatesLink),
|
||||
// Keep this here for now, we might want to add more things to the top bar in the future
|
||||
// 'layout-top': () => h(LayoutTop),
|
||||
});
|
||||
|
||||
@@ -67,6 +67,10 @@
|
||||
animation: .3s transition 0s ease;
|
||||
} */
|
||||
|
||||
html {
|
||||
scrollbar-gutter: stable;
|
||||
}
|
||||
|
||||
.VPHome {
|
||||
overflow-x: hidden;
|
||||
}
|
||||
@@ -117,6 +121,10 @@
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
.overview-container.icon-drawer-open {
|
||||
padding-bottom: 288px;
|
||||
}
|
||||
|
||||
.VPHomeHero .container {
|
||||
flex-direction: column-reverse;
|
||||
}
|
||||
@@ -144,14 +152,6 @@
|
||||
.VPHomeHero .container {
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
html.has-bb-banner {
|
||||
--vp-layout-top-height: 72px;
|
||||
}
|
||||
|
||||
html.has-bb-banner {
|
||||
--Dark-Background: #161618;
|
||||
}
|
||||
}
|
||||
|
||||
.VPNavBarHamburger .container > span {
|
||||
@@ -163,8 +163,23 @@
|
||||
max-width: 480px;
|
||||
}
|
||||
|
||||
html:not(.has-bb-banner) #bb-banner {
|
||||
display: none !important;
|
||||
visibility: hidden !important;
|
||||
pointer-events: none !important;
|
||||
.VPSidebar {
|
||||
/* Hide Scrollbar */
|
||||
-ms-overflow-style: none;
|
||||
scrollbar-width: none;
|
||||
scrollbar-width: thin; /* can also be normal, or none, to not render scrollbar */
|
||||
scrollbar-color: var(--vp-c-text-4) transparent; /* foreground background */
|
||||
}
|
||||
.VPSidebar::-webkit-scrollbar {
|
||||
width: 0;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.VPSidebar::-webkit-scrollbar-track {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.VPSidebar::-webkit-scrollbar-thumb {
|
||||
background: transparent;
|
||||
border: none;
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ export interface IconEntity extends IconMetaData {
|
||||
externalLibrary?: ExternalLibs;
|
||||
createdRelease?: Release;
|
||||
changedRelease?: Release;
|
||||
popularity?: number;
|
||||
}
|
||||
|
||||
export interface Category {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { PageData } from 'vitepress';
|
||||
import { type PageData } from 'vitepress';
|
||||
import getStructuredData from './getStructuredData';
|
||||
import { createGeneralOGImage, createIconOGImage } from './createOGImage';
|
||||
|
||||
|
||||
@@ -12,19 +12,23 @@ Implementation of the Lucide icon library for web applications.
|
||||
::: code-group
|
||||
|
||||
```sh [pnpm]
|
||||
pnpm add lucide@next
|
||||
pnpm add lucide
|
||||
```
|
||||
|
||||
```sh [yarn]
|
||||
yarn add lucide@next
|
||||
yarn add lucide
|
||||
```
|
||||
|
||||
```sh [npm]
|
||||
npm install lucide@next
|
||||
npm install lucide
|
||||
```
|
||||
|
||||
```sh [bun]
|
||||
bun add lucide@next
|
||||
bun add lucide
|
||||
```
|
||||
|
||||
```sh [deno]
|
||||
deno add lucide
|
||||
```
|
||||
|
||||
:::
|
||||
@@ -38,19 +42,23 @@ Implementation of the Lucide icon library for React applications.
|
||||
::: code-group
|
||||
|
||||
```sh [pnpm]
|
||||
pnpm add lucide-react@next
|
||||
pnpm add lucide-react
|
||||
```
|
||||
|
||||
```sh [yarn]
|
||||
yarn add lucide-react@next
|
||||
yarn add lucide-react
|
||||
```
|
||||
|
||||
```sh [npm]
|
||||
npm install lucide-react@next
|
||||
npm install lucide-react
|
||||
```
|
||||
|
||||
```sh [bun]
|
||||
bun add lucide-react@next
|
||||
bun add lucide-react
|
||||
```
|
||||
|
||||
```sh [deno]
|
||||
deno add lucide-react
|
||||
```
|
||||
|
||||
:::
|
||||
@@ -80,6 +88,10 @@ npm install @lucide/vue
|
||||
bun add @lucide/vue
|
||||
```
|
||||
|
||||
```sh [deno]
|
||||
deno add @lucide/vue
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
For more details, see the [documentation](./vue/index.md).
|
||||
@@ -91,19 +103,23 @@ Implementation of the Lucide icon library for Svelte applications.
|
||||
::: code-group
|
||||
|
||||
```sh [pnpm]
|
||||
pnpm add @lucide/svelte@next
|
||||
pnpm add @lucide/svelte
|
||||
```
|
||||
|
||||
```sh [yarn]
|
||||
yarn add @lucide/svelte@next
|
||||
yarn add @lucide/svelte
|
||||
```
|
||||
|
||||
```sh [npm]
|
||||
npm install @lucide/svelte@next
|
||||
npm install @lucide/svelte
|
||||
```
|
||||
|
||||
```sh [bun]
|
||||
bun add @lucide/svelte@next
|
||||
bun add @lucide/svelte
|
||||
```
|
||||
|
||||
```sh [deno]
|
||||
deno add @lucide/svelte
|
||||
```
|
||||
:::
|
||||
> `@lucide/svelte` is only for Svelte 5, for Svelte 4 use the `lucide-svelte` package.
|
||||
@@ -117,19 +133,23 @@ Implementation of the Lucide icon library for Solid applications.
|
||||
::: code-group
|
||||
|
||||
```sh [pnpm]
|
||||
pnpm add lucide-solid@next
|
||||
pnpm add lucide-solid
|
||||
```
|
||||
|
||||
```sh [yarn]
|
||||
yarn add lucide-solid@next
|
||||
yarn add lucide-solid
|
||||
```
|
||||
|
||||
```sh [npm]
|
||||
npm install lucide-solid@next
|
||||
npm install lucide-solid
|
||||
```
|
||||
|
||||
```sh [bun]
|
||||
bun add lucide-solid@next
|
||||
bun add lucide-solid
|
||||
```
|
||||
|
||||
```sh [deno]
|
||||
deno add lucide-solid
|
||||
```
|
||||
|
||||
:::
|
||||
@@ -158,6 +178,10 @@ npm install @lucide/angular
|
||||
bun add @lucide/angular
|
||||
```
|
||||
|
||||
```sh [deno]
|
||||
deno add @lucide/angular
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
For more details, see the [documentation](./angular/index.md).
|
||||
@@ -169,19 +193,23 @@ Implementation of the Lucide icon library for preact applications.
|
||||
::: code-group
|
||||
|
||||
```sh [pnpm]
|
||||
pnpm add lucide-preact@next
|
||||
pnpm add lucide-preact
|
||||
```
|
||||
|
||||
```sh [yarn]
|
||||
yarn add lucide-preact@next
|
||||
yarn add lucide-preact
|
||||
```
|
||||
|
||||
```sh [npm]
|
||||
npm install lucide-preact@next
|
||||
npm install lucide-preact
|
||||
```
|
||||
|
||||
```sh [bun]
|
||||
bun add lucide-preact@next
|
||||
bun add lucide-preact
|
||||
```
|
||||
|
||||
```sh [deno]
|
||||
deno add lucide-preact
|
||||
```
|
||||
|
||||
|
||||
@@ -196,19 +224,23 @@ Implementation of the Lucide icon library for Astro applications.
|
||||
::: code-group
|
||||
|
||||
```sh [pnpm]
|
||||
pnpm add @lucide/astro@next
|
||||
pnpm add @lucide/astro
|
||||
```
|
||||
|
||||
```sh [yarn]
|
||||
yarn add @lucide/astro@next
|
||||
yarn add @lucide/astro
|
||||
```
|
||||
|
||||
```sh [npm]
|
||||
npm install @lucide/astro@next
|
||||
npm install @lucide/astro
|
||||
```
|
||||
|
||||
```sh [bun]
|
||||
bun add @lucide/astro@next
|
||||
bun add @lucide/astro
|
||||
```
|
||||
|
||||
```sh [deno]
|
||||
deno add @lucide/astro
|
||||
```
|
||||
|
||||
:::
|
||||
@@ -222,19 +254,23 @@ Implementation of the Lucide icon library for multiple usages that like to use:
|
||||
::: code-group
|
||||
|
||||
```sh [pnpm]
|
||||
pnpm add lucide-static@next
|
||||
pnpm add lucide-static
|
||||
```
|
||||
|
||||
```sh [yarn]
|
||||
yarn add lucide-static@next
|
||||
yarn add lucide-static
|
||||
```
|
||||
|
||||
```sh [npm]
|
||||
npm install lucide-static@next
|
||||
npm install lucide-static
|
||||
```
|
||||
|
||||
```sh [bun]
|
||||
bun add lucide-static@next
|
||||
bun add lucide-static
|
||||
```
|
||||
|
||||
```sh [deno]
|
||||
deno add lucide-static
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
---
|
||||
title: Optimizations - React Native
|
||||
description: Learn how to optimize the bundle size of your React Native and Expo web exports by tree-shaking Lucide icons.
|
||||
---
|
||||
|
||||
# Optimizations
|
||||
|
||||
By default you import icons from the `lucide-react-native` entry point:
|
||||
|
||||
```jsx
|
||||
import { Camera } from 'lucide-react-native';
|
||||
```
|
||||
|
||||
This is convenient, but it relies on the bundler to _tree-shake_ the entry point (a "barrel" file that re-exports every icon) so that only the icons you actually use end up in your bundle.
|
||||
|
||||
On native platforms this is usually fine. On **web exports** it can be a problem, because the Metro bundler is currently not very good at tree-shaking barrel imports and may include **all** icons in your final bundle.
|
||||
|
||||
## The Metro tree-shaking limitation
|
||||
|
||||
When you build for web with Expo (`expo export --platform web`), Metro is used to bundle your JavaScript. Metro bundles modules on-demand and, by default, does not remove unused exports from a barrel file.
|
||||
|
||||
This means an import like the one below can pull in the entire icon set, even though only a single icon is rendered:
|
||||
|
||||
```jsx
|
||||
// May bundle every Lucide icon on web exports
|
||||
import { Camera } from 'lucide-react-native';
|
||||
```
|
||||
|
||||
Expo documents an experimental optimization for [React Native web imports](https://docs.expo.dev/guides/tree-shaking/#react-native-web-imports) and for [removing unused imports and exports](https://docs.expo.dev/guides/tree-shaking/#remove-unused-imports-and-exports). In practice this tree-shaking does **not** currently work reliably for `lucide-react-native` barrel imports, so the unused icons are not removed from web exports.
|
||||
|
||||
## Recommended: import icons individually
|
||||
|
||||
To guarantee that only the icons you use are bundled — regardless of the bundler's tree-shaking capabilities — import each icon directly from its own module:
|
||||
|
||||
```jsx
|
||||
import Camera from 'lucide-react-native/icons/camera';
|
||||
|
||||
// Usage
|
||||
const App = () => {
|
||||
return <Camera />;
|
||||
};
|
||||
|
||||
export default App;
|
||||
```
|
||||
|
||||
Because each icon lives in its own file, the bundler only ever includes the icons you explicitly import. This keeps your web export small without depending on Metro's experimental tree-shaking.
|
||||
|
||||
The icon module name is the [kebab-case](https://developer.mozilla.org/en-US/docs/Glossary/Kebab_case) version of the icon name. For example, the `ArrowRight` icon is imported from `lucide-react-native/icons/arrow-right`:
|
||||
|
||||
```jsx
|
||||
import ArrowRight from 'lucide-react-native/icons/arrow-right';
|
||||
```
|
||||
|
||||
::: tip
|
||||
Individual icon imports work identically on native and web, so you can safely use this style across your whole project to keep bundles as small as possible on every platform.
|
||||
:::
|
||||
@@ -1,9 +1,19 @@
|
||||
import iconNodes from '../.vitepress/data/iconNodes';
|
||||
import * as iconDetails from '../.vitepress/data/iconDetails';
|
||||
|
||||
export default {
|
||||
async load() {
|
||||
return {
|
||||
icons: Object.entries(iconNodes).map(([name, iconNode]) => ({ name, iconNode })),
|
||||
icons: Object.entries(iconDetails).map(
|
||||
([, { name, iconNode, popularity, createdRelease, aliases = [] }]) => ({
|
||||
name,
|
||||
iconNode,
|
||||
popularity: popularity?.count ?? 0,
|
||||
aliases: aliases
|
||||
.map((alias) => (typeof alias === 'string' ? alias : alias?.name))
|
||||
.filter((alias): alias is string => Boolean(alias)),
|
||||
createdRelease,
|
||||
}),
|
||||
),
|
||||
};
|
||||
},
|
||||
};
|
||||
|
||||
@@ -9,14 +9,15 @@
|
||||
"docs:build": "pnpm run /^prebuild:.*/ && vitepress build",
|
||||
"docs:preview": "vitepress preview",
|
||||
"build:docs": "vitepress build",
|
||||
"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",
|
||||
"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:iconPopularity": "node ./scripts/writeiconPopularity.mts",
|
||||
"prebuild:brandStopwords": "node ./scripts/writeBrandStopwords.mts",
|
||||
"postbuild:vercelJson": "node ./scripts/writeVercelOutput.mts",
|
||||
"dev": "npx nitropack dev",
|
||||
"prebuild:api": "npx nitropack prepare",
|
||||
"build:api": "npx nitropack build",
|
||||
@@ -38,7 +39,7 @@
|
||||
"vitepress": "^1.6.4",
|
||||
"vitepress-plugin-group-icons": "^1.6.5",
|
||||
"vitepress-plugin-llms": "^1.11.1",
|
||||
"markdown-it": "^14.1.0",
|
||||
"markdown-it": "^14.2.0",
|
||||
"markdown-it-container": "^4.0.0",
|
||||
"semver": "^7.7.3",
|
||||
"sharp": "^0.34.5",
|
||||
|
||||
|
Before Width: | Height: | Size: 86 KiB |
|
Before Width: | Height: | Size: 83 KiB |
|
Before Width: | Height: | Size: 88 KiB |
|
Before Width: | Height: | Size: 79 KiB |
@@ -0,0 +1,6 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 160 200" fill="none">
|
||||
<path fill="#00e8ff" d="M40 120l20-60l90 90l-30 50l-40-40h-20" />
|
||||
<path fill="#283198" d="M80 160 L80 80 L120 40 L 120 120 M0 160 L40 200 L40 120 L20 120" />
|
||||
<path fill="#324fff" d="M40 120v-80l40-40v80M120 200v-80l40-40v80M0 160v-80l40 40" />
|
||||
<path fill="#0ff" d="M40 200v-80l40 40" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 377 B |
@@ -26,6 +26,7 @@ const writeIconFiles = icons.map(async (iconFileName) => {
|
||||
import iconNode from '../iconNodes/${iconName}.node.json'
|
||||
import metaData from '../../../../icons/${iconName}.json'
|
||||
import releaseData from '../releaseMetadata/${iconName}.json'
|
||||
import popularity from '../iconPopularity/${iconName}.json'
|
||||
|
||||
const { tags, categories, contributors, aliases, deprecated, deprecationReason, toBeRemovedInVersion } = metaData
|
||||
|
||||
@@ -37,6 +38,7 @@ const iconDetails = {
|
||||
categories,
|
||||
aliases,
|
||||
deprecated,
|
||||
popularity,
|
||||
deprecationReason,
|
||||
toBeRemovedInVersion,
|
||||
...releaseData,
|
||||
@@ -42,7 +42,7 @@ const getRelatedIcons = (currentIcon, icons) => {
|
||||
};
|
||||
|
||||
const iconsMetaDataPromises = svgFiles.map(async (iconName) => {
|
||||
const metaDataFileContent = await fs.promises.readFile(`../icons/${iconName}`);
|
||||
const metaDataFileContent = await fs.promises.readFile(`../icons/${iconName}`, 'utf-8');
|
||||
const metaData = JSON.parse(metaDataFileContent);
|
||||
|
||||
const name = iconName.replace('.json', '');
|
||||
@@ -70,10 +70,10 @@ const comparisonsPromises = tags.map(async (tag, index) => {
|
||||
};
|
||||
});
|
||||
|
||||
const comparisons = await Promise.all(comparisonsPromises);
|
||||
const comparisons = (await Promise.all(comparisonsPromises)).filter((comparison) => comparison != null && Object.keys(comparison.iconFiles).length > 0);
|
||||
const newReleaseMetaData = {};
|
||||
|
||||
comparisons.forEach(({ tag, iconFiles, date } = {}) => {
|
||||
comparisons.forEach(({ tag, iconFiles, date }) => {
|
||||
if (tag == null) return;
|
||||
|
||||
iconFiles.forEach(({ status, file, renamedFile }) => {
|
||||
@@ -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) => alias.name).join('|');
|
||||
const aliasRouteMatches = aliases.map((alias) => typeof alias === 'string' ? alias : alias?.name).join('|');
|
||||
|
||||
return {
|
||||
src: `^/icons/(${aliasRouteMatches})$`,
|
||||
@@ -0,0 +1,104 @@
|
||||
/* eslint-disable no-restricted-syntax, no-await-in-loop */
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import { loadEnvFile } from 'node:process';
|
||||
import { readSvgDirectory } from '@lucide/helpers';
|
||||
|
||||
const currentDir = process.cwd();
|
||||
const ICONS_DIR = path.resolve(currentDir, '../icons');
|
||||
const iconPopularityDirectory = path.resolve(currentDir, '.vitepress/data', 'iconPopularity');
|
||||
|
||||
try {
|
||||
// Load environment variables from .env file, if it exists.
|
||||
loadEnvFile(`${currentDir}/.env`);
|
||||
} catch (error) {}
|
||||
|
||||
if (fs.existsSync(iconPopularityDirectory)) {
|
||||
fs.rmSync(iconPopularityDirectory, { recursive: true, force: true });
|
||||
}
|
||||
|
||||
if (!fs.existsSync(iconPopularityDirectory)) {
|
||||
fs.mkdirSync(iconPopularityDirectory);
|
||||
}
|
||||
|
||||
const iconJsonFiles = await readSvgDirectory(ICONS_DIR, '.json');
|
||||
const iconNames = iconJsonFiles.map((file) => path.basename(file, '.json'));
|
||||
|
||||
const defaultIconNamePopularity: Record<string, number> = Object.fromEntries(
|
||||
iconNames.map((iconName) => [iconName, 0])
|
||||
);
|
||||
|
||||
interface AnalyticsResponse {
|
||||
results: {
|
||||
dimensions: [route: string];
|
||||
metrics: [count: number];
|
||||
}[];
|
||||
}
|
||||
|
||||
const writeIconPopularity = async (iconVisitCounts: Record<string, number>) => {
|
||||
const writePopularityPromises = Object.entries(iconVisitCounts).map(([iconName, count]) => {
|
||||
const location = path.resolve(iconPopularityDirectory, `${iconName}.json`);
|
||||
return fs.promises.writeFile(location, JSON.stringify({ count }, null, 2), 'utf-8');
|
||||
});
|
||||
|
||||
await Promise.all(writePopularityPromises);
|
||||
console.log('Successfully written icon popularity data for', writePopularityPromises.length, 'icons.');
|
||||
};
|
||||
|
||||
if (process.env.LUCIDE_ANALYTICS_TOKEN === undefined) {
|
||||
console.warn('LUCIDE_ANALYTICS_TOKEN environment variable is not set. Writing default icon popularity data.');
|
||||
await writeIconPopularity(defaultIconNamePopularity);
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await fetch('https://analytics.lucide.dev/api/v2/query', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: `Bearer ${process.env.LUCIDE_ANALYTICS_TOKEN}`,
|
||||
},
|
||||
body: JSON.stringify({
|
||||
"site_id": "lucide.dev",
|
||||
"metrics": [
|
||||
"visitors"
|
||||
],
|
||||
"dimensions": [
|
||||
"visit:entry_page"
|
||||
],
|
||||
"date_range": "12mo"
|
||||
}),
|
||||
})
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`Network response was not ok: ${response.statusText}`);
|
||||
}
|
||||
|
||||
const analyticsData: AnalyticsResponse = await response.json();
|
||||
|
||||
const iconVisitCounts = analyticsData.results.reduce((acc, { dimensions, metrics }) => {
|
||||
const [route] = dimensions;
|
||||
const [count] = metrics;
|
||||
|
||||
if (!route.startsWith('/icons')) {
|
||||
return acc
|
||||
}
|
||||
// Only match routes that start with /icons/ and end with an icon name, e.g. /icons/activity, /icons/activity/ or /icons/activity?ref=homepage
|
||||
const match = route.match(/^\/icons\/([^\/\?]+)(?:[\/\?]|$)/);
|
||||
if (match) {
|
||||
const iconName = match[1];
|
||||
|
||||
if (iconNames.includes(iconName)) {
|
||||
acc[iconName] = (acc[iconName] || 0) + count;
|
||||
}
|
||||
}
|
||||
|
||||
return acc;
|
||||
}, defaultIconNamePopularity);
|
||||
|
||||
await writeIconPopularity(iconVisitCounts);
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error fetching analytics data:', error);
|
||||
await writeIconPopularity(defaultIconNamePopularity);
|
||||
}
|
||||
@@ -40,7 +40,7 @@
|
||||
}
|
||||
},
|
||||
"dependentRequired": {
|
||||
"deprecated": ["deprecationReason", "toBeRemovedInVersion"],
|
||||
"deprecated": ["deprecationReason"],
|
||||
"deprecationReason": ["deprecated"],
|
||||
"toBeRemovedInVersion": ["deprecated"]
|
||||
}
|
||||
@@ -134,7 +134,7 @@
|
||||
}
|
||||
},
|
||||
"dependentRequired": {
|
||||
"deprecated": ["deprecationReason", "toBeRemovedInVersion"],
|
||||
"deprecated": ["deprecationReason"],
|
||||
"deprecationReason": ["deprecated"],
|
||||
"toBeRemovedInVersion": ["deprecated"]
|
||||
},
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"$schema": "../icon.schema.json",
|
||||
"contributors": [
|
||||
"ahtohbi4",
|
||||
"jamiemlaw",
|
||||
"karsa-mistmere",
|
||||
"jguddas"
|
||||
],
|
||||
"use-cases": [
|
||||
"marking content as sponsored",
|
||||
"linking to an advertise with us page"
|
||||
],
|
||||
"tags": [
|
||||
"advert",
|
||||
"affiliate",
|
||||
"brand",
|
||||
"campaign",
|
||||
"commercial",
|
||||
"marketing",
|
||||
"monetize",
|
||||
"paid",
|
||||
"partner",
|
||||
"promo",
|
||||
"sponsor"
|
||||
],
|
||||
"categories": [
|
||||
"multimedia",
|
||||
"notifications"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
<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="M10 13H6" />
|
||||
<path d="M10 15v-4a2 2 0 0 0-4 0v4" />
|
||||
<path d="M14 14.5a.5.5 0 0 0 .5.5h1a2.5 2.5 0 0 0 2.5-2.5v-1A2.5 2.5 0 0 0 15.5 9h-1a.5.5 0 0 0-.5.5z" />
|
||||
<rect x="2" y="5" width="20" height="14" rx="2" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 434 B |
@@ -23,8 +23,7 @@
|
||||
{
|
||||
"name": "alarm-check",
|
||||
"deprecationReason": "alias.name",
|
||||
"deprecated": true,
|
||||
"toBeRemovedInVersion": "v1.0"
|
||||
"deprecated": true
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -19,8 +19,7 @@
|
||||
{
|
||||
"name": "alarm-minus",
|
||||
"deprecationReason": "alias.name",
|
||||
"deprecated": true,
|
||||
"toBeRemovedInVersion": "v1.0"
|
||||
"deprecated": true
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -19,8 +19,7 @@
|
||||
{
|
||||
"name": "alarm-plus",
|
||||
"deprecationReason": "alias.name",
|
||||
"deprecated": true,
|
||||
"toBeRemovedInVersion": "v1.0"
|
||||
"deprecated": true
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -25,8 +25,7 @@
|
||||
{
|
||||
"name": "arrow-down-01",
|
||||
"deprecationReason": "alias.name",
|
||||
"deprecated": true,
|
||||
"toBeRemovedInVersion": "v1.0"
|
||||
"deprecated": true
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -25,8 +25,7 @@
|
||||
{
|
||||
"name": "arrow-down-10",
|
||||
"deprecationReason": "alias.name",
|
||||
"deprecated": true,
|
||||
"toBeRemovedInVersion": "v1.0"
|
||||
"deprecated": true
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -25,8 +25,7 @@
|
||||
{
|
||||
"name": "arrow-down-az",
|
||||
"deprecationReason": "alias.name",
|
||||
"deprecated": true,
|
||||
"toBeRemovedInVersion": "v1.0"
|
||||
"deprecated": true
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -25,8 +25,7 @@
|
||||
{
|
||||
"name": "sort-desc",
|
||||
"deprecationReason": "alias.name",
|
||||
"deprecated": true,
|
||||
"toBeRemovedInVersion": "v1.0"
|
||||
"deprecated": true
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -26,8 +26,7 @@
|
||||
{
|
||||
"name": "arrow-down-za",
|
||||
"deprecationReason": "alias.name",
|
||||
"deprecated": true,
|
||||
"toBeRemovedInVersion": "v1.0"
|
||||
"deprecated": true
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -25,8 +25,7 @@
|
||||
{
|
||||
"name": "arrow-up-01",
|
||||
"deprecationReason": "alias.name",
|
||||
"deprecated": true,
|
||||
"toBeRemovedInVersion": "v1.0"
|
||||
"deprecated": true
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -25,8 +25,7 @@
|
||||
{
|
||||
"name": "arrow-up-10",
|
||||
"deprecationReason": "alias.name",
|
||||
"deprecated": true,
|
||||
"toBeRemovedInVersion": "v1.0"
|
||||
"deprecated": true
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -25,8 +25,7 @@
|
||||
{
|
||||
"name": "arrow-up-az",
|
||||
"deprecationReason": "alias.name",
|
||||
"deprecated": true,
|
||||
"toBeRemovedInVersion": "v1.0"
|
||||
"deprecated": true
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -26,8 +26,7 @@
|
||||
{
|
||||
"name": "sort-asc",
|
||||
"deprecationReason": "alias.name",
|
||||
"deprecated": true,
|
||||
"toBeRemovedInVersion": "v1.0"
|
||||
"deprecated": true
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -26,8 +26,7 @@
|
||||
{
|
||||
"name": "arrow-up-za",
|
||||
"deprecationReason": "alias.name",
|
||||
"deprecated": true,
|
||||
"toBeRemovedInVersion": "v1.0"
|
||||
"deprecated": true
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -16,8 +16,7 @@
|
||||
{
|
||||
"name": "axis-3-d",
|
||||
"deprecationReason": "alias.name",
|
||||
"deprecated": true,
|
||||
"toBeRemovedInVersion": "v1.0"
|
||||
"deprecated": true
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -8,8 +8,7 @@
|
||||
{
|
||||
"name": "verified",
|
||||
"deprecationReason": "alias.name",
|
||||
"deprecated": true,
|
||||
"toBeRemovedInVersion": "v1.0"
|
||||
"deprecated": true
|
||||
}
|
||||
],
|
||||
"use-cases": [],
|
||||
|
||||
@@ -19,8 +19,7 @@
|
||||
{
|
||||
"name": "badge-help",
|
||||
"deprecationReason": "alias.name",
|
||||
"deprecated": true,
|
||||
"toBeRemovedInVersion": "v1.0"
|
||||
"deprecated": true
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
{
|
||||
"$schema": "../icon.schema.json",
|
||||
"contributors": [
|
||||
"mfjramirezf"
|
||||
],
|
||||
"use-cases": [
|
||||
"confirm a paid product",
|
||||
"confirm a payment method was added successfully"
|
||||
],
|
||||
"tags": [
|
||||
"banknote",
|
||||
"bill",
|
||||
"currency",
|
||||
"payment",
|
||||
"money",
|
||||
"finance",
|
||||
"document",
|
||||
"verification",
|
||||
"tick",
|
||||
"verified",
|
||||
"accepted",
|
||||
"done",
|
||||
"complete",
|
||||
"found",
|
||||
"paid",
|
||||
"task",
|
||||
"check",
|
||||
"success"
|
||||
],
|
||||
"categories": [
|
||||
"finance"
|
||||
]
|
||||
}
|
||||
@@ -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="M11.748 18H4a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v4.875" />
|
||||
<path d="m16 19 2 2 4-4" />
|
||||
<path d="M18 12h.01" />
|
||||
<path d="M6 12h.01" />
|
||||
<circle cx="12" cy="12" r="2" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 405 B |
@@ -36,8 +36,7 @@
|
||||
{
|
||||
"name": "between-horizonal-end",
|
||||
"deprecated": true,
|
||||
"deprecationReason": "alias.typo",
|
||||
"toBeRemovedInVersion": "v1.0"
|
||||
"deprecationReason": "alias.typo"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -36,8 +36,7 @@
|
||||
{
|
||||
"name": "between-horizonal-start",
|
||||
"deprecated": true,
|
||||
"deprecationReason": "alias.typo",
|
||||
"toBeRemovedInVersion": "v1.0"
|
||||
"deprecationReason": "alias.typo"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
{
|
||||
"$schema": "../icon.schema.json",
|
||||
"contributors": [
|
||||
"Patolord"
|
||||
],
|
||||
"use-cases": [
|
||||
"indicate injury or fracture status in health/fitness tracking",
|
||||
"show an error or failed state in healthcare UI flows"
|
||||
],
|
||||
"tags": [
|
||||
"bone",
|
||||
"fracture",
|
||||
"injury",
|
||||
"orthopedic",
|
||||
"medical",
|
||||
"anatomy",
|
||||
"skeletal",
|
||||
"broken",
|
||||
"xray",
|
||||
"trauma",
|
||||
"health",
|
||||
"vet",
|
||||
"veterinary",
|
||||
"crack",
|
||||
"break",
|
||||
"damage"
|
||||
],
|
||||
"categories": [
|
||||
"medical",
|
||||
"animals"
|
||||
]
|
||||
}
|
||||
@@ -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="M14 4.5a1 1 0 0 1 5 0 .5.5 0 0 0 .5.5 1 1 0 0 1 0 5c-.81 0-1.8-.7-2.5 0l-1.958 1.957a.15.15 0 0 1-.252-.072l-.493-2.07a.15.15 0 0 0-.111-.112l-2.072-.494a.15.15 0 0 1-.072-.252L14 7c.7-.7 0-1.69 0-2.5" />
|
||||
<path d="m16 20-1-2" />
|
||||
<path d="m20 16-2-1" />
|
||||
<path d="m4 8 2 1" />
|
||||
<path d="m8 4 1 2" />
|
||||
<path d="M9.698 14.19a.15.15 0 0 0 .112.112l2.074.489a.15.15 0 0 1 .072.252L10 17c-.7.7 0 1.69 0 2.5a1 1 0 0 1-5 0 .495.495 0 0 0-.5-.5 1 1 0 0 1 0-5c.81 0 1.8.7 2.5 0l1.956-1.957a.15.15 0 0 1 .252.072z" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 732 B |
@@ -29,8 +29,7 @@
|
||||
{
|
||||
"name": "book-template",
|
||||
"deprecationReason": "alias.name",
|
||||
"deprecated": true,
|
||||
"toBeRemovedInVersion": "v1.0.0"
|
||||
"deprecated": true
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -8,8 +8,7 @@
|
||||
{
|
||||
"name": "curly-braces",
|
||||
"deprecationReason": "alias.name",
|
||||
"deprecated": true,
|
||||
"toBeRemovedInVersion": "v1.0"
|
||||
"deprecated": true
|
||||
}
|
||||
],
|
||||
"use-cases": [],
|
||||
|
||||
@@ -20,8 +20,7 @@
|
||||
{
|
||||
"name": "subtitles",
|
||||
"deprecationReason": "alias.name",
|
||||
"deprecated": true,
|
||||
"toBeRemovedInVersion": "v1.0"
|
||||
"deprecated": true
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -3,10 +3,21 @@
|
||||
"contributors": [
|
||||
"Andreto",
|
||||
"mittalyashu",
|
||||
"ericfennis"
|
||||
"ericfennis",
|
||||
"jguddas",
|
||||
"karsa-mistmere",
|
||||
"jamiemlaw"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"orange",
|
||||
"healthy",
|
||||
"nature",
|
||||
"fresh",
|
||||
"root",
|
||||
"produce",
|
||||
"organic",
|
||||
"nutrition",
|
||||
"vegetable",
|
||||
"food",
|
||||
"eat"
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<path d="M2.27 21.7s9.87-3.5 12.73-6.36a4.5 4.5 0 0 0-6.36-6.37C5.77 11.84 2.27 21.7 2.27 21.7zM8.64 14l-2.05-2.04M15.34 15l-2.46-2.46" />
|
||||
<path d="M22 9s-1.33-2-3.5-2C16.86 7 15 9 15 9s1.33 2 3.5 2S22 9 22 9z" />
|
||||
<path d="M15 2s-2 1.33-2 3.5S15 9 15 9s2-1.84 2-3.5C17 3.33 15 2 15 2z" />
|
||||
<path d="M15 16a1 1 0 0 0-7-7q-4 4-5.987 12.385a.5.5 0 0 0 .602.602Q11 20 15 16l-3-3" />
|
||||
<path d="M15 9q4 4 7 0-3-4-7 0 4-4 0-7-4 3 0 7" />
|
||||
<path d="m8 15-2.58-2.58" />
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 503 B After Width: | Height: | Size: 383 B |
@@ -18,8 +18,7 @@
|
||||
{
|
||||
"name": "area-chart",
|
||||
"deprecated": true,
|
||||
"deprecationReason": "alias.name",
|
||||
"toBeRemovedInVersion": "v1.0"
|
||||
"deprecationReason": "alias.name"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -18,8 +18,7 @@
|
||||
{
|
||||
"name": "bar-chart-horizontal-big",
|
||||
"deprecated": true,
|
||||
"deprecationReason": "alias.name",
|
||||
"toBeRemovedInVersion": "v1.0"
|
||||
"deprecationReason": "alias.name"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -18,8 +18,7 @@
|
||||
{
|
||||
"name": "bar-chart-horizontal",
|
||||
"deprecated": true,
|
||||
"deprecationReason": "alias.name",
|
||||
"toBeRemovedInVersion": "v1.0"
|
||||
"deprecationReason": "alias.name"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -33,8 +33,7 @@
|
||||
{
|
||||
"name": "candlestick-chart",
|
||||
"deprecated": true,
|
||||
"deprecationReason": "alias.name",
|
||||
"toBeRemovedInVersion": "v1.0"
|
||||
"deprecationReason": "alias.name"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -18,8 +18,7 @@
|
||||
{
|
||||
"name": "bar-chart-big",
|
||||
"deprecated": true,
|
||||
"deprecationReason": "alias.name",
|
||||
"toBeRemovedInVersion": "v1.0"
|
||||
"deprecationReason": "alias.name"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -19,8 +19,7 @@
|
||||
{
|
||||
"name": "bar-chart-4",
|
||||
"deprecated": true,
|
||||
"deprecationReason": "alias.name",
|
||||
"toBeRemovedInVersion": "v1.0"
|
||||
"deprecationReason": "alias.name"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -18,8 +18,7 @@
|
||||
{
|
||||
"name": "bar-chart-3",
|
||||
"deprecated": true,
|
||||
"deprecationReason": "alias.name",
|
||||
"toBeRemovedInVersion": "v1.0"
|
||||
"deprecationReason": "alias.name"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -17,8 +17,7 @@
|
||||
{
|
||||
"name": "line-chart",
|
||||
"deprecated": true,
|
||||
"deprecationReason": "alias.name",
|
||||
"toBeRemovedInVersion": "v1.0"
|
||||
"deprecationReason": "alias.name"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -20,8 +20,7 @@
|
||||
{
|
||||
"name": "bar-chart",
|
||||
"deprecated": true,
|
||||
"deprecationReason": "alias.name",
|
||||
"toBeRemovedInVersion": "v1.0"
|
||||
"deprecationReason": "alias.name"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -19,8 +19,7 @@
|
||||
{
|
||||
"name": "bar-chart-2",
|
||||
"deprecated": true,
|
||||
"deprecationReason": "alias.name",
|
||||
"toBeRemovedInVersion": "v1.0"
|
||||
"deprecationReason": "alias.name"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -34,8 +34,7 @@
|
||||
{
|
||||
"name": "gantt-chart",
|
||||
"deprecated": true,
|
||||
"deprecationReason": "alias.name",
|
||||
"toBeRemovedInVersion": "v1.0"
|
||||
"deprecationReason": "alias.name"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -20,8 +20,7 @@
|
||||
{
|
||||
"name": "pie-chart",
|
||||
"deprecated": true,
|
||||
"deprecationReason": "alias.name",
|
||||
"toBeRemovedInVersion": "v1.0"
|
||||
"deprecationReason": "alias.name"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -18,8 +18,7 @@
|
||||
{
|
||||
"name": "scatter-chart",
|
||||
"deprecated": true,
|
||||
"deprecationReason": "alias.name",
|
||||
"toBeRemovedInVersion": "v1.0"
|
||||
"deprecationReason": "alias.name"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -18,8 +18,7 @@
|
||||
{
|
||||
"name": "alert-circle",
|
||||
"deprecationReason": "alias.name",
|
||||
"deprecated": true,
|
||||
"toBeRemovedInVersion": "v1.0"
|
||||
"deprecated": true
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -21,8 +21,7 @@
|
||||
{
|
||||
"name": "arrow-down-circle",
|
||||
"deprecationReason": "alias.name",
|
||||
"deprecated": true,
|
||||
"toBeRemovedInVersion": "v1.0"
|
||||
"deprecated": true
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -23,8 +23,7 @@
|
||||
{
|
||||
"name": "arrow-left-circle",
|
||||
"deprecationReason": "alias.name",
|
||||
"deprecated": true,
|
||||
"toBeRemovedInVersion": "v1.0"
|
||||
"deprecated": true
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -17,8 +17,7 @@
|
||||
{
|
||||
"name": "arrow-down-left-from-circle",
|
||||
"deprecationReason": "alias.name",
|
||||
"deprecated": true,
|
||||
"toBeRemovedInVersion": "v1.0"
|
||||
"deprecated": true
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -17,8 +17,7 @@
|
||||
{
|
||||
"name": "arrow-down-right-from-circle",
|
||||
"deprecationReason": "alias.name",
|
||||
"deprecated": true,
|
||||
"toBeRemovedInVersion": "v1.0"
|
||||
"deprecated": true
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -21,8 +21,7 @@
|
||||
{
|
||||
"name": "arrow-up-left-from-circle",
|
||||
"deprecationReason": "alias.name",
|
||||
"deprecated": true,
|
||||
"toBeRemovedInVersion": "v1.0"
|
||||
"deprecated": true
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -17,8 +17,7 @@
|
||||
{
|
||||
"name": "arrow-up-right-from-circle",
|
||||
"deprecationReason": "alias.name",
|
||||
"deprecated": true,
|
||||
"toBeRemovedInVersion": "v1.0"
|
||||
"deprecated": true
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -23,8 +23,7 @@
|
||||
{
|
||||
"name": "arrow-right-circle",
|
||||
"deprecationReason": "alias.name",
|
||||
"deprecated": true,
|
||||
"toBeRemovedInVersion": "v1.0"
|
||||
"deprecated": true
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -20,8 +20,7 @@
|
||||
{
|
||||
"name": "arrow-up-circle",
|
||||
"deprecationReason": "alias.name",
|
||||
"deprecated": true,
|
||||
"toBeRemovedInVersion": "v1.0"
|
||||
"deprecated": true
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -21,8 +21,7 @@
|
||||
{
|
||||
"name": "check-circle",
|
||||
"deprecationReason": "alias.name",
|
||||
"deprecated": true,
|
||||
"toBeRemovedInVersion": "v1.0"
|
||||
"deprecated": true
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -19,8 +19,7 @@
|
||||
{
|
||||
"name": "check-circle-2",
|
||||
"deprecationReason": "alias.name",
|
||||
"deprecated": true,
|
||||
"toBeRemovedInVersion": "v1.0"
|
||||
"deprecated": true
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -16,8 +16,7 @@
|
||||
{
|
||||
"name": "chevron-down-circle",
|
||||
"deprecationReason": "alias.name",
|
||||
"deprecated": true,
|
||||
"toBeRemovedInVersion": "v1.0"
|
||||
"deprecated": true
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -19,8 +19,7 @@
|
||||
{
|
||||
"name": "chevron-left-circle",
|
||||
"deprecationReason": "alias.name",
|
||||
"deprecated": true,
|
||||
"toBeRemovedInVersion": "v1.0"
|
||||
"deprecated": true
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||