mirror of
https://github.com/lucide-icons/lucide.git
synced 2026-11-11 13:28:19 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f664af1933 | ||
|
|
03ad294db0 | ||
|
|
a2ec77fc7f | ||
|
|
602bca62a2 | ||
|
|
423afc6d03 | ||
|
|
374398b58d | ||
|
|
6c2b8e6fa0 | ||
|
|
ecc612044e | ||
|
|
896aba0d19 | ||
|
|
45740bef8b | ||
|
|
84ab8524b5 | ||
|
|
071e4d2738 | ||
|
|
3c9d1a56a4 | ||
|
|
c20dd8464d | ||
|
|
29af709846 | ||
|
|
410dfc3577 | ||
|
|
574e156701 | ||
|
|
22cfe96931 | ||
|
|
1475fc02e0 | ||
|
|
7f14e74e4d | ||
|
|
5b40f2c5a7 | ||
|
|
bac39e6c53 | ||
|
|
523026ac18 | ||
|
|
2214caa407 | ||
|
|
105f501730 | ||
|
|
5f787f956b | ||
|
|
437c370821 | ||
|
|
fb885f333a | ||
|
|
71ec48ce30 | ||
|
|
d624fc51ab | ||
|
|
1c381a075c | ||
|
|
a168a87834 | ||
|
|
7e9def13a6 | ||
|
|
228c86ed12 | ||
|
|
50b7038d27 | ||
|
|
a51e94b25c | ||
|
|
3d7a12949b | ||
|
|
07c885e6c1 | ||
|
|
446e644e63 | ||
|
|
6d38f90429 |
@@ -13,21 +13,19 @@ body:
|
||||
description: Which Lucide packages are affected? You may select more than one.
|
||||
options:
|
||||
- label: lucide
|
||||
- label: lucide-angular (old version)
|
||||
- label: '@lucide/angular (new version)'
|
||||
- label: '@lucide/astro'
|
||||
- label: lucide-flutter
|
||||
- label: lucide-preact
|
||||
- label: lucide-react
|
||||
- label: '@lucide/vue'
|
||||
- label: '@lucide/svelte'
|
||||
- label: '@lucide/angular'
|
||||
- label: '@lucide/astro'
|
||||
- label: lucide-react-native
|
||||
- label: lucide-preact
|
||||
- label: lucide-solid
|
||||
- label: lucide-static
|
||||
- label: lucide-svelte (old version)
|
||||
- label: '@lucide/svelte (new version)'
|
||||
- label: lucide-vue
|
||||
- label: lucide-vue-next
|
||||
- label: lucide-astro
|
||||
- label: '@lucide/icons'
|
||||
- label: lucide-vue-next (deprecated)
|
||||
- label: lucide-svelte (deprecated)
|
||||
- label: lucide-angular (deprecated)
|
||||
- label: Figma plugin
|
||||
- label: source/main
|
||||
- label: other/not relevant
|
||||
@@ -38,7 +36,7 @@ body:
|
||||
attributes:
|
||||
label: Version
|
||||
description: What version of Lucide are you running?
|
||||
placeholder: e.g. 0.289.1
|
||||
placeholder: e.g. 1.1.0
|
||||
validations:
|
||||
required: true
|
||||
- type: checkboxes
|
||||
|
||||
@@ -13,21 +13,19 @@ body:
|
||||
description: Which Lucide project do you wish this feature were added to? You may select more than one.
|
||||
options:
|
||||
- label: lucide
|
||||
- label: lucide-angular (old version)
|
||||
- label: '@lucide/angular (new version)'
|
||||
- label: '@lucide/astro'
|
||||
- label: lucide-flutter
|
||||
- label: lucide-preact
|
||||
- label: lucide-react
|
||||
- label: '@lucide/vue'
|
||||
- label: '@lucide/svelte'
|
||||
- label: '@lucide/angular'
|
||||
- label: '@lucide/astro'
|
||||
- label: lucide-react-native
|
||||
- label: lucide-preact
|
||||
- label: lucide-solid
|
||||
- label: lucide-static
|
||||
- label: lucide-svelte (old version)
|
||||
- label: '@lucide/svelte (new version)'
|
||||
- label: lucide-vue
|
||||
- label: lucide-vue-next
|
||||
- label: lucide-astro
|
||||
- label: '@lucide/icons'
|
||||
- label: lucide-vue-next (deprecated)
|
||||
- label: lucide-svelte (deprecated)
|
||||
- label: lucide-angular (deprecated)
|
||||
- label: Figma plugin
|
||||
- label: all JS packages
|
||||
- label: site
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
## Reviewing PRs
|
||||
|
||||
When reviewing PRs, please respond in a friendly and constructive manner.
|
||||
|
||||
- First, thank the contributor for their contribution in an enthusiastic way.
|
||||
- If you have any suggestions for improvement, provide them clearly and concisely.
|
||||
- If you have any questions about the PR, ask them respectfully.
|
||||
- Let the contributor know that we have many PRs to review and that we appreciate their patience while we review their contribution.
|
||||
@@ -0,0 +1,20 @@
|
||||
---
|
||||
applyTo: "icons/*.json"
|
||||
---
|
||||
# JSON Metadata Descriptor
|
||||
|
||||
The schema for the JSON metadata descriptor can be found in `icon.schema.json`. It defines the required and optional properties for the JSON files that accompany each icon. The JSON metadata descriptor should be placed in the same directory as the SVG file of the icon and should have the same name as the SVG file, but with a `.json` extension. For example, if the SVG file is named `home.svg`, the JSON metadata descriptor should be named `home.json`.
|
||||
|
||||
## Contributors
|
||||
|
||||
The `contributors` property is a required array of GitHub usernames for the people who created or contributed to the icon. It is used to give credit to contributors and to track the icon's history. Add the PR author to the `contributors` array if they are not already listed and they have made a significant contribution to the icon's SVG.
|
||||
|
||||
## Tags
|
||||
|
||||
The `tags` property is an array of strings that describe the icon and can be used for searching.
|
||||
Validate the tags against the `icon.schema.json` to ensure they are correctly formatted and adhere to the defined structure.
|
||||
Provide tag suggestions based on the name of the icon and the use cases provided in the PR description. Use the existing tags in the repository as a reference for consistency and to avoid duplicates. Don't suggest words like: 'icon' and preferably use single words. Tags should always be in lowercase and should not contain spaces. The name of icon should not be included in the tags, as it is already specified.
|
||||
|
||||
# Categories
|
||||
|
||||
The `categories` property is an array of strings that specify the categories to which the icon belongs, such as "devices", "interface", "media", etc. See the `categories` property in the `icon.schema.json` for more details on the allowed values. The categories should be chosen based on the use cases provided in the PR description and the existing categories in the repository. The categories should be relevant to the icon and should help users find the icon when searching for specific types of icons. The name of icon should not be included in the categories, as it is already specified. Suggest categories based on the name of the icon and the use cases provided in the PR description. Use the existing categories in the repository as a reference for consistency and to avoid duplicates. Categories should always be in lowercase and should not contain spaces.
|
||||
+2
-10
@@ -52,15 +52,13 @@
|
||||
💎 vue package:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- 'packages/lucide-vue/*'
|
||||
- 'packages/lucide-vue-next/*'
|
||||
- 'packages/vue/*'
|
||||
|
||||
# For changes in the Lucide angular package
|
||||
🅰️ angular package:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- 'packages/angular/*'
|
||||
- 'packages/lucide-angular/*'
|
||||
|
||||
# For changes in the Lucide preact package
|
||||
⚛️ preact package:
|
||||
@@ -72,7 +70,7 @@
|
||||
🧣 svelte package:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- 'packages/lucide-svelte/*'
|
||||
- 'packages/svelte/*'
|
||||
|
||||
# For changes in the Lucide solid package
|
||||
🪝 solid package:
|
||||
@@ -97,9 +95,3 @@
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- 'packages/lucide-static/*'
|
||||
|
||||
# For changes in the Lucide flutter package
|
||||
🏹 flutter package:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- 'packages/lucide-flutter/*'
|
||||
|
||||
@@ -32,8 +32,37 @@ concurrency:
|
||||
group: continuous-integration
|
||||
|
||||
jobs:
|
||||
check-dispatch-gate:
|
||||
if: github.repository == 'lucide-icons/lucide' &&
|
||||
startsWith(github.event.head_commit.message, 'feat(icons)') &&
|
||||
github.event_name != 'workflow_dispatch'
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
RELEASE_ENVIRONMENT: ${{ steps.environment.outputs.RELEASE_ENVIRONMENT }}
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
|
||||
- name: Fetch tags
|
||||
run: git fetch --all --tags
|
||||
|
||||
- name: Check if latest tag was created today
|
||||
id: environment
|
||||
run: |
|
||||
LATEST_TAG=$(git tag --sort=-v:refname | grep -E '^[0-9]+\.[0-9]+\.[0-9]+$' | head -n 1)
|
||||
TAG_DATE=$(git log -1 --format=%cs "$LATEST_TAG")
|
||||
TODAY=$(date +%Y-%m-%d)
|
||||
|
||||
if [ "$TAG_DATE" == "$TODAY" ]; then
|
||||
echo "::warning::A release tag already exists for today ($TODAY): $LATEST_TAG. Manual approval will be required to proceed."
|
||||
echo "RELEASE_ENVIRONMENT=Icon Release Gated" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "RELEASE_ENVIRONMENT=Icon Release" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
create-release:
|
||||
if: github.repository == 'lucide-icons/lucide' && startsWith(github.event.head_commit.message, 'feat(icons)') && github.event_name != 'workflow_dispatch'
|
||||
if: github.repository == 'lucide-icons/lucide'
|
||||
needs: check-dispatch-gate
|
||||
environment: ${{ needs.check-dispatch-gate.outputs.RELEASE_ENVIRONMENT }}
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
VERSION: ${{ steps.new-version.outputs.NEW_VERSION }}
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
name: Lucide Angular checks
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- next
|
||||
pull_request:
|
||||
paths:
|
||||
- packages/lucide-angular/**
|
||||
- tools/build-icons/**
|
||||
- pnpm-lock.yaml
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: pnpm/action-setup@v4
|
||||
- uses: actions/setup-node@v6
|
||||
with:
|
||||
cache: 'pnpm'
|
||||
node-version-file: 'package.json'
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install --frozen-lockfile
|
||||
|
||||
- name: Build
|
||||
run: pnpm --filter lucide-angular build
|
||||
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: pnpm/action-setup@v4
|
||||
- uses: actions/setup-node@v6
|
||||
with:
|
||||
cache: 'pnpm'
|
||||
node-version-file: 'package.json'
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install --frozen-lockfile
|
||||
|
||||
- name: Test
|
||||
run: pnpm --filter lucide-angular test
|
||||
@@ -1,46 +0,0 @@
|
||||
name: Lucide Svelte checks
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- next
|
||||
pull_request:
|
||||
paths:
|
||||
- packages/lucide-svelte/**
|
||||
- packages/shared/**
|
||||
- tools/build-icons/**
|
||||
- tools/rollup-plugins/**
|
||||
- pnpm-lock.yaml
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: pnpm/action-setup@v4
|
||||
- uses: actions/setup-node@v6
|
||||
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@v6
|
||||
- uses: pnpm/action-setup@v4
|
||||
- uses: actions/setup-node@v6
|
||||
with:
|
||||
cache: 'pnpm'
|
||||
node-version-file: 'package.json'
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install --frozen-lockfile
|
||||
|
||||
- name: Test
|
||||
run: pnpm --filter lucide-svelte test
|
||||
@@ -1,46 +0,0 @@
|
||||
name: Lucide Vue Next checks
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- next
|
||||
pull_request:
|
||||
paths:
|
||||
- packages/lucide-vue-next/**
|
||||
- packages/shared/**
|
||||
- tools/build-icons/**
|
||||
- tools/rollup-plugins/**
|
||||
- pnpm-lock.yaml
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: pnpm/action-setup@v4
|
||||
- uses: actions/setup-node@v6
|
||||
with:
|
||||
cache: 'pnpm'
|
||||
node-version-file: 'package.json'
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install --frozen-lockfile
|
||||
|
||||
- name: Build
|
||||
run: pnpm --filter lucide-vue-next build
|
||||
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: pnpm/action-setup@v4
|
||||
- uses: actions/setup-node@v6
|
||||
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
|
||||
@@ -39,6 +39,7 @@ packages/**/LICENSE
|
||||
categories.json
|
||||
tags.json
|
||||
.vercel
|
||||
package-lock.json
|
||||
|
||||
# docs
|
||||
docs/.vitepress/cache
|
||||
|
||||
+5
-4
@@ -7,8 +7,8 @@ docs/.vitepress/cache
|
||||
docs/.vitepress/data
|
||||
docs/.nitro
|
||||
|
||||
# lucide-angular
|
||||
packages/lucide-angular/.angular/cache
|
||||
# @lucide/angular
|
||||
packages/angular/.angular
|
||||
|
||||
# lucide-static
|
||||
packages/lucide-static/icons
|
||||
@@ -17,7 +17,8 @@ packages/lucide-static/sprite.svg
|
||||
packages/lucide-static/tags.json
|
||||
packages/lucide-static/icon-nodes.json
|
||||
packages/lucide-static/font
|
||||
packages/svelte/.svelte-kit
|
||||
|
||||
# lucide-svelte
|
||||
packages/lucide-svelte/src/icons/*.svelte
|
||||
packages/lucide-svelte/.svelte-kit
|
||||
packages/svelte/src/icons/*.svelte
|
||||
packages/svelte/.svelte-kit
|
||||
|
||||
@@ -92,7 +92,7 @@ Thank you to all the people who contributed to Lucide!
|
||||
|
||||
### Hero backers 🦸
|
||||
|
||||
<a href="https://https://zephyr-cloud.io/"><img src="docs/public/sponsors/zephyr-cloud.svg" width="180" alt="Zephyr Cloud – From idea to prod: fast micro-frontend delivery!" /></a>
|
||||
<a href="https://zephyr-cloud.io/"><img src="docs/public/sponsors/zephyr-cloud.svg" width="180" alt="Zephyr Cloud – From idea to prod: fast micro-frontend delivery!" /></a>
|
||||
|
||||
### Awesome backers 🍺
|
||||
|
||||
|
||||
@@ -54,7 +54,6 @@
|
||||
"jira": "Jira",
|
||||
"kotlin": "Kotlin",
|
||||
"kubernetes": "Kubernetes",
|
||||
"less": "Less",
|
||||
"leetcode": "LeetCode",
|
||||
"leet-code": "LeetCode",
|
||||
"line": "LINE",
|
||||
|
||||
@@ -11,7 +11,7 @@ export default eventHandler(async (event) => {
|
||||
const name = params.data.split('/').at(-3);
|
||||
const iconSizeString = params.data.split('/').at(-2);
|
||||
const svgData = params.data.split('/').at(-1);
|
||||
const iconSize = parseInt(iconSizeString, 10);
|
||||
const iconSize = Math.min(parseInt(iconSizeString, 10) || imageSize, 256);
|
||||
const data = svgData.slice(0, -4);
|
||||
|
||||
const prevSvg = iconNodes[name]
|
||||
|
||||
+12
-194
@@ -1,14 +1,14 @@
|
||||
import { fileURLToPath, URL } from 'node:url';
|
||||
import { defineConfig } from 'vitepress';
|
||||
import { defineConfig, UserConfig } from 'vitepress';
|
||||
import { groupIconMdPlugin, groupIconVitePlugin } from 'vitepress-plugin-group-icons';
|
||||
import sidebar from './sidebar';
|
||||
import snackPlayer from './markdown/snackPlayer';
|
||||
import sandpackPlugin from './markdown/sandpack';
|
||||
import { readFile } from 'node:fs/promises';
|
||||
import { resourcesSidebar } from './sidebar/resources';
|
||||
import getStructuredData from './getStructuredData';
|
||||
import { createGeneralOGImage, createIconOGImage } from './createOGImage';
|
||||
import llmstxt from 'vitepress-plugin-llms';
|
||||
import { transformPageData } from './transformPageData';
|
||||
import getHeadConfig from './getHeadConfig';
|
||||
|
||||
const defaultSandpackCSS = await readFile(
|
||||
fileURLToPath(new URL('./theme/sandpack-default.css', import.meta.url)),
|
||||
@@ -56,6 +56,12 @@ export default defineConfig({
|
||||
new URL('./theme/components/overrides/VPFooter.vue', import.meta.url),
|
||||
),
|
||||
},
|
||||
{
|
||||
find: /^.*\/VPCarbonAds\.vue$/,
|
||||
replacement: fileURLToPath(
|
||||
new URL('./theme/components/overrides/VPCarbonAds.vue', import.meta.url),
|
||||
),
|
||||
},
|
||||
{
|
||||
find: '~/.vitepress',
|
||||
replacement: fileURLToPath(new URL('./', import.meta.url)),
|
||||
@@ -73,199 +79,11 @@ export default defineConfig({
|
||||
'brand-logo-statement.md',
|
||||
'icons/**', // Not working, need investigation
|
||||
],
|
||||
}),
|
||||
}) as unknown as UserConfig['vite']['plugins'][0],
|
||||
],
|
||||
},
|
||||
head: [
|
||||
[
|
||||
'link',
|
||||
{
|
||||
rel: 'preconnect',
|
||||
href: 'https://analytics.lucide.dev',
|
||||
},
|
||||
],
|
||||
[
|
||||
'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',
|
||||
content: 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',
|
||||
content: socialTitle,
|
||||
},
|
||||
],
|
||||
[
|
||||
'meta',
|
||||
{
|
||||
property: 'twitter:description',
|
||||
content: description,
|
||||
},
|
||||
],
|
||||
[
|
||||
'meta',
|
||||
{
|
||||
property: 'twitter:image',
|
||||
content: 'https://lucide.dev/og.png',
|
||||
},
|
||||
],
|
||||
],
|
||||
async transformPageData(pageData) {
|
||||
pageData.frontmatter.head ??= [];
|
||||
if (
|
||||
pageData.relativePath.startsWith('icons/') &&
|
||||
!pageData.relativePath.startsWith('icons/lab/') &&
|
||||
pageData.params?.name
|
||||
) {
|
||||
const iconName = pageData.params.name;
|
||||
pageData.title = `${iconName} icon details`;
|
||||
|
||||
const taggedAs = pageData.params?.tags?.length
|
||||
? `Tagged as: ${pageData.params.tags.join(', ')}.`
|
||||
: '';
|
||||
const categorizedIn = pageData.params?.category?.length
|
||||
? `Categorized in: ${pageData.params.category.join(', ')}.`
|
||||
: '';
|
||||
|
||||
pageData.description =
|
||||
`Details and related icons for ${iconName} icon. ${taggedAs} ${categorizedIn}`.trim();
|
||||
|
||||
const structuredData = await getStructuredData(iconName, pageData);
|
||||
|
||||
const ogPath = await createIconOGImage(iconName, pageData.params?.tags || []);
|
||||
|
||||
if (ogPath) {
|
||||
const content = `https://lucide.dev${ogPath}`;
|
||||
pageData.frontmatter.head.push(
|
||||
[
|
||||
'meta',
|
||||
{
|
||||
property: 'og:image',
|
||||
content,
|
||||
},
|
||||
],
|
||||
[
|
||||
'meta',
|
||||
{
|
||||
property: 'twitter:image',
|
||||
content,
|
||||
},
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
pageData.frontmatter.head.push([
|
||||
'script',
|
||||
{ type: 'application/ld+json' },
|
||||
JSON.stringify(structuredData),
|
||||
]);
|
||||
}
|
||||
|
||||
if (pageData.relativePath.startsWith('guide/')) {
|
||||
const ogPath = await createGeneralOGImage(pageData);
|
||||
|
||||
if (ogPath) {
|
||||
const content = `https://lucide.dev${ogPath}`;
|
||||
pageData.frontmatter.head.push(
|
||||
[
|
||||
'meta',
|
||||
{
|
||||
property: 'og:image',
|
||||
content,
|
||||
},
|
||||
],
|
||||
[
|
||||
'meta',
|
||||
{
|
||||
property: 'twitter:image',
|
||||
content,
|
||||
},
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
head: getHeadConfig({ title, description, socialTitle }),
|
||||
transformPageData,
|
||||
themeConfig: {
|
||||
logo: {
|
||||
light: '/logo.light.svg',
|
||||
|
||||
@@ -0,0 +1,134 @@
|
||||
import { HeadConfig } from 'vitepress';
|
||||
|
||||
const getHeadConfig = ({
|
||||
title,
|
||||
description,
|
||||
socialTitle,
|
||||
}: {
|
||||
title: string;
|
||||
description: string;
|
||||
socialTitle?: string;
|
||||
}): HeadConfig[] => [
|
||||
[
|
||||
'link',
|
||||
{
|
||||
rel: 'preconnect',
|
||||
href: 'https://analytics.lucide.dev',
|
||||
},
|
||||
],
|
||||
[
|
||||
'script',
|
||||
{
|
||||
src: 'https://analytics.lucide.dev/js/script.js',
|
||||
'data-domain': 'lucide.dev',
|
||||
defer: '',
|
||||
},
|
||||
],
|
||||
[
|
||||
'script',
|
||||
{
|
||||
src: 'https://media.bitterbrains.com/main.js?from=LUCIDE&type=top',
|
||||
async: 'true',
|
||||
},
|
||||
],
|
||||
[
|
||||
'meta',
|
||||
{
|
||||
property: 'og:locale',
|
||||
content: 'en_US',
|
||||
},
|
||||
],
|
||||
[
|
||||
'meta',
|
||||
{
|
||||
property: 'og:type',
|
||||
content: 'website',
|
||||
},
|
||||
],
|
||||
[
|
||||
'meta',
|
||||
{
|
||||
property: 'og:site_name',
|
||||
content: 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',
|
||||
content: socialTitle,
|
||||
},
|
||||
],
|
||||
[
|
||||
'meta',
|
||||
{
|
||||
property: 'twitter:description',
|
||||
content: description,
|
||||
},
|
||||
],
|
||||
[
|
||||
'meta',
|
||||
{
|
||||
property: 'twitter:image',
|
||||
content: 'https://lucide.dev/og.png',
|
||||
},
|
||||
],
|
||||
];
|
||||
|
||||
export default getHeadConfig;
|
||||
@@ -0,0 +1,160 @@
|
||||
<script setup lang="ts">
|
||||
import { useLocalStorage } from '@vueuse/core';
|
||||
import IconButton from './base/IconButton.vue';
|
||||
import { x } from '../../data/iconNodes';
|
||||
import Icon from '@lucide/vue/src/Icon';
|
||||
import { computed, onMounted, ref } from 'vue';
|
||||
import VPButton from 'vitepress/dist/client/theme-default/components/VPButton.vue';
|
||||
|
||||
const showAskSurvey = useLocalStorage('show-ask-overlay', true, {
|
||||
initOnMounted: true,
|
||||
});
|
||||
|
||||
const delayedShow = ref(false)
|
||||
|
||||
const showPopup = computed(() => showAskSurvey.value && delayedShow.value );
|
||||
let isInitialized = false
|
||||
|
||||
function startTally() {
|
||||
window.Tally.openPopup('EkvOpB', {
|
||||
layout: 'modal',
|
||||
width: 700,
|
||||
autoClose: 5000,
|
||||
onClose() {
|
||||
showAskSurvey.value = false;
|
||||
},
|
||||
onSubmit() {
|
||||
showAskSurvey.value = false;
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
setTimeout(() => {
|
||||
delayedShow.value = true
|
||||
}, 10000)
|
||||
})
|
||||
|
||||
function initTally() {
|
||||
try {
|
||||
if (!isInitialized) {
|
||||
isInitialized = true
|
||||
const s = document.createElement('script')
|
||||
s.src = `//tally.so/widgets/embed.js`
|
||||
s.async = true
|
||||
s.onload = startTally
|
||||
document.body.appendChild(s)
|
||||
} else {
|
||||
startTally();
|
||||
}
|
||||
} catch (error) {
|
||||
window.open('https://tally.so/r/EkvOpB', '_blank');
|
||||
}
|
||||
}
|
||||
|
||||
function hidePopup() {
|
||||
showAskSurvey.value = false;
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Teleport to="body">
|
||||
<div
|
||||
:class="{
|
||||
'show-popup': showPopup,
|
||||
}"
|
||||
class="ask-overlay"
|
||||
>
|
||||
<IconButton
|
||||
@click="hidePopup"
|
||||
class="hide-button"
|
||||
>
|
||||
<Icon
|
||||
:iconNode="x"
|
||||
:size="20"
|
||||
absoluteStrokeWidth
|
||||
/>
|
||||
</IconButton>
|
||||
|
||||
<h2 class="title">
|
||||
We value your feedback!
|
||||
</h2>
|
||||
|
||||
<p class="description">
|
||||
Can you spare a moment to take our survey? <br>Your feedback helps us improve Lucide and make it better for everyone.
|
||||
</p>
|
||||
|
||||
<div class="buttons">
|
||||
<VPButton
|
||||
text="Take the Survey"
|
||||
theme="brand"
|
||||
@click="initTally"
|
||||
/>
|
||||
|
||||
<VPButton
|
||||
text="Close"
|
||||
theme="alt"
|
||||
@click="hidePopup"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</Teleport>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.ask-overlay {
|
||||
position: fixed;
|
||||
z-index: 99;;
|
||||
bottom: 24px;
|
||||
width: calc(100% - 48px);
|
||||
max-width: 420px;
|
||||
left: 24px;
|
||||
transition:
|
||||
opacity 0.25s,
|
||||
transform 0.5s cubic-bezier(0.19, 1, 0.22, 1);
|
||||
padding: 20px;
|
||||
border-radius: 12px;
|
||||
box-shadow: var(--vp-shadow-4);
|
||||
background-color: var(--vp-carbon-ads-bg-color);
|
||||
opacity: 0;
|
||||
transform: translateY(200px);
|
||||
}
|
||||
|
||||
.ask-overlay .title {
|
||||
line-height: 24px;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.ask-overlay .description {
|
||||
padding-top: 8px;
|
||||
line-height: 24px;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
color: var(--vp-c-text-2);
|
||||
}
|
||||
|
||||
.ask-overlay.show-popup {
|
||||
transform: translateY(0);
|
||||
opacity: 1;
|
||||
pointer-events: auto;
|
||||
transition:
|
||||
opacity 0.5s,
|
||||
transform 0.25s ease;
|
||||
}
|
||||
|
||||
.ask-overlay .buttons {
|
||||
margin-top: 16px;
|
||||
display: flex;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.hide-button {
|
||||
padding: 4px;
|
||||
position: absolute;
|
||||
top: 8px;
|
||||
right: 8px;
|
||||
z-index: 3;
|
||||
background-color: transparent;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,90 @@
|
||||
<script setup lang="ts">
|
||||
import { useRouter } from 'vitepress';
|
||||
import { computed } from 'vue';
|
||||
|
||||
const router = useRouter();
|
||||
|
||||
const frameworks = [
|
||||
{
|
||||
ariaLabel: 'Get JavaScript certificates from certificates.dev',
|
||||
image: '/certificates-dev/js-certificates-dev.jpg',
|
||||
href: 'https://certificates.dev/javascript?friend=LUCIDE',
|
||||
routes: [
|
||||
'/guide/lucide/',
|
||||
'/guide/svelte/',
|
||||
'/guide/solid/',
|
||||
'/guide/astro/',
|
||||
'/guide/static/'
|
||||
],
|
||||
},
|
||||
{
|
||||
ariaLabel: 'Get React certificates from certificates.dev',
|
||||
image: '/certificates-dev/react-certificates-dev.jpg',
|
||||
href: 'https://certificates.dev/react?friend=LUCIDE',
|
||||
routes: [
|
||||
'/guide/react/',
|
||||
'/guide/react-native/',
|
||||
'/guide/preact/',
|
||||
],
|
||||
},
|
||||
{
|
||||
ariaLabel: 'Get Vue certificates from certificates.dev',
|
||||
href: 'https://certificates.dev/vuejs?friend=LUCIDE',
|
||||
image: '/certificates-dev/vue-certificates-dev.jpg',
|
||||
routes: [
|
||||
'/guide/vue/',
|
||||
],
|
||||
},
|
||||
{
|
||||
ariaLabel: 'Get Angular certificates from certificates.dev',
|
||||
href: 'https://certificates.dev/angular?friend=LUCIDE',
|
||||
image: '/certificates-dev/angular-certificates-dev.jpg',
|
||||
routes: [
|
||||
'/guide/angular/',
|
||||
],
|
||||
}
|
||||
];
|
||||
|
||||
const selected = computed(() => {
|
||||
const current = frameworks.find(({ routes }) => {
|
||||
return routes.some(route => router.route.path.startsWith(route));
|
||||
});
|
||||
|
||||
return current || frameworks[0];
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<a class="certificates-link" :href="selected.href" :aria-label="selected.ariaLabel" target="_blank" rel="noopener noreferrer">
|
||||
<img :src="selected.image" :alt="selected.ariaLabel" />
|
||||
</a>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.certificates-link {
|
||||
/* padding: 20px; */
|
||||
border-radius: 12px;
|
||||
min-height: 100px;
|
||||
text-align: center;
|
||||
line-height: 18px;
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
background-color: var(--vp-carbon-ads-bg-color);
|
||||
margin-bottom: 20px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.certificates-link img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
max-width: 100%;
|
||||
border-radius: 6px;
|
||||
transition: transform 0.3s ease, opacity 0.3s ease;
|
||||
}
|
||||
|
||||
.certificates-link:hover img {
|
||||
transform: scale(1.05);
|
||||
opacity: 0.9;
|
||||
|
||||
}
|
||||
</style>
|
||||
@@ -50,7 +50,7 @@ onMounted(() => {
|
||||
absoluteStrokeWidth
|
||||
/>
|
||||
</IconButton>
|
||||
<VPDocAsideCarbonAds :carbon-ads="theme.carbonAds" />
|
||||
<VPDocAsideCarbonAds :carbon-ads="theme.carbonAds" overlay />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -9,9 +9,7 @@
|
||||
margin-bottom: 16px;
|
||||
position: sticky;
|
||||
z-index: 10;
|
||||
top: 48px;
|
||||
padding-top: 24px;
|
||||
margin-top: -32px;
|
||||
top: var(--vp-layout-top-height);
|
||||
width: 100%;
|
||||
display: flex;
|
||||
margin-bottom: 32px;
|
||||
@@ -22,7 +20,8 @@
|
||||
@media (min-width: 960px) {
|
||||
.search-bar {
|
||||
padding-top: 32px;
|
||||
top: 64px;
|
||||
margin-top: calc((var(--vp-layout-top-height, 0px) + 32px) * -1);
|
||||
top: calc(var(--vp-layout-top-height, 0px) + 64px);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -0,0 +1,133 @@
|
||||
<script setup lang="ts">
|
||||
import type { DefaultTheme } from 'vitepress/theme'
|
||||
import { ref, watch, onMounted } from 'vue'
|
||||
import { useAside } from 'vitepress/dist/client/theme-default/composables/aside.js'
|
||||
import { useData } from 'vitepress/dist/client/theme-default/composables/data.js'
|
||||
|
||||
const { page } = useData()
|
||||
const props = defineProps<{
|
||||
carbonAds: DefaultTheme.CarbonAdsOptions
|
||||
overlay?: boolean
|
||||
}>()
|
||||
|
||||
const carbonOptions = props.carbonAds
|
||||
|
||||
const { isAsideEnabled } = useAside()
|
||||
const container = ref()
|
||||
|
||||
let isInitialized = false
|
||||
|
||||
function init() {
|
||||
if (!isInitialized) {
|
||||
isInitialized = true
|
||||
const params = new URLSearchParams({
|
||||
serve: carbonOptions.code,
|
||||
placement: carbonOptions.placement,
|
||||
format: 'responsive',
|
||||
})
|
||||
const s = document.createElement('script')
|
||||
s.id = '_carbonads_js'
|
||||
s.src = `//cdn.carbonads.com/carbon.js?${params.toString()}`
|
||||
s.async = true
|
||||
container.value.appendChild(s)
|
||||
}
|
||||
}
|
||||
|
||||
watch(() => page.value.relativePath, () => {
|
||||
if (isInitialized && isAsideEnabled.value) {
|
||||
;(window as any)._carbonads?.refresh()
|
||||
}
|
||||
})
|
||||
|
||||
// no need to account for option changes during dev, we can just
|
||||
// refresh the page
|
||||
if (carbonOptions) {
|
||||
onMounted(() => {
|
||||
// if the page is loaded when aside is active, load carbon directly.
|
||||
// otherwise, only load it if the page resizes to wide enough. this avoids
|
||||
// loading carbon at all on mobile where it's never shown
|
||||
if (isAsideEnabled.value || props.overlay) {
|
||||
init()
|
||||
} else {
|
||||
watch(isAsideEnabled, (wide) => wide && init())
|
||||
}
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="VPCarbonAds" ref="container" />
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.VPCarbonAds {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding: 20px;
|
||||
border-radius: 12px;
|
||||
min-height: 256px;
|
||||
text-align: center;
|
||||
line-height: 18px;
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
background-color: var(--vp-carbon-ads-bg-color);
|
||||
}
|
||||
|
||||
.VPCarbonAds :deep(img) {
|
||||
margin: 0 auto;
|
||||
border-radius: 6px;
|
||||
}
|
||||
|
||||
.VPCarbonAds :deep(.carbon-text) {
|
||||
display: block;
|
||||
margin: 0 auto;
|
||||
padding-top: 12px;
|
||||
color: var(--vp-carbon-ads-text-color);
|
||||
transition: color 0.25s;
|
||||
}
|
||||
|
||||
.VPCarbonAds :deep(.carbon-text:hover) {
|
||||
color: var(--vp-carbon-ads-hover-text-color);
|
||||
}
|
||||
.VPCarbonAds :deep(#carbon-responsive .carbon-poweredby),
|
||||
.VPCarbonAds :deep(.carbon-poweredby) {
|
||||
display: block;
|
||||
padding-bottom: 2px;
|
||||
font-size: 11px;
|
||||
font-weight: 500;
|
||||
color: var(--vp-carbon-ads-poweredby-color);
|
||||
text-transform: uppercase;
|
||||
transition: color 0.25s;
|
||||
}
|
||||
.VPCarbonAds :deep(#carbon-responsive) {
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.VPCarbonAds :deep(#carbon-responsive .carbon-poweredby) {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.VPCarbonAds :deep(#carbon-responsive .carbon-poweredby:hover),
|
||||
.VPCarbonAds :deep(.carbon-poweredby:hover) {
|
||||
color: var(--vp-carbon-ads-hover-poweredby-color);
|
||||
}
|
||||
|
||||
.VPCarbonAds :deep(> div) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.VPCarbonAds :deep(> div:first-of-type) {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.VPCarbonAds :deep(#carbon-responsive) {
|
||||
flex-direction: column-reverse;
|
||||
}
|
||||
|
||||
.VPCarbonAds :deep(#carbon-responsive .carbon-responsive-wrap) {
|
||||
border-radius: 10px;
|
||||
}
|
||||
</style>
|
||||
@@ -3,6 +3,7 @@ import { useData } from 'vitepress';
|
||||
import { useSidebar } from 'vitepress/dist/client/theme-default/composables/sidebar';
|
||||
import VPLink from 'vitepress/dist/client/theme-default/components/VPLink.vue';
|
||||
import { computed } from 'vue';
|
||||
import SurveyAskOverlay from '../SurveyAskOverlay.vue';
|
||||
|
||||
const { theme } = useData();
|
||||
const { hasSidebar } = useSidebar();
|
||||
|
||||
@@ -7,12 +7,12 @@ import IconsSidebarNavAfter from './layouts/IconsSidebarNavAfter.vue';
|
||||
import HomeHeroIconsCard from './components/home/HomeHeroIconsCard.vue';
|
||||
import HomeHeroAfter from './components/home/HomeHeroAfter.vue';
|
||||
import HomeHeroInfoBefore from './components/home/HomeHeroInfoBefore.vue';
|
||||
import LayoutTop from './components/base/LayoutTop.vue';
|
||||
import { ICON_STYLE_CONTEXT, iconStyleContext } from './composables/useIconStyle';
|
||||
import { CATEGORY_VIEW_CONTEXT, categoryViewContext } from './composables/useCategoryView';
|
||||
import { EXTERNAL_LIBS_CONTEXT, externalLibContext } from './composables/useExternalLibs';
|
||||
import FrameworkSelect from './components/guide/FrameworkSelect.vue';
|
||||
import SnackPlayer from './components/editors/SnackPlayer.vue';
|
||||
import CertificatesLink from './components/guide/CertificatesLink.vue';
|
||||
|
||||
const theme: Partial<Theme> = {
|
||||
extends: DefaultTheme,
|
||||
@@ -23,7 +23,9 @@ const theme: Partial<Theme> = {
|
||||
'sidebar-nav-after': () => h(IconsSidebarNavAfter),
|
||||
'home-hero-image': () => h(HomeHeroIconsCard),
|
||||
'home-hero-actions-after': () => h(HomeHeroAfter),
|
||||
'layout-top': () => h(LayoutTop),
|
||||
'aside-ads-before': () => h(CertificatesLink),
|
||||
// Keep this here for now, we might want to add more things to the top bar in the future
|
||||
// 'layout-top': () => h(LayoutTop),
|
||||
});
|
||||
},
|
||||
enhanceApp({ app }) {
|
||||
|
||||
@@ -144,6 +144,14 @@
|
||||
.VPHomeHero .container {
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
html.has-bb-banner {
|
||||
--vp-layout-top-height: 72px;
|
||||
}
|
||||
|
||||
html.has-bb-banner {
|
||||
--Dark-Background: #161618;
|
||||
}
|
||||
}
|
||||
|
||||
.VPNavBarHamburger .container > span {
|
||||
@@ -154,3 +162,9 @@
|
||||
margin: 0 auto 48px;
|
||||
max-width: 480px;
|
||||
}
|
||||
|
||||
html:not(.has-bb-banner) #bb-banner {
|
||||
display: none !important;
|
||||
visibility: hidden !important;
|
||||
pointer-events: none !important;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
import { PageData } from 'vitepress';
|
||||
import getStructuredData from './getStructuredData';
|
||||
import { createGeneralOGImage, createIconOGImage } from './createOGImage';
|
||||
|
||||
export async function transformPageData(pageData: PageData) {
|
||||
pageData.frontmatter.head ??= [];
|
||||
if (
|
||||
pageData.relativePath.startsWith('icons/') &&
|
||||
!pageData.relativePath.startsWith('icons/lab/') &&
|
||||
pageData.params?.name
|
||||
) {
|
||||
const iconName = pageData.params.name;
|
||||
pageData.title = `${iconName} icon details`;
|
||||
|
||||
const taggedAs = pageData.params?.tags?.length
|
||||
? `Tagged as: ${pageData.params.tags.join(', ')}.`
|
||||
: '';
|
||||
const categorizedIn = pageData.params?.category?.length
|
||||
? `Categorized in: ${pageData.params.category.join(', ')}.`
|
||||
: '';
|
||||
|
||||
pageData.description =
|
||||
`Details and related icons for ${iconName} icon. ${taggedAs} ${categorizedIn}`.trim();
|
||||
|
||||
const structuredData = await getStructuredData(iconName, pageData);
|
||||
|
||||
const ogPath = await createIconOGImage(iconName, pageData.params?.tags || []);
|
||||
|
||||
if (ogPath) {
|
||||
const content = `https://lucide.dev${ogPath}`;
|
||||
pageData.frontmatter.head.push(
|
||||
[
|
||||
'meta',
|
||||
{
|
||||
property: 'og:image',
|
||||
content,
|
||||
},
|
||||
],
|
||||
[
|
||||
'meta',
|
||||
{
|
||||
property: 'twitter:image',
|
||||
content,
|
||||
},
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
pageData.frontmatter.head.push([
|
||||
'script',
|
||||
{ type: 'application/ld+json' },
|
||||
JSON.stringify(structuredData),
|
||||
]);
|
||||
}
|
||||
|
||||
if (pageData.relativePath.startsWith('guide/')) {
|
||||
const ogPath = await createGeneralOGImage(pageData);
|
||||
|
||||
if (ogPath) {
|
||||
const content = `https://lucide.dev${ogPath}`;
|
||||
pageData.frontmatter.head.push(
|
||||
[
|
||||
'meta',
|
||||
{
|
||||
property: 'og:image',
|
||||
content,
|
||||
},
|
||||
],
|
||||
[
|
||||
'meta',
|
||||
{
|
||||
property: 'twitter:image',
|
||||
content,
|
||||
},
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
Vendored
+38
@@ -46,5 +46,43 @@ declare global {
|
||||
*/
|
||||
append(container: Element): void;
|
||||
};
|
||||
Tally: {
|
||||
// From https://tally.so/help/developer-resources#2f676e40530a460ea6a634b8441f6001
|
||||
openPopup: (
|
||||
formId: string,
|
||||
options?: {
|
||||
key?: string; // This is used as a unique identifier used for the "Show only once" and "Don't show after submit" functionality
|
||||
layout?: 'default' | 'modal';
|
||||
width?: number;
|
||||
alignLeft?: boolean;
|
||||
hideTitle?: boolean;
|
||||
overlay?: boolean;
|
||||
emoji?: {
|
||||
text: string;
|
||||
animation:
|
||||
| 'none'
|
||||
| 'wave'
|
||||
| 'tada'
|
||||
| 'heart-beat'
|
||||
| 'spin'
|
||||
| 'flash'
|
||||
| 'bounce'
|
||||
| 'rubber-band'
|
||||
| 'head-shake';
|
||||
};
|
||||
autoClose?: number; // in milliseconds
|
||||
showOnce?: boolean;
|
||||
doNotShowAfterSubmit?: boolean;
|
||||
customFormUrl?: string; // when you want to load the form via it's custom domain URL
|
||||
hiddenFields?: {
|
||||
[key: string]: any;
|
||||
};
|
||||
onOpen?: () => void;
|
||||
onClose?: () => void;
|
||||
onPageView?: (page: number) => void;
|
||||
onSubmit?: (payload: SubmissionPayload) => void;
|
||||
},
|
||||
) => void;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -30,7 +30,7 @@ However, not everyone can understand them easily. Read more about [how to use Lu
|
||||
|
||||
## Official Packages
|
||||
|
||||
Lucide's official packages are designed to work on different platforms, making it easier for users to integrate icons into their projects. The packages are available for various technologies, including [Web (Vanilla)](https://lucide.dev/guide/packages/lucide), [React](https://lucide.dev/guide/packages/lucide-react), [React Native](https://lucide.dev/guide/packages/lucide-react-native), [Vue](https://lucide.dev/guide/packages/lucide-vue), [Vue 3](https://lucide.dev/guide/packages/lucide-vue-next), [Svelte](https://lucide.dev/guide/packages/lucide-svelte), [Preact](https://lucide.dev/guide/packages/lucide-preact), [Solid](https://lucide.dev/guide/packages/lucide-solid), [Angular](https://lucide.dev/guide/packages/angular), [Astro](https://lucide.dev/guide/packages/lucide-astro), and [NodeJS](https://lucide.dev/guide/packages/lucide-static#nodejs).
|
||||
Lucide's official packages are designed to work on different platforms, making it easier for users to integrate icons into their projects. The packages are available for various technologies, including [Web (Vanilla)](./lucide/index.md), [React](./react/index.md), [React Native](./react-native/index.md), [Vue](./vue/index.md), [Svelte](./svelte/index.md), [Preact](./preact/index.md), [Solid](./solid/index.md), [Angular](./angular/index.md), [Astro](./astro/index.md), and [Static](./static/index.md).
|
||||
|
||||
## Community
|
||||
|
||||
|
||||
@@ -3,12 +3,13 @@
|
||||
::: warning
|
||||
This documentation is for `@lucide/angular`.
|
||||
|
||||
To learn about our legacy package for Angular, please refer to [`lucide-angular`](./lucide-angular).
|
||||
To learn about our legacy package for Angular, please refer to [`lucide-angular`](https://v0.lucide.dev/guide/packages/lucide-angular).
|
||||
:::
|
||||
|
||||
A standalone, signal-based, zoneless implementation of Lucide icons for Angular.
|
||||
|
||||
**What you can accomplish:**
|
||||
|
||||
- Use icons as standalone Angular components with full dependency injection support
|
||||
- Configure icons globally through modern Angular providers
|
||||
- Integrate with Angular's reactive forms and data binding
|
||||
@@ -118,6 +119,7 @@ Alternatively, the component also accepts string inputs.
|
||||
To use icons this way, first, you have to provide icons via `provideLucideIcons`:
|
||||
|
||||
:::code-group
|
||||
|
||||
```ts{7-10} [app.config.ts]
|
||||
import { ApplicationConfig } from '@angular/core';
|
||||
import { provideLucideIcons, LucideCircleCheck, LucideCircleX } from '@lucide/angular';
|
||||
@@ -148,6 +150,7 @@ import { LucideIcon } from '@lucide/angular';
|
||||
})
|
||||
export class Foobar { }
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
::: tip
|
||||
@@ -259,19 +262,25 @@ export class Foobar {
|
||||
## Troubleshooting
|
||||
|
||||
### The icon is not being displayed
|
||||
|
||||
If using per-icon-components:
|
||||
|
||||
1. Ensure that the icon component is being imported, if using per-icon-components
|
||||
2. Check that the icon name matches exactly (case-sensitive)
|
||||
|
||||
If using the dynamic component:
|
||||
|
||||
1. Ensure the icon is provided via `provideLucideIcons()` if using string names
|
||||
2. Verify the icon is imported from `@lucide/angular` and not the legacy package
|
||||
|
||||
### TypeScript errors?
|
||||
|
||||
Make sure you're importing from `@lucide/angular` and not `lucide-angular`.
|
||||
|
||||
### Icons render with wrong defaults
|
||||
|
||||
Ensure `provideLucideConfig()` is used at the right level.
|
||||
|
||||
## Migration guide
|
||||
|
||||
Migrating from `lucide-angular`? Read our [comprehensive migration guide](https://github.com/lucide-icons/lucide/blob/main/packages/angular/MIGRATION.md).
|
||||
|
||||
@@ -1,187 +0,0 @@
|
||||
# Lucide Angular
|
||||
|
||||
::: warning
|
||||
This documentation is for our legacy package for Angular.
|
||||
|
||||
For our modern, standalone-first implementation, please refer to [`@lucide/angular`](./angular).
|
||||
:::
|
||||
|
||||
Angular components and services for Lucide icons that integrate with Angular's dependency injection and component system. Provides both traditional module-based and modern standalone component approaches for maximum flexibility in Angular applications.
|
||||
|
||||
**What you can accomplish:**
|
||||
- Use icons as Angular components with full dependency injection support
|
||||
- Configure icons globally through Angular services and providers
|
||||
- Choose from multiple component selectors (lucide-angular, lucide-icon, i-lucide, span-lucide)
|
||||
- Integrate with Angular's reactive forms and data binding
|
||||
- Build scalable applications with tree-shaken icon bundles and lazy loading support
|
||||
|
||||
## Installation
|
||||
|
||||
::: code-group
|
||||
|
||||
```sh [pnpm]
|
||||
pnpm add lucide-angular
|
||||
```
|
||||
|
||||
```sh [yarn]
|
||||
yarn add lucide-angular
|
||||
```
|
||||
|
||||
```sh [npm]
|
||||
npm install lucide-angular
|
||||
```
|
||||
|
||||
```sh [bun]
|
||||
bun add lucide-angular
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
## How to use
|
||||
|
||||
### Step 1: Import `LucideAngularModule`
|
||||
|
||||
In any Angular module you wish to use Lucide icons in, you have to import `LucideAngularModule`, and pick any icons you wish to use:
|
||||
|
||||
```js
|
||||
import { LucideAngularModule, File, House, Menu, UserCheck } from 'lucide-angular';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
LucideAngularModule.pick({File, House, Menu, UserCheck})
|
||||
]
|
||||
})
|
||||
export class AppModule { }
|
||||
```
|
||||
|
||||
or using standalone version:
|
||||
|
||||
```js
|
||||
import { Component } from '@angular/core';
|
||||
import { LucideAngularModule, FileIcon } from 'lucide-angular';
|
||||
|
||||
@Component({
|
||||
standalone: true,
|
||||
selector: 'app-root',
|
||||
templateUrl: './app.component.html',
|
||||
styleUrl: './app.component.scss',
|
||||
imports: [LucideAngularModule]
|
||||
})
|
||||
export class AppComponent {
|
||||
readonly FileIcon = FileIcon;
|
||||
}
|
||||
```
|
||||
### Step 2: Use the icons in templates
|
||||
|
||||
Within your templates you may now use one of the following component tags to insert an icon:
|
||||
|
||||
```html
|
||||
<lucide-angular name="file" class="my-icon"></lucide-angular>
|
||||
<lucide-icon name="house" class="my-icon"></lucide-icon>
|
||||
<i-lucide name="menu" class="my-icon"></i-lucide>
|
||||
<span-lucide name="user-check" class="my-icon"></span-lucide>
|
||||
```
|
||||
for standalone
|
||||
```html
|
||||
<lucide-angular [img]="FileIcon" class="my-icon"></lucide-angular>
|
||||
<lucide-icon [img]="FileIcon" class="my-icon"></lucide-icon>
|
||||
<i-lucide [img]="FileIcon" class="my-icon"></i-lucide>
|
||||
<span-lucide [img]="FileIcon" class="my-icon"></span-lucide>
|
||||
```
|
||||
|
||||
### Props
|
||||
|
||||
You can pass additional props to adjust the icon appearance.
|
||||
|
||||
| name | type | default |
|
||||
| --------------------- | --------- | ------------ |
|
||||
| `size` | *number* | 24 |
|
||||
| `color` | *string* | currentColor |
|
||||
| `strokeWidth` | *number* | 2 |
|
||||
| `absoluteStrokeWidth` | *boolean* | false |
|
||||
|
||||
```html
|
||||
<i-lucide name="house" [size]="48" color="red" [strokeWidth]="1"></i-lucide>
|
||||
```
|
||||
|
||||
### Global configuration
|
||||
|
||||
You can inject the `LucideIconConfig` service in your root component to globally configure the default property values as defined above.
|
||||
|
||||
### Styling using a custom CSS class
|
||||
|
||||
Any extra HTML attribute is ignored, but the `class` attribute
|
||||
is passed onto the internal SVG image element and it can be used to style it:
|
||||
|
||||
```css
|
||||
svg.my-icon {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
stroke-width: 3;
|
||||
}
|
||||
```
|
||||
|
||||
## Injecting multiple icon providers
|
||||
|
||||
You may provide additional icons using the `LUCIDE_ICONS` injection token,
|
||||
which accepts multiple providers of the interface `LucideIconsProviderInterface`
|
||||
with the utility class `LucideIconsProvider` available for easier usage:
|
||||
|
||||
```js
|
||||
import { LUCIDE_ICONS, LucideIconProvider } from 'lucide-angular';
|
||||
import { MyIcon } from './icons/my-icon';
|
||||
|
||||
const myIcons = {MyIcon};
|
||||
|
||||
@NgModule({
|
||||
providers: [
|
||||
{provide: LUCIDE_ICONS, multi: true, useValue: new LucideIconProvider(myIcons)},
|
||||
]
|
||||
})
|
||||
export class AppModule { }
|
||||
```
|
||||
|
||||
To add custom icons, you will first need to convert them to an [svgson format](https://github.com/elrumordelaluz/svgson).
|
||||
|
||||
## Loading all icons
|
||||
|
||||
::: danger
|
||||
You may also opt to import all icons if necessary using the following format but be aware that this will significantly increase your application build size.
|
||||
:::
|
||||
|
||||
```js
|
||||
import { icons } from 'lucide-angular';
|
||||
|
||||
...
|
||||
|
||||
LucideAngularModule.pick(icons)
|
||||
```
|
||||
|
||||
## With Lucide Lab or custom icons
|
||||
|
||||
[Lucide Lab](https://github.com/lucide-icons/lucide-lab) is a collection of icons that are not part of the Lucide main library.
|
||||
They can be used in the same way as the official icons.
|
||||
|
||||
```js
|
||||
import { LucideAngularModule } from 'lucide-angular';
|
||||
import { coconut } from '@lucide/lab';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
LucideAngularModule.pick({ coconut })
|
||||
]
|
||||
})
|
||||
export class AppModule { }
|
||||
```
|
||||
|
||||
## Accessibility
|
||||
|
||||
By default, we hide icons from screen readers using `aria-hidden="true"`.
|
||||
|
||||
You can add accessibility attributes using aria-labels.
|
||||
|
||||
```html
|
||||
<lucide-icon name="check" aria-label="Task completed"></lucide-icon>
|
||||
```
|
||||
|
||||
For best practices on accessibility, please see our [accessibility guide](../accessibility.md).
|
||||
@@ -3,6 +3,7 @@
|
||||
Vue 2 components for Lucide icons that integrate with Vue's Options API and template system. Each icon is a Vue component that renders as an inline SVG, providing familiar Vue development patterns for legacy applications still using Vue 2.
|
||||
|
||||
**What you can accomplish:**
|
||||
|
||||
- Use icons as Vue 2 components with Options API integration
|
||||
- Maintain legacy Vue 2 applications with modern icon components
|
||||
- Integrate with Vue 2's template system and component lifecycle
|
||||
@@ -155,7 +156,7 @@ You can add accessibility attributes using aria-labels.
|
||||
|
||||
```vue
|
||||
<script setup>
|
||||
import { Check } from 'lucide-vue-next';
|
||||
import { Check } from '@lucide/vue';
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
||||
@@ -15,24 +15,22 @@ Make sure you have a Svelte environment set up. If you don't have one yet, you c
|
||||
|
||||
## Installation
|
||||
|
||||
<!-- TODO: v1 Remove After full release -->
|
||||
|
||||
::: code-group
|
||||
|
||||
```sh [pnpm]
|
||||
pnpm install @lucide/svelte@next
|
||||
pnpm install @lucide/svelte
|
||||
```
|
||||
|
||||
```sh [yarn]
|
||||
yarn add @lucide/svelte@next
|
||||
yarn add @lucide/svelte
|
||||
```
|
||||
|
||||
```sh [npm]
|
||||
npm install @lucide/svelte@next
|
||||
npm install @lucide/svelte
|
||||
```
|
||||
|
||||
```sh [bun]
|
||||
bun add @lucide/svelte@next
|
||||
bun add @lucide/svelte
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
+2
-2
@@ -32,7 +32,7 @@
|
||||
"@rollup/plugin-replace": "^6.0.3",
|
||||
"@types/semver": "^7.7.1",
|
||||
"h3": "^1.15.9",
|
||||
"nitropack": "^2.12.4",
|
||||
"nitropack": "^2.13.4",
|
||||
"rollup-plugin-copy": "^3.5.0",
|
||||
"svg-path-commander": "^2.1.11",
|
||||
"vitepress": "^1.6.4",
|
||||
@@ -43,7 +43,7 @@
|
||||
"semver": "^7.7.3",
|
||||
"sharp": "^0.34.5",
|
||||
"shiki": "^3.15.0",
|
||||
"simple-git": "^3.32.3",
|
||||
"simple-git": "^3.36.0",
|
||||
"sitemap": "^7.1.2",
|
||||
"svg-pathdata": "^6.0.3",
|
||||
"svgson": "^5.3.1"
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 86 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 83 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 88 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 79 KiB |
+9
-1
@@ -13,7 +13,7 @@
|
||||
"title": "Lucide Icons icon schema",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["$schema", "categories", "tags"],
|
||||
"required": ["$schema", "contributors", "categories", "tags", "use-cases"],
|
||||
"properties": {
|
||||
"$schema": {
|
||||
"type": "string"
|
||||
@@ -114,6 +114,14 @@
|
||||
"minItems": 1,
|
||||
"uniqueItems": true
|
||||
},
|
||||
"use-cases": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"minItems": 0,
|
||||
"uniqueItems": true
|
||||
},
|
||||
"deprecated": {
|
||||
"const": true
|
||||
},
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
"danielbayley",
|
||||
"ericfennis"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"letter",
|
||||
"font size",
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
"danielbayley",
|
||||
"ericfennis"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"letter",
|
||||
"font size",
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
{
|
||||
"$schema": "../icon.schema.json",
|
||||
"use-cases": [
|
||||
"indicating a large and small text size",
|
||||
"formatting text size",
|
||||
"indicating a heading and body text"
|
||||
],
|
||||
"contributors": [
|
||||
"it-is-not",
|
||||
"jguddas",
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
"karsa-mistmere",
|
||||
"jguddas"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"disability",
|
||||
"disabled",
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
"colebemis",
|
||||
"jguddas"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"pulse",
|
||||
"action",
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
"karsa-mistmere",
|
||||
"jguddas"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"air conditioner",
|
||||
"ac",
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
"csandman",
|
||||
"ericfennis"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"stream",
|
||||
"cast",
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
"jguddas",
|
||||
"karsa-mistmere"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"done",
|
||||
"todo",
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
"jguddas",
|
||||
"karsa-mistmere"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"remove"
|
||||
],
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
"karsa-mistmere",
|
||||
"jguddas"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"morning",
|
||||
"turn-off"
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
"jguddas",
|
||||
"karsa-mistmere"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"add"
|
||||
],
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
"jguddas",
|
||||
"karsa-mistmere"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"morning"
|
||||
],
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
"karsa-mistmere",
|
||||
"jguddas"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"fire",
|
||||
"alert",
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
"csandman",
|
||||
"mittalyashu"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"photo",
|
||||
"book"
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
"contributors": [
|
||||
"ericfennis"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"items",
|
||||
"flex",
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
"contributors": [
|
||||
"ericfennis"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"items",
|
||||
"flex",
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
"contributors": [
|
||||
"ericfennis"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"items",
|
||||
"bottom",
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
"contributors": [
|
||||
"ericfennis"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"items",
|
||||
"right",
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
"r4lv",
|
||||
"ericfennis"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"items",
|
||||
"flex",
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
"r4lv",
|
||||
"ericfennis"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"right",
|
||||
"items",
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
"r4lv",
|
||||
"ericfennis"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"left",
|
||||
"items",
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
"contributors": [
|
||||
"ericfennis"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"center",
|
||||
"items",
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
"contributors": [
|
||||
"ericfennis"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"right",
|
||||
"items",
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
"contributors": [
|
||||
"ericfennis"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"left",
|
||||
"items",
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
"contributors": [
|
||||
"ericfennis"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"center",
|
||||
"items",
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
"contributors": [
|
||||
"ericfennis"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"around",
|
||||
"items",
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
"contributors": [
|
||||
"ericfennis"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"top",
|
||||
"items",
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
"contributors": [
|
||||
"ericfennis"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"left",
|
||||
"items",
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
"ericfennis",
|
||||
"jguddas"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"items",
|
||||
"flex",
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
"contributors": [
|
||||
"ericfennis"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"bottom",
|
||||
"items",
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
"contributors": [
|
||||
"ericfennis"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"top",
|
||||
"items",
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
"contributors": [
|
||||
"ericfennis"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"center",
|
||||
"items",
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
"contributors": [
|
||||
"ericfennis"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"bottom",
|
||||
"items",
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
"contributors": [
|
||||
"ericfennis"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"top",
|
||||
"items",
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
"contributors": [
|
||||
"ericfennis"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"center",
|
||||
"items",
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
"contributors": [
|
||||
"ericfennis"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"center",
|
||||
"items",
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
"karsa-mistmere",
|
||||
"danielbayley"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"ambulance",
|
||||
"emergency",
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
"karsa-mistmere",
|
||||
"jguddas"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"and",
|
||||
"typography",
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
"danielbayley",
|
||||
"karsa-mistmere"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"and",
|
||||
"operator",
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
"contributors": [
|
||||
"karsa-mistmere"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"pottery",
|
||||
"artifact",
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
"ericfennis",
|
||||
"karsa-mistmere"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"ship"
|
||||
],
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
"karsa-mistmere",
|
||||
"ericfennis"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"emoji",
|
||||
"anger",
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
"contributors": [
|
||||
"karsa-mistmere"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"emoji",
|
||||
"nuisance",
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
"contributors": [
|
||||
"danielbayley"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"signal",
|
||||
"connection",
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
"karsa-mistmere",
|
||||
"danielbayley"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"metal",
|
||||
"iron",
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
"colebemis",
|
||||
"ericfennis"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"camera",
|
||||
"photo",
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
"contributors": [
|
||||
"danielbayley"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"application",
|
||||
"menu bar",
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
"danielbayley",
|
||||
"karsa-mistmere"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"application",
|
||||
"menu bar",
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
"contributors": [
|
||||
"karsa-mistmere"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"fruit",
|
||||
"food",
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
"ericfennis",
|
||||
"danielbayley"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"unarchive",
|
||||
"index",
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
"contributors": [
|
||||
"danielbayley"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"index",
|
||||
"backup",
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
"karsa-mistmere",
|
||||
"danielbayley"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"index",
|
||||
"backup",
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
"karsa-mistmere",
|
||||
"jguddas"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"sofa",
|
||||
"furniture",
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
"jamiemlaw",
|
||||
"jguddas"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"backwards",
|
||||
"reverse",
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
"jamiemlaw",
|
||||
"jguddas"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"backwards",
|
||||
"reverse",
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
"jamiemlaw",
|
||||
"jguddas"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"previous",
|
||||
"back",
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
"jamiemlaw",
|
||||
"jguddas"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"previous",
|
||||
"back",
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
"jamiemlaw",
|
||||
"jguddas"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"next",
|
||||
"forward",
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
"jamiemlaw",
|
||||
"jguddas"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"next",
|
||||
"forward",
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
"jamiemlaw",
|
||||
"jguddas"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"caps lock",
|
||||
"capitals",
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
"jamiemlaw",
|
||||
"jguddas"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"shift",
|
||||
"keyboard",
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
"karsa-mistmere",
|
||||
"danielbayley"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"filter",
|
||||
"sort",
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
"karsa-mistmere",
|
||||
"danielbayley"
|
||||
],
|
||||
"use-cases": [],
|
||||
"tags": [
|
||||
"filter",
|
||||
"sort",
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user