mirror of
https://github.com/lucide-icons/lucide.git
synced 2025-12-17 12:07:41 +01:00
Compare commits
5 Commits
0.523.0
...
lucide-vue
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d1d57d3c85 | ||
|
|
701c2fb6b2 | ||
|
|
294ec9c727 | ||
|
|
99c883e60a | ||
|
|
9e68779d22 |
@@ -1,17 +0,0 @@
|
||||
# Custom words
|
||||
fullscreen
|
||||
gamepad
|
||||
gantt
|
||||
kanban
|
||||
pilcrow
|
||||
squircle
|
||||
strikethrough
|
||||
touchpad
|
||||
ungroup
|
||||
toc
|
||||
|
||||
# Brands
|
||||
codepen
|
||||
codesandbox
|
||||
dribbble
|
||||
x.com
|
||||
@@ -6,5 +6,6 @@ tests
|
||||
node_modules
|
||||
.eslintrc.js
|
||||
docs/images
|
||||
docs/**/examples/
|
||||
docs/guide/basics/examples
|
||||
docs/guide/advanced/examples
|
||||
packages/lucide-react/dynamicIconImports.js
|
||||
|
||||
17
.eslintrc.js
17
.eslintrc.js
@@ -1,4 +1,4 @@
|
||||
const DEFAULT_ATTRS = require('./tools/build-icons/render/default-attrs.json');
|
||||
const DEFAULT_ATTRS = require('./scripts/render/default-attrs.json');
|
||||
|
||||
module.exports = {
|
||||
root: true,
|
||||
@@ -15,9 +15,7 @@ module.exports = {
|
||||
'no-use-before-define': 'off',
|
||||
'import/no-extraneous-dependencies': [
|
||||
'error',
|
||||
{
|
||||
devDependencies: ['**/*.test.js', '**/*.spec.js', '**/scripts/**'],
|
||||
},
|
||||
{ devDependencies: ['**/*.test.js', '**/*.spec.js', './scripts/**'] },
|
||||
],
|
||||
'import/extensions': [
|
||||
'error',
|
||||
@@ -45,14 +43,11 @@ module.exports = {
|
||||
'@html-eslint/no-inline-styles': 'error',
|
||||
'@html-eslint/require-attrs': [
|
||||
'error',
|
||||
...Object.entries(DEFAULT_ATTRS).map(([attr, value]) => ({
|
||||
tag: 'svg',
|
||||
attr,
|
||||
value: String(value),
|
||||
})),
|
||||
...Object.entries(DEFAULT_ATTRS)
|
||||
.map(([attr, value]) => ({ tag: 'svg', attr, value: String(value) }))
|
||||
],
|
||||
'@html-eslint/indent': ['error', 2],
|
||||
'@html-eslint/no-multiple-empty-lines': ['error', { max: 0 }],
|
||||
"@html-eslint/no-multiple-empty-lines": ["error", { "max": 0 }],
|
||||
'@html-eslint/no-extra-spacing-attrs': [
|
||||
'error',
|
||||
{
|
||||
@@ -69,7 +64,7 @@ module.exports = {
|
||||
'@html-eslint/element-newline': 'error',
|
||||
'@html-eslint/no-trailing-spaces': 'error',
|
||||
'@html-eslint/quotes': 'error',
|
||||
},
|
||||
}
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
14
.github/ISSUE_TEMPLATE/02_bug_report.yml
vendored
14
.github/ISSUE_TEMPLATE/02_bug_report.yml
vendored
@@ -22,7 +22,6 @@ body:
|
||||
- label: lucide-svelte
|
||||
- label: lucide-vue
|
||||
- label: lucide-vue-next
|
||||
- label: lucide-astro
|
||||
- label: Figma plugin
|
||||
- label: source/main
|
||||
- label: other/not relevant
|
||||
@@ -36,16 +35,6 @@ body:
|
||||
placeholder: e.g. 0.289.1
|
||||
validations:
|
||||
required: true
|
||||
- type: checkboxes
|
||||
id: can-reproduce-in-latest-version
|
||||
attributes:
|
||||
label: Can you reproduce this in the latest version?
|
||||
description: i.e. after running `npm install lucide-react@latest`
|
||||
options:
|
||||
- label: 'Yes'
|
||||
- label: 'No'
|
||||
validations:
|
||||
required: false
|
||||
- type: checkboxes
|
||||
id: browsers
|
||||
attributes:
|
||||
@@ -70,9 +59,6 @@ body:
|
||||
- label: Windows
|
||||
- label: Linux
|
||||
- label: macOS
|
||||
- label: ChromeOS
|
||||
- label: iOS
|
||||
- label: Android
|
||||
- label: Other/not relevant
|
||||
- type: textarea
|
||||
id: description
|
||||
|
||||
@@ -30,9 +30,6 @@ body:
|
||||
- label: Windows
|
||||
- label: Linux
|
||||
- label: macOS
|
||||
- label: ChromeOS
|
||||
- label: iOS
|
||||
- label: Android
|
||||
- label: Other/not relevant
|
||||
- type: textarea
|
||||
id: description
|
||||
|
||||
@@ -22,7 +22,6 @@ body:
|
||||
- label: lucide-svelte
|
||||
- label: lucide-vue
|
||||
- label: lucide-vue-next
|
||||
- label: lucide-astro
|
||||
- label: Figma plugin
|
||||
- label: all JS packages
|
||||
- label: site
|
||||
|
||||
44
.github/actions/build-and-test.yml
vendored
Normal file
44
.github/actions/build-and-test.yml
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
name: "Build and Test"
|
||||
description: "Builds and test a package"
|
||||
|
||||
inputs:
|
||||
name:
|
||||
description: “Name of the package”
|
||||
required: true
|
||||
|
||||
runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 16
|
||||
|
||||
- uses: pnpm/action-setup@v2
|
||||
name: Install pnpm
|
||||
id: pnpm-install
|
||||
with:
|
||||
version: 8
|
||||
run_install: false
|
||||
|
||||
- name: Get pnpm store directory
|
||||
id: pnpm-cache
|
||||
run: |
|
||||
echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT
|
||||
|
||||
- uses: actions/cache@v3
|
||||
name: Setup pnpm cache
|
||||
with:
|
||||
path: ${{ steps.pnpm-cache.outputs.STORE_PATH }}
|
||||
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-pnpm-store-
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install --filter lucide-preact
|
||||
|
||||
- name: Build
|
||||
run: pnpm --filter lucide-preact build
|
||||
|
||||
- name: Test
|
||||
run: pnpm --filter lucide-preact test
|
||||
41
.github/actions/check-icons.yml
vendored
Normal file
41
.github/actions/check-icons.yml
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
name: "Check icons"
|
||||
description: "Cross-checks icon and category references in JSON descriptors"
|
||||
|
||||
inputs:
|
||||
name:
|
||||
description: “Name of the package”
|
||||
required: true
|
||||
|
||||
runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 16
|
||||
|
||||
- uses: pnpm/action-setup@v2
|
||||
name: Install pnpm
|
||||
id: pnpm-install
|
||||
with:
|
||||
version: 8
|
||||
run_install: false
|
||||
|
||||
- name: Get pnpm store directory
|
||||
id: pnpm-cache
|
||||
run: |
|
||||
echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT
|
||||
|
||||
- uses: actions/cache@v3
|
||||
name: Setup pnpm cache
|
||||
with:
|
||||
path: ${{ steps.pnpm-cache.outputs.STORE_PATH }}
|
||||
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-pnpm-store-
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install --filter .
|
||||
|
||||
- name: Check icons and categories
|
||||
run: pnpm checkIcons
|
||||
36
.github/labeler.yml
vendored
36
.github/labeler.yml
vendored
@@ -1,98 +1,92 @@
|
||||
# For changed dependencies
|
||||
📦 dependencies:
|
||||
- changed-files:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- pnpm-lock.yaml
|
||||
|
||||
# For changes in documentation
|
||||
📖 documentation:
|
||||
- changed-files:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- docs/*.md
|
||||
- docs/**/*.md
|
||||
|
||||
# For changes in the site, but not markdown files
|
||||
🌍 site:
|
||||
- changed-files:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- 'docs/**'
|
||||
|
||||
# For changes in the metadata
|
||||
🫧 metadata:
|
||||
- changed-files:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- 'icons/*.json'
|
||||
- categories/*
|
||||
|
||||
# For changes or added icons
|
||||
🎨 icon:
|
||||
- changed-files:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- 'icons/*.svg'
|
||||
|
||||
# For changes in the lucide package
|
||||
🧳 lucide package:
|
||||
- changed-files:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- 'packages/lucide/*'
|
||||
|
||||
# For changes in the lucide React package
|
||||
⚛️ react package:
|
||||
- changed-files:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- 'packages/lucide-react/*'
|
||||
|
||||
# For changes in the lucide React Native package
|
||||
⚛️ react native package:
|
||||
- changed-files:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- 'packages/lucide-react-native/*'
|
||||
|
||||
# For changes in the lucide vue packages
|
||||
💎 vue package:
|
||||
- changed-files:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- 'packages/lucide-vue/*'
|
||||
- 'packages/lucide-vue-next/*'
|
||||
|
||||
# For changes in the lucide angular package
|
||||
🅰️ angular package:
|
||||
- changed-files:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- 'packages/lucide-angular/*'
|
||||
|
||||
# For changes in the lucide preact package
|
||||
⚛️ preact package:
|
||||
- changed-files:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- 'packages/lucide-preact/*'
|
||||
|
||||
# For changes in the lucide svelte package
|
||||
🧣 svelte package:
|
||||
- changed-files:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- 'packages/lucide-svelte/*'
|
||||
|
||||
# For changes in the lucide solid package
|
||||
🪝 solid package:
|
||||
- changed-files:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- 'packages/lucide-solid/*'
|
||||
|
||||
# For changes in the lucide astro package
|
||||
🚀 astro package:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- 'packages/astro/*'
|
||||
|
||||
# For changes in the lucide static package
|
||||
🪨 static package:
|
||||
- changed-files:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- 'packages/lucide-static/*'
|
||||
|
||||
# For changes in the lucide flutter package
|
||||
🏹 flutter package:
|
||||
- changed-files:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- 'packages/lucide-flutter/*'
|
||||
|
||||
24
.github/pull_request_template.md
vendored
24
.github/pull_request_template.md
vendored
@@ -1,18 +1,16 @@
|
||||
<!-- Thank you for contributing! -->
|
||||
|
||||
<!--
|
||||
PR Title Guidelines:
|
||||
|
||||
Please use the format: <type>(<scope>): <short description>
|
||||
|
||||
Example: feat(icons): added `camera` icon
|
||||
|
||||
Available types: fix, feat, perf, docs, style, refactor, test, chore, ci, build
|
||||
Common scopes: icons, docs, studio, site, dev
|
||||
-->
|
||||
|
||||
<!-- Insert `closes #issueNumber` here if merging this PR will resolve an existing issue -->
|
||||
## Description
|
||||
|
||||
## What is the purpose of this pull request?
|
||||
<!-- Please choose one of the following, and put an "x" next to it. -->
|
||||
- [ ] New Icon
|
||||
- [ ] Bug fix
|
||||
- [ ] New Feature
|
||||
- [ ] Documentation update
|
||||
- [ ] Other:
|
||||
|
||||
### Description
|
||||
<!-- Please insert your description here and provide info about the "what" this PR is contribution -->
|
||||
|
||||
### Icon use case <!-- ONLY for new icons, remove this part if not icon PR -->
|
||||
@@ -49,7 +47,7 @@ Common scopes: icons, docs, studio, site, dev
|
||||
- [ ] I've made sure that the icons look sharp on low DPI displays.
|
||||
- [ ] I've made sure that the icons look consistent with the icon set in size, optical volume and density.
|
||||
- [ ] I've made sure that the icons are visually centered.
|
||||
- [ ] I've correctly optimized all icons to three points of precision.
|
||||
- [ ] I've correctly optimized all icons to two points of precision.
|
||||
|
||||
## Before Submitting <!-- For every PR! -->
|
||||
<!-- All of these requirements must be fulfilled. -->
|
||||
|
||||
44
.github/workflows/ci.yml
vendored
44
.github/workflows/ci.yml
vendored
@@ -9,18 +9,20 @@ on:
|
||||
|
||||
jobs:
|
||||
create-release:
|
||||
if: github.repository == 'lucide-icons/lucide' && startsWith(github.event.head_commit.message, 'feat(icons)')
|
||||
if: github.repository == 'lucide-icons/lucide'
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
VERSION: ${{ steps.new-version.outputs.NEW_VERSION }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: pnpm/action-setup@v4
|
||||
- uses: pnpm/action-setup@v2
|
||||
with:
|
||||
version: 8
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18
|
||||
cache: 'pnpm'
|
||||
node-version-file: 'package.json'
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install --frozen-lockfile
|
||||
@@ -61,40 +63,8 @@ jobs:
|
||||
uses: softprops/action-gh-release@v1
|
||||
with:
|
||||
tag_name: ${{ steps.new-version.outputs.NEW_VERSION }}
|
||||
name: Version ${{ steps.new-version.outputs.NEW_VERSION }}
|
||||
generate_release_notes: true
|
||||
|
||||
test-semantic-release:
|
||||
if: github.repository == 'lucide-icons/lucide'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Semantic Release
|
||||
id: semantic
|
||||
uses: cycjimmy/semantic-release-action@v4
|
||||
with:
|
||||
tag_format: ${version}
|
||||
branches: |
|
||||
['new-release-workflow']
|
||||
extends: |
|
||||
semantic-release-monorepo
|
||||
extra_plugins: |
|
||||
@semantic-release/github
|
||||
@semantic-release/git
|
||||
@semantic-release/release-notes-generator
|
||||
conventional-changelog-conventionalcommits
|
||||
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Log output
|
||||
if: steps.semantic.outputs.new_release_published == 'true'
|
||||
run: |
|
||||
echo ${{ steps.semantic.outputs.new_release_version }}
|
||||
echo ${{ steps.semantic.outputs.new_release_major_version }}
|
||||
echo ${{ steps.semantic.outputs.new_release_minor_version }}
|
||||
echo ${{ steps.semantic.outputs.new_release_patch_version }}
|
||||
name: New icons ${{ steps.new-version.outputs.NEW_VERSION }}
|
||||
body: ${{ steps.change-log.outputs.CHANGE_LOG }}
|
||||
|
||||
start-release:
|
||||
if: github.repository == 'lucide-icons/lucide'
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
name: Close Issue with Banned Phrases
|
||||
|
||||
on:
|
||||
issues:
|
||||
types: [opened]
|
||||
|
||||
jobs:
|
||||
block_phrases:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
issues: write
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Check for blocked phrases in issue title
|
||||
run: |
|
||||
ISSUE_TITLE=$(jq -r '.issue.title' "$GITHUB_EVENT_PATH")
|
||||
BLOCKED_PHRASES=("twitter" "whatsapp" "logo" "google" "tiktok" "facebook" "slack" "discord" "bluesky" "spotify" "behance" "pix" "x.com")
|
||||
|
||||
# Check title and body for blocked phrases
|
||||
for PHRASE in "${BLOCKED_PHRASES[@]}"
|
||||
do
|
||||
if echo "$ISSUE_TITLE" | grep -i "$PHRASE"; then
|
||||
gh issue close ${{ github.event.issue.number }} --reason "not planned" --comment "This looks like a duplicate, use the [search](https://github.com/lucide-icons/lucide/issues?q=is%3Aissue+$PHRASE) to find similar issues.
|
||||
|
||||
Read more about brand guideline rules at [We're not accepting new Brand icons #670](https://github.com/lucide-icons/lucide/issues/670).
|
||||
|
||||
Always happy to help on [Discord](https://discord.gg/EH6nSts)."
|
||||
gh issue lock ${{ github.event.issue.number }} --reason spam
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
5
.github/workflows/close-stale-prs.yml
vendored
5
.github/workflows/close-stale-prs.yml
vendored
@@ -1,13 +1,11 @@
|
||||
name: Close stale issues and PR
|
||||
on:
|
||||
schedule:
|
||||
- cron: '45 1 * * *'
|
||||
- cron: "45 1 * * *"
|
||||
|
||||
jobs:
|
||||
stale:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
pull-requests: write
|
||||
steps:
|
||||
- uses: actions/stale@v9
|
||||
with:
|
||||
@@ -16,5 +14,4 @@ jobs:
|
||||
close-pr-message: This PR was closed because it has been stalled for 5 days with no activity.
|
||||
close-pr-label: 🧶 stale
|
||||
days-before-stale: 30
|
||||
days-before-issue-stale: -1
|
||||
days-before-close: -1
|
||||
|
||||
58
.github/workflows/comment-icon-preview.yml
vendored
58
.github/workflows/comment-icon-preview.yml
vendored
@@ -1,58 +0,0 @@
|
||||
name: Icon preview comment
|
||||
|
||||
on:
|
||||
workflow_run:
|
||||
workflows: ['Pull request icon preview']
|
||||
types:
|
||||
- completed
|
||||
|
||||
jobs:
|
||||
upload:
|
||||
runs-on: ubuntu-latest
|
||||
if: >
|
||||
github.event.workflow_run.event == 'pull_request' &&
|
||||
github.event.workflow_run.conclusion == 'success'
|
||||
steps:
|
||||
- name: 'Download artifact'
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
let allArtifacts = await github.rest.actions.listWorkflowRunArtifacts({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
run_id: context.payload.workflow_run.id,
|
||||
});
|
||||
let matchArtifact = allArtifacts.data.artifacts.filter((artifact) => {
|
||||
return artifact.name == "pr_number"
|
||||
})[0];
|
||||
let download = await github.rest.actions.downloadArtifact({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
artifact_id: matchArtifact.id,
|
||||
archive_format: 'zip',
|
||||
});
|
||||
const fs = require('fs');
|
||||
fs.writeFileSync('${{github.workspace}}/pr_number.zip', Buffer.from(download.data));
|
||||
|
||||
- name: 'Unzip artifact'
|
||||
run: unzip pr_number.zip
|
||||
|
||||
- name: 'Get PR number'
|
||||
run: echo "number=$(cat NR)" >> $GITHUB_OUTPUT
|
||||
id: pr-number
|
||||
|
||||
- name: Find Comment
|
||||
uses: peter-evans/find-comment@v2
|
||||
id: pr-comment
|
||||
with:
|
||||
issue-number: ${{ steps.pr-number.outputs.number }}
|
||||
comment-author: 'github-actions[bot]'
|
||||
body-includes: Added or changed icons
|
||||
|
||||
- name: Create or update comment
|
||||
uses: peter-evans/create-or-update-comment@v3
|
||||
with:
|
||||
comment-id: ${{ steps.pr-comment.outputs.comment-id }}
|
||||
issue-number: ${{ steps.pr-number.outputs.number }}
|
||||
body-path: comment-markup.md
|
||||
edit-mode: replace
|
||||
5
.github/workflows/labeler.yml
vendored
5
.github/workflows/labeler.yml
vendored
@@ -1,6 +1,6 @@
|
||||
name: 'Pull Request Labeler'
|
||||
name: "Pull Request Labeler"
|
||||
on:
|
||||
- pull_request_target
|
||||
- pull_request_target
|
||||
|
||||
jobs:
|
||||
triage:
|
||||
@@ -9,5 +9,4 @@ jobs:
|
||||
pull-requests: write
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/labeler@v5
|
||||
|
||||
32
.github/workflows/lint-pr-title.yml
vendored
32
.github/workflows/lint-pr-title.yml
vendored
@@ -1,32 +0,0 @@
|
||||
name: Linting PR
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types:
|
||||
- opened
|
||||
- edited
|
||||
- reopened
|
||||
|
||||
jobs:
|
||||
lint-pr-title:
|
||||
name: PR Title Lint
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: amannn/action-semantic-pull-request@v5
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
types: |
|
||||
fix
|
||||
feat
|
||||
perf
|
||||
refactor
|
||||
test
|
||||
style
|
||||
docs
|
||||
ci
|
||||
build
|
||||
chore
|
||||
requireScope: true
|
||||
ignoreLabels: |
|
||||
bot
|
||||
39
.github/workflows/linting-icons.yml
vendored
39
.github/workflows/linting-icons.yml
vendored
@@ -1,39 +0,0 @@
|
||||
name: Linting Icons
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- 'icons/*'
|
||||
|
||||
jobs:
|
||||
lint-filenames:
|
||||
name: Lint Filenames
|
||||
if: github.repository == 'lucide-icons/lucide'
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: 'package.json'
|
||||
- name: Get changed files
|
||||
id: changed-files
|
||||
uses: tj-actions/changed-files@v46
|
||||
with:
|
||||
files: icons/*
|
||||
|
||||
- name: Generate annotations
|
||||
run: node ./scripts/lintFilenames.mts
|
||||
env:
|
||||
CHANGED_FILES: ${{ steps.changed-files.outputs.all_changed_files }}
|
||||
|
||||
lint-aliases:
|
||||
name: Check Uniqueness of Aliases
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Check Uniqueness of Aliases
|
||||
run: "! cat <(printf \"%s\\n\" icons/*.json | while read -r name; do basename \"$name\" .json; done) <(jq -cr 'select(.aliases) | .aliases[] | if type==\"string\" then . else .name end' icons/*.json) | sort | uniq -c | grep -ve '^\\s*1 '"
|
||||
@@ -1,20 +1,22 @@
|
||||
name: Linting PR
|
||||
name: Linting
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- icons/*.svg
|
||||
branches:
|
||||
- '**'
|
||||
|
||||
jobs:
|
||||
lint-code:
|
||||
linting:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: pnpm/action-setup@v4
|
||||
- uses: pnpm/action-setup@v2
|
||||
with:
|
||||
version: 8
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18
|
||||
cache: 'pnpm'
|
||||
node-version-file: 'package.json'
|
||||
|
||||
- name: Install Dependencies
|
||||
run: pnpm install --frozen-lockfile
|
||||
21
.github/workflows/lucide-angular.yml
vendored
21
.github/workflows/lucide-angular.yml
vendored
@@ -8,15 +8,17 @@ on:
|
||||
- pnpm-lock.yaml
|
||||
|
||||
jobs:
|
||||
build:
|
||||
lucide-angular:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: pnpm/action-setup@v4
|
||||
- uses: pnpm/action-setup@v2
|
||||
with:
|
||||
version: 8
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18
|
||||
cache: 'pnpm'
|
||||
node-version-file: 'package.json'
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install --frozen-lockfile
|
||||
@@ -24,18 +26,5 @@ jobs:
|
||||
- name: Build
|
||||
run: pnpm --filter lucide-angular build
|
||||
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: pnpm/action-setup@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
cache: 'pnpm'
|
||||
node-version-file: 'package.json'
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install --frozen-lockfile
|
||||
|
||||
- name: Test
|
||||
run: pnpm --filter lucide-angular test
|
||||
|
||||
42
.github/workflows/lucide-astro.yml
vendored
42
.github/workflows/lucide-astro.yml
vendored
@@ -1,42 +0,0 @@
|
||||
name: Lucide Astro Checks
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- packages/astro/**
|
||||
- packages/shared/**
|
||||
- tools/build-icons/**
|
||||
- pnpm-lock.yaml
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: pnpm/action-setup@v2
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: 'package.json'
|
||||
cache: 'pnpm'
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install --frozen-lockfile
|
||||
|
||||
- name: Build
|
||||
run: pnpm --filter @lucide/astro build
|
||||
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: pnpm/action-setup@v2
|
||||
- uses: actions/setup-node@v3.8.1
|
||||
with:
|
||||
node-version-file: 'package.json'
|
||||
cache: 'pnpm'
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install --frozen-lockfile
|
||||
|
||||
- name: Test
|
||||
run: pnpm --filter @lucide/astro test
|
||||
11
.github/workflows/lucide-font.yml
vendored
11
.github/workflows/lucide-font.yml
vendored
@@ -3,6 +3,7 @@ name: Lucide font checks
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- icons/**
|
||||
- tools/build-font/**
|
||||
- pnpm-lock.yaml
|
||||
|
||||
@@ -11,11 +12,13 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: pnpm/action-setup@v4
|
||||
- uses: pnpm/action-setup@v2
|
||||
with:
|
||||
version: 8
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18
|
||||
cache: 'pnpm'
|
||||
node-version-file: 'package.json'
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install --frozen-lockfile
|
||||
@@ -26,8 +29,8 @@ jobs:
|
||||
- name: Create font in ./lucide-font
|
||||
run: pnpm build:font
|
||||
|
||||
- name: 'Upload to Artifacts'
|
||||
uses: actions/upload-artifact@v4
|
||||
- name: "Upload to Artifacts"
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: lucide-font
|
||||
path: lucide-font
|
||||
|
||||
10
.github/workflows/lucide-preact.yml
vendored
10
.github/workflows/lucide-preact.yml
vendored
@@ -4,7 +4,6 @@ on:
|
||||
pull_request:
|
||||
paths:
|
||||
- packages/lucide-preact/**
|
||||
- packages/shared/**
|
||||
- tools/build-icons/**
|
||||
- tools/rollup-plugins/**
|
||||
- pnpm-lock.yaml
|
||||
@@ -14,14 +13,19 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: pnpm/action-setup@v4
|
||||
- uses: pnpm/action-setup@v2
|
||||
with:
|
||||
version: 8
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18
|
||||
cache: 'pnpm'
|
||||
node-version-file: 'package.json'
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install --frozen-lockfile
|
||||
|
||||
- name: Build
|
||||
run: pnpm --filter lucide-preact build
|
||||
|
||||
- name: Test
|
||||
run: pnpm --filter lucide-preact test
|
||||
|
||||
22
.github/workflows/lucide-react-native.yml
vendored
22
.github/workflows/lucide-react-native.yml
vendored
@@ -4,21 +4,22 @@ on:
|
||||
pull_request:
|
||||
paths:
|
||||
- packages/lucide-react-native/**
|
||||
- packages/shared/**
|
||||
- tools/build-icons/**
|
||||
- tools/rollup-plugins/**
|
||||
- pnpm-lock.yaml
|
||||
|
||||
jobs:
|
||||
build:
|
||||
lucide-react-native:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: pnpm/action-setup@v4
|
||||
- uses: pnpm/action-setup@v2
|
||||
with:
|
||||
version: 8
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18
|
||||
cache: 'pnpm'
|
||||
node-version-file: 'package.json'
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install --frozen-lockfile
|
||||
@@ -26,18 +27,5 @@ jobs:
|
||||
- name: Build
|
||||
run: pnpm --filter lucide-react-native build
|
||||
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: pnpm/action-setup@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
cache: 'pnpm'
|
||||
node-version-file: 'package.json'
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install --frozen-lockfile
|
||||
|
||||
- name: Test
|
||||
run: pnpm --filter lucide-react-native test
|
||||
|
||||
22
.github/workflows/lucide-react.yml
vendored
22
.github/workflows/lucide-react.yml
vendored
@@ -4,22 +4,23 @@ on:
|
||||
pull_request:
|
||||
paths:
|
||||
- packages/lucide-react/**
|
||||
- packages/shared/**
|
||||
- tools/build-icons/**
|
||||
- tools/rollup-plugins/**
|
||||
- scripts/generateNextJSAliases.mjs
|
||||
- pnpm-lock.yaml
|
||||
|
||||
jobs:
|
||||
build:
|
||||
lucide-react:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: pnpm/action-setup@v4
|
||||
- uses: pnpm/action-setup@v2
|
||||
with:
|
||||
version: 8
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18
|
||||
cache: 'pnpm'
|
||||
node-version-file: 'package.json'
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install --frozen-lockfile
|
||||
@@ -27,18 +28,5 @@ jobs:
|
||||
- name: Build
|
||||
run: pnpm --filter lucide-react build
|
||||
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: pnpm/action-setup@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
cache: 'pnpm'
|
||||
node-version-file: 'package.json'
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install --frozen-lockfile
|
||||
|
||||
- name: Test
|
||||
run: pnpm --filter lucide-react test
|
||||
|
||||
24
.github/workflows/lucide-shared.yml
vendored
24
.github/workflows/lucide-shared.yml
vendored
@@ -1,24 +0,0 @@
|
||||
name: Lucide Shared Checks
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- packages/shared/**
|
||||
- pnpm-lock.yaml
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: pnpm/action-setup@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
cache: 'pnpm'
|
||||
node-version-file: 'package.json'
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install --frozen-lockfile
|
||||
|
||||
- name: Test
|
||||
run: pnpm --filter lucide-react test
|
||||
22
.github/workflows/lucide-solid.yml
vendored
22
.github/workflows/lucide-solid.yml
vendored
@@ -4,21 +4,22 @@ on:
|
||||
pull_request:
|
||||
paths:
|
||||
- packages/lucide-solid/**
|
||||
- packages/shared/**
|
||||
- tools/build-icons/**
|
||||
- tools/rollup-plugins/**
|
||||
- pnpm-lock.yaml
|
||||
|
||||
jobs:
|
||||
build:
|
||||
lucide-solid:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: pnpm/action-setup@v4
|
||||
- uses: pnpm/action-setup@v2
|
||||
with:
|
||||
version: 8
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18
|
||||
cache: 'pnpm'
|
||||
node-version-file: 'package.json'
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install --frozen-lockfile
|
||||
@@ -26,18 +27,5 @@ jobs:
|
||||
- name: Build
|
||||
run: pnpm --filter lucide-solid build
|
||||
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: pnpm/action-setup@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
cache: 'pnpm'
|
||||
node-version-file: 'package.json'
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install --frozen-lockfile
|
||||
|
||||
- name: Test
|
||||
run: pnpm --filter lucide-solid test
|
||||
|
||||
6
.github/workflows/lucide-static.yml
vendored
6
.github/workflows/lucide-static.yml
vendored
@@ -12,11 +12,13 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: pnpm/action-setup@v4
|
||||
- uses: pnpm/action-setup@v2
|
||||
with:
|
||||
version: 8
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18
|
||||
cache: 'pnpm'
|
||||
node-version-file: 'package.json'
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install --frozen-lockfile
|
||||
|
||||
43
.github/workflows/lucide-svelte-5.yml
vendored
43
.github/workflows/lucide-svelte-5.yml
vendored
@@ -1,43 +0,0 @@
|
||||
name: Lucide Svelte 5 checks
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- packages/svelte/**
|
||||
- packages/shared/**
|
||||
- tools/build-icons/**
|
||||
- tools/rollup-plugins/**
|
||||
- pnpm-lock.yaml
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: pnpm/action-setup@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
cache: 'pnpm'
|
||||
node-version-file: 'package.json'
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install --frozen-lockfile
|
||||
|
||||
- name: Build
|
||||
run: pnpm --filter @lucide/svelte build
|
||||
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: pnpm/action-setup@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
cache: 'pnpm'
|
||||
node-version-file: 'package.json'
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install --frozen-lockfile
|
||||
|
||||
- name: Test
|
||||
run: pnpm --filter @lucide/svelte test
|
||||
22
.github/workflows/lucide-svelte.yml
vendored
22
.github/workflows/lucide-svelte.yml
vendored
@@ -4,21 +4,22 @@ on:
|
||||
pull_request:
|
||||
paths:
|
||||
- packages/lucide-svelte/**
|
||||
- packages/shared/**
|
||||
- tools/build-icons/**
|
||||
- tools/rollup-plugins/**
|
||||
- pnpm-lock.yaml
|
||||
|
||||
jobs:
|
||||
build:
|
||||
lucide-svelte:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: pnpm/action-setup@v4
|
||||
- uses: pnpm/action-setup@v2
|
||||
with:
|
||||
version: 8
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18
|
||||
cache: 'pnpm'
|
||||
node-version-file: 'package.json'
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install --frozen-lockfile
|
||||
@@ -26,18 +27,5 @@ jobs:
|
||||
- name: Build
|
||||
run: pnpm --filter lucide-svelte build
|
||||
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: pnpm/action-setup@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
cache: 'pnpm'
|
||||
node-version-file: 'package.json'
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install --frozen-lockfile
|
||||
|
||||
- name: Test
|
||||
run: pnpm --filter lucide-svelte test
|
||||
|
||||
22
.github/workflows/lucide-vue-next.yml
vendored
22
.github/workflows/lucide-vue-next.yml
vendored
@@ -4,21 +4,22 @@ on:
|
||||
pull_request:
|
||||
paths:
|
||||
- packages/lucide-vue-next/**
|
||||
- packages/shared/**
|
||||
- tools/build-icons/**
|
||||
- tools/rollup-plugins/**
|
||||
- pnpm-lock.yaml
|
||||
|
||||
jobs:
|
||||
build:
|
||||
lucide-vue-next:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: pnpm/action-setup@v4
|
||||
- uses: pnpm/action-setup@v2
|
||||
with:
|
||||
version: 8
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18
|
||||
cache: 'pnpm'
|
||||
node-version-file: 'package.json'
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install --frozen-lockfile
|
||||
@@ -26,18 +27,5 @@ jobs:
|
||||
- name: Build
|
||||
run: pnpm --filter lucide-vue-next build
|
||||
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: pnpm/action-setup@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
cache: 'pnpm'
|
||||
node-version-file: 'package.json'
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install --frozen-lockfile
|
||||
|
||||
- name: Test
|
||||
run: pnpm --filter lucide-vue-next test
|
||||
|
||||
31
.github/workflows/lucide-vue.yml
vendored
Normal file
31
.github/workflows/lucide-vue.yml
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
name: Lucide Vue checks
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- packages/lucide-vue/**
|
||||
- tools/build-icons/**
|
||||
- tools/rollup-plugins/**
|
||||
- pnpm-lock.yaml
|
||||
|
||||
jobs:
|
||||
lucide-vue:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: pnpm/action-setup@v2
|
||||
with:
|
||||
version: 8
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18
|
||||
cache: 'pnpm'
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install --frozen-lockfile
|
||||
|
||||
- name: Build
|
||||
run: pnpm --filter lucide-vue build
|
||||
|
||||
- name: Test
|
||||
run: pnpm --filter lucide-vue test
|
||||
21
.github/workflows/lucide.yml
vendored
21
.github/workflows/lucide.yml
vendored
@@ -9,15 +9,17 @@ on:
|
||||
- pnpm-lock.yaml
|
||||
|
||||
jobs:
|
||||
build:
|
||||
lucide:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: pnpm/action-setup@v4
|
||||
- uses: pnpm/action-setup@v2
|
||||
with:
|
||||
version: 8
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18
|
||||
cache: 'pnpm'
|
||||
node-version-file: 'package.json'
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install --frozen-lockfile
|
||||
@@ -25,18 +27,5 @@ jobs:
|
||||
- name: Build
|
||||
run: pnpm --filter lucide build
|
||||
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: pnpm/action-setup@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
cache: 'pnpm'
|
||||
node-version-file: 'package.json'
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install --frozen-lockfile
|
||||
|
||||
- name: Test
|
||||
run: pnpm --filter lucide test
|
||||
|
||||
46
.github/workflows/pull-request-icon-preview.yml
vendored
46
.github/workflows/pull-request-icon-preview.yml
vendored
@@ -1,46 +0,0 @@
|
||||
name: Pull request icon preview
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- 'icons/*.svg'
|
||||
|
||||
jobs:
|
||||
generate-changed-icons-comment:
|
||||
name: Generate Changed Icons Comment
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: 'package.json'
|
||||
|
||||
- name: Get changed files
|
||||
id: changed-files
|
||||
uses: tj-actions/changed-files@v46
|
||||
with:
|
||||
files: icons/*.svg
|
||||
|
||||
- uses: actions/setup-node@v4
|
||||
- name: Install svgson for code preview (safer and faster than installing all deps)
|
||||
run: npm install svgson@5.3.1 --force
|
||||
|
||||
- name: Save PR number
|
||||
run: |
|
||||
mkdir -p ./pr
|
||||
echo ${{ github.event.number }} > ./pr/NR
|
||||
|
||||
- name: Generate comment markup
|
||||
run: node ./scripts/generateChangedIconsCommentMarkup.mts >> ./pr/comment-markup.md
|
||||
id: comment-markup
|
||||
env:
|
||||
CHANGED_FILES: ${{ steps.changed-files.outputs.all_changed_files }}
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: pr_number
|
||||
path: pr/
|
||||
109
.github/workflows/pull-request.yml
vendored
Normal file
109
.github/workflows/pull-request.yml
vendored
Normal file
@@ -0,0 +1,109 @@
|
||||
name: Add Changed Icons comment
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
paths:
|
||||
- 'icons/*.svg'
|
||||
branches:
|
||||
- main
|
||||
- fix-icon-preview
|
||||
|
||||
jobs:
|
||||
lint-filenames:
|
||||
if: github.repository == 'lucide-icons/lucide'
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
ref: refs/pull/${{ github.event.pull_request.number }}/merge
|
||||
- name: Get changed files
|
||||
id: changed-files
|
||||
uses: tj-actions/changed-files@v41
|
||||
with:
|
||||
files: icons/*
|
||||
- name: Generate annotations
|
||||
run: node ./scripts/lintFilenames.mjs
|
||||
env:
|
||||
CHANGED_FILES: ${{ steps.changed-files.outputs.all_changed_files }}
|
||||
|
||||
lint-contributors:
|
||||
if: github.repository == 'lucide-icons/lucide'
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
ref: refs/pull/${{ github.event.pull_request.number }}/merge
|
||||
- name: Get changed files
|
||||
id: changed-files
|
||||
uses: tj-actions/changed-files@v41
|
||||
with:
|
||||
files: icons/*
|
||||
- uses: actions/setup-node@v4
|
||||
- name: Install simple-git (safer and faster than installing all deps)
|
||||
run: npm install simple-git
|
||||
- name: Generate annotations
|
||||
run: node ./scripts/updateContributors.mjs
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
FETCH_DEPTH: ${{ github.event.pull_request.commits }}
|
||||
CHANGED_FILES: ${{ steps.changed-files.outputs.all_changed_files }}
|
||||
- name: Generate annotations
|
||||
env:
|
||||
ANNOTATION_SEVERITY: notice
|
||||
ANNOTATION_TITLE: Contributors have changed!
|
||||
ANNOTATION_DESCRIPTION: Don't add people who have only performed automatic optimizations.
|
||||
run: |
|
||||
git diff --unified=0 -- icons/*.json | # diff icon metadata (unified=0 gives the correct chunk line number)
|
||||
perl -ne '/^(\+|- |@)/ && print' | # get chunks (lines that start with "+++", "@@", "+ ", "- ")
|
||||
perl -pe 's/\n/%0A/' | # url encode line breaks (\n -> %0A)
|
||||
perl -pe 's/%0A(\+\+\+ b\/)/\n\1/g' | # split chunks(one chunk per line)
|
||||
perl -pe "s/\+\+\+ b\/([^@]*)%0A@@ -(\d+)[^\s]* \+(\d+)[^@]*@@(.*)/::$ANNOTATION_SEVERITY file=\1,line=\2,endLine=\3,title=$ANNOTATION_TITLE::$ANNOTATION_DESCRIPTION%0A\4/"
|
||||
# Example for the previous substitution
|
||||
# input: +++ b/icons/accessibility.json%0A@@ -2,0 +3 @@%0A+ "contributors": ["hi"],%0A@@ -13 +14 @@%0A+}%0A
|
||||
# output: ::$ANNOTATION_SEVERITY file=icons/accessibility.json,line=2,endLine=3,title=$ANNOTATION_TITLE::$ANNOTATION_DESCRIPTION%0A%0A+ "contributors": ["hi"],%0A@@ -13 +14 @@%0A+}%0A
|
||||
|
||||
generate-changed-icons-comment:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
ref: refs/pull/${{ github.event.pull_request.number }}/merge
|
||||
|
||||
- name: Get changed files
|
||||
id: changed-files
|
||||
uses: tj-actions/changed-files@v41
|
||||
with:
|
||||
files: icons/*.svg
|
||||
|
||||
- name: Find Comment
|
||||
uses: peter-evans/find-comment@v2
|
||||
id: pr-comment
|
||||
with:
|
||||
issue-number: ${{ github.event.pull_request.number }}
|
||||
comment-author: 'github-actions[bot]'
|
||||
body-includes: Added or changed icons
|
||||
|
||||
- name: Generate comment markup
|
||||
run: node ./scripts/generateChangedIconsCommentMarkup.mjs >> comment-markup.md
|
||||
id: comment-markup
|
||||
env:
|
||||
CHANGED_FILES: ${{ steps.changed-files.outputs.all_changed_files }}
|
||||
|
||||
- name: Create or update comment
|
||||
uses: peter-evans/create-or-update-comment@v3
|
||||
with:
|
||||
comment-id: ${{ steps.pr-comment.outputs.comment-id }}
|
||||
issue-number: ${{ github.event.pull_request.number }}
|
||||
body-path: ./comment-markup.md
|
||||
edit-mode: replace
|
||||
48
.github/workflows/release.yml
vendored
48
.github/workflows/release.yml
vendored
@@ -38,13 +38,10 @@ jobs:
|
||||
if: github.repository == 'lucide-icons/lucide'
|
||||
runs-on: ubuntu-latest
|
||||
needs: pre-release
|
||||
permissions:
|
||||
id-token: write
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
package:
|
||||
[
|
||||
package: [
|
||||
'lucide',
|
||||
'lucide-react',
|
||||
'lucide-react-native',
|
||||
@@ -54,16 +51,16 @@ jobs:
|
||||
'lucide-preact',
|
||||
'lucide-solid',
|
||||
'lucide-svelte',
|
||||
'@lucide/astro',
|
||||
'@lucide/svelte',
|
||||
]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: pnpm/action-setup@v4
|
||||
- uses: pnpm/action-setup@v2
|
||||
with:
|
||||
version: 8
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18
|
||||
cache: 'pnpm'
|
||||
node-version-file: 'package.json'
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install --frozen-lockfile
|
||||
@@ -81,24 +78,22 @@ jobs:
|
||||
run: pnpm --filter ${{ matrix.package }} test
|
||||
|
||||
- name: Publish
|
||||
run: pnpm --filter ${{ matrix.package }} publish --access public --no-git-checks --ignore-scripts
|
||||
env:
|
||||
NPM_CONFIG_PROVENANCE: true
|
||||
run: pnpm --filter ${{ matrix.package }} publish --no-git-checks --ignore-scripts
|
||||
|
||||
lucide-static:
|
||||
if: github.repository == 'lucide-icons/lucide'
|
||||
runs-on: ubuntu-latest
|
||||
needs: [pre-release, lucide-font]
|
||||
permissions:
|
||||
id-token: write
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/download-artifact@v4
|
||||
- uses: pnpm/action-setup@v4
|
||||
- uses: actions/download-artifact@v3
|
||||
- uses: pnpm/action-setup@v2
|
||||
with:
|
||||
version: 8
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18
|
||||
cache: 'pnpm'
|
||||
node-version-file: 'package.json'
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install --frozen-lockfile
|
||||
@@ -117,8 +112,6 @@ jobs:
|
||||
|
||||
- name: Publish
|
||||
run: pnpm --filter lucide-static publish --no-git-checks
|
||||
env:
|
||||
NPM_CONFIG_PROVENANCE: true
|
||||
|
||||
lucide-font:
|
||||
if: github.repository == 'lucide-icons/lucide'
|
||||
@@ -126,11 +119,13 @@ jobs:
|
||||
needs: pre-release
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: pnpm/action-setup@v4
|
||||
- uses: pnpm/action-setup@v2
|
||||
with:
|
||||
version: 8
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18
|
||||
cache: 'pnpm'
|
||||
node-version-file: 'package.json'
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install --frozen-lockfile
|
||||
@@ -141,8 +136,8 @@ jobs:
|
||||
- name: Create font in ./lucide-font
|
||||
run: pnpm build:font
|
||||
|
||||
- name: 'Upload to Artifacts'
|
||||
uses: actions/upload-artifact@v4
|
||||
- name: "Upload to Artifacts"
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: lucide-font
|
||||
path: lucide-font
|
||||
@@ -150,18 +145,21 @@ jobs:
|
||||
post-release:
|
||||
if: github.repository == 'lucide-icons/lucide'
|
||||
runs-on: ubuntu-latest
|
||||
needs: [pre-release, lucide-font]
|
||||
needs: [
|
||||
pre-release,
|
||||
lucide-font,
|
||||
]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/download-artifact@v4
|
||||
- uses: actions/download-artifact@v3
|
||||
- name: Zip font and icons
|
||||
run: |
|
||||
zip -r lucide-font-${{ needs.pre-release.outputs.VERSION }}.zip lucide-font
|
||||
zip -r lucide-icons-${{ needs.pre-release.outputs.VERSION }}.zip icons
|
||||
|
||||
- name: Release zip and fonts
|
||||
uses: softprops/action-gh-release@v2
|
||||
uses: softprops/action-gh-release@v1
|
||||
with:
|
||||
tag_name: ${{ needs.pre-release.outputs.VERSION }}
|
||||
files: |
|
||||
|
||||
32
.github/workflows/request-review.yml
vendored
32
.github/workflows/request-review.yml
vendored
@@ -1,32 +0,0 @@
|
||||
name: 'Request Review'
|
||||
on:
|
||||
pull_request_target:
|
||||
types: [opened]
|
||||
paths: icons/*.svg
|
||||
|
||||
jobs:
|
||||
request-review:
|
||||
if: github.event.pull_request.draft == false
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
ref: refs/pull/${{ github.event.pull_request.number }}/merge
|
||||
- name: Get changed files
|
||||
id: changed-files
|
||||
uses: tj-actions/changed-files@v41
|
||||
with:
|
||||
files: icons/*.svg
|
||||
- run: |
|
||||
while IFS= read -r file; do
|
||||
jq -r '.contributors[]' "${file%.svg}.json"
|
||||
done <<< "$CHANGED_FILES" | while read -r contributor; do
|
||||
gh pr edit "${{ github.event.pull_request.number }}" --add-reviewer "$contributor" || true
|
||||
done
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
CHANGED_FILES: ${{ steps.changed-files.outputs.all_changed_files }}
|
||||
9
.gitignore
vendored
9
.gitignore
vendored
@@ -16,17 +16,11 @@ outlined
|
||||
packages/**/src/icons/*.js
|
||||
packages/**/src/icons/*.ts
|
||||
packages/**/src/icons/*.tsx
|
||||
packages/**/src/aliases/*.ts
|
||||
packages/**/src/aliases.ts
|
||||
!packages/**/src/aliases/index.ts
|
||||
packages/**/src/dynamicIconImports.ts
|
||||
packages/**/DynamicIcon.d.ts
|
||||
packages/**/dynamicIconImports.js
|
||||
packages/**/dynamicIconImports.d.ts
|
||||
packages/**/dynamicIconImports.js.map
|
||||
packages/**/dynamic.d.ts
|
||||
packages/**/dynamic.mjs.map
|
||||
packages/**/dynamic.mjs
|
||||
packages/**/LICENSE
|
||||
categories.json
|
||||
tags.json
|
||||
@@ -40,10 +34,7 @@ docs/.vitepress/data/iconNodes
|
||||
docs/.vitepress/data/iconMetaData.ts
|
||||
docs/.vitepress/data/releaseMetaData.json
|
||||
docs/.vitepress/data/releaseMetaData
|
||||
docs/.vitepress/data/categoriesData.json
|
||||
docs/.vitepress/data/iconDetails
|
||||
docs/.vitepress/data/relatedIcons.json
|
||||
docs/.vercel
|
||||
docs/.nitro
|
||||
.gitignore
|
||||
|
||||
|
||||
@@ -1,12 +1,5 @@
|
||||
pnpm-lock.yaml
|
||||
|
||||
# docs examples
|
||||
docs/**/examples/
|
||||
docs/.vitepress/.temp
|
||||
docs/.vitepress/cache
|
||||
docs/.vitepress/data
|
||||
docs/.nitro
|
||||
|
||||
# lucide-angular
|
||||
packages/lucide-angular/.angular/cache
|
||||
|
||||
|
||||
11
.vscode/settings.json
vendored
11
.vscode/settings.json
vendored
@@ -1,6 +1,13 @@
|
||||
{
|
||||
"cSpell.words": ["devs", "preact", "Preact"],
|
||||
"cSpell.words": [
|
||||
"devs",
|
||||
"preact",
|
||||
"Preact"
|
||||
],
|
||||
"eslint.enable": true,
|
||||
"eslint.validate": ["javascript", "svg"],
|
||||
"eslint.validate": [
|
||||
"javascript",
|
||||
"svg"
|
||||
],
|
||||
"svg.preview.background": "transparent"
|
||||
}
|
||||
|
||||
2
.vscode/svg.code-snippets
vendored
2
.vscode/svg.code-snippets
vendored
@@ -49,7 +49,7 @@
|
||||
"circle",
|
||||
"<circle"
|
||||
],
|
||||
"body": "<circle cx=\"${2:12}\" cy=\"${3:$2}\" r=\"${1|10,2,.5\" fill=\"currentColor|}\" />"
|
||||
"body": "<circle cx=\"${2:12}\" cy=\"${3:$2}\" r=\"${1|10,2,.5|}\" />"
|
||||
},
|
||||
"Ellipse": {
|
||||
"scope": "xml",
|
||||
|
||||
@@ -16,10 +16,10 @@ Guidelines for pull requests:
|
||||
|
||||
- __Make your commit messages as descriptive as possible.__ Include as much information as you can. Explain anything that the file diffs themselves won’t make apparent.
|
||||
- __Document your pull request__. Explain your fix, link to the relevant issue, add screenshots when adding new icons.
|
||||
- __Make sure the target of your pull request is the relevant branch__. Most of bug fixes or new feature should go to the `main` branch.
|
||||
- __Include only related work__. If your pull request has unrelated commits, it won't be accepted.
|
||||
- __Make sure the target of your pull request is the relevant branch__. Most of bugfix or new feature should go to the `main` branch.
|
||||
- __Include only related work__. If your pull request has unrelated commit, it won't be accepted.
|
||||
|
||||
### Icon Pull Requests
|
||||
### Pull Requests Including Icons
|
||||
|
||||
#### Guidelines
|
||||
|
||||
@@ -27,30 +27,24 @@ Please make sure you follow the icon guidelines, that should be followed to keep
|
||||
|
||||
Read it here: [ICON_GUIDELINES](https://lucide.dev/docs/icon-design-guide).
|
||||
|
||||
#### Lucide Studio
|
||||
|
||||
For formatting and adjusting SVG icons, [@jguddas](https://github.com/jguddas) made a great tool called [Lucide Studio](https://studio.lucide.dev/). It is a web-based SVG editor that allows you to edit and adjust icons in the Lucide style. You can use it to create new icons or modify existing ones.
|
||||
|
||||
#### Editor guides
|
||||
### Editor guides
|
||||
|
||||
Here you can find instructions on how to implement the guidelines with different vector graphics editors:
|
||||
|
||||
##### [Adobe Illustrator Guide](https://lucide.dev/docs/illustrator-guide)
|
||||
#### [Adobe Illustrator Guide](https://lucide.dev/docs/illustrator-guide)
|
||||
|
||||
You can also [download an Adobe Illustrator template](https://github.com/lucide-icons/lucide/blob/main/docs/public/templates/illustrator_template.ai).
|
||||
|
||||
##### [Inkscape Guide](https://lucide.dev/docs/inkscape-guide)
|
||||
#### [Inkscape Guide](https://lucide.dev/docs/inkscape-guide)
|
||||
|
||||
##### [Figma Guide](https://lucide.dev/docs/figma-guide)
|
||||
#### [Figma Guide](https://lucide.dev/docs/figma-guide)
|
||||
|
||||
##### [Affinity Designer Guide](https://lucide.dev/guide/design/affinity-designer-guide)
|
||||
### Submitting Multiple Icons
|
||||
|
||||
#### Submitting Multiple Icons
|
||||
|
||||
If you want to submit multiple icons, please separate the icons and group them. That makes reviewing the icons easier and keeps the thread clean and scoped.
|
||||
So don't submit multiple icons in one PR that have nothing to do with each other.
|
||||
If you want submit multiple icons, please separate the icons and group them. That makes reviewing the icons easier and keep the thread clean and scoped.
|
||||
So don't submit multiple icons in one PR that have noting to do with each other.
|
||||
So for example don't create one PR with icons: `arrow-up`, `bicycle`, `arrow-down`.
|
||||
Separate them into two PRs; 'pr-01' `arrow`, `arrow-down` and 'pr-02' `bicycle`.
|
||||
Seperate them by two PRs; 'pr-01' `arrow`, `arrow-down` and 'pr-02' `bicycle`.
|
||||
|
||||
## Icon Requests
|
||||
|
||||
@@ -76,12 +70,12 @@ pnpm install # Install dependencies, including the workspace packages
|
||||
|
||||
### Packages -> PNPM Workspaces
|
||||
|
||||
To distribute different packages we use [PNPM workspaces](https://pnpm.io/workspaces). Before you start make sure you are familiar with this concept. The concept of working in workspaces is created by Yarn, they have a well written introduction: [yarn workspaces](https://classic.yarnpkg.com/en/docs/workspaces).
|
||||
To distribute different packages we use PNPM workspaces. Before you start make sure you are familiar with this concept. The concept of working in workspaces is created by Yarn, they have a well written introduction: [yarn workspaces](https://classic.yarnpkg.com/lang/enhttps://lucide.dev/docs/workspaces).
|
||||
|
||||
The configured directory for workspaces is the [packages](https://github.com/lucide-icons/lucide/tree/main/packages) directory, located in the root directory. There you will find all the current packages from lucide.
|
||||
There are more workspaces defined, see [`pnpm-workspace.yaml`](https://github.com/lucide-icons/lucide/blob/main/pnpm-workspace.yaml).
|
||||
|
||||
> Note: One package is not managed by pnpm: **lucide-flutter**, this package is written in Dart and uses pub for publishing.
|
||||
> Note: One package is not managed by pnpm: **lucide-flutter**, this package is written in Dart and used pub for publishing.
|
||||
|
||||
### Generated Code
|
||||
|
||||
@@ -131,7 +125,7 @@ When adding new features to for example the icon component for a framework. It i
|
||||
|
||||
### Local Testing
|
||||
|
||||
To test changes in a local project, you can use `yarn link`, `npm link`, `bun link` or `pnpm link` to link the package. Before you do this make sure you've built the package first.
|
||||
To test changes in a local project, you can use `yarn link`, `npm link` or `pnpm link` to link the package. Before you do this make sure you builded the package first.
|
||||
|
||||
```sh
|
||||
# in packages/lucide-react
|
||||
@@ -161,30 +155,6 @@ lucide
|
||||
|
||||
The lucide.dev website is using [vitepress](https://vitepress.dev/) to generate the static website. The markdown files are located in the docs directory.
|
||||
|
||||
#### Running the Docs Website Locally
|
||||
|
||||
To test the docs website locally, follow these steps:
|
||||
|
||||
1. **Navigate to the docs directory**
|
||||
|
||||
```sh
|
||||
cd docs
|
||||
```
|
||||
|
||||
2. **Start the Local Development Server**
|
||||
|
||||
```sh
|
||||
pnpm run docs:dev
|
||||
```
|
||||
|
||||
3. **Open the Website Locally**
|
||||
|
||||
Vitepress should open with the following format:
|
||||
|
||||
VitePress dev server is running at:
|
||||
- **Local**: `http://localhost:3000/`
|
||||
- **Network**: `http://192.168.x.x:3000/`
|
||||
|
||||
### Guides
|
||||
|
||||
Detailed documentation about: installation, guides, packages, design guides etc.
|
||||
@@ -193,13 +163,15 @@ Detailed documentation about: installation, guides, packages, design guides etc.
|
||||
|
||||
All the icons of lucide in SVG format. These will be used as source for all the packages and other distributions for the lucide icons.
|
||||
|
||||
### Packages
|
||||
### packages
|
||||
|
||||
Includes all the (npm) packages of lucide.
|
||||
|
||||
### Scripts
|
||||
> Note: One package is not managed by pnpm: **lucide-flutter**, this package is written in Dart and used pub for publishing.
|
||||
|
||||
Includes useful scripts to automate certain jobs. Big part of the scripts is the template generation, for example it generates icon components for all the packages. These scripts are usually executed from the "scripts" section in the package.json.
|
||||
### scripts
|
||||
|
||||
Includes usefully scripts to automate certain jobs. Big part of the scripts is the template generation, for example it generates icon components for all the packages. These scripts are usually executed from the "scripts" section in the package.json.
|
||||
|
||||
## Documentation
|
||||
|
||||
@@ -216,4 +188,4 @@ If you need any help or have problems with you contribution. Please don't hesita
|
||||
Thank you to all the people who already contributed to Lucide!
|
||||
|
||||
<a href="https://github.com/lucide-icons/lucide/graphs/contributors">
|
||||
<img src="https://opencollective.com/lucide-icons/contributors.svg?width=800" /></a>
|
||||
<img src="https://opencollective.com/lucide-icons/contributors.svg?width=890" /></a>
|
||||
|
||||
280
README.md
280
README.md
@@ -1,47 +1,185 @@
|
||||
<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>
|
||||
</p>
|
||||
<p align=center><img width="480" src="https://lucide.dev/lucide-logo-repo.svg" alt="Lucide Logo"></p>
|
||||
<p align="center">
|
||||
<a href="https://github.com/lucide-icons/lucide/blob/main/LICENSE"><img src="https://img.shields.io/npm/l/lucide" alt="license"></a>
|
||||
<a href="https://www.figma.com/community/plugin/939567362549682242/Lucide-Icons"><img src="https://img.shields.io/badge/Figma-F24E1E?logo=figma&logoColor=white" alt="figma installs"></a>
|
||||
<a href="https://www.npmjs.com/package/lucide"><img src="https://img.shields.io/npm/v/lucide" alt="npm package"></a>
|
||||
<a href="https://www.figma.com/community/plugin/939567362549682242/Lucide-Icons"><img src="https://img.shields.io/endpoint?logo=figma&label=installs&url=https://yuanqing.github.io/figma-plugins-stats/plugin/939567362549682242/installs.json" alt="figma installs"></a>
|
||||
<a href="https://github.com/lucide-icons/lucide/actions/workflows/release.yml"><img src="https://github.com/lucide-icons/lucide/actions/workflows/release.yml/badge.svg" alt="build status"></a>
|
||||
<a href="https://discord.gg/EH6nSts"><img src="https://img.shields.io/discord/723074157486800936?label=chat&logo=discord&logoColor=%23ffffff&colorB=%237289DA" alt="discord chat"></a>
|
||||
</p>
|
||||
<p align="center">
|
||||
<a href="https://lucide.dev/icons/">Icons</a>
|
||||
·
|
||||
<a href="https://lucide.dev/guide/">Guide</a>
|
||||
·
|
||||
<a href="https://lucide.dev/packages">Packages</a>
|
||||
·
|
||||
<a href="https://lucide.dev/license">License</a>
|
||||
·
|
||||
<a href="https://lucide.dev/showcase">Showcase</a>
|
||||
</p>
|
||||
|
||||
# Lucide
|
||||
|
||||
Lucide is an open-source icon library that provides 1000+ vector (svg) files for displaying icons and symbols in digital and non-digital projects. The library aims to make it easier for designers and developers to incorporate icons into their projects by providing several official [packages](https://lucide.dev/packages) to make it easier to use these icons in your project.
|
||||
Community-run fork of [Feather Icons](https://github.com/feathericons/feather), open for anyone to contribute icons.
|
||||
|
||||
## Packages
|
||||
It began after growing dissatisfaction with the [Feather Icons](https://github.com/feathericons/feather) project moderation. With over 300+ open issues and over 100+ open PRs, the Feather Icons project has been abandoned. This unfortunately means that hundreds of developers and designers wasted their time contributing to Feather Icons with no chance of PRs being accepted.
|
||||
|
||||
| Logo | Package | Version | Downloads | Links |
|
||||
| ---- | ------- | ------- | --------- | ----- |
|
||||
| <img src="https://lucide.dev/framework-logos/js.svg" alt="JS logo" width="48"> | **`lucide`** | [](https://www.npmjs.com/package/lucide) |  | [Docs](https://lucide.dev/guide/packages/lucide) · [Source](./packages/lucide) |
|
||||
| <img src="https://lucide.dev/framework-logos/react.svg" alt="React logo" width="48"> | **`lucide-react`** | [](https://www.npmjs.com/package/lucide-react) |  | [Docs](https://lucide.dev/guide/packages/lucide-react) · [Source](./packages/lucide-react) |
|
||||
| <img src="https://lucide.dev/framework-logos/vue.svg" alt="Vue logo" width="48"> | **`lucide-vue-next`** | [](https://www.npmjs.com/package/lucide-vue-next) |  | [Docs](https://lucide.dev/guide/packages/lucide-vue-next) · [Source](./packages/lucide-vue-next) |
|
||||
| <img src="https://lucide.dev/framework-logos/svelte.svg" alt="Svelte logo" width="48"> | **`lucide-svelte`** | [](https://www.npmjs.com/package/lucide-svelte) |  | [Docs](https://lucide.dev/guide/packages/lucide-svelte) · [Source](./packages/lucide-svelte) |
|
||||
| <img src="https://lucide.dev/framework-logos/solid.svg" alt="Solid logo" width="48"> | **`lucide-solid`** | [](https://www.npmjs.com/package/lucide-solid) |  | [Docs](https://lucide.dev/guide/packages/lucide-solid) · [Source](./packages/lucide-solid) |
|
||||
| <img src="https://lucide.dev/framework-logos/preact.svg" alt="Preact logo" width="48"> | **`lucide-preact`** | [](https://www.npmjs.com/package/lucide-preact) |  | [Docs](https://lucide.dev/guide/packages/lucide-preact) · [Source](./packages/lucide-preact) |
|
||||
| <img src="https://lucide.dev/framework-logos/react-native.svg" alt="React Native logo" width="48"> | **`lucide-react-native`** | [](https://www.npmjs.com/package/lucide-react-native) |  | [Docs](https://lucide.dev/guide/packages/lucide-react-native) · [Source](./packages/lucide-react-native) |
|
||||
| <img src="https://lucide.dev/framework-logos/angular.svg" alt="Angular logo" width="48"> | **`lucide-angular`** | [](https://www.npmjs.com/package/lucide-angular) |  | [Docs](https://lucide.dev/guide/packages/lucide-angular) · [Source](./packages/lucide-angular) |
|
||||
| <img src="https://lucide.dev/framework-logos/astro.svg" alt="Astro logo" width="48"> | **`@lucide/astro`** | [](https://www.npmjs.com/package/@lucide/astro) |  | [Docs](https://lucide.dev/guide/packages/lucide-astro) · [Source](./packages/astro) |
|
||||
| <img src="https://lucide.dev/framework-logos/svg.svg" alt="SVG logo" width="48"> | **`lucide-static`** | [](https://www.npmjs.com/package/lucide-static) |  | [Docs](https://lucide.dev/guide/packages/lucide-static) · [Source](./packages/lucide-static) |
|
||||
Lucide is trying to expand the icon set as much as possible while staying faithful to the original simplistic design language. We do this as a community of devs and designers and hope that you'll join us!
|
||||
|
||||
### Why choose Lucide over Feather Icons
|
||||
|
||||
- More icons to work with: Lucide already has hundreds of icons more than Feather does.
|
||||
- Official libraries and integrations with popular frameworks and design tools.
|
||||
- Well maintained code base.
|
||||
- Active community, regularly growing and improving the set.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
- [Usage](#usage)
|
||||
- [Web](#web)
|
||||
- [React](#react)
|
||||
- [React Native](#react-native)
|
||||
- [Vue 2](#vue-2)
|
||||
- [Vue 3](#vue-3)
|
||||
- [Angular](#angular)
|
||||
- [Preact](#preact)
|
||||
- [Static (svg sprite, font, icons ..)](#static-svg-sprite-font-icons-)
|
||||
- [Figma](#figma)
|
||||
- [Laravel](#laravel)
|
||||
- [Svelte](#svelte)
|
||||
- [Solid](#solid)
|
||||
- [Hyva](#hyva)
|
||||
- [Eleventy](#eleventy)
|
||||
- [Contributing](#contributing)
|
||||
- [Community](#community)
|
||||
- [License](#license)
|
||||
- [Credits](#credits)
|
||||
- [Sponsors](#sponsors)
|
||||
|
||||
## Usage
|
||||
|
||||
At its core, Lucide is a collection of [SVG](https://svgontheweb.com/#svg) files. This means that you can use Lucide icons in all the same ways you can use SVGs (e.g. `img`, `background-image`, `inline`, `object`, `embed`, `iframe`). Here's a helpful article detailing the many ways SVGs can be used on the web: [SVG on the Web – Implementation Options](https://svgontheweb.com/#implementation)
|
||||
|
||||
The following are additional ways you can use Lucide.
|
||||
With the Javascript library you can easily incorporate the icon you want in your webpage.
|
||||
|
||||
### Web
|
||||
|
||||
Implementation of the lucide icon library for web applications.
|
||||
|
||||
```sh
|
||||
npm install lucide
|
||||
```
|
||||
|
||||
or
|
||||
|
||||
```sh
|
||||
yarn add lucide
|
||||
```
|
||||
|
||||
For more details, see the [documentation](https://github.com/lucide-icons/lucide/tree/main/packages/lucide#lucide).
|
||||
|
||||
### React
|
||||
|
||||
Implementation of the lucide icon library for react applications.
|
||||
|
||||
```sh
|
||||
yarn add lucide-react
|
||||
```
|
||||
|
||||
or
|
||||
|
||||
```sh
|
||||
npm install lucide-react
|
||||
```
|
||||
|
||||
For more details, see the [documentation](https://github.com/lucide-icons/lucide/tree/main/packages/lucide-react#lucide-react).
|
||||
|
||||
### React Native
|
||||
|
||||
Implementation of the lucide icon library for React Native applications.
|
||||
|
||||
```sh
|
||||
yarn add lucide-react-native
|
||||
```
|
||||
|
||||
or
|
||||
|
||||
```sh
|
||||
npm install lucide-react-native
|
||||
```
|
||||
|
||||
For more details, see the [documentation](https://github.com/lucide-icons/lucide/tree/main/packages/lucide-react-native#lucide-react-native).
|
||||
|
||||
### Vue 2
|
||||
|
||||
Implementation of the lucide icon library for vue applications.
|
||||
|
||||
```sh
|
||||
yarn add lucide-vue
|
||||
```
|
||||
|
||||
or
|
||||
|
||||
```sh
|
||||
npm install lucide-vue
|
||||
```
|
||||
|
||||
For more details, see the [documentation](https://github.com/lucide-icons/lucide/tree/main/packages/lucide-vue#lucide-vue).
|
||||
|
||||
### Vue 3
|
||||
|
||||
Implementation of the lucide icon library for vue applications.
|
||||
|
||||
```sh
|
||||
yarn add lucide-vue-next
|
||||
```
|
||||
|
||||
or
|
||||
|
||||
```sh
|
||||
npm install lucide-vue-next
|
||||
```
|
||||
|
||||
For more details, see the [documentation](https://github.com/lucide-icons/lucide/tree/main/packages/lucide-vue-next#lucide-vue-next).
|
||||
|
||||
### Angular
|
||||
|
||||
```sh
|
||||
yarn add lucide-angular
|
||||
```
|
||||
|
||||
or
|
||||
|
||||
```sh
|
||||
npm install lucide-angular
|
||||
```
|
||||
|
||||
For more details, see the [documentation](https://github.com/lucide-icons/lucide/tree/main/packages/lucide-angular#lucide-angular).
|
||||
|
||||
### Preact
|
||||
|
||||
Implementation of the lucide icon library for preact applications.
|
||||
|
||||
```sh
|
||||
yarn add lucide-preact
|
||||
```
|
||||
|
||||
or
|
||||
|
||||
```sh
|
||||
npm install lucide-preact
|
||||
```
|
||||
|
||||
For more details, see the [documentation](https://github.com/lucide-icons/lucide/tree/main/packages/lucide-preact#lucide-preact).
|
||||
|
||||
### Static (svg sprite, font, icons ..)
|
||||
|
||||
Assets:
|
||||
[Font Files](https://github.com/lucide-icons/lucide/releases/latest)
|
||||
[SVG Files](https://github.com/lucide-icons/lucide/releases/latest)
|
||||
[SVG Sprite](https://cdn.jsdelivr.net/npm/lucide-static@latest/sprite.svg)
|
||||
|
||||
NPM package
|
||||
|
||||
```sh
|
||||
yarn add lucide-static
|
||||
```
|
||||
|
||||
or
|
||||
|
||||
```sh
|
||||
npm install lucide-static
|
||||
```
|
||||
|
||||
### Figma
|
||||
|
||||
@@ -51,6 +189,68 @@ Visit [Figma community page](https://www.figma.com/community/plugin/939567362549
|
||||
|
||||
<img width="420" src="https://www.figma.com/community/plugin/939567362549682242/thumbnail" alt="Figma Lucide Cover">
|
||||
|
||||
### Laravel
|
||||
|
||||
Implementation of Lucide icon's using `blade-icons` for Laravel based projects.
|
||||
|
||||
```sh
|
||||
composer require mallardduck/blade-lucide-icons
|
||||
```
|
||||
|
||||
For more details, see the [documentation](https://github.com/mallardduck/blade-lucide-icons/blob/main/README.md).
|
||||
|
||||
### Svelte
|
||||
|
||||
Implementation of the lucide icon library for Svelte applications.
|
||||
|
||||
```sh
|
||||
yarn add lucide-svelte
|
||||
```
|
||||
|
||||
or
|
||||
|
||||
```sh
|
||||
npm install lucide-svelte
|
||||
```
|
||||
|
||||
For more details, see the [documentation](https://github.com/lucide-icons/lucide/tree/main/packages/lucide-svelte#lucide-svelte).
|
||||
|
||||
### Solid
|
||||
|
||||
Implementation of the lucide icon library for solid applications.
|
||||
|
||||
```sh
|
||||
yarn add lucide-solid
|
||||
```
|
||||
|
||||
or
|
||||
|
||||
```sh
|
||||
npm install lucide-solid
|
||||
```
|
||||
|
||||
For more details, see the [documentation](https://github.com/lucide-icons/lucide/tree/main/packages/lucide-solid#lucide-solid).
|
||||
|
||||
### Hyva
|
||||
|
||||
Implementation of Lucide icon's using Hyvä's svg php viewmodal to render icons for Magento 2 Hyva theme based projects.
|
||||
|
||||
```sh
|
||||
composer require siteation/magento2-hyva-icons-lucide
|
||||
```
|
||||
|
||||
For more details, see the [documentation](https://github.com/Siteation/magento2-hyva-icons-lucide/blob/main/README.md).
|
||||
|
||||
### Eleventy
|
||||
|
||||
Using this plugin, Eleventy projects can incorporate Lucide icons. it makes it simple to use Lucide icons into your themes via shortcodes, improving your website's overall usability and visual appeal.
|
||||
|
||||
```sh
|
||||
npm install @grimlink/eleventy-plugin-lucide-icons
|
||||
```
|
||||
|
||||
For more details, see the [documentation](https://github.com/GrimLink/eleventy-plugin-lucide-icons/blob/main/README.md).
|
||||
|
||||
## Contributing
|
||||
|
||||
For more info on how to contribute please see the [contribution guidelines](https://github.com/lucide-icons/lucide/blob/main/CONTRIBUTING.md).
|
||||
@@ -63,26 +263,20 @@ Join the community on our [Discord](https://discord.gg/EH6nSts) server!
|
||||
|
||||
## License
|
||||
|
||||
Lucide is totally free for commercial use and personal use, this software is licensed under the [ISC License](https://github.com/lucide-icons/lucide/blob/main/LICENSE).
|
||||
Lucide is totally free for commercial use and personally use, this software is licensed under the [ISC License](https://github.com/lucide-icons/lucide/blob/main/LICENSE).
|
||||
|
||||
## Credits
|
||||
|
||||
Thank you to all the people who contributed to Lucide!
|
||||
|
||||
<a href="https://github.com/lucide-icons/lucide/graphs/contributors">
|
||||
|
||||
<img src="https://opencollective.com/lucide-icons/contributors.svg?width=800" />
|
||||
</a>
|
||||
<img src="https://opencollective.com/lucide-icons/contributors.svg?width=890" /></a>
|
||||
|
||||
## Sponsors
|
||||
|
||||
|
||||
<a href="https://vercel.com?utm_source=lucide&utm_campaign=oss">
|
||||
<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>
|
||||
|
||||
### Awesome backers 🍺
|
||||
|
||||
<a href="https://www.scipress.io?utm_source=lucide"><img src="docs/public/sponsors/scipress.svg" width="180" alt="Scipress sponsor badge" /></a>
|
||||
<a href="https://github.com/pdfme/pdfme"><img src="docs/public/sponsors/pdfme.svg" width="180" alt="pdfme sponsor badge" /></a>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"$schema": "../category.schema.json",
|
||||
"title": "Charts",
|
||||
"icon": "chart-pie"
|
||||
"icon": "pie-chart"
|
||||
}
|
||||
5
categories/currency.json
Normal file
5
categories/currency.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"$schema": "../category.schema.json",
|
||||
"title": "Currency",
|
||||
"icon": "dollar-sign"
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"$schema": "../category.schema.json",
|
||||
"title": "Coding & development",
|
||||
"icon": "code-xml"
|
||||
"icon": "code-2"
|
||||
}
|
||||
|
||||
5
categories/furniture.json
Normal file
5
categories/furniture.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"$schema": "../category.schema.json",
|
||||
"title": "Furniture",
|
||||
"icon": "rocking-chair"
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"$schema": "../category.schema.json",
|
||||
"title": "Home",
|
||||
"icon": "house"
|
||||
"icon": "home"
|
||||
}
|
||||
5
categories/maps.json
Normal file
5
categories/maps.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"$schema": "../category.schema.json",
|
||||
"title": "Maps",
|
||||
"icon": "map"
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"$schema": "../category.schema.json",
|
||||
"title": "Mathematics",
|
||||
"title": "Maths",
|
||||
"icon": "divide"
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"$schema": "../category.schema.json",
|
||||
"title": "Finance",
|
||||
"title": "Money",
|
||||
"icon": "piggy-bank"
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"$schema": "../category.schema.json",
|
||||
"title": "Multimedia",
|
||||
"icon": "circle-play"
|
||||
"icon": "play-circle"
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"$schema": "../category.schema.json",
|
||||
"title": "Notification",
|
||||
"icon": "triangle-alert"
|
||||
"title": "Notifications",
|
||||
"icon": "alert-triangle"
|
||||
}
|
||||
10
cspell.json
10
cspell.json
@@ -1,10 +0,0 @@
|
||||
{
|
||||
"dictionaries": ["en-us", "custom-words"],
|
||||
"dictionaryDefinitions": [
|
||||
{
|
||||
"name": "custom-words",
|
||||
"path": "./.cspell/custom-words.txt",
|
||||
"addWords": true
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,10 +1,11 @@
|
||||
import iconMetaData from '../../data/iconMetaData';
|
||||
import { eventHandler, setResponseHeader } from 'h3'
|
||||
import iconMetaData from '../../data/iconMetaData'
|
||||
|
||||
export default eventHandler((event) => {
|
||||
setResponseHeader(event, 'Cache-Control', 'public, max-age=86400');
|
||||
setResponseHeader(event, 'Access-Control-Allow-Origin', '*');
|
||||
setResponseHeader(event, 'Cache-Control', 'public, max-age=86400')
|
||||
setResponseHeader(event, 'Access-Control-Allow-Origin', '*')
|
||||
|
||||
return Object.fromEntries(
|
||||
Object.entries(iconMetaData).map(([name, { categories }]) => [name, categories]),
|
||||
);
|
||||
});
|
||||
Object.entries(iconMetaData).map(([name, { categories }]) => [ name, categories ])
|
||||
)
|
||||
})
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
import iconNodes from '../../data/iconNodes/index.ts';
|
||||
import { IconNodeWithKeys } from '../../theme/types';
|
||||
import iconMetaData from '../../data/iconMetaData';
|
||||
import releaseMeta from '../../data/releaseMetaData.json';
|
||||
import categories from '../../data/categoriesData.json';
|
||||
|
||||
const dataResponse = {
|
||||
icons: Object.entries(iconNodes).reduce((acc, [name, iconNode]) => {
|
||||
const newIconNode = (iconNode as IconNodeWithKeys).map(([name, { key, ...attrs }]) => {
|
||||
return [name, attrs];
|
||||
});
|
||||
|
||||
acc[name] = {
|
||||
iconNode: newIconNode,
|
||||
aliases: (iconMetaData[name]?.aliases ?? []).map((alias) =>
|
||||
typeof alias === 'string' ? alias : alias.name,
|
||||
),
|
||||
tags: iconMetaData[name].tags ?? [],
|
||||
categories: iconMetaData[name].categories ?? [],
|
||||
...releaseMeta[name],
|
||||
};
|
||||
|
||||
return acc;
|
||||
}, {}),
|
||||
aliases: Object.entries(iconNodes).reduce((acc, [name]) => {
|
||||
for (const alias of iconMetaData[name]?.aliases ?? []) {
|
||||
acc[typeof alias === 'string' ? alias : alias.name] = name;
|
||||
}
|
||||
|
||||
return acc;
|
||||
}, {}),
|
||||
categories,
|
||||
};
|
||||
|
||||
export default eventHandler((event) => {
|
||||
setResponseHeader(event, 'Cache-Control', 'public, max-age=86400');
|
||||
setResponseHeader(event, 'Access-Control-Allow-Origin', '*');
|
||||
|
||||
return dataResponse;
|
||||
});
|
||||
@@ -13,10 +13,7 @@ export default eventHandler((event) => {
|
||||
const data = pathData.at(-1).slice(0, -4);
|
||||
const [name] = pathData;
|
||||
|
||||
const src = Buffer.from(data, 'base64')
|
||||
.toString('utf8')
|
||||
.replaceAll('\n', '')
|
||||
.replace(/<svg[^>]*>|<\/svg>/g, '');
|
||||
const src = Buffer.from(data, 'base64').toString('utf8');
|
||||
|
||||
const children = [];
|
||||
|
||||
@@ -28,25 +25,25 @@ export default eventHandler((event) => {
|
||||
.map((_, idx, arr) => arr.slice(0, idx + 1).join('-'))
|
||||
.reverse()
|
||||
.find((groupName) => groupName in iconNodes);
|
||||
if (!(name in iconNodes) && backdropName) {
|
||||
if (backdropName) {
|
||||
const iconNode = iconNodes[backdropName];
|
||||
|
||||
const LucideIcon = createLucideIcon(backdropName, iconNode);
|
||||
const svg = renderToStaticMarkup(createElement(LucideIcon));
|
||||
const backdropString = svg.replaceAll('\n', '').replace(/<svg[^>]*>|<\/svg>/g, '');
|
||||
const backdropString = svg.replace(/<svg[^>]*>|<\/svg>/g, '');
|
||||
|
||||
children.push(
|
||||
createElement(Backdrop, {
|
||||
backdropString,
|
||||
src,
|
||||
color: '#777',
|
||||
}),
|
||||
color: name in iconNodes ? 'red' : '#777',
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
const svg = Buffer.from(
|
||||
// We can't use jsx here, is not supported here by nitro.
|
||||
renderToString(createElement(SvgPreview, { src, showGrid: true }, children)),
|
||||
renderToString(createElement(SvgPreview, { src, showGrid: true }, children))
|
||||
).toString('utf8');
|
||||
|
||||
defaultContentType(event, 'image/svg+xml');
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
import { eventHandler, setResponseHeader, defaultContentType } from 'h3';
|
||||
import { renderToString, renderToStaticMarkup } from 'react-dom/server';
|
||||
import { createElement } from 'react';
|
||||
import Diff from '../../../lib/SvgPreview/Diff.tsx';
|
||||
import iconNodes from '../../../data/iconNodes';
|
||||
import createLucideIcon from 'lucide-react/src/createLucideIcon';
|
||||
|
||||
export default eventHandler((event) => {
|
||||
const { params } = event.context;
|
||||
|
||||
const pathData = params.data.split('/');
|
||||
const data = pathData.at(-1).slice(0, -4);
|
||||
const [name] = pathData;
|
||||
|
||||
const newSrc = Buffer.from(data, 'base64')
|
||||
.toString('utf8')
|
||||
.replaceAll('\n', '')
|
||||
.replace(/<svg[^>]*>|<\/svg>/g, '');
|
||||
|
||||
const children = [];
|
||||
|
||||
const oldSrc = iconNodes[name]
|
||||
? renderToStaticMarkup(createElement(createLucideIcon(name, iconNodes[name])))
|
||||
.replaceAll('\n', '')
|
||||
.replace(/<svg[^>]*>|<\/svg>/g, '')
|
||||
: '';
|
||||
|
||||
const svg = Buffer.from(
|
||||
// We can't use jsx here, is not supported here by nitro.
|
||||
renderToString(createElement(Diff, { oldSrc, newSrc, showGrid: true }, children)),
|
||||
).toString('utf8');
|
||||
|
||||
defaultContentType(event, 'image/svg+xml');
|
||||
setResponseHeader(event, 'Cache-Control', 'public,max-age=31536000');
|
||||
|
||||
return svg;
|
||||
});
|
||||
@@ -28,7 +28,7 @@ export default eventHandler(async (event) => {
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
`,
|
||||
`
|
||||
);
|
||||
|
||||
const resvg = new Resvg(svg, { background: '#000' });
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import { eventHandler, setResponseHeader, defaultContentType } from 'h3';
|
||||
import { renderToString } from 'react-dom/server';
|
||||
import { createElement } from 'react';
|
||||
import { eventHandler, setResponseHeader, defaultContentType } from 'h3'
|
||||
import { renderToString } from 'react-dom/server'
|
||||
import { createElement } from 'react'
|
||||
import SvgPreview from '../../../lib/SvgPreview/index.tsx';
|
||||
import createLucideIcon, { IconNode } from 'lucide-react/src/createLucideIcon';
|
||||
import createLucideIcon, { IconNode } from 'lucide-react/src/createLucideIcon'
|
||||
import { parseSync } from 'svgson';
|
||||
|
||||
export default eventHandler((event) => {
|
||||
const { params } = event.context;
|
||||
const { params } = event.context
|
||||
|
||||
const [strokeWidth, svgData] = params.data.split('/');
|
||||
const data = svgData.slice(0, -4);
|
||||
@@ -16,8 +16,8 @@ export default eventHandler((event) => {
|
||||
const Icon = createLucideIcon(
|
||||
'icon',
|
||||
parseSync(src.includes('<svg') ? src : `<svg>${src}</svg>`).children.map(
|
||||
({ name, attributes }) => [name, attributes],
|
||||
) as IconNode,
|
||||
({ name, attributes }) => [name, attributes]
|
||||
) as IconNode
|
||||
);
|
||||
|
||||
const svg = Buffer.from(
|
||||
@@ -33,12 +33,12 @@ export default eventHandler((event) => {
|
||||
@media screen and (prefers-color-scheme: dark) {
|
||||
svg { stroke: #fff; fill: transparent !important; }
|
||||
}
|
||||
</style>`,
|
||||
),
|
||||
</style>`
|
||||
)
|
||||
).toString('utf8');
|
||||
|
||||
defaultContentType(event, 'image/svg+xml');
|
||||
setResponseHeader(event, 'Cache-Control', 'public,max-age=31536000');
|
||||
defaultContentType(event, 'image/svg+xml')
|
||||
setResponseHeader(event, 'Cache-Control', 'public,max-age=31536000')
|
||||
|
||||
return svg;
|
||||
});
|
||||
return svg
|
||||
})
|
||||
|
||||
@@ -1,30 +1,30 @@
|
||||
import { eventHandler, getQuery, setResponseHeader } from 'h3';
|
||||
import iconNodes from '../../data/iconNodes';
|
||||
import { IconNodeWithKeys } from '../../theme/types';
|
||||
import { eventHandler, getQuery, setResponseHeader } from 'h3'
|
||||
import iconNodes from '../../data/iconNodes'
|
||||
import { IconNodeWithKeys } from '../../theme/types'
|
||||
|
||||
export default eventHandler((event) => {
|
||||
const query = getQuery(event);
|
||||
const query = getQuery(event)
|
||||
|
||||
const withUniqueKeys = query.withUniqueKeys === 'true';
|
||||
const withUniqueKeys = query.withUniqueKeys === 'true'
|
||||
|
||||
setResponseHeader(event, 'Cache-Control', 'public, max-age=86400');
|
||||
setResponseHeader(event, 'Access-Control-Allow-Origin', '*');
|
||||
setResponseHeader(event, 'Cache-Control', 'public, max-age=86400')
|
||||
setResponseHeader(event, 'Access-Control-Allow-Origin', '*')
|
||||
|
||||
if (withUniqueKeys) {
|
||||
return iconNodes;
|
||||
return iconNodes
|
||||
}
|
||||
|
||||
return Object.entries(iconNodes).reduce((acc, [name, iconNode]) => {
|
||||
if (withUniqueKeys) {
|
||||
return [name, iconNode];
|
||||
return [name, iconNode]
|
||||
}
|
||||
|
||||
const newIconNode = (iconNode as IconNodeWithKeys).map(([name, { key, ...attrs }]) => {
|
||||
return [name, attrs];
|
||||
});
|
||||
const newIconNode = (iconNode as IconNodeWithKeys).map(([name, { key, ...attrs}]) => {
|
||||
return [name, attrs]
|
||||
})
|
||||
|
||||
acc[name] = newIconNode;
|
||||
acc[name] = newIconNode
|
||||
|
||||
return acc;
|
||||
}, {});
|
||||
});
|
||||
return acc
|
||||
}, {})
|
||||
})
|
||||
|
||||
@@ -1,29 +1,29 @@
|
||||
import { eventHandler, getQuery, setResponseHeader, createError } from 'h3';
|
||||
import iconNodes from '../../data/iconNodes';
|
||||
import createLucideIcon from 'lucide-react/src/createLucideIcon';
|
||||
import { renderToString } from 'react-dom/server';
|
||||
import { createElement } from 'react';
|
||||
import { eventHandler, getQuery, setResponseHeader, createError } from 'h3'
|
||||
import iconNodes from '../../data/iconNodes'
|
||||
import createLucideIcon from 'lucide-react/src/createLucideIcon'
|
||||
import { renderToString } from 'react-dom/server'
|
||||
import { createElement } from 'react'
|
||||
|
||||
export default eventHandler((event) => {
|
||||
const { params } = event.context;
|
||||
const { params } = event.context
|
||||
|
||||
const iconNode = iconNodes[params.iconName];
|
||||
const iconNode = iconNodes[params.iconName]
|
||||
|
||||
if (iconNode == null) {
|
||||
const error = createError({
|
||||
statusCode: 404,
|
||||
message: `Icon "${params.iconName}" not found`,
|
||||
});
|
||||
})
|
||||
|
||||
return sendError(event, error);
|
||||
return sendError(event, error)
|
||||
}
|
||||
|
||||
const width = getQuery(event).width || undefined;
|
||||
const height = getQuery(event).height || undefined;
|
||||
const color = getQuery(event).color || undefined;
|
||||
const strokeWidth = getQuery(event).strokeWidth || undefined;
|
||||
const width = getQuery(event).width || undefined
|
||||
const height = getQuery(event).height || undefined
|
||||
const color = getQuery(event).color || undefined
|
||||
const strokeWidth = getQuery(event).strokeWidth || undefined
|
||||
|
||||
const LucideIcon = createLucideIcon(params.iconName, iconNode);
|
||||
const LucideIcon = createLucideIcon(params.iconName, iconNode)
|
||||
|
||||
const svg = Buffer.from(
|
||||
renderToString(
|
||||
@@ -32,13 +32,14 @@ export default eventHandler((event) => {
|
||||
height,
|
||||
color: color ? `#${color}` : undefined,
|
||||
strokeWidth,
|
||||
}),
|
||||
),
|
||||
}
|
||||
))
|
||||
).toString('utf8');
|
||||
|
||||
defaultContentType(event, 'image/svg+xml');
|
||||
setResponseHeader(event, 'Cache-Control', 'public,max-age=31536000');
|
||||
setResponseHeader(event, 'Access-Control-Allow-Origin', '*');
|
||||
defaultContentType(event, 'image/svg+xml')
|
||||
setResponseHeader(event, 'Cache-Control', 'public,max-age=31536000')
|
||||
setResponseHeader(event, 'Access-Control-Allow-Origin', '*')
|
||||
|
||||
return svg;
|
||||
});
|
||||
return svg
|
||||
|
||||
})
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
import iconMetaData from '../../data/iconMetaData';
|
||||
import { eventHandler, setResponseHeader } from 'h3'
|
||||
import iconMetaData from '../../data/iconMetaData'
|
||||
|
||||
export default eventHandler((event) => {
|
||||
setResponseHeader(event, 'Cache-Control', 'public, max-age=86400');
|
||||
setResponseHeader(event, 'Access-Control-Allow-Origin', '*');
|
||||
setResponseHeader(event, 'Cache-Control', 'public, max-age=86400')
|
||||
setResponseHeader(event, 'Access-Control-Allow-Origin', '*')
|
||||
|
||||
return Object.fromEntries(Object.entries(iconMetaData).map(([name, { tags }]) => [name, tags]));
|
||||
});
|
||||
return Object.fromEntries(
|
||||
Object.entries(iconMetaData).map(([name, { tags }]) => [ name, tags ])
|
||||
)
|
||||
})
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
export default eventHandler(() => {
|
||||
return { nitro: 'Is Awesome! asda' };
|
||||
});
|
||||
return { nitro: 'Is Awesome! asda' }
|
||||
})
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { fileURLToPath, URL } from 'node:url';
|
||||
import { defineConfig } from 'vitepress';
|
||||
import { fileURLToPath, URL } from 'node:url'
|
||||
import { defineConfig } from 'vitepress'
|
||||
import sidebar from './sidebar';
|
||||
|
||||
const title = 'Lucide';
|
||||
const socialTitle = 'Lucide Icons';
|
||||
const description = 'Beautiful & consistent icon toolkit made by the community.';
|
||||
const title = "Lucide";
|
||||
const socialTitle = "Lucide Icons";
|
||||
const description = "Beautiful & consistent icon toolkit made by the community."
|
||||
|
||||
// https://vitepress.dev/reference/site-config
|
||||
export default defineConfig({
|
||||
@@ -19,135 +19,86 @@ export default defineConfig({
|
||||
{
|
||||
find: /^.*\/VPIconAlignLeft\.vue$/,
|
||||
replacement: fileURLToPath(
|
||||
new URL('./theme/components/overrides/VPIconAlignLeft.vue', import.meta.url),
|
||||
),
|
||||
new URL('./theme/components/overrides/VPIconAlignLeft.vue', import.meta.url)
|
||||
)
|
||||
},
|
||||
{
|
||||
find: /^.*\/VPFooter\.vue$/,
|
||||
replacement: fileURLToPath(
|
||||
new URL('./theme/components/overrides/VPFooter.vue', import.meta.url),
|
||||
),
|
||||
},
|
||||
{
|
||||
find: '~/.vitepress',
|
||||
replacement: fileURLToPath(new URL('./', import.meta.url)),
|
||||
},
|
||||
],
|
||||
new URL('./theme/components/overrides/VPFooter.vue', import.meta.url)
|
||||
)
|
||||
}
|
||||
]
|
||||
},
|
||||
},
|
||||
head: [
|
||||
[
|
||||
'script',
|
||||
{
|
||||
[ 'script', {
|
||||
src: 'https://analytics.lucide.dev/js/script.js',
|
||||
'data-domain': 'lucide.dev',
|
||||
defer: '',
|
||||
},
|
||||
],
|
||||
[
|
||||
'meta',
|
||||
{
|
||||
property: 'og:locale',
|
||||
content: 'en_US',
|
||||
},
|
||||
],
|
||||
[
|
||||
'meta',
|
||||
{
|
||||
property: 'og:type',
|
||||
content: 'website',
|
||||
},
|
||||
],
|
||||
[
|
||||
'meta',
|
||||
{
|
||||
property: 'og:site_name',
|
||||
defer: ''
|
||||
}],
|
||||
[ 'meta', {
|
||||
property:"og:locale",
|
||||
content:"en_US"
|
||||
}],
|
||||
[ 'meta', {
|
||||
property:"og:type",
|
||||
content:"website"
|
||||
}],
|
||||
[ 'meta', {
|
||||
property:"og:site_name",
|
||||
content: title,
|
||||
},
|
||||
],
|
||||
[
|
||||
'meta',
|
||||
{
|
||||
property: 'og:title',
|
||||
}],
|
||||
[ 'meta', {
|
||||
property:"og:title",
|
||||
content: socialTitle,
|
||||
},
|
||||
],
|
||||
[
|
||||
'meta',
|
||||
{
|
||||
property: 'og:description',
|
||||
content: description,
|
||||
},
|
||||
],
|
||||
[
|
||||
'meta',
|
||||
{
|
||||
property: 'og:url',
|
||||
content: 'https://lucide.dev',
|
||||
},
|
||||
],
|
||||
[
|
||||
'meta',
|
||||
{
|
||||
property: 'og:image',
|
||||
content: 'https://lucide.dev/og.png',
|
||||
},
|
||||
],
|
||||
[
|
||||
'meta',
|
||||
{
|
||||
property: 'og:image:width',
|
||||
content: '1200',
|
||||
},
|
||||
],
|
||||
[
|
||||
'meta',
|
||||
{
|
||||
property: 'og:image:height',
|
||||
content: '630',
|
||||
},
|
||||
],
|
||||
[
|
||||
'meta',
|
||||
{
|
||||
property: 'og:image:type',
|
||||
content: 'image/png',
|
||||
},
|
||||
],
|
||||
[
|
||||
'meta',
|
||||
{
|
||||
property: 'twitter:card',
|
||||
content: 'summary_large_image',
|
||||
},
|
||||
],
|
||||
[
|
||||
'meta',
|
||||
{
|
||||
property: 'twitter:title',
|
||||
}],
|
||||
[ 'meta', {
|
||||
property:"og:description",
|
||||
content: description
|
||||
}],
|
||||
[ 'meta', {
|
||||
property:"og:url",
|
||||
content:"https://lucide.dev"
|
||||
}],
|
||||
[ 'meta', {
|
||||
property:"og:image",
|
||||
content: "https://lucide.dev/og.png"
|
||||
}],
|
||||
[ 'meta', {
|
||||
property:"og:image:width",
|
||||
content:"1200"
|
||||
}],
|
||||
[ 'meta', {
|
||||
property:"og:image:height",
|
||||
content:"630"
|
||||
}],
|
||||
[ 'meta', {
|
||||
property:"og:image:type",
|
||||
content:"image/png"
|
||||
}],
|
||||
[ 'meta', {
|
||||
property:"twitter:card",
|
||||
content:"summary_large_image"
|
||||
}],
|
||||
[ 'meta', {
|
||||
property:"twitter:title",
|
||||
content: socialTitle,
|
||||
},
|
||||
],
|
||||
[
|
||||
'meta',
|
||||
{
|
||||
property: 'twitter:description',
|
||||
content: description,
|
||||
},
|
||||
],
|
||||
[
|
||||
'meta',
|
||||
{
|
||||
property: 'twitter:image',
|
||||
content: 'https://lucide.dev/og.png',
|
||||
},
|
||||
],
|
||||
}],
|
||||
[ 'meta', {
|
||||
property:"twitter:description",
|
||||
content: description
|
||||
}],
|
||||
[ 'meta', {
|
||||
property:"twitter:image",
|
||||
content:"https://lucide.dev/og.png"
|
||||
}],
|
||||
],
|
||||
themeConfig: {
|
||||
// https://vitepress.dev/reference/default-theme-config
|
||||
logo: {
|
||||
light: '/logo.light.svg',
|
||||
dark: '/logo.dark.svg',
|
||||
dark: '/logo.dark.svg'
|
||||
},
|
||||
nav: [
|
||||
{ text: 'Icons', link: '/icons/' },
|
||||
@@ -159,21 +110,21 @@ export default defineConfig({
|
||||
sidebar,
|
||||
socialLinks: [
|
||||
{ icon: 'github', link: 'https://github.com/lucide-icons/lucide' },
|
||||
{ icon: 'discord', link: 'https://discord.gg/EH6nSts' },
|
||||
{ icon: 'discord', link: 'https://discord.gg/EH6nSts' }
|
||||
],
|
||||
footer: {
|
||||
message: 'Released under the ISC License.',
|
||||
copyright: `Copyright © ${new Date().getFullYear()} Lucide Contributors`,
|
||||
copyright: `Copyright © ${new Date().getFullYear()} Lucide Contributors`
|
||||
},
|
||||
editLink: {
|
||||
pattern: 'https://github.com/lucide-icons/lucide/edit/main/docs/:path',
|
||||
pattern: 'https://github.com/lucide-icons/lucide/edit/main/docs/:path'
|
||||
},
|
||||
carbonAds: {
|
||||
code: 'CWYIC53U',
|
||||
placement: 'lucidedev',
|
||||
},
|
||||
placement: 'lucidedev'
|
||||
}
|
||||
},
|
||||
sitemap: {
|
||||
hostname: 'https://lucide.dev/',
|
||||
},
|
||||
});
|
||||
hostname: 'https://lucide.dev/'
|
||||
}
|
||||
})
|
||||
|
||||
@@ -1,174 +0,0 @@
|
||||
[
|
||||
{
|
||||
"name": "accessibility",
|
||||
"title": "Accessibility"
|
||||
},
|
||||
{
|
||||
"name": "account",
|
||||
"title": "Accounts & access"
|
||||
},
|
||||
{
|
||||
"name": "animals",
|
||||
"title": "Animals"
|
||||
},
|
||||
{
|
||||
"name": "arrows",
|
||||
"title": "Arrows"
|
||||
},
|
||||
{
|
||||
"name": "brands",
|
||||
"title": "Brands"
|
||||
},
|
||||
{
|
||||
"name": "buildings",
|
||||
"title": "Buildings"
|
||||
},
|
||||
{
|
||||
"name": "charts",
|
||||
"title": "Charts"
|
||||
},
|
||||
{
|
||||
"name": "communication",
|
||||
"title": "Communication"
|
||||
},
|
||||
{
|
||||
"name": "connectivity",
|
||||
"title": "Connectivity"
|
||||
},
|
||||
{
|
||||
"name": "cursors",
|
||||
"title": "Cursors"
|
||||
},
|
||||
{
|
||||
"name": "design",
|
||||
"title": "Design"
|
||||
},
|
||||
{
|
||||
"name": "development",
|
||||
"title": "Coding & development"
|
||||
},
|
||||
{
|
||||
"name": "devices",
|
||||
"title": "Devices"
|
||||
},
|
||||
{
|
||||
"name": "emoji",
|
||||
"title": "Emoji"
|
||||
},
|
||||
{
|
||||
"name": "files",
|
||||
"title": "File icons"
|
||||
},
|
||||
{
|
||||
"name": "finance",
|
||||
"title": "Finance"
|
||||
},
|
||||
{
|
||||
"name": "food-beverage",
|
||||
"title": "Food & beverage"
|
||||
},
|
||||
{
|
||||
"name": "gaming",
|
||||
"title": "Gaming"
|
||||
},
|
||||
{
|
||||
"name": "home",
|
||||
"title": "Home"
|
||||
},
|
||||
{
|
||||
"name": "layout",
|
||||
"title": "Layout"
|
||||
},
|
||||
{
|
||||
"name": "mail",
|
||||
"title": "Mail"
|
||||
},
|
||||
{
|
||||
"name": "math",
|
||||
"title": "Mathematics"
|
||||
},
|
||||
{
|
||||
"name": "medical",
|
||||
"title": "Medical"
|
||||
},
|
||||
{
|
||||
"name": "multimedia",
|
||||
"title": "Multimedia"
|
||||
},
|
||||
{
|
||||
"name": "nature",
|
||||
"title": "Nature"
|
||||
},
|
||||
{
|
||||
"name": "navigation",
|
||||
"title": "Navigation"
|
||||
},
|
||||
{
|
||||
"name": "notifications",
|
||||
"title": "Notification"
|
||||
},
|
||||
{
|
||||
"name": "people",
|
||||
"title": "People"
|
||||
},
|
||||
{
|
||||
"name": "photography",
|
||||
"title": "Photography"
|
||||
},
|
||||
{
|
||||
"name": "science",
|
||||
"title": "Science"
|
||||
},
|
||||
{
|
||||
"name": "seasons",
|
||||
"title": "Seasons"
|
||||
},
|
||||
{
|
||||
"name": "security",
|
||||
"title": "Security"
|
||||
},
|
||||
{
|
||||
"name": "shapes",
|
||||
"title": "Shapes"
|
||||
},
|
||||
{
|
||||
"name": "shopping",
|
||||
"title": "Shopping"
|
||||
},
|
||||
{
|
||||
"name": "social",
|
||||
"title": "Social"
|
||||
},
|
||||
{
|
||||
"name": "sports",
|
||||
"title": "Sports"
|
||||
},
|
||||
{
|
||||
"name": "sustainability",
|
||||
"title": "Sustainability"
|
||||
},
|
||||
{
|
||||
"name": "text",
|
||||
"title": "Text formatting"
|
||||
},
|
||||
{
|
||||
"name": "time",
|
||||
"title": "Time & calendar"
|
||||
},
|
||||
{
|
||||
"name": "tools",
|
||||
"title": "Tools"
|
||||
},
|
||||
{
|
||||
"name": "transportation",
|
||||
"title": "Transportation"
|
||||
},
|
||||
{
|
||||
"name": "travel",
|
||||
"title": "Travel"
|
||||
},
|
||||
{
|
||||
"name": "weather",
|
||||
"title": "Weather"
|
||||
}
|
||||
]
|
||||
@@ -14,13 +14,5 @@
|
||||
"light": "/library-logos/tamagui.svg",
|
||||
"dark": "/library-logos/tamagui.svg"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Reflex",
|
||||
"url": "https://reflex.dev",
|
||||
"image": {
|
||||
"light": "/library-logos/reflex-light.svg",
|
||||
"dark": "/library-logos/reflex-dark.svg"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
@@ -3,163 +3,87 @@
|
||||
"order": 0,
|
||||
"icon": "js",
|
||||
"shields": [
|
||||
{
|
||||
"alt": "npm",
|
||||
"src": "https://img.shields.io/npm/v/lucide",
|
||||
"href": "https://www.npmjs.com/package/lucide"
|
||||
},
|
||||
{
|
||||
"alt": "npm",
|
||||
"src": "https://img.shields.io/npm/dw/lucide",
|
||||
"href": "https://www.npmjs.com/package/lucide"
|
||||
}
|
||||
{ "alt": "npm", "src": "https://img.shields.io/npm/v/lucide", "href": "https://www.npmjs.com/package/lucide" },
|
||||
{ "alt": "npm", "src": "https://img.shields.io/npm/dw/lucide", "href": "https://www.npmjs.com/package/lucide" }
|
||||
]
|
||||
},
|
||||
"lucide-react": {
|
||||
"order": 1,
|
||||
"icon": "react",
|
||||
"shields": [
|
||||
{
|
||||
"alt": "npm",
|
||||
"src": "https://img.shields.io/npm/v/lucide-react",
|
||||
"href": "https://www.npmjs.com/package/lucide-react"
|
||||
{ "alt": "npm", "src": "https://img.shields.io/npm/v/lucide-react", "href": "https://www.npmjs.com/package/lucide-react" },
|
||||
{ "alt": "npm", "src": "https://img.shields.io/npm/dw/lucide-react", "href": "https://www.npmjs.com/package/lucide-react" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"alt": "npm",
|
||||
"src": "https://img.shields.io/npm/dw/lucide-react",
|
||||
"href": "https://www.npmjs.com/package/lucide-react"
|
||||
}
|
||||
"lucide-vue": {
|
||||
"order": 2,
|
||||
"icon": "vue",
|
||||
"shields": [
|
||||
{ "alt": "npm", "src": "https://img.shields.io/npm/v/lucide-vue", "href": "https://www.npmjs.com/package/lucide-vue" },
|
||||
{ "alt": "npm", "src": "https://img.shields.io/npm/dw/lucide-vue", "href": "https://www.npmjs.com/package/lucide-vue" }
|
||||
]
|
||||
},
|
||||
"lucide-vue-next": {
|
||||
"order": 2,
|
||||
"order": 3,
|
||||
"icon": "vue-next",
|
||||
"shields": [
|
||||
{
|
||||
"alt": "npm",
|
||||
"src": "https://img.shields.io/npm/v/lucide-vue-next",
|
||||
"href": "https://www.npmjs.com/package/lucide-vue-next"
|
||||
},
|
||||
{
|
||||
"alt": "npm",
|
||||
"src": "https://img.shields.io/npm/dw/lucide-vue-next",
|
||||
"href": "https://www.npmjs.com/package/lucide-vue-next"
|
||||
}
|
||||
{ "alt": "npm", "src": "https://img.shields.io/npm/v/lucide-vue-next", "href": "https://www.npmjs.com/package/lucide-vue-next" },
|
||||
{ "alt": "npm", "src": "https://img.shields.io/npm/dw/lucide-vue-next", "href": "https://www.npmjs.com/package/lucide-vue-next" }
|
||||
]
|
||||
},
|
||||
"lucide-svelte": {
|
||||
"order": 3,
|
||||
"order": 4,
|
||||
"icon": "svelte",
|
||||
"shields": [
|
||||
{
|
||||
"alt": "npm",
|
||||
"src": "https://img.shields.io/npm/v/lucide-svelte",
|
||||
"href": "https://www.npmjs.com/package/lucide-svelte"
|
||||
},
|
||||
{
|
||||
"alt": "npm",
|
||||
"src": "https://img.shields.io/npm/dw/lucide-svelte",
|
||||
"href": "https://www.npmjs.com/package/lucide-svelte"
|
||||
}
|
||||
{ "alt": "npm", "src": "https://img.shields.io/npm/v/lucide-svelte", "href": "https://www.npmjs.com/package/lucide-svelte" },
|
||||
{ "alt": "npm", "src": "https://img.shields.io/npm/dw/lucide-svelte", "href": "https://www.npmjs.com/package/lucide-svelte" }
|
||||
]
|
||||
},
|
||||
"lucide-solid": {
|
||||
"order": 4,
|
||||
"icon": "solid",
|
||||
"shields": [
|
||||
{
|
||||
"alt": "npm",
|
||||
"src": "https://img.shields.io/npm/v/lucide-solid",
|
||||
"href": "https://www.npmjs.com/package/lucide-solid"
|
||||
},
|
||||
{
|
||||
"alt": "npm",
|
||||
"src": "https://img.shields.io/npm/dw/lucide-solid",
|
||||
"href": "https://www.npmjs.com/package/lucide-solid"
|
||||
}
|
||||
]
|
||||
},
|
||||
"lucide-react-native": {
|
||||
"order": 5,
|
||||
"icon": "react-native",
|
||||
"shields": [
|
||||
{
|
||||
"alt": "npm",
|
||||
"src": "https://img.shields.io/npm/v/lucide-react-native",
|
||||
"href": "https://www.npmjs.com/package/lucide-react-native"
|
||||
},
|
||||
{
|
||||
"alt": "npm",
|
||||
"src": "https://img.shields.io/npm/dw/lucide-react-native",
|
||||
"href": "https://www.npmjs.com/package/lucide-react-native"
|
||||
}
|
||||
]
|
||||
},
|
||||
"lucide-angular": {
|
||||
"order": 6,
|
||||
"icon": "angular",
|
||||
"shields": [
|
||||
{
|
||||
"alt": "npm",
|
||||
"src": "https://img.shields.io/npm/v/lucide-angular",
|
||||
"href": "https://www.npmjs.com/package/lucide-angular"
|
||||
},
|
||||
{
|
||||
"alt": "npm",
|
||||
"src": "https://img.shields.io/npm/dw/lucide-angular",
|
||||
"href": "https://www.npmjs.com/package/lucide-angular"
|
||||
}
|
||||
{ "alt": "npm", "src": "https://img.shields.io/npm/v/lucide-solid", "href": "https://www.npmjs.com/package/lucide-solid" },
|
||||
{ "alt": "npm", "src": "https://img.shields.io/npm/dw/lucide-solid", "href": "https://www.npmjs.com/package/lucide-solid" }
|
||||
]
|
||||
},
|
||||
"lucide-preact": {
|
||||
"order": 7,
|
||||
"order": 5,
|
||||
"icon": "preact",
|
||||
"shields": [
|
||||
{
|
||||
"alt": "npm",
|
||||
"src": "https://img.shields.io/npm/v/lucide-preact",
|
||||
"href": "https://www.npmjs.com/package/lucide-preact"
|
||||
},
|
||||
{
|
||||
"alt": "npm",
|
||||
"src": "https://img.shields.io/npm/dw/lucide-preact",
|
||||
"href": "https://www.npmjs.com/package/lucide-preact"
|
||||
}
|
||||
{ "alt": "npm", "src": "https://img.shields.io/npm/v/lucide-preact", "href": "https://www.npmjs.com/package/lucide-preact" },
|
||||
{ "alt": "npm", "src": "https://img.shields.io/npm/dw/lucide-preact", "href": "https://www.npmjs.com/package/lucide-preact" }
|
||||
]
|
||||
},
|
||||
"@lucide/astro": {
|
||||
"docsAlias": "lucide-astro",
|
||||
"packageDirname": "astro",
|
||||
"order": 8,
|
||||
"icon": "astro",
|
||||
"iconDark": "astro-dark",
|
||||
"lucide-react-native": {
|
||||
"order": 6,
|
||||
"icon": "react-native",
|
||||
"shields": [
|
||||
{
|
||||
"alt": "npm",
|
||||
"src": "https://img.shields.io/npm/v/@lucide/astro",
|
||||
"href": "https://www.npmjs.com/package/@lucide/astro"
|
||||
{ "alt": "npm", "src": "https://img.shields.io/npm/v/lucide-react-native", "href": "https://www.npmjs.com/package/lucide-react-native" },
|
||||
{ "alt": "npm", "src": "https://img.shields.io/npm/dw/lucide-react-native", "href": "https://www.npmjs.com/package/lucide-react-native" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"alt": "npm",
|
||||
"src": "https://img.shields.io/npm/dw/@lucide/astro",
|
||||
"href": "https://www.npmjs.com/package/@lucide/astro"
|
||||
}
|
||||
"lucide-angular": {
|
||||
"order": 7,
|
||||
"icon": "angular",
|
||||
"shields": [
|
||||
{ "alt": "npm", "src": "https://img.shields.io/npm/v/lucide-angular", "href": "https://www.npmjs.com/package/lucide-angular" },
|
||||
{ "alt": "npm", "src": "https://img.shields.io/npm/dw/lucide-angular", "href": "https://www.npmjs.com/package/lucide-angular" }
|
||||
]
|
||||
},
|
||||
"lucide-static": {
|
||||
"order": 9,
|
||||
"order": 8,
|
||||
"icon": "svg",
|
||||
"shields": [
|
||||
{
|
||||
"alt": "npm",
|
||||
"src": "https://img.shields.io/npm/v/lucide-static",
|
||||
"href": "https://www.npmjs.com/package/lucide-static"
|
||||
{ "alt": "npm", "src": "https://img.shields.io/npm/v/lucide-static", "href": "https://www.npmjs.com/package/lucide-static" },
|
||||
{ "alt": "npm", "src": "https://img.shields.io/npm/dw/lucide-static", "href": "https://www.npmjs.com/package/lucide-static" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"alt": "npm",
|
||||
"src": "https://img.shields.io/npm/dw/lucide-static",
|
||||
"href": "https://www.npmjs.com/package/lucide-static"
|
||||
}
|
||||
"lucide-flutter": {
|
||||
"order": 9,
|
||||
"icon": "flutter",
|
||||
"shields": [
|
||||
{ "alt": "flutter", "src": "https://img.shields.io/pub/v/lucide_icons", "href": "https://img.shields.io/pub/v/lucide_icons" }
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,24 +76,5 @@
|
||||
],
|
||||
"source": "https://github.com/swisnl/nuxt-lucide-icons",
|
||||
"documentation": "https://github.com/swisnl/nuxt-lucide-icons/blob/main/README.md"
|
||||
},
|
||||
{
|
||||
"name": "lucide-lustre",
|
||||
"description": "A library providing https://lucide.dev icons to lustre.",
|
||||
"icon": "/framework-logos/lustre.webp",
|
||||
"shields": [
|
||||
{
|
||||
"alt": "Latest Stable Version",
|
||||
"src": "https://img.shields.io/hexpm/v/lucide_lustre",
|
||||
"href": "https://hex.pm/packages/lucide_lustre"
|
||||
},
|
||||
{
|
||||
"alt": "Total Downloads",
|
||||
"src": "https://img.shields.io/hexpm/dw/lucide_lustre",
|
||||
"href": "https://hex.pm/packages/lucide_lustre"
|
||||
}
|
||||
],
|
||||
"source": "https://github.com/dinkelspiel/lucide_lustre",
|
||||
"documentation": "https://github.com/dinkelspiel/lucide_lustre/blob/master/README.md"
|
||||
}
|
||||
]
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
[
|
||||
{
|
||||
"name": "Eric Fennis",
|
||||
"title": "Creator of Lucide & Software engineer @nedap",
|
||||
"image": "https://github.com/ericfennis.png?size=192",
|
||||
"sponsor": "https://github.com/sponsors/ericfennis",
|
||||
"socialLinks": [
|
||||
{
|
||||
"icon": "github",
|
||||
"link": "https://github.com/ericfennis"
|
||||
},
|
||||
{
|
||||
"icon": "x",
|
||||
"link": "https://x.com/ericfennis"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Karsa Rigó",
|
||||
"title": "Maintainer of Lucide & Software engineer @sztaki",
|
||||
"image": "https://github.com/karsa-mistmere.png?size=192",
|
||||
"socialLinks": [
|
||||
{
|
||||
"icon": "github",
|
||||
"link": "https://github.com/karsa-mistmere"
|
||||
},
|
||||
{
|
||||
"icon": "linkedin",
|
||||
"link": "https://www.linkedin.com/in/karsamistmere"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Jakob Guddas",
|
||||
"title": "Maintainer of Lucide & Software engineer @LEGO",
|
||||
"image": "https://github.com/jguddas.png?size=192",
|
||||
"socialLinks": [
|
||||
{
|
||||
"icon": "github",
|
||||
"link": "https://github.com/jguddas"
|
||||
},
|
||||
{
|
||||
"icon": "linkedin",
|
||||
"link": "https://www.linkedin.com/in/jguddas"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -3,92 +3,55 @@ import React from 'react';
|
||||
interface BackdropProps {
|
||||
src: string;
|
||||
color?: string;
|
||||
outline?: boolean;
|
||||
backdropString: string;
|
||||
}
|
||||
|
||||
const Backdrop = ({
|
||||
src,
|
||||
color = 'red',
|
||||
outline = true,
|
||||
backdropString,
|
||||
}: BackdropProps): JSX.Element => {
|
||||
const id = React.useId();
|
||||
const Backdrop = ({ src, color = 'red', backdropString }: BackdropProps): JSX.Element => {
|
||||
return (
|
||||
<>
|
||||
<defs xmlns="http://www.w3.org/2000/svg">
|
||||
<pattern
|
||||
id={`pattern-${id}`}
|
||||
id="pattern"
|
||||
width=".1"
|
||||
height=".1"
|
||||
patternUnits="userSpaceOnUse"
|
||||
patternTransform="rotate(45 50 50)"
|
||||
>
|
||||
<line
|
||||
stroke={color}
|
||||
strokeWidth={0.1}
|
||||
y2={1}
|
||||
/>
|
||||
<line
|
||||
stroke={color}
|
||||
strokeWidth={0.1}
|
||||
y2={1}
|
||||
/>
|
||||
<line stroke={color} strokeWidth={0.1} y2={1} />
|
||||
<line stroke={color} strokeWidth={0.1} y2={1} />
|
||||
</pattern>
|
||||
</defs>
|
||||
<mask
|
||||
id={`svg-preview-backdrop-mask-${id}`}
|
||||
maskUnits="userSpaceOnUse"
|
||||
>
|
||||
<g
|
||||
stroke="#fff"
|
||||
dangerouslySetInnerHTML={{ __html: backdropString }}
|
||||
/>
|
||||
<g dangerouslySetInnerHTML={{ __html: src }} />
|
||||
<mask id="svg-preview-backdrop-mask-outline" maskUnits="userSpaceOnUse">
|
||||
<g stroke="#fff" dangerouslySetInnerHTML={{ __html: backdropString }} />
|
||||
<g dangerouslySetInnerHTML={{ __html: src }} strokeWidth={2.05} />
|
||||
</mask>
|
||||
<mask
|
||||
id={`svg-preview-backdrop-mask-outline-${id}`}
|
||||
maskUnits="userSpaceOnUse"
|
||||
>
|
||||
<rect
|
||||
x="0"
|
||||
y="0"
|
||||
width="24"
|
||||
height="24"
|
||||
fill="#fff"
|
||||
stroke="none"
|
||||
/>
|
||||
<g
|
||||
strokeWidth={1.75}
|
||||
dangerouslySetInnerHTML={{ __html: backdropString }}
|
||||
/>
|
||||
<mask id="svg-preview-backdrop-mask-fill" maskUnits="userSpaceOnUse">
|
||||
<g stroke="#fff" dangerouslySetInnerHTML={{ __html: backdropString }} />
|
||||
<g dangerouslySetInnerHTML={{ __html: src }} strokeWidth={2.05} />
|
||||
<g strokeWidth={1.75} dangerouslySetInnerHTML={{ __html: backdropString }} />
|
||||
</mask>
|
||||
<g mask={`url(#svg-preview-backdrop-mask-${id})`}>
|
||||
<rect
|
||||
x="0"
|
||||
y="0"
|
||||
width="24"
|
||||
height="24"
|
||||
opacity={0.5}
|
||||
fill={`url(#pattern-${id})`}
|
||||
stroke="none"
|
||||
/>
|
||||
<g
|
||||
stroke={color}
|
||||
strokeWidth={2.25}
|
||||
opacity={0.75}
|
||||
dangerouslySetInnerHTML={{ __html: src }}
|
||||
/>
|
||||
{outline && (
|
||||
<g
|
||||
stroke={color}
|
||||
strokeWidth={2.25}
|
||||
opacity={0.75}
|
||||
mask={`url(#svg-preview-backdrop-mask-outline-${id})`}
|
||||
dangerouslySetInnerHTML={{ __html: backdropString }}
|
||||
/>
|
||||
)}
|
||||
<g strokeWidth={2.25} stroke="url(#pattern)" mask={'url(#svg-preview-backdrop-mask-outline)'}>
|
||||
<rect x="0" y="0" width="24" height="24" fill="url(#pattern)" opacity={0.5} stroke="none" />
|
||||
</g>
|
||||
<rect
|
||||
x="0"
|
||||
y="0"
|
||||
width="24"
|
||||
height="24"
|
||||
fill="url(#pattern)"
|
||||
stroke="none"
|
||||
mask={'url(#svg-preview-backdrop-mask-fill)'}
|
||||
/>
|
||||
<rect
|
||||
x="0"
|
||||
y="0"
|
||||
width="24"
|
||||
height="24"
|
||||
fill={color}
|
||||
opacity={0.5}
|
||||
stroke="none"
|
||||
mask={'url(#svg-preview-backdrop-mask-fill)'}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,71 +0,0 @@
|
||||
import React from 'react';
|
||||
import Backdrop from './Backdrop.tsx';
|
||||
import { darkModeCss, Grid } from './index.tsx';
|
||||
|
||||
const SvgPreview = React.forwardRef<
|
||||
SVGSVGElement,
|
||||
{
|
||||
oldSrc: string;
|
||||
newSrc: string;
|
||||
} & React.SVGProps<SVGSVGElement>
|
||||
>(({ oldSrc, newSrc, children, ...props }, ref) => {
|
||||
return (
|
||||
<svg
|
||||
ref={ref}
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width={24}
|
||||
height={24}
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
strokeWidth={2}
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
{...props}
|
||||
>
|
||||
<style>{darkModeCss}</style>
|
||||
<Grid
|
||||
strokeWidth={0.1}
|
||||
stroke="#777"
|
||||
strokeOpacity={0.3}
|
||||
radius={1}
|
||||
/>
|
||||
<mask
|
||||
id="gray"
|
||||
maskUnits="userSpaceOnUse"
|
||||
>
|
||||
<rect
|
||||
x="0"
|
||||
y="0"
|
||||
width="24"
|
||||
height="24"
|
||||
fill="#000"
|
||||
stroke="none"
|
||||
/>
|
||||
<g
|
||||
stroke="#fff"
|
||||
dangerouslySetInnerHTML={{ __html: oldSrc }}
|
||||
/>
|
||||
</mask>
|
||||
<Backdrop
|
||||
src=""
|
||||
outline={false}
|
||||
backdropString={`<g mask="url('#gray')">${newSrc}</g>`}
|
||||
color="#777"
|
||||
/>
|
||||
<Backdrop
|
||||
src={oldSrc}
|
||||
backdropString={newSrc}
|
||||
color="lime"
|
||||
/>
|
||||
<Backdrop
|
||||
src={newSrc}
|
||||
backdropString={oldSrc}
|
||||
color="red"
|
||||
/>
|
||||
{children}
|
||||
</svg>
|
||||
);
|
||||
});
|
||||
|
||||
export default SvgPreview;
|
||||
@@ -2,23 +2,7 @@ import React from 'react';
|
||||
import { PathProps, Path } from './types';
|
||||
import { getPaths, assert } from './utils';
|
||||
|
||||
export const darkModeCss = `
|
||||
@media screen and (prefers-color-scheme: light) {
|
||||
.svg-preview-grid-rect { fill: none }
|
||||
}
|
||||
@media screen and (prefers-color-scheme: dark) {
|
||||
.svg-preview-grid-rect { fill: none }
|
||||
.svg
|
||||
.svg-preview-grid-group,
|
||||
.svg-preview-radii-group,
|
||||
.svg-preview-shadow-mask-group,
|
||||
.svg-preview-shadow-group {
|
||||
stroke: #fff;
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export const Grid = ({
|
||||
const Grid = ({
|
||||
radius,
|
||||
fill = '#fff',
|
||||
...props
|
||||
@@ -26,11 +10,7 @@ export const Grid = ({
|
||||
strokeWidth: number;
|
||||
radius: number;
|
||||
} & PathProps<'stroke', 'strokeWidth'>) => (
|
||||
<g
|
||||
className="svg-preview-grid-group"
|
||||
strokeLinecap="butt"
|
||||
{...props}
|
||||
>
|
||||
<g className="svg-preview-grid-group" strokeLinecap="butt" {...props}>
|
||||
<rect
|
||||
className="svg-preview-grid-rect"
|
||||
width={24 - props.strokeWidth}
|
||||
@@ -41,29 +21,11 @@ export const Grid = ({
|
||||
fill={fill}
|
||||
/>
|
||||
<path
|
||||
strokeDasharray={'0 0.1 ' + '0.1 0.15 '.repeat(11) + '0 0.15'}
|
||||
strokeWidth={0.1}
|
||||
d={
|
||||
props.d ||
|
||||
new Array(Math.floor(24 - 1))
|
||||
.fill(null)
|
||||
.map((_, i) => i)
|
||||
.filter((i) => i % 3 !== 2)
|
||||
.flatMap((i) => [
|
||||
`M${props.strokeWidth} ${i + 1}h${24 - props.strokeWidth * 2}`,
|
||||
`M${i + 1} ${props.strokeWidth}v${24 - props.strokeWidth * 2}`,
|
||||
])
|
||||
.join('')
|
||||
}
|
||||
/>
|
||||
<path
|
||||
d={
|
||||
props.d ||
|
||||
new Array(Math.floor(24 - 1))
|
||||
.fill(null)
|
||||
.map((_, i) => i)
|
||||
.filter((i) => i % 3 === 2)
|
||||
.flatMap((i) => [
|
||||
.flatMap((_, i) => [
|
||||
`M${props.strokeWidth} ${i + 1}h${24 - props.strokeWidth * 2}`,
|
||||
`M${i + 1} ${props.strokeWidth}v${24 - props.strokeWidth * 2}`,
|
||||
])
|
||||
@@ -82,21 +44,15 @@ const Shadow = ({
|
||||
paths: Path[];
|
||||
} & PathProps<'stroke' | 'strokeWidth' | 'strokeOpacity', 'd'>) => {
|
||||
const groupedPaths = Object.entries(
|
||||
paths.reduce(
|
||||
(groups, val) => {
|
||||
paths.reduce((groups, val) => {
|
||||
const key = val.c.id;
|
||||
groups[key] = [...(groups[key] || []), val];
|
||||
return groups;
|
||||
},
|
||||
{} as Record<number, Path[]>,
|
||||
),
|
||||
}, {} as Record<number, Path[]>)
|
||||
);
|
||||
return (
|
||||
<>
|
||||
<g
|
||||
className="svg-preview-shadow-mask-group"
|
||||
{...props}
|
||||
>
|
||||
<g className="svg-preview-shadow-mask-group" {...props}>
|
||||
{groupedPaths.map(([id, paths]) => (
|
||||
<mask
|
||||
id={`svg-preview-shadow-mask-${id}`}
|
||||
@@ -105,15 +61,7 @@ const Shadow = ({
|
||||
strokeWidth={props.strokeWidth}
|
||||
stroke="#000"
|
||||
>
|
||||
<rect
|
||||
x={0}
|
||||
y={0}
|
||||
width={24}
|
||||
height={24}
|
||||
fill="#fff"
|
||||
stroke="none"
|
||||
rx={radius}
|
||||
/>
|
||||
<rect x={0} y={0} width={24} height={24} fill="#fff" stroke="none" rx={radius} />
|
||||
<path
|
||||
d={paths
|
||||
.flatMap(({ prev, next }) => [
|
||||
@@ -126,16 +74,9 @@ const Shadow = ({
|
||||
</mask>
|
||||
))}
|
||||
</g>
|
||||
<g
|
||||
className="svg-preview-shadow-group"
|
||||
{...props}
|
||||
>
|
||||
<g className="svg-preview-shadow-group" {...props}>
|
||||
{paths.map(({ d, c: { id } }, i) => (
|
||||
<path
|
||||
key={i}
|
||||
mask={`url(#svg-preview-shadow-mask-${id})`}
|
||||
d={d}
|
||||
/>
|
||||
<path key={i} mask={`url(#svg-preview-shadow-mask-${id})`} d={d} />
|
||||
))}
|
||||
<path
|
||||
d={paths
|
||||
@@ -153,16 +94,9 @@ const ColoredPath = ({
|
||||
paths,
|
||||
...props
|
||||
}: { paths: Path[]; colors: string[] } & PathProps<never, 'd' | 'stroke'>) => (
|
||||
<g
|
||||
className="svg-preview-colored-path-group"
|
||||
{...props}
|
||||
>
|
||||
<g className="svg-preview-colored-path-group" {...props}>
|
||||
{paths.map(({ d, c }, i) => (
|
||||
<path
|
||||
key={i}
|
||||
d={d}
|
||||
stroke={colors[(c.name === 'path' ? i : c.id) % colors.length]}
|
||||
/>
|
||||
<path key={i} d={d} stroke={colors[(c.name === 'path' ? i : c.id) % colors.length]} />
|
||||
))}
|
||||
</g>
|
||||
);
|
||||
@@ -204,15 +138,7 @@ const ControlPath = ({
|
||||
key={i}
|
||||
maskUnits="userSpaceOnUse"
|
||||
>
|
||||
<rect
|
||||
x="0"
|
||||
y="0"
|
||||
width="24"
|
||||
height="24"
|
||||
fill="#fff"
|
||||
stroke="none"
|
||||
rx={radius}
|
||||
/>
|
||||
<rect x="0" y="0" width="24" height="24" fill="#fff" stroke="none" rx={radius} />
|
||||
<path d={`M${prev.x} ${prev.y}h.01`} />
|
||||
<path d={`M${next.x} ${next.y}h.01`} />
|
||||
</mask>
|
||||
@@ -220,10 +146,7 @@ const ControlPath = ({
|
||||
);
|
||||
})}
|
||||
</g>
|
||||
<g
|
||||
className="svg-preview-control-path-group"
|
||||
{...props}
|
||||
>
|
||||
<g className="svg-preview-control-path-group" {...props}>
|
||||
{controlPaths.map(({ d, showMarker }, i) => (
|
||||
<path
|
||||
key={i}
|
||||
@@ -232,33 +155,18 @@ const ControlPath = ({
|
||||
/>
|
||||
))}
|
||||
</g>
|
||||
<g
|
||||
className="svg-preview-control-path-marker-group"
|
||||
{...props}
|
||||
>
|
||||
<g className="svg-preview-control-path-marker-group" {...props}>
|
||||
<path
|
||||
d={controlPaths
|
||||
.flatMap(({ prev, next, showMarker }) =>
|
||||
showMarker ? [`M${prev.x} ${prev.y}h.01`, `M${next.x} ${next.y}h.01`] : [],
|
||||
showMarker ? [`M${prev.x} ${prev.y}h.01`, `M${next.x} ${next.y}h.01`] : []
|
||||
)
|
||||
.join('')}
|
||||
/>
|
||||
{controlPaths.map(({ d, prev, next, startMarker, endMarker }, i) => (
|
||||
<React.Fragment key={i}>
|
||||
{startMarker && (
|
||||
<circle
|
||||
cx={prev.x}
|
||||
cy={prev.y}
|
||||
r={pointSize / 2}
|
||||
/>
|
||||
)}
|
||||
{endMarker && (
|
||||
<circle
|
||||
cx={next.x}
|
||||
cy={next.y}
|
||||
r={pointSize / 2}
|
||||
/>
|
||||
)}
|
||||
{startMarker && <circle cx={prev.x} cy={prev.y} r={pointSize / 2} />}
|
||||
{endMarker && <circle cx={next.x} cy={next.y} r={pointSize / 2} />}
|
||||
</React.Fragment>
|
||||
))}
|
||||
</g>
|
||||
@@ -274,16 +182,15 @@ const Radii = ({
|
||||
any
|
||||
>) => {
|
||||
return (
|
||||
<g
|
||||
className="svg-preview-radii-group"
|
||||
{...props}
|
||||
>
|
||||
<g className="svg-preview-radii-group" {...props}>
|
||||
{paths.map(
|
||||
({ c, prev, next, circle }, i) =>
|
||||
circle && (
|
||||
<React.Fragment key={i}>
|
||||
{c.name !== 'circle' && (
|
||||
<path d={`M${prev.x} ${prev.y} ${circle.x} ${circle.y} ${next.x} ${next.y}`} />
|
||||
{c.name !== "circle" && (
|
||||
<path
|
||||
d={`M${prev.x} ${prev.y} ${circle.x} ${circle.y} ${next.x} ${next.y}`}
|
||||
/>
|
||||
)}
|
||||
<circle
|
||||
cy={circle.y}
|
||||
@@ -293,7 +200,7 @@ const Radii = ({
|
||||
stroke={
|
||||
(Math.round(circle.x * 100) / 100) % 1 !== 0 ||
|
||||
(Math.round(circle.y * 100) / 100) % 1 !== 0
|
||||
? 'red'
|
||||
? "red"
|
||||
: undefined
|
||||
}
|
||||
/>
|
||||
@@ -301,7 +208,11 @@ const Radii = ({
|
||||
cy={circle.y}
|
||||
cx={circle.x}
|
||||
r={circle.r}
|
||||
stroke={(Math.round(circle.r * 1000) / 1000) % 1 !== 0 ? 'red' : undefined}
|
||||
stroke={
|
||||
(Math.round(circle.r * 1000) / 1000) % 1 !== 0
|
||||
? "red"
|
||||
: undefined
|
||||
}
|
||||
/>
|
||||
</React.Fragment>
|
||||
),
|
||||
@@ -317,29 +228,15 @@ const Handles = ({
|
||||
'strokeWidth' | 'stroke' | 'strokeDasharray' | 'strokeOpacity',
|
||||
any
|
||||
>) => {
|
||||
console.log(paths);
|
||||
return (
|
||||
<g
|
||||
className="svg-preview-handles-group"
|
||||
{...props}
|
||||
>
|
||||
<g className="svg-preview-handles-group" {...props}>
|
||||
{paths.map(({ c, prev, next, cp1, cp2 }) => (
|
||||
<>
|
||||
{cp1 && <path d={`M${prev.x} ${prev.y} ${cp1.x} ${cp1.y}`} />}
|
||||
{cp1 && (
|
||||
<circle
|
||||
cy={cp1.y}
|
||||
cx={cp1.x}
|
||||
r={0.25}
|
||||
/>
|
||||
)}
|
||||
{cp1 && <circle cy={cp1.y} cx={cp1.x} r={0.25} />}
|
||||
{cp2 && <path d={`M${next.x} ${next.y} ${cp2.x} ${cp2.y}`} />}
|
||||
{cp2 && (
|
||||
<circle
|
||||
cy={cp2.y}
|
||||
cx={cp2.x}
|
||||
r={0.25}
|
||||
/>
|
||||
)}
|
||||
{cp2 && <circle cy={cp2.y} cx={cp2.x} r={0.25} />}
|
||||
</>
|
||||
))}
|
||||
</g>
|
||||
@@ -355,6 +252,19 @@ const SvgPreview = React.forwardRef<
|
||||
>(({ src, children, showGrid = false, ...props }, ref) => {
|
||||
const paths = typeof src === 'string' ? getPaths(src) : src;
|
||||
|
||||
const darkModeCss = `@media screen and (prefers-color-scheme: light) {
|
||||
.svg-preview-grid-rect { fill: none }
|
||||
}
|
||||
@media screen and (prefers-color-scheme: dark) {
|
||||
.svg-preview-grid-rect { fill: none }
|
||||
.svg
|
||||
.svg-preview-grid-group,
|
||||
.svg-preview-radii-group,
|
||||
.svg-preview-shadow-mask-group,
|
||||
.svg-preview-shadow-group {
|
||||
stroke: #fff;
|
||||
}
|
||||
}`;
|
||||
return (
|
||||
<svg
|
||||
ref={ref}
|
||||
@@ -370,27 +280,9 @@ const SvgPreview = React.forwardRef<
|
||||
{...props}
|
||||
>
|
||||
<style>{darkModeCss}</style>
|
||||
{showGrid && (
|
||||
<Grid
|
||||
strokeWidth={0.1}
|
||||
stroke="#777"
|
||||
strokeOpacity={0.3}
|
||||
radius={1}
|
||||
/>
|
||||
)}
|
||||
<Shadow
|
||||
paths={paths}
|
||||
strokeWidth={4}
|
||||
stroke="#777"
|
||||
radius={1}
|
||||
strokeOpacity={0.15}
|
||||
/>
|
||||
<Handles
|
||||
paths={paths}
|
||||
strokeWidth={0.12}
|
||||
stroke="#777"
|
||||
strokeOpacity={0.6}
|
||||
/>
|
||||
{showGrid && <Grid strokeWidth={0.1} stroke="#777" strokeOpacity={0.3} radius={1} />}
|
||||
<Shadow paths={paths} strokeWidth={4} stroke="#777" radius={1} strokeOpacity={0.15} />
|
||||
<Handles paths={paths} strokeWidth={0.12} stroke="#777" strokeOpacity={0.6} />
|
||||
<ColoredPath
|
||||
paths={paths}
|
||||
colors={[
|
||||
@@ -415,19 +307,8 @@ const SvgPreview = React.forwardRef<
|
||||
stroke="#777"
|
||||
strokeOpacity={0.3}
|
||||
/>
|
||||
<ControlPath
|
||||
radius={1}
|
||||
paths={paths}
|
||||
pointSize={1}
|
||||
stroke="#fff"
|
||||
strokeWidth={0.125}
|
||||
/>
|
||||
<Handles
|
||||
paths={paths}
|
||||
strokeWidth={0.12}
|
||||
stroke="#FFF"
|
||||
strokeOpacity={0.3}
|
||||
/>
|
||||
<ControlPath radius={1} paths={paths} pointSize={1} stroke="#fff" strokeWidth={0.125} />
|
||||
<Handles paths={paths} strokeWidth={0.12} stroke="#FFF" strokeOpacity={0.3} />
|
||||
{children}
|
||||
</svg>
|
||||
);
|
||||
|
||||
@@ -16,7 +16,7 @@ export type Path = {
|
||||
|
||||
export type PathProps<
|
||||
RequiredProps extends keyof SVGProps<SVGPathElement | SVGRectElement | SVGCircleElement>,
|
||||
NeverProps extends keyof SVGProps<SVGPathElement | SVGRectElement | SVGCircleElement>,
|
||||
NeverProps extends keyof SVGProps<SVGPathElement | SVGRectElement | SVGCircleElement>
|
||||
> = Required<Pick<React.SVGProps<SVGElement & SVGRectElement & SVGCircleElement>, RequiredProps>> &
|
||||
Omit<
|
||||
React.SVGProps<SVGPathElement & SVGRectElement & SVGCircleElement>,
|
||||
|
||||
@@ -51,7 +51,7 @@ export const getCommands = (src: string) =>
|
||||
getNodes(src)
|
||||
.map(convertToPathNode)
|
||||
.flatMap(({ d, name }, idx) =>
|
||||
new SVGPathData(d).toAbs().commands.map((c, cIdx) => ({ ...c, id: idx, idx: cIdx, name })),
|
||||
new SVGPathData(d).toAbs().commands.map((c, cIdx) => ({ ...c, id: idx, idx: cIdx, name }))
|
||||
);
|
||||
|
||||
export const getPaths = (src: string) => {
|
||||
@@ -60,10 +60,10 @@ export const getPaths = (src: string) => {
|
||||
let prev: Point | undefined = undefined;
|
||||
let start: Point | undefined = undefined;
|
||||
const addPath = (
|
||||
c: (typeof commands)[number],
|
||||
c: typeof commands[number],
|
||||
next: Point,
|
||||
d?: string,
|
||||
extras?: { circle?: Path['circle']; cp1?: Path['cp1']; cp2?: Path['cp2'] },
|
||||
extras?: { circle?: Path['circle']; cp1?: Path['cp1']; cp2?: Path['cp2'] }
|
||||
) => {
|
||||
assert(prev);
|
||||
paths.push({
|
||||
@@ -153,7 +153,7 @@ export const getPaths = (src: string) => {
|
||||
{
|
||||
cp1: { x: prev.x - reflectedCp1.x, y: prev.y - reflectedCp1.y },
|
||||
cp2: { x: c.x2, y: c.y2 },
|
||||
},
|
||||
}
|
||||
);
|
||||
break;
|
||||
}
|
||||
@@ -169,7 +169,7 @@ export const getPaths = (src: string) => {
|
||||
assert(prev);
|
||||
const backTrackCP = (
|
||||
index: number,
|
||||
currentPoint: { x: number; y: number },
|
||||
currentPoint: { x: number; y: number }
|
||||
): { x: number; y: number } => {
|
||||
const previousCommand = commands[index - 1];
|
||||
if (!previousCommand) {
|
||||
@@ -211,7 +211,7 @@ export const getPaths = (src: string) => {
|
||||
{
|
||||
cp1: { x: prevCP.x, y: prevCP.y },
|
||||
cp2: { x: prevCP.x, y: prevCP.y },
|
||||
},
|
||||
}
|
||||
);
|
||||
break;
|
||||
}
|
||||
@@ -226,13 +226,13 @@ export const getPaths = (src: string) => {
|
||||
c.lArcFlag,
|
||||
c.sweepFlag,
|
||||
c.x,
|
||||
c.y,
|
||||
c.y
|
||||
);
|
||||
addPath(
|
||||
c,
|
||||
c,
|
||||
`M ${prev.x} ${prev.y} A${c.rX} ${c.rY} ${c.xRot} ${c.lArcFlag} ${c.sweepFlag} ${c.x} ${c.y}`,
|
||||
{ circle: c.rX === c.rY ? { ...center, r: c.rX } : undefined },
|
||||
{ circle: c.rX === c.rY ? { ...center, r: c.rX } : undefined }
|
||||
);
|
||||
break;
|
||||
}
|
||||
@@ -253,7 +253,7 @@ export const arcEllipseCenter = (
|
||||
fa: number,
|
||||
fs: number,
|
||||
x2: number,
|
||||
y2: number,
|
||||
y2: number
|
||||
) => {
|
||||
const phi = (a * Math.PI) / 180;
|
||||
|
||||
@@ -280,7 +280,7 @@ export const arcEllipseCenter = (
|
||||
sign *
|
||||
Math.sqrt(
|
||||
Math.max(rx * rx * ry * ry - rx * rx * y1p * y1p - ry * ry * x1p * x1p, 0) /
|
||||
(rx * rx * y1p * y1p + ry * ry * x1p * x1p),
|
||||
(rx * rx * y1p * y1p + ry * ry * x1p * x1p)
|
||||
);
|
||||
|
||||
const V2 = [(rx * y1p) / ry, (-ry * x1p) / rx];
|
||||
|
||||
@@ -1,34 +1,28 @@
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import { Category, IconEntity } from '../theme/types';
|
||||
import fs from "fs";
|
||||
import path from "path";
|
||||
import {Category, IconEntity} from "../theme/types";
|
||||
|
||||
const directory = path.join(process.cwd(), '../categories');
|
||||
const directory = path.join(process.cwd(), "../categories");
|
||||
|
||||
export function getAllCategoryFiles(): Category[] {
|
||||
const fileNames = fs.readdirSync(directory).filter((file) => path.extname(file) === '.json');
|
||||
|
||||
return fileNames.map((fileName) => {
|
||||
const name = path.basename(fileName, '.json');
|
||||
const fileContent = fs.readFileSync(path.join(directory, fileName), 'utf8');
|
||||
const name = path.basename(fileName, '.json')
|
||||
const fileContent = fs.readFileSync(path.join(directory, fileName), 'utf8')
|
||||
|
||||
const parsedFileContent = JSON.parse(fileContent);
|
||||
const parsedFileContent = JSON.parse(fileContent)
|
||||
|
||||
return {
|
||||
name,
|
||||
title: parsedFileContent.title,
|
||||
};
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export function mapCategoryIconCount(
|
||||
categories: Category[],
|
||||
icons: { categories: IconEntity['categories'] }[],
|
||||
) {
|
||||
export function mapCategoryIconCount(categories: Category[], icons: { categories: IconEntity['categories'] }[]) {
|
||||
return categories.map((category) => ({
|
||||
...category,
|
||||
iconCount: icons.reduce(
|
||||
(acc, curr) => (curr.categories.includes(category.name) ? ++acc : acc),
|
||||
0,
|
||||
),
|
||||
}));
|
||||
iconCount: icons.reduce((acc, curr) => (curr.categories.includes(category.name) ? ++acc : acc), 0)
|
||||
}))
|
||||
}
|
||||
|
||||
@@ -1,161 +0,0 @@
|
||||
import { bundledLanguages, type ThemeRegistration } from 'shikiji';
|
||||
import { getHighlighter } from 'shikiji';
|
||||
|
||||
type CodeExampleType = {
|
||||
title: string;
|
||||
language: string;
|
||||
code: string;
|
||||
}[];
|
||||
|
||||
const getIconCodes = (): CodeExampleType => {
|
||||
return [
|
||||
{
|
||||
language: 'js',
|
||||
title: 'Vanilla',
|
||||
code: `\
|
||||
import { createIcons, icons } from 'lucide';
|
||||
import { $CamelCase } from '@lucide/lab';
|
||||
|
||||
createIcons({
|
||||
icons: {
|
||||
$CamelCase
|
||||
}
|
||||
});
|
||||
|
||||
document.body.append('<i data-lucide="$Name"></i>');\
|
||||
`,
|
||||
},
|
||||
{
|
||||
language: 'tsx',
|
||||
title: 'React',
|
||||
code: `import { Icon } from 'lucide-react';
|
||||
import { $CamelCase } from '@lucide/lab';
|
||||
|
||||
const App = () => {
|
||||
return (
|
||||
<Icon iconNode={$CamelCase} />
|
||||
);
|
||||
};
|
||||
|
||||
export default App;
|
||||
`,
|
||||
},
|
||||
{
|
||||
language: 'vue',
|
||||
title: 'Vue',
|
||||
code: `<script setup>
|
||||
import { Icon } from 'lucide-vue-next';
|
||||
import { $CamelCase } from '@lucide/lab';
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Icon :iconNode="$CamelCase" />
|
||||
</template>
|
||||
`,
|
||||
},
|
||||
{
|
||||
language: 'svelte',
|
||||
title: 'Svelte',
|
||||
code: `<script>
|
||||
import { Icon } from 'lucide-svelte';
|
||||
import { $CamelCase } from '@lucide/lab';
|
||||
</script>
|
||||
|
||||
<Icon iconNode={$CamelCase} />
|
||||
`,
|
||||
},
|
||||
{
|
||||
language: 'tsx',
|
||||
title: 'Preact',
|
||||
code: `import { Icon } from 'lucide-preact';
|
||||
import { $CamelCase } from '@lucide/lab';
|
||||
|
||||
const App = () => {
|
||||
return (
|
||||
<Icon iconNode={$CamelCase} />
|
||||
);
|
||||
};
|
||||
|
||||
export default App;
|
||||
`,
|
||||
},
|
||||
{
|
||||
language: 'tsx',
|
||||
title: 'Solid',
|
||||
code: `import { Icon } from 'lucide-solid';
|
||||
import { $CamelCase } from '@lucide/lab';
|
||||
|
||||
const App = () => {
|
||||
return (
|
||||
<Icon iconNode={$CamelCase} />
|
||||
);
|
||||
};
|
||||
|
||||
export default App;
|
||||
`,
|
||||
},
|
||||
{
|
||||
language: 'tsx',
|
||||
title: 'Angular',
|
||||
code: `// app.module.ts
|
||||
import { LucideAngularModule } from 'lucide-angular';
|
||||
import { $CamelCase } from '@lucide/lab';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
LucideAngularModule.pick({ $CamelCase })
|
||||
],
|
||||
})
|
||||
|
||||
// app.component.html
|
||||
<lucide-icon name="$CamelCase"></lucide-icon>
|
||||
`,
|
||||
},
|
||||
];
|
||||
};
|
||||
|
||||
export type ThemeOptions =
|
||||
| ThemeRegistration
|
||||
| { light: ThemeRegistration; dark: ThemeRegistration };
|
||||
|
||||
const highLightCode = async (code: string, lang: string, active?: boolean) => {
|
||||
const highlighter = await getHighlighter({
|
||||
themes: ['github-light', 'github-dark'],
|
||||
langs: Object.keys(bundledLanguages),
|
||||
});
|
||||
|
||||
const highlightedCode = highlighter
|
||||
.codeToHtml(code, {
|
||||
lang,
|
||||
themes: {
|
||||
light: 'github-light',
|
||||
dark: 'github-dark',
|
||||
},
|
||||
defaultColor: false,
|
||||
})
|
||||
.replace('shiki-themes', 'shiki-themes vp-code');
|
||||
|
||||
return `<div class="language-${lang} ${active ? 'active' : ''}">
|
||||
<button title="Copy Code" class="copy"></button>
|
||||
<span class="lang">${lang}</span>
|
||||
${highlightedCode}
|
||||
</div>`;
|
||||
};
|
||||
|
||||
export default async function createCodeExamples() {
|
||||
const codes = getIconCodes();
|
||||
|
||||
const codeExamplePromises = codes.map(async ({ title, language, code }, index) => {
|
||||
const isFirst = index === 0;
|
||||
|
||||
const codeString = await highLightCode(code, language, isFirst);
|
||||
|
||||
return {
|
||||
title,
|
||||
language: language,
|
||||
code: codeString,
|
||||
};
|
||||
});
|
||||
|
||||
return Promise.all(codeExamplePromises);
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
import { bundledLanguages, type ThemeRegistration } from 'shikiji';
|
||||
import { getHighlighter } from 'shikiji';
|
||||
|
||||
export type ThemeOptions =
|
||||
| ThemeRegistration
|
||||
| { light: ThemeRegistration; dark: ThemeRegistration };
|
||||
|
||||
const highLightCode = async (code: string, lang: string, active?: boolean) => {
|
||||
const highlighter = await getHighlighter({
|
||||
themes: ['github-light', 'github-dark'],
|
||||
langs: Object.keys(bundledLanguages),
|
||||
});
|
||||
|
||||
const highlightedCode = highlighter
|
||||
.codeToHtml(code, {
|
||||
lang,
|
||||
themes: {
|
||||
light: 'github-light',
|
||||
dark: 'github-dark',
|
||||
},
|
||||
defaultColor: false,
|
||||
})
|
||||
.replace('shiki-themes', 'shiki-themes vp-code');
|
||||
|
||||
return `<div class="language-${lang} ${active ? 'active' : ''}">
|
||||
<button title="Copy Code" class="copy"></button>
|
||||
<span class="lang">${lang}</span>
|
||||
${highlightedCode}
|
||||
</div>`;
|
||||
};
|
||||
|
||||
export default highLightCode;
|
||||
@@ -1,5 +0,0 @@
|
||||
export type CodeExampleType = {
|
||||
title: string;
|
||||
language: string;
|
||||
code: string;
|
||||
}[];
|
||||
@@ -1,33 +1,33 @@
|
||||
import { bundledLanguages, type ThemeRegistration } from 'shikiji';
|
||||
import { getHighlighter } from 'shikiji';
|
||||
import {
|
||||
bundledLanguages,
|
||||
type ThemeRegistration
|
||||
} from 'shikiji'
|
||||
import {
|
||||
getHighlighter,
|
||||
} from 'shikiji'
|
||||
|
||||
|
||||
type CodeExampleType = {
|
||||
title: string;
|
||||
language: string;
|
||||
code: string;
|
||||
}[];
|
||||
title: string,
|
||||
language: string,
|
||||
code: string,
|
||||
}[]
|
||||
|
||||
const getIconCodes = (): CodeExampleType => {
|
||||
return [
|
||||
{
|
||||
language: 'js',
|
||||
title: 'Vanilla',
|
||||
code: `\
|
||||
import { createIcons, icons } from 'lucide';
|
||||
|
||||
createIcons({ icons });
|
||||
|
||||
document.body.append('<i data-lucide="$Name"></i>');\
|
||||
`,
|
||||
language: 'html',
|
||||
title: 'HTML',
|
||||
code: `<i data-lucide="Name"></i>`
|
||||
},
|
||||
{
|
||||
language: 'tsx',
|
||||
title: 'React',
|
||||
code: `import { $PascalCase } from 'lucide-react';
|
||||
code: `import { PascalCase } from 'lucide-react';
|
||||
|
||||
const App = () => {
|
||||
return (
|
||||
<$PascalCase />
|
||||
<PascalCase />
|
||||
);
|
||||
};
|
||||
|
||||
@@ -38,11 +38,11 @@ export default App;
|
||||
language: 'vue',
|
||||
title: 'Vue',
|
||||
code: `<script setup>
|
||||
import { $PascalCase } from 'lucide-vue-next';
|
||||
import { PascalCase } from 'lucide-vue-next';
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<$PascalCase />
|
||||
<PascalCase />
|
||||
</template>
|
||||
`,
|
||||
},
|
||||
@@ -50,20 +50,20 @@ import { $PascalCase } from 'lucide-vue-next';
|
||||
language: 'svelte',
|
||||
title: 'Svelte',
|
||||
code: `<script>
|
||||
import { $PascalCase } from 'lucide-svelte';
|
||||
import { PascalCase } from 'lucide-svelte';
|
||||
</script>
|
||||
|
||||
<$PascalCase />
|
||||
<PascalCase />
|
||||
`,
|
||||
},
|
||||
{
|
||||
language: 'tsx',
|
||||
title: 'Preact',
|
||||
code: `import { $PascalCase } from 'lucide-preact';
|
||||
code: `import { PascalCase } from 'lucide-preact';
|
||||
|
||||
const App = () => {
|
||||
return (
|
||||
<$PascalCase />
|
||||
<PascalCase />
|
||||
);
|
||||
};
|
||||
|
||||
@@ -73,11 +73,11 @@ export default App;
|
||||
{
|
||||
language: 'tsx',
|
||||
title: 'Solid',
|
||||
code: `import { $PascalCase } from 'lucide-solid';
|
||||
code: `import { PascalCase } from 'lucide-solid';
|
||||
|
||||
const App = () => {
|
||||
return (
|
||||
<$PascalCase />
|
||||
<PascalCase />
|
||||
);
|
||||
};
|
||||
|
||||
@@ -88,16 +88,16 @@ export default App;
|
||||
language: 'tsx',
|
||||
title: 'Angular',
|
||||
code: `// app.module.ts
|
||||
import { LucideAngularModule, $PascalCase } from 'lucide-angular';
|
||||
import { LucideAngularModule, PascalCase } from 'lucide-angular';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
LucideAngularModule.pick({ $PascalCase })
|
||||
LucideAngularModule.pick({ PascalCase })
|
||||
],
|
||||
})
|
||||
|
||||
// app.component.html
|
||||
<lucide-icon name="$Name"></lucide-icon>
|
||||
<lucide-icon name="Name"></lucide-icon>
|
||||
`,
|
||||
},
|
||||
{
|
||||
@@ -107,39 +107,38 @@ import { LucideAngularModule, $PascalCase } from 'lucide-angular';
|
||||
@import ('~lucide-static/font/Lucide.css');
|
||||
</style>
|
||||
|
||||
<div class="icon-$Name"></div>
|
||||
<div class="icon-Name"></div>
|
||||
`,
|
||||
},
|
||||
];
|
||||
};
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
export type ThemeOptions =
|
||||
| ThemeRegistration
|
||||
| { light: ThemeRegistration; dark: ThemeRegistration };
|
||||
| { light: ThemeRegistration; dark: ThemeRegistration }
|
||||
|
||||
const highLightCode = async (code: string, lang: string, active?: boolean) => {
|
||||
const highlighter = await getHighlighter({
|
||||
themes: ['github-light', 'github-dark'],
|
||||
langs: Object.keys(bundledLanguages),
|
||||
});
|
||||
langs: Object.keys(bundledLanguages)
|
||||
})
|
||||
|
||||
const highlightedCode = highlighter
|
||||
.codeToHtml(code, {
|
||||
const highlightedCode = highlighter.codeToHtml(code, {
|
||||
lang,
|
||||
themes: {
|
||||
light: 'github-light',
|
||||
dark: 'github-dark',
|
||||
dark: 'github-dark'
|
||||
},
|
||||
defaultColor: false,
|
||||
})
|
||||
.replace('shiki-themes', 'shiki-themes vp-code');
|
||||
defaultColor: false
|
||||
}).replace('shiki-themes', 'shiki-themes vp-code')
|
||||
|
||||
return `<div class="language-${lang} ${active ? 'active' : ''}">
|
||||
<button title="Copy Code" class="copy"></button>
|
||||
<span class="lang">${lang}</span>
|
||||
${highlightedCode}
|
||||
</div>`;
|
||||
};
|
||||
</div>`
|
||||
}
|
||||
|
||||
|
||||
export default async function createCodeExamples() {
|
||||
const codes = getIconCodes();
|
||||
@@ -154,7 +153,7 @@ export default async function createCodeExamples() {
|
||||
language: language,
|
||||
code: codeString,
|
||||
};
|
||||
});
|
||||
})
|
||||
|
||||
return Promise.all(codeExamplePromises);
|
||||
}
|
||||
@@ -1,36 +1,38 @@
|
||||
import { promises as fs, constants } from 'fs';
|
||||
import path from 'path';
|
||||
import yaml from 'js-yaml'
|
||||
import { PackageItem } from '../theme/types';
|
||||
|
||||
const fileExist = (filePath) =>
|
||||
fs
|
||||
.access(filePath, constants.F_OK)
|
||||
.then(() => true)
|
||||
.catch(() => false);
|
||||
const fileExist = (filePath) => fs.access(filePath, constants.F_OK).then(() => true).catch(() => false)
|
||||
|
||||
const fetchPackages = async (): Promise<PackageItem[]> => {
|
||||
const docsDir = path.resolve(process.cwd(), '../packages');
|
||||
const fileNames = await (
|
||||
await fs.readdir(docsDir)
|
||||
).map((filename) => ({ filename, directory: docsDir }));
|
||||
const fileNames = await (await fs.readdir(docsDir)).map(filename => ({filename, directory: docsDir}))
|
||||
|
||||
const packageJsons = await Promise.all(
|
||||
fileNames.map(async ({ filename, directory }) => {
|
||||
const filePath = path.resolve(directory, filename);
|
||||
const packageJsons = await Promise.all(fileNames.map( async ({filename, directory}) => {
|
||||
const filePath = path.resolve(directory, filename)
|
||||
const fileStat = await fs.lstat(filePath);
|
||||
|
||||
if (!fileStat.isDirectory()) return null;
|
||||
if(!fileStat.isDirectory()) return null;
|
||||
|
||||
const jsonFilePath = path.resolve(filePath, 'package.json');
|
||||
const jsonFilePath = path.resolve(filePath, 'package.json')
|
||||
if (await fileExist(jsonFilePath)) {
|
||||
return JSON.parse(await fs.readFile(jsonFilePath, 'utf-8'));
|
||||
return JSON.parse(
|
||||
await fs.readFile(jsonFilePath, 'utf-8')
|
||||
)
|
||||
}
|
||||
|
||||
return null;
|
||||
}),
|
||||
const ymlFilePath = path.resolve(filePath, 'pubspec.yaml')
|
||||
if(await fileExist(ymlFilePath)) {
|
||||
return yaml.load(
|
||||
await fs.readFile(ymlFilePath, 'utf-8')
|
||||
);
|
||||
}
|
||||
|
||||
return packageJsons;
|
||||
};
|
||||
return null
|
||||
}))
|
||||
|
||||
return packageJsons
|
||||
}
|
||||
|
||||
export default fetchPackages;
|
||||
|
||||
@@ -1,15 +1,17 @@
|
||||
export type IconContent = [icon: string, src: string];
|
||||
export type IconContent = [icon: string, src:string];
|
||||
|
||||
async function generateZip(icons: IconContent[]) {
|
||||
const JSZip = (await import('jszip')).default;
|
||||
const JSZip = (await import('jszip')).default
|
||||
|
||||
const zip = new JSZip();
|
||||
|
||||
const addingZipPromises = icons.map(([name, src]) => zip.file(`${name}.svg`, src));
|
||||
const addingZipPromises = icons.map(([name, src]) =>
|
||||
zip.file(`${name}.svg`, src),
|
||||
);
|
||||
|
||||
await Promise.all(addingZipPromises);
|
||||
await Promise.all(addingZipPromises)
|
||||
|
||||
return zip.generateAsync({ type: 'blob' });
|
||||
}
|
||||
|
||||
export default generateZip;
|
||||
export default generateZip
|
||||
|
||||
@@ -1,15 +1,17 @@
|
||||
import { createLucideIcon } from 'lucide-react/src/lucide-react';
|
||||
import { type LucideProps, type IconNode } from 'lucide-react/src/createLucideIcon';
|
||||
import { IconEntity } from '../theme/types';
|
||||
import { createLucideIcon } from "lucide-react/src/lucide-react"
|
||||
import { type LucideProps, type IconNode } from "lucide-react/src/createLucideIcon"
|
||||
import { IconEntity } from "../theme/types"
|
||||
import { renderToStaticMarkup } from 'react-dom/server';
|
||||
import { IconContent } from './generateZip';
|
||||
import { IconContent } from "./generateZip";
|
||||
|
||||
const getFallbackZip = (icons: IconEntity[], params: LucideProps) => {
|
||||
return icons.map<IconContent>((icon) => {
|
||||
const Icon = createLucideIcon(icon.name, icon.iconNode as IconNode);
|
||||
const src = renderToStaticMarkup(<Icon {...params} />);
|
||||
return [icon.name, src];
|
||||
});
|
||||
};
|
||||
return icons
|
||||
.map<IconContent>((icon) => {
|
||||
const Icon = createLucideIcon(icon.name, icon.iconNode as IconNode)
|
||||
const src = renderToStaticMarkup(<Icon {...params} />)
|
||||
return [icon.name, src]
|
||||
})
|
||||
}
|
||||
|
||||
export default getFallbackZip;
|
||||
|
||||
export default getFallbackZip
|
||||
|
||||
@@ -1,34 +1,34 @@
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import { IconNodeWithKeys } from '../theme/types';
|
||||
import iconNodes from '../data/iconNodes';
|
||||
import releaseMeta from '../data/releaseMetaData.json';
|
||||
import fs from "fs";
|
||||
import path from "path";
|
||||
import { IconNodeWithKeys } from "../theme/types";
|
||||
import iconNodes from '../data/iconNodes'
|
||||
import releaseMeta from "../data/releaseMetaData.json";
|
||||
|
||||
const DATE_OF_FORK = '2020-06-08T16:39:52+0100';
|
||||
|
||||
const directory = path.join(process.cwd(), '../icons');
|
||||
const directory = path.join(process.cwd(), "../icons");
|
||||
|
||||
export interface GetDataOptions {
|
||||
withChildKeys?: boolean;
|
||||
withChildKeys?: boolean
|
||||
}
|
||||
|
||||
export async function getData(name: string) {
|
||||
const jsonPath = path.join(directory, `${name}.json`);
|
||||
const jsonContent = fs.readFileSync(jsonPath, 'utf8');
|
||||
const jsonContent = fs.readFileSync(jsonPath, "utf8");
|
||||
const { tags, categories, contributors } = JSON.parse(jsonContent);
|
||||
|
||||
const iconNode = iconNodes[name];
|
||||
const iconNode = iconNodes[name]
|
||||
|
||||
const releaseData = releaseMeta?.[name] ?? {
|
||||
createdRelease: {
|
||||
version: '0.0.0',
|
||||
date: DATE_OF_FORK,
|
||||
"createdRelease": {
|
||||
"version": "0.0.0",
|
||||
"date": DATE_OF_FORK
|
||||
},
|
||||
changedRelease: {
|
||||
version: '0.0.0',
|
||||
date: DATE_OF_FORK,
|
||||
},
|
||||
};
|
||||
"changedRelease": {
|
||||
"version": "0.0.0",
|
||||
"date": DATE_OF_FORK
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
name,
|
||||
@@ -36,11 +36,11 @@ export async function getData(name: string) {
|
||||
categories,
|
||||
iconNode,
|
||||
contributors,
|
||||
...releaseData,
|
||||
...releaseData
|
||||
};
|
||||
}
|
||||
|
||||
export async function getAllData(): Promise<{ name: string; iconNode: IconNodeWithKeys }[]> {
|
||||
export async function getAllData(): Promise<{ name: string, iconNode: IconNodeWithKeys}[]> {
|
||||
const names = Object.keys(iconNodes);
|
||||
|
||||
return Promise.all(names.map((name) => getData(name)));
|
||||
|
||||
@@ -1,54 +1,50 @@
|
||||
import { DefaultTheme, UserConfig } from 'vitepress';
|
||||
import { DefaultTheme, UserConfig } from "vitepress"
|
||||
|
||||
const sidebar: UserConfig<DefaultTheme.Config>['themeConfig']['sidebar'] = {
|
||||
guide: [
|
||||
'guide':[
|
||||
{
|
||||
text: 'Introduction',
|
||||
items: [
|
||||
{ text: 'What is lucide?', link: '/guide/' },
|
||||
{ text: 'Installation', link: '/guide/installation' },
|
||||
{ text: 'Comparison', link: '/guide/comparison' },
|
||||
],
|
||||
{ text: 'Comparison', link: '/guide/comparison' }
|
||||
]
|
||||
},
|
||||
{
|
||||
text: 'Basics',
|
||||
items: [
|
||||
{
|
||||
text: 'Color',
|
||||
link: '/guide/basics/color',
|
||||
link: '/guide/basics/color'
|
||||
},
|
||||
{
|
||||
text: 'Sizing',
|
||||
link: '/guide/basics/sizing',
|
||||
link: '/guide/basics/sizing'
|
||||
},
|
||||
{
|
||||
text: 'Stroke width',
|
||||
link: '/guide/basics/stroke-width',
|
||||
link: '/guide/basics/stroke-width'
|
||||
},
|
||||
],
|
||||
]
|
||||
},
|
||||
// TODO: Add this section
|
||||
{
|
||||
text: 'Advanced',
|
||||
items: [
|
||||
{
|
||||
text: 'Accessibility',
|
||||
link: '/guide/advanced/accessibility',
|
||||
},
|
||||
// {
|
||||
// text: 'Accessibility',
|
||||
// link: '/guide/advanced/accessibility'
|
||||
// },
|
||||
{
|
||||
text: 'Global styling',
|
||||
link: '/guide/advanced/global-styling',
|
||||
link: '/guide/advanced/global-styling'
|
||||
},
|
||||
// {
|
||||
// text: 'Animations',
|
||||
// },
|
||||
{
|
||||
text: 'Filled icons',
|
||||
link: '/guide/advanced/filled-icons',
|
||||
},
|
||||
{
|
||||
text: 'Aliased Names',
|
||||
link: '/guide/advanced/aliased-names',
|
||||
link: '/guide/advanced/filled-icons'
|
||||
},
|
||||
// {
|
||||
// text: 'Combining icons',
|
||||
@@ -59,81 +55,75 @@ const sidebar: UserConfig<DefaultTheme.Config>['themeConfig']['sidebar'] = {
|
||||
// {
|
||||
// text: 'Auto importing'
|
||||
// },
|
||||
],
|
||||
]
|
||||
},
|
||||
{
|
||||
text: 'Packages',
|
||||
items: [
|
||||
{
|
||||
text: 'Lucide',
|
||||
link: '/guide/packages/lucide',
|
||||
link: '/guide/packages/lucide'
|
||||
},
|
||||
{
|
||||
text: 'Lucide React',
|
||||
link: '/guide/packages/lucide-react',
|
||||
},
|
||||
{
|
||||
text: 'Lucide Vue',
|
||||
link: '/guide/packages/lucide-vue-next',
|
||||
},
|
||||
{
|
||||
text: 'Lucide Svelte',
|
||||
link: '/guide/packages/lucide-svelte',
|
||||
},
|
||||
{
|
||||
text: 'Lucide Solid',
|
||||
link: '/guide/packages/lucide-solid',
|
||||
link: '/guide/packages/lucide-react'
|
||||
},
|
||||
{
|
||||
text: 'Lucide React Native',
|
||||
link: '/guide/packages/lucide-react-native',
|
||||
link: '/guide/packages/lucide-react-native'
|
||||
},
|
||||
{
|
||||
text: 'Lucide Angular',
|
||||
link: '/guide/packages/lucide-angular',
|
||||
text: 'Lucide Vue',
|
||||
link: '/guide/packages/lucide-vue-next'
|
||||
},
|
||||
{
|
||||
text: 'Lucide Svelte',
|
||||
link: '/guide/packages/lucide-svelte'
|
||||
},
|
||||
{
|
||||
text: 'Lucide Solid',
|
||||
link: '/guide/packages/lucide-solid'
|
||||
},
|
||||
{
|
||||
text: 'Lucide Preact',
|
||||
link: '/guide/packages/lucide-preact',
|
||||
link: '/guide/packages/lucide-preact'
|
||||
},
|
||||
{
|
||||
text: 'Lucide Astro',
|
||||
link: '/guide/packages/lucide-astro',
|
||||
text: 'Lucide Angular',
|
||||
link: '/guide/packages/lucide-angular'
|
||||
},
|
||||
{
|
||||
text: 'Lucide Static',
|
||||
link: '/guide/packages/lucide-static',
|
||||
link: '/guide/packages/lucide-static'
|
||||
},
|
||||
],
|
||||
]
|
||||
},
|
||||
{
|
||||
text: 'Contributing',
|
||||
items: [
|
||||
{
|
||||
text: 'Icon Design Principles',
|
||||
link: '/guide/design/icon-design-guide',
|
||||
link: '/guide/design/icon-design-guide'
|
||||
},
|
||||
{
|
||||
text: 'Designing in Illustrator',
|
||||
link: '/guide/design/illustrator-guide',
|
||||
link: '/guide/design/illustrator-guide'
|
||||
},
|
||||
{
|
||||
text: 'Designing in InkScape',
|
||||
link: '/guide/design/inkscape-guide',
|
||||
link: '/guide/design/inkscape-guide'
|
||||
},
|
||||
{
|
||||
text: 'Designing in Figma',
|
||||
link: '/guide/design/figma-guide',
|
||||
link: '/guide/design/figma-guide'
|
||||
},
|
||||
{
|
||||
text: 'Designing in Affinity Designer',
|
||||
link: '/guide/design/affinity-designer-guide',
|
||||
},
|
||||
],
|
||||
]
|
||||
},
|
||||
],
|
||||
// This should be here to keep the sidebar shown on the icons page
|
||||
icons: [{ text: '', link: '/' }],
|
||||
};
|
||||
'icons': [
|
||||
{ text: '', link: '/' },
|
||||
],
|
||||
}
|
||||
|
||||
export default sidebar;
|
||||
export default sidebar
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue';
|
||||
|
||||
import { useRouter } from 'vitepress';
|
||||
|
||||
const { go } = useRouter()
|
||||
@@ -7,16 +8,7 @@ const props = defineProps<{
|
||||
href?: string
|
||||
}>()
|
||||
|
||||
const isExternal = computed(() => props.href?.startsWith('http') ?? false)
|
||||
|
||||
const component = computed(() => props.href ? 'a' : 'div')
|
||||
const target = computed(() => isExternal.value ? '_blank' : undefined)
|
||||
const rel = computed(() => isExternal.value ? 'noreferrer noopener' : undefined)
|
||||
|
||||
const onClick = computed(() => {
|
||||
if(!props.href || isExternal) return
|
||||
return go(props.href)
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -24,9 +16,7 @@ const onClick = computed(() => {
|
||||
:is="component"
|
||||
:href="href"
|
||||
class="badge"
|
||||
:target="target"
|
||||
:rel="rel"
|
||||
@click="onClick"
|
||||
@click="props?.href ? go(href) : undefined"
|
||||
>
|
||||
<slot/>
|
||||
</component>
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
<template>
|
||||
<div class="card-grid-flex">
|
||||
<div class="grid">
|
||||
<slot />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
.card-grid-flex {
|
||||
<style scoped>
|
||||
.grid {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: stretch;
|
||||
@@ -15,20 +15,20 @@
|
||||
margin: -8px;
|
||||
}
|
||||
|
||||
.card-grid-flex > * {
|
||||
.grid > * {
|
||||
flex-basis: 100%;
|
||||
box-sizing: border-box;
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
@media (min-width: 960px) {
|
||||
.card-grid-flex > * {
|
||||
.grid > * {
|
||||
flex-basis: 50%;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 1280px) {
|
||||
.card-grid-flex > * {
|
||||
.grid > * {
|
||||
flex-basis: 33.33%;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,90 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue';
|
||||
|
||||
const props = defineProps<{
|
||||
label: string
|
||||
id: string
|
||||
value: string
|
||||
modelValue: string | string[]
|
||||
}>()
|
||||
|
||||
const emit = defineEmits(['change', 'input', 'update:modelValue'])
|
||||
|
||||
const model = computed({
|
||||
get: () => {
|
||||
if (Array.isArray(props.modelValue)) {
|
||||
return props.modelValue.includes(props.value)
|
||||
}
|
||||
return props.modelValue === props.value
|
||||
|
||||
},
|
||||
set: (value: string) => {
|
||||
if (Array.isArray(props.modelValue)) {
|
||||
const newValue = [...props.modelValue]
|
||||
const index = newValue.indexOf(props.value)
|
||||
if (value) {
|
||||
if (index === -1) {
|
||||
newValue.push(props.value)
|
||||
}
|
||||
} else {
|
||||
if (index !== -1) {
|
||||
newValue.splice(index, 1)
|
||||
}
|
||||
}
|
||||
emit('update:modelValue', newValue)
|
||||
} else {
|
||||
emit('update:modelValue', value)
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="checkbox-wrapper">
|
||||
<input
|
||||
type="checkbox"
|
||||
class="checkbox"
|
||||
ref="input"
|
||||
:id="id"
|
||||
v-model="model"
|
||||
v-bind="$attrs"
|
||||
/>
|
||||
<label :for="id" class="checkbox-label">
|
||||
{{ label }}
|
||||
</label>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.checkbox-wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.checkbox-label {
|
||||
line-height: 20px;
|
||||
font-size: 13px;
|
||||
color: var(--vt-c-text-1);
|
||||
transition: color .5s;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.checkbox {
|
||||
-webkit-appearance: none;
|
||||
appearance: none;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
cursor: pointer;
|
||||
border: 1px solid var(--vp-input-border-color);
|
||||
background-color: var(--vp-input-switch-bg-color);
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.checkbox:checked {
|
||||
border-color: transparent;
|
||||
background: url("data:image/svg+xml,%3Csvg width='12px' height='12px' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='4' stroke-linecap='round' stroke-linejoin='round' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E")
|
||||
center no-repeat var(--vp-c-brand);;
|
||||
}
|
||||
|
||||
</style>
|
||||
@@ -24,10 +24,40 @@ const headingElement = computed(() => `h${props.headingLevel}`)
|
||||
font-size: 32px;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
margin-bottom: 36px;
|
||||
margin-bottom: 32px;
|
||||
}
|
||||
|
||||
section {
|
||||
margin-bottom: 96px;
|
||||
}
|
||||
|
||||
.grid {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: stretch;
|
||||
justify-content: center;
|
||||
align-content: space-evenly;
|
||||
box-sizing: border-box;
|
||||
margin: -8px;
|
||||
}
|
||||
|
||||
.grid > * {
|
||||
flex-basis: 100%;
|
||||
box-sizing: border-box;
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
@media (min-width: 960px) {
|
||||
.grid > * {
|
||||
flex-basis: 50%;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 1280px) {
|
||||
.grid > * {
|
||||
flex-basis: 33.33%;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
</style>
|
||||
|
||||
@@ -38,7 +38,6 @@ const value = computed({
|
||||
<Input
|
||||
ref="input"
|
||||
type="search"
|
||||
autofocus
|
||||
v-bind="$attrs"
|
||||
v-model="value"
|
||||
class="input-wrapper"
|
||||
|
||||
@@ -1,22 +1,15 @@
|
||||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
import { Switch } from '@headlessui/vue'
|
||||
|
||||
defineProps({
|
||||
modelValue: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
})
|
||||
|
||||
const emit = defineEmits(['update:modelValue'])
|
||||
const enabled = ref(false)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Switch
|
||||
:model-value="modelValue"
|
||||
@update:model-value="emit('update:modelValue', $event)"
|
||||
v-model="enabled"
|
||||
class="switch"
|
||||
:class="{ enabled: modelValue }"
|
||||
:class="{ enabled }"
|
||||
>
|
||||
<span class="thumb" />
|
||||
</Switch>
|
||||
|
||||
@@ -42,7 +42,7 @@ onMounted(() => {
|
||||
font-weight: 400;
|
||||
background: var(--vp-c-brand-dark);
|
||||
color: white;
|
||||
z-index: 99;
|
||||
z-index: 10;
|
||||
white-space: nowrap;
|
||||
padding: 2px 8px;
|
||||
border-radius: 4px;
|
||||
|
||||
@@ -1,18 +1,16 @@
|
||||
export default {
|
||||
async load() {
|
||||
const version = await fetch('https://api.github.com/repos/lucide-icons/lucide/releases/latest')
|
||||
.then((res) => {
|
||||
const version = await fetch('https://api.github.com/repos/lucide-icons/lucide/releases/latest').then(res => {
|
||||
if (res.ok) {
|
||||
const releaseData = res.json() as Promise<{ tag_name: string }>;
|
||||
const releaseData = res.json() as Promise<{ tag_name: string }>
|
||||
|
||||
return releaseData;
|
||||
return releaseData
|
||||
}
|
||||
return null;
|
||||
})
|
||||
.then((res) => res?.tag_name);
|
||||
return null
|
||||
}).then(res => res.tag_name)
|
||||
|
||||
return {
|
||||
version,
|
||||
};
|
||||
},
|
||||
};
|
||||
version
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,8 @@ import { data } from './HomeHeroBefore.data'
|
||||
<HomeContainer class="container">
|
||||
<Badge
|
||||
:href="`https://github.com/lucide-icons/lucide/releases/tag/${data.version}`"
|
||||
target="_blank"
|
||||
rel="noreferrer noopener"
|
||||
>v{{ data.version }}</Badge>
|
||||
</HomeContainer>
|
||||
</template>
|
||||
|
||||
@@ -1,17 +1,16 @@
|
||||
import iconNodes from '../../../data/iconNodes';
|
||||
import iconNodes from '../../../data/iconNodes'
|
||||
|
||||
const getRandomItem = <Item>(items: Item[]): Item =>
|
||||
items[Math.floor(Math.random() * items.length)];
|
||||
const getRandomItem = <Item>(items: Item[]): Item => items[Math.floor(Math.random()*items.length)];
|
||||
|
||||
export default {
|
||||
async load() {
|
||||
const icons = Object.entries(iconNodes).map(([name, iconNode]) => ({ name, iconNode }));
|
||||
const icons = Object.entries(iconNodes).map(([name, iconNode]) => ({ name, iconNode }))
|
||||
|
||||
const randomIcons = Array.from({ length: 200 }, () => getRandomItem(icons));
|
||||
const randomIcons = Array.from({ length: 200 }, () => getRandomItem(icons))
|
||||
|
||||
return {
|
||||
icons: randomIcons,
|
||||
iconsCount: icons.length,
|
||||
};
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,6 +28,8 @@ function insert() {
|
||||
const replaceIndex = random(0, 48)
|
||||
const newIcon = getRandomNewIcon()
|
||||
|
||||
// items.value.splice(replaceIndex, 0, newIcon);
|
||||
|
||||
items.value[replaceIndex] = newIcon
|
||||
}
|
||||
|
||||
@@ -74,6 +76,7 @@ onBeforeUnmount(() => {
|
||||
|
||||
<style scoped>
|
||||
.card-wrapper {
|
||||
/* padding: 0 24px; */
|
||||
margin-left: auto;
|
||||
margin-bottom: auto;
|
||||
margin-top: 48px;
|
||||
@@ -84,10 +87,13 @@ onBeforeUnmount(() => {
|
||||
border-radius: 8px;
|
||||
width: 100%;
|
||||
height:100%;
|
||||
/* box-shadow: var(--vp-shadow-2); */
|
||||
max-height: 220px;
|
||||
max-width: 560px;
|
||||
margin: 0 auto;
|
||||
position: relative;
|
||||
/* max-height: 240px; */
|
||||
/* margin-top: 96px; */
|
||||
}
|
||||
|
||||
.card-grid {
|
||||
@@ -101,6 +107,7 @@ onBeforeUnmount(() => {
|
||||
max-width: 512px;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
/* white-space: nowrap; */
|
||||
}
|
||||
|
||||
.list-enter-active {
|
||||
|
||||
@@ -48,7 +48,6 @@ function resetStyle () {
|
||||
color.value = 'currentColor'
|
||||
strokeWidth.value = 2
|
||||
size.value = 24
|
||||
absoluteStrokeWidth.value = false
|
||||
}
|
||||
|
||||
watch(absoluteStrokeWidth, (enabled) => {
|
||||
@@ -172,14 +171,16 @@ watch(absoluteStrokeWidth, (enabled) => {
|
||||
margin-top: 32px;
|
||||
padding: 0;
|
||||
background: none;
|
||||
max-width: 280px;
|
||||
}
|
||||
|
||||
@media (min-width: 640px) {
|
||||
|
||||
.card {
|
||||
display: grid;
|
||||
grid-template-columns: 8fr 10fr;
|
||||
}
|
||||
/*
|
||||
/*
|
||||
.card-column {
|
||||
flex: 1;
|
||||
} */
|
||||
|
||||
@@ -37,12 +37,6 @@ export default {
|
||||
logo: '/framework-logos/angular.svg',
|
||||
label: 'Lucide documentation for Angular',
|
||||
},
|
||||
{
|
||||
name: 'lucide-astro',
|
||||
logo: '/framework-logos/astro.svg',
|
||||
logoDark: '/framework-logos/astro-dark.svg',
|
||||
label: 'Lucide documentation for Astro',
|
||||
},
|
||||
{
|
||||
name: 'lucide-react-native',
|
||||
logo: '/framework-logos/react-native.svg',
|
||||
@@ -53,7 +47,7 @@ export default {
|
||||
logo: '/framework-logos/flutter.svg',
|
||||
label: 'Lucide documentation for Flutter',
|
||||
},
|
||||
],
|
||||
};
|
||||
},
|
||||
};
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import HomeContainer from './HomeContainer.vue'
|
||||
import HomeSectionTitle from './HomeSectionTitle.vue'
|
||||
import { useRouter } from 'vitepress';
|
||||
import { data } from './HomePackagesSection.data'
|
||||
import VPButton from 'vitepress/dist/client/theme-default/components/VPButton.vue';
|
||||
@@ -10,10 +9,10 @@ const { go } = useRouter()
|
||||
|
||||
<template>
|
||||
<HomeContainer>
|
||||
<HomeSectionTitle>Available For:</HomeSectionTitle>
|
||||
<h2 class="section-title">Available For:</h2>
|
||||
<div class="packages-list">
|
||||
<a
|
||||
v-for="{ name, logo, logoDark } in data.packages"
|
||||
v-for="{ name, logo } in data.packages"
|
||||
:href="`/guide/packages/${name}`"
|
||||
class="package-logo"
|
||||
:aria-label="`Read more about: ${name} package`"
|
||||
@@ -21,17 +20,10 @@ const { go } = useRouter()
|
||||
>
|
||||
<img
|
||||
:src="logo"
|
||||
:class="{ light: logoDark, 'image-logo': true }"
|
||||
:alt="`${name} logo`"
|
||||
height="36"
|
||||
width="36"
|
||||
loading="lazy"
|
||||
/>
|
||||
|
||||
<img
|
||||
v-if="logoDark"
|
||||
:src="logoDark"
|
||||
:alt="`${name} logo`"
|
||||
class="image-logo dark"
|
||||
loading="lazy"
|
||||
/>
|
||||
</a>
|
||||
</div>
|
||||
@@ -42,13 +34,14 @@ const { go } = useRouter()
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
.image-logo {
|
||||
object-fit: contain;
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
.section-title {
|
||||
color: var(--vp-c-text-2);
|
||||
font-weight: 500;
|
||||
line-height: 32px;
|
||||
font-size: 16px;
|
||||
text-align: center;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.packages-list {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
@@ -71,11 +64,4 @@ const { go } = useRouter()
|
||||
.package-logo:hover {
|
||||
opacity: .6;
|
||||
}
|
||||
|
||||
html.dark .image-logo.light {
|
||||
display: none;
|
||||
}
|
||||
html:not(.dark) .image-logo.dark {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue';
|
||||
|
||||
const props = defineProps<{
|
||||
headingLevel: 1 | 2 | 3 | 4 | 5 | 6,
|
||||
}>()
|
||||
|
||||
const headingElement = computed(() => `h${props.headingLevel ?? 2}`)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<component :is="headingElement" class="section-title">
|
||||
<slot />
|
||||
</component>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.section-title {
|
||||
color: var(--vp-c-text-2);
|
||||
font-weight: 500;
|
||||
line-height: 32px;
|
||||
font-size: 16px;
|
||||
text-align: center;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
</style>
|
||||
@@ -1,59 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
import Card from '../base/Card.vue';
|
||||
import HomeSectionTitle from './HomeSectionTitle.vue';
|
||||
import VPButton from 'vitepress/dist/client/theme-default/components/VPButton.vue';
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<HomeSectionTitle :headingLevel="3"> Sponsor the Lucide maintainers </HomeSectionTitle>
|
||||
<Card class="sponsor-card">
|
||||
<img
|
||||
src="/company-logos/open-collective-light.svg"
|
||||
alt="Open Collective logo"
|
||||
class="logo light"
|
||||
width="242"
|
||||
height="42"
|
||||
/>
|
||||
<img
|
||||
src="/company-logos/open-collective-dark.svg"
|
||||
alt="Open Collective logo"
|
||||
class="logo dark"
|
||||
width="242"
|
||||
height="42"
|
||||
/>
|
||||
<VPButton
|
||||
href="https://opencollective.com/lucide-icons"
|
||||
class="sponsor-button"
|
||||
text="Become a sponsor"
|
||||
/>
|
||||
</Card>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.sponsor-card {
|
||||
margin: 0 auto;
|
||||
max-width: 500px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 24px;
|
||||
}
|
||||
|
||||
.sponsor-button {
|
||||
margin: auto 0;
|
||||
}
|
||||
|
||||
html.dark .logo.dark {
|
||||
display: none;
|
||||
}
|
||||
html:not(.dark) .logo.light {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@media (min-width: 640px) {
|
||||
.sponsor-card {
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user