Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1675213eb6 | ||
|
|
ac25ea327d | ||
|
|
b9e922b100 | ||
|
|
6e42a8792a | ||
|
|
d7f8d17986 | ||
|
|
c81e6846c5 | ||
|
|
804d25586b | ||
|
|
39e3964a9b | ||
|
|
2f8257d8b4 | ||
|
|
fe0bd9b887 | ||
|
|
d0229f4cfc | ||
|
|
cc1caae101 | ||
|
|
d632a8e272 | ||
|
|
653e44b832 | ||
|
|
f0eaba827e | ||
|
|
dc803026e0 | ||
|
|
3c62e4bfef | ||
|
|
6d6da7ca3a | ||
|
|
2453b6467d | ||
|
|
a88e7070cc | ||
|
|
a7611e2957 | ||
|
|
7c2ff2e5d6 | ||
|
|
51e37e2e2c | ||
|
|
5faceb5495 | ||
|
|
3814a64cd5 | ||
|
|
43c76b1f08 | ||
|
|
2401a39571 | ||
|
|
7623e23f78 | ||
|
|
663a9d7fc3 | ||
|
|
d53f615cf3 | ||
|
|
d8700b257a | ||
|
|
30bb61917b | ||
|
|
1e6b96db3d | ||
|
|
5c52182778 | ||
|
|
1fde1f1c1a | ||
|
|
dada0a8297 | ||
|
|
fa09963bf8 | ||
|
|
cc53931091 | ||
|
|
86b3ddfdca | ||
|
|
f1360e1d9b | ||
|
|
e2df99b883 | ||
|
|
aed7aeaa72 | ||
|
|
11ff82b056 | ||
|
|
25d96b7ec0 | ||
|
|
10962ce51b | ||
|
|
7dfbd21bce | ||
|
|
b18f27ea8d | ||
|
|
5e6186ff70 | ||
|
|
acb947a770 | ||
|
|
e9bec8e6f8 | ||
|
|
4ea3561788 | ||
|
|
76c1b0caa9 | ||
|
|
f2eab2c30a | ||
|
|
3fc90467a3 | ||
|
|
519aae64d6 | ||
|
|
7a395122a1 |
@@ -41,13 +41,13 @@ Common scopes: icons, docs, studio, site, dev
|
||||
|
||||
### Naming <!-- ONLY for new icons -->
|
||||
<!-- All of these requirements must be fulfilled. -->
|
||||
- [ ] I've read and followed the [naming conventions](https://lucide.dev/guide/design/icon-design-guide#naming-conventions)
|
||||
- [ ] I've read and followed the [naming conventions](https://lucide.dev/contribute/icon-design-guide#naming-conventions)
|
||||
- [ ] I've named icons by what they are rather than their use case.
|
||||
- [ ] I've provided meta JSON files in `icons/[iconName].json`.
|
||||
|
||||
### Design <!-- ONLY for new icons -->
|
||||
<!-- All of these requirements must be fulfilled. -->
|
||||
- [ ] I've read and followed the [icon design guidelines](https://lucide.dev/guide/design/icon-design-guide)
|
||||
- [ ] I've read and followed the [icon design guidelines](https://lucide.dev/contribute/icon-design-guide)
|
||||
- [ ] I've made sure that the icons look sharp on low DPI displays.
|
||||
- [ ] I've made sure that the icons look consistent with the icon set in size, optical volume and density.
|
||||
- [ ] I've made sure that the icons are visually centered.
|
||||
|
||||
@@ -23,6 +23,9 @@ jobs:
|
||||
- name: Install dependencies
|
||||
run: pnpm install --frozen-lockfile
|
||||
|
||||
- name: Execute unit tests for build-font
|
||||
run: pnpm test:font
|
||||
|
||||
- name: Create font in ./lucide-font
|
||||
run: pnpm build:font
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ on:
|
||||
type: string
|
||||
tag:
|
||||
description: NPM tag
|
||||
default: 'next' # set to latest after v1 release
|
||||
default: 'latest'
|
||||
type: string
|
||||
|
||||
permissions:
|
||||
@@ -136,6 +136,9 @@ jobs:
|
||||
- name: Install dependencies
|
||||
run: pnpm install --frozen-lockfile
|
||||
|
||||
- name: Execute unit tests for build-font
|
||||
run: pnpm test:font
|
||||
|
||||
- name: Create font in ./lucide-font
|
||||
run: pnpm build:font --saveCodePoints
|
||||
env:
|
||||
|
||||
@@ -26,9 +26,13 @@ packages/**/src/utils/*.ts
|
||||
packages/**/src/dynamicIconImports.ts
|
||||
packages/**/DynamicIcon.d.ts
|
||||
packages/**/dynamicIconImports.js
|
||||
packages/**/dynamicIconImports.mjs
|
||||
packages/**/dynamicIconImports.d.ts
|
||||
packages/**/dynamicIconImports.d.mts
|
||||
packages/**/dynamicIconImports.js.map
|
||||
packages/**/dynamicIconImports.mjs.map
|
||||
packages/**/dynamic.d.ts
|
||||
packages/**/dynamic.d.mts
|
||||
packages/**/dynamic.mjs.map
|
||||
packages/**/dynamic.mjs
|
||||
packages/**/LICENSE
|
||||
|
||||
@@ -39,7 +39,7 @@ This means adding them could:
|
||||
Lucide is all about **visual consistency**.
|
||||
|
||||
Adding brand logos would:
|
||||
- Break [our own design rules](https://lucide.dev/guide/design/icon-design-guide#icon-design-principles) for shapes, proportions, and stroke.
|
||||
- Break [our own design rules](https://lucide.dev/contribute/icon-design-guide#icon-design-principles) for shapes, proportions, and stroke.
|
||||
- Mix two fundamentally different categories of graphics (pictograms vs. corporate logos).
|
||||
- Create a library where a subset of icons will always look "out of place".
|
||||
|
||||
|
||||
@@ -80,6 +80,8 @@ Thank you to all the people who contributed to Lucide!
|
||||
<img src="https://opencollective.com/lucide-icons/contributors.svg?width=800" />
|
||||
</a>
|
||||
|
||||
[//]: <> (Sponsors)
|
||||
|
||||
## Sponsors
|
||||
|
||||
<a href="https://vercel.com?utm_source=lucide&utm_campaign=oss">
|
||||
@@ -88,7 +90,10 @@ Thank you to all the people who contributed to Lucide!
|
||||
|
||||
<a href="https://www.digitalocean.com/?refcode=b0877a2caebd&utm_campaign=Referral_Invite&utm_medium=Referral_Program&utm_source=badge"><img src="docs/public/digitalocean.svg" width="200" alt="DigitalOcean Referral Badge" /></a>
|
||||
|
||||
[//]: <> (Open Collective backers)
|
||||
### Hero backers 🦸
|
||||
|
||||
<a href="https://https://zephyr-cloud.io/"><img src="docs/public/sponsors/zephyr-cloud.svg" width="180" alt="Zephyr Cloud – From idea to prod: fast micro-frontend delivery!" /></a>
|
||||
|
||||
### Awesome backers 🍺
|
||||
|
||||
<a href="https://github.com/pdfme/pdfme"><img src="docs/public/sponsors/pdfme.svg" width="180" alt="pdfme – Open-source PDF generation library built with TypeScript and React." /></a>
|
||||
|
||||
@@ -105,6 +105,7 @@
|
||||
"order": 6,
|
||||
"icon": "angular",
|
||||
"docsAlias": "angular",
|
||||
"packageDirname": "angular",
|
||||
"shields": [
|
||||
{
|
||||
"alt": "npm",
|
||||
|
||||
@@ -459,7 +459,20 @@ const SvgPreview = (
|
||||
/>
|
||||
<ColoredPath
|
||||
paths={paths}
|
||||
colors={['#dfdfd6']}
|
||||
colors={[
|
||||
'#1982c4',
|
||||
'#4267AC',
|
||||
'#6a4c93',
|
||||
'#B55379',
|
||||
'#FF595E',
|
||||
'#FF7655',
|
||||
'#ff924c',
|
||||
'#FFAE43',
|
||||
'#ffca3a',
|
||||
'#C5CA30',
|
||||
'#8ac926',
|
||||
'#52A675',
|
||||
]}
|
||||
/>
|
||||
<Radii
|
||||
paths={paths}
|
||||
|
||||
@@ -1,15 +1,22 @@
|
||||
<script setup lang="ts">
|
||||
import VPLink from 'vitepress/dist/client/theme-default/components/VPLink.vue';
|
||||
import Icon from '@lucide/vue/src/Icon';
|
||||
import RocketDuotoneIcon from '../home/RocketDuotoneIcon.ts';
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="top-notification">
|
||||
<p>
|
||||
<Icon
|
||||
:iconNode="RocketDuotoneIcon"
|
||||
size="18"
|
||||
class="rocket-icon"
|
||||
/>
|
||||
<VPLink
|
||||
class="notification-link"
|
||||
href="/guide/version-1"
|
||||
>Lucide v1 is out!</VPLink
|
||||
>🚀<br />
|
||||
>
|
||||
You're looking at the site for v1, for v0 go to
|
||||
<VPLink
|
||||
class="notification-link"
|
||||
@@ -21,11 +28,7 @@ import VPLink from 'vitepress/dist/client/theme-default/components/VPLink.vue';
|
||||
</template>
|
||||
|
||||
<style>
|
||||
:root {
|
||||
--vp-layout-top-height: 64px;
|
||||
}
|
||||
|
||||
@media (min-width: 640px) {
|
||||
@media (min-width: 960px) {
|
||||
:root {
|
||||
--vp-layout-top-height: 32px;
|
||||
}
|
||||
@@ -34,19 +37,19 @@ import VPLink from 'vitepress/dist/client/theme-default/components/VPLink.vue';
|
||||
|
||||
<style scoped>
|
||||
.top-notification {
|
||||
position: fixed;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
z-index: 9999;
|
||||
display: flex;
|
||||
height: var(--vp-layout-top-height);
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
background: var(--vp-c-brand-dark);
|
||||
color: var(--vp-c-bg-alt-down);
|
||||
font-size: 14px;
|
||||
padding: 0 16px;
|
||||
padding: 4px 16px;
|
||||
text-wrap: balance;
|
||||
}
|
||||
|
||||
.notification-link {
|
||||
@@ -58,9 +61,9 @@ import VPLink from 'vitepress/dist/client/theme-default/components/VPLink.vue';
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
@media (min-width: 640px) {
|
||||
.top-notification br {
|
||||
display: none;
|
||||
}
|
||||
.rocket-icon {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
margin-right: 4px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -118,5 +118,15 @@ label {
|
||||
font-weight: bold;
|
||||
margin-bottom: 4px;
|
||||
display: block;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.framework-select:before {
|
||||
content: ' ';
|
||||
position: absolute;
|
||||
inset: 0 -16px -24px;
|
||||
background: color-mix(in srgb, var(--vp-c-bg-alt), transparent 50%);
|
||||
backdrop-filter: blur(4px);
|
||||
mask-image: linear-gradient(to bottom, black calc(100% - 16px), transparent 100%);
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -3,25 +3,7 @@ import Badge from '../base/Badge.vue';
|
||||
import { moveRight } from '../../../data/iconNodes';
|
||||
import Icon from '@lucide/vue/src/Icon';
|
||||
import { data } from './HomeHeroInfoBefore.data';
|
||||
const rocketDuoTone = [
|
||||
[
|
||||
'path',
|
||||
{
|
||||
d: 'M8 18a2 2 0 0 0-2-2c-2.53-.078-3.247 3.605-3.5 5.5 1.895-.253 5.578-.97 5.5-3.5',
|
||||
fill: 'currentColor',
|
||||
opacity: 0.5,
|
||||
},
|
||||
],
|
||||
[
|
||||
'path',
|
||||
{
|
||||
d: 'M22 2c0 2.72-.78 7.5-6 11 0 0 1.08 3.38 0 5-.969 1.448-4 2-4 2v-5l-3-3H4s.553-3.033 2-4c1.616-1.077 4.982.043 5 .05A12.88 12.88 0 0 1 22 2m-6 3a3 3 0 1 0 0 6 3 3 0 0 0 0-6',
|
||||
fill: 'currentColor',
|
||||
'fill-rule': 'evenodd',
|
||||
'clip-rule': 'evenodd',
|
||||
},
|
||||
],
|
||||
] as const;
|
||||
import RocketDuotoneIcon from './RocketDuotoneIcon.ts';
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -33,7 +15,7 @@ const rocketDuoTone = [
|
||||
class="badge-special confetti-button animate"
|
||||
href="/guide/version-1"
|
||||
>
|
||||
<Icon :iconNode="rocketDuoTone" />
|
||||
<Icon :iconNode="RocketDuotoneIcon" />
|
||||
Version 1
|
||||
<Icon
|
||||
:iconNode="moveRight"
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
const RocketDuotoneIcon = [
|
||||
[
|
||||
'path',
|
||||
{
|
||||
d: 'M8 18a2 2 0 0 0-2-2c-2.53-.078-3.247 3.605-3.5 5.5 1.895-.253 5.578-.97 5.5-3.5',
|
||||
fill: 'currentColor',
|
||||
opacity: 0.5,
|
||||
},
|
||||
],
|
||||
[
|
||||
'path',
|
||||
{
|
||||
d: 'M22 2c0 2.72-.78 7.5-6 11 0 0 1.08 3.38 0 5-.969 1.448-4 2-4 2v-5l-3-3H4s.553-3.033 2-4c1.616-1.077 4.982.043 5 .05A12.88 12.88 0 0 1 22 2m-6 3a3 3 0 1 0 0 6 3 3 0 0 0 0-6',
|
||||
fill: 'currentColor',
|
||||
'fill-rule': 'evenodd',
|
||||
'clip-rule': 'evenodd',
|
||||
},
|
||||
],
|
||||
] as const;
|
||||
|
||||
export default RocketDuotoneIcon;
|
||||
@@ -5,11 +5,18 @@ import IconButton from '../base/IconButton.vue';
|
||||
import VPDocAsideCarbonAds from 'vitepress/dist/client/theme-default/components/VPDocAsideCarbonAds.vue';
|
||||
import { x } from '../../../data/iconNodes';
|
||||
import Icon from '@lucide/vue/src/Icon';
|
||||
import { onMounted, ref } from 'vue';
|
||||
import { computed, onMounted, ref } from 'vue';
|
||||
|
||||
const { theme } = useData();
|
||||
const showAd = useSessionStorage('show-carbon-ads', true);
|
||||
const showAd = useSessionStorage('show-carbon-ads', true, {
|
||||
initOnMounted: true,
|
||||
});
|
||||
const carbonLoaded = ref(true);
|
||||
const shouldHideAd = computed(() => !showAd.value || !carbonLoaded.value);
|
||||
|
||||
function hideAd() {
|
||||
showAd.value = false;
|
||||
}
|
||||
|
||||
defineProps<{
|
||||
drawerOpen: boolean;
|
||||
@@ -28,13 +35,13 @@ onMounted(() => {
|
||||
<div
|
||||
:class="{
|
||||
'drawer-open': drawerOpen,
|
||||
'hide-ad': !(showAd && carbonLoaded),
|
||||
'hide-ad': shouldHideAd,
|
||||
}"
|
||||
class="floating-ad"
|
||||
v-if="theme.carbonAds"
|
||||
>
|
||||
<IconButton
|
||||
@click="showAd = false"
|
||||
@click="hideAd"
|
||||
class="hide-button"
|
||||
>
|
||||
<Icon
|
||||
@@ -66,6 +73,7 @@ onMounted(() => {
|
||||
.floating-ad.hide-ad {
|
||||
transform: translateX(224px);
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.floating-ad.drawer-open.hide-ad {
|
||||
@@ -96,6 +104,7 @@ onMounted(() => {
|
||||
position: absolute;
|
||||
top: 8px;
|
||||
right: 8px;
|
||||
z-index: 3;
|
||||
background-color: transparent;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -9,7 +9,7 @@ import Sandpack from '~/.vitepress/theme/components/editors/SandpackPreact.vue'
|
||||
# Combining icons
|
||||
|
||||
You can combine multiple icons into a single icon by nesting SVG elements.
|
||||
This is useful if you want to create custom icons icons by combining existing ones.
|
||||
This is useful if you want to create custom icons by combining existing ones.
|
||||
|
||||
::: sandpack {showTabs=false editorHeight=400 editorWidthPercentage=60 dependencies="lucide-preact"}
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ description: Learn how to combine multiple icons into a single icon nested SVG e
|
||||
# Combining icons
|
||||
|
||||
You can combine multiple icons into a single icon by nesting SVG elements.
|
||||
This is useful if you want to create custom icons icons by combining existing ones.
|
||||
This is useful if you want to create custom icons by combining existing ones.
|
||||
|
||||
```SnackPlayer name=State&ext=js&dependencies=react-native-svg,lucide-react-native
|
||||
import React, {useState, useEffect} from 'react';
|
||||
|
||||
@@ -9,7 +9,7 @@ import Sandpack from '~/.vitepress/theme/components/editors/Sandpack.vue'
|
||||
# Combining icons
|
||||
|
||||
You can combine multiple icons into a single icon by nesting SVG elements.
|
||||
This is useful if you want to create custom icons icons by combining existing ones.
|
||||
This is useful if you want to create custom icons by combining existing ones.
|
||||
|
||||
::: sandpack {template=react showTabs=false editorHeight=400 editorWidthPercentage=60 dependencies="lucide-react"}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ description: Learn about the different types exported by the `lucide-react` pack
|
||||
# TypeScript Support
|
||||
|
||||
List of exported types from the `lucide-react` package.
|
||||
These can be used to type your components when using Lucide icons in a TypeScript React project
|
||||
These can be used to type your components when using Lucide icons in a TypeScript React project.
|
||||
|
||||
## `LucideProps`
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ import Sandpack from '~/.vitepress/theme/components/editors/Sandpack.vue'
|
||||
# Combining icons
|
||||
|
||||
You can combine multiple icons into a single icon by nesting SVG elements.
|
||||
This is useful if you want to create custom icons icons by combining existing ones.
|
||||
This is useful if you want to create custom icons by combining existing ones.
|
||||
|
||||
::: sandpack {template=vite-solid showTabs=false editorHeight=400 editorWidthPercentage=60 dependencies="lucide-solid"}
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ import Sandpack from '~/.vitepress/theme/components/editors/SandpackSvelte.vue';
|
||||
# Combining icons
|
||||
|
||||
You can combine multiple icons into a single icon by nesting SVG elements.
|
||||
This is useful if you want to create custom icons icons by combining existing ones.
|
||||
This is useful if you want to create custom icons by combining existing ones.
|
||||
|
||||
::: sandpack {template=vite-svelte showTabs=false editorHeight=400 editorWidthPercentage=60}
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ import Sandpack from '~/.vitepress/theme/components/editors/SandpackVue.vue'
|
||||
# Combining icons
|
||||
|
||||
You can combine multiple icons into a single icon by nesting SVG elements.
|
||||
This is useful if you want to create custom icons icons by combining existing ones.
|
||||
This is useful if you want to create custom icons by combining existing ones.
|
||||
|
||||
::: sandpack {template=vue showTabs=false editorHeight=400 editorWidthPercentage=60 dependencies="@lucide/vue"}
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
"element-to-path": "^1.2.1",
|
||||
"fuse.js": "^7.1.0",
|
||||
"jszip": "^3.10.1",
|
||||
"lodash-es": "^4.17.23",
|
||||
"lodash-es": "^4.18.1",
|
||||
"lucide": "workspace:*",
|
||||
"lucide-react": "workspace:*",
|
||||
"motion-v": "1.10.3",
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="138" height="42" fill="none" viewBox="0 0 138 42">
|
||||
<path fill="#fff" fill-rule="evenodd" d="M138 4a4 4 0 0 0-4-4H4a4 4 0 0 0-4 4v34a4 4 0 0 0 4 4h130a4 4 0 0 0 4-4z" clip-rule="evenodd"/>
|
||||
<path fill="url(#a)" fill-rule="evenodd" d="M16 27.6a6.6 6.6 0 0 0 5.5-10.4l4.3-4.3c.3-.3.1-1-.4-1a29 29 0 0 1-4.8-1.4h-.1l-.6-.3A11.4 11.4 0 0 0 5.1 24.5c.2.6 1 .9 1.5.6q.7-.6.5-1.4a9.3 9.3 0 0 1 14.6-10l-2 1.8q-1.6-1-3.7-1.1a6.6 6.6 0 0 0-5.4 10.4L6.3 29c-.4.3-.2 1 .3 1a29 29 0 0 1 4.8 1.4h.1l.6.3a11 11 0 0 0 12-2.7 11 11 0 0 0 2.8-11.6c-.2-.6-1-.9-1.5-.6q-.6.6-.5 1.4a9.3 9.3 0 0 1-14.6 10l2-1.8q1.6 1 3.7 1.1m4.4-6.6a4.5 4.5 0 0 1-6.7 4l6.2-6.1q.5.9.5 2.1m-9 0a4.5 4.5 0 0 1 6.8-3.9L12 23.3q-.6-1-.6-2.3" clip-rule="evenodd"/>
|
||||
<path fill="url(#b)" d="M57.7 19.3q3.5.1 3.5 4 0 3.6-3.5 3.8-2.3 0-2.8-1.9h-.3l.2 1.4v3.7h-1.4V19.5h1.4l-.2 1.7h.3q.6-1.9 2.8-1.9m16.6 7.4h.3l2-7.2h1.5l-2.5 8.3q-.4 2-2.4 2.2l-2.2.2v-1.4h2.5q.5.1.5-.4l.5-1.5H73l-2.2-7.4h1.4zm-26-7.4q3.3 0 3.3 3.7H46c0 1.7.5 3 2.5 3q2 0 2-2.1H52q-.4 3.1-3.5 3.2-3.8-.1-3.9-3.9 0-3.7 3.7-3.9m46.1-3q4 0 4.4 4.2h-1.5q-.2-3-3-3-3 0-3 4.2t3.3 4.2q3 0 3.2-3h1.4q-.3 4.3-4.6 4.2-4.7 0-4.7-5.4t4.5-5.4m16 3q3.6.1 3.8 4-.2 3.6-3.9 3.8-3.7-.1-3.8-3.9.1-3.7 3.8-3.9m6.4 4.6q0 2 2 2 2.3-.2 2.3-2.4v-4h1.4v5.8q-.1.6.4.4l.9-.1v1.3h-.8q-1.6 0-1.7-1.6h-.3q-.5 1.8-2.6 1.8-2.9 0-2.8-3v-4.6h1.5zm15.6 1.4q-.1.6.4.4l.9-.1v1.3h-.8q-1.7-.1-1.8-1.7h-.3q-.4 1.9-2.8 2-3.4-.2-3.5-4 .1-3.7 3.5-3.9 2.4 0 2.8 2h.3l-.1-1.4v-4h1.4zm-89-5.7L36 25.4v.3h7.8v1.2h-8v-3l7.5-5.8v-.3H36v-1.2h7.4zm21 .3L64 21h.3q.5-1.8 2.7-1.8 2.8 0 2.7 3v4.6h-1.5l.3-4.4q0-2-2-2-2.3.1-2.3 2.5v4H63V15.7h1.4zM80.5 21h.3q.4-1.7 2.2-1.6h1.3V21l-1.6-.2q-2 0-2 2.3v4h-1.5v-7.5h1.4zm20.9-5.3q2 0 2 2v8h2.2v1.1h-6v-1.2h2.4v-8.4q.1-.6-.5-.4l-1.4.3v-1.4zm8.8 4.7q-2.4 0-2.4 2.7t2.4 2.7q2.4 0 2.5-2.7 0-2.6-2.5-2.7m-52.8 0q-2.6 0-2.6 2.7.1 2.6 2.6 2.7 2.3 0 2.3-2.7 0-2.6-2.3-2.7m70.8 0q-2.4 0-2.4 2.7 0 2.6 2.4 2.7 2.7 0 2.6-2.7-.1-2.6-2.6-2.7m-80 0q-1.8 0-2.1 1.5h4q0-1.4-1.9-1.5"/>
|
||||
<defs>
|
||||
<linearGradient id="a" x1="4.6" x2="27.4" y1="21" y2="21" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#010101"/>
|
||||
<stop offset="1" stop-color="#949494"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="b" x1="35.7" x2="133.7" y1="23.1" y2="23.1" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#010101"/>
|
||||
<stop offset="1" stop-color="#646464"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.4 KiB |
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"$schema": "../icon.schema.json",
|
||||
"contributors": [
|
||||
"kemie",
|
||||
"ericfennis",
|
||||
"karsa-mistmere",
|
||||
"jguddas"
|
||||
],
|
||||
"tags": [
|
||||
"food",
|
||||
"dish",
|
||||
"restaurant",
|
||||
"course",
|
||||
"meal",
|
||||
"meat",
|
||||
"bbq",
|
||||
"steak",
|
||||
"vegetarian"
|
||||
],
|
||||
"categories": [
|
||||
"food-beverage"
|
||||
]
|
||||
}
|
||||
@@ -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="M11.771 6.109a2.5 2.5 0 0 1 3.12 3.12" />
|
||||
<path d="M17.852 12.185a6.5 6.5 0 0 0-9.035-9.04" />
|
||||
<path d="M18.013 18.013C15.029 20.349 10.831 22 7 22a3 3 0 0 1-2.68-1.66L2.4 16.5" />
|
||||
<path d="m18.5 6 2.19 4.5a6.48 6.48 0 0 1-.139 4.393" />
|
||||
<path d="m2 2 20 20" />
|
||||
<path d="M6.355 6.37a7 7 0 0 0-.075.23c-1.1 3.13-.78 3.9-3.18 6.08A3 3 0 0 0 5 18c3.356 0 6.993-1.267 9.85-3.151" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 608 B |
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"$schema": "../icon.schema.json",
|
||||
"contributors": [
|
||||
"colebemis",
|
||||
"csandman",
|
||||
"ericfennis",
|
||||
"danielbayley",
|
||||
"pettelau"
|
||||
],
|
||||
"tags": [
|
||||
"alarm",
|
||||
"notification",
|
||||
"sound",
|
||||
"reminder"
|
||||
],
|
||||
"categories": [
|
||||
"account",
|
||||
"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.268 21a2 2 0 0 0 3.464 0" />
|
||||
<path d="m15 8 2 2 4-4" />
|
||||
<path d="M16.8607 4.4824A6 6 0 0 0 6 8C6 12.499 4.589 13.956 3.262 15.326" />
|
||||
<path d="M3.262 15.326A1 1 0 0 0 4 17H20A1 1 0 0 0 20.74 15.327C20.209 14.779 19.665 14.218 19.203 13.454" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 473 B |
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"$schema": "../icon.schema.json",
|
||||
"contributors": [
|
||||
"colebemis",
|
||||
"csandman",
|
||||
"siarie",
|
||||
"ericfennis",
|
||||
"jguddas",
|
||||
"ZeenatLawal",
|
||||
"swastik7805",
|
||||
"karsa-mistmere"
|
||||
],
|
||||
"tags": [
|
||||
"unsaved",
|
||||
"unfavorite",
|
||||
"unmarked",
|
||||
"unlabel",
|
||||
"disabled",
|
||||
"removed",
|
||||
"unpin",
|
||||
"unread",
|
||||
"unclip",
|
||||
"marker",
|
||||
"untag"
|
||||
],
|
||||
"categories": [
|
||||
"account"
|
||||
]
|
||||
}
|
||||
@@ -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="M19 19v1a1 1 0 0 1-1.496.868l-4.512-2.578a2 2 0 0 0-1.984 0l-4.512 2.578A1 1 0 0 1 5 20V5" />
|
||||
<path d="m2 2 20 20" />
|
||||
<path d="M8.656 3H17a2 2 0 0 1 2 2v8.344" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 386 B |
@@ -12,8 +12,8 @@
|
||||
"unlike",
|
||||
"unfavorite",
|
||||
"remove",
|
||||
"damage",
|
||||
"ui & ux"
|
||||
"delete",
|
||||
"damage"
|
||||
],
|
||||
"categories": [
|
||||
"medical",
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
{
|
||||
"$schema": "../icon.schema.json",
|
||||
"contributors": [
|
||||
"colebemis",
|
||||
"ericfennis",
|
||||
"danielbayley",
|
||||
"karsa-mistmere",
|
||||
"jguddas",
|
||||
"Ayberkyvs",
|
||||
"UsamaKhan",
|
||||
"swastik7805"
|
||||
],
|
||||
"tags": [
|
||||
"unlike",
|
||||
"unfavorite",
|
||||
"remove",
|
||||
"reject",
|
||||
"dismiss",
|
||||
"delete",
|
||||
"clear"
|
||||
],
|
||||
"categories": [
|
||||
"social",
|
||||
"multimedia",
|
||||
"design",
|
||||
"shapes"
|
||||
]
|
||||
}
|
||||
@@ -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="m15.5 12.5 5 5" />
|
||||
<path d="m20.5 12.5-5 5" />
|
||||
<path d="M21.955 8.774a5.5 5.5 0 0 0-9.546-2.95.6.6 0 0 1-.818 0A5.5 5.5 0 0 0 2 9.5c0 2.3 1.5 4 3 5.5l5.508 5.332a2 2 0 0 0 2.57.352" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 408 B |
@@ -0,0 +1,27 @@
|
||||
{
|
||||
"$schema": "../icon.schema.json",
|
||||
"contributors": [
|
||||
"colebemis",
|
||||
"danielbayley",
|
||||
"jguddas",
|
||||
"juanisidoro",
|
||||
"karsa-mistmere",
|
||||
"Spleefies"
|
||||
],
|
||||
"tags": [
|
||||
"stack",
|
||||
"pile",
|
||||
"pages",
|
||||
"sheets",
|
||||
"paperwork",
|
||||
"copies",
|
||||
"copy",
|
||||
"layers",
|
||||
"remove",
|
||||
"delete"
|
||||
],
|
||||
"categories": [
|
||||
"design",
|
||||
"layout"
|
||||
]
|
||||
}
|
||||
@@ -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="M12.83 2.18a2 2 0 0 0-1.66 0L2.6 6.08a1 1 0 0 0 0 1.83l8.58 3.91a2 2 0 0 0 .83.18 2 2 0 0 0 .83-.18l8.58-3.9a1 1 0 0 0 0-1.832z" />
|
||||
<path d="M16 17h6" />
|
||||
<path d="M2.003 11.995a1 1 0 0 0 .597.915l8.58 3.91a2 2 0 0 0 .83.18" />
|
||||
<path d="M2.003 16.995a1 1 0 0 0 .597.915l8.58 3.91a2 2 0 0 0 .83.18 2 2 0 0 0 .83-.18l2.11-.96" />
|
||||
<path d="M22.018 12.004a1 1 0 0 1-.598.916l-.177.08" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 610 B |
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"$schema": "../icon.schema.json",
|
||||
"contributors": [
|
||||
"colebemis",
|
||||
"karsa-mistmere",
|
||||
"ericfennis",
|
||||
"csandman",
|
||||
"TonySullivan"
|
||||
],
|
||||
"tags": [
|
||||
"location",
|
||||
"navigation",
|
||||
"travel",
|
||||
"waypoint",
|
||||
"marker",
|
||||
"drop"
|
||||
],
|
||||
"categories": [
|
||||
"text",
|
||||
"navigation",
|
||||
"travel",
|
||||
"account"
|
||||
]
|
||||
}
|
||||
@@ -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="M 12.248 21.969 a 1 1 0 0 1 -0.849 -0.17 C 9.539 20.193 4 14.993 4 10 a 8 8 0 0 1 16 0 C 20 10.42 19.961 10.841 19.888 11.262" />
|
||||
<path d="m22 22-1.88-1.88" />
|
||||
<circle cx="12" cy="10" r="3" />
|
||||
<circle cx="18" cy="18" r="3" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 451 B |
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"$schema": "../icon.schema.json",
|
||||
"contributors": [
|
||||
"kongsgard"
|
||||
],
|
||||
"tags": [
|
||||
"signal",
|
||||
"broadcast",
|
||||
"connectivity",
|
||||
"live",
|
||||
"frequency"
|
||||
],
|
||||
"categories": [
|
||||
"devices",
|
||||
"multimedia",
|
||||
"social"
|
||||
]
|
||||
}
|
||||
@@ -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="M13.414 13.414a2 2 0 1 1-2.828-2.828" />
|
||||
<path d="M16.247 7.761a6 6 0 0 1 1.744 4.572" />
|
||||
<path d="M19.075 4.933a10 10 0 0 1 2.234 10.72" />
|
||||
<path d="m2 2 20 20" />
|
||||
<path d="M4.925 19.067a10 10 0 0 1 0-14.134" />
|
||||
<path d="M7.753 16.239a6 6 0 0 1 0-8.478" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 487 B |
@@ -9,7 +9,7 @@
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<path d="M16.466 7.5C15.643 4.237 13.952 2 12 2 9.239 2 7 6.477 7 12s2.239 10 5 10c.342 0 .677-.069 1-.2" />
|
||||
<path d="m15.194 13.707 3.814 1.86-1.86 3.814" />
|
||||
<path d="M19 15.57c-1.804.885-4.274 1.43-7 1.43-5.523 0-10-2.239-10-5s4.477-5 10-5c4.838 0 8.873 1.718 9.8 4" />
|
||||
<path d="M16.47214 7.52786 A 5 10 0 1 0 13 21.79796" />
|
||||
<path d="M21.79796 11 A 10 5 0 1 0 19 15.57071" />
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 486 B After Width: | Height: | Size: 371 B |
@@ -0,0 +1,60 @@
|
||||
{
|
||||
"$schema": "../icon.schema.json",
|
||||
"contributors": [
|
||||
"colebemis",
|
||||
"karsa-mistmere",
|
||||
"RajnishKMehta"
|
||||
],
|
||||
"tags": [
|
||||
"cybersecurity",
|
||||
"secure",
|
||||
"safety",
|
||||
"protection",
|
||||
"guardian",
|
||||
"armored",
|
||||
"armoured",
|
||||
"defense",
|
||||
"defence",
|
||||
"defender",
|
||||
"block",
|
||||
"threat",
|
||||
"prevention",
|
||||
"antivirus",
|
||||
"vigilance",
|
||||
"vigilant",
|
||||
"detection",
|
||||
"scan",
|
||||
"find",
|
||||
"strength",
|
||||
"strong",
|
||||
"tough",
|
||||
"invincible",
|
||||
"invincibility",
|
||||
"invulnerable",
|
||||
"undamaged",
|
||||
"audit",
|
||||
"admin",
|
||||
"verification",
|
||||
"crest",
|
||||
"shieldcog",
|
||||
"bravery",
|
||||
"knight",
|
||||
"foot soldier",
|
||||
"infantry",
|
||||
"trooper",
|
||||
"pawn",
|
||||
"battle",
|
||||
"war",
|
||||
"military",
|
||||
"army",
|
||||
"cadet",
|
||||
"scout"
|
||||
],
|
||||
"categories": [
|
||||
"account",
|
||||
"security",
|
||||
"development",
|
||||
"gaming",
|
||||
"shapes"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
<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 22c-3.806-1.45-7-3.966-7-9V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1v4" />
|
||||
<path d="M14.923 16.547 14 16.164" />
|
||||
<path d="m14.923 18.843-.923.383" />
|
||||
<path d="M16.547 14.923 16.164 14" />
|
||||
<path d="m16.547 20.467-.383.924" />
|
||||
<path d="m18.843 14.923.383-.923" />
|
||||
<path d="m19.225 21.391-.382-.924" />
|
||||
<path d="m20.467 16.547.923-.383" />
|
||||
<path d="m20.467 18.843.923.383" />
|
||||
<circle cx="17.695" cy="17.695" r="3" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 709 B |
@@ -0,0 +1,59 @@
|
||||
{
|
||||
"$schema": "../icon.schema.json",
|
||||
"contributors": [
|
||||
"colebemis",
|
||||
"karsa-mistmere",
|
||||
"RajnishKMehta"
|
||||
],
|
||||
"tags": [
|
||||
"cybersecurity",
|
||||
"secure",
|
||||
"safety",
|
||||
"protection",
|
||||
"guardian",
|
||||
"armored",
|
||||
"armoured",
|
||||
"defense",
|
||||
"defence",
|
||||
"defender",
|
||||
"block",
|
||||
"threat",
|
||||
"prevention",
|
||||
"antivirus",
|
||||
"vigilance",
|
||||
"vigilant",
|
||||
"detection",
|
||||
"scan",
|
||||
"find",
|
||||
"strength",
|
||||
"strong",
|
||||
"tough",
|
||||
"invincible",
|
||||
"invincibility",
|
||||
"invulnerable",
|
||||
"undamaged",
|
||||
"audit",
|
||||
"admin",
|
||||
"verification",
|
||||
"crest",
|
||||
"bravery",
|
||||
"knight",
|
||||
"foot soldier",
|
||||
"infantry",
|
||||
"trooper",
|
||||
"pawn",
|
||||
"battle",
|
||||
"war",
|
||||
"military",
|
||||
"army",
|
||||
"cadet",
|
||||
"scout"
|
||||
],
|
||||
"categories": [
|
||||
"account",
|
||||
"security",
|
||||
"development",
|
||||
"gaming",
|
||||
"shapes"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
<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.929 14.467-.383.924" />
|
||||
<path d="M10.929 8.923 10.546 8" />
|
||||
<path d="M13.225 8.923 13.608 8" />
|
||||
<path d="m13.607 15.391-.382-.924" />
|
||||
<path d="m14.849 10.547.923-.383" />
|
||||
<path d="m14.849 12.843.923.383" />
|
||||
<path d="M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z" />
|
||||
<path d="m9.305 10.547-.923-.383" />
|
||||
<path d="m9.305 12.843-.923.383" />
|
||||
<circle cx="12.077" cy="11.695" r="3" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 738 B |
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"$schema": "../icon.schema.json",
|
||||
"contributors": [
|
||||
"Youya-ui"
|
||||
],
|
||||
"tags": [
|
||||
"footwear",
|
||||
"sports",
|
||||
"running",
|
||||
"athletic",
|
||||
"shoe",
|
||||
"sneaker",
|
||||
"training",
|
||||
"exercise",
|
||||
"fitness"
|
||||
],
|
||||
"categories": [
|
||||
"sports"
|
||||
]
|
||||
}
|
||||
@@ -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="m15 10.42 4.8-5.07" />
|
||||
<path d="M19 18h3" />
|
||||
<path d="M9.5 22 21.414 9.415A2 2 0 0 0 21.2 6.4l-5.61-4.208A1 1 0 0 0 14 3v2a2 2 0 0 1-1.394 1.906L8.677 8.053A1 1 0 0 0 8 9c-.155 6.393-2.082 9-4 9a2 2 0 0 0 0 4h14" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 439 B |
@@ -19,6 +19,12 @@
|
||||
"deprecationReason": "alias.name",
|
||||
"deprecated": true,
|
||||
"toBeRemovedInVersion": "v1.0"
|
||||
},
|
||||
{
|
||||
"name": "text-select",
|
||||
"deprecated": true,
|
||||
"deprecationReason": "alias.name",
|
||||
"toBeRemovedInVersion": "v1.0"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
Before Width: | Height: | Size: 601 B After Width: | Height: | Size: 601 B |
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"$schema": "../icon.schema.json",
|
||||
"contributors": [
|
||||
"jguddas",
|
||||
"karsa-mistmere"
|
||||
],
|
||||
"tags": [
|
||||
"tags",
|
||||
"history"
|
||||
],
|
||||
"categories": [
|
||||
"time"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
<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="M4 12h.01" />
|
||||
<path d="M4 16h.01" />
|
||||
<path d="M4 20h.01" />
|
||||
<path d="M4 4h.01" />
|
||||
<path d="M4 8h.01" />
|
||||
<path d="M9.414 13.414a2 2 0 0 0 1.414.586H19a1 1 0 0 0 1-1v-2a1 1 0 0 0-1-1h-8.172a2 2 0 0 0-1.414.586L8 12z" />
|
||||
<path d="M9.414 21.414a2 2 0 0 0 1.414.586H19a1 1 0 0 0 1-1v-2a1 1 0 0 0-1-1h-8.172a2 2 0 0 0-1.414.586L8 20z" />
|
||||
<path d="M9.414 5.414A2 2 0 0 0 10.828 6H19a1 1 0 0 0 1-1V3a1 1 0 0 0-1-1h-8.172a2 2 0 0 0-1.414.586L8 4z" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 675 B |
@@ -10,7 +10,8 @@
|
||||
"camera",
|
||||
"lightning",
|
||||
"electricity",
|
||||
"energy"
|
||||
"energy",
|
||||
"power"
|
||||
],
|
||||
"categories": [
|
||||
"connectivity",
|
||||
|
||||
@@ -9,7 +9,9 @@
|
||||
"camera",
|
||||
"lightning",
|
||||
"electricity",
|
||||
"energy"
|
||||
"energy",
|
||||
"power",
|
||||
"quick"
|
||||
],
|
||||
"categories": [
|
||||
"connectivity",
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
"build": "pnpm -r --filter './packages/**' build",
|
||||
"test": "pnpm -r --filter './packages/**' test",
|
||||
"test:update": "pnpm -r --filter './packages/**' --filter !'./packages/lucide-angular' test -- -u",
|
||||
"test:font": "pnpm --filter build-font test",
|
||||
"lucide": "pnpm --filter lucide",
|
||||
"lucide-angular": "pnpm --filter lucide-angular",
|
||||
"lucide-react": "pnpm --filter lucide-react",
|
||||
@@ -21,7 +22,7 @@
|
||||
"addjsons": "node ./scripts/addMissingIconJsonFiles.mts",
|
||||
"checkIcons": "node ./scripts/checkIconsAndCategories.mts",
|
||||
"generate:changelog": "node ./scripts/generateChangelog.mts",
|
||||
"generate:backers": "node scripts/updateOpenCollectiveBackers.mts",
|
||||
"generate:sponsors": "node scripts/updateSponsors.mts",
|
||||
"generate:contributors": "node ./scripts/updateContributors.mts icons/*.svg",
|
||||
"generate:nextJSAliases": "node ./scripts/generateNextJSAliases.mts",
|
||||
"suggest:tags": "node ./scripts/suggestTags.mts",
|
||||
@@ -71,7 +72,7 @@
|
||||
"prettier-plugin-astro": "^0.14.1",
|
||||
"semver": "^7.7.3",
|
||||
"simple-git": "^3.32.3",
|
||||
"svgo": "^3.3.2",
|
||||
"svgo": "^3.3.3",
|
||||
"svgson": "^5.3.1",
|
||||
"vitest": "4.0.12",
|
||||
"yargs": "^17.7.2",
|
||||
|
||||
@@ -63,6 +63,8 @@ Join the [Discord server](https://discord.gg/EH6nSts) to chat with the maintaine
|
||||
|
||||
Lucide is licensed under the ISC license. See [LICENSE](https://lucide.dev/license).
|
||||
|
||||
[//]: <> (Sponsors)
|
||||
|
||||
## Sponsors
|
||||
|
||||
<a href="https://vercel.com?utm_source=lucide&utm_campaign=oss">
|
||||
@@ -71,7 +73,19 @@ Lucide is licensed under the ISC license. See [LICENSE](https://lucide.dev/licen
|
||||
|
||||
<a href="https://www.digitalocean.com/?refcode=b0877a2caebd&utm_campaign=Referral_Invite&utm_medium=Referral_Program&utm_source=badge"><img src="https://lucide.dev/digitalocean.svg" width="200" alt="DigitalOcean Referral Badge" /></a>
|
||||
|
||||
### Hero backers 🦸
|
||||
|
||||
<a href="https://https://zephyr-cloud.io/"><img src="https://lucide.dev/sponsors/zephyr-cloud.svg" width="180" alt="Zephyr Cloud – From idea to prod: fast micro-frontend delivery!" /></a>
|
||||
|
||||
### Awesome backers 🍺
|
||||
|
||||
<a href="https://www.scipress.io?utm_source=lucide"><img src="https://lucide.dev/sponsors/scipress.svg" width="180" alt="Scipress sponsor badge" /></a>
|
||||
<a href="https://github.com/pdfme/pdfme"><img src="https://lucide.dev/sponsors/pdfme.svg" width="180" alt="pdfme sponsor badge" /></a>
|
||||
<a href="https://github.com/pdfme/pdfme"><img src="https://lucide.dev/sponsors/pdfme.svg" width="180" alt="pdfme – Open-source PDF generation library built with TypeScript and React." /></a>
|
||||
<a href="https://www.paxhistoria.co/"><img src="https://lucide.dev/sponsors/paxhistoria.svg?" width="180" alt="Pax Historia – An alternate history sandbox game" /></a>
|
||||
|
||||
### Backers ☕
|
||||
|
||||
<a href="https://www.fina.money/"><img src="https://lucide.dev/sponsors/fina-money.png" width="180" alt="Fina Money – Modular Finance Tracker" /></a>
|
||||
|
||||
### Other contributors 💸
|
||||
|
||||
You can find all our past and non-recurring financial contributors at [our Open Collective page](https://opencollective.com/lucide-icons).
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
"projectType": "library",
|
||||
"root": ".",
|
||||
"sourceRoot": "./src",
|
||||
"prefix": "lib",
|
||||
"prefix": "lucide",
|
||||
"architect": {
|
||||
"build": {
|
||||
"builder": "@angular/build:ng-packagr",
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
"clean": "rm -rf dist && rm -rf ./src/icons/*.ts",
|
||||
"build:icons": "build-icons --output=./src --templateSrc=./scripts/exportTemplate.mts --renderUniqueKey --iconFileExtension=.ts --exportFileName=lucide-angular.ts --useDefaultExports=0",
|
||||
"build:ng": "ng build --configuration production",
|
||||
"test": "pnpm prebuild && ng test --no-watch",
|
||||
"test": "pnpm build:icons && ng test --no-watch",
|
||||
"test:watch": "ng test",
|
||||
"lint": "npx eslint 'src/**/*.{js,jsx,ts,tsx,html,css,scss}' --quiet --fix",
|
||||
"e2e": "ng e2e",
|
||||
|
||||
@@ -13,7 +13,7 @@ export interface LucideConfig {
|
||||
* Width and height.
|
||||
* @default 24
|
||||
*/
|
||||
size: number;
|
||||
size: string | number;
|
||||
/**
|
||||
* Stroke width
|
||||
* @default 2
|
||||
|
||||
@@ -113,12 +113,6 @@ describe('LucideIconBase', () => {
|
||||
expect(getSvgAttribute('width')).toBe('18');
|
||||
expect(getSvgAttribute('height')).toBe('18');
|
||||
});
|
||||
it('should use default on invalid string', () => {
|
||||
size.set('large');
|
||||
fixture.detectChanges();
|
||||
expect(getSvgAttribute('width')).toBe('24');
|
||||
expect(getSvgAttribute('height')).toBe('24');
|
||||
});
|
||||
});
|
||||
|
||||
describe('strokeWidth', () => {
|
||||
@@ -132,9 +126,9 @@ describe('LucideIconBase', () => {
|
||||
expect(getSvgAttribute('stroke-width')).toBe('1.41');
|
||||
});
|
||||
it('should allow string stroke width', () => {
|
||||
strokeWidth.set('1px');
|
||||
strokeWidth.set('0.125rem');
|
||||
fixture.detectChanges();
|
||||
expect(getSvgAttribute('stroke-width')).toBe('1');
|
||||
expect(getSvgAttribute('stroke-width')).toBe('0.125rem');
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -13,20 +13,6 @@ import { LucideIconData, Nullable } from './types';
|
||||
import defaultAttributes from './default-attributes';
|
||||
import { lucideIconTemplate } from './lucide-icon-template';
|
||||
|
||||
function transformNumericStringInput(
|
||||
value: Nullable<string | number>,
|
||||
defaultValue: number,
|
||||
): number {
|
||||
if (typeof value === 'string') {
|
||||
const parsedValue = parseInt(value, 10);
|
||||
if (isNaN(parsedValue)) {
|
||||
return defaultValue;
|
||||
}
|
||||
return parsedValue;
|
||||
}
|
||||
return value ?? defaultValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
@@ -37,10 +23,10 @@ function transformNumericStringInput(
|
||||
host: {
|
||||
...defaultAttributes,
|
||||
class: 'lucide',
|
||||
'[attr.width]': 'size().toString(10)',
|
||||
'[attr.height]': 'size().toString(10)',
|
||||
'[attr.width]': 'size()',
|
||||
'[attr.height]': 'size()',
|
||||
'[attr.stroke]': 'color()',
|
||||
'[attr.stroke-width]': 'strokeWidth().toString(10)',
|
||||
'[attr.stroke-width]': 'strokeWidth()',
|
||||
'[attr.aria-hidden]': '!title()',
|
||||
},
|
||||
})
|
||||
@@ -68,8 +54,7 @@ export abstract class LucideIconBase {
|
||||
* @default 24
|
||||
*/
|
||||
readonly size = input(this.iconConfig.size, {
|
||||
transform: (value: Nullable<string | number>) =>
|
||||
transformNumericStringInput(value, this.iconConfig.size),
|
||||
transform: (value: Nullable<string | number>) => value ?? this.iconConfig.size,
|
||||
});
|
||||
/**
|
||||
* Stroke color.
|
||||
@@ -83,8 +68,7 @@ export abstract class LucideIconBase {
|
||||
* @default 2
|
||||
*/
|
||||
readonly strokeWidth = input(this.iconConfig.strokeWidth, {
|
||||
transform: (value: Nullable<string | number>) =>
|
||||
transformNumericStringInput(value, this.iconConfig.strokeWidth),
|
||||
transform: (value: Nullable<string | number>) => value ?? this.iconConfig.strokeWidth,
|
||||
});
|
||||
/**
|
||||
* If set to true, it adds [`vector-effect="non-scaling-stroke"`](https://developer.mozilla.org/en-US/docs/Web/SVG/Reference/Attribute/vector-effect) to child elements.
|
||||
|
||||
@@ -19,9 +19,9 @@ export type LucideIconData = {
|
||||
*/
|
||||
interface LucideIconProps {
|
||||
title: Signal<Nullable<string>>;
|
||||
size: Signal<Nullable<number>>;
|
||||
size: Signal<Nullable<number | string>>;
|
||||
color: Signal<Nullable<string>>;
|
||||
strokeWidth: Signal<Nullable<number>>;
|
||||
strokeWidth: Signal<Nullable<number | string>>;
|
||||
absoluteStrokeWidth: Signal<Nullable<boolean>>;
|
||||
}
|
||||
|
||||
|
||||
@@ -60,6 +60,8 @@ Join the [Discord server](https://discord.gg/EH6nSts) to chat with the maintaine
|
||||
|
||||
Lucide is licensed under the ISC license. See [LICENSE](https://lucide.dev/license).
|
||||
|
||||
[//]: <> (Sponsors)
|
||||
|
||||
## Sponsors
|
||||
|
||||
<a href="https://vercel.com?utm_source=lucide&utm_campaign=oss">
|
||||
@@ -68,7 +70,10 @@ Lucide is licensed under the ISC license. See [LICENSE](https://lucide.dev/licen
|
||||
|
||||
<a href="https://www.digitalocean.com/?refcode=b0877a2caebd&utm_campaign=Referral_Invite&utm_medium=Referral_Program&utm_source=badge"><img src="https://lucide.dev/digitalocean.svg" width="200" alt="DigitalOcean Referral Badge" /></a>
|
||||
|
||||
[//]: <> (Open Collective backers)
|
||||
### Hero backers 🦸
|
||||
|
||||
<a href="https://https://zephyr-cloud.io/"><img src="https://lucide.dev/sponsors/zephyr-cloud.svg" width="180" alt="Zephyr Cloud – From idea to prod: fast micro-frontend delivery!" /></a>
|
||||
|
||||
### Awesome backers 🍺
|
||||
|
||||
<a href="https://github.com/pdfme/pdfme"><img src="https://lucide.dev/sponsors/pdfme.svg" width="180" alt="pdfme – Open-source PDF generation library built with TypeScript and React." /></a>
|
||||
|
||||
@@ -57,9 +57,9 @@
|
||||
"linkedom": "^0.18.5",
|
||||
"prettier": "^3.4.2",
|
||||
"typescript": "^5.8.3",
|
||||
"vite": "^7.3.1",
|
||||
"vite": "^7.3.2",
|
||||
"vitest": "^4.1.1",
|
||||
"astro": "^6.0.8"
|
||||
"astro": "^6.1.6"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"astro": "^4 || ^5 || ^6"
|
||||
|
||||
@@ -68,6 +68,8 @@ Join the [Discord server](https://discord.gg/EH6nSts) to chat with the maintaine
|
||||
|
||||
Lucide is licensed under the ISC license. See [LICENSE](https://lucide.dev/license).
|
||||
|
||||
[//]: <> (Sponsors)
|
||||
|
||||
## Sponsors
|
||||
|
||||
<a href="https://vercel.com?utm_source=lucide&utm_campaign=oss">
|
||||
@@ -76,7 +78,19 @@ Lucide is licensed under the ISC license. See [LICENSE](https://lucide.dev/licen
|
||||
|
||||
<a href="https://www.digitalocean.com/?refcode=b0877a2caebd&utm_campaign=Referral_Invite&utm_medium=Referral_Program&utm_source=badge"><img src="https://lucide.dev/digitalocean.svg" width="200" alt="DigitalOcean Referral Badge" /></a>
|
||||
|
||||
### Hero backers 🦸
|
||||
|
||||
<a href="https://https://zephyr-cloud.io/"><img src="https://lucide.dev/sponsors/zephyr-cloud.svg" width="180" alt="Zephyr Cloud – From idea to prod: fast micro-frontend delivery!" /></a>
|
||||
|
||||
### Awesome backers 🍺
|
||||
|
||||
<a href="https://www.scipress.io?utm_source=lucide"><img src="https://lucide.dev/sponsors/scipress.svg" width="180" alt="Scipress sponsor badge" /></a>
|
||||
<a href="https://github.com/pdfme/pdfme"><img src="../../docs/public/sponsors/pdfme.svg" width="180" alt="pdfme sponsor badge" /></a>
|
||||
<a href="https://github.com/pdfme/pdfme"><img src="https://lucide.dev/sponsors/pdfme.svg" width="180" alt="pdfme – Open-source PDF generation library built with TypeScript and React." /></a>
|
||||
<a href="https://www.paxhistoria.co/"><img src="https://lucide.dev/sponsors/paxhistoria.svg?" width="180" alt="Pax Historia – An alternate history sandbox game" /></a>
|
||||
|
||||
### Backers ☕
|
||||
|
||||
<a href="https://www.fina.money/"><img src="https://lucide.dev/sponsors/fina-money.png" width="180" alt="Fina Money – Modular Finance Tracker" /></a>
|
||||
|
||||
### Other contributors 💸
|
||||
|
||||
You can find all our past and non-recurring financial contributors at [our Open Collective page](https://opencollective.com/lucide-icons).
|
||||
|
||||
@@ -59,6 +59,8 @@ Join the [Discord server](https://discord.gg/EH6nSts) to chat with the maintaine
|
||||
|
||||
Lucide is licensed under the ISC license. See [LICENSE](https://lucide.dev/license).
|
||||
|
||||
[//]: <> (Sponsors)
|
||||
|
||||
## Sponsors
|
||||
|
||||
<a href="https://vercel.com?utm_source=lucide&utm_campaign=oss">
|
||||
@@ -67,7 +69,10 @@ Lucide is licensed under the ISC license. See [LICENSE](https://lucide.dev/licen
|
||||
|
||||
<a href="https://www.digitalocean.com/?refcode=b0877a2caebd&utm_campaign=Referral_Invite&utm_medium=Referral_Program&utm_source=badge"><img src="https://lucide.dev/digitalocean.svg" width="200" alt="DigitalOcean Referral Badge" /></a>
|
||||
|
||||
[//]: <> (Open Collective backers)
|
||||
### Hero backers 🦸
|
||||
|
||||
<a href="https://https://zephyr-cloud.io/"><img src="https://lucide.dev/sponsors/zephyr-cloud.svg" width="180" alt="Zephyr Cloud – From idea to prod: fast micro-frontend delivery!" /></a>
|
||||
|
||||
### Awesome backers 🍺
|
||||
|
||||
<a href="https://github.com/pdfme/pdfme"><img src="https://lucide.dev/sponsors/pdfme.svg" width="180" alt="pdfme – Open-source PDF generation library built with TypeScript and React." /></a>
|
||||
|
||||
@@ -59,6 +59,8 @@ Join the [Discord server](https://discord.gg/EH6nSts) to chat with the maintaine
|
||||
|
||||
Lucide is licensed under the ISC license. See [LICENSE](https://lucide.dev/license).
|
||||
|
||||
[//]: <> (Sponsors)
|
||||
|
||||
## Sponsors
|
||||
|
||||
<a href="https://vercel.com?utm_source=lucide&utm_campaign=oss">
|
||||
@@ -67,7 +69,10 @@ Lucide is licensed under the ISC license. See [LICENSE](https://lucide.dev/licen
|
||||
|
||||
<a href="https://www.digitalocean.com/?refcode=b0877a2caebd&utm_campaign=Referral_Invite&utm_medium=Referral_Program&utm_source=badge"><img src="https://lucide.dev/digitalocean.svg" width="200" alt="DigitalOcean Referral Badge" /></a>
|
||||
|
||||
[//]: <> (Open Collective backers)
|
||||
### Hero backers 🦸
|
||||
|
||||
<a href="https://https://zephyr-cloud.io/"><img src="https://lucide.dev/sponsors/zephyr-cloud.svg" width="180" alt="Zephyr Cloud – From idea to prod: fast micro-frontend delivery!" /></a>
|
||||
|
||||
### Awesome backers 🍺
|
||||
|
||||
<a href="https://github.com/pdfme/pdfme"><img src="https://lucide.dev/sponsors/pdfme.svg" width="180" alt="pdfme – Open-source PDF generation library built with TypeScript and React." /></a>
|
||||
|
||||
@@ -24,11 +24,11 @@
|
||||
"author": "Eric Fennis",
|
||||
"amdName": "lucide-preact",
|
||||
"main": "dist/cjs/lucide-preact.js",
|
||||
"module": "dist/esm/lucide-preact.js",
|
||||
"module": "dist/esm/lucide-preact.mjs",
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./dist/lucide-preact.d.ts",
|
||||
"import": "./dist/esm/lucide-preact.js",
|
||||
"import": "./dist/esm/lucide-preact.mjs",
|
||||
"require": "./dist/cjs/lucide-preact.js"
|
||||
}
|
||||
},
|
||||
|
||||
@@ -17,11 +17,12 @@ const bundles = [
|
||||
inputs,
|
||||
outputDir,
|
||||
preserveModules: true,
|
||||
extension: 'mjs',
|
||||
},
|
||||
];
|
||||
|
||||
const configs = bundles
|
||||
.map(({ inputs, outputDir, format, preserveModules }) =>
|
||||
.map(({ inputs, outputDir, format, preserveModules, extension = 'js' }) =>
|
||||
inputs.map((input) => ({
|
||||
input,
|
||||
plugins: plugins({ pkg }),
|
||||
@@ -31,9 +32,10 @@ const configs = bundles
|
||||
...(preserveModules
|
||||
? {
|
||||
dir: `${outputDir}/${format}`,
|
||||
entryFileNames: `[name].${extension}`,
|
||||
}
|
||||
: {
|
||||
file: `${outputDir}/${format}/${outputFileName}.js`,
|
||||
file: `${outputDir}/${format}/${outputFileName}.${extension}`,
|
||||
}),
|
||||
preserveModules,
|
||||
format,
|
||||
|
||||
@@ -59,6 +59,8 @@ Join the [Discord server](https://discord.gg/EH6nSts) to chat with the maintaine
|
||||
|
||||
Lucide is licensed under the ISC license. See [LICENSE](https://lucide.dev/license).
|
||||
|
||||
[//]: <> (Sponsors)
|
||||
|
||||
## Sponsors
|
||||
|
||||
<a href="https://vercel.com?utm_source=lucide&utm_campaign=oss">
|
||||
@@ -67,7 +69,10 @@ Lucide is licensed under the ISC license. See [LICENSE](https://lucide.dev/licen
|
||||
|
||||
<a href="https://www.digitalocean.com/?refcode=b0877a2caebd&utm_campaign=Referral_Invite&utm_medium=Referral_Program&utm_source=badge"><img src="https://lucide.dev/digitalocean.svg" width="200" alt="DigitalOcean Referral Badge" /></a>
|
||||
|
||||
[//]: <> (Open Collective backers)
|
||||
### Hero backers 🦸
|
||||
|
||||
<a href="https://https://zephyr-cloud.io/"><img src="https://lucide.dev/sponsors/zephyr-cloud.svg" width="180" alt="Zephyr Cloud – From idea to prod: fast micro-frontend delivery!" /></a>
|
||||
|
||||
### Awesome backers 🍺
|
||||
|
||||
<a href="https://github.com/pdfme/pdfme"><img src="https://lucide.dev/sponsors/pdfme.svg" width="180" alt="pdfme – Open-source PDF generation library built with TypeScript and React." /></a>
|
||||
|
||||
@@ -24,20 +24,20 @@
|
||||
"author": "Eric Fennis",
|
||||
"amdName": "lucide-react-native",
|
||||
"main": "dist/cjs/lucide-react-native.js",
|
||||
"module": "dist/esm/lucide-react-native.js",
|
||||
"module": "dist/esm/lucide-react-native.mjs",
|
||||
"typings": "dist/lucide-react-native.d.ts",
|
||||
"react-native": "dist/esm/lucide-react-native.js",
|
||||
"react-native": "dist/esm/lucide-react-native.mjs",
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./dist/lucide-react-native.d.ts",
|
||||
"import": "./dist/esm/lucide-react-native.js",
|
||||
"browser": "./dist/esm/lucide-react-native.js",
|
||||
"import": "./dist/esm/lucide-react-native.mjs",
|
||||
"browser": "./dist/esm/lucide-react-native.mjs",
|
||||
"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",
|
||||
"import": "./dist/esm/icons/index.mjs",
|
||||
"browser": "./dist/esm/icons/index.mjs",
|
||||
"require": "./dist/cjs/icons/index.js"
|
||||
}
|
||||
},
|
||||
|
||||
@@ -18,11 +18,12 @@ const bundles = [
|
||||
inputs,
|
||||
outputDir,
|
||||
preserveModules: true,
|
||||
extension: 'mjs',
|
||||
},
|
||||
];
|
||||
|
||||
const configs = bundles
|
||||
.map(({ inputs, outputDir, format, preserveModules }) =>
|
||||
.map(({ inputs, outputDir, format, preserveModules, extension = 'js' }) =>
|
||||
inputs.map((input) => ({
|
||||
input,
|
||||
plugins: plugins({ pkg }),
|
||||
@@ -33,9 +34,10 @@ const configs = bundles
|
||||
? {
|
||||
dir: `${outputDir}/${format}`,
|
||||
exports: 'auto',
|
||||
entryFileNames: `[name].${extension}`,
|
||||
}
|
||||
: {
|
||||
file: `${outputDir}/${format}/${outputFileName}.js`,
|
||||
file: `${outputDir}/${format}/${outputFileName}.${extension}`,
|
||||
}),
|
||||
format,
|
||||
preserveModules,
|
||||
|
||||
@@ -59,6 +59,8 @@ Join the [Discord server](https://discord.gg/EH6nSts) to chat with the maintaine
|
||||
|
||||
Lucide is licensed under the ISC license. See [LICENSE](https://lucide.dev/license).
|
||||
|
||||
[//]: <> (Sponsors)
|
||||
|
||||
## Sponsors
|
||||
|
||||
<a href="https://vercel.com?utm_source=lucide&utm_campaign=oss">
|
||||
@@ -67,7 +69,10 @@ Lucide is licensed under the ISC license. See [LICENSE](https://lucide.dev/licen
|
||||
|
||||
<a href="https://www.digitalocean.com/?refcode=b0877a2caebd&utm_campaign=Referral_Invite&utm_medium=Referral_Program&utm_source=badge"><img src="https://lucide.dev/digitalocean.svg" width="200" alt="DigitalOcean Referral Badge" /></a>
|
||||
|
||||
[//]: <> (Open Collective backers)
|
||||
### Hero backers 🦸
|
||||
|
||||
<a href="https://https://zephyr-cloud.io/"><img src="https://lucide.dev/sponsors/zephyr-cloud.svg" width="180" alt="Zephyr Cloud – From idea to prod: fast micro-frontend delivery!" /></a>
|
||||
|
||||
### Awesome backers 🍺
|
||||
|
||||
<a href="https://github.com/pdfme/pdfme"><img src="https://lucide.dev/sponsors/pdfme.svg" width="180" alt="pdfme – Open-source PDF generation library built with TypeScript and React." /></a>
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
// This file is make sure that we can import from "lucide-react/dynamic" without having to specify the extension. This is a workaround for the fact that some bundlers (like Webpack) don't support importing from "lucide-react/dynamic.mjs" without specifying the extension.
|
||||
// Unfortunately, we can't use exports field in package.json because it breaks some runtime environments. See https://github.com/lucide-icons/lucide/issues/2743#issuecomment-2626784300
|
||||
// eslint-disable-next-line import/no-unresolved
|
||||
export * from './dynamic.mjs';
|
||||
@@ -1 +1 @@
|
||||
export { default } from './dist/esm/dynamicIconImports.js';
|
||||
export { default } from './dist/esm/dynamicIconImports.mjs';
|
||||
|
||||
@@ -24,22 +24,24 @@
|
||||
"author": "Eric Fennis",
|
||||
"amdName": "lucide-react",
|
||||
"main": "dist/cjs/lucide-react.js",
|
||||
"module": "dist/esm/lucide-react.js",
|
||||
"module": "dist/esm/lucide-react.mjs",
|
||||
"typings": "dist/lucide-react.d.ts",
|
||||
"sideEffects": false,
|
||||
"files": [
|
||||
"dist",
|
||||
"dynamic.js",
|
||||
"dynamic.mjs",
|
||||
"dynamic.js.map",
|
||||
"dynamic.mjs.map",
|
||||
"dynamic.d.mts",
|
||||
"dynamic.d.ts",
|
||||
"dynamicIconImports.mjs",
|
||||
"dynamicIconImports.js.map",
|
||||
"dynamicIconImports.d.ts"
|
||||
"dynamicIconImports.d.ts",
|
||||
"dynamicIconImports.d.mts"
|
||||
],
|
||||
"scripts": {
|
||||
"build": "pnpm clean && pnpm copy:license && pnpm build:icons && pnpm typecheck && pnpm build:bundles",
|
||||
"copy:license": "cp ../../LICENSE ./LICENSE",
|
||||
"clean": "rm -rf dist && rm -rf stats && rm -rf ./src/icons/*.ts && rm -f dynamic.* && rm -f dynamicIconImports.d.ts",
|
||||
"clean": "rm -rf dist && rm -rf stats && rm -rf ./src/icons/*.ts && rm -f dynamic.{d.ts,d.mts,mts,mjs,mjs.map} && rm -f dynamicIconImports.d.ts",
|
||||
"build:icons": "build-icons --output=./src --templateSrc=./scripts/exportTemplate.mts --renderUniqueKey --withAliases --withDynamicImports --separateAliasesFile --separateAliasesFileIgnore=fingerprint --aliasesFileExtension=.ts --iconFileExtension=.ts --exportFileName=index.ts",
|
||||
"build:bundles": "rollup -c ./rollup.config.mjs",
|
||||
"typecheck": "tsc",
|
||||
|
||||
@@ -14,31 +14,41 @@ const bundles = [
|
||||
format: 'cjs',
|
||||
inputs,
|
||||
outputDir: 'dist/cjs',
|
||||
extension: 'js',
|
||||
},
|
||||
{
|
||||
format: 'esm',
|
||||
inputs,
|
||||
outputDir: 'dist/esm',
|
||||
preserveModules: true,
|
||||
extension: 'mjs',
|
||||
},
|
||||
|
||||
{
|
||||
format: 'esm',
|
||||
inputs: ['src/dynamicIconImports.ts', 'src/DynamicIcon.ts', ...aliasesEntries],
|
||||
outputDir: 'dist/esm',
|
||||
external: [/src/],
|
||||
preserveModules: true,
|
||||
extension: 'mjs',
|
||||
paths: (id) => {
|
||||
if (id.match(/src/)) {
|
||||
const [, modulePath] = id.match(/src\/(.*)\.ts/);
|
||||
|
||||
return `./${modulePath}.mjs`;
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
format: 'esm',
|
||||
inputs: ['src/dynamic.ts'],
|
||||
outputFile: 'dynamic.mjs',
|
||||
external: [/src/],
|
||||
extension: 'mjs',
|
||||
paths: (id) => {
|
||||
if (id.match(/src/)) {
|
||||
const [, modulePath] = id.match(/src\/(.*)\.ts/);
|
||||
|
||||
return `dist/esm/${modulePath}.js`;
|
||||
return `dist/esm/${modulePath}.mjs`;
|
||||
}
|
||||
},
|
||||
},
|
||||
@@ -54,6 +64,7 @@ const configs = bundles
|
||||
minify,
|
||||
preserveModules,
|
||||
entryFileNames,
|
||||
extension = 'js',
|
||||
external = [],
|
||||
paths,
|
||||
}) =>
|
||||
@@ -63,7 +74,7 @@ const configs = bundles
|
||||
...plugins({ pkg, minify }),
|
||||
// Make sure we emit "use client" directive to make it compatible with Next.js
|
||||
preserveDirectives({
|
||||
include: ['src/DynamicIcon.ts', 'src/context.ts', 'src/Icon.ts'],
|
||||
include: ['src/lucide-react.ts', 'src/DynamicIcon.ts', 'src/context.ts', 'src/Icon.ts'],
|
||||
suppressPreserveModulesWarning: true,
|
||||
}),
|
||||
],
|
||||
@@ -73,12 +84,12 @@ const configs = bundles
|
||||
...(preserveModules
|
||||
? {
|
||||
dir: outputDir,
|
||||
entryFileNames: entryFileNames ?? `[name].${extension}`,
|
||||
}
|
||||
: {
|
||||
file: outputFile ?? `${outputDir}/${outputFileName}.js`,
|
||||
file: outputFile ?? `${outputDir}/${outputFileName}.${extension}`,
|
||||
}),
|
||||
paths,
|
||||
entryFileNames,
|
||||
format,
|
||||
sourcemap: true,
|
||||
preserveModules,
|
||||
@@ -100,6 +111,11 @@ export default [
|
||||
file: `dynamicIconImports.d.ts`,
|
||||
format: 'es',
|
||||
},
|
||||
// Extra declaration file with .d.mts extension for better compatibility with ESM environments
|
||||
{
|
||||
file: `dynamicIconImports.d.mts`,
|
||||
format: 'es',
|
||||
},
|
||||
],
|
||||
plugins: [dts()],
|
||||
},
|
||||
@@ -110,6 +126,11 @@ export default [
|
||||
file: `dynamic.d.ts`,
|
||||
format: 'es',
|
||||
},
|
||||
// Extra declaration file with .d.mts extension for better compatibility with ESM environments
|
||||
{
|
||||
file: `dynamic.d.mts`,
|
||||
format: 'es',
|
||||
},
|
||||
],
|
||||
plugins: [dts()],
|
||||
},
|
||||
|
||||
@@ -59,6 +59,8 @@ Join the [Discord server](https://discord.gg/EH6nSts) to chat with the maintaine
|
||||
|
||||
Lucide is licensed under the ISC license. See [LICENSE](https://lucide.dev/license).
|
||||
|
||||
[//]: <> (Sponsors)
|
||||
|
||||
## Sponsors
|
||||
|
||||
<a href="https://vercel.com?utm_source=lucide&utm_campaign=oss">
|
||||
@@ -67,7 +69,10 @@ Lucide is licensed under the ISC license. See [LICENSE](https://lucide.dev/licen
|
||||
|
||||
<a href="https://www.digitalocean.com/?refcode=b0877a2caebd&utm_campaign=Referral_Invite&utm_medium=Referral_Program&utm_source=badge"><img src="https://lucide.dev/digitalocean.svg" width="200" alt="DigitalOcean Referral Badge" /></a>
|
||||
|
||||
[//]: <> (Open Collective backers)
|
||||
### Hero backers 🦸
|
||||
|
||||
<a href="https://https://zephyr-cloud.io/"><img src="https://lucide.dev/sponsors/zephyr-cloud.svg" width="180" alt="Zephyr Cloud – From idea to prod: fast micro-frontend delivery!" /></a>
|
||||
|
||||
### Awesome backers 🍺
|
||||
|
||||
<a href="https://github.com/pdfme/pdfme"><img src="https://lucide.dev/sponsors/pdfme.svg" width="180" alt="pdfme – Open-source PDF generation library built with TypeScript and React." /></a>
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
"author": "Eric Fennis",
|
||||
"source": "src/lucide-solid.ts",
|
||||
"main": "dist/cjs/lucide-solid.js",
|
||||
"module": "dist/esm/lucide-solid.js",
|
||||
"module": "dist/esm/lucide-solid.mjs",
|
||||
"types": "dist/types/lucide-solid.d.ts",
|
||||
"files": [
|
||||
"dist"
|
||||
@@ -34,22 +34,22 @@
|
||||
".": {
|
||||
"types": "./dist/types/lucide-solid.d.ts",
|
||||
"solid": "./dist/source/lucide-solid.jsx",
|
||||
"import": "./dist/esm/lucide-solid.js",
|
||||
"browser": "./dist/esm/lucide-solid.js",
|
||||
"import": "./dist/esm/lucide-solid.mjs",
|
||||
"browser": "./dist/esm/lucide-solid.mjs",
|
||||
"require": "./dist/cjs/lucide-solid.js"
|
||||
},
|
||||
"./icons": {
|
||||
"types": "./dist/types/lucide-solid.d.ts",
|
||||
"solid": "./dist/source/lucide-solid.jsx",
|
||||
"import": "./dist/esm/lucide-solid.js",
|
||||
"browser": "./dist/esm/lucide-solid.js",
|
||||
"import": "./dist/esm/lucide-solid.mjs",
|
||||
"browser": "./dist/esm/lucide-solid.mjs",
|
||||
"require": "./dist/cjs/lucide-solid.js"
|
||||
},
|
||||
"./icons/*": {
|
||||
"types": "./dist/types/icons/*.d.ts",
|
||||
"solid": "./dist/source/icons/*.jsx",
|
||||
"import": "./dist/esm/icons/*.js",
|
||||
"browser": "./dist/esm/icons/*.js",
|
||||
"import": "./dist/esm/icons/*.mjs",
|
||||
"browser": "./dist/esm/icons/*.mjs",
|
||||
"require": "./dist/cjs/icons/*.js"
|
||||
}
|
||||
},
|
||||
|
||||
@@ -23,11 +23,12 @@ const bundles = [
|
||||
inputs,
|
||||
outputDir,
|
||||
preserveModules: true,
|
||||
extension: 'mjs',
|
||||
},
|
||||
];
|
||||
|
||||
const configs = bundles
|
||||
.map(({ inputs, outputDir, format, preserveModules }) =>
|
||||
.map(({ inputs, outputDir, format, preserveModules, extension = 'js' }) =>
|
||||
inputs.map((input) => ({
|
||||
input,
|
||||
plugins: [
|
||||
@@ -117,9 +118,10 @@ const configs = bundles
|
||||
? {
|
||||
dir: `${outputDir}/${format}`,
|
||||
exports: 'auto',
|
||||
entryFileNames: `[name].${extension}`,
|
||||
}
|
||||
: {
|
||||
file: `${outputDir}/${format}/${outputFileName}.js`,
|
||||
file: `${outputDir}/${format}/${outputFileName}.${extension}`,
|
||||
}),
|
||||
format: format === 'source' ? 'esm' : format,
|
||||
preserveModules,
|
||||
|
||||
@@ -73,6 +73,8 @@ Join the [Discord server](https://discord.gg/EH6nSts) to chat with the maintaine
|
||||
|
||||
Lucide is licensed under the ISC license. See [LICENSE](https://lucide.dev/license).
|
||||
|
||||
[//]: <> (Sponsors)
|
||||
|
||||
## Sponsors
|
||||
|
||||
<a href="https://vercel.com?utm_source=lucide&utm_campaign=oss">
|
||||
@@ -81,7 +83,10 @@ Lucide is licensed under the ISC license. See [LICENSE](https://lucide.dev/licen
|
||||
|
||||
<a href="https://www.digitalocean.com/?refcode=b0877a2caebd&utm_campaign=Referral_Invite&utm_medium=Referral_Program&utm_source=badge"><img src="https://lucide.dev/digitalocean.svg" width="200" alt="DigitalOcean Referral Badge" /></a>
|
||||
|
||||
[//]: <> (Open Collective backers)
|
||||
### Hero backers 🦸
|
||||
|
||||
<a href="https://https://zephyr-cloud.io/"><img src="https://lucide.dev/sponsors/zephyr-cloud.svg" width="180" alt="Zephyr Cloud – From idea to prod: fast micro-frontend delivery!" /></a>
|
||||
|
||||
### Awesome backers 🍺
|
||||
|
||||
<a href="https://github.com/pdfme/pdfme"><img src="https://lucide.dev/sponsors/pdfme.svg" width="180" alt="pdfme – Open-source PDF generation library built with TypeScript and React." /></a>
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
],
|
||||
"source": "src/lucide-static.js",
|
||||
"main": "dist/cjs/lucide-static.js",
|
||||
"module": "dist/esm/lucide-static.js",
|
||||
"module": "dist/esm/lucide-static.mjs",
|
||||
"typings": "dist/lucide-static.d.ts",
|
||||
"sideEffects": false,
|
||||
"scripts": {
|
||||
|
||||
@@ -16,11 +16,12 @@ const bundles = [
|
||||
inputs,
|
||||
outputDir,
|
||||
preserveModules: true,
|
||||
extension: 'mjs',
|
||||
},
|
||||
];
|
||||
|
||||
const configs = bundles
|
||||
.map(({ inputs, outputDir, format, minify, preserveModules }) =>
|
||||
.map(({ inputs, outputDir, format, minify, preserveModules, extension = 'js' }) =>
|
||||
inputs.map((input) => ({
|
||||
input,
|
||||
plugins: plugins({ pkg, minify }),
|
||||
@@ -29,9 +30,10 @@ const configs = bundles
|
||||
...(preserveModules
|
||||
? {
|
||||
dir: `${outputDir}/${format}`,
|
||||
entryFileNames: `[name].${extension}`,
|
||||
}
|
||||
: {
|
||||
file: `${outputDir}/${format}/${outputFileName}${minify ? '.min' : ''}.js`,
|
||||
file: `${outputDir}/${format}/${outputFileName}${minify ? '.min' : ''}.${extension}`,
|
||||
}),
|
||||
format,
|
||||
sourcemap: true,
|
||||
|
||||
@@ -15,6 +15,7 @@ export default async function generateSprite(
|
||||
value: '',
|
||||
attributes: {
|
||||
id: name,
|
||||
viewBox: parsedSvg.attributes.viewBox,
|
||||
},
|
||||
children: parsedSvg.children,
|
||||
}));
|
||||
|
||||
@@ -60,6 +60,8 @@ Join the [Discord server](https://discord.gg/EH6nSts) to chat with the maintaine
|
||||
|
||||
Lucide is licensed under the ISC license. See [LICENSE](https://lucide.dev/license).
|
||||
|
||||
[//]: <> (Sponsors)
|
||||
|
||||
## Sponsors
|
||||
|
||||
<a href="https://vercel.com?utm_source=lucide&utm_campaign=oss">
|
||||
@@ -68,7 +70,10 @@ Lucide is licensed under the ISC license. See [LICENSE](https://lucide.dev/licen
|
||||
|
||||
<a href="https://www.digitalocean.com/?refcode=b0877a2caebd&utm_campaign=Referral_Invite&utm_medium=Referral_Program&utm_source=badge"><img src="https://lucide.dev/digitalocean.svg" width="200" alt="DigitalOcean Referral Badge" /></a>
|
||||
|
||||
[//]: <> (Open Collective backers)
|
||||
### Hero backers 🦸
|
||||
|
||||
<a href="https://https://zephyr-cloud.io/"><img src="https://lucide.dev/sponsors/zephyr-cloud.svg" width="180" alt="Zephyr Cloud – From idea to prod: fast micro-frontend delivery!" /></a>
|
||||
|
||||
### Awesome backers 🍺
|
||||
|
||||
<a href="https://github.com/pdfme/pdfme"><img src="https://lucide.dev/sponsors/pdfme.svg" width="180" alt="pdfme – Open-source PDF generation library built with TypeScript and React." /></a>
|
||||
|
||||
@@ -59,6 +59,8 @@ Join the [Discord server](https://discord.gg/EH6nSts) to chat with the maintaine
|
||||
|
||||
Lucide is licensed under the ISC license. See [LICENSE](https://lucide.dev/license).
|
||||
|
||||
[//]: <> (Sponsors)
|
||||
|
||||
## Sponsors
|
||||
|
||||
<a href="https://vercel.com?utm_source=lucide&utm_campaign=oss">
|
||||
@@ -67,7 +69,10 @@ Lucide is licensed under the ISC license. See [LICENSE](https://lucide.dev/licen
|
||||
|
||||
<a href="https://www.digitalocean.com/?refcode=b0877a2caebd&utm_campaign=Referral_Invite&utm_medium=Referral_Program&utm_source=badge"><img src="https://lucide.dev/digitalocean.svg" width="200" alt="DigitalOcean Referral Badge" /></a>
|
||||
|
||||
[//]: <> (Open Collective backers)
|
||||
### Hero backers 🦸
|
||||
|
||||
<a href="https://https://zephyr-cloud.io/"><img src="https://lucide.dev/sponsors/zephyr-cloud.svg" width="180" alt="Zephyr Cloud – From idea to prod: fast micro-frontend delivery!" /></a>
|
||||
|
||||
### Awesome backers 🍺
|
||||
|
||||
<a href="https://github.com/pdfme/pdfme"><img src="https://lucide.dev/sponsors/pdfme.svg" width="180" alt="pdfme – Open-source PDF generation library built with TypeScript and React." /></a>
|
||||
|
||||
@@ -69,6 +69,8 @@ Join the [Discord server](https://discord.gg/EH6nSts) to chat with the maintaine
|
||||
|
||||
Lucide is licensed under the ISC license. See [LICENSE](https://lucide.dev/license).
|
||||
|
||||
[//]: <> (Sponsors)
|
||||
|
||||
## Sponsors
|
||||
|
||||
<a href="https://vercel.com?utm_source=lucide&utm_campaign=oss">
|
||||
@@ -77,7 +79,10 @@ Lucide is licensed under the ISC license. See [LICENSE](https://lucide.dev/licen
|
||||
|
||||
<a href="https://www.digitalocean.com/?refcode=b0877a2caebd&utm_campaign=Referral_Invite&utm_medium=Referral_Program&utm_source=badge"><img src="https://lucide.dev/digitalocean.svg" width="200" alt="DigitalOcean Referral Badge" /></a>
|
||||
|
||||
[//]: <> (Open Collective backers)
|
||||
### Hero backers 🦸
|
||||
|
||||
<a href="https://https://zephyr-cloud.io/"><img src="https://lucide.dev/sponsors/zephyr-cloud.svg" width="180" alt="Zephyr Cloud – From idea to prod: fast micro-frontend delivery!" /></a>
|
||||
|
||||
### Awesome backers 🍺
|
||||
|
||||
<a href="https://github.com/pdfme/pdfme"><img src="https://lucide.dev/sponsors/pdfme.svg" width="180" alt="pdfme – Open-source PDF generation library built with TypeScript and React." /></a>
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
"source": "src/lucide.js",
|
||||
"main": "dist/cjs/lucide.js",
|
||||
"main:umd": "dist/umd/lucide.js",
|
||||
"module": "dist/esm/lucide.js",
|
||||
"module": "dist/esm/lucide.mjs",
|
||||
"unpkg": "dist/umd/lucide.min.js",
|
||||
"typings": "dist/lucide.d.ts",
|
||||
"sideEffects": false,
|
||||
|
||||
@@ -53,6 +53,7 @@ const configs = bundles
|
||||
...(preserveModules
|
||||
? {
|
||||
dir: `${outputDir}/${format}`,
|
||||
entryFileNames: '[name].mjs',
|
||||
}
|
||||
: {
|
||||
file: `${outputDir}/${format}/${outputFileName}${minify ? '.min' : ''}.js`,
|
||||
|
||||
@@ -60,6 +60,8 @@ Join the [Discord server](https://discord.gg/EH6nSts) to chat with the maintaine
|
||||
|
||||
Lucide is licensed under the ISC license. See [LICENSE](https://lucide.dev/license).
|
||||
|
||||
[//]: <> (Sponsors)
|
||||
|
||||
## Sponsors
|
||||
|
||||
<a href="https://vercel.com?utm_source=lucide&utm_campaign=oss">
|
||||
@@ -68,7 +70,10 @@ Lucide is licensed under the ISC license. See [LICENSE](https://lucide.dev/licen
|
||||
|
||||
<a href="https://www.digitalocean.com/?refcode=b0877a2caebd&utm_campaign=Referral_Invite&utm_medium=Referral_Program&utm_source=badge"><img src="https://lucide.dev/digitalocean.svg" width="200" alt="DigitalOcean Referral Badge" /></a>
|
||||
|
||||
[//]: <> (Open Collective backers)
|
||||
### Hero backers 🦸
|
||||
|
||||
<a href="https://https://zephyr-cloud.io/"><img src="https://lucide.dev/sponsors/zephyr-cloud.svg" width="180" alt="Zephyr Cloud – From idea to prod: fast micro-frontend delivery!" /></a>
|
||||
|
||||
### Awesome backers 🍺
|
||||
|
||||
<a href="https://github.com/pdfme/pdfme"><img src="https://lucide.dev/sponsors/pdfme.svg" width="180" alt="pdfme – Open-source PDF generation library built with TypeScript and React." /></a>
|
||||
|
||||
@@ -7,6 +7,8 @@ import { getJSBanner } from './license.mts';
|
||||
const currentDir = getCurrentDirPath(import.meta.url);
|
||||
const targetDirectory = path.join(currentDir, '../dist');
|
||||
|
||||
const jsBanner = getJSBanner();
|
||||
|
||||
const files = await readdir(targetDirectory, {
|
||||
recursive: true,
|
||||
encoding: 'utf-8',
|
||||
@@ -22,43 +24,10 @@ for (const file of files) {
|
||||
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
const contents = (await readFile(filepath, { encoding: 'utf-8' })) as unknown as string;
|
||||
let newContents = contents;
|
||||
const ext = path.extname(filepath);
|
||||
let license;
|
||||
|
||||
if (/\.(js|mjs|cjs|ts)/.test(ext)) {
|
||||
license = getJSBanner();
|
||||
}
|
||||
|
||||
if (license) {
|
||||
newContents = license + contents;
|
||||
}
|
||||
|
||||
// Places icon block comment at the top of the Svelte component class
|
||||
if (/icons\/(.*?)\.svelte\.d\.ts/.test(filepath)) {
|
||||
const svelteFilepath = filepath.replace('.d.ts', '');
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
const svelteFileContents = (await readFile(svelteFilepath, { encoding: 'utf-8' })) as unknown as string;;
|
||||
|
||||
const blockCommentRegex = /\/\*\*\n\s\*\s(@component\s@name)[\s\S]*?\*\//;
|
||||
const blockCommentMatch = blockCommentRegex.exec(svelteFileContents);
|
||||
|
||||
if (blockCommentMatch !== null) {
|
||||
const blockComment = blockCommentMatch[0];
|
||||
|
||||
const exportClassRegex = /export default class (\w+) extends SvelteComponentTyped<(.*?)> {/;
|
||||
|
||||
if (exportClassRegex.test(newContents)) {
|
||||
newContents = newContents.replace(
|
||||
exportClassRegex,
|
||||
`${blockComment}\nexport default class $1 extends SvelteComponentTyped<$2> {`,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (newContents !== contents) {
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
await writeFile(filepath, newContents, { encoding: 'utf-8' });
|
||||
await writeFile(filepath, jsBanner + contents, { encoding: 'utf-8' });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,43 +1,34 @@
|
||||
import base64SVG from '@lucide/build-icons/utils/base64SVG';
|
||||
import { getJSBanner } from './license.mts';
|
||||
import { getHTMLBanner } from './license.mts';
|
||||
import defineExportTemplate from '@lucide/build-icons/utils/defineExportTemplate';
|
||||
|
||||
export default defineExportTemplate(async ({
|
||||
iconName,
|
||||
children,
|
||||
componentName,
|
||||
getSvg,
|
||||
deprecated,
|
||||
deprecationReason,
|
||||
}) => {
|
||||
const svgContents = await getSvg();
|
||||
const svgBase64 = base64SVG(svgContents);
|
||||
export default defineExportTemplate(
|
||||
async ({ iconName, children, getSvg, deprecated, deprecationReason }) => {
|
||||
const svgContents = await getSvg();
|
||||
const svgBase64 = base64SVG(svgContents);
|
||||
|
||||
return `\
|
||||
return `\
|
||||
${getHTMLBanner()}
|
||||
<script lang="ts">
|
||||
${getJSBanner()}
|
||||
import Icon from '../Icon.svelte';
|
||||
import type { IconNode, IconProps } from '../types.js';
|
||||
|
||||
let props: IconProps = $props();
|
||||
|
||||
const iconNode: IconNode = ${JSON.stringify(children)};
|
||||
|
||||
/**
|
||||
* @component @name ${componentName}
|
||||
* @description Lucide SVG icon component, renders SVG Element with children.
|
||||
*
|
||||
* @preview  - https://lucide.dev/icons/${iconName}
|
||||
* @see https://lucide.dev/guide/packages/lucide-svelte - Documentation
|
||||
*
|
||||
* @param {Object} props - Lucide icons props and any valid SVG attribute
|
||||
* @returns {FunctionalComponent} Svelte component
|
||||
* ${deprecated ? `@deprecated ${deprecationReason}` : ''}
|
||||
*/
|
||||
</script>
|
||||
|
||||
<Icon name="${iconName}" {...props} iconNode={iconNode}>
|
||||
{@render props.children?.()}
|
||||
</Icon>
|
||||
<!--
|
||||
@component
|
||||
|
||||
Lucide SVG icon component, renders SVG Element with children.
|
||||
|
||||
@preview  - https://lucide.dev/icons/${iconName}
|
||||
@see https://lucide.dev/guide/packages/lucide-svelte - Documentation
|
||||
${deprecated ? `\n@deprecated ${deprecationReason}\n` : ''}\
|
||||
-->
|
||||
|
||||
<Icon name="${iconName}" {...props} iconNode={iconNode} />
|
||||
`;
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
@@ -3,11 +3,26 @@ import pkg from '../package.json' with { type: 'json' };
|
||||
|
||||
const license = fs.readFileSync('LICENSE', 'utf-8');
|
||||
|
||||
export function getHTMLBanner() {
|
||||
return `\
|
||||
<!--
|
||||
${pkg.name} v${pkg.version} - ${pkg.license}
|
||||
|
||||
This source code is licensed under the ${pkg.license} license.
|
||||
See the LICENSE file in the root directory of this source tree.
|
||||
-->
|
||||
|
||||
`;
|
||||
}
|
||||
|
||||
export function getJSBanner() {
|
||||
return `/**
|
||||
return `\
|
||||
/**
|
||||
* @file
|
||||
* @license ${pkg.name} v${pkg.version} - ${pkg.license}
|
||||
*
|
||||
* ${license.split('\n').join('\n * ')}
|
||||
* This source code is licensed under the ${pkg.license} license.
|
||||
* See the LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
`;
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
exports[`Using lucide icon components > should add a class to the element 1`] = `
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class="lucide-icon lucide lucide-smile my-icon"
|
||||
fill="none"
|
||||
height="24"
|
||||
@@ -51,14 +52,13 @@ exports[`Using lucide icon components > should add a class to the element 1`] =
|
||||
|
||||
<!---->
|
||||
<!---->
|
||||
|
||||
<!---->
|
||||
</svg>
|
||||
`;
|
||||
|
||||
exports[`Using lucide icon components > should adjust the size, stroke color and stroke width 1`] = `
|
||||
<div>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class="lucide-icon lucide lucide-smile"
|
||||
fill="none"
|
||||
height="48"
|
||||
@@ -108,8 +108,6 @@ exports[`Using lucide icon components > should adjust the size, stroke color and
|
||||
|
||||
<!---->
|
||||
<!---->
|
||||
|
||||
<!---->
|
||||
</svg>
|
||||
|
||||
|
||||
@@ -126,6 +124,7 @@ exports[`Using lucide icon components > should not scale the strokeWidth when ab
|
||||
stroke-width="1"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
aria-hidden="true"
|
||||
class="lucide-icon lucide lucide-smile"
|
||||
>
|
||||
<circle cx="12"
|
||||
@@ -153,6 +152,7 @@ exports[`Using lucide icon components > should not scale the strokeWidth when ab
|
||||
exports[`Using lucide icon components > should render an component 1`] = `
|
||||
<div>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
class="lucide-icon lucide lucide-smile"
|
||||
fill="none"
|
||||
height="24"
|
||||
@@ -202,8 +202,6 @@ exports[`Using lucide icon components > should render an component 1`] = `
|
||||
|
||||
<!---->
|
||||
<!---->
|
||||
|
||||
<!---->
|
||||
</svg>
|
||||
|
||||
|
||||
@@ -260,12 +258,10 @@ exports[`Using lucide icon components > should render an icon slot 1`] = `
|
||||
|
||||
</line>
|
||||
|
||||
<!---->
|
||||
<!---->
|
||||
<text>
|
||||
Test
|
||||
</text>
|
||||
|
||||
<!---->
|
||||
</svg>
|
||||
|
||||
|
||||
@@ -94,3 +94,23 @@ describe('Using lucide icon components', () => {
|
||||
expect(IconComponent).toHaveAttribute('stroke-width', '1');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Icon Component Accessibility', () => {
|
||||
it('should have aria-hidden prop when no aria prop or children are present', async () => {
|
||||
const { container } = render(Smile, {
|
||||
props: {
|
||||
size: 48,
|
||||
color: 'red',
|
||||
absoluteStrokeWidth: true,
|
||||
},
|
||||
});
|
||||
|
||||
expect(container.firstChild).toHaveAttribute('aria-hidden', 'true');
|
||||
});
|
||||
|
||||
it('should not have aria-hidden prop when there are children that could be a <title> element', async () => {
|
||||
const { container } = render(TestSlots);
|
||||
|
||||
expect(container.firstChild).not.toHaveAttribute('aria-hidden');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -52,6 +52,8 @@ Join the [Discord server](https://discord.gg/EH6nSts) to chat with the maintaine
|
||||
|
||||
Lucide is licensed under the ISC license. See [LICENSE](https://lucide.dev/license).
|
||||
|
||||
[//]: <> (Sponsors)
|
||||
|
||||
## Sponsors
|
||||
|
||||
<a href="https://vercel.com?utm_source=lucide&utm_campaign=oss">
|
||||
@@ -60,7 +62,10 @@ Lucide is licensed under the ISC license. See [LICENSE](https://lucide.dev/licen
|
||||
|
||||
<a href="https://www.digitalocean.com/?refcode=b0877a2caebd&utm_campaign=Referral_Invite&utm_medium=Referral_Program&utm_source=badge"><img src="https://lucide.dev/digitalocean.svg" width="200" alt="DigitalOcean Referral Badge" /></a>
|
||||
|
||||
[//]: <> (Open Collective backers)
|
||||
### Hero backers 🦸
|
||||
|
||||
<a href="https://https://zephyr-cloud.io/"><img src="https://lucide.dev/sponsors/zephyr-cloud.svg" width="180" alt="Zephyr Cloud – From idea to prod: fast micro-frontend delivery!" /></a>
|
||||
|
||||
### Awesome backers 🍺
|
||||
|
||||
<a href="https://github.com/pdfme/pdfme"><img src="https://lucide.dev/sponsors/pdfme.svg" width="180" alt="pdfme – Open-source PDF generation library built with TypeScript and React." /></a>
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
"amdName": "lucide-vue",
|
||||
"source": "build/lucide-vue.js",
|
||||
"main": "dist/cjs/lucide-vue.js",
|
||||
"module": "dist/esm/lucide-vue.js",
|
||||
"module": "dist/esm/lucide-vue.mjs",
|
||||
"typings": "dist/lucide-vue.d.ts",
|
||||
"sideEffects": false,
|
||||
"files": [
|
||||
|
||||
@@ -17,11 +17,12 @@ const bundles = [
|
||||
inputs,
|
||||
outputDir,
|
||||
preserveModules: true,
|
||||
extension: 'mjs',
|
||||
},
|
||||
];
|
||||
|
||||
const configs = bundles
|
||||
.map(({ inputs, outputDir, format, minify, preserveModules }) =>
|
||||
.map(({ inputs, outputDir, format, minify, preserveModules, extension = 'js' }) =>
|
||||
inputs.map((input) => ({
|
||||
input,
|
||||
plugins: plugins({ pkg, minify }),
|
||||
@@ -31,9 +32,10 @@ const configs = bundles
|
||||
...(preserveModules
|
||||
? {
|
||||
dir: `${outputDir}/${format}`,
|
||||
entryFileNames: `[name].${extension}`,
|
||||
}
|
||||
: {
|
||||
file: `${outputDir}/${format}/${outputFileName}.js`,
|
||||
file: `${outputDir}/${format}/${outputFileName}.${extension}`,
|
||||
}),
|
||||
format,
|
||||
preserveModules,
|
||||
|
||||
@@ -2,13 +2,13 @@ import { readdirSync } from 'node:fs';
|
||||
import { join } from 'node:path';
|
||||
import { existsSync, readFileSync, writeFileSync } from 'fs';
|
||||
|
||||
function updateOpenCollectiveBackers() {
|
||||
function updateSponsors() {
|
||||
const packagesPath = join(import.meta.dirname, '../packages');
|
||||
const mainReadme = readFileSync(join(import.meta.dirname, '../README.md'), 'utf8');
|
||||
const awesomeRegex = /(\[\/\/]: <> \(Open Collective backers\).+)$/s;
|
||||
const awesomeBlock = awesomeRegex.exec(mainReadme);
|
||||
if (awesomeBlock?.[1]) {
|
||||
const packageAwesomeBlock = awesomeBlock[1].replaceAll('src="docs/public/sponsors', 'src="https://lucide.dev/sponsors')
|
||||
const sponsorsRegex = /(\[\/\/]: <> \(Sponsors\).+)$/s;
|
||||
const sponsorsBlock = sponsorsRegex.exec(mainReadme);
|
||||
if (sponsorsBlock?.[1]) {
|
||||
const packageSponsorsBlock = sponsorsBlock[1].replaceAll('src="docs/public', 'src="https://lucide.dev')
|
||||
readdirSync(packagesPath).forEach((packagePath) => {
|
||||
if (['lucide-figma', 'shared'].includes(packagePath) || packagePath.startsWith('.')) {
|
||||
return;
|
||||
@@ -16,19 +16,19 @@ function updateOpenCollectiveBackers() {
|
||||
const readmePath = join(packagesPath, packagePath, 'README.md');
|
||||
if (existsSync(readmePath)) {
|
||||
const readmeContent = readFileSync(readmePath, 'utf8');
|
||||
if (awesomeRegex.test(readmeContent)) {
|
||||
writeFileSync(readmePath, readmeContent.replace(awesomeRegex, packageAwesomeBlock));
|
||||
console.log(`Upgraded Awesome backers block in ${readmePath}`);
|
||||
if (sponsorsRegex.test(readmeContent)) {
|
||||
writeFileSync(readmePath, readmeContent.replace(sponsorsRegex, packageSponsorsBlock));
|
||||
console.log(`Upgraded Sponsors block in ${readmePath}`);
|
||||
} else {
|
||||
console.error(`Could not find Awesome backers block in ${readmePath}`)
|
||||
console.error(`Could not find Sponsors block in ${readmePath}`)
|
||||
}
|
||||
} else {
|
||||
console.warn(`No readme found at ${readmePath}`);
|
||||
}
|
||||
})
|
||||
} else {
|
||||
console.error('Could not identify Awesome backers block')
|
||||
console.error('Could not identify Sponsors block')
|
||||
}
|
||||
}
|
||||
|
||||
updateOpenCollectiveBackers();
|
||||
updateSponsors();
|
||||
@@ -6,7 +6,8 @@
|
||||
"main": "main.ts",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"start": "node ./src/main.ts"
|
||||
"start": "node ./src/main.ts",
|
||||
"test": "vitest run"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
|
||||
@@ -0,0 +1,141 @@
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
import { put } from '@vercel/blob';
|
||||
import { allocateCodePoints } from './allocateCodepoints.ts';
|
||||
|
||||
vi.mock('@vercel/blob', () => ({
|
||||
put: vi.fn(),
|
||||
}));
|
||||
|
||||
function mockLatestCodePoints(codePoints: Record<string, number>) {
|
||||
const response = {
|
||||
json: vi.fn().mockResolvedValue(structuredClone(codePoints)),
|
||||
};
|
||||
|
||||
vi.stubGlobal('fetch', vi.fn().mockResolvedValue(response));
|
||||
}
|
||||
|
||||
describe('allocateCodePoints', () => {
|
||||
beforeEach(() => {
|
||||
vi.spyOn(console, 'log').mockImplementation(() => {});
|
||||
vi.spyOn(console, 'warn').mockImplementation(() => {});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
vi.restoreAllMocks();
|
||||
vi.unstubAllGlobals();
|
||||
});
|
||||
|
||||
it('keeps existing code points and allocates new ones in sequence', async () => {
|
||||
mockLatestCodePoints({ camera: 57400 });
|
||||
|
||||
const codePoints = await allocateCodePoints({
|
||||
iconsWithAliases: [
|
||||
['camera', ['camera-old']],
|
||||
['new-icon', []],
|
||||
],
|
||||
});
|
||||
|
||||
expect(codePoints.camera).toBe(57400);
|
||||
expect(codePoints['camera-old']).toBe(57400);
|
||||
expect(codePoints['new-icon']).toBe(57401);
|
||||
expect(fetch).toHaveBeenCalledWith(
|
||||
'https://geoxmjocxfnaryc4.public.blob.vercel-storage.com/latest/font/codepoints.json',
|
||||
);
|
||||
});
|
||||
|
||||
it('preserves legacy alias code points when alias and canonical differ', async () => {
|
||||
mockLatestCodePoints({ camera: 57400, shutter: 57405 });
|
||||
|
||||
const codePoints = await allocateCodePoints({
|
||||
iconsWithAliases: [['camera', ['shutter']]],
|
||||
});
|
||||
|
||||
expect(codePoints.camera).toBe(57400);
|
||||
expect(codePoints.shutter).toBe(57405);
|
||||
expect(console.log).toHaveBeenCalledWith(
|
||||
expect.stringContaining('adding a legacy alias codepoint'),
|
||||
);
|
||||
});
|
||||
|
||||
it('throws when a legacy alias code point is already allocated and fixes are disabled', async () => {
|
||||
mockLatestCodePoints({ 'icon-b': 57402, 'icon-a': 57400, 'alias-a': 57402 });
|
||||
|
||||
await expect(
|
||||
allocateCodePoints({
|
||||
iconsWithAliases: [
|
||||
['icon-b', []],
|
||||
['icon-a', ['alias-a']],
|
||||
],
|
||||
}),
|
||||
).rejects.toThrow(
|
||||
"The code point for alias 'alias-a' for 'icon-a' is already allocated to: 'icon-b'.",
|
||||
);
|
||||
});
|
||||
|
||||
it('throws when two canonical icons share the same code point without allowFixes', async () => {
|
||||
mockLatestCodePoints({ 'icon-a': 57400, 'icon-b': 57400 });
|
||||
|
||||
await expect(
|
||||
allocateCodePoints({
|
||||
iconsWithAliases: [
|
||||
['icon-a', []],
|
||||
['icon-b', []],
|
||||
],
|
||||
}),
|
||||
).rejects.toThrow(
|
||||
"We couldn't assign a unique codepoint for 'icon-b', since '57400' was already taken up by 'icon-a'",
|
||||
);
|
||||
});
|
||||
|
||||
it('skips conflicting legacy alias code points when fixes are enabled', async () => {
|
||||
mockLatestCodePoints({ 'icon-b': 57402, 'icon-a': 57400, 'alias-a': 57402 });
|
||||
|
||||
const codePoints = await allocateCodePoints({
|
||||
allowFixes: true,
|
||||
iconsWithAliases: [
|
||||
['icon-b', []],
|
||||
['icon-a', ['alias-a']],
|
||||
],
|
||||
});
|
||||
|
||||
expect(codePoints['icon-a']).toBe(57400);
|
||||
expect(codePoints['alias-a']).toBe(57400);
|
||||
expect(console.warn).toHaveBeenCalledWith(
|
||||
expect.stringContaining("we're simply not adding this custom alias codepoint"),
|
||||
);
|
||||
});
|
||||
|
||||
it('reassigns duplicate canonical code points when fixes are enabled', async () => {
|
||||
mockLatestCodePoints({ 'icon-a': 57400, 'icon-b': 57400 });
|
||||
|
||||
const codePoints = await allocateCodePoints({
|
||||
allowFixes: true,
|
||||
iconsWithAliases: [
|
||||
['icon-a', []],
|
||||
['icon-b', []],
|
||||
],
|
||||
});
|
||||
|
||||
expect(codePoints['icon-a']).toBe(57400);
|
||||
expect(codePoints['icon-b']).toBe(57401);
|
||||
expect(console.warn).toHaveBeenCalledWith(
|
||||
expect.stringContaining("Assigning a new codepoint for 'icon-b'"),
|
||||
);
|
||||
});
|
||||
|
||||
it('uploads the merged code point map when saveCodePoints is enabled', async () => {
|
||||
mockLatestCodePoints({ camera: 57400 });
|
||||
|
||||
await allocateCodePoints({
|
||||
saveCodePoints: true,
|
||||
iconsWithAliases: [['camera', ['camera-old']]],
|
||||
});
|
||||
|
||||
expect(put).toHaveBeenCalledWith(
|
||||
'latest/font/codepoints.json',
|
||||
JSON.stringify({ camera: 57400, 'camera-old': 57400 }, null, 2),
|
||||
{ access: 'public', allowOverwrite: true },
|
||||
);
|
||||
expect(console.log).toHaveBeenCalledWith('Code points uploaded to Vercel Blob Storage.');
|
||||
});
|
||||
});
|
||||
@@ -1,6 +1,4 @@
|
||||
import { type IconAliases } from '@lucide/helpers';
|
||||
import { promises as fs } from 'fs';
|
||||
import { cwd } from 'process';
|
||||
import { put } from '@vercel/blob';
|
||||
|
||||
const VERCEL_BLOB_CODEPOINTS_PATH = 'latest/font/codepoints.json';
|
||||
@@ -17,43 +15,91 @@ async function getLatestCodePoints(): Promise<CodePoints> {
|
||||
|
||||
interface AllocateCodePointsOptions {
|
||||
saveCodePoints?: boolean;
|
||||
allowFixes?: boolean;
|
||||
iconsWithAliases: IconAliases;
|
||||
}
|
||||
|
||||
export async function allocateCodePoints({
|
||||
saveCodePoints = false,
|
||||
allowFixes = false,
|
||||
iconsWithAliases,
|
||||
}: AllocateCodePointsOptions): Promise<CodePoints> {
|
||||
const baseCodePoints = await getLatestCodePoints();
|
||||
const latestCodePoints = await getLatestCodePoints();
|
||||
|
||||
const endCodePoint = Math.max(...Object.values(baseCodePoints));
|
||||
let maxCodePoint = Math.max(...Object.values(latestCodePoints));
|
||||
let codePointMap = new Map<number, string>();
|
||||
let newCodePoints: CodePoints = {};
|
||||
|
||||
await Promise.all(
|
||||
iconsWithAliases.map(async ([iconName, aliases]) => {
|
||||
if (!baseCodePoints[iconName]) {
|
||||
console.log('Code point not found creating new one for', iconName);
|
||||
baseCodePoints[iconName] = endCodePoint + 1;
|
||||
}
|
||||
for (const [iconName, aliases] of iconsWithAliases) {
|
||||
let codePoint: number | null = null;
|
||||
|
||||
aliases.forEach((alias, index) => {
|
||||
if (baseCodePoints[alias]) {
|
||||
return;
|
||||
// Check if the icon is already present.
|
||||
if (iconName in latestCodePoints) {
|
||||
codePoint = latestCodePoints[iconName];
|
||||
}
|
||||
|
||||
// Check if one of the aliases of the icon is already present, we need to add this as a legacy codepoint for backwards compatibility
|
||||
for (const alias of aliases) {
|
||||
if (alias in latestCodePoints) {
|
||||
if (codePoint && codePoint !== latestCodePoints[alias]) {
|
||||
if (codePointMap.has(latestCodePoints[alias])) {
|
||||
if (allowFixes) {
|
||||
console.warn(
|
||||
`The code point for alias '${alias}' for '${iconName}' is already allocated to: '${codePointMap.get(latestCodePoints[alias])}', we're simply not adding this custom alias codepoint.`,
|
||||
);
|
||||
} else {
|
||||
throw new Error(
|
||||
`The code point for alias '${alias}' for '${iconName}' is already allocated to: '${codePointMap.get(latestCodePoints[alias])}'.`,
|
||||
);
|
||||
}
|
||||
} else {
|
||||
console.log(
|
||||
`'${alias}' uses a different codepoint than its canonical name '${iconName}', adding a legacy alias codepoint for: ${latestCodePoints[alias]}.`,
|
||||
);
|
||||
codePointMap.set(latestCodePoints[alias], iconName);
|
||||
newCodePoints[alias] = latestCodePoints[alias];
|
||||
}
|
||||
}
|
||||
codePoint ??= latestCodePoints[alias];
|
||||
}
|
||||
}
|
||||
|
||||
console.log('Code point not found creating new one for', alias);
|
||||
// Assign a new codepoint, if no existing code point was found.
|
||||
codePoint ??= ++maxCodePoint;
|
||||
|
||||
baseCodePoints[alias] = endCodePoint + index + 1;
|
||||
});
|
||||
}),
|
||||
);
|
||||
if (allowFixes && codePointMap.has(codePoint)) {
|
||||
console.warn(
|
||||
`Assigning a new codepoint for '${iconName}', since '${codePoint}' was already taken up by '${codePointMap.get(codePoint)}'.`,
|
||||
);
|
||||
codePoint = ++maxCodePoint;
|
||||
}
|
||||
|
||||
if (codePointMap.has(codePoint)) {
|
||||
throw new Error(
|
||||
`We couldn't assign a unique codepoint for '${iconName}', since '${codePoint}' was already taken up by '${codePointMap.get(codePoint)}'`,
|
||||
);
|
||||
}
|
||||
|
||||
codePointMap.set(codePoint, iconName);
|
||||
for (const name of [iconName, ...aliases]) {
|
||||
if (!newCodePoints[name]) {
|
||||
newCodePoints[name] = codePoint;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Write the changes to the original map to keep its order.
|
||||
for (const [name, codePoint] of Object.entries(newCodePoints)) {
|
||||
latestCodePoints[name] = codePoint;
|
||||
}
|
||||
|
||||
if (saveCodePoints) {
|
||||
const content = JSON.stringify(baseCodePoints, null, 2);
|
||||
const content = JSON.stringify(latestCodePoints, null, 2);
|
||||
|
||||
await put(VERCEL_BLOB_CODEPOINTS_PATH, content, { access: 'public', allowOverwrite: true });
|
||||
|
||||
console.log('Code points uploaded to Vercel Blob Storage.');
|
||||
}
|
||||
|
||||
return baseCodePoints;
|
||||
return latestCodePoints;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
import { buildFont } from './buildFont.ts';
|
||||
import svgtofont from 'svgtofont';
|
||||
|
||||
vi.mock('svgtofont', () => ({
|
||||
default: vi.fn(),
|
||||
}));
|
||||
|
||||
describe('buildFont', () => {
|
||||
beforeEach(() => {
|
||||
vi.spyOn(console, 'time').mockImplementation(() => {});
|
||||
vi.spyOn(console, 'timeEnd').mockImplementation(() => {});
|
||||
vi.spyOn(console, 'log').mockImplementation(() => {});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
vi.restoreAllMocks();
|
||||
});
|
||||
|
||||
it('calls svgtofont with expected settings and unicode resolver', async () => {
|
||||
vi.mocked(svgtofont).mockResolvedValue(undefined);
|
||||
|
||||
await buildFont({
|
||||
inputDir: '/icons',
|
||||
targetDir: '/dist',
|
||||
fontName: 'lucide',
|
||||
classNamePrefix: 'icon',
|
||||
codePoints: { camera: 57400 },
|
||||
startUnicode: 57400,
|
||||
});
|
||||
|
||||
expect(console.time).toHaveBeenCalledWith('Font generation');
|
||||
expect(console.timeEnd).toHaveBeenCalledWith('Font generation');
|
||||
expect(svgtofont).toHaveBeenCalledTimes(1);
|
||||
|
||||
const [options] = vi.mocked(svgtofont).mock.calls[0];
|
||||
|
||||
expect(options.src).toBe('/icons');
|
||||
expect(options.dist).toBe('/dist');
|
||||
expect(options.fontName).toBe('lucide');
|
||||
expect(options.classNamePrefix).toBe('icon');
|
||||
expect(options.addLigatures).toBe(true);
|
||||
expect(options.getIconUnicode('camera')).toEqual([String.fromCharCode(57400), 57400]);
|
||||
expect(() => options.getIconUnicode('missing')).toThrow('No codepoint found for icon: missing');
|
||||
});
|
||||
|
||||
it('logs errors from svgtofont and still finishes timing', async () => {
|
||||
const error = new Error('svgtofont failed');
|
||||
vi.mocked(svgtofont).mockRejectedValue(error);
|
||||
|
||||
await buildFont({
|
||||
inputDir: '/icons',
|
||||
targetDir: '/dist',
|
||||
fontName: 'lucide',
|
||||
classNamePrefix: 'icon',
|
||||
codePoints: { camera: 57400 },
|
||||
startUnicode: 57400,
|
||||
});
|
||||
|
||||
expect(console.log).toHaveBeenCalledWith(error);
|
||||
expect(console.timeEnd).toHaveBeenCalledWith('Font generation');
|
||||
});
|
||||
});
|
||||