Compare commits

...
Author SHA1 Message Date
softClaude Opus 5.5github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>aquazureEric
dd9e311c0c feat(lab): added circuit-resistor icon (#4698)
* added icon and metadata

* fixed contributor's name

* Move to lab

* Add correct design

* chore: remove angular cache files

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Apply batched suggestions from code review

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

* Adjust metadata

---------

Co-authored-by: aquazure <pumpkinbrush@icloud.com>
Co-authored-by: Eric <eric.fennis@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-11-02 17:12:13 +01:00
5297593247 feat(lab): added map-pin-laptop icon (#3699)
* Added icons/map-pin-laptop.svg

* Added icons/map-pin-laptop.json

* Move to lab

* Update lab/map-pin-laptop.svg

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

* Update metadata

---------

Co-authored-by: Eric <eric.fennis@gmail.com>
Co-authored-by: Karsa <contact@karsa.org>
2026-11-02 16:58:04 +01:00
Turboman3000github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>Copilot Autofix powered by AIEric Fennis
9fe2cb8792 feat(icons): added globe-plus icon (#4938)
* Added icons/globe-plus.svg

* Added icons/globe-plus.json

* Apply batched suggestions from code review

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Eric Fennis <eric.fennis@gmail.com>

* Adjust svg and metadata

* update metadata

---------

Co-authored-by: Eric Fennis <eric.fennis@gmail.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-11-02 16:55:40 +01:00
dependabot[bot]anddependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> 6fbb37f7ab chore(deps-dev): bump preact (#5135)
Bumps the preact-deps group with 1 update in the / directory: [preact](https://github.com/preactjs/preact).


Updates `preact` from 11.0.2 to 11.1.0
- [Release notes](https://github.com/preactjs/preact/releases)
- [Commits](https://github.com/preactjs/preact/compare/11.0.2...11.1.0)

---
updated-dependencies:
- dependency-name: preact
  dependency-version: 11.1.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: preact-deps
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-11-02 15:57:06 +01:00
Karsaandgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> 0669a71ff5 feat(icons): added diagram-flow-horizontal, diagram-flow-vertical icons (#5125)
* feat(groups): added `chart` and `graph` groups

* feat(icons): added `mind-map` icon

* feat(icons): added `mind-map` icon

* feat(icons): added diagram-flow-* icons

* chore(icons): remove mind-map

* Update icons/diagram-flow-vertical.json

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

* Update icons/diagram-flow-horizontal.json

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

* Update icons/diagram-flow-vertical.json

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

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-11-02 15:23:28 +01:00
dependabot[bot]anddependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> 7515e7cd42 chore(deps): bump the svelte-deps group across 1 directory with 3 updates (#5139)
Bumps the svelte-deps group with 3 updates in the / directory: [@sveltejs/package](https://github.com/sveltejs/kit/tree/HEAD/packages/package), [svelte](https://github.com/sveltejs/svelte/tree/HEAD/packages/svelte) and [@sveltejs/kit](https://github.com/sveltejs/kit/tree/HEAD/packages/kit).


Updates `@sveltejs/package` from 3.0.1 to 3.0.2
- [Release notes](https://github.com/sveltejs/kit/releases)
- [Changelog](https://github.com/sveltejs/kit/blob/main/packages/package/CHANGELOG.md)
- [Commits](https://github.com/sveltejs/kit/commits/@sveltejs/package@3.0.2/packages/package)

Updates `svelte` from 5.57.2 to 5.57.3
- [Release notes](https://github.com/sveltejs/svelte/releases)
- [Changelog](https://github.com/sveltejs/svelte/blob/main/packages/svelte/CHANGELOG.md)
- [Commits](https://github.com/sveltejs/svelte/commits/svelte@5.57.3/packages/svelte)

Updates `@sveltejs/kit` from 3.1.0 to 3.1.1
- [Release notes](https://github.com/sveltejs/kit/releases)
- [Changelog](https://github.com/sveltejs/kit/blob/main/packages/kit/CHANGELOG.md)
- [Commits](https://github.com/sveltejs/kit/commits/@sveltejs/kit@3.1.1/packages/kit)

---
updated-dependencies:
- dependency-name: "@sveltejs/kit"
  dependency-version: 3.1.1
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: svelte-deps
- dependency-name: "@sveltejs/package"
  dependency-version: 3.0.2
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: svelte-deps
- dependency-name: svelte
  dependency-version: 5.57.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: svelte-deps
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-11-02 15:21:35 +01:00
Eric FennisandClaude 857a08d1f2 chore(deps): bump playwright to 1.64.1 to support ubuntu 26.04 runners (#5140)
GitHub's `ubuntu-latest` runners now resolve to Ubuntu 26.04, and
`playwright install --with-deps chromium` fails there on Playwright 1.58.2:

  Cannot install dependencies for ubuntu26.04-x64 with Playwright 1.58.2!
  Error: ERROR: Playwright does not support chromium on ubuntu26.04-x64

Ubuntu 26.04 support was added in Playwright 1.61, so bump the pinned
version in all integration packages to the latest stable (1.64.1). This
fixes the `integration` job in the react, vue, svelte, solid and solid-2
workflows.


Claude-Session: https://claude.ai/code/session_01G9u8FfWcVzm87hKho1ZQcc

Co-authored-by: Claude <noreply@anthropic.com>
2026-11-02 15:03:05 +01:00
PrimeTestLabEric Fennisgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
6446cf2b15 feat(icons): added globe-ban icon (#5020)
* feat(icons): add globe-ban

* fix(icons): add 2px spacing in `globe-ban`

* Apply batched suggestions from code review

Co-authored-by: Eric Fennis <eric.fennis@gmail.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

* Refactor globe-ban.svg by removing old paths

Removed old globe-ban SVG elements and retained new structure.

* Update icons/globe-ban.json

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

* Update metadata

---------

Co-authored-by: Eric Fennis <eric.fennis@gmail.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-11-02 15:02:46 +01:00
Karsa fc6c1ed941 fix(icons): update (circle|square)-letter-j design for better optical centering and consistency with base letter J icon (#5138) 2026-11-02 14:49:02 +01:00
Karsaandgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> a529c28a87 fix(icons): changed chef-hat icon (#4577)
* Updated icons/chef-hat.svg

* Updated icons/chef-hat.json

* Update chef-hat.svg

* Update chef-hat.svg

* Update icons/chef-hat.json

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

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-11-02 14:09:46 +01:00
14cab02398 feat(site): Add sponsor page (#5132)
* feat(docs): add sponsor page

Add a /sponsor page to lucide.dev with sponsor tiers, an amount picker,
a sponsor wall and a FAQ.

- Fetch active Open Collective sponsors at build time into
  sponsorsData.json, falling back to an empty list when the API fails
- Group sponsors by monthly amount so the wall keeps working while the
  Open Collective tiers are renamed
- Add reusable SponsorLogoGrid and SponsorAvatars components
- Add general Faq/FaqItem components fed by `faq` frontmatter, which
  also emits FAQPage structured data
- Link the page from the nav, footer and the home page sponsor card

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* feat(docs): add navbar sponsor button, more sponsor stats and tier links

- Replace the Sponsor nav text link with a dedicated heart button in the
  navbar, shown icon-only at tablet widths where the menu is crowded
- Show weekly npm downloads across all Lucide packages and the all-time
  Open Collective sponsor count in the sponsor page hero
- Add tierLinks.ts for direct Open Collective and GitHub Sponsors tier
  checkout links, falling back to the general pages while empty

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* feat(docs): update team member titles and add funding manifest

* update tier links

* Adjust hero

* Add motion counter to hero

* Add custom option

* Add scroll padding

* Fix reduce motion sponsor page

* Refactor sponsor tier links into tier data

Store only the Open Collective tier slug and GitHub Sponsors tier id on
each tier and derive the checkout URLs from them, so amounts are no
longer duplicated in the links. Removes tierLinks.ts and the circular
import between it and tiers.ts.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01G9u8FefqMHXb8HoeQ8LhcU

* Set transition duration to zero

* Add social links

* Fix stikcybar

* Format code

* Refactor SponsorAmountPicker and SponsorHeroAnimation

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* Fix sponsor animation

* Adjust tiers

* Update readmes

* Update sponsors

* Update sponsors

* Update sponsors

* Update logo gris size

* Add breaking space

* Update logos

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-11-02 12:21:25 +01:00
85 changed files with 3665 additions and 565 deletions
+2
View File
@@ -66,6 +66,7 @@ docs/.vitepress/data/categoriesData.json
docs/.vitepress/data/iconDetails
docs/.vitepress/data/relatedIcons.json
docs/.vitepress/data/brandStopwords.json
docs/.vitepress/data/sponsorsData.json
docs/.vitepress/data/iconPopularity
docs/.vitepress/data/lab/iconNodes
docs/.vitepress/data/lab/iconMetaData.ts
@@ -74,3 +75,4 @@ docs/.vercel
docs/.nitro
docs/public/og/**
!docs/public/og/general.png
.claude
+1
View File
@@ -0,0 +1 @@
https://lucide.dev/funding.json
+21 -16
View File
@@ -1,9 +1,9 @@
<p align="center">
<a href="https://github.com/lucide-icons/lucide#gh-light-mode-only">
<img src="https://lucide.dev/lucide-logo-repo.svg#gh-light-mode-only" alt="Lucide - Beautiful & consistent icon toolkit made by the community. Open-source project and a fork of Feather Icons." width="480">
</a>
<a href="https://github.com/lucide-icons/lucide#gh-dark-mode-only">
<img src="https://lucide.dev/lucide-logo-repo-dark.svg#gh-dark-mode-only" alt="Lucide - Beautiful & consistent icon toolkit made by the community. Open-source project and a fork of Feather Icons." width="480">
<a href="https://github.com/lucide-icons/lucide">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://lucide.dev/lucide-logo-repo-dark.svg">
<img src="https://lucide.dev/lucide-logo-repo.svg" alt="Lucide - Beautiful & consistent icon toolkit made by the community. Open-source project and a fork of Feather Icons." width="480">
</picture>
</a>
</p>
<p align="center">
@@ -88,24 +88,29 @@ Thank you to all the people who contributed to Lucide!
<img src="docs/public/vercel.svg" alt="Powered by Vercel" width="200" />
</a>
<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>
[//]: <> (Sponsor tiers start)
### Hero Backer 🦸
### Bronze 🥉
<a href="https://about.sourcegraph.com"><img src="https://images.opencollective.com/sourcegraph/f67b621/logo.png" height="64" alt="Sourcegraph – Understand, fix, and automate across your codebase with Sourcegraph's code intelligence platform" /></a>
<a href="https://opencollective.com/zephyr-cloud"><img src="docs/public/sponsors/zephyr-cloud.svg" height="64" alt="Zephyr Cloud" /></a>
<a href="https://about.sourcegraph.com"><picture><source media="(prefers-color-scheme: dark)" srcset="docs/public/sponsors/dark/sourcegraph.svg" /><img src="docs/public/sponsors/sourcegraph.svg" height="48" alt="Sourcegraph – Understand, fix, and automate across your codebase with Sourcegraph's code intelligence platform" /></picture></a>
&nbsp;&nbsp;
<a href="https://opencollective.com/zephyr-cloud"><picture><source media="(prefers-color-scheme: dark)" srcset="docs/public/sponsors/dark/zephyr-cloud.svg" /><img src="docs/public/sponsors/zephyr-cloud.svg" height="48" alt="Zephyr Cloud" /></picture></a>
### Awesome backers 🍺
[//]: <> (Main README only start)
<a href="https://www.paxhistoria.co"><img src="https://images.opencollective.com/pax-historia/9b4e54b/logo.png" height="64" alt="Pax Historia" /></a>
<a href="https://pdfme.com"><img src="https://images.opencollective.com/pdfmeorg/9e0174d/logo.png" height="64" alt="pdfme – Free and Open source PDF generation library!" /></a>
### Backers 🍺
### Backer ☕️
<a href="https://www.paxhistoria.co"><img src="https://images.opencollective.com/pax-historia/9b4e54b/logo.png" height="32" alt="Pax Historia" /></a>
&nbsp;&nbsp;
<a href="https://pdfme.com"><img src="https://images.opencollective.com/pdfmeorg/9e0174d/logo.png" height="32" alt="pdfme – Free and Open source PDF generation library!" /></a>
<a href="https://www.fina.money"><img src="docs/public/sponsors/fina-money.png" height="64" alt="Fina Money – Build the most flexible finance tracker" /></a>
<a href="https://opencollective.com/rjvdw"><img src="https://images.opencollective.com/rjvdw/28bc9cd/avatar.png" height="64" alt="Ruud" /></a>
### Supporters ☕️
<a href="https://www.fina.money"><img src="https://images.opencollective.com/fina-money/7c1f196/logo.png" height="32" alt="Fina Money – Build the most flexible finance tracker" /></a>
&nbsp;&nbsp;
<a href="https://opencollective.com/rjvdw"><img src="https://images.opencollective.com/rjvdw/28bc9cd/avatar.png" height="32" alt="Ruud" /></a>
[//]: <> (Main README only end)
[//]: <> (Sponsor tiers end)
+4
View File
@@ -88,6 +88,7 @@ export default defineConfig({
'index.md',
'packages.md',
'showcase.md',
'sponsor.md',
'brand-logo-statement.md',
'icons/**', // Not working, need investigation
],
@@ -123,6 +124,9 @@ export default defineConfig({
socialLinks: [
{ icon: 'github', link: 'https://github.com/lucide-icons/lucide' },
{ icon: 'discord', link: 'https://discord.gg/EH6nSts' },
{ icon: 'x', link: 'https://x.com/lucide_icons' },
{ icon: 'linkedin', link: 'https://www.linkedin.com/company/lucide-icons/' },
{ icon: 'bluesky', link: 'https://bsky.app/profile/lucide-icons.bsky.social' },
],
footer: {
message: 'Released under the ISC License.',
+5 -1
View File
@@ -9,6 +9,10 @@
"icon": "github",
"link": "https://github.com/ericfennis"
},
{
"icon": "linkedin",
"link": "https://www.linkedin.com/in/ericfennis"
},
{
"icon": "x",
"link": "https://x.com/ericfennis"
@@ -36,7 +40,7 @@
},
{
"name": "Jakob Guddas",
"title": "Creator of Lucide Studio",
"title": "Creator of Lucide Studio & Software engineer @LEGO",
"image": "https://github.com/jguddas.png?size=192",
"socialLinks": [
{
+20
View File
@@ -79,3 +79,23 @@ export default async function getStructuredData(iconName: string, pageData: Page
},
};
}
export interface FaqEntry {
question: string;
answer: string;
}
export function getFaqStructuredData(faq: FaqEntry[]) {
return {
'@context': 'https://schema.org',
'@type': 'FAQPage',
mainEntity: faq.map(({ question, answer }) => ({
'@type': 'Question',
name: question,
acceptedAnswer: {
'@type': 'Answer',
text: answer,
},
})),
};
}
@@ -0,0 +1,71 @@
<script setup lang="ts">
import { computed } from 'vue';
import { useData } from 'vitepress';
import FaqItem from './FaqItem.vue';
interface FaqEntry {
question: string;
answer: string;
}
const props = withDefaults(
defineProps<{
title?: string;
headingLevel?: 1 | 2 | 3 | 4 | 5 | 6;
/** Defaults to the page's `faq` frontmatter, which also feeds the FAQPage structured data. */
items?: FaqEntry[];
}>(),
{
headingLevel: 2,
},
);
const { frontmatter } = useData();
const entries = computed<FaqEntry[]>(() => props.items ?? frontmatter.value.faq ?? []);
const headingElement = computed(() => `h${props.headingLevel}`);
</script>
<template>
<section class="faq">
<component
v-if="title"
:is="headingElement"
class="title"
>
{{ title }}
</component>
<div class="items">
<FaqItem
v-for="entry in entries"
:key="entry.question"
:question="entry.question"
:answer="entry.answer"
/>
<slot />
</div>
</section>
</template>
<style scoped>
.faq {
display: flex;
flex-direction: column;
gap: 24px;
}
.title {
margin: 0;
font-size: 32px;
line-height: 40px;
font-weight: 600;
letter-spacing: -0.02em;
color: var(--vp-c-text-1);
}
.items {
display: flex;
flex-direction: column;
border-top: 1px solid var(--vp-c-divider);
}
</style>
@@ -0,0 +1,74 @@
<script setup lang="ts">
import { chevronDown } from '../../../data/iconNodes';
import Icon from '@lucide/vue/src/Icon';
defineProps<{
question: string;
answer?: string;
}>();
</script>
<template>
<details class="faq-item">
<summary class="question">
{{ question }}
<Icon
:iconNode="chevronDown"
name="chevron-down"
:size="20"
class="chevron"
aria-hidden="true"
/>
</summary>
<div class="answer">
<slot>
<p>{{ answer }}</p>
</slot>
</div>
</details>
</template>
<style scoped>
.faq-item {
border-bottom: 1px solid var(--vp-c-divider);
}
.question {
display: flex;
align-items: center;
justify-content: space-between;
gap: 16px;
min-height: 56px;
font-size: 16px;
font-weight: 600;
color: var(--vp-c-text-1);
list-style: none;
cursor: pointer;
}
.question::-webkit-details-marker {
display: none;
}
.chevron {
flex-shrink: 0;
color: var(--vp-c-text-2);
transition: transform 0.2s;
}
.faq-item[open] .chevron {
transform: rotate(180deg);
}
.answer {
padding-bottom: 20px;
font-size: 16px;
line-height: 28px;
color: var(--vp-c-text-2);
}
.answer :slotted(p),
.answer p {
margin: 0;
}
</style>
@@ -0,0 +1,71 @@
<script setup lang="ts">
import { computed, onBeforeUnmount, ref, watch } from 'vue';
import { animate, useInView, useReducedMotion } from 'motion-v';
/**
* Springs a number up from 0 once it scrolls into view.
* Ported from motion-counter by Tanja Gomilar (MIT): https://github.com/tgomilar/motion-components
*/
const props = withDefaults(
defineProps<{
value: number;
suffix?: string;
/** Spring duration, in seconds. */
duration?: number;
/** Delay before counting starts, in seconds. */
delay?: number;
}>(),
{
suffix: '',
duration: 1.5,
delay: 0,
},
);
const el = ref<HTMLElement>();
const inView = useInView(el, { once: true, amount: 0.2 });
const reducedMotion = useReducedMotion();
const current = ref(0);
const format = (value: number) => `${Math.round(value).toLocaleString('en-US')}${props.suffix}`;
const finalText = computed(() => format(props.value));
let controls: ReturnType<typeof animate> | undefined;
watch(inView, (isInView) => {
if (!isInView) return;
if (reducedMotion.value) {
current.value = props.value;
return;
}
controls = animate(0, props.value, {
type: 'spring',
duration: props.duration,
delay: props.delay,
bounce: 0.05,
onUpdate: (latest) => {
current.value = latest;
},
});
});
onBeforeUnmount(() => controls?.stop());
</script>
<template>
<span
ref="el"
class="motion-counter"
>
<span class="visually-hidden">{{ finalText }}</span>
<span aria-hidden="true">{{ format(current) }}</span>
</span>
</template>
<style scoped>
.motion-counter {
font-variant-numeric: tabular-nums;
}
</style>
@@ -7,7 +7,7 @@
</script>
<template>
<TabGroup>
<TabGroup as="div">
<TabList class="tab-list">
<template v-for="(tab, index) in props.tabs" :key="index">
<Tab :id="`tab-${index}`" class="tab">{{ tab }}</Tab>
@@ -22,7 +22,7 @@ import VPButton from 'vitepress/dist/client/theme-default/components/VPButton.vu
height="42"
/>
<VPButton
href="https://opencollective.com/lucide-icons"
href="/sponsor"
class="sponsor-button"
text="Become a sponsor"
/>
@@ -108,7 +108,7 @@
@media (min-width: 960px) {
.search-bar {
padding-top: 32px;
margin-top: calc((var(--vp-layout-top-height, 0px) + 32px) * -1);
margin-top: calc((var(--vp-layout-top-height, 0px) + 33px) * -1);
top: calc(var(--vp-layout-top-height, 0px) + 64px);
}
}
@@ -21,6 +21,10 @@ const links = computed(() => [
text: 'Contribute',
href: '/contribute/',
},
{
text: 'Sponsor',
href: '/sponsor',
},
{
text: 'Changelog',
href: `${githubLink.value}/releases`,
@@ -0,0 +1,466 @@
<script setup lang="ts">
import { computed, ref } from 'vue';
import VPButton from 'vitepress/dist/client/theme-default/components/VPButton.vue';
import Icon from '@lucide/vue/src/Icon';
import { check } from '../../../data/iconNodes';
import SponsorSection from './SponsorSection.vue';
import SponsorSectionHeader from './SponsorSectionHeader.vue';
import {
TIERS,
formatEuro,
getAmountLinks,
getPreviousTier,
getTierForAmount,
getTierLinks,
type Frequency,
} from './tiers';
const frequencies: { id: Frequency; label: string }[] = [
{ id: 'monthly', label: 'Monthly' },
{ id: 'once', label: 'One-time' },
];
const frequency = ref<Frequency>('monthly');
const amount = ref(20);
// `v-model` on a number input casts to a number, an empty field stays ''.
const customAmount = ref<number | ''>('');
const isMonthly = computed(() => frequency.value === 'monthly');
const total = computed(() => {
const value = customAmount.value === '' ? amount.value : Number(customAmount.value);
return value > 0 ? Math.round(value) : 0;
});
const tier = computed(() => (isMonthly.value ? getTierForAmount(total.value) : null));
// A monthly preset opens its tier's checkout, other amounts open a checkout prefilled with
// the amount. The platforms expect whole amounts, so decimals are rounded.
const links = computed(() => {
const value = Math.round(total.value);
if (customAmount.value === '' && tier.value) return getTierLinks(tier.value);
if (value > 0) return getAmountLinks(value, frequency.value);
return getTierLinks();
});
const amountText = computed(() => formatEuro(total.value));
const summary = computed(() => {
if (total.value === 0) {
return { title: 'Choose an amount', perks: 'Pick a preset or enter your own.' };
}
if (!isMonthly.value) {
return {
title: `${amountText.value} one-time`,
perks: 'A one-time thank-you. Tier perks apply to monthly sponsorships.',
};
}
if (tier.value) {
return {
title: `${amountText.value} / month · ${tier.value.name}`,
perks: tier.value.summary,
};
}
return { title: `${amountText.value} / month`, perks: 'Every bit helps. Thank you!' };
});
const perksPanel = computed(() => {
if (tier.value) {
const previousTier = getPreviousTier(tier.value.id);
return {
title: tier.value.name,
subtitle: `From ${formatEuro(tier.value.monthly)} / month`,
perks: [
...(previousTier ? [{ text: `Everything in ${previousTier.name}`, inherited: true }] : []),
...tier.value.perks.map((text) => ({ text, inherited: false })),
],
message: '',
};
}
if (!isMonthly.value) {
return {
title: 'One-time gift',
subtitle: total.value > 0 ? `${amountText.value}, once` : 'Any amount',
perks: [],
message:
'Thank you! Tier perks come with monthly sponsorships. Switch to Monthly to see what you would get.',
};
}
return {
title: 'No tier yet',
subtitle: total.value > 0 ? `${amountText.value} / month` : 'Choose an amount',
perks: [],
message: `Every bit helps. From ${formatEuro(TIERS[0].monthly)} a month you become a ${TIERS[0].name}.`,
};
});
const isSelected = (value: number) => customAmount.value === '' && amount.value === value;
function pickAmount(value: number) {
amount.value = value;
customAmount.value = '';
}
</script>
<template>
<SponsorSection band>
<SponsorSectionHeader
title="Choose your support"
description="Pick an amount, monthly or one-time. Monthly amounts map to a sponsor tier with its own perks. Lucide stays free and open source either way."
/>
<div class="layout">
<div class="card picker">
<div
role="group"
aria-label="Frequency"
class="frequency"
>
<button
v-for="option in frequencies"
:key="option.id"
type="button"
class="frequency-option"
:class="{ active: frequency === option.id }"
:aria-pressed="frequency === option.id"
@click="frequency = option.id"
>
{{ option.label }}
</button>
</div>
<div class="amounts">
<button
v-for="option in TIERS"
:key="option.id"
type="button"
class="amount"
:class="{ selected: isSelected(option.monthly) }"
:aria-pressed="isSelected(option.monthly)"
@click="pickAmount(option.monthly)"
>
<span class="amount-value">{{ formatEuro(option.monthly) }}</span>
<span class="amount-label">{{ isMonthly ? option.name : 'One-time' }}</span>
</button>
<label
class="amount custom"
:class="{ selected: customAmount !== '' }"
>
<span class="amount-label">Custom (€)</span>
<input
v-model="customAmount"
type="number"
min="1"
inputmode="numeric"
placeholder="Other"
class="amount-value custom-input"
/>
</label>
</div>
<div class="summary">
<div class="summary-text">
<span class="summary-title">{{ summary.title }}</span>
<span class="summary-perks">{{ summary.perks }}</span>
</div>
<div class="summary-actions">
<VPButton
:href="links.openCollective"
text="Open Collective"
/>
<VPButton
:href="links.githubSponsors"
text="GitHub Sponsors"
theme="alt"
/>
</div>
</div>
</div>
<aside
class="card perks"
aria-live="polite"
>
<div class="perks-header">
<span class="eyebrow">Your perks</span>
<h3 class="perks-title">{{ perksPanel.title }}</h3>
<span class="perks-subtitle">{{ perksPanel.subtitle }}</span>
</div>
<ul
v-if="perksPanel.perks.length"
class="perks-list"
>
<li
v-for="perk in perksPanel.perks"
:key="perk.text"
class="perk"
:class="{ inherited: perk.inherited }"
>
<Icon
:iconNode="check"
name="check"
:size="18"
class="perk-icon"
aria-hidden="true"
/>
{{ perk.text }}
</li>
</ul>
<p
v-else
class="perks-message"
>
{{ perksPanel.message }}
</p>
<a
href="#tiers"
class="compare"
>
Compare all tiers
</a>
</aside>
</div>
</SponsorSection>
</template>
<style scoped>
.layout {
display: flex;
flex-wrap: wrap;
gap: 24px;
align-items: stretch;
}
.card {
min-width: 0;
padding: 24px;
border-radius: 16px;
background-color: var(--vp-c-bg);
border: 1px solid var(--vp-c-divider);
display: flex;
flex-direction: column;
gap: 24px;
}
.picker {
flex: 999 1 520px;
}
.frequency {
display: inline-flex;
align-self: flex-start;
padding: 4px;
gap: 4px;
border-radius: 999px;
background-color: var(--vp-c-bg-soft);
border: 1px solid var(--vp-c-divider);
}
.frequency-option {
min-height: 40px;
padding: 0 18px;
border-radius: 999px;
font-size: 14px;
font-weight: 600;
color: var(--vp-c-text-2);
transition:
color 0.25s,
background-color 0.25s;
}
.frequency-option.active {
background-color: var(--vp-c-bg);
color: var(--vp-c-text-1);
box-shadow: var(--vp-shadow-1);
}
.amounts {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
gap: 12px;
}
.amount {
display: flex;
flex-direction: column;
align-items: flex-start;
justify-content: center;
gap: 2px;
min-height: 72px;
padding: 8px 12px;
border-radius: 12px;
border: 2px solid var(--vp-c-divider);
background-color: var(--vp-c-bg);
color: var(--vp-c-text-1);
text-align: left;
cursor: pointer;
transition:
border-color 0.25s,
background-color 0.25s;
}
.amount:hover {
border-color: var(--vp-c-border);
}
.amount.selected {
border-color: var(--sponsor-accent);
background-color: rgba(245, 101, 101, 0.08);
}
.amount-value {
font-size: 20px;
line-height: 28px;
font-weight: 600;
}
.amount-label {
font-size: 13px;
line-height: 18px;
font-weight: 500;
color: var(--vp-c-text-2);
}
.custom {
cursor: text;
}
.custom-input {
width: 100%;
padding: 0;
border: 0;
outline: none;
background: transparent;
color: var(--vp-c-text-1);
}
.custom:focus-within {
border-color: var(--sponsor-accent);
}
.summary {
display: flex;
flex-wrap: wrap;
gap: 16px;
align-items: center;
justify-content: space-between;
padding: 16px;
border-radius: 12px;
background-color: var(--vp-c-bg-soft);
}
.summary-text {
flex: 1 1 280px;
min-width: 0;
display: flex;
flex-direction: column;
gap: 4px;
}
.summary-title {
font-size: 18px;
line-height: 24px;
font-weight: 600;
color: var(--vp-c-text-1);
}
.summary-perks {
font-size: 14px;
line-height: 22px;
color: var(--vp-c-text-2);
}
.summary-actions {
display: flex;
flex-wrap: wrap;
gap: 8px;
}
.perks {
flex: 1 1 300px;
gap: 20px;
}
.perks-header {
display: flex;
flex-direction: column;
gap: 4px;
}
.eyebrow {
font-size: 13px;
font-weight: 600;
color: var(--vp-c-text-2);
text-transform: uppercase;
letter-spacing: 0.04em;
}
.perks-title {
margin: 0;
font-size: 24px;
line-height: 32px;
font-weight: 600;
letter-spacing: -0.02em;
color: var(--vp-c-text-1);
}
.perks-subtitle {
font-size: 14px;
color: var(--vp-c-text-2);
}
.perks-list {
margin: 0;
padding: 16px 0 0;
list-style: none;
display: flex;
flex-direction: column;
gap: 12px;
font-size: 14px;
line-height: 22px;
border-top: 1px solid var(--vp-c-divider);
}
.perk {
display: flex;
gap: 10px;
color: var(--vp-c-text-1);
}
.perk.inherited {
color: var(--vp-c-text-2);
font-weight: 500;
}
.perk-icon {
flex-shrink: 0;
margin-top: 2px;
color: var(--sponsor-accent);
}
.perks-message {
margin: 0;
padding-top: 16px;
border-top: 1px solid var(--vp-c-divider);
font-size: 14px;
line-height: 22px;
color: var(--vp-c-text-2);
}
.compare {
margin-top: auto;
padding: 10px 0;
font-size: 14px;
font-weight: 600;
color: var(--sponsor-accent);
text-decoration: none;
}
.compare:hover {
text-decoration: underline;
}
</style>
@@ -0,0 +1,123 @@
<script setup lang="ts">
import { computed } from 'vue';
import { getSupporters } from './sponsors';
import { OPEN_COLLECTIVE_URL } from './tiers';
const props = withDefaults(
defineProps<{
title?: string;
headingLevel?: 2 | 3 | 4 | 5 | 6;
/** Maximum number of avatars shown before "and N more". */
max?: number;
}>(),
{
title: 'Backers and supporters',
headingLevel: 3,
max: 48,
},
);
const supporters = getSupporters();
const visibleSupporters = computed(() => supporters.slice(0, props.max));
const remainingCount = computed(() => supporters.length - visibleSupporters.value.length);
const headingElement = computed(() => `h${props.headingLevel}`);
</script>
<template>
<div
v-if="supporters.length"
class="avatars"
>
<component
:is="headingElement"
class="title"
>
{{ title }}
</component>
<div class="list">
<a
v-for="supporter in visibleSupporters"
:key="supporter.slug"
:href="supporter.website"
:title="supporter.name"
target="_blank"
rel="noreferrer noopener"
class="avatar-link"
>
<img
:src="supporter.avatar"
:alt="supporter.name"
width="40"
height="40"
class="avatar"
loading="lazy"
/>
</a>
<a
v-if="remainingCount > 0"
:href="OPEN_COLLECTIVE_URL"
target="_blank"
rel="noreferrer"
class="more"
>
and {{ remainingCount }} more
</a>
</div>
</div>
</template>
<style scoped>
.avatars {
display: flex;
flex-direction: column;
gap: 12px;
}
.title {
margin: 0;
font-size: 14px;
font-weight: 600;
line-height: 20px;
color: var(--vp-c-text-2);
text-transform: uppercase;
letter-spacing: 0.04em;
}
.list {
display: flex;
flex-wrap: wrap;
gap: 8px;
align-items: center;
}
.avatar-link {
display: block;
border-radius: 999px;
transition: transform 0.25s;
}
.avatar-link:hover {
transform: translateY(-2px);
}
.avatar {
width: 40px;
height: 40px;
border-radius: 999px;
object-fit: cover;
background-color: var(--vp-c-bg-soft);
border: 2px solid var(--vp-c-bg);
}
.more {
padding-left: 8px;
font-size: 14px;
color: var(--vp-c-text-2);
text-decoration: none;
}
.more:hover {
text-decoration: underline;
}
</style>
@@ -0,0 +1,71 @@
<script setup lang="ts">
import VPButton from 'vitepress/dist/client/theme-default/components/VPButton.vue';
import SponsorSection from './SponsorSection.vue';
</script>
<template>
<SponsorSection class="cta">
<div class="cta-card">
<h2 class="title">You like building with Lucide?</h2>
<p class="description">
Help keep it beautiful and consistent for everyone who comes after you.
</p>
<div class="actions">
<VPButton
href="#tiers"
text="Become a sponsor"
size="big"
/>
<VPButton
href="https://github.com/lucide-icons/lucide"
text="Star on GitHub"
size="big"
theme="alt"
/>
</div>
</div>
</SponsorSection>
</template>
<style scoped>
.cta {
padding-top: 0;
padding-bottom: 96px;
}
.cta-card {
padding: 48px 32px;
border-radius: 16px;
background-color: var(--vp-c-bg-soft);
border: 1px solid var(--vp-c-divider);
display: flex;
flex-direction: column;
align-items: center;
text-align: center;
gap: 20px;
}
.title {
margin: 0;
font-size: 32px;
line-height: 40px;
font-weight: 600;
letter-spacing: -0.02em;
color: var(--vp-c-text-1);
}
.description {
margin-bottom: 24px;
max-width: 640px;
font-size: 18px;
line-height: 28px;
color: var(--vp-c-text-2);
}
.actions {
display: flex;
flex-wrap: wrap;
gap: 12px;
justify-content: center;
}
</style>
@@ -0,0 +1,105 @@
<script setup lang="ts">
import Icon from '@lucide/vue/src/Icon';
import { gitPullRequest, server, shapes, users } from '../../../data/iconNodes';
import SponsorSection from './SponsorSection.vue';
import SponsorSectionHeader from './SponsorSectionHeader.vue';
const uses = [
{
title: 'Maintenance and reviews',
description: 'Reviewing icon PRs, fixing issues and shipping releases across every package.',
icon: gitPullRequest,
name: 'git-pull-request',
},
{
title: 'New icons and packages',
description: 'Designing icons the community asks for and supporting new frameworks.',
icon: shapes,
name: 'shapes',
},
{
title: 'Contributors',
description: 'Supporting the people who design, review and document Lucide.',
icon: users,
name: 'users',
},
{
title: 'Infrastructure',
description: 'Hosting lucide.dev, search, CI and the tools the team relies on.',
icon: server,
name: 'server',
},
];
</script>
<template>
<SponsorSection band>
<SponsorSectionHeader
title="Where your money goes"
description="Lucide holds its funds on Open Collective, so every expense is public."
/>
<div class="uses">
<div
v-for="use in uses"
:key="use.title"
class="use"
>
<div class="icon-tile">
<Icon
:iconNode="use.icon"
:name="use.name"
:size="22"
aria-hidden="true"
/>
</div>
<h3 class="use-title">{{ use.title }}</h3>
<p class="use-description">{{ use.description }}</p>
</div>
</div>
</SponsorSection>
</template>
<style scoped>
.uses {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
gap: 16px;
}
.use {
padding: 24px;
border-radius: 12px;
background-color: var(--vp-c-bg);
border: 1px solid var(--vp-c-divider);
display: flex;
flex-direction: column;
gap: 12px;
}
.icon-tile {
width: 44px;
height: 44px;
border-radius: 8px;
background-color: var(--vp-c-default-soft);
color: var(--sponsor-accent);
display: flex;
align-items: center;
justify-content: center;
}
.use-title {
margin: 0;
font-size: 16px;
line-height: 24px;
font-weight: 600;
color: var(--vp-c-text-1);
}
.use-description {
margin: 0;
font-size: 14px;
line-height: 24px;
font-weight: 500;
color: var(--vp-c-text-2);
}
</style>
@@ -0,0 +1,196 @@
<script setup lang="ts">
import VPButton from 'vitepress/dist/client/theme-default/components/VPButton.vue';
import MotionCounter from '../base/MotionCounter.vue';
import SponsorSection from './SponsorSection.vue';
import SponsorHeroAnimation from './SponsorHeroAnimation.vue';
import { data } from './SponsorStats.data';
import { allTimeSponsorCount } from './sponsors';
/** Rounds down to a short "120M+" / "25k+" figure, split so the counter only counts the number. */
function toCompact(value: number) {
if (value >= 1_000_000) return { value: Math.floor(value / 1_000_000), suffix: 'M+' };
if (value >= 1_000) return { value: Math.floor(value / 1_000), suffix: 'k+' };
return { value, suffix: '' };
}
const stats = [
{ value: data.weeklyDownloads, label: 'Weekly downloads', format: toCompact },
{ value: data.stars, label: 'GitHub stars', format: toCompact },
{
value: data.iconsCount,
label: 'Icons',
format: (value: number) => ({ value: Math.floor(value / 100) * 100, suffix: '+' }),
},
{
value: allTimeSponsorCount,
label: 'All-time sponsors',
format: (value: number) => ({ value, suffix: '' }),
},
]
// Stats the build couldn't fetch are left out.
.filter((stat): stat is typeof stat & { value: number } => stat.value != null)
.map(({ value, label, format }) => ({ ...format(value), label }));
</script>
<template>
<SponsorSection class="hero">
<div class="hero-content">
<div class="intro">
<h1 class="title">Sponsor <span class="name">Lucide</span></h1>
<p class="lead">
Lucide is built and maintained by a small team and a big community. Your sponsorship pays
for icon reviews, new packages and the hours that keep every release dependable.
</p>
<div class="actions">
<VPButton
href="#tiers"
text="Become a sponsor"
size="big"
/>
<VPButton
href="#sponsors"
text="See our sponsors"
size="big"
theme="alt"
/>
</div>
<dl class="stats">
<div
v-for="(stat, index) in stats"
:key="stat.label"
class="stat"
>
<dt class="stat-label">{{ stat.label }}</dt>
<dd class="stat-value">
<MotionCounter
:value="stat.value"
:suffix="stat.suffix"
:delay="0.5 +(index * 0.1)"
/>
</dd>
</div>
</dl>
</div>
<SponsorHeroAnimation class="hero-animation" />
</div>
</SponsorSection>
</template>
<style scoped>
.hero {
padding-top: 48px;
}
.hero-content {
display: flex;
flex-wrap: wrap;
gap: 48px;
align-items: center;
flex-direction: column-reverse;
}
.intro {
min-width: 0;
display: flex;
flex-direction: column;
gap: 24px;
}
.title {
margin: 0;
font-size: 40px;
line-height: 48px;
font-weight: 700;
letter-spacing: -0.02em;
color: var(--vp-c-text-1);
}
.name {
color: var(--vp-c-brand-3);
}
.lead {
margin: 0;
max-width: 560px;
font-size: 18px;
line-height: 28px;
font-weight: 500;
color: var(--vp-c-text-2);
}
.actions {
display: flex;
flex-wrap: wrap;
gap: 12px;
}
.stats {
max-width: 560px;
margin: 0;
padding-top: 24px;
border-top: 1px solid var(--vp-c-divider);
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 24px 16px;
}
.stat {
display: flex;
flex-direction: column;
gap: 2px;
}
.stat-value {
order: -1;
margin: 0;
font-size: 24px;
line-height: 32px;
font-weight: 700;
letter-spacing: -0.02em;
color: var(--vp-c-text-1);
}
.stat-label {
font-size: 13px;
color: var(--vp-c-text-2);
white-space: nowrap;
}
.hero-animation {
display: block;
flex: 1 1 340px;
min-width: 0;
width: 100%;
margin: 0 -24px;
}
@media (min-width: 640px) {
.stats {
grid-template-columns: repeat(4, minmax(0, 1fr));
}
}
@media (min-width: 768px) {
.hero {
padding-top: 96px;
}
.title {
font-size: 56px;
line-height: 64px;
}
.stat-value {
font-size: 28px;
line-height: 36px;
}
}
@media (min-width: 960px) {
.hero-content {
flex-direction: row;
}
}
</style>
@@ -0,0 +1,259 @@
<script setup lang="ts">
import { onMounted, ref } from 'vue';
import { motion, type Options as MotionOptions } from 'motion-v';
import { useMediaQuery } from '@vueuse/core';
// motion-v re-exports framer-motion's `Variants`, which doesn't match the `variants` prop of its components
type Variants = MotionOptions['variants'];
/**
* Draws the heart icon the way the SVG editor previews it (handles and arc radii),
* played once and stopped at the red heart.
*/
const HEART_PATH =
'M2 9.5a5.5 5.5 0 0 1 9.591-3.676.56.56 0 0 0 .818 0A5.49 5.49 0 0 1 22 9.5c0 2.29-1.5 4-3 5.5l-5.492 5.313a2 2 0 0 1-3 .019L5 15c-1.5-1.5-3-3.2-3-5.5';
const VERTICES =
'M2 9.5h.01M11.591 5.824h.01M12.409 5.824h.01M22 9.5h.01M19 15h.01M13.508 20.313h.01M10.508 20.332h.01M5 15h.01';
const MARKERS = [[2, 9.5]];
/** Bezier handles as [x1, y1, x2, y2] segments, grouped by when they appear. */
const HANDLE_GROUPS = [
{ delay: 0.2, segments: [[22, 9.5, 22, 11.79]] },
{ delay: 0.4, segments: [[19, 15, 20.5, 13.5]] },
{ delay: 0.6, segments: [[5, 15, 3.5, 13.5]] },
{ delay: 0.8, segments: [[2, 9.5, 2, 11.8]] },
];
/** Arc radius guides: the arc's centre and radius, drawn from one arc end to the centre to the other. */
const ARC_GUIDES = [
{ cx: 7.5, cy: 9.5, r: 5.5, from: [2, 9.5], to: [11.591, 5.824], delay: 0.3 },
{ cx: 12, cy: 5.4415, r: 0.56, from: [11.591, 5.824], to: [12.409, 5.824], delay: 0.5 },
{ cx: 16.5101, cy: 9.4738, r: 5.49, from: [12.409, 5.824], to: [22, 9.5], delay: 0.7 },
{ cx: 11.9996, cy: 18.9997, r: 2, from: [13.508, 20.313], to: [10.508, 20.332], delay: 0.9 },
];
const draw: Variants = {
hidden: { pathLength: 0, opacity: 0 },
visible: {
pathLength: 1.02,
opacity: 1,
transition: {
pathLength: { delay: 2.4, type: 'spring', duration: 2.8, bounce: 0 },
opacity: { delay: 2.4, duration: 0.1 },
},
},
exit: {
stroke: 'var(--vp-c-brand)',
pathLength: 1.02,
opacity: 1,
transition: {
duration: 0.8,
},
},
};
const drawAnimation = ref('visible');
const showHandles = ref(true);
const onAnimationComplete = (variant: unknown) => {
if (variant === 'visible') {
drawAnimation.value = 'exit';
} else if (variant === 'exit') {
showHandles.value = false;
}
};
// Only rendered on the client, so reduced motion is known before the first frame
const mounted = ref(false);
const reducedMotion = useMediaQuery('(prefers-reduced-motion: reduce)');
onMounted(() => {
if (reducedMotion.value) {
drawAnimation.value = 'exit';
}
mounted.value = true;
});
/** Skips straight to the end state when the user prefers reduced motion. */
const initial = <T,>(value: T) => (reducedMotion.value ? false : value);
</script>
<template>
<div
class="sponsor-hero-animation-container"
>
<div
class="sponsor-hero-animation"
aria-hidden="true"
>
<svg
v-if="mounted"
xmlns="http://www.w3.org/2000/svg"
viewBox="-12 -12 48 48"
fill="none"
overflow="auto"
stroke="currentColor"
stroke-width="1"
stroke-linecap="round"
stroke-linejoin="round"
class="hero-background"
focusable="false"
>
<g
stroke-linecap="butt"
stroke-width="0.1"
stroke="#777"
stroke-opacity="0.3"
>
<path
stroke-dasharray="0 0.1 0.1 0.15 0.1 0.15 0.1 0.15 0.1 0.15 0.1 0.15 0.1 0.15 0.1 0.15 0.1 0.15 0.1 0.15 0.1 0.15 0.1 0.15 0 0.15"
stroke-width="0.1"
d="M1 0.1v23.8M2 0.1v23.8M4 0.1v23.8M5 0.1v23.8M7 0.1v23.8M8 0.1v23.8M10 0.1v23.8M11 0.1v23.8M13 0.1v23.8M14 0.1v23.8M16 0.1v23.8M17 0.1v23.8M19 0.1v23.8M20 0.1v23.8M22 0.1v23.8M23 0.1v23.8M0.1 1h23.8M0.1 2h23.8M0.1 4h23.8M0.1 5h23.8M0.1 7h23.8M0.1 8h23.8M0.1 10h23.8M0.1 11h23.8M0.1 13h23.8M0.1 14h23.8M0.1 16h23.8M0.1 17h23.8M0.1 19h23.8M0.1 20h23.8M0.1 22h23.8M0.1 23h23.8"
/>
<path
d="M3 0.1v23.8M6 0.1v23.8M9 0.1v23.8M12 0.1v23.8M15 0.1v23.8M18 0.1v23.8M21 0.1v23.8M0.1 3h23.8M0.1 6h23.8M0.1 9h23.8M0.1 12h23.8M0.1 15h23.8M0.1 18h23.8M0.1 21h23.8"
/>
</g>
<motion.g
stroke-width="0.12"
stroke-dasharray="0 0.25 0.25"
stroke="#777"
stroke-opacity="0.3"
:initial="initial({ opacity: 1 })"
:animate="{ opacity: showHandles ? 1 : 0 }"
:transition="{ duration: 0.6 }"
>
<motion.g
v-for="arc in ARC_GUIDES"
:key="`${arc.cx},${arc.cy}`"
:initial="initial({ opacity: 0, scale: 0.2 })"
:animate="{ opacity: 1, scale: 1 }"
:transition="{ delay: arc.delay, duration: 0.3 }"
>
<path :d="`M${arc.from.join(' ')}L${arc.cx} ${arc.cy}L${arc.to.join(' ')}`" />
<circle
:cx="arc.cx"
:cy="arc.cy"
r="0.25"
stroke-dasharray="0"
stroke="red"
/>
<circle
:cx="arc.cx"
:cy="arc.cy"
:r="arc.r"
stroke="red"
/>
</motion.g>
</motion.g>
<motion.path
:d="HEART_PATH"
stroke-width="2"
:style="{ stroke: reducedMotion? 'var(--vp-c-brand)' : 'var(--vp-c-gray-1)' }"
:initial="initial('hidden')"
:animate="drawAnimation"
:variants="draw"
@animation-complete="onAnimationComplete"
/>
<motion.g
:style="{ stroke: 'var(--vp-c-text-1)' }"
stroke-width="0.125"
:initial="initial({ opacity: 1 })"
:animate="{ opacity: showHandles ? 1 : 0 }"
:transition="{ duration: 0.2 }"
>
<motion.path
:d="HEART_PATH"
:initial="initial({ opacity: 0 })"
:animate="{ opacity: 1 }"
:transition="{ delay: 1.6, duration: 1.5 }"
/>
<motion.path
:d="VERTICES"
:initial="initial({ opacity: 0 })"
:animate="{ opacity: 1 }"
:transition="{ delay: 0.2, duration: 0.3 }"
/>
<motion.circle
v-for="[cx, cy] in MARKERS"
:key="`${cx},${cy}`"
:cx="cx"
:cy="cy"
r="0.5"
:initial="initial({ opacity: 0, scale: 0.2 })"
:animate="{ opacity: 1, scale: 1 }"
:transition="{ duration: 0.8 }"
/>
</motion.g>
<motion.g
stroke-width="0.12"
stroke="#FFF"
stroke-opacity="0.3"
:initial="initial({ opacity: 1 })"
:animate="{ opacity: showHandles ? 1 : 0 }"
:transition="{ duration: 0.6 }"
>
<motion.g
v-for="(group, index) in HANDLE_GROUPS"
:key="index"
:initial="initial({ opacity: 0, scale: 0.2 })"
:animate="{ opacity: 1, scale: 1 }"
:transition="{ delay: group.delay, duration: 0.3 }"
>
<template
v-for="[x1, y1, x2, y2] in group.segments"
:key="`${x2},${y2}`"
>
<path :d="`M${x1} ${y1} ${x2} ${y2}`" />
<circle
:cx="x2"
:cy="y2"
r="0.25"
/>
</template>
</motion.g>
</motion.g>
</svg>
</div>
</div>
</template>
<style scoped>
.sponsor-hero-animation-container {
margin: -48px -24px 0;
display: flex;
}
.sponsor-hero-animation {
position: relative;
width: 100%;
max-width: 520px;
margin: 0 auto;
aspect-ratio: 8 / 5;
overflow: hidden;
}
@media (min-width: 960px) {
.sponsor-hero-animation {
max-width: 860px;
}
}
.hero-background {
position: absolute;
top: 50%;
left: 50%;
width: 130%;
aspect-ratio: 1;
transform: translate(-50%, -50%) rotateX(-51deg) rotateZ(-43deg);
transform-style: preserve-3d;
pointer-events: none;
}
</style>
@@ -0,0 +1,186 @@
<script setup lang="ts">
import { computed } from 'vue';
import { getSponsorsByTier } from './sponsors';
import { getTier } from './tiers';
type LogoTier = 'platinum' | 'gold' | 'bronze';
type Size = 'lg' | 'md' | 'sm';
const defaultSizes: Record<LogoTier, Size> = {
platinum: 'lg',
gold: 'md',
bronze: 'sm',
};
const props = withDefaults(
defineProps<{
tier: LogoTier;
/** Defaults to the tier name. */
title?: string;
headingLevel?: 2 | 3 | 4 | 5 | 6;
size?: Size;
/**
* Number of "Your logo here" slots to fill up to. Without placeholders the grid
* renders nothing while the tier has no sponsors.
*/
placeholders?: number;
}>(),
{
headingLevel: 3,
placeholders: 0,
},
);
const sponsors = getSponsorsByTier(props.tier);
const placeholderCount = computed(() => Math.max(props.placeholders - sponsors.length, 0));
const headingElement = computed(() => `h${props.headingLevel}`);
const sizeClass = computed(() => props.size ?? defaultSizes[props.tier]);
</script>
<template>
<div
v-if="sponsors.length || placeholderCount"
class="logo-grid"
>
<component
:is="headingElement"
class="title"
>
{{ title ?? getTier(tier).name }}
</component>
<div
class="tiles"
:class="sizeClass"
>
<a
v-for="sponsor in sponsors"
:key="sponsor.slug"
:href="sponsor.website"
target="_blank"
rel="noreferrer noopener"
class="tile"
>
<img
:src="sponsor.image"
:alt="sponsor.name"
class="logo"
:class="{ 'light-only': sponsor.imageDark }"
loading="lazy"
/>
<img
v-if="sponsor.imageDark"
:src="sponsor.imageDark"
:alt="sponsor.name"
class="logo dark-only"
loading="lazy"
/>
</a>
<a
v-for="index in placeholderCount"
:key="`placeholder-${index}`"
href="/sponsor#tiers"
class="tile placeholder"
>
Your logo here
</a>
</div>
</div>
</template>
<style scoped>
.logo-grid {
display: flex;
flex-direction: column;
gap: 12px;
}
.title {
margin: 0;
font-size: 14px;
font-weight: 600;
line-height: 20px;
color: var(--vp-c-text-2);
text-transform: uppercase;
letter-spacing: 0.04em;
}
.tiles {
display: grid;
gap: 12px;
}
.tiles.lg {
grid-template-columns: 1fr;
}
.tiles.md {
grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
}
.tiles.sm {
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
}
.tile {
display: flex;
align-items: center;
justify-content: center;
padding: 16px 24px;
border-radius: 12px;
background-color: var(--vp-c-bg-soft);
border: 1px solid var(--vp-c-divider);
text-decoration: none;
transition: border-color 0.25s;
}
.tile:hover {
border-color: var(--vp-c-brand-1);
}
.lg .tile {
min-height: 120px;
}
.md .tile {
min-height: 96px;
}
.sm .tile {
min-height: 72px;
}
.logo {
/* max-width: 70%; */
object-fit: contain;
}
.lg .logo {
max-height: 72px;
}
.md .logo {
max-height: 64px;
}
.sm .logo {
max-height: 56px;
}
html:not(.dark) .logo.dark-only,
html.dark .logo.light-only {
display: none;
}
.placeholder {
background-color: transparent;
border: 2px dashed var(--vp-c-border);
color: var(--vp-c-text-2);
font-size: 15px;
font-weight: 600;
}
.lg .placeholder {
font-size: 16px;
}
</style>
@@ -0,0 +1,51 @@
<script setup lang="ts">
defineProps<{
/** Full-bleed tinted background with divider borders. */
band?: boolean;
narrow?: boolean;
}>();
</script>
<template>
<section
class="sponsor-section"
:class="{ band }"
>
<div
class="inner"
:class="{ narrow }"
>
<slot />
</div>
</section>
</template>
<style scoped>
.sponsor-section {
--sponsor-accent: var(--vp-c-brand-5);
padding: 72px 24px;
}
html.dark .sponsor-section {
--sponsor-accent: var(--vp-c-brand-1);
}
.sponsor-section.band {
background-color: var(--vp-c-bg-soft);
border-top: 1px solid var(--vp-c-divider);
border-bottom: 1px solid var(--vp-c-divider);
}
.inner {
max-width: 1152px;
margin: 0 auto;
display: flex;
flex-direction: column;
gap: 32px;
}
.inner.narrow {
max-width: 768px;
gap: 24px;
}
</style>
@@ -0,0 +1,43 @@
<script setup lang="ts">
defineProps<{
title: string;
description?: string;
}>();
</script>
<template>
<div class="section-header">
<h2 class="title">{{ title }}</h2>
<p
v-if="description"
class="description"
>
{{ description }}
</p>
</div>
</template>
<style scoped>
.section-header {
display: flex;
flex-direction: column;
gap: 12px;
max-width: 680px;
}
.title {
margin: 0;
font-size: 32px;
line-height: 40px;
font-weight: 600;
letter-spacing: -0.02em;
color: var(--vp-c-text-1);
}
.description {
margin: 0;
font-size: 16px;
line-height: 28px;
color: var(--vp-c-text-2);
}
</style>
@@ -0,0 +1,82 @@
import iconNodes from '../../../data/iconNodes';
import fetchPackages from '../../../lib/fetchPackages';
const NPM_DOWNLOADS_API = 'https://api.npmjs.org/downloads/point/last-week';
/**
* Packages that are no longer in the repo but are still published and installed.
*/
const LEGACY_PACKAGES = ['lucide-vue-next', 'lucide-vue', 'lucide-svelte', 'lucide-angular'];
async function fetchStars() {
try {
const response = await fetch('https://api.github.com/repos/lucide-icons/lucide');
if (!response.ok) return null;
const { stargazers_count } = (await response.json()) as { stargazers_count: number };
return stargazers_count;
} catch {
return null;
}
}
async function fetchDownloads(url: string) {
const response = await fetch(url);
if (!response.ok) {
throw new Error(`npm downloads API responded with ${response.status} for ${url}`);
}
return response.json();
}
/**
* Sum of last week's npm downloads of every published Lucide package, or `null` when any
* request fails, so a partial total never shows up as the real number.
*/
async function fetchWeeklyDownloads() {
try {
const packageNames = (await fetchPackages())
.filter((packageJson) => packageJson?.name && !packageJson.private)
.map(({ name }) => name)
.concat(LEGACY_PACKAGES);
// The bulk endpoint only accepts unscoped packages, scoped ones are fetched one by one.
const unscoped = packageNames.filter((name) => !name.startsWith('@'));
const scoped = packageNames.filter((name) => name.startsWith('@'));
const [bulk, ...single] = await Promise.all([
fetchDownloads(`${NPM_DOWNLOADS_API}/${unscoped.join(',')}`) as Promise<
Record<string, { downloads: number } | null>
>,
...scoped.map(
(name) => fetchDownloads(`${NPM_DOWNLOADS_API}/${name}`) as Promise<{ downloads: number }>,
),
]);
return [...Object.values(bulk), ...single].reduce(
(total, result) => total + (result?.downloads ?? 0),
0,
);
} catch (error) {
console.warn(`Could not fetch npm downloads. ${error}`);
return null;
}
}
const loader = {
async load() {
const [stars, weeklyDownloads] = await Promise.all([fetchStars(), fetchWeeklyDownloads()]);
return {
stars,
weeklyDownloads,
iconsCount: Object.keys(iconNodes).length,
};
},
};
declare const data: Awaited<ReturnType<typeof loader.load>>;
export { data };
export default loader;
@@ -0,0 +1,188 @@
<script setup lang="ts">
import { computed } from 'vue';
import VPButton from 'vitepress/dist/client/theme-default/components/VPButton.vue';
import Icon from '@lucide/vue/src/Icon';
import { check } from '../../../data/iconNodes';
import { formatEuro, getPreviousTier, getTierLinks, type Tier } from './tiers';
const props = defineProps<{
tier: Tier;
}>();
const previousTier = computed(() => getPreviousTier(props.tier.id));
const links = computed(() => getTierLinks(props.tier));
</script>
<template>
<article class="tier-card">
<div class="header">
<h3 class="name">{{ tier.name }}</h3>
<div class="price">
<span class="amount">{{ formatEuro(tier.monthly) }}</span>
<span class="period">/ month</span>
</div>
<span
v-if="tier.yearly"
class="yearly"
>
or {{ formatEuro(tier.yearly) }} / year, two months free
</span>
</div>
<ul class="perks">
<li
v-if="previousTier"
class="inherited"
>
Everything in {{ previousTier.name }}, plus
</li>
<li
v-for="perk in tier.perks"
:key="perk"
class="perk"
>
<Icon
:iconNode="check"
name="check"
:size="18"
class="perk-icon"
aria-hidden="true"
/>
{{ perk }}
</li>
</ul>
<div class="actions">
<VPButton
:href="links.openCollective"
text="Open Collective"
:theme="tier.featured ? 'brand' : 'alt'"
class="primary-action"
/>
<a
:href="links.githubSponsors"
target="_blank"
rel="noreferrer"
class="secondary-action"
>
GitHub Sponsors
</a>
</div>
</article>
</template>
<style scoped>
.tier-card {
flex: 0 0 300px;
scroll-snap-align: start;
padding: 24px;
border-radius: 12px;
border: 1px solid var(--vp-c-divider);
background-color: var(--vp-c-bg);
display: flex;
flex-direction: column;
gap: 16px;
transition: border-color 0.25s;
}
.tier-card:last-child {
scroll-snap-align: end;
}
.tier-card:hover,
.tier-card:focus-within {
border-color: var(--vp-c-brand-3);
}
.header {
display: flex;
flex-direction: column;
gap: 4px;
}
.name {
margin: 0;
font-size: 20px;
line-height: 28px;
font-weight: 600;
color: var(--vp-c-text-1);
}
.price {
display: flex;
align-items: baseline;
gap: 4px;
}
.amount {
font-size: 32px;
line-height: 40px;
font-weight: 700;
letter-spacing: -0.02em;
color: var(--vp-c-text-1);
}
.period,
.yearly {
font-size: 14px;
color: var(--vp-c-text-2);
}
.yearly {
font-size: 13px;
}
.perks {
flex-grow: 1;
margin: 0;
padding: 0;
list-style: none;
display: flex;
flex-direction: column;
gap: 10px;
font-size: 14px;
line-height: 22px;
color: var(--vp-c-text-1);
}
.inherited {
color: var(--vp-c-text-2);
font-weight: 500;
}
.perk {
display: flex;
gap: 8px;
}
.perk-icon {
flex-shrink: 0;
margin-top: 2px;
color: var(--sponsor-accent);
}
.actions {
display: flex;
flex-direction: column;
gap: 8px;
}
.primary-action {
display: block;
}
.secondary-action {
display: flex;
align-items: center;
justify-content: center;
min-height: 44px;
font-size: 14px;
font-weight: 600;
color: var(--sponsor-accent);
text-decoration: none;
}
.secondary-action:hover {
text-decoration: underline;
}
</style>
@@ -0,0 +1,273 @@
<script setup lang="ts">
import { ref } from 'vue';
import { useScroll } from '@vueuse/core';
import VPButton from 'vitepress/dist/client/theme-default/components/VPButton.vue';
import Icon from '@lucide/vue/src/Icon';
import { chevronLeft, chevronRight } from '../../../data/iconNodes';
import SponsorSection from './SponsorSection.vue';
import SponsorSectionHeader from './SponsorSectionHeader.vue';
import SponsorTierCard from './SponsorTierCard.vue';
import { PARTNER_EMAIL, TIERS } from './tiers';
// Card width plus the gap between cards.
const SCROLL_STEP = 316;
const track = ref<HTMLElement | null>(null);
const { arrivedState } = useScroll(track);
function scrollTrack(direction: 1 | -1) {
track.value?.scrollBy({ left: direction * SCROLL_STEP, behavior: 'smooth' });
}
</script>
<template>
<SponsorSection
id="tiers"
class="tiers"
>
<div class="tiers-header">
<SponsorSectionHeader
title="Sponsor tiers"
description="Two tiers for individuals, three for companies. Each step adds one clear placement, and perks stack as you go up. Same tiers on Open Collective (EUR) and GitHub Sponsors (USD)."
class="tiers-title"
/>
<div class="track-controls">
<button
type="button"
class="track-button"
aria-label="Previous tiers"
:disabled="arrivedState.left"
@click="scrollTrack(-1)"
>
<Icon
:iconNode="chevronLeft"
name="chevron-left"
:size="20"
aria-hidden="true"
/>
</button>
<button
type="button"
class="track-button"
aria-label="Next tiers"
:disabled="arrivedState.right"
@click="scrollTrack(1)"
>
<Icon
:iconNode="chevronRight"
name="chevron-right"
:size="20"
aria-hidden="true"
/>
</button>
</div>
</div>
<div class="track-wrapper">
<div
ref="track"
class="track"
role="region"
aria-label="Sponsor tiers"
tabindex="0"
>
<SponsorTierCard
v-for="tier in TIERS"
:key="tier.id"
:tier="tier"
/>
</div>
<div
class="fade fade-left"
:class="{ visible: !arrivedState.left }"
aria-hidden="true"
/>
<div
class="fade fade-right"
:class="{ visible: !arrivedState.right }"
aria-hidden="true"
/>
</div>
<div class="partner">
<div class="partner-text">
<h3 class="partner-title">Partner? Let's talk.</h3>
<p class="partner-description">
One partner at a time, custom amount. An exclusive "Supported by" slot, your logo in
release posts, an annual roadmap call and priority review of your icon PRs.
</p>
</div>
<VPButton
:href="`mailto:${PARTNER_EMAIL}`"
text="Contact us"
theme="alt"
target="_self"
/>
</div>
<p class="disclaimer">
Sponsors never buy icon acceptance or design influence. Every icon meets the same guidelines
and community review. Paying by invoice through GitHub Sponsors avoids part of GitHub's
organization fee.
</p>
</SponsorSection>
</template>
<style scoped>
.tiers {
padding-top: 96px;
padding-bottom: 48px;
/* The track bleeds to the right edge of the viewport. */
overflow-x: clip;
}
.tiers-header {
display: flex;
flex-wrap: wrap;
gap: 16px 24px;
align-items: flex-end;
justify-content: space-between;
}
.tiers-title {
flex: 999 1 480px;
min-width: 0;
}
.track-controls {
display: flex;
gap: 8px;
}
.track-button {
width: 44px;
height: 44px;
border-radius: 999px;
border: 1px solid var(--vp-c-border);
background-color: var(--vp-c-bg);
color: var(--vp-c-text-1);
display: flex;
align-items: center;
justify-content: center;
transition:
background-color 0.25s,
opacity 0.25s;
}
.track-button:not(:disabled):hover {
background-color: var(--vp-c-bg-soft);
}
.track-button:disabled {
opacity: 0.4;
cursor: default;
}
.track-wrapper {
position: relative;
margin-right: min(-24px, calc((1152px - 100vw) / 2));
}
.track {
display: flex;
gap: 16px;
align-items: stretch;
overflow-x: auto;
scroll-snap-type: x mandatory;
scroll-behavior: smooth;
padding-bottom: 12px;
padding-right: 24px;
scroll-padding-right: 24px;
scrollbar-width: thin;
scroll-snap-align: center;
scroll-padding-left: 24px;
scroll-padding-right: 24px;
}
.track:focus-visible {
outline: 2px solid var(--vp-c-brand-1);
outline-offset: 4px;
border-radius: 12px;
}
.fade {
position: absolute;
top: 0;
bottom: 12px;
pointer-events: none;
opacity: 0;
transition: opacity 0.2s;
}
.fade.visible {
opacity: 1;
}
.fade-left {
left: 0;
width: 48px;
background: linear-gradient(to left, transparent, var(--vp-c-bg));
}
.fade-right {
right: 0;
width: 48px;
background: linear-gradient(to right, transparent, var(--vp-c-bg) 85%);
}
@media (min-width: 640px) {
.fade-left {
width: 96px;
}
.fade-right {
width: 160px;
}
.track {
scroll-snap-align: start;
}
}
.partner {
padding: 24px 28px;
border-radius: 16px;
background-color: var(--vp-c-bg-soft);
border: 1px solid var(--vp-c-divider);
display: flex;
flex-wrap: wrap;
gap: 24px;
align-items: center;
justify-content: space-between;
}
.partner-text {
flex: 999 1 480px;
min-width: 0;
display: flex;
flex-direction: column;
gap: 8px;
}
.partner-title {
margin: 0;
font-size: 20px;
line-height: 28px;
font-weight: 600;
color: var(--vp-c-text-1);
}
.partner-description,
.disclaimer {
margin: 0;
font-size: 14px;
line-height: 22px;
color: var(--vp-c-text-2);
}
.disclaimer {
margin-top: -8px;
font-size: 13px;
line-height: 20px;
}
</style>
@@ -0,0 +1,42 @@
<script setup lang="ts">
import SponsorSection from './SponsorSection.vue';
import SponsorSectionHeader from './SponsorSectionHeader.vue';
import SponsorLogoGrid from './SponsorLogoGrid.vue';
import SponsorAvatars from './SponsorAvatars.vue';
</script>
<template>
<SponsorSection
id="sponsors"
class="wall"
>
<SponsorSectionHeader
title="Our sponsors"
description="Thank you to everyone who keeps Lucide going."
class="wall-header"
/>
<SponsorLogoGrid
tier="platinum"
:placeholders="1"
/>
<SponsorLogoGrid
tier="gold"
:placeholders="2"
/>
<SponsorLogoGrid tier="bronze" />
<SponsorAvatars />
</SponsorSection>
</template>
<style scoped>
.wall {
padding-top: 48px;
padding-bottom: 96px;
}
.wall-header {
max-width: none;
padding-top: 24px;
border-top: 1px solid var(--vp-c-divider);
}
</style>
@@ -0,0 +1,26 @@
import sponsorsData from '../../../data/sponsorsData.json';
import type { TierId } from './tiers';
export interface Sponsor {
slug: string;
name: string;
website: string;
image: string;
imageDark?: string;
avatar: string;
monthlyAmount: number;
tier: TierId | null;
}
export const sponsors = sponsorsData.sponsors as Sponsor[];
/** Everyone who ever contributed on Open Collective, `null` when the build couldn't fetch it. */
export const allTimeSponsorCount: number | null = sponsorsData.allTimeCount;
export const getSponsorsByTier = (tierId: TierId) => sponsors.filter(({ tier }) => tier === tierId);
const LOGO_TIERS: TierId[] = ['bronze', 'gold', 'platinum'];
/** Everyone below the first logo tier, shown as avatars. */
export const getSupporters = () =>
sponsors.filter(({ tier }) => !tier || !LOGO_TIERS.includes(tier));
@@ -0,0 +1,170 @@
export const OPEN_COLLECTIVE_URL = 'https://opencollective.com/lucide-icons';
export const GITHUB_SPONSORS_URL = 'https://github.com/sponsors/lucide-icons';
export const PARTNER_EMAIL = 'info@lucide.dev';
export type TierId = 'supporter' | 'backer' | 'bronze' | 'gold' | 'platinum';
export interface Tier {
id: TierId;
name: string;
/** Monthly amount in euros. */
monthly: number;
/** Yearly amount in euros, for tiers that can be paid yearly. */
yearly?: number;
audience: string;
/** One-sentence summary of the perks, used in the amount picker. */
summary: string;
/** Perks this tier adds on top of the previous one. */
perks: string[];
featured?: boolean;
/**
* Tier slug on Open Collective. Open the tier on opencollective.com/lucide-icons and copy
* it from the "Contribute" link, e.g. `basic-73095` from
* https://opencollective.com/lucide-icons/contribute/basic-73095/checkout
*/
openCollectiveTier: string;
/**
* Tier id on GitHub Sponsors. Open the tier on github.com/sponsors/lucide-icons and copy
* the `tier_id` from its link, e.g. `671689` from
* https://github.com/sponsors/lucide-icons/sponsorships?tier_id=671689
*/
githubSponsorsTierId: number;
}
export const TIERS: Tier[] = [
{
id: 'supporter',
name: 'Supporter',
monthly: 5,
audience: 'For individuals',
summary:
'Sponsor badge on GitHub, a Discord sponsor role and your avatar on lucide.dev/sponsor.',
perks: [
'Sponsor badge on GitHub',
'Discord sponsor role',
'Small avatar on lucide.dev/sponsor',
],
openCollectiveTier: 'basic-73095',
githubSponsorsTierId: 671689,
},
{
id: 'backer',
name: 'Backer',
monthly: 20,
audience: 'For individuals and freelancers',
summary: 'Everything in Supporter, plus a small avatar or logo in the main README.',
perks: ['Small avatar or logo in the main README on GitHub'],
openCollectiveTier: 'awesome-backer-73677',
githubSponsorsTierId: 671692,
},
{
id: 'bronze',
name: 'Bronze',
monthly: 100,
audience: 'For small companies and startups',
summary: 'Small logo on lucide.dev/sponsor and in all npm READMEs, plus a sticker sheet.',
perks: [
'Small logo on lucide.dev/sponsor',
'Small logo in all npm package READMEs',
'Free Lucide sticker sheet',
],
openCollectiveTier: 'donation-55643',
githubSponsorsTierId: 675253,
},
{
id: 'gold',
name: 'Gold',
monthly: 500,
yearly: 5000,
audience: 'For companies shipping Lucide',
summary: 'Medium logo on the lucide.dev homepage and docs sidebar, plus a welcome t-shirt.',
perks: [
'Medium logo in the main README on GitHub',
'Medium logo in all npm package READMEs',
'Medium logo in the lucide.dev homepage sponsor strip and docs sidebar',
'Medium logo on lucide.dev/sponsor',
'One-time welcome t-shirt',
],
featured: true,
openCollectiveTier: 'champions-circle-73678',
githubSponsorsTierId: 675254,
},
{
id: 'platinum',
name: 'Platinum',
monthly: 1000,
yearly: 10000,
audience: 'For large companies and dev tools',
summary:
'Top homepage placement, logo on icon search, a private maintainer channel and a $100 merch voucher.',
perks: [
'Top placement on the homepage',
'Large logo at the top of the main README on GitHub',
'Large logo at the top of all npm package READMEs',
'Large logo in the lucide.dev homepage sponsor strip and docs sidebar',
'Logo on the icon search page',
'Dedicated welcome post on X and Bluesky',
'Private channel with maintainers',
'$100 merch shop voucher',
],
openCollectiveTier: 'platinum-107266',
githubSponsorsTierId: 675255,
},
];
export const getTier = (id: TierId) => TIERS.find((tier) => tier.id === id)!;
/** The tier before this one, whose perks it inherits. */
export const getPreviousTier = (id: TierId) => TIERS[TIERS.findIndex((tier) => tier.id === id) - 1];
/** The highest tier a monthly amount qualifies for, or `null` below the lowest tier. */
export function getTierForAmount(monthly: number) {
return [...TIERS].reverse().find((tier) => monthly >= tier.monthly) ?? null;
}
/**
* The highest tier a yearly total qualifies for, or `null` below the lowest tier. Tiers with a
* yearly price (two months free) count that price, so a yearly Gold sponsor isn't listed as Bronze.
*/
export function getTierForYearlyAmount(yearly: number) {
return [...TIERS].reverse().find((tier) => yearly >= (tier.yearly ?? tier.monthly * 12)) ?? null;
}
export type Frequency = 'monthly' | 'once';
const getOpenCollectiveParams = (amount: number, frequency: Frequency) =>
new URLSearchParams({
interval: frequency === 'monthly' ? 'month' : 'oneTime',
amount: String(amount),
contributeAs: 'me',
});
/** Checkout links for a tier, or the general sponsor pages without a tier. */
export function getTierLinks(tier?: Tier) {
if (!tier) {
return { openCollective: OPEN_COLLECTIVE_URL, githubSponsors: GITHUB_SPONSORS_URL };
}
const openCollectiveParams = getOpenCollectiveParams(tier.monthly, 'monthly');
return {
openCollective: `${OPEN_COLLECTIVE_URL}/contribute/${tier.openCollectiveTier}/checkout?${openCollectiveParams}`,
githubSponsors: `${GITHUB_SPONSORS_URL}/sponsorships?tier_id=${tier.githubSponsorsTierId}`,
};
}
/** Checkout links prefilled with a custom amount and frequency. */
export function getAmountLinks(amount: number, frequency: Frequency) {
const openCollectiveParams = getOpenCollectiveParams(amount, frequency);
const githubSponsorsParams = new URLSearchParams({
frequency: frequency === 'monthly' ? 'recurring' : 'one-time',
amount: String(amount),
});
return {
openCollective: `${OPEN_COLLECTIVE_URL}/donate?${openCollectiveParams}`,
githubSponsors: `${GITHUB_SPONSORS_URL}/sponsorships?${githubSponsorsParams}`,
};
}
export const formatEuro = (amount: number) => `€${amount.toLocaleString('en-US')}`;
+2
View File
@@ -11,6 +11,7 @@ import { ICON_STYLE_CONTEXT, iconStyleContext } from './composables/useIconStyle
import { CATEGORY_VIEW_CONTEXT, categoryViewContext } from './composables/useCategoryView';
import { EXTERNAL_LIBS_CONTEXT, externalLibContext } from './composables/useExternalLibs';
import SideBarNavBefore from './layouts/SideBarNavBefore.vue';
import NavBarSponsorButton from './layouts/NavBarSponsorButton.vue';
import SnackPlayer from './components/editors/SnackPlayer.vue';
import { setupTracking } from './utils/openpanel';
import trackUnderlineDirection from './utils/underlineDirection';
@@ -24,6 +25,7 @@ const theme: Partial<Theme> = {
'sidebar-nav-after': () => h(IconsSidebarNavAfter),
'home-hero-image': () => h(HomeHeroIconsCard),
'home-hero-actions-after': () => h(HomeHeroAfter),
'nav-bar-content-after': () => h(NavBarSponsorButton),
// Keep this here for now, we might want to add more things to the top bar in the future
// 'layout-top': () => h(LayoutTop),
});
@@ -0,0 +1,95 @@
<script setup lang="ts">
import { computed } from 'vue';
import { useData } from 'vitepress';
import Icon from '@lucide/vue/src/Icon';
import { heart } from '../../data/iconNodes';
const { page } = useData();
const isActive = computed(() => page.value.relativePath === 'sponsor.md');
</script>
<template>
<a
href="/sponsor"
class="sponsor-button"
:class="{ active: isActive }"
:aria-current="isActive ? 'page' : undefined"
>
<Icon
:iconNode="heart"
name="heart"
:size="16"
class="heart"
aria-hidden="true"
/>
<span class="label">Sponsor</span>
</a>
</template>
<style scoped>
.sponsor-button {
display: inline-flex;
align-items: center;
gap: 6px;
height: 32px;
padding: 0 12px;
border-radius: 16px;
border: 1px solid var(--vp-c-divider);
background-color: var(--vp-c-bg-soft);
color: var(--vp-c-text-1);
font-size: 14px;
font-weight: 500;
white-space: nowrap;
text-decoration: none;
transition:
border-color 0.25s,
color 0.25s;
}
.heart {
color: var(--vp-c-brand-3);
transition:
fill 0.25s,
transform 0.25s;
}
.sponsor-button:hover,
.sponsor-button.active {
border-color: var(--vp-c-brand-3);
}
.sponsor-button:hover .heart,
.sponsor-button.active .heart {
fill: currentColor;
}
.sponsor-button:hover .heart {
transform: scale(1.1);
}
@media (min-width: 768px) {
.sponsor-button {
margin-left: 16px;
}
}
/* The nav menu leaves no room for the label between tablet and desktop widths. */
@media (min-width: 768px) and (max-width: 959px) {
.sponsor-button {
justify-content: center;
width: 32px;
padding: 0;
margin-left: 8px;
}
.label {
position: absolute;
width: 1px;
height: 1px;
overflow: hidden;
clip-path: inset(50%);
white-space: nowrap;
}
}
</style>
+2 -1
View File
@@ -68,7 +68,8 @@
*::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
transition-duration: 0s !important;
transition-delay: 0s !important;
scroll-behavior: auto !important;
}
+10 -1
View File
@@ -1,5 +1,5 @@
import { type PageData } from 'vitepress';
import getStructuredData from './getStructuredData';
import getStructuredData, { getFaqStructuredData } from './getStructuredData';
import { createGeneralOGImage, createIconOGImage } from './createOGImage';
export async function transformPageData(pageData: PageData) {
@@ -53,6 +53,15 @@ export async function transformPageData(pageData: PageData) {
]);
}
// Pages can list their FAQ in the `faq` frontmatter, rendered by the `Faq` component.
if (Array.isArray(pageData.frontmatter.faq)) {
pageData.frontmatter.head.push([
'script',
{ type: 'application/ld+json' },
JSON.stringify(getFaqStructuredData(pageData.frontmatter.faq)),
]);
}
if (pageData.relativePath.startsWith('guide/')) {
const ogPath = await createGeneralOGImage(pageData);
+1
View File
@@ -17,6 +17,7 @@
"prebuild:iconDetails": "node ./scripts/writeIconDetails.mts",
"prebuild:iconPopularity": "node --env-file-if-exists=.env ./scripts/writeiconPopularity.mts && node ./scripts/writeiconPopularityIndex.mts",
"prebuild:brandStopwords": "node ./scripts/writeBrandStopwords.mts",
"prebuild:sponsors": "node --env-file-if-exists=.env ./scripts/writeSponsorsData.mts",
"prebuild:writeLabIconNodes": "node ./scripts/writeLabIconNodes.mts",
"prebuild:writeLabIconMetaIndex": "node ./scripts/writeLabIconMetaIndex.mts",
"postbuild:vercelJson": "node ./scripts/writeVercelOutput.mts",
+85
View File
@@ -0,0 +1,85 @@
{
"$schema": "https://fundingjson.org/schema/v1.0.0.json",
"version": "v1.0.0",
"entity": {
"type": "organisation",
"role": "steward",
"name": "Lucide Icons",
"email": "info@lucide.dev",
"description": "Lucide Icons is the team that maintains Lucide, a community-driven, open-source icon library. The project is led by Eric Fennis together with co-maintainer Karsa Mistmere.",
"webpageUrl": {
"url": "https://lucide.dev"
}
},
"projects": [
{
"guid": "lucide",
"name": "Lucide",
"description": "Beautiful and consistent icon toolkit made by the community. Lucide provides a large set of open-source SVG icons plus official packages for React, Vue, Svelte, Solid, Preact, Angular, React Native and vanilla JavaScript, along with a Figma plugin. It is free for personal and commercial use under the ISC license.",
"webpageUrl": {
"url": "https://lucide.dev"
},
"repositoryUrl": {
"url": "https://github.com/lucide-icons/lucide",
"wellKnown": "https://github.com/lucide-icons/lucide/blob/main/.well-known/funding-manifest-urls"
},
"licenses": ["spdx:ISC"],
"tags": ["icons", "svg", "design", "user-interface", "react", "vue", "svelte", "figma"]
}
],
"funding": {
"channels": [
{
"guid": "opencollective",
"type": "payment-provider",
"address": "https://opencollective.com/lucide-icons",
"description": "Recurring or one-time contributions via Open Collective."
},
{
"guid": "github-sponsors-lucide",
"type": "payment-provider",
"address": "https://github.com/sponsors/lucide-icons",
"description": "Sponsor the Lucide project via GitHub Sponsors."
},
{
"guid": "github-sponsors-ericfennis",
"type": "payment-provider",
"address": "https://github.com/sponsors/ericfennis",
"description": "Sponsor the lead maintainer via GitHub Sponsors."
}
],
"plans": [
{
"guid": "maintainer-time",
"status": "active",
"name": "Maintainer time",
"description": "Funds 44 hours of maintenance per week: 32 hours for Eric Fennis and 12 hours for Karsa Mistmere at EUR 40 per hour. Covers reviewing icon contributions, maintaining the framework packages, releases, documentation and community support.",
"amount": 91520,
"currency": "EUR",
"frequency": "yearly",
"channels": ["opencollective", "github-sponsors-lucide", "github-sponsors-ericfennis"]
},
{
"guid": "infrastructure-tooling",
"status": "active",
"name": "Infrastructure and tooling",
"description": "Covers hosting on DigitalOcean (EUR 1,200/year), the domain (EUR 10/year), design and project tools Figma, Notion and Linear (EUR 900/year) and AI coding assistance (EUR 240/year).",
"amount": 2350,
"currency": "EUR",
"frequency": "yearly",
"channels": ["opencollective", "github-sponsors-lucide"]
},
{
"guid": "custom-contribution",
"status": "active",
"name": "Custom contribution",
"description": "Contribute any amount to support Lucide.",
"amount": 0,
"currency": "EUR",
"frequency": "one-time",
"channels": ["opencollective", "github-sponsors-lucide", "github-sponsors-ericfennis"]
}
],
"history": []
}
}
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="164" height="23" fill="none" viewBox="0 0 164 23"><g clip-path="url(#a)"><g fill="#f34e3f" clip-path="url(#b)"><path d="m8.47 6 2.55.69L9.3.19 6.35 1l1.04 3.93c.14.53.56.95 1.08 1.09M4.16 19.22l5.56-5.55 2.03 7.56 2.94-.79-2.93-10.98L.78 6.54 0 9.49l7.55 2.02-5.53 5.54zM14.53 10.2l.68 2.56c.14.53.56.94 1.08 1.08l3.96 1.05.78-2.95zM16.87 2.2l-2.53 2.54c-.28.27-.44.65-.45 1.04l-.04 1.6 1.48.06c-.02 0 .02 0 0 0 .4 0 .79-.16 1.07-.45l2.62-2.61z"/></g></g><path fill="#f8f8f8" d="M35.86 10.13q-1.35-.57-3.37-.94-1.37-.3-2.07-.51T29.4 8.1a1.3 1.3 0 0 1-.33-.94q0-.7.39-1.1.38-.39 1.05-.54t1.67-.16q1.2 0 2.4.3 1.18.28 2.56.9l.5-2.75q-1.26-.6-2.62-.89-1.37-.29-2.84-.29-1.76 0-3.2.55-1.45.54-2.32 1.57a3.8 3.8 0 0 0-.86 2.52q0 1.3.66 2.2.67.89 1.96 1.43t3.3.9q1.41.29 2.13.52.7.23 1.11.64.4.41.4 1.2 0 .7-.45 1.11t-1.2.56-1.8.14a15 15 0 0 1-6.13-1.4l-.3 2.73q1.2.69 2.89 1.05 1.67.35 3.59.35c1.27 0 2.33-.18 3.34-.54q1.5-.55 2.4-1.6t.91-2.56q0-1.4-.7-2.36a5 5 0 0 0-2.05-1.52M49.71 6.82a7 7 0 0 0-3.43-.8c-1.26 0-2.44.26-3.44.8q-1.52.81-2.37 2.27a6.3 6.3 0 0 0-.86 3.27q0 1.8.85 3.24a6 6 0 0 0 2.37 2.28 7 7 0 0 0 3.45.83c1.3 0 2.4-.28 3.43-.83a6.1 6.1 0 0 0 3.25-5.54q0-1.81-.86-3.26a6 6 0 0 0-2.39-2.25m-.2 7.47q-.47.84-1.31 1.32t-1.9.48c-.69 0-1.37-.16-1.93-.48q-.84-.48-1.33-1.33a4 4 0 0 1-.5-1.96q0-1.12.5-1.93a3.5 3.5 0 0 1 1.33-1.3 4 4 0 0 1 1.91-.46q1.07 0 1.92.47t1.3 1.3.48 1.96-.47 1.93M63.34 13.5q-.07.23-.19.44a4 4 0 0 1-1.32 1.5q-.85.56-1.89.56-1.37 0-2.06-.74-.67-.74-.67-2.12V6.26h-2.96v7.32q0 1.56.62 2.7.63 1.17 1.74 1.78 1.12.63 2.55.63 2.18 0 3.45-1.11.42-.37.74-.8v1.66h2.95V6.26h-2.95zM74.49 6.04q-2.1 0-3.14 1.37a5 5 0 0 0-.44.73V6.26h-2.96v12.18h2.96v-5.01q0-2.04.88-3.28a2.8 2.8 0 0 1 2.39-1.23h.73q.22.02.4.02h.36L76 6.2a8 8 0 0 0-1.51-.15M80.82 9.07a4 4 0 0 1 1.94-.46 5 5 0 0 1 3.25 1.13l1.22-2.2a8 8 0 0 0-2.22-1.16 8 8 0 0 0-2.5-.37q-1.8 0-3.28.8a6 6 0 0 0-2.36 2.23 6.4 6.4 0 0 0-.87 3.32q0 1.86.85 3.3.84 1.43 2.34 2.22a7 7 0 0 0 3.3.78 8 8 0 0 0 2.47-.34 9 9 0 0 0 2.27-1.14l-1.17-2.15a7 7 0 0 1-1.62.8 5 5 0 0 1-1.66.28q-1.08 0-1.95-.44a3.3 3.3 0 0 1-1.37-1.3 4 4 0 0 1-.5-2q0-1.18.5-2.02.5-.83 1.36-1.28M96.8 6.74q-1.36-.7-2.98-.7a7 7 0 0 0-3.42.8 5.7 5.7 0 0 0-2.28 2.26 6.6 6.6 0 0 0-.8 3.26c0 1.21.28 2.26.85 3.23a6 6 0 0 0 2.38 2.27q1.53.82 3.45.82 1.33 0 2.38-.27 1.05-.29 2-.92l-.76-2.42q-.7.51-1.65.78a6 6 0 0 1-1.82.28q-1.2 0-2.07-.43a3 3 0 0 1-1.33-1.28q-.26-.45-.37-1.04h8.95a5.3 5.3 0 0 0-.41-4.73 5.3 5.3 0 0 0-2.12-1.92m-6.1 3.6q.4-.85 1.2-1.3a4 4 0 0 1 1.87-.45q.98 0 1.7.39.7.39 1.04 1.18.19.48.23 1.07h-6.35q.1-.48.3-.89M110.92 7.92a4.6 4.6 0 0 0-1.84-1.43 7 7 0 0 0-2.63-.48q-1.65 0-2.94.78a5.5 5.5 0 0 0-2.05 2.15q-.75 1.38-.75 3.09c0 1.14.25 2.1.75 2.98q.75 1.32 2.07 2.09t2.97.77q1.47 0 2.57-.47a4.3 4.3 0 0 0 1.81-1.42v.58q0 1.64-1.06 2.6a4.2 4.2 0 0 1-2.92.95 8 8 0 0 1-4.45-1.38l-1.16 2.09q1.2.81 2.7 1.25t3.24.43q3.12 0 4.87-1.66 1.77-1.67 1.76-4.64V6.26h-2.93zm-.5 5.98q-.47.81-1.3 1.25t-1.91.43q-1 0-1.81-.46a3.3 3.3 0 0 1-1.28-1.27 3.84 3.84 0 0 1 0-3.7q.46-.82 1.28-1.3a4.05 4.05 0 0 1 3.73-.03q.8.44 1.3 1.25.47.83.47 1.91 0 1.1-.48 1.92M118.95 7.41a5 5 0 0 0-.44.73V6.26h-2.96v12.18h2.96v-5.01q0-2.04.88-3.28a2.8 2.8 0 0 1 2.39-1.23h.73l.4.03h.36l.33-2.76a8 8 0 0 0-1.51-.15q-2.1 0-3.14 1.37M133.69 7.36Q132.26 6 129.34 6q-2.22 0-4.47.74l.36 2.6a9 9 0 0 1 1.8-.55q.98-.2 2-.19 1.56 0 2.35.6.78.6.79 1.77v.1a57 57 0 0 0-3.76-.19q-2.41 0-3.56 1.1a3.7 3.7 0 0 0-1.16 2.79q0 1.12.51 2.02.52.89 1.48 1.38.98.5 2.24.5 1.25 0 2.22-.36a4.4 4.4 0 0 0 2.03-1.47v1.59h2.96v-7.26q0-2.48-1.44-3.83m-2.95 8.38q-.73.42-1.84.42a3.5 3.5 0 0 1-1.8-.4 1.3 1.3 0 0 1-.63-1.14q0-.8.65-1.22.64-.42 2.18-.42.84 0 1.53.03.68.04 1.34.12a3.5 3.5 0 0 1-.35 1.5q-.34.7-1.08 1.11M146.9 6.84a5.7 5.7 0 0 0-2.99-.83q-1.26 0-2.36.44a5 5 0 0 0-1.89 1.25V6.26h-2.96v16h2.96v-5.22q.51.56 1.2.91.66.36 1.42.56t1.61.2q1.67 0 3.03-.79a5.7 5.7 0 0 0 2.14-2.23q.8-1.44.8-3.3c0-1.25-.27-2.31-.8-3.28a6 6 0 0 0-2.16-2.28m-.44 7.44q-.46.84-1.27 1.3-.8.46-1.84.46a4 4 0 0 1-1.93-.44q-.84-.44-1.3-1.29a4 4 0 0 1-.46-1.95q0-1.12.47-1.95t1.3-1.3 1.92-.46q1.03 0 1.84.47t1.27 1.32q.45.86.45 1.94 0 1.07-.45 1.9M162.78 8.41q-.63-1.15-1.74-1.77a5 5 0 0 0-2.56-.63q-2.17 0-3.45 1.11-.41.37-.73.8V2.06h-2.96v16.38h2.96V11.2q.08-.23.19-.44a4 4 0 0 1 1.32-1.5q.84-.57 1.9-.56 1.37 0 2.05.74t.68 2.12v6.88h2.96v-7.32a5.6 5.6 0 0 0-.63-2.7"/><defs><clipPath id="a"><path fill="#fff" d="M0 .2h21.03v21.03H0z"/></clipPath><clipPath id="b"><path fill="#fff" d="M0 .2h21.03v21.03H0z"/></clipPath></defs></svg>

After

Width:  |  Height:  |  Size: 4.5 KiB

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="175" height="31" fill="none" viewBox="0 0 175 31"><path fill="#fff" fill-rule="evenodd" d="M15.48 24.45a8.96 8.96 0 0 0 7.39-14.05l5.82-5.82c.5-.5.21-1.34-.47-1.47a39 39 0 0 1-6.55-1.83l-.13-.05-.77-.3a15.5 15.5 0 0 0-16.23 3.6A15.4 15.4 0 0 0 .76 20.28c.26.81 1.22 1.12 1.96.7.63-.37.88-1.14.67-1.83a12.63 12.63 0 0 1 19.8-13.68L20.56 8.1A8.96 8.96 0 0 0 8.1 20.57l-5.82 5.82c-.49.5-.21 1.34.47 1.47a39 39 0 0 1 6.55 1.83l.13.05.78.3a15.5 15.5 0 0 0 16.17-3.54l.06-.07a15.4 15.4 0 0 0 3.78-15.74c-.27-.81-1.22-1.12-1.97-.7a1.6 1.6 0 0 0-.67 1.84 12.63 12.63 0 0 1-19.8 13.66l2.63-2.62c1.44 1 3.2 1.58 5.08 1.58m5.95-8.97a6.1 6.1 0 0 1-9.02 5.38l8.29-8.29q.72 1.32.73 2.91m-12.22 0a6.11 6.11 0 0 1 9.23-5.25l-8.38 8.37a6 6 0 0 1-.85-3.12" clip-rule="evenodd"/><path fill="#fff" d="M80.9 23.48H79v-15h1.9v5.48l-.25 1.62h.4c.44-1.62 1.54-2.4 3.56-2.4 2.58 0 3.76 1.32 3.76 4v6.3h-2.1l.4-5.9c.12-1.98-.82-2.72-2.62-2.72-2.12 0-3.14 1.28-3.14 3.38zM42.5 11.12V9.48h10.12v4.14l-10.18 7.8v.4h10.54v1.66H42.14v-4.16l10.18-7.8v-.4z"/><path fill="#fff" fill-rule="evenodd" d="M62.29 19.4h1.88c-.3 2.74-1.86 4.38-4.76 4.38-3.34 0-5.16-2.04-5.16-5.3s1.76-5.3 4.96-5.3c3 0 4.52 1.8 4.52 4.98h-7.6c0 2.36.6 4.02 3.28 4.02 1.9 0 2.7-.96 2.88-2.78m-5.98-2.54h5.46c-.02-1.24-.84-2.1-2.52-2.1s-2.6.7-2.94 2.1M66.1 28.08H68V23l-.2-1.82h.4c.5 1.62 1.61 2.6 3.8 2.6 3.05 0 4.73-2.04 4.73-5.3s-1.68-5.3-4.74-5.3c-2.1 0-3.3.98-3.8 2.6h-.4l.2-2.3h-1.9zm5.51-5.94c-2.22 0-3.52-1.5-3.52-3.68s1.12-3.68 3.52-3.68c2.14 0 3.22 1.32 3.22 3.68s-1.08 3.68-3.22 3.68" clip-rule="evenodd"/><path fill="#fff" d="M91.62 13.48h-1.9l2.92 10h2.08l-.66 2.08c-.14.54-.2.58-.76.56l-3.38-.04v1.9l2.98-.26c1.92-.16 2.82-1.36 3.3-3.08l3.3-11.16h-1.9l-2.8 9.7h-.4zM103.13 23.48h-1.9v-10h1.9l-.2 2.1h.4c.42-1.62 1.32-2.1 3.04-2.1h1.78v1.86l-2.18-.2c-1.88-.16-2.84.98-2.84 3.1zM121.92 22.14c-3 0-4.5-1.86-4.5-5.66s1.42-5.66 4.2-5.66c2.4 0 3.72 1.22 4 4.04h1.96c-.32-3.88-2.34-5.68-5.94-5.68-4.06 0-6.16 2.44-6.16 7.3s2.18 7.3 6.46 7.3c3.78 0 5.92-1.8 6.24-5.7h-1.96c-.28 2.84-1.72 4.06-4.3 4.06M129.47 8.48h1.74q2.66-.02 2.64 2.64v10.74h3.14v1.62h-8.12v-1.62h3.16V10.52c0-.56-.06-.7-.6-.6l-1.96.36z"/><path fill="#fff" fill-rule="evenodd" d="M143.18 13.18c-3.2 0-5.2 2.04-5.2 5.3s2 5.3 5.2 5.3c3.22 0 5.22-2.04 5.22-5.3s-2-5.3-5.22-5.3m0 9c-2.18 0-3.32-1.32-3.32-3.7s1.14-3.7 3.32-3.7c2.2 0 3.34 1.32 3.34 3.7s-1.14 3.7-3.34 3.7" clip-rule="evenodd"/><path fill="#fff" d="M150.33 13.48h2.1l-.4 5.9c-.12 1.94.82 2.7 2.62 2.7 2.08 0 3.12-1.28 3.14-3.26v-5.34h1.9v7.8c0 .56.06.7.6.6l1.14-.2v1.8h-1.04c-1.42 0-2.36-.88-2.36-2.16l-.4.02c-.44 1.62-1.68 2.44-3.54 2.44-2.58 0-3.76-1.32-3.76-4z"/><path fill="#fff" fill-rule="evenodd" d="M173.07 8.48h-1.9v5.48l.2 1.82h-.4c-.48-1.62-1.6-2.6-3.8-2.6-3.04 0-4.74 2.04-4.74 5.3s1.7 5.3 4.74 5.3c2.1 0 3.32-.98 3.8-2.6h.4c0 1.32 1.02 2.3 2.4 2.3h1.04v-1.8l-1.14.2c-.56.1-.6-.04-.6-.6zm-5.5 6.34c2.2 0 3.5 1.5 3.5 3.66s-1.1 3.64-3.5 3.64c-2.16 0-3.24-1.3-3.24-3.64s1.08-3.66 3.24-3.66" clip-rule="evenodd"/></svg>

After

Width:  |  Height:  |  Size: 3.0 KiB

+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="164" height="23" fill="none" viewBox="0 0 164 23"><g clip-path="url(#a)"><g fill="#f34e3f" clip-path="url(#b)"><path d="m8.47 6 2.55.69L9.3.19 6.35 1l1.04 3.93c.14.53.56.95 1.08 1.09M4.16 19.22l5.56-5.55 2.03 7.56 2.94-.79-2.93-10.98L.78 6.54 0 9.49l7.55 2.02-5.53 5.54zM14.53 10.2l.68 2.56c.14.53.56.94 1.08 1.08l3.96 1.05.78-2.95zM16.87 2.2l-2.53 2.54c-.28.27-.44.65-.45 1.04l-.04 1.6 1.48.06c-.02 0 .02 0 0 0 .4 0 .79-.16 1.07-.45l2.62-2.61z"/></g></g><path fill="#000" d="M35.86 10.13q-1.35-.57-3.37-.94-1.37-.3-2.07-.51T29.4 8.1a1.3 1.3 0 0 1-.33-.94q0-.7.39-1.1.38-.39 1.05-.54t1.67-.16q1.2 0 2.4.3 1.18.28 2.56.9l.5-2.75q-1.26-.6-2.62-.89-1.37-.29-2.84-.29-1.76 0-3.2.55-1.45.54-2.32 1.57a3.8 3.8 0 0 0-.86 2.52q0 1.3.66 2.2.67.89 1.96 1.43t3.3.9q1.41.29 2.13.52.7.23 1.11.64.4.41.4 1.2 0 .7-.45 1.11t-1.2.56-1.8.14a15 15 0 0 1-6.13-1.4l-.3 2.73q1.2.69 2.89 1.05 1.67.35 3.59.35c1.27 0 2.33-.18 3.34-.54q1.5-.55 2.4-1.6t.91-2.56q0-1.4-.7-2.36a5 5 0 0 0-2.05-1.52M49.71 6.82a7 7 0 0 0-3.43-.8c-1.26 0-2.44.26-3.44.8q-1.52.81-2.37 2.27a6.3 6.3 0 0 0-.86 3.27q0 1.8.85 3.24a6 6 0 0 0 2.37 2.28 7 7 0 0 0 3.45.83c1.3 0 2.4-.28 3.43-.83a6.1 6.1 0 0 0 3.25-5.54q0-1.81-.86-3.26a6 6 0 0 0-2.39-2.25m-.2 7.47q-.47.84-1.31 1.32t-1.9.48c-.69 0-1.37-.16-1.93-.48q-.84-.48-1.33-1.33a4 4 0 0 1-.5-1.96q0-1.12.5-1.93a3.5 3.5 0 0 1 1.33-1.3 4 4 0 0 1 1.91-.46q1.07 0 1.92.47t1.3 1.3.48 1.96-.47 1.93M63.34 13.5q-.07.23-.19.44a4 4 0 0 1-1.32 1.5q-.85.56-1.89.56-1.37 0-2.06-.74-.67-.74-.67-2.12V6.26h-2.96v7.32q0 1.56.62 2.7.63 1.17 1.74 1.78 1.12.63 2.55.63 2.18 0 3.45-1.11.42-.37.74-.8v1.66h2.95V6.26h-2.95zM74.49 6.04q-2.1 0-3.14 1.37a5 5 0 0 0-.44.73V6.26h-2.96v12.18h2.96v-5.01q0-2.04.88-3.28a2.8 2.8 0 0 1 2.39-1.23h.73q.22.02.4.02h.36L76 6.2a8 8 0 0 0-1.51-.15M80.82 9.07a4 4 0 0 1 1.94-.46 5 5 0 0 1 3.25 1.13l1.22-2.2a8 8 0 0 0-2.22-1.16 8 8 0 0 0-2.5-.37q-1.8 0-3.28.8a6 6 0 0 0-2.36 2.23 6.4 6.4 0 0 0-.87 3.32q0 1.86.85 3.3.84 1.43 2.34 2.22a7 7 0 0 0 3.3.78 8 8 0 0 0 2.47-.34 9 9 0 0 0 2.27-1.14l-1.17-2.15a7 7 0 0 1-1.62.8 5 5 0 0 1-1.66.28q-1.08 0-1.95-.44a3.3 3.3 0 0 1-1.37-1.3 4 4 0 0 1-.5-2q0-1.18.5-2.02.5-.83 1.36-1.28M96.8 6.74q-1.36-.7-2.98-.7a7 7 0 0 0-3.42.8 5.7 5.7 0 0 0-2.28 2.26 6.6 6.6 0 0 0-.8 3.26c0 1.21.28 2.26.85 3.23a6 6 0 0 0 2.38 2.27q1.53.82 3.45.82 1.33 0 2.38-.27 1.05-.29 2-.92l-.76-2.42q-.7.51-1.65.78a6 6 0 0 1-1.82.28q-1.2 0-2.07-.43a3 3 0 0 1-1.33-1.28q-.26-.45-.37-1.04h8.95a5.3 5.3 0 0 0-.41-4.73 5.3 5.3 0 0 0-2.12-1.92m-6.1 3.6q.4-.85 1.2-1.3a4 4 0 0 1 1.87-.45q.98 0 1.7.39.7.39 1.04 1.18.19.48.23 1.07h-6.35q.1-.48.3-.89M110.92 7.92a4.6 4.6 0 0 0-1.84-1.43 7 7 0 0 0-2.63-.48q-1.65 0-2.94.78a5.5 5.5 0 0 0-2.05 2.15q-.75 1.38-.75 3.09c0 1.14.25 2.1.75 2.98q.75 1.32 2.07 2.09t2.97.77q1.47 0 2.57-.47a4.3 4.3 0 0 0 1.81-1.42v.58q0 1.64-1.06 2.6a4.2 4.2 0 0 1-2.92.95 8 8 0 0 1-4.45-1.38l-1.16 2.09q1.2.81 2.7 1.25t3.24.43q3.12 0 4.87-1.66 1.77-1.67 1.76-4.64V6.26h-2.93zm-.5 5.98q-.47.81-1.3 1.25t-1.91.43q-1 0-1.81-.46a3.3 3.3 0 0 1-1.28-1.27 3.84 3.84 0 0 1 0-3.7q.46-.82 1.28-1.3a4.05 4.05 0 0 1 3.73-.03q.8.44 1.3 1.25.47.83.47 1.91 0 1.1-.48 1.92M118.95 7.41a5 5 0 0 0-.44.73V6.26h-2.96v12.18h2.96v-5.01q0-2.04.88-3.28a2.8 2.8 0 0 1 2.39-1.23h.73l.4.03h.36l.33-2.76a8 8 0 0 0-1.51-.15q-2.1 0-3.14 1.37M133.69 7.36Q132.26 6 129.34 6q-2.22 0-4.47.74l.36 2.6a9 9 0 0 1 1.8-.55q.98-.2 2-.19 1.56 0 2.35.6.78.6.79 1.77v.1a57 57 0 0 0-3.76-.19q-2.41 0-3.56 1.1a3.7 3.7 0 0 0-1.16 2.79q0 1.12.51 2.02.52.89 1.48 1.38.98.5 2.24.5 1.25 0 2.22-.36a4.4 4.4 0 0 0 2.03-1.47v1.59h2.96v-7.26q0-2.48-1.44-3.83m-2.95 8.38q-.73.42-1.84.42a3.5 3.5 0 0 1-1.8-.4 1.3 1.3 0 0 1-.63-1.14q0-.8.65-1.22.64-.42 2.18-.42.84 0 1.53.03.68.04 1.34.12a3.5 3.5 0 0 1-.35 1.5q-.34.7-1.08 1.11M146.9 6.84a5.7 5.7 0 0 0-2.99-.83q-1.26 0-2.36.44a5 5 0 0 0-1.89 1.25V6.26h-2.96v16h2.96v-5.22q.51.56 1.2.91.66.36 1.42.56t1.61.2q1.67 0 3.03-.79a5.7 5.7 0 0 0 2.14-2.23q.8-1.44.8-3.3c0-1.25-.27-2.31-.8-3.28a6 6 0 0 0-2.16-2.28m-.44 7.44q-.46.84-1.27 1.3-.8.46-1.84.46a4 4 0 0 1-1.93-.44q-.84-.44-1.3-1.29a4 4 0 0 1-.46-1.95q0-1.12.47-1.95t1.3-1.3 1.92-.46q1.03 0 1.84.47t1.27 1.32q.45.86.45 1.94 0 1.07-.45 1.9M162.78 8.41q-.63-1.15-1.74-1.77a5 5 0 0 0-2.56-.63q-2.17 0-3.45 1.11-.41.37-.73.8V2.06h-2.96v16.38h2.96V11.2q.08-.23.19-.44a4 4 0 0 1 1.32-1.5q.84-.57 1.9-.56 1.37 0 2.05.74t.68 2.12v6.88h2.96v-7.32a5.6 5.6 0 0 0-.63-2.7"/><defs><clipPath id="a"><path fill="#000" d="M0 .2h21.03v21.03H0z"/></clipPath><clipPath id="b"><path fill="#000" d="M0 .2h21.03v21.03H0z"/></clipPath></defs></svg>

After

Width:  |  Height:  |  Size: 4.4 KiB

+1 -15
View File
@@ -1,15 +1 @@
<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>
<svg xmlns="http://www.w3.org/2000/svg" width="175" height="31" fill="none" viewBox="0 0 175 31"><path fill="#010101" fill-rule="evenodd" d="M15.48 24.45a8.96 8.96 0 0 0 7.39-14.05l5.82-5.82c.5-.5.21-1.34-.47-1.47a39 39 0 0 1-6.55-1.83l-.13-.05-.77-.3a15.5 15.5 0 0 0-16.23 3.6A15.4 15.4 0 0 0 .76 20.28c.26.81 1.22 1.12 1.96.7.63-.37.88-1.14.67-1.83a12.63 12.63 0 0 1 19.8-13.68L20.56 8.1A8.96 8.96 0 0 0 8.1 20.57l-5.82 5.82c-.49.5-.21 1.34.47 1.47a39 39 0 0 1 6.55 1.83l.13.05.78.3a15.5 15.5 0 0 0 16.17-3.54l.06-.07a15.4 15.4 0 0 0 3.78-15.74c-.27-.81-1.22-1.12-1.97-.7a1.6 1.6 0 0 0-.67 1.84 12.63 12.63 0 0 1-19.8 13.66l2.63-2.62c1.44 1 3.2 1.58 5.08 1.58m5.95-8.97a6.1 6.1 0 0 1-9.02 5.38l8.29-8.29q.72 1.32.73 2.91m-12.22 0a6.11 6.11 0 0 1 9.23-5.25l-8.38 8.37a6 6 0 0 1-.85-3.12" clip-rule="evenodd"/><path fill="#010101" d="M80.9 23.48H79v-15h1.9v5.48l-.25 1.62h.4c.44-1.62 1.54-2.4 3.56-2.4 2.58 0 3.76 1.32 3.76 4v6.3h-2.1l.4-5.9c.12-1.98-.82-2.72-2.62-2.72-2.12 0-3.14 1.28-3.14 3.38zM42.5 11.12V9.48h10.12v4.14l-10.18 7.8v.4h10.54v1.66H42.14v-4.16l10.18-7.8v-.4z"/><path fill="#010101" fill-rule="evenodd" d="M62.29 19.4h1.88c-.3 2.74-1.86 4.38-4.76 4.38-3.34 0-5.16-2.04-5.16-5.3s1.76-5.3 4.96-5.3c3 0 4.52 1.8 4.52 4.98h-7.6c0 2.36.6 4.02 3.28 4.02 1.9 0 2.7-.96 2.88-2.78m-5.98-2.54h5.46c-.02-1.24-.84-2.1-2.52-2.1s-2.6.7-2.94 2.1M66.1 28.08H68V23l-.2-1.82h.4c.5 1.62 1.61 2.6 3.8 2.6 3.05 0 4.73-2.04 4.73-5.3s-1.68-5.3-4.74-5.3c-2.1 0-3.3.98-3.8 2.6h-.4l.2-2.3h-1.9zm5.51-5.94c-2.22 0-3.52-1.5-3.52-3.68s1.12-3.68 3.52-3.68c2.14 0 3.22 1.32 3.22 3.68s-1.08 3.68-3.22 3.68" clip-rule="evenodd"/><path fill="#010101" d="M91.62 13.48h-1.9l2.92 10h2.08l-.66 2.08c-.14.54-.2.58-.76.56l-3.38-.04v1.9l2.98-.26c1.92-.16 2.82-1.36 3.3-3.08l3.3-11.16h-1.9l-2.8 9.7h-.4zM103.13 23.48h-1.9v-10h1.9l-.2 2.1h.4c.42-1.62 1.32-2.1 3.04-2.1h1.78v1.86l-2.18-.2c-1.88-.16-2.84.98-2.84 3.1zM121.92 22.14c-3 0-4.5-1.86-4.5-5.66s1.42-5.66 4.2-5.66c2.4 0 3.72 1.22 4 4.04h1.96c-.32-3.88-2.34-5.68-5.94-5.68-4.06 0-6.16 2.44-6.16 7.3s2.18 7.3 6.46 7.3c3.78 0 5.92-1.8 6.24-5.7h-1.96c-.28 2.84-1.72 4.06-4.3 4.06M129.47 8.48h1.74q2.66-.02 2.64 2.64v10.74h3.14v1.62h-8.12v-1.62h3.16V10.52c0-.56-.06-.7-.6-.6l-1.96.36z"/><path fill="#010101" fill-rule="evenodd" d="M143.18 13.18c-3.2 0-5.2 2.04-5.2 5.3s2 5.3 5.2 5.3c3.22 0 5.22-2.04 5.22-5.3s-2-5.3-5.22-5.3m0 9c-2.18 0-3.32-1.32-3.32-3.7s1.14-3.7 3.32-3.7c2.2 0 3.34 1.32 3.34 3.7s-1.14 3.7-3.34 3.7" clip-rule="evenodd"/><path fill="#010101" d="M150.33 13.48h2.1l-.4 5.9c-.12 1.94.82 2.7 2.62 2.7 2.08 0 3.12-1.28 3.14-3.26v-5.34h1.9v7.8c0 .56.06.7.6.6l1.14-.2v1.8h-1.04c-1.42 0-2.36-.88-2.36-2.16l-.4.02c-.44 1.62-1.68 2.44-3.54 2.44-2.58 0-3.76-1.32-3.76-4z"/><path fill="#010101" fill-rule="evenodd" d="M173.07 8.48h-1.9v5.48l.2 1.82h-.4c-.48-1.62-1.6-2.6-3.8-2.6-3.04 0-4.74 2.04-4.74 5.3s1.7 5.3 4.74 5.3c2.1 0 3.32-.98 3.8-2.6h.4c0 1.32 1.02 2.3 2.4 2.3h1.04v-1.8l-1.14.2c-.56.1-.6-.04-.6-.6zm-5.5 6.34c2.2 0 3.5 1.5 3.5 3.66s-1.1 3.64-3.5 3.64c-2.16 0-3.24-1.3-3.24-3.64s1.08-3.66 3.24-3.66" clip-rule="evenodd"/></svg>

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

+164
View File
@@ -0,0 +1,164 @@
import { existsSync } from 'node:fs';
import { join } from 'node:path';
import { getTierForYearlyAmount } from '../../.vitepress/theme/components/sponsor/tiers.ts';
const COLLECTIVE_SLUG = 'lucide-icons';
const OPEN_COLLECTIVE_API = 'https://api.opencollective.com/graphql/v2';
const sponsorLogosPath = join(import.meta.dirname, '../../public/sponsors');
const GRACE_PERIOD_DAYS = 31;
const DAY_IN_MS = 24 * 60 * 60 * 1000;
export interface Account {
slug: string;
name: string;
website: string | null;
imageUrl: string | null;
description: string | null;
}
interface Order {
status: 'ACTIVE' | 'CANCELLED' | 'ERROR' | 'PAUSED';
amount: { valueInCents: number | null } | null;
frequency: 'MONTHLY' | 'YEARLY' | 'ONETIME' | null;
nextChargeDate: string | null;
fromAccount: Account;
}
interface CollectiveResponse {
data?: {
account: {
stats: { contributorsCount: number | null } | null;
orders: { nodes: Order[] };
} | null;
};
errors?: { message: string }[];
}
const query = /* GraphQL */ `
query Sponsors($slug: String!) {
account(slug: $slug) {
stats {
contributorsCount
}
orders(filter: INCOMING, status: [ACTIVE, CANCELLED, ERROR, PAUSED], limit: 1000) {
nodes {
status
amount {
valueInCents
}
frequency
nextChargeDate
fromAccount {
slug
name
website
imageUrl
description
}
}
}
}
}
`;
export async function fetchCollective() {
const headers: Record<string, string> = { 'Content-Type': 'application/json' };
if (process.env.OPENCOLLECTIVE_TOKEN) {
headers['Personal-Token'] = process.env.OPENCOLLECTIVE_TOKEN;
}
const response = await fetch(OPEN_COLLECTIVE_API, {
method: 'POST',
headers,
body: JSON.stringify({ query, variables: { slug: COLLECTIVE_SLUG } }),
});
if (!response.ok) {
throw new Error(`Open Collective API responded with ${response.status} ${response.statusText}`);
}
const { data, errors } = (await response.json()) as CollectiveResponse;
if (errors?.length) {
throw new Error(
`Open Collective API errors: ${errors.map(({ message }) => message).join(', ')}`,
);
}
if (!data?.account) {
throw new Error(`Could not find Open Collective account "${COLLECTIVE_SLUG}"`);
}
return data.account;
}
/**
* Active contributions, plus recurring ones that stopped (cancelled, failed or paused) less than
* a month after their next payment was due. A failed payment doesn't drop a sponsor right away.
*/
function isCurrentSponsor({ status, nextChargeDate }: Order) {
if (status === 'ACTIVE') return true;
if (!nextChargeDate) return false;
return Date.now() < new Date(nextChargeDate).getTime() + GRACE_PERIOD_DAYS * DAY_IN_MS;
}
function getYearlyAmount({ amount, frequency }: Order) {
const value = (amount?.valueInCents ?? 0) / 100;
return frequency === 'YEARLY' ? value : value * 12;
}
/**
* The current sponsors with everything they contribute in a year and the tier that qualifies
* for, highest amount first.
*/
export function getCurrentSponsors(orders: Order[]) {
const yearlyAmounts = new Map<string, { account: Account; yearlyAmount: number }>();
orders.filter(isCurrentSponsor).forEach((order) => {
const sponsor = yearlyAmounts.get(order.fromAccount.slug);
if (sponsor) {
sponsor.yearlyAmount += getYearlyAmount(order);
} else {
yearlyAmounts.set(order.fromAccount.slug, {
account: order.fromAccount,
yearlyAmount: getYearlyAmount(order),
});
}
});
return [...yearlyAmounts.values()]
.map(({ account, yearlyAmount }) => {
const roundedAmount = Math.round(yearlyAmount * 100) / 100;
return {
account,
yearlyAmount: roundedAmount,
tier: getTierForYearlyAmount(roundedAmount)?.id ?? null,
};
})
.sort(
(a, b) => b.yearlyAmount - a.yearlyAmount || a.account.name.localeCompare(b.account.name),
);
}
const findLogo = (fileName: string) =>
['svg', 'png']
.map((extension) => `${fileName}.${extension}`)
.find((file) => existsSync(join(sponsorLogosPath, file)));
/**
* Custom logos in docs/public/sponsors, as paths relative to that directory.
* A logo in docs/public/sponsors/dark is used in dark mode.
*/
export function getLocalLogos(slug: string) {
return { light: findLogo(slug), dark: findLogo(`dark/${slug}`) };
}
export const getWebsite = ({ slug, website }: Account) =>
website || `https://opencollective.com/${slug}`;
export const getOpenCollectiveLogo = ({ slug, imageUrl }: Account) =>
imageUrl ?? `https://images.opencollective.com/${slug}/logo/256.png`;
+69
View File
@@ -0,0 +1,69 @@
import fs from 'fs';
import path from 'path';
import { loadEnvFile } from 'node:process';
import type { TierId } from '../.vitepress/theme/components/sponsor/tiers.ts';
import {
fetchCollective,
getCurrentSponsors,
getLocalLogos,
getOpenCollectiveLogo,
getWebsite,
} from './helpers/openCollective.mts';
const currentDir = process.cwd();
const dataDirectory = path.resolve(currentDir, '.vitepress/data');
const outputPath = path.resolve(dataDirectory, 'sponsorsData.json');
try {
// Load environment variables from .env file, if it exists.
loadEnvFile(`${currentDir}/.env`);
} catch {
// No .env file, so rely on the environment as-is.
}
export interface Sponsor {
slug: string;
name: string;
website: string;
/** Logo for the logo tiers, preferring a local file in `public/sponsors`. */
image: string;
/** Logo for dark mode, from `public/sponsors/dark`. */
imageDark?: string;
/** Square avatar for the backer and supporter tiers. */
avatar: string;
/** Recurring contribution normalised to a monthly amount, in the collective's currency. */
monthlyAmount: number;
/** The tier their yearly contribution qualifies for, `null` below the lowest tier. */
tier: TierId | null;
}
let sponsors: Sponsor[] = [];
/** Everyone who ever contributed financially, including past and one-time contributors. */
let allTimeCount: number | null = null;
try {
const collective = await fetchCollective();
sponsors = getCurrentSponsors(collective.orders.nodes).map(({ account, yearlyAmount, tier }) => {
const logos = getLocalLogos(account.slug);
return {
slug: account.slug,
name: account.name,
website: getWebsite(account),
image: logos.light ? `/sponsors/${logos.light}` : getOpenCollectiveLogo(account),
imageDark: logos.dark && `/sponsors/${logos.dark}`,
avatar:
account.imageUrl ?? `https://images.opencollective.com/${account.slug}/avatar/128.png`,
monthlyAmount: Math.round((yearlyAmount / 12) * 100) / 100,
tier,
};
});
allTimeCount = collective.stats?.contributorsCount ?? null;
} catch (error) {
console.warn(`Could not fetch sponsors, writing an empty list. ${error}`);
}
fs.mkdirSync(dataDirectory, { recursive: true });
fs.writeFileSync(outputPath, JSON.stringify({ allTimeCount, sponsors }, null, 2), 'utf-8');
console.log(`Wrote ${sponsors.length} sponsors to ${outputPath}`);
+45
View File
@@ -0,0 +1,45 @@
---
title: Sponsor
description: Sponsor Lucide to fund icon reviews, new packages and dependable releases. Pick a tier on Open Collective or GitHub Sponsors.
layout: page
faq:
- question: Will Lucide stay free?
answer: Yes. Every icon stays free and open source under the ISC license, whether or not you sponsor.
- question: Open Collective or GitHub Sponsors?
answer: Both have the same tiers. Open Collective takes card, bank transfer and PayPal in EUR with a public ledger. GitHub Sponsors bills in USD through your existing GitHub account, with invoicing for organizations.
- question: Can I pay yearly?
answer: Gold and Platinum can be paid yearly at ten times the monthly price, so you get two months free and one invoice.
- question: When does my logo appear?
answer: Logos come from your Open Collective or GitHub profile. lucide.dev updates within a day. The npm READMEs use a hosted image, so they update without a new release.
- question: Does sponsoring get my icons accepted?
answer: No. Partners get their icon PRs reviewed first, but every icon meets the same design guidelines and community review.
- question: Can I cancel anytime?
answer: Yes, recurring contributions can be cancelled anytime on Open Collective or GitHub Sponsors.
---
<script setup>
import Faq from '~/.vitepress/theme/components/base/Faq.vue'
import SponsorSection from '~/.vitepress/theme/components/sponsor/SponsorSection.vue'
import SponsorHero from '~/.vitepress/theme/components/sponsor/SponsorHero.vue'
import SponsorAmountPicker from '~/.vitepress/theme/components/sponsor/SponsorAmountPicker.vue'
import SponsorTiers from '~/.vitepress/theme/components/sponsor/SponsorTiers.vue'
import SponsorWall from '~/.vitepress/theme/components/sponsor/SponsorWall.vue'
import SponsorFundingUses from '~/.vitepress/theme/components/sponsor/SponsorFundingUses.vue'
import SponsorCta from '~/.vitepress/theme/components/sponsor/SponsorCta.vue'
</script>
<SponsorHero />
<SponsorAmountPicker />
<SponsorTiers />
<SponsorWall />
<SponsorFundingUses />
<SponsorSection narrow class="faq-section">
<Faq title="Frequently asked questions" />
</SponsorSection>
<SponsorCta />
<style scoped>
.faq-section {
padding-block: 96px;
}
</style>
+25 -1
View File
@@ -7,10 +7,34 @@
],
"use-cases": [],
"tags": [
"toque blanche",
"culinary cap",
"cooking",
"baking",
"culinary",
"gastronomy",
"food",
"kitchen",
"restaurant"
"restaurant",
"cuisine",
"catering",
"meal",
"dining",
"gourmet",
"apron",
"uniform",
"menu",
"toque",
"cook",
"baker",
"cookery",
"headwear",
"headgear",
"cap",
"kitchen staff",
"culinary professional",
"food service",
"hospitality"
],
"categories": [
"food-beverage"
+4 -2
View File
@@ -9,6 +9,8 @@
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M17 21a1 1 0 0 0 1-1v-5.35c0-.457.316-.844.727-1.041a4 4 0 0 0-2.134-7.589 5 5 0 0 0-9.186 0 4 4 0 0 0-2.134 7.588c.411.198.727.585.727 1.041V20a1 1 0 0 0 1 1Z" />
<path d="M6 17h12" />
<path d="M10 11v5" />
<path d="M14 11v5" />
<path d="M6 12.65c0-.457-.316-.844-.727-1.041A4 4 0 017.52 4.034a1.53 1.53 0 001.367-.547 4 4 0 016.225 0 1.53 1.53 0 001.367.547 4 4 0 012.248 7.575c-.411.197-.727.584-.727 1.04V19a2 2 0 01-2 2H8a2 2 0 01-2-2z" />
<path d="M6 16h12" />
</svg>

Before

Width:  |  Height:  |  Size: 407 B

After

Width:  |  Height:  |  Size: 497 B

+1 -1
View File
@@ -9,6 +9,6 @@
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M15 8v5a3 3 0 1 1-6 0" />
<path d="M14 8v5.5a1 1 0 01-5 0V13" />
<circle cx="12" cy="12" r="10" />
</svg>

Before

Width:  |  Height:  |  Size: 281 B

After

Width:  |  Height:  |  Size: 285 B

+35
View File
@@ -0,0 +1,35 @@
{
"$schema": "../icon.schema.json",
"contributors": [
"linus-sch",
"karsa-mistmerea"
],
"use-cases": [
"Showing relationships between concepts in visual planning tools",
"Structuring topics and subtopics in study notes",
"Planning branching workflows in diagram editors"
],
"tags": [
"$group:graph",
"mind map",
"visualization",
"brainstorm",
"brainstorming",
"ideas",
"concepts",
"planning",
"hierarchy",
"branches",
"organization",
"tree",
"workflow",
"flowchart",
"process",
"process mapping",
"sequence"
],
"categories": [
"design",
"charts"
]
}
+17
View File
@@ -0,0 +1,17 @@
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M8 12h.5a3.5 3.5 0 013.5 3.5 3.5 3.5 0 003.5 3.5h.5" />
<path d="M8.5 12A3.5 3.5 0 0012 8.5 3.5 3.5 0 0115.5 5h.5" />
<rect x="16" y="16" width="6" height="6" rx="1" />
<rect x="16" y="2" width="6" height="6" rx="1" />
<rect x="2" y="9" width="6" height="6" rx="1" />
</svg>

After

Width:  |  Height:  |  Size: 495 B

+28
View File
@@ -0,0 +1,28 @@
{
"$schema": "../icon.schema.json",
"contributors": [
"$extends:diagram-flow-horizontal"
],
"use-cases": [
"Showing top-to-bottom branching workflows in diagram editors",
"Organizing parent and child concepts in visual planning tools"
],
"tags": [
"$group:graph",
"flowchart",
"workflow",
"hierarchy",
"branches",
"tree",
"parent",
"child",
"process",
"sequence",
"decision tree"
],
"categories": [
"design",
"charts",
"development"
]
}
+17
View File
@@ -0,0 +1,17 @@
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M12 8.5a3.5 3.5 0 003.5 3.5 3.5 3.5 0 013.5 3.5v.5" />
<path d="M12 8v.5A3.5 3.5 0 018.5 12 3.5 3.5 0 005 15.5v.5" />
<rect x="16" y="16" width="6" height="6" rx="1" />
<rect x="2" y="16" width="6" height="6" rx="1" />
<rect x="9" y="2" width="6" height="6" rx="1" />
</svg>

After

Width:  |  Height:  |  Size: 495 B

+33
View File
@@ -0,0 +1,33 @@
{
"$schema": "../icon.schema.json",
"contributors": [
"$extends:globe",
"PrimeTestLab"
],
"use-cases": [
"Indicating that a website or domain is blocked",
"Showing that a service is not available in a region",
"Disabling public or internet access for a resource",
"Applying parental controls or content filters to website access"
],
"tags": [
"$extends:globe",
"$group:off",
"web",
"website",
"banned",
"geo blocking",
"offline",
"parental controls",
"content filter",
"region lock",
"public access",
"access control",
"domain blocking",
"region restriction"
],
"categories": [
"$extends:globe",
"security"
]
}
+17
View File
@@ -0,0 +1,17 @@
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M12 22a14.48 14.48 0 01-4.008-10C7.993 9.136 9 5.258 11 2.05A10 10 0 0012 22" />
<path d="m15.172 3.172 5.656 5.656" />
<path d="M15.86 14a14.5 14.5 0 01-3.859 8 10 10 0 009.949-9" />
<path d="M2 12h10.5" />
<circle cx="18" cy="6" r="4" />
</svg>

After

Width:  |  Height:  |  Size: 467 B

-1
View File
@@ -10,7 +10,6 @@
"tags": [
"$extends:globe",
"$group:check",
"internet",
"web",
"available",
"online",
-5
View File
@@ -14,13 +14,8 @@
"$extends:globe",
"$group:code",
"website",
"internet",
"globe",
"connection",
"network",
"digital",
"access",
"global",
"link"
],
"categories": [
+1 -3
View File
@@ -11,9 +11,7 @@
"$extends:globe",
"$group:lock",
"vpn",
"network",
"encryption",
"connection"
"encryption"
],
"categories": [
"security",
-6
View File
@@ -11,16 +11,10 @@
"tags": [
"$extends:globe",
"$group:off",
"globe",
"earth",
"planet",
"mute",
"avoid",
"internet",
"offline",
"disconnected",
"network",
"connection",
"no connection",
"network failure",
"signal off"
+22
View File
@@ -0,0 +1,22 @@
{
"$schema": "../icon.schema.json",
"contributors": [
"$extends:globe",
"Turboman3000"
],
"use-cases": [
"Adding an internet service provider in network settings",
"Adding a translation or language in localization settings",
"Adding a new website or domain",
"Registering a new country or region in service coverage",
"Adding a supported language to an app",
"Enabling global access for a user or service"
],
"tags": [
"$extends:globe",
"$group:plus"
],
"categories": [
"$extends:globe"
]
}
+17
View File
@@ -0,0 +1,17 @@
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M15.929 10.563A14.5 14.5 0 0112 22a1 1 0 010-20 15 15 0 01.68.768" />
<path d="M19 2v6" />
<path d="M21.92 10.734A10 10 0 0112 22a14.5 14.5 0 010-20 10 10 0 011.266.08" />
<path d="M22 12H2" />
<path d="M22 5h-6" />
</svg>

After

Width:  |  Height:  |  Size: 443 B

-4
View File
@@ -8,12 +8,8 @@
"tags": [
"$extends:globe",
"$group:x",
"globe",
"internet",
"offline",
"disconnected",
"network",
"connection",
"no connection",
"network failure",
"signal off"
+12 -1
View File
@@ -10,7 +10,18 @@
"world",
"browser",
"language",
"translate"
"translate",
"location",
"country",
"coverage",
"publish",
"connection",
"global",
"earth",
"globe",
"internet",
"planet",
"network"
],
"categories": [
"navigation",
+1 -1
View File
@@ -9,6 +9,6 @@
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M15 8v5a3 3 0 1 1-6 0" />
<path d="M14 8v5.5a1 1 0 01-5 0V13" />
<rect width="18" height="18" x="3" y="3" rx="2" />
</svg>

Before

Width:  |  Height:  |  Size: 298 B

After

Width:  |  Height:  |  Size: 302 B

+1 -1
View File
@@ -19,7 +19,7 @@
"@types/react-dom": "19.3.0",
"@vitejs/plugin-react": "^6.1.2",
"@vitest/browser-playwright": "5.0.3",
"playwright": "1.58.2",
"playwright": "1.64.1",
"typescript": "^6.0.3",
"vite": "^8.3.3",
"vitest": "5.0.5",
@@ -21,7 +21,7 @@
"@solidjs/vite-plugin": "3.0.0-next.47",
"@vitest/browser-playwright": "5.0.3",
"filesystem-routing": "0.4.0",
"playwright": "1.58.2",
"playwright": "1.64.1",
"typescript": "^6.0.3",
"vite": "^8.3.3",
"vitest": "5.0.5"
+1 -1
View File
@@ -15,7 +15,7 @@
},
"devDependencies": {
"@vitest/browser-playwright": "5.0.3",
"playwright": "1.58.2",
"playwright": "1.64.1",
"typescript": "^6.0.3",
"vite": "^8.3.3",
"vite-plugin-solid": "^2.11.14",
@@ -15,14 +15,14 @@
},
"dependencies": {
"@lucide/svelte": "workspace:*",
"svelte": "5.57.2"
"svelte": "5.57.3"
},
"devDependencies": {
"@sveltejs/adapter-auto": "^8.0.0",
"@sveltejs/kit": "^3.1.0",
"@sveltejs/kit": "^3.1.1",
"@sveltejs/vite-plugin-svelte": "^7.3.1",
"@vitest/browser-playwright": "5.0.3",
"playwright": "1.58.2",
"playwright": "1.64.1",
"svelte-check": "^4.7.7",
"typescript": "^6.0.3",
"vite": "^8.3.3",
+2 -2
View File
@@ -11,14 +11,14 @@
},
"dependencies": {
"@lucide/svelte": "workspace:*",
"svelte": "5.57.2"
"svelte": "5.57.3"
},
"devDependencies": {
"@sveltejs/vite-plugin-svelte": "^7.3.1",
"@tsconfig/svelte": "^5.0.8",
"@types/node": "^26.1.1",
"@vitest/browser-playwright": "5.0.3",
"playwright": "1.58.2",
"playwright": "1.64.1",
"svelte-check": "^4.7.7",
"typescript": "^6.0.3",
"vite": "^8.3.3",
+1 -1
View File
@@ -19,7 +19,7 @@
"@vitejs/plugin-vue": "^6.0.10",
"@vitest/browser-playwright": "5.0.3",
"@vue/tsconfig": "^0.9.1",
"playwright": "1.58.2",
"playwright": "1.64.1",
"typescript": "^6.0.3",
"vite": "^8.3.3",
"vitest": "5.0.5",
+30
View File
@@ -0,0 +1,30 @@
{
"$schema": "../icon.schema.json",
"contributors": [
"synthetic-blood",
"ericfennis"
],
"use-cases": [
"labeling resistors in circuit diagrams",
"decorating electronics tutorials and articles",
"representing passive components in schematic editors",
"identifying resistor entries in bills of materials",
"indicating resistance or ohm-related settings in a UI"
],
"tags": [
"circuit",
"component",
"resistor",
"electronics",
"electrical",
"ohm",
"schematic",
"symbol",
"passive",
"engineering",
"iec"
],
"categories": [
"devices"
]
}
+15
View File
@@ -0,0 +1,15 @@
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M2 12h4.5" />
<path d="M22 12h-3.876" />
<rect x="6.5" y="9" width="11.5" height="6" rx="1" />
</svg>

After

Width:  |  Height:  |  Size: 318 B

+32
View File
@@ -0,0 +1,32 @@
{
"$schema": "../icon.schema.json",
"contributors": [
"colebemis",
"csandman",
"ericfennis",
"karsa-mistmere",
"k8adev"
],
"use-cases": [],
"tags": [
"technology",
"device",
"portable",
"connection",
"digital",
"navigation",
"office",
"communication",
"travel",
"computer",
"screen",
"remote",
"location",
"marker",
"drop"
],
"categories": [
"navigation",
"devices"
]
}
+16
View File
@@ -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="M16 22h6" />
<path d="M18 10a8 8 0 00-16 0c0 4.993 5.539 10.193 7.399 11.799a1 1 0 001.202 0 38 38 0 00.887-.83" />
<circle cx="10" cy="10" r="3" />
<rect x="16" y="14" width="6" height="4" rx="1" />
</svg>

After

Width:  |  Height:  |  Size: 425 B

+4 -15
View File
@@ -71,24 +71,13 @@ Lucide is licensed under the ISC license. See [LICENSE](https://lucide.dev/licen
<img src="https://lucide.dev/vercel.svg" alt="Powered by Vercel" width="200" />
</a>
[//]: <> (Sponsor tiers start)
### Hero Backer 🦸
### Bronze 🥉
<a href="https://about.sourcegraph.com"><img src="https://images.opencollective.com/sourcegraph/f67b621/logo.png" height="64" alt="Sourcegraph – Understand, fix, and automate across your codebase with Sourcegraph's code intelligence platform" /></a>
<a href="https://opencollective.com/zephyr-cloud"><img src="https://lucide.dev/sponsors/zephyr-cloud.svg" height="64" alt="Zephyr Cloud" /></a>
### Awesome backers 🍺
<a href="https://www.paxhistoria.co"><img src="https://images.opencollective.com/pax-historia/9b4e54b/logo.png" height="64" alt="Pax Historia" /></a>
<a href="https://pdfme.com"><img src="https://images.opencollective.com/pdfmeorg/9e0174d/logo.png" height="64" alt="pdfme – Free and Open source PDF generation library!" /></a>
### Backer ☕️
<a href="https://www.fina.money"><img src="https://lucide.dev/sponsors/fina-money.png" height="64" alt="Fina Money – Build the most flexible finance tracker" /></a>
<a href="https://opencollective.com/rjvdw"><img src="https://images.opencollective.com/rjvdw/28bc9cd/avatar.png" height="64" alt="Ruud" /></a>
<a href="https://about.sourcegraph.com"><picture><source media="(prefers-color-scheme: dark)" srcset="https://lucide.dev/sponsors/dark/sourcegraph.svg" /><img src="https://lucide.dev/sponsors/sourcegraph.svg" height="48" alt="Sourcegraph – Understand, fix, and automate across your codebase with Sourcegraph's code intelligence platform" /></picture></a>
&nbsp;&nbsp;
<a href="https://opencollective.com/zephyr-cloud"><picture><source media="(prefers-color-scheme: dark)" srcset="https://lucide.dev/sponsors/dark/zephyr-cloud.svg" /><img src="https://lucide.dev/sponsors/zephyr-cloud.svg" height="48" alt="Zephyr Cloud" /></picture></a>
[//]: <> (Sponsor tiers end)
+4 -15
View File
@@ -68,24 +68,13 @@ Lucide is licensed under the ISC license. See [LICENSE](https://lucide.dev/licen
<img src="https://lucide.dev/vercel.svg" alt="Powered by Vercel" width="200" />
</a>
[//]: <> (Sponsor tiers start)
### Hero Backer 🦸
### Bronze 🥉
<a href="https://about.sourcegraph.com"><img src="https://images.opencollective.com/sourcegraph/f67b621/logo.png" height="64" alt="Sourcegraph – Understand, fix, and automate across your codebase with Sourcegraph's code intelligence platform" /></a>
<a href="https://opencollective.com/zephyr-cloud"><img src="https://lucide.dev/sponsors/zephyr-cloud.svg" height="64" alt="Zephyr Cloud" /></a>
### Awesome backers 🍺
<a href="https://www.paxhistoria.co"><img src="https://images.opencollective.com/pax-historia/9b4e54b/logo.png" height="64" alt="Pax Historia" /></a>
<a href="https://pdfme.com"><img src="https://images.opencollective.com/pdfmeorg/9e0174d/logo.png" height="64" alt="pdfme – Free and Open source PDF generation library!" /></a>
### Backer ☕️
<a href="https://www.fina.money"><img src="https://lucide.dev/sponsors/fina-money.png" height="64" alt="Fina Money – Build the most flexible finance tracker" /></a>
<a href="https://opencollective.com/rjvdw"><img src="https://images.opencollective.com/rjvdw/28bc9cd/avatar.png" height="64" alt="Ruud" /></a>
<a href="https://about.sourcegraph.com"><picture><source media="(prefers-color-scheme: dark)" srcset="https://lucide.dev/sponsors/dark/sourcegraph.svg" /><img src="https://lucide.dev/sponsors/sourcegraph.svg" height="48" alt="Sourcegraph – Understand, fix, and automate across your codebase with Sourcegraph's code intelligence platform" /></picture></a>
&nbsp;&nbsp;
<a href="https://opencollective.com/zephyr-cloud"><picture><source media="(prefers-color-scheme: dark)" srcset="https://lucide.dev/sponsors/dark/zephyr-cloud.svg" /><img src="https://lucide.dev/sponsors/zephyr-cloud.svg" height="48" alt="Zephyr Cloud" /></picture></a>
[//]: <> (Sponsor tiers end)
+4 -15
View File
@@ -76,24 +76,13 @@ Lucide is licensed under the ISC license. See [LICENSE](https://lucide.dev/licen
<img src="https://lucide.dev/vercel.svg" alt="Powered by Vercel" width="200" />
</a>
[//]: <> (Sponsor tiers start)
### Hero Backer 🦸
### Bronze 🥉
<a href="https://about.sourcegraph.com"><img src="https://images.opencollective.com/sourcegraph/f67b621/logo.png" height="64" alt="Sourcegraph – Understand, fix, and automate across your codebase with Sourcegraph's code intelligence platform" /></a>
<a href="https://opencollective.com/zephyr-cloud"><img src="https://lucide.dev/sponsors/zephyr-cloud.svg" height="64" alt="Zephyr Cloud" /></a>
### Awesome backers 🍺
<a href="https://www.paxhistoria.co"><img src="https://images.opencollective.com/pax-historia/9b4e54b/logo.png" height="64" alt="Pax Historia" /></a>
<a href="https://pdfme.com"><img src="https://images.opencollective.com/pdfmeorg/9e0174d/logo.png" height="64" alt="pdfme – Free and Open source PDF generation library!" /></a>
### Backer ☕️
<a href="https://www.fina.money"><img src="https://lucide.dev/sponsors/fina-money.png" height="64" alt="Fina Money – Build the most flexible finance tracker" /></a>
<a href="https://opencollective.com/rjvdw"><img src="https://images.opencollective.com/rjvdw/28bc9cd/avatar.png" height="64" alt="Ruud" /></a>
<a href="https://about.sourcegraph.com"><picture><source media="(prefers-color-scheme: dark)" srcset="https://lucide.dev/sponsors/dark/sourcegraph.svg" /><img src="https://lucide.dev/sponsors/sourcegraph.svg" height="48" alt="Sourcegraph – Understand, fix, and automate across your codebase with Sourcegraph's code intelligence platform" /></picture></a>
&nbsp;&nbsp;
<a href="https://opencollective.com/zephyr-cloud"><picture><source media="(prefers-color-scheme: dark)" srcset="https://lucide.dev/sponsors/dark/zephyr-cloud.svg" /><img src="https://lucide.dev/sponsors/zephyr-cloud.svg" height="48" alt="Zephyr Cloud" /></picture></a>
[//]: <> (Sponsor tiers end)
+4 -15
View File
@@ -67,24 +67,13 @@ Lucide is licensed under the ISC license. See [LICENSE](https://lucide.dev/licen
<img src="https://lucide.dev/vercel.svg" alt="Powered by Vercel" width="200" />
</a>
[//]: <> (Sponsor tiers start)
### Hero Backer 🦸
### Bronze 🥉
<a href="https://about.sourcegraph.com"><img src="https://images.opencollective.com/sourcegraph/f67b621/logo.png" height="64" alt="Sourcegraph – Understand, fix, and automate across your codebase with Sourcegraph's code intelligence platform" /></a>
<a href="https://opencollective.com/zephyr-cloud"><img src="https://lucide.dev/sponsors/zephyr-cloud.svg" height="64" alt="Zephyr Cloud" /></a>
### Awesome backers 🍺
<a href="https://www.paxhistoria.co"><img src="https://images.opencollective.com/pax-historia/9b4e54b/logo.png" height="64" alt="Pax Historia" /></a>
<a href="https://pdfme.com"><img src="https://images.opencollective.com/pdfmeorg/9e0174d/logo.png" height="64" alt="pdfme – Free and Open source PDF generation library!" /></a>
### Backer ☕️
<a href="https://www.fina.money"><img src="https://lucide.dev/sponsors/fina-money.png" height="64" alt="Fina Money – Build the most flexible finance tracker" /></a>
<a href="https://opencollective.com/rjvdw"><img src="https://images.opencollective.com/rjvdw/28bc9cd/avatar.png" height="64" alt="Ruud" /></a>
<a href="https://about.sourcegraph.com"><picture><source media="(prefers-color-scheme: dark)" srcset="https://lucide.dev/sponsors/dark/sourcegraph.svg" /><img src="https://lucide.dev/sponsors/sourcegraph.svg" height="48" alt="Sourcegraph – Understand, fix, and automate across your codebase with Sourcegraph's code intelligence platform" /></picture></a>
&nbsp;&nbsp;
<a href="https://opencollective.com/zephyr-cloud"><picture><source media="(prefers-color-scheme: dark)" srcset="https://lucide.dev/sponsors/dark/zephyr-cloud.svg" /><img src="https://lucide.dev/sponsors/zephyr-cloud.svg" height="48" alt="Zephyr Cloud" /></picture></a>
[//]: <> (Sponsor tiers end)
+1 -1
View File
@@ -55,7 +55,7 @@
"@testing-library/jest-dom": "^7.0.1",
"@testing-library/preact": "^3.2.6",
"jest-serializer-html": "^7.1.0",
"preact": "^11.0.2",
"preact": "^11.1.0",
"rollup": "^4.65.0",
"rollup-plugin-dts": "^6.5.1",
"typescript": "^6.0.3",
+4 -15
View File
@@ -67,24 +67,13 @@ Lucide is licensed under the ISC license. See [LICENSE](https://lucide.dev/licen
<img src="https://lucide.dev/vercel.svg" alt="Powered by Vercel" width="200" />
</a>
[//]: <> (Sponsor tiers start)
### Hero Backer 🦸
### Bronze 🥉
<a href="https://about.sourcegraph.com"><img src="https://images.opencollective.com/sourcegraph/f67b621/logo.png" height="64" alt="Sourcegraph – Understand, fix, and automate across your codebase with Sourcegraph's code intelligence platform" /></a>
<a href="https://opencollective.com/zephyr-cloud"><img src="https://lucide.dev/sponsors/zephyr-cloud.svg" height="64" alt="Zephyr Cloud" /></a>
### Awesome backers 🍺
<a href="https://www.paxhistoria.co"><img src="https://images.opencollective.com/pax-historia/9b4e54b/logo.png" height="64" alt="Pax Historia" /></a>
<a href="https://pdfme.com"><img src="https://images.opencollective.com/pdfmeorg/9e0174d/logo.png" height="64" alt="pdfme – Free and Open source PDF generation library!" /></a>
### Backer ☕️
<a href="https://www.fina.money"><img src="https://lucide.dev/sponsors/fina-money.png" height="64" alt="Fina Money – Build the most flexible finance tracker" /></a>
<a href="https://opencollective.com/rjvdw"><img src="https://images.opencollective.com/rjvdw/28bc9cd/avatar.png" height="64" alt="Ruud" /></a>
<a href="https://about.sourcegraph.com"><picture><source media="(prefers-color-scheme: dark)" srcset="https://lucide.dev/sponsors/dark/sourcegraph.svg" /><img src="https://lucide.dev/sponsors/sourcegraph.svg" height="48" alt="Sourcegraph – Understand, fix, and automate across your codebase with Sourcegraph's code intelligence platform" /></picture></a>
&nbsp;&nbsp;
<a href="https://opencollective.com/zephyr-cloud"><picture><source media="(prefers-color-scheme: dark)" srcset="https://lucide.dev/sponsors/dark/zephyr-cloud.svg" /><img src="https://lucide.dev/sponsors/zephyr-cloud.svg" height="48" alt="Zephyr Cloud" /></picture></a>
[//]: <> (Sponsor tiers end)
+4 -15
View File
@@ -67,24 +67,13 @@ Lucide is licensed under the ISC license. See [LICENSE](https://lucide.dev/licen
<img src="https://lucide.dev/vercel.svg" alt="Powered by Vercel" width="200" />
</a>
[//]: <> (Sponsor tiers start)
### Hero Backer 🦸
### Bronze 🥉
<a href="https://about.sourcegraph.com"><img src="https://images.opencollective.com/sourcegraph/f67b621/logo.png" height="64" alt="Sourcegraph – Understand, fix, and automate across your codebase with Sourcegraph's code intelligence platform" /></a>
<a href="https://opencollective.com/zephyr-cloud"><img src="https://lucide.dev/sponsors/zephyr-cloud.svg" height="64" alt="Zephyr Cloud" /></a>
### Awesome backers 🍺
<a href="https://www.paxhistoria.co"><img src="https://images.opencollective.com/pax-historia/9b4e54b/logo.png" height="64" alt="Pax Historia" /></a>
<a href="https://pdfme.com"><img src="https://images.opencollective.com/pdfmeorg/9e0174d/logo.png" height="64" alt="pdfme – Free and Open source PDF generation library!" /></a>
### Backer ☕️
<a href="https://www.fina.money"><img src="https://lucide.dev/sponsors/fina-money.png" height="64" alt="Fina Money – Build the most flexible finance tracker" /></a>
<a href="https://opencollective.com/rjvdw"><img src="https://images.opencollective.com/rjvdw/28bc9cd/avatar.png" height="64" alt="Ruud" /></a>
<a href="https://about.sourcegraph.com"><picture><source media="(prefers-color-scheme: dark)" srcset="https://lucide.dev/sponsors/dark/sourcegraph.svg" /><img src="https://lucide.dev/sponsors/sourcegraph.svg" height="48" alt="Sourcegraph – Understand, fix, and automate across your codebase with Sourcegraph's code intelligence platform" /></picture></a>
&nbsp;&nbsp;
<a href="https://opencollective.com/zephyr-cloud"><picture><source media="(prefers-color-scheme: dark)" srcset="https://lucide.dev/sponsors/dark/zephyr-cloud.svg" /><img src="https://lucide.dev/sponsors/zephyr-cloud.svg" height="48" alt="Zephyr Cloud" /></picture></a>
[//]: <> (Sponsor tiers end)
+4 -15
View File
@@ -67,24 +67,13 @@ Lucide is licensed under the ISC license. See [LICENSE](https://lucide.dev/licen
<img src="https://lucide.dev/vercel.svg" alt="Powered by Vercel" width="200" />
</a>
[//]: <> (Sponsor tiers start)
### Hero Backer 🦸
### Bronze 🥉
<a href="https://about.sourcegraph.com"><img src="https://images.opencollective.com/sourcegraph/f67b621/logo.png" height="64" alt="Sourcegraph – Understand, fix, and automate across your codebase with Sourcegraph's code intelligence platform" /></a>
<a href="https://opencollective.com/zephyr-cloud"><img src="https://lucide.dev/sponsors/zephyr-cloud.svg" height="64" alt="Zephyr Cloud" /></a>
### Awesome backers 🍺
<a href="https://www.paxhistoria.co"><img src="https://images.opencollective.com/pax-historia/9b4e54b/logo.png" height="64" alt="Pax Historia" /></a>
<a href="https://pdfme.com"><img src="https://images.opencollective.com/pdfmeorg/9e0174d/logo.png" height="64" alt="pdfme – Free and Open source PDF generation library!" /></a>
### Backer ☕️
<a href="https://www.fina.money"><img src="https://lucide.dev/sponsors/fina-money.png" height="64" alt="Fina Money – Build the most flexible finance tracker" /></a>
<a href="https://opencollective.com/rjvdw"><img src="https://images.opencollective.com/rjvdw/28bc9cd/avatar.png" height="64" alt="Ruud" /></a>
<a href="https://about.sourcegraph.com"><picture><source media="(prefers-color-scheme: dark)" srcset="https://lucide.dev/sponsors/dark/sourcegraph.svg" /><img src="https://lucide.dev/sponsors/sourcegraph.svg" height="48" alt="Sourcegraph – Understand, fix, and automate across your codebase with Sourcegraph's code intelligence platform" /></picture></a>
&nbsp;&nbsp;
<a href="https://opencollective.com/zephyr-cloud"><picture><source media="(prefers-color-scheme: dark)" srcset="https://lucide.dev/sponsors/dark/zephyr-cloud.svg" /><img src="https://lucide.dev/sponsors/zephyr-cloud.svg" height="48" alt="Zephyr Cloud" /></picture></a>
[//]: <> (Sponsor tiers end)
+4 -15
View File
@@ -81,24 +81,13 @@ Lucide is licensed under the ISC license. See [LICENSE](https://lucide.dev/licen
<img src="https://lucide.dev/vercel.svg" alt="Powered by Vercel" width="200" />
</a>
[//]: <> (Sponsor tiers start)
### Hero Backer 🦸
### Bronze 🥉
<a href="https://about.sourcegraph.com"><img src="https://images.opencollective.com/sourcegraph/f67b621/logo.png" height="64" alt="Sourcegraph – Understand, fix, and automate across your codebase with Sourcegraph's code intelligence platform" /></a>
<a href="https://opencollective.com/zephyr-cloud"><img src="https://lucide.dev/sponsors/zephyr-cloud.svg" height="64" alt="Zephyr Cloud" /></a>
### Awesome backers 🍺
<a href="https://www.paxhistoria.co"><img src="https://images.opencollective.com/pax-historia/9b4e54b/logo.png" height="64" alt="Pax Historia" /></a>
<a href="https://pdfme.com"><img src="https://images.opencollective.com/pdfmeorg/9e0174d/logo.png" height="64" alt="pdfme – Free and Open source PDF generation library!" /></a>
### Backer ☕️
<a href="https://www.fina.money"><img src="https://lucide.dev/sponsors/fina-money.png" height="64" alt="Fina Money – Build the most flexible finance tracker" /></a>
<a href="https://opencollective.com/rjvdw"><img src="https://images.opencollective.com/rjvdw/28bc9cd/avatar.png" height="64" alt="Ruud" /></a>
<a href="https://about.sourcegraph.com"><picture><source media="(prefers-color-scheme: dark)" srcset="https://lucide.dev/sponsors/dark/sourcegraph.svg" /><img src="https://lucide.dev/sponsors/sourcegraph.svg" height="48" alt="Sourcegraph – Understand, fix, and automate across your codebase with Sourcegraph's code intelligence platform" /></picture></a>
&nbsp;&nbsp;
<a href="https://opencollective.com/zephyr-cloud"><picture><source media="(prefers-color-scheme: dark)" srcset="https://lucide.dev/sponsors/dark/zephyr-cloud.svg" /><img src="https://lucide.dev/sponsors/zephyr-cloud.svg" height="48" alt="Zephyr Cloud" /></picture></a>
[//]: <> (Sponsor tiers end)
+4 -15
View File
@@ -77,24 +77,13 @@ Lucide is licensed under the ISC license. See [LICENSE](https://lucide.dev/licen
<img src="https://lucide.dev/vercel.svg" alt="Powered by Vercel" width="200" />
</a>
[//]: <> (Sponsor tiers start)
### Hero Backer 🦸
### Bronze 🥉
<a href="https://about.sourcegraph.com"><img src="https://images.opencollective.com/sourcegraph/f67b621/logo.png" height="64" alt="Sourcegraph – Understand, fix, and automate across your codebase with Sourcegraph's code intelligence platform" /></a>
<a href="https://opencollective.com/zephyr-cloud"><img src="https://lucide.dev/sponsors/zephyr-cloud.svg" height="64" alt="Zephyr Cloud" /></a>
### Awesome backers 🍺
<a href="https://www.paxhistoria.co"><img src="https://images.opencollective.com/pax-historia/9b4e54b/logo.png" height="64" alt="Pax Historia" /></a>
<a href="https://pdfme.com"><img src="https://images.opencollective.com/pdfmeorg/9e0174d/logo.png" height="64" alt="pdfme – Free and Open source PDF generation library!" /></a>
### Backer ☕️
<a href="https://www.fina.money"><img src="https://lucide.dev/sponsors/fina-money.png" height="64" alt="Fina Money – Build the most flexible finance tracker" /></a>
<a href="https://opencollective.com/rjvdw"><img src="https://images.opencollective.com/rjvdw/28bc9cd/avatar.png" height="64" alt="Ruud" /></a>
<a href="https://about.sourcegraph.com"><picture><source media="(prefers-color-scheme: dark)" srcset="https://lucide.dev/sponsors/dark/sourcegraph.svg" /><img src="https://lucide.dev/sponsors/sourcegraph.svg" height="48" alt="Sourcegraph – Understand, fix, and automate across your codebase with Sourcegraph's code intelligence platform" /></picture></a>
&nbsp;&nbsp;
<a href="https://opencollective.com/zephyr-cloud"><picture><source media="(prefers-color-scheme: dark)" srcset="https://lucide.dev/sponsors/dark/zephyr-cloud.svg" /><img src="https://lucide.dev/sponsors/zephyr-cloud.svg" height="48" alt="Zephyr Cloud" /></picture></a>
[//]: <> (Sponsor tiers end)
+4 -15
View File
@@ -69,24 +69,13 @@ Lucide is licensed under the ISC license. See [LICENSE](https://lucide.dev/licen
<img src="https://lucide.dev/vercel.svg" alt="Powered by Vercel" width="200" />
</a>
[//]: <> (Sponsor tiers start)
### Hero Backer 🦸
### Bronze 🥉
<a href="https://about.sourcegraph.com"><img src="https://images.opencollective.com/sourcegraph/f67b621/logo.png" height="64" alt="Sourcegraph – Understand, fix, and automate across your codebase with Sourcegraph's code intelligence platform" /></a>
<a href="https://opencollective.com/zephyr-cloud"><img src="https://lucide.dev/sponsors/zephyr-cloud.svg" height="64" alt="Zephyr Cloud" /></a>
### Awesome backers 🍺
<a href="https://www.paxhistoria.co"><img src="https://images.opencollective.com/pax-historia/9b4e54b/logo.png" height="64" alt="Pax Historia" /></a>
<a href="https://pdfme.com"><img src="https://images.opencollective.com/pdfmeorg/9e0174d/logo.png" height="64" alt="pdfme – Free and Open source PDF generation library!" /></a>
### Backer ☕️
<a href="https://www.fina.money"><img src="https://lucide.dev/sponsors/fina-money.png" height="64" alt="Fina Money – Build the most flexible finance tracker" /></a>
<a href="https://opencollective.com/rjvdw"><img src="https://images.opencollective.com/rjvdw/28bc9cd/avatar.png" height="64" alt="Ruud" /></a>
<a href="https://about.sourcegraph.com"><picture><source media="(prefers-color-scheme: dark)" srcset="https://lucide.dev/sponsors/dark/sourcegraph.svg" /><img src="https://lucide.dev/sponsors/sourcegraph.svg" height="48" alt="Sourcegraph – Understand, fix, and automate across your codebase with Sourcegraph's code intelligence platform" /></picture></a>
&nbsp;&nbsp;
<a href="https://opencollective.com/zephyr-cloud"><picture><source media="(prefers-color-scheme: dark)" srcset="https://lucide.dev/sponsors/dark/zephyr-cloud.svg" /><img src="https://lucide.dev/sponsors/zephyr-cloud.svg" height="48" alt="Zephyr Cloud" /></picture></a>
[//]: <> (Sponsor tiers end)
+4 -15
View File
@@ -69,24 +69,13 @@ Lucide is licensed under the ISC license. See [LICENSE](https://lucide.dev/licen
<img src="https://lucide.dev/vercel.svg" alt="Powered by Vercel" width="200" />
</a>
[//]: <> (Sponsor tiers start)
### Hero Backer 🦸
### Bronze 🥉
<a href="https://about.sourcegraph.com"><img src="https://images.opencollective.com/sourcegraph/f67b621/logo.png" height="64" alt="Sourcegraph – Understand, fix, and automate across your codebase with Sourcegraph's code intelligence platform" /></a>
<a href="https://opencollective.com/zephyr-cloud"><img src="https://lucide.dev/sponsors/zephyr-cloud.svg" height="64" alt="Zephyr Cloud" /></a>
### Awesome backers 🍺
<a href="https://www.paxhistoria.co"><img src="https://images.opencollective.com/pax-historia/9b4e54b/logo.png" height="64" alt="Pax Historia" /></a>
<a href="https://pdfme.com"><img src="https://images.opencollective.com/pdfmeorg/9e0174d/logo.png" height="64" alt="pdfme – Free and Open source PDF generation library!" /></a>
### Backer ☕️
<a href="https://www.fina.money"><img src="https://lucide.dev/sponsors/fina-money.png" height="64" alt="Fina Money – Build the most flexible finance tracker" /></a>
<a href="https://opencollective.com/rjvdw"><img src="https://images.opencollective.com/rjvdw/28bc9cd/avatar.png" height="64" alt="Ruud" /></a>
<a href="https://about.sourcegraph.com"><picture><source media="(prefers-color-scheme: dark)" srcset="https://lucide.dev/sponsors/dark/sourcegraph.svg" /><img src="https://lucide.dev/sponsors/sourcegraph.svg" height="48" alt="Sourcegraph – Understand, fix, and automate across your codebase with Sourcegraph's code intelligence platform" /></picture></a>
&nbsp;&nbsp;
<a href="https://opencollective.com/zephyr-cloud"><picture><source media="(prefers-color-scheme: dark)" srcset="https://lucide.dev/sponsors/dark/zephyr-cloud.svg" /><img src="https://lucide.dev/sponsors/zephyr-cloud.svg" height="48" alt="Zephyr Cloud" /></picture></a>
[//]: <> (Sponsor tiers end)
+2 -2
View File
@@ -65,14 +65,14 @@
"devDependencies": {
"@lucide/build-icons": "workspace:*",
"@lucide/helpers": "workspace:*",
"@sveltejs/package": "^3.0.1",
"@sveltejs/package": "^3.0.2",
"@sveltejs/vite-plugin-svelte": "^7.3.1",
"@testing-library/jest-dom": "^7.0.1",
"@testing-library/svelte": "^5.4.2",
"@tsconfig/svelte": "^5.0.8",
"jest-serializer-html": "^7.1.0",
"jsdom": "^30.1.3",
"svelte": "^5.57.2",
"svelte": "^5.57.3",
"svelte-check": "^4.7.7",
"svelte-preprocess": "^6.0.5",
"typescript": "^6.0.3",
+4 -15
View File
@@ -67,24 +67,13 @@ Lucide is licensed under the ISC license. See [LICENSE](https://lucide.dev/licen
<img src="https://lucide.dev/vercel.svg" alt="Powered by Vercel" width="200" />
</a>
[//]: <> (Sponsor tiers start)
### Hero Backer 🦸
### Bronze 🥉
<a href="https://about.sourcegraph.com"><img src="https://images.opencollective.com/sourcegraph/f67b621/logo.png" height="64" alt="Sourcegraph – Understand, fix, and automate across your codebase with Sourcegraph's code intelligence platform" /></a>
<a href="https://opencollective.com/zephyr-cloud"><img src="https://lucide.dev/sponsors/zephyr-cloud.svg" height="64" alt="Zephyr Cloud" /></a>
### Awesome backers 🍺
<a href="https://www.paxhistoria.co"><img src="https://images.opencollective.com/pax-historia/9b4e54b/logo.png" height="64" alt="Pax Historia" /></a>
<a href="https://pdfme.com"><img src="https://images.opencollective.com/pdfmeorg/9e0174d/logo.png" height="64" alt="pdfme – Free and Open source PDF generation library!" /></a>
### Backer ☕️
<a href="https://www.fina.money"><img src="https://lucide.dev/sponsors/fina-money.png" height="64" alt="Fina Money – Build the most flexible finance tracker" /></a>
<a href="https://opencollective.com/rjvdw"><img src="https://images.opencollective.com/rjvdw/28bc9cd/avatar.png" height="64" alt="Ruud" /></a>
<a href="https://about.sourcegraph.com"><picture><source media="(prefers-color-scheme: dark)" srcset="https://lucide.dev/sponsors/dark/sourcegraph.svg" /><img src="https://lucide.dev/sponsors/sourcegraph.svg" height="48" alt="Sourcegraph – Understand, fix, and automate across your codebase with Sourcegraph's code intelligence platform" /></picture></a>
&nbsp;&nbsp;
<a href="https://opencollective.com/zephyr-cloud"><picture><source media="(prefers-color-scheme: dark)" srcset="https://lucide.dev/sponsors/dark/zephyr-cloud.svg" /><img src="https://lucide.dev/sponsors/zephyr-cloud.svg" height="48" alt="Zephyr Cloud" /></picture></a>
[//]: <> (Sponsor tiers end)
+179 -176
View File
@@ -312,7 +312,7 @@ importers:
version: 6.1.2(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1))
'@vitest/browser-playwright':
specifier: 5.0.3
version: 5.0.3(playwright@1.58.2)(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1))(vitest@5.0.3)
version: 5.0.3(playwright@1.64.1)(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1))(vitest@5.0.3)
typescript:
specifier: ^6.0.3
version: 6.0.3
@@ -367,7 +367,7 @@ importers:
version: 6.1.2(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1))
'@vitest/browser-playwright':
specifier: 5.0.3
version: 5.0.3(playwright@1.58.2)(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1))(vitest@5.0.3)
version: 5.0.3(playwright@1.64.1)(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1))(vitest@5.0.3)
typescript:
specifier: ^6.0.3
version: 6.0.3
@@ -410,7 +410,7 @@ importers:
version: 6.1.2(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1))
'@vitest/browser-playwright':
specifier: 5.0.3
version: 5.0.3(playwright@1.58.2)(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1))(vitest@5.0.3)
version: 5.0.3(playwright@1.64.1)(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1))(vitest@5.0.3)
typescript:
specifier: ^6.0.3
version: 6.0.3
@@ -456,7 +456,7 @@ importers:
version: 6.1.2(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1))
'@vitest/browser-playwright':
specifier: 5.0.3
version: 5.0.3(playwright@1.58.2)(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1))(vitest@5.0.3)
version: 5.0.3(playwright@1.64.1)(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1))(vitest@5.0.3)
typescript:
specifier: ^6.0.3
version: 6.0.3
@@ -493,10 +493,10 @@ importers:
version: 6.1.2(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1))
'@vitest/browser-playwright':
specifier: 5.0.3
version: 5.0.3(playwright@1.58.2)(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1))(vitest@5.0.3)
version: 5.0.3(playwright@1.64.1)(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1))(vitest@5.0.3)
playwright:
specifier: 1.58.2
version: 1.58.2
specifier: 1.64.1
version: 1.64.1
typescript:
specifier: ^6.0.3
version: 6.0.3
@@ -517,32 +517,32 @@ importers:
version: link:../../../packages/solid
'@solidjs/meta':
specifier: 1.0.0-next.2
version: 1.0.0-next.2(@solidjs/web@2.0.0-rc.18(solid-js@2.0.0-rc.18))(solid-js@2.0.0-rc.18)
version: 1.0.0-next.2(@solidjs/web@2.0.0-rc.20(solid-js@2.0.0-rc.20))(solid-js@2.0.0-rc.20)
'@solidjs/router':
specifier: 2.0.0-next.34
version: 2.0.0-next.34(@solidjs/web@2.0.0-rc.18(solid-js@2.0.0-rc.18))(filesystem-routing@0.4.0(supports-color@10.2.2)(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1)))(solid-js@2.0.0-rc.18)
version: 2.0.0-next.34(@solidjs/web@2.0.0-rc.20(solid-js@2.0.0-rc.20))(filesystem-routing@0.4.0(supports-color@10.2.2)(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1)))(solid-js@2.0.0-rc.20)
'@solidjs/web':
specifier: next
version: 2.0.0-rc.18(solid-js@2.0.0-rc.18)
version: 2.0.0-rc.20(solid-js@2.0.0-rc.20)
solid-js:
specifier: next
version: 2.0.0-rc.18
version: 2.0.0-rc.20
devDependencies:
'@solidjs/testing-library':
specifier: 1.0.0-beta.3
version: 1.0.0-beta.3(@solidjs/web@2.0.0-rc.18(solid-js@2.0.0-rc.18))(solid-js@2.0.0-rc.18)
version: 1.0.0-beta.3(@solidjs/web@2.0.0-rc.20(solid-js@2.0.0-rc.20))(solid-js@2.0.0-rc.20)
'@solidjs/vite-plugin':
specifier: 3.0.0-next.47
version: 3.0.0-next.47(@solidjs/web@2.0.0-rc.18(solid-js@2.0.0-rc.18))(@testing-library/jest-dom@7.0.1(@testing-library/dom@10.4.2)(vitest@5.0.3))(solid-js@2.0.0-rc.18)(supports-color@10.2.2)(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1))
version: 3.0.0-next.47(@solidjs/web@2.0.0-rc.20(solid-js@2.0.0-rc.20))(@testing-library/jest-dom@7.0.1(@testing-library/dom@10.4.2)(vitest@5.0.3))(solid-js@2.0.0-rc.20)(supports-color@10.2.2)(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1))
'@vitest/browser-playwright':
specifier: 5.0.3
version: 5.0.3(playwright@1.58.2)(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1))(vitest@5.0.3)
version: 5.0.3(playwright@1.64.1)(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1))(vitest@5.0.3)
filesystem-routing:
specifier: 0.4.0
version: 0.4.0(supports-color@10.2.2)(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1))
playwright:
specifier: 1.58.2
version: 1.58.2
specifier: 1.64.1
version: 1.64.1
typescript:
specifier: ^6.0.3
version: 6.0.3
@@ -576,7 +576,7 @@ importers:
devDependencies:
'@vitest/browser-playwright':
specifier: 5.0.3
version: 5.0.3(playwright@1.58.2)(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1))(vitest@5.0.3)
version: 5.0.3(playwright@1.64.1)(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1))(vitest@5.0.3)
typescript:
specifier: ^6.0.3
version: 6.0.3
@@ -604,10 +604,10 @@ importers:
devDependencies:
'@vitest/browser-playwright':
specifier: 5.0.3
version: 5.0.3(playwright@1.58.2)(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1))(vitest@5.0.3)
version: 5.0.3(playwright@1.64.1)(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1))(vitest@5.0.3)
playwright:
specifier: 1.58.2
version: 1.58.2
specifier: 1.64.1
version: 1.64.1
typescript:
specifier: ^6.0.3
version: 6.0.3
@@ -630,27 +630,27 @@ importers:
specifier: workspace:*
version: link:../../../packages/svelte
svelte:
specifier: 5.57.2
version: 5.57.2(@typescript-eslint/types@8.69.0)
specifier: 5.57.3
version: 5.57.3(@typescript-eslint/types@8.69.0)
devDependencies:
'@sveltejs/adapter-auto':
specifier: ^8.0.0
version: 8.0.0(@sveltejs/kit@3.1.0(@sveltejs/vite-plugin-svelte@7.3.1(svelte@5.57.2(@typescript-eslint/types@8.69.0))(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1)))(svelte@5.57.2(@typescript-eslint/types@8.69.0))(typescript@6.0.3)(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1)))
version: 8.0.0(@sveltejs/kit@3.1.1(@sveltejs/vite-plugin-svelte@7.3.1(svelte@5.57.3(@typescript-eslint/types@8.69.0))(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1)))(svelte@5.57.3(@typescript-eslint/types@8.69.0))(typescript@6.0.3)(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1)))
'@sveltejs/kit':
specifier: ^3.1.0
version: 3.1.0(@sveltejs/vite-plugin-svelte@7.3.1(svelte@5.57.2(@typescript-eslint/types@8.69.0))(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1)))(svelte@5.57.2(@typescript-eslint/types@8.69.0))(typescript@6.0.3)(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1))
specifier: ^3.1.1
version: 3.1.1(@sveltejs/vite-plugin-svelte@7.3.1(svelte@5.57.3(@typescript-eslint/types@8.69.0))(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1)))(svelte@5.57.3(@typescript-eslint/types@8.69.0))(typescript@6.0.3)(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1))
'@sveltejs/vite-plugin-svelte':
specifier: ^7.3.1
version: 7.3.1(svelte@5.57.2(@typescript-eslint/types@8.69.0))(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1))
version: 7.3.1(svelte@5.57.3(@typescript-eslint/types@8.69.0))(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1))
'@vitest/browser-playwright':
specifier: 5.0.3
version: 5.0.3(playwright@1.58.2)(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1))(vitest@5.0.3)
version: 5.0.3(playwright@1.64.1)(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1))(vitest@5.0.3)
playwright:
specifier: 1.58.2
version: 1.58.2
specifier: 1.64.1
version: 1.64.1
svelte-check:
specifier: ^4.7.7
version: 4.7.7(picomatch@4.0.7)(svelte@5.57.2(@typescript-eslint/types@8.69.0))(typescript@6.0.3)
version: 4.7.7(picomatch@4.0.7)(svelte@5.57.3(@typescript-eslint/types@8.69.0))(typescript@6.0.3)
typescript:
specifier: ^6.0.3
version: 6.0.3
@@ -662,7 +662,7 @@ importers:
version: 5.0.3(@types/node@26.4.1)(@vitest/browser-playwright@5.0.3)(@vitest/coverage-v8@5.0.5)(@vitest/ui@5.0.5)(jsdom@30.1.3)(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1))
vitest-browser-svelte:
specifier: 3.1.0
version: 3.1.0(svelte@5.57.2(@typescript-eslint/types@8.69.0))(vitest@5.0.3)
version: 3.1.0(svelte@5.57.3(@typescript-eslint/types@8.69.0))(vitest@5.0.3)
integrations/lucide-svelte/vite:
dependencies:
@@ -670,12 +670,12 @@ importers:
specifier: workspace:*
version: link:../../../packages/svelte
svelte:
specifier: 5.57.2
version: 5.57.2(@typescript-eslint/types@8.69.0)
specifier: 5.57.3
version: 5.57.3(@typescript-eslint/types@8.69.0)
devDependencies:
'@sveltejs/vite-plugin-svelte':
specifier: ^7.3.1
version: 7.3.1(svelte@5.57.2(@typescript-eslint/types@8.69.0))(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1))
version: 7.3.1(svelte@5.57.3(@typescript-eslint/types@8.69.0))(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1))
'@tsconfig/svelte':
specifier: ^5.0.8
version: 5.0.8
@@ -684,13 +684,13 @@ importers:
version: 26.4.1
'@vitest/browser-playwright':
specifier: 5.0.3
version: 5.0.3(playwright@1.58.2)(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1))(vitest@5.0.3)
version: 5.0.3(playwright@1.64.1)(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1))(vitest@5.0.3)
playwright:
specifier: 1.58.2
version: 1.58.2
specifier: 1.64.1
version: 1.64.1
svelte-check:
specifier: ^4.7.7
version: 4.7.7(picomatch@4.0.7)(svelte@5.57.2(@typescript-eslint/types@8.69.0))(typescript@6.0.3)
version: 4.7.7(picomatch@4.0.7)(svelte@5.57.3(@typescript-eslint/types@8.69.0))(typescript@6.0.3)
typescript:
specifier: ^6.0.3
version: 6.0.3
@@ -702,7 +702,7 @@ importers:
version: 5.0.3(@types/node@26.4.1)(@vitest/browser-playwright@5.0.3)(@vitest/coverage-v8@5.0.5)(@vitest/ui@5.0.5)(jsdom@30.1.3)(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1))
vitest-browser-svelte:
specifier: 3.1.0
version: 3.1.0(svelte@5.57.2(@typescript-eslint/types@8.69.0))(vitest@5.0.3)
version: 3.1.0(svelte@5.57.3(@typescript-eslint/types@8.69.0))(vitest@5.0.3)
integrations/lucide-vue/nuxt:
dependencies:
@@ -724,7 +724,7 @@ importers:
version: 6.0.10(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1))(vue@3.5.44(typescript@6.0.3))
'@vitest/browser-playwright':
specifier: 5.0.3
version: 5.0.3(playwright@1.58.2)(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1))(vitest@5.0.3)
version: 5.0.3(playwright@1.64.1)(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1))(vitest@5.0.3)
typescript:
specifier: ^6.0.3
version: 6.0.3
@@ -761,7 +761,7 @@ importers:
version: 6.0.10(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1))(vue@3.5.44(typescript@6.0.3))
'@vitest/browser-playwright':
specifier: 5.0.3
version: 5.0.3(playwright@1.58.2)(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1))(vitest@5.0.3)
version: 5.0.3(playwright@1.64.1)(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1))(vitest@5.0.3)
typescript:
specifier: ^6.0.3
version: 6.0.3
@@ -798,13 +798,13 @@ importers:
version: 6.0.10(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1))(vue@3.5.44(typescript@6.0.3))
'@vitest/browser-playwright':
specifier: 5.0.3
version: 5.0.3(playwright@1.58.2)(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1))(vitest@5.0.3)
version: 5.0.3(playwright@1.64.1)(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1))(vitest@5.0.3)
'@vue/tsconfig':
specifier: ^0.9.1
version: 0.9.1(typescript@6.0.3)(vue@3.5.44(typescript@6.0.3))
playwright:
specifier: 1.58.2
version: 1.58.2
specifier: 1.64.1
version: 1.64.1
typescript:
specifier: ^6.0.3
version: 6.0.3
@@ -867,7 +867,7 @@ importers:
version: link:../../tools/build-helpers
'@vitest/browser-playwright':
specifier: ^5.0.3
version: 5.0.3(playwright@1.58.2)(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.104.1)(sass@1.104.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1))(vitest@5.0.3)
version: 5.0.3(playwright@1.64.1)(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.104.1)(sass@1.104.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1))(vitest@5.0.3)
angular-eslint:
specifier: 22.5.0
version: 22.5.0(chokidar@5.0.0)(eslint@10.9.1(jiti@2.7.0)(supports-color@10.2.2))(supports-color@10.2.2)(typescript-eslint@8.69.0(eslint@10.9.1(jiti@2.7.0)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3))(typescript@6.0.3)
@@ -1045,19 +1045,19 @@ importers:
version: link:../shared
'@preact/preset-vite':
specifier: ^2.10.6
version: 2.10.6(@babel/core@7.29.7(supports-color@10.2.2))(preact@11.0.2)(rollup@4.65.1)(supports-color@10.2.2)(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1))
version: 2.10.6(@babel/core@7.29.7(supports-color@10.2.2))(preact@11.1.0)(rollup@4.65.1)(supports-color@10.2.2)(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1))
'@testing-library/jest-dom':
specifier: ^7.0.1
version: 7.0.1(@testing-library/dom@10.4.2)(vitest@5.0.3)
'@testing-library/preact':
specifier: ^3.2.6
version: 3.2.6(preact@11.0.2)
version: 3.2.6(preact@11.1.0)
jest-serializer-html:
specifier: ^7.1.0
version: 7.1.0
preact:
specifier: ^11.0.2
version: 11.0.2
specifier: ^11.1.0
version: 11.1.0
rollup:
specifier: ^4.65.0
version: 4.65.1
@@ -1297,19 +1297,19 @@ importers:
version: 6.1.0(@babel/core@7.29.7(supports-color@10.2.2))(@types/babel__core@7.20.5)(rollup@4.65.1)(supports-color@10.2.2)
'@solidjs/testing-library':
specifier: next
version: 1.0.0-rc.2(@solidjs/web@2.0.0-rc.18(solid-js@2.0.0-rc.18))(solid-js@2.0.0-rc.18)
version: 1.0.0-rc.2(@solidjs/web@2.0.0-rc.20(solid-js@2.0.0-rc.20))(solid-js@2.0.0-rc.20)
'@solidjs/vite-plugin':
specifier: next
version: 3.0.0-next.35(@solidjs/web@2.0.0-rc.18(solid-js@2.0.0-rc.18))(@testing-library/jest-dom@7.0.1(@testing-library/dom@10.4.2)(vitest@5.0.3))(solid-js@2.0.0-rc.18)(supports-color@10.2.2)(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1))
version: 3.0.0-next.35(@solidjs/web@2.0.0-rc.20(solid-js@2.0.0-rc.20))(@testing-library/jest-dom@7.0.1(@testing-library/dom@10.4.2)(vitest@5.0.3))(solid-js@2.0.0-rc.20)(supports-color@10.2.2)(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1))
'@solidjs/web':
specifier: next
version: 2.0.0-rc.18(solid-js@2.0.0-rc.18)
version: 2.0.0-rc.20(solid-js@2.0.0-rc.20)
'@testing-library/jest-dom':
specifier: ^7.0.1
version: 7.0.1(@testing-library/dom@10.4.2)(vitest@5.0.3)
babel-preset-solid:
specifier: next
version: 2.0.0-rc.2(@babel/core@7.29.7(supports-color@10.2.2))(solid-js@2.0.0-rc.18)
version: 2.0.0-rc.2(@babel/core@7.29.7(supports-color@10.2.2))(solid-js@2.0.0-rc.20)
esbuild:
specifier: ^0.28.2
version: 0.28.2
@@ -1324,7 +1324,7 @@ importers:
version: 6.5.1(rollup@4.65.1)(typescript@6.0.3)
solid-js:
specifier: next
version: 2.0.0-rc.18
version: 2.0.0-rc.20
typescript:
specifier: ^6.0.3
version: 6.0.3
@@ -1341,17 +1341,17 @@ importers:
specifier: workspace:*
version: link:../../tools/build-helpers
'@sveltejs/package':
specifier: ^3.0.1
version: 3.0.1(svelte@5.57.2(@typescript-eslint/types@8.69.0))(typescript@6.0.3)
specifier: ^3.0.2
version: 3.0.2(svelte@5.57.3(@typescript-eslint/types@8.69.0))(typescript@6.0.3)
'@sveltejs/vite-plugin-svelte':
specifier: ^7.3.1
version: 7.3.1(svelte@5.57.2(@typescript-eslint/types@8.69.0))(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1))
version: 7.3.1(svelte@5.57.3(@typescript-eslint/types@8.69.0))(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1))
'@testing-library/jest-dom':
specifier: ^7.0.1
version: 7.0.1(@testing-library/dom@10.4.2)(vitest@5.0.3)
'@testing-library/svelte':
specifier: ^5.4.2
version: 5.4.2(svelte@5.57.2(@typescript-eslint/types@8.69.0))(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1))(vitest@5.0.3)
version: 5.4.2(svelte@5.57.3(@typescript-eslint/types@8.69.0))(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1))(vitest@5.0.3)
'@tsconfig/svelte':
specifier: ^5.0.8
version: 5.0.8
@@ -1362,14 +1362,14 @@ importers:
specifier: ^30.1.3
version: 30.1.3
svelte:
specifier: ^5.57.2
version: 5.57.2(@typescript-eslint/types@8.69.0)
specifier: ^5.57.3
version: 5.57.3(@typescript-eslint/types@8.69.0)
svelte-check:
specifier: ^4.7.7
version: 4.7.7(picomatch@4.0.7)(svelte@5.57.2(@typescript-eslint/types@8.69.0))(typescript@6.0.3)
version: 4.7.7(picomatch@4.0.7)(svelte@5.57.3(@typescript-eslint/types@8.69.0))(typescript@6.0.3)
svelte-preprocess:
specifier: ^6.0.5
version: 6.0.5(@babel/core@7.29.7(supports-color@10.2.2))(less@4.9.1(supports-color@10.2.2))(postcss@8.5.32)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(svelte@5.57.2(@typescript-eslint/types@8.69.0))(typescript@6.0.3)
version: 6.0.5(@babel/core@7.29.7(supports-color@10.2.2))(less@4.9.1(supports-color@10.2.2))(postcss@8.5.32)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(svelte@5.57.3(@typescript-eslint/types@8.69.0))(typescript@6.0.3)
typescript:
specifier: ^6.0.3
version: 6.0.3
@@ -5905,8 +5905,8 @@ packages:
filesystem-routing:
optional: true
'@solidjs/signals@2.0.0-rc.19':
resolution: {integrity: sha512-Epg4lyelYZnwG152q1U7lXAXp/2/jaQdaRbzh60rcOelSwmCMf/WN6FQuUEUwbn1p/QNyoJzdGSKPajkVe3zOg==}
'@solidjs/signals@2.0.0-rc.20':
resolution: {integrity: sha512-BIL5dKm0dAtPGsCEuLSNw60spDbmYG5QFK+aHUxPIgPLweA8IeJKd62DiqqqU/jqX0x39ty31GoP1n+ZINkrcg==}
engines: {node: '>=22.12.0'}
'@solidjs/start@2.0.5':
@@ -5973,11 +5973,11 @@ packages:
'@testing-library/jest-dom':
optional: true
'@solidjs/web@2.0.0-rc.18':
resolution: {integrity: sha512-qtxuskii4N/gMipmg94yfPSJ0djwVWF+Elrdhtdb/8ZThvPc6RI/edY6guEMwdx7OADa1f9cQ0MwQe7kDW+Vwg==}
'@solidjs/web@2.0.0-rc.20':
resolution: {integrity: sha512-ACGUZ1XBNxiHnWW274na+1JZfuIhiS/BN5XM72wVKNYSopR/NyjVPR4O/nvshtbYlEk1lKJ9d1uBaXDaz6ddYg==}
engines: {node: '>=22.12.0'}
peerDependencies:
solid-js: ^2.0.0-rc.18
solid-js: ^2.0.0-rc.20
'@speed-highlight/core@1.2.24':
resolution: {integrity: sha512-qeW2e1l78afw8VhRPfPQ1Gjj+KU5XFQ/OFV5ti6eTa9bruO7mJyZtA4vw0ofqmA3tKCkROE9xLk3VZoeRc98nw==}
@@ -5998,8 +5998,8 @@ packages:
peerDependencies:
'@sveltejs/kit': ^3.0.0-next.0
'@sveltejs/kit@3.1.0':
resolution: {integrity: sha512-JTWlq2HQlkqx6vIoxhC0R6sc4WVqbQoRyEmr5YlqKmiYbzY1U3awtSWTmjMLlS056a49AmkQR6rnNANXIE8B0Q==}
'@sveltejs/kit@3.1.1':
resolution: {integrity: sha512-BiEMvekYXE9Gu/YhWJ/yJ0WDLH1PX/dmjuAeFp5rrtdmgdzkjt7DvimlSP+/U4tgposl7pkE20luHpcnc6BgRw==}
engines: {node: '>=22.17'}
hasBin: true
peerDependencies:
@@ -6018,8 +6018,8 @@ packages:
resolution: {integrity: sha512-VT3qmUb8pRV2QrZjd8iAmtg8lf4W0TIjZbvXtz5MKei/q96teWZgGJyyidJzOjzZzvdq616eSRVeMYIQChUTAQ==}
engines: {node: '>= 18.0.0'}
'@sveltejs/package@3.0.1':
resolution: {integrity: sha512-QblEaqd2r685OZWVO4I0DLAKUOozIp7YxvahxPYntv+4zzMQbisX2vubBEg2d8riF+bPF13AqTzMFlhyuSlaRQ==}
'@sveltejs/package@3.0.2':
resolution: {integrity: sha512-1HhN/Lgw1Bqyu7T6fWILt6euTyt+h+yBH2yUVYxTkGVUdIV1Xsp/gGaHnfBkD584i1fXte1cR4+zYtUsQC/F6A==}
engines: {node: '>=22'}
hasBin: true
peerDependencies:
@@ -6355,6 +6355,9 @@ packages:
'@types/estree-jsx@1.0.5':
resolution: {integrity: sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==}
'@types/estree@1.0.10':
resolution: {integrity: sha512-lTyOMnOcmRBzdCv6/4zUZCrEhV0xrqQiUZBZtVcbmLHBXKLnN8q89v/wKRF/Q0HbwVsqbIG3o5HDoFl9sduM+g==}
'@types/estree@1.0.9':
resolution: {integrity: sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==}
@@ -7900,6 +7903,10 @@ packages:
resolution: {integrity: sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==}
engines: {node: '>= 20.19.0'}
chokidar@6.0.0:
resolution: {integrity: sha512-Ec2Z7wpcKBiMpR7DxteoqS/sq5G5d2A4fpxzPv6+fD7xNNdrTghn7L11YwV5EN1B3i72Erc3XVT5FkWIDx90+A==}
engines: {node: '>= 22.22'}
chownr@3.0.0:
resolution: {integrity: sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==}
engines: {node: '>=18'}
@@ -9147,11 +9154,6 @@ packages:
fs.realpath@1.0.0:
resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==}
fsevents@2.3.2:
resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==}
engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
os: [darwin]
fsevents@2.3.3:
resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
@@ -11196,14 +11198,14 @@ packages:
pkg-types@2.4.0:
resolution: {integrity: sha512-07Fys7iVx0X6TcviMOgogM1Lk33ZyqOezMnU79S+kffWqwolG/5W9V8EgQSeYCIfFTYVgssRbnH630Oa2+soBA==}
playwright-core@1.58.2:
resolution: {integrity: sha512-yZkEtftgwS8CsfYo7nm0KE8jsvm6i/PTgVtB8DL726wNf6H2IMsDuxCpJj59KDaxCtSnrWan2AeDqM7JBaultg==}
engines: {node: '>=18'}
playwright-core@1.64.1:
resolution: {integrity: sha512-BC4s8y6SEVA6Q1rSxZTto8hI1KUI3xXlHGZgvGqP4IqPdI/a6FX9H29IDNz7vKo9l21b6LfYosScPL6M3xxyDQ==}
engines: {node: '>=20'}
hasBin: true
playwright@1.58.2:
resolution: {integrity: sha512-vA30H8Nvkq/cPBnNw4Q8TWz1EJyqgpuinBcHET0YVJVFldr8JDNiU9LaWAE1KqSkRYazuaBhTpB5ZzShOezQ6A==}
engines: {node: '>=18'}
playwright@1.64.1:
resolution: {integrity: sha512-HCrVhHr5QQuwYoswEUGTb7gGp522yflbv/ST8nF4sFWGuLjQCt17Q/EubpGGSNKYn1tsTCPZxqHhHCfVURu7UA==}
engines: {node: '>=20'}
hasBin: true
pngjs@3.4.0:
@@ -11264,8 +11266,8 @@ packages:
preact-render-to-string:
optional: true
preact@11.0.2:
resolution: {integrity: sha512-ofG+Lqznbt13JKDjdWPLTo5ONBqcNgidqnLRzJBG6PZjzGXOLRd5y9r448+HUofTyDbgKWVrPhHP0IgcxEZslQ==}
preact@11.1.0:
resolution: {integrity: sha512-hz1VsjWx5pSYPDVEzb9w+XyOmQpP1qW/ZEaMiYm+C8ykJr8KP+TKGZIbCW0QmZ/Yr/jg3XkZoziEWn9iWHZ9Mw==}
peerDependencies:
preact-render-to-string: '>=6.7.0'
peerDependenciesMeta:
@@ -11470,8 +11472,8 @@ packages:
resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==}
engines: {node: '>= 14.18.0'}
readdirp@5.0.0:
resolution: {integrity: sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==}
readdirp@5.1.1:
resolution: {integrity: sha512-Kko+Y5XQ6fM+Ce3dq3m9YGxnacYZYl9cA1wZjaF3Vbry2L3i1qVg8+CAgNPsXRArPMUMCaOR7oa9Nqntc43JKA==}
engines: {node: '>= 20.19.0'}
redent@3.0.0:
@@ -12225,8 +12227,8 @@ packages:
solid-js@1.9.15:
resolution: {integrity: sha512-EeiY2xfpZJqPLjXspVEKjAII4yv8NyG//NxZ3IpOFHdUNnnTyL0uJOeS9LWGvA7cFCz5y94cjFwYlmw5Luncsg==}
solid-js@2.0.0-rc.18:
resolution: {integrity: sha512-g4KjUQUjfqvqHYnBddN5nVAF7DFcDjtuH+NeDu/26vx6SlSDiqBJS8jsNag6VpdKAnfK8oLfphogEhXtM4UOyw==}
solid-js@2.0.0-rc.20:
resolution: {integrity: sha512-FxaEI7LHupehFoR9j2CfJAGCoRgiKgeNlzii4szUS6lnD8RkpdtvX1k6WFG71vl5bskXRRsmEQVAXsbIemQOuw==}
engines: {node: '>=22.12.0'}
solid-refresh@0.6.3:
@@ -12531,14 +12533,14 @@ packages:
typescript:
optional: true
svelte2tsx@0.7.61:
resolution: {integrity: sha512-EpQ/+UHITBULeUojx/LLD3uTYasZXcX1BrqlrzfLUnT9vdUhaOWK59a3ryWcFU8L0sY1SP+gRhJ2Beiis98+qw==}
svelte2tsx@0.7.62:
resolution: {integrity: sha512-ZXfsmL0jzAs01ho0w5z5LSIC2WgSdpTF0QCwaXLq7oHgho4P9fTgHlLp1pKAx6/xtVYRSW5nGH5ZRpEHZCqliA==}
peerDependencies:
svelte: ^3.55 || ^4.0.0-next.0 || ^4.0 || ^5.0.0-next.0
typescript: ^4.9.4 || ^5.0.0 || ^6.0.0
svelte@5.57.2:
resolution: {integrity: sha512-1YiPCAXT0Ct6g1vOMmSLa0Nsc3QRMvtDF32ihgglGVrugIuIK38RyDiFNXVDhtQ81TJjSO57NdMw6DyYLqSGDQ==}
svelte@5.57.3:
resolution: {integrity: sha512-5mAftM3SoDV9X0zdF386F9p2pv8iKOwi/KfBS1XnBAkVCKFzVOLHUoa8iGWAt4buoicLmyWVRpuuD5wplXOQsg==}
engines: {node: '>=18'}
svg-path-commander@2.3.3:
@@ -16066,7 +16068,7 @@ snapshots:
'@html-eslint/types@0.65.0':
dependencies:
'@types/css-tree': 2.3.11
'@types/estree': 1.0.9
'@types/estree': 1.0.10
es-html-parser: 0.3.1
'@humanfs/core@0.19.2':
@@ -17742,12 +17744,12 @@ snapshots:
'@poppinss/exception@1.2.3': {}
'@preact/preset-vite@2.10.6(@babel/core@7.29.7(supports-color@10.2.2))(preact@11.0.2)(rollup@4.65.1)(supports-color@10.2.2)(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1))':
'@preact/preset-vite@2.10.6(@babel/core@7.29.7(supports-color@10.2.2))(preact@11.1.0)(rollup@4.65.1)(supports-color@10.2.2)(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1))':
dependencies:
'@babel/core': 7.29.7(supports-color@10.2.2)
'@babel/plugin-transform-react-jsx': 7.29.7(@babel/core@7.29.7(supports-color@10.2.2))(supports-color@10.2.2)
'@babel/plugin-transform-react-jsx-development': 7.29.7(@babel/core@7.29.7(supports-color@10.2.2))(supports-color@10.2.2)
'@prefresh/vite': 2.4.12(preact@11.0.2)(supports-color@10.2.2)(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1))
'@prefresh/vite': 2.4.12(preact@11.1.0)(supports-color@10.2.2)(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1))
'@rollup/pluginutils': 5.4.0(rollup@4.65.1)
babel-plugin-transform-hook-names: 1.0.2(@babel/core@7.29.7(supports-color@10.2.2))
debug: 4.4.3(supports-color@10.2.2)
@@ -17763,20 +17765,20 @@ snapshots:
'@prefresh/babel-plugin@0.5.3': {}
'@prefresh/core@1.5.11(preact@11.0.2)':
'@prefresh/core@1.5.11(preact@11.1.0)':
dependencies:
preact: 11.0.2
preact: 11.1.0
'@prefresh/utils@1.2.1': {}
'@prefresh/vite@2.4.12(preact@11.0.2)(supports-color@10.2.2)(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1))':
'@prefresh/vite@2.4.12(preact@11.1.0)(supports-color@10.2.2)(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1))':
dependencies:
'@babel/core': 7.29.7(supports-color@10.2.2)
'@prefresh/babel-plugin': 0.5.3
'@prefresh/core': 1.5.11(preact@11.0.2)
'@prefresh/core': 1.5.11(preact@11.1.0)
'@prefresh/utils': 1.2.1
'@rollup/pluginutils': 4.2.1
preact: 11.0.2
preact: 11.1.0
vite: 8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1)
transitivePeerDependencies:
- supports-color
@@ -18459,23 +18461,23 @@ snapshots:
dependencies:
solid-js: 1.9.15
'@solidjs/meta@1.0.0-next.2(@solidjs/web@2.0.0-rc.18(solid-js@2.0.0-rc.18))(solid-js@2.0.0-rc.18)':
'@solidjs/meta@1.0.0-next.2(@solidjs/web@2.0.0-rc.20(solid-js@2.0.0-rc.20))(solid-js@2.0.0-rc.20)':
dependencies:
'@solidjs/web': 2.0.0-rc.18(solid-js@2.0.0-rc.18)
solid-js: 2.0.0-rc.18
'@solidjs/web': 2.0.0-rc.20(solid-js@2.0.0-rc.20)
solid-js: 2.0.0-rc.20
'@solidjs/router@1.0.0(solid-js@1.9.15)':
dependencies:
solid-js: 1.9.15
'@solidjs/router@2.0.0-next.34(@solidjs/web@2.0.0-rc.18(solid-js@2.0.0-rc.18))(filesystem-routing@0.4.0(supports-color@10.2.2)(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1)))(solid-js@2.0.0-rc.18)':
'@solidjs/router@2.0.0-next.34(@solidjs/web@2.0.0-rc.20(solid-js@2.0.0-rc.20))(filesystem-routing@0.4.0(supports-color@10.2.2)(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1)))(solid-js@2.0.0-rc.20)':
dependencies:
'@solidjs/web': 2.0.0-rc.18(solid-js@2.0.0-rc.18)
solid-js: 2.0.0-rc.18
'@solidjs/web': 2.0.0-rc.20(solid-js@2.0.0-rc.20)
solid-js: 2.0.0-rc.20
optionalDependencies:
filesystem-routing: 0.4.0(supports-color@10.2.2)(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1))
'@solidjs/signals@2.0.0-rc.19': {}
'@solidjs/signals@2.0.0-rc.20': {}
'@solidjs/start@2.0.5(@solidjs/router@1.0.0(solid-js@1.9.15))(@testing-library/jest-dom@7.0.1(@testing-library/dom@10.4.2)(vitest@5.0.3))(crossws@0.4.12(srvx@1.0.5))(ocache@0.3.0)(supports-color@10.2.2)(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1))':
dependencies:
@@ -18520,28 +18522,28 @@ snapshots:
optionalDependencies:
'@solidjs/router': 1.0.0(solid-js@1.9.15)
'@solidjs/testing-library@1.0.0-beta.3(@solidjs/web@2.0.0-rc.18(solid-js@2.0.0-rc.18))(solid-js@2.0.0-rc.18)':
'@solidjs/testing-library@1.0.0-beta.3(@solidjs/web@2.0.0-rc.20(solid-js@2.0.0-rc.20))(solid-js@2.0.0-rc.20)':
dependencies:
'@solidjs/web': 2.0.0-rc.18(solid-js@2.0.0-rc.18)
'@solidjs/web': 2.0.0-rc.20(solid-js@2.0.0-rc.20)
'@testing-library/dom': 10.4.2
solid-js: 2.0.0-rc.18
solid-js: 2.0.0-rc.20
'@solidjs/testing-library@1.0.0-rc.2(@solidjs/web@2.0.0-rc.18(solid-js@2.0.0-rc.18))(solid-js@2.0.0-rc.18)':
'@solidjs/testing-library@1.0.0-rc.2(@solidjs/web@2.0.0-rc.20(solid-js@2.0.0-rc.20))(solid-js@2.0.0-rc.20)':
dependencies:
'@solidjs/web': 2.0.0-rc.18(solid-js@2.0.0-rc.18)
'@solidjs/web': 2.0.0-rc.20(solid-js@2.0.0-rc.20)
'@testing-library/dom': 10.4.2
solid-js: 2.0.0-rc.18
solid-js: 2.0.0-rc.20
'@solidjs/vite-plugin@3.0.0-next.35(@solidjs/web@2.0.0-rc.18(solid-js@2.0.0-rc.18))(@testing-library/jest-dom@7.0.1(@testing-library/dom@10.4.2)(vitest@5.0.3))(solid-js@2.0.0-rc.18)(supports-color@10.2.2)(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1))':
'@solidjs/vite-plugin@3.0.0-next.35(@solidjs/web@2.0.0-rc.20(solid-js@2.0.0-rc.20))(@testing-library/jest-dom@7.0.1(@testing-library/dom@10.4.2)(vitest@5.0.3))(solid-js@2.0.0-rc.20)(supports-color@10.2.2)(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1))':
dependencies:
'@ampproject/remapping': 2.3.0
'@babel/core': 7.29.7(supports-color@10.2.2)
'@solidjs/babel-plugin': 2.0.0-rc.13(@babel/core@7.29.7(supports-color@10.2.2))
'@solidjs/compiler': 2.0.0-rc.13
'@solidjs/web': 2.0.0-rc.18(solid-js@2.0.0-rc.18)
'@solidjs/web': 2.0.0-rc.20(solid-js@2.0.0-rc.20)
'@types/babel__core': 7.20.5
merge-anything: 5.1.7
solid-js: 2.0.0-rc.18
solid-js: 2.0.0-rc.20
vite: 8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1)
vitefu: 1.1.3(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1))
optionalDependencies:
@@ -18550,16 +18552,16 @@ snapshots:
- '@tsrx/core'
- supports-color
'@solidjs/vite-plugin@3.0.0-next.47(@solidjs/web@2.0.0-rc.18(solid-js@2.0.0-rc.18))(@testing-library/jest-dom@7.0.1(@testing-library/dom@10.4.2)(vitest@5.0.3))(solid-js@2.0.0-rc.18)(supports-color@10.2.2)(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1))':
'@solidjs/vite-plugin@3.0.0-next.47(@solidjs/web@2.0.0-rc.20(solid-js@2.0.0-rc.20))(@testing-library/jest-dom@7.0.1(@testing-library/dom@10.4.2)(vitest@5.0.3))(solid-js@2.0.0-rc.20)(supports-color@10.2.2)(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1))':
dependencies:
'@ampproject/remapping': 2.3.0
'@babel/core': 7.29.7(supports-color@10.2.2)
'@solidjs/babel-plugin': 2.0.0-rc.13(@babel/core@7.29.7(supports-color@10.2.2))
'@solidjs/compiler': 2.0.0-rc.13
'@solidjs/web': 2.0.0-rc.18(solid-js@2.0.0-rc.18)
'@solidjs/web': 2.0.0-rc.20(solid-js@2.0.0-rc.20)
'@types/babel__core': 7.20.5
merge-anything: 5.1.7
solid-js: 2.0.0-rc.18
solid-js: 2.0.0-rc.20
vite: 8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1)
vitefu: 1.1.3(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1))
optionalDependencies:
@@ -18568,11 +18570,11 @@ snapshots:
- '@tsrx/core'
- supports-color
'@solidjs/web@2.0.0-rc.18(solid-js@2.0.0-rc.18)':
'@solidjs/web@2.0.0-rc.20(solid-js@2.0.0-rc.20)':
dependencies:
seroval: 1.7.0
seroval-plugins: 1.7.0(seroval@1.7.0)
solid-js: 2.0.0-rc.18
solid-js: 2.0.0-rc.20
'@speed-highlight/core@1.2.24': {}
@@ -18584,43 +18586,43 @@ snapshots:
dependencies:
acorn: 8.19.0
'@sveltejs/adapter-auto@8.0.0(@sveltejs/kit@3.1.0(@sveltejs/vite-plugin-svelte@7.3.1(svelte@5.57.2(@typescript-eslint/types@8.69.0))(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1)))(svelte@5.57.2(@typescript-eslint/types@8.69.0))(typescript@6.0.3)(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1)))':
'@sveltejs/adapter-auto@8.0.0(@sveltejs/kit@3.1.1(@sveltejs/vite-plugin-svelte@7.3.1(svelte@5.57.3(@typescript-eslint/types@8.69.0))(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1)))(svelte@5.57.3(@typescript-eslint/types@8.69.0))(typescript@6.0.3)(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1)))':
dependencies:
'@sveltejs/kit': 3.1.0(@sveltejs/vite-plugin-svelte@7.3.1(svelte@5.57.2(@typescript-eslint/types@8.69.0))(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1)))(svelte@5.57.2(@typescript-eslint/types@8.69.0))(typescript@6.0.3)(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1))
'@sveltejs/kit': 3.1.1(@sveltejs/vite-plugin-svelte@7.3.1(svelte@5.57.3(@typescript-eslint/types@8.69.0))(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1)))(svelte@5.57.3(@typescript-eslint/types@8.69.0))(typescript@6.0.3)(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1))
'@sveltejs/kit@3.1.0(@sveltejs/vite-plugin-svelte@7.3.1(svelte@5.57.2(@typescript-eslint/types@8.69.0))(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1)))(svelte@5.57.2(@typescript-eslint/types@8.69.0))(typescript@6.0.3)(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1))':
'@sveltejs/kit@3.1.1(@sveltejs/vite-plugin-svelte@7.3.1(svelte@5.57.3(@typescript-eslint/types@8.69.0))(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1)))(svelte@5.57.3(@typescript-eslint/types@8.69.0))(typescript@6.0.3)(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1))':
dependencies:
'@rolldown/pluginutils': 1.0.1
'@standard-schema/spec': 1.1.0
'@sveltejs/vite-plugin-svelte': 7.3.1(svelte@5.57.2(@typescript-eslint/types@8.69.0))(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1))
'@sveltejs/vite-plugin-svelte': 7.3.1(svelte@5.57.3(@typescript-eslint/types@8.69.0))(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1))
cookie: 2.0.1
devalue: 5.9.4
esm-env: 1.2.2
magic-string: 1.4.5
mrmime: 2.0.1
sirv: 3.0.2
svelte: 5.57.2(@typescript-eslint/types@8.69.0)
svelte: 5.57.3(@typescript-eslint/types@8.69.0)
vite: 8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1)
optionalDependencies:
typescript: 6.0.3
'@sveltejs/load-config@0.2.3': {}
'@sveltejs/package@3.0.1(svelte@5.57.2(@typescript-eslint/types@8.69.0))(typescript@6.0.3)':
'@sveltejs/package@3.0.2(svelte@5.57.3(@typescript-eslint/types@8.69.0))(typescript@6.0.3)':
dependencies:
'@sveltejs/load-config': 0.2.3
chokidar: 5.0.0
svelte: 5.57.2(@typescript-eslint/types@8.69.0)
svelte2tsx: 0.7.61(svelte@5.57.2(@typescript-eslint/types@8.69.0))(typescript@6.0.3)
chokidar: 6.0.0
svelte: 5.57.3(@typescript-eslint/types@8.69.0)
svelte2tsx: 0.7.62(svelte@5.57.3(@typescript-eslint/types@8.69.0))(typescript@6.0.3)
optionalDependencies:
typescript: 6.0.3
'@sveltejs/vite-plugin-svelte@7.3.1(svelte@5.57.2(@typescript-eslint/types@8.69.0))(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1))':
'@sveltejs/vite-plugin-svelte@7.3.1(svelte@5.57.3(@typescript-eslint/types@8.69.0))(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1))':
dependencies:
deepmerge: 4.3.1
magic-string: 1.4.5
obug: 2.2.1
svelte: 5.57.2(@typescript-eslint/types@8.69.0)
svelte: 5.57.3(@typescript-eslint/types@8.69.0)
vite: 8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1)
vitefu: 1.1.3(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1))
@@ -18964,10 +18966,10 @@ snapshots:
optionalDependencies:
vitest: 5.0.3(@types/node@26.4.1)(@vitest/browser-playwright@5.0.3)(@vitest/coverage-v8@5.0.5)(@vitest/ui@5.0.5)(jsdom@30.1.3)(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1))
'@testing-library/preact@3.2.6(preact@11.0.2)':
'@testing-library/preact@3.2.6(preact@11.1.0)':
dependencies:
'@testing-library/dom': 10.4.2
preact: 11.0.2
preact: 11.1.0
'@testing-library/react@16.3.3(@testing-library/dom@10.4.2)(@types/react-dom@19.3.0(@types/react@19.3.0))(@types/react@19.3.0)(react-dom@19.3.1(react@19.3.1))(react@19.3.1)':
dependencies:
@@ -18979,15 +18981,15 @@ snapshots:
'@types/react': 19.3.0
'@types/react-dom': 19.3.0(@types/react@19.3.0)
'@testing-library/svelte-core@1.1.3(svelte@5.57.2(@typescript-eslint/types@8.69.0))':
'@testing-library/svelte-core@1.1.3(svelte@5.57.3(@typescript-eslint/types@8.69.0))':
dependencies:
svelte: 5.57.2(@typescript-eslint/types@8.69.0)
svelte: 5.57.3(@typescript-eslint/types@8.69.0)
'@testing-library/svelte@5.4.2(svelte@5.57.2(@typescript-eslint/types@8.69.0))(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1))(vitest@5.0.3)':
'@testing-library/svelte@5.4.2(svelte@5.57.3(@typescript-eslint/types@8.69.0))(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1))(vitest@5.0.3)':
dependencies:
'@testing-library/dom': 10.4.2
'@testing-library/svelte-core': 1.1.3(svelte@5.57.2(@typescript-eslint/types@8.69.0))
svelte: 5.57.2(@typescript-eslint/types@8.69.0)
'@testing-library/svelte-core': 1.1.3(svelte@5.57.3(@typescript-eslint/types@8.69.0))
svelte: 5.57.3(@typescript-eslint/types@8.69.0)
optionalDependencies:
vite: 8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1)
vitest: 5.0.3(@types/node@26.4.1)(@vitest/browser-playwright@5.0.3)(@vitest/coverage-v8@5.0.5)(@vitest/ui@5.0.5)(jsdom@30.1.3)(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1))
@@ -19060,7 +19062,9 @@ snapshots:
'@types/estree-jsx@1.0.5':
dependencies:
'@types/estree': 1.0.9
'@types/estree': 1.0.10
'@types/estree@1.0.10': {}
'@types/estree@1.0.9': {}
@@ -19542,11 +19546,11 @@ snapshots:
vite: 8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1)
vue: 3.5.44(typescript@6.0.3)
'@vitest/browser-playwright@5.0.3(playwright@1.58.2)(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.104.1)(sass@1.104.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1))(vitest@5.0.3)':
'@vitest/browser-playwright@5.0.3(playwright@1.64.1)(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.104.1)(sass@1.104.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1))(vitest@5.0.3)':
dependencies:
'@vitest/browser': 5.0.3(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.104.1)(sass@1.104.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1))(vitest@5.0.3)
'@vitest/mocker': 5.0.3(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.104.1)(sass@1.104.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1))
playwright: 1.58.2
playwright: 1.64.1
tinyrainbow: 3.2.0
vitest: 5.0.3(@types/node@26.4.1)(@vitest/browser-playwright@5.0.3)(@vitest/coverage-v8@5.0.5(vitest@5.0.3))(@vitest/ui@5.0.5(vitest@5.0.3))(jsdom@30.1.3)(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.104.1)(sass@1.104.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1))
transitivePeerDependencies:
@@ -19555,11 +19559,11 @@ snapshots:
- utf-8-validate
- vite
'@vitest/browser-playwright@5.0.3(playwright@1.58.2)(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1))(vitest@5.0.3)':
'@vitest/browser-playwright@5.0.3(playwright@1.64.1)(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1))(vitest@5.0.3)':
dependencies:
'@vitest/browser': 5.0.3(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1))(vitest@5.0.3)
'@vitest/mocker': 5.0.3(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1))
playwright: 1.58.2
playwright: 1.64.1
tinyrainbow: 3.2.0
vitest: 5.0.3(@types/node@26.4.1)(@vitest/browser-playwright@5.0.3)(@vitest/coverage-v8@5.0.5)(@vitest/ui@5.0.5)(jsdom@30.1.3)(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1))
transitivePeerDependencies:
@@ -20467,12 +20471,12 @@ snapshots:
optionalDependencies:
solid-js: 1.9.15
babel-preset-solid@2.0.0-rc.2(@babel/core@7.29.7(supports-color@10.2.2))(solid-js@2.0.0-rc.18):
babel-preset-solid@2.0.0-rc.2(@babel/core@7.29.7(supports-color@10.2.2))(solid-js@2.0.0-rc.20):
dependencies:
'@babel/core': 7.29.7(supports-color@10.2.2)
'@dom-expressions/babel-plugin-jsx': 0.50.0-next.44(@babel/core@7.29.7(supports-color@10.2.2))
optionalDependencies:
solid-js: 2.0.0-rc.18
solid-js: 2.0.0-rc.20
bail@2.0.2: {}
@@ -20765,7 +20769,11 @@ snapshots:
chokidar@5.0.0:
dependencies:
readdirp: 5.0.0
readdirp: 5.1.1
chokidar@6.0.0:
dependencies:
readdirp: 5.1.1
chownr@3.0.0: {}
@@ -21698,7 +21706,7 @@ snapshots:
eslint-scope@9.1.2:
dependencies:
'@types/esrecurse': 4.3.1
'@types/estree': 1.0.9
'@types/estree': 1.0.10
esrecurse: 4.3.0
estraverse: 5.3.0
@@ -21787,7 +21795,7 @@ snapshots:
estree-walker@3.0.3:
dependencies:
'@types/estree': 1.0.9
'@types/estree': 1.0.10
esutils@2.0.3: {}
@@ -22112,9 +22120,6 @@ snapshots:
fs.realpath@1.0.0: {}
fsevents@2.3.2:
optional: true
fsevents@2.3.3:
optional: true
@@ -22727,11 +22732,11 @@ snapshots:
is-reference@1.2.1:
dependencies:
'@types/estree': 1.0.9
'@types/estree': 1.0.10
is-reference@3.0.3:
dependencies:
'@types/estree': 1.0.9
'@types/estree': 1.0.10
is-regex@1.2.1:
dependencies:
@@ -24831,13 +24836,11 @@ snapshots:
exsolve: 1.2.0
pathe: 2.0.3
playwright-core@1.58.2: {}
playwright-core@1.64.1: {}
playwright@1.58.2:
playwright@1.64.1:
dependencies:
playwright-core: 1.58.2
optionalDependencies:
fsevents: 2.3.2
playwright-core: 1.64.1
pngjs@3.4.0: {}
@@ -24878,7 +24881,7 @@ snapshots:
preact@10.29.8: {}
preact@11.0.2: {}
preact@11.1.0: {}
prelude-ls@1.2.1: {}
@@ -25103,7 +25106,7 @@ snapshots:
readdirp@4.1.2: {}
readdirp@5.0.0: {}
readdirp@5.1.1: {}
redent@3.0.0:
dependencies:
@@ -26060,9 +26063,9 @@ snapshots:
seroval: 1.5.6
seroval-plugins: 1.5.6(seroval@1.5.6)
solid-js@2.0.0-rc.18:
solid-js@2.0.0-rc.20:
dependencies:
'@solidjs/signals': 2.0.0-rc.19
'@solidjs/signals': 2.0.0-rc.20
csstype: 3.2.3
seroval: 1.7.0
seroval-plugins: 1.7.0(seroval@1.7.0)
@@ -26337,7 +26340,7 @@ snapshots:
supports-preserve-symlinks-flag@1.0.0: {}
svelte-check@4.7.7(picomatch@4.0.7)(svelte@5.57.2(@typescript-eslint/types@8.69.0))(typescript@6.0.3):
svelte-check@4.7.7(picomatch@4.0.7)(svelte@5.57.3(@typescript-eslint/types@8.69.0))(typescript@6.0.3):
dependencies:
'@jridgewell/trace-mapping': 0.3.31
'@sveltejs/load-config': 0.2.3
@@ -26345,14 +26348,14 @@ snapshots:
fdir: 6.5.0(picomatch@4.0.7)
picocolors: 1.1.1
sade: 1.8.1
svelte: 5.57.2(@typescript-eslint/types@8.69.0)
svelte: 5.57.3(@typescript-eslint/types@8.69.0)
typescript: 6.0.3
transitivePeerDependencies:
- picomatch
svelte-preprocess@6.0.5(@babel/core@7.29.7(supports-color@10.2.2))(less@4.9.1(supports-color@10.2.2))(postcss@8.5.32)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(svelte@5.57.2(@typescript-eslint/types@8.69.0))(typescript@6.0.3):
svelte-preprocess@6.0.5(@babel/core@7.29.7(supports-color@10.2.2))(less@4.9.1(supports-color@10.2.2))(postcss@8.5.32)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(svelte@5.57.3(@typescript-eslint/types@8.69.0))(typescript@6.0.3):
dependencies:
svelte: 5.57.2(@typescript-eslint/types@8.69.0)
svelte: 5.57.3(@typescript-eslint/types@8.69.0)
optionalDependencies:
'@babel/core': 7.29.7(supports-color@10.2.2)
less: 4.9.1(supports-color@10.2.2)
@@ -26361,19 +26364,19 @@ snapshots:
stylus: 0.56.0(supports-color@10.2.2)
typescript: 6.0.3
svelte2tsx@0.7.61(svelte@5.57.2(@typescript-eslint/types@8.69.0))(typescript@6.0.3):
svelte2tsx@0.7.62(svelte@5.57.3(@typescript-eslint/types@8.69.0))(typescript@6.0.3):
dependencies:
dedent-js: 1.0.1
scule: 1.3.0
svelte: 5.57.2(@typescript-eslint/types@8.69.0)
svelte: 5.57.3(@typescript-eslint/types@8.69.0)
typescript: 6.0.3
svelte@5.57.2(@typescript-eslint/types@8.69.0):
svelte@5.57.3(@typescript-eslint/types@8.69.0):
dependencies:
'@jridgewell/remapping': 2.3.5
'@jridgewell/sourcemap-codec': 1.6.0
'@sveltejs/acorn-typescript': 1.0.13(acorn@8.19.0)
'@types/estree': 1.0.9
'@types/estree': 1.0.10
acorn: 8.19.0
aria-query: 5.3.1
axobject-query: 4.1.0
@@ -27405,10 +27408,10 @@ snapshots:
solid-js: 1.9.15
vitest: 5.0.3(@types/node@26.4.1)(@vitest/browser-playwright@5.0.3)(@vitest/coverage-v8@5.0.5)(@vitest/ui@5.0.5)(jsdom@30.1.3)(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1))
vitest-browser-svelte@3.1.0(svelte@5.57.2(@typescript-eslint/types@8.69.0))(vitest@5.0.3):
vitest-browser-svelte@3.1.0(svelte@5.57.3(@typescript-eslint/types@8.69.0))(vitest@5.0.3):
dependencies:
'@testing-library/svelte-core': 1.1.3(svelte@5.57.2(@typescript-eslint/types@8.69.0))
svelte: 5.57.2(@typescript-eslint/types@8.69.0)
'@testing-library/svelte-core': 1.1.3(svelte@5.57.3(@typescript-eslint/types@8.69.0))
svelte: 5.57.3(@typescript-eslint/types@8.69.0)
vitest: 5.0.3(@types/node@26.4.1)(@vitest/browser-playwright@5.0.3)(@vitest/coverage-v8@5.0.5)(@vitest/ui@5.0.5)(jsdom@30.1.3)(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1))
vitest-browser-vue@3.1.0(@vue/compiler-dom@3.5.44)(@vue/server-renderer@3.5.44)(vitest@5.0.3)(vue@3.5.44(typescript@6.0.3)):
@@ -27438,7 +27441,7 @@ snapshots:
why-is-node-running: 3.2.1
optionalDependencies:
'@types/node': 26.4.1
'@vitest/browser-playwright': 5.0.3(playwright@1.58.2)(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.104.1)(sass@1.104.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1))(vitest@5.0.3)
'@vitest/browser-playwright': 5.0.3(playwright@1.64.1)(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.104.1)(sass@1.104.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1))(vitest@5.0.3)
'@vitest/coverage-v8': 5.0.5(vitest@5.0.3)
'@vitest/ui': 5.0.5(vitest@5.0.3)
jsdom: 30.1.3
@@ -27463,7 +27466,7 @@ snapshots:
why-is-node-running: 3.2.1
optionalDependencies:
'@types/node': 26.4.1
'@vitest/browser-playwright': 5.0.3(playwright@1.58.2)(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1))(vitest@5.0.3)
'@vitest/browser-playwright': 5.0.3(playwright@1.64.1)(vite@8.3.5(@types/node@26.4.1)(esbuild@0.28.2)(jiti@2.7.0)(less@4.9.1(supports-color@10.2.2))(sass-embedded@1.105.1)(sass@1.105.1)(stylus@0.56.0(supports-color@10.2.2))(terser@5.51.2)(yaml@2.9.1))(vitest@5.0.3)
'@vitest/coverage-v8': 5.0.5(vitest@5.0.3)
'@vitest/ui': 5.0.5(vitest@5.0.3)
jsdom: 30.1.3
+69 -135
View File
@@ -1,114 +1,39 @@
import { existsSync, readdirSync, readFileSync, writeFileSync } from 'node:fs';
import { join } from 'node:path';
const COLLECTIVE_SLUG = 'lucide-icons';
const OPEN_COLLECTIVE_API = 'https://api.opencollective.com/graphql/v2';
import { TIERS, type TierId } from '../docs/.vitepress/theme/components/sponsor/tiers.ts';
import {
type Account,
fetchCollective,
getCurrentSponsors,
getLocalLogos,
getOpenCollectiveLogo,
getWebsite,
} from '../docs/scripts/helpers/openCollective.mts';
const rootPath = join(import.meta.dirname, '..');
const mainReadmePath = join(rootPath, 'README.md');
const sponsorLogosPath = join(rootPath, 'docs/public/sponsors');
const tiersStartMarker = '[//]: <> (Sponsor tiers start)';
const tiersEndMarker = '[//]: <> (Sponsor tiers end)';
const mainReadmeOnlyStartMarker = '[//]: <> (Main README only start)';
const mainReadmeOnlyEndMarker = '[//]: <> (Main README only end)';
/**
* Headings for the Open Collective tiers, keyed by tier slug.
* Tiers that are not listed here fall back to their Open Collective name.
* How each sponsor tier shows up in the READMEs, following the tier perks in tiers.ts.
* Tiers that are not in the npm package READMEs are wrapped in the "Main README only" markers.
* Only tiers with `customLogo` use the logos in docs/public/sponsors, the others use their avatar.
*/
const TIER_TITLES: Record<string, string> = {
'hero-backer': 'Hero Backer 🦸',
'awesome-backer': 'Awesome backers 🍺',
backer: 'Backer ☕️',
const README_TIERS: Record<
TierId,
{ title: string; logoHeight: number; inPackages: boolean; customLogo: boolean }
> = {
platinum: { title: 'Platinum 💎', logoHeight: 96, inPackages: true, customLogo: true },
gold: { title: 'Gold 🥇', logoHeight: 64, inPackages: true, customLogo: true },
bronze: { title: 'Bronze 🥉', logoHeight: 48, inPackages: true, customLogo: true },
backer: { title: 'Backers 🍺', logoHeight: 32, inPackages: false, customLogo: false },
supporter: { title: 'Supporters ☕️', logoHeight: 32, inPackages: false, customLogo: false },
};
interface Account {
slug: string;
name: string;
website: string | null;
imageUrl: string | null;
description: string | null;
}
interface Tier {
slug: string;
name: string;
amount: { valueInCents: number | null } | null;
}
interface Order {
tier: Pick<Tier, 'slug'> | null;
fromAccount: Account;
}
interface CollectiveResponse {
data?: {
account: {
tiers: { nodes: Tier[] };
orders: { nodes: Order[] };
} | null;
};
errors?: { message: string }[];
}
const query = /* GraphQL */ `
query Sponsors($slug: String!) {
account(slug: $slug) {
... on AccountWithContributions {
tiers(limit: 100) {
nodes {
slug
name
amount {
valueInCents
}
}
}
}
orders(filter: INCOMING, status: [ACTIVE], limit: 1000) {
nodes {
tier {
slug
}
fromAccount {
slug
name
website
imageUrl
description
}
}
}
}
}
`;
async function fetchCollective() {
const headers: Record<string, string> = { 'Content-Type': 'application/json' };
if (process.env.OPENCOLLECTIVE_TOKEN) {
headers['Personal-Token'] = process.env.OPENCOLLECTIVE_TOKEN;
}
const response = await fetch(OPEN_COLLECTIVE_API, {
method: 'POST',
headers,
body: JSON.stringify({ query, variables: { slug: COLLECTIVE_SLUG } }),
});
if (!response.ok) {
throw new Error(`Open Collective API responded with ${response.status} ${response.statusText}`);
}
const { data, errors } = (await response.json()) as CollectiveResponse;
if (errors?.length) {
throw new Error(`Open Collective API errors: ${errors.map(({ message }) => message).join(', ')}`);
}
if (!data?.account) {
throw new Error(`Could not find Open Collective account "${COLLECTIVE_SLUG}"`);
}
return data.account;
}
const escapeHtml = (value: string) =>
value
.replaceAll('&', '&amp;')
@@ -116,48 +41,53 @@ const escapeHtml = (value: string) =>
.replaceAll('<', '&lt;')
.replaceAll('>', '&gt;');
function getLogo({ slug, imageUrl }: Account) {
const localLogo = ['svg', 'png'].find((extension) =>
existsSync(join(sponsorLogosPath, `${slug}.${extension}`)),
);
if (localLogo) return `docs/public/sponsors/${slug}.${localLogo}`;
return imageUrl ?? `https://images.opencollective.com/${slug}/logo/256.png`;
}
function renderSponsor(account: Account) {
const href = account.website || `https://opencollective.com/${account.slug}`;
/** Uses a `<picture>` to switch to the dark logo in dark mode, when there is one. */
function renderSponsor(account: Account, height: number, customLogo: boolean) {
const logos: { light?: string; dark?: string } = customLogo ? getLocalLogos(account.slug) : {};
const src = logos.light ? `docs/public/sponsors/${logos.light}` : getOpenCollectiveLogo(account);
const alt = account.description ? `${account.name} – ${account.description}` : account.name;
return `<a href="${escapeHtml(href)}"><img src="${escapeHtml(getLogo(account))}" height="64" alt="${escapeHtml(alt)}" /></a>`;
const image = `<img src="${escapeHtml(src)}" height="${height}" alt="${escapeHtml(alt)}" />`;
const logo = logos.dark
? `<picture><source media="(prefers-color-scheme: dark)" srcset="docs/public/sponsors/${escapeHtml(logos.dark)}" />${image}</picture>`
: image;
return `<a href="${escapeHtml(getWebsite(account))}">${logo}</a>`;
}
function renderTiers({ tiers, orders }: Awaited<ReturnType<typeof fetchCollective>>) {
const sponsorsByTier = new Map<string, Map<string, Account>>();
function renderTiers({ orders }: Awaited<ReturnType<typeof fetchCollective>>) {
const sponsorsByTier = Map.groupBy(getCurrentSponsors(orders.nodes), ({ tier }) => tier);
orders.nodes.forEach(({ tier, fromAccount }) => {
if (!tier) return;
if (!sponsorsByTier.has(tier.slug)) sponsorsByTier.set(tier.slug, new Map());
sponsorsByTier.get(tier.slug)!.set(fromAccount.slug, fromAccount);
});
// Highest tier first, so Platinum sponsors are at the top.
const renderTierGroup = (inPackages: boolean) =>
[...TIERS]
.reverse()
.filter(({ id }) => README_TIERS[id].inPackages === inPackages)
.flatMap(({ id }) => {
const sponsors = sponsorsByTier.get(id) ?? [];
if (!sponsors.length) return [];
return [...tiers.nodes]
.sort((a, b) => (b.amount?.valueInCents ?? 0) - (a.amount?.valueInCents ?? 0))
.flatMap((tier) => {
const sponsors = [...(sponsorsByTier.get(tier.slug)?.values() ?? [])];
if (!sponsors.length) return [];
const { title, logoHeight, customLogo } = README_TIERS[id];
const sponsorLinks = sponsors
.map(({ account }) => account)
.sort((a, b) => a.name.localeCompare(b.name))
.map((account) => renderSponsor(account, logoHeight, customLogo))
// READMEs strip `style`, so non-breaking spaces are used to space out the logos.
.join('\n&nbsp;&nbsp;\n');
if (!TIER_TITLES[tier.slug]) {
console.warn(`No title configured for tier "${tier.slug}", using "${tier.name}"`);
}
return `### ${title}\n\n${sponsorLinks}`;
})
.join('\n\n');
const sponsorLinks = sponsors
.sort((a, b) => a.name.localeCompare(b.name))
.map(renderSponsor)
.join('\n');
const packageTiers = renderTierGroup(true);
const mainReadmeOnlyTiers = renderTierGroup(false);
return `### ${TIER_TITLES[tier.slug] ?? tier.name}\n\n${sponsorLinks}`;
})
return [
packageTiers,
mainReadmeOnlyTiers &&
[mainReadmeOnlyStartMarker, mainReadmeOnlyTiers, mainReadmeOnlyEndMarker].join('\n\n'),
]
.filter(Boolean)
.join('\n\n');
}
@@ -189,9 +119,13 @@ function updatePackageSponsors() {
const packagesPath = join(rootPath, 'packages');
const mainReadme = readFileSync(mainReadmePath, 'utf8');
const sponsorsRegex = /(\[\/\/]: <> \(Sponsors\).+)$/s;
const mainReadmeOnlyRegex =
/\[\/\/]: <> \(Main README only start\).*?\[\/\/]: <> \(Main README only end\)\s*/gs;
const sponsorsBlock = sponsorsRegex.exec(mainReadme);
if (sponsorsBlock?.[1]) {
const packageSponsorsBlock = sponsorsBlock[1].replaceAll('src="docs/public', 'src="https://lucide.dev')
const packageSponsorsBlock = sponsorsBlock[1]
.replace(mainReadmeOnlyRegex, '')
.replaceAll('="docs/public/', '="https://lucide.dev/');
readdirSync(packagesPath).forEach((packagePath) => {
if (['lucide-figma', 'shared'].includes(packagePath) || packagePath.startsWith('.')) {
return;
@@ -203,14 +137,14 @@ function updatePackageSponsors() {
writeFileSync(readmePath, readmeContent.replace(sponsorsRegex, packageSponsorsBlock));
console.log(`Upgraded Sponsors block in ${readmePath}`);
} else {
console.error(`Could not find Sponsors 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 Sponsors block')
console.error('Could not identify Sponsors block');
}
}