Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
38c834bcda | ||
|
|
f3a1bba31d | ||
|
|
ea82684178 | ||
|
|
7e3d6a8121 | ||
|
|
2c35468403 | ||
|
|
96aec6562a |
16
icons/bar-chart-3.svg
Normal file
@@ -0,0 +1,16 @@
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<path d="M2 2v20h20" />
|
||||
<path d="M17 18V9" />
|
||||
<path d="M12 18V4" />
|
||||
<path d="M7 18v-4" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 306 B |
16
icons/bar-chart-4.svg
Normal file
@@ -0,0 +1,16 @@
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<path d="M2 2v20h20" />
|
||||
<path d="M12 18V9" />
|
||||
<path d="M17 18V4" />
|
||||
<path d="M7 18v-4" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 306 B |
16
icons/bar-chart-horizontal.svg
Normal file
@@ -0,0 +1,16 @@
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<path d="M2 2V22H22" />
|
||||
<path d="M6 17L15 17" />
|
||||
<path d="M6 12L20 12" />
|
||||
<path d="M6 7L10 7" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 313 B |
14
icons/line-chart.svg
Normal file
@@ -0,0 +1,14 @@
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<path d="M2 2v20h20" />
|
||||
<path d="m20 9-6 6-5-5-3 3" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 267 B |
17
icons/map-pin-off.svg
Normal file
@@ -0,0 +1,17 @@
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<path d="M5.43 5.43A8.06 8.06 0 0 0 4 10c0 6 8 12 8 12a29.94 29.94 0 0 0 5-5"/>
|
||||
<path d="M19.18 13.52A8.66 8.66 0 0 0 20 10a8 8 0 0 0-8-8 7.88 7.88 0 0 0-3.52.82"/>
|
||||
<path d="M9.13 9.13A2.78 2.78 0 0 0 9 10a3 3 0 0 0 3 3 2.78 2.78 0 0 0 .87-.13"/>
|
||||
<path d="M14.9 9.25a3 3 0 0 0-2.15-2.16"/>
|
||||
<line x1="2" y1="2" x2="22" y2="22" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 547 B |
15
icons/navigation-2-off.svg
Normal file
@@ -0,0 +1,15 @@
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<path d="M9.31 9.31 5 21l7-4 7 4-1.17-3.17"/>
|
||||
<path d="M14.53 8.88 12 2 10.83 5.17"/>
|
||||
<line x1="2" y1="2" x2="22" y2="22" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 339 B |
15
icons/navigation-off.svg
Normal file
@@ -0,0 +1,15 @@
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<path d="M8.43 8.43 3 11l8 2 2 8 2.57-5.43"/>
|
||||
<path d="M17.39 11.73 22 2 12.27 6.61"/>
|
||||
<line x1="2" y1="2" x2="22" y2="22" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 340 B |
@@ -9,7 +9,7 @@
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<path d="m2 22 2-2h3l7-7" />
|
||||
<path d="M4 20v-3l7-7" />
|
||||
<path d="M14.29 13.3a1 1 0 0 0 1.41 0l.8-.8c.27-.27.27-.72 0-1s-.28-.72 0-1l4.08-4.08a2 2 0 0 0 0-2.83l-.17-.17a2 2 0 0 0-2.83 0L13.5 7.51c-.28.27-.73.27-1 0s-.73-.28-1 0l-.8.79a1 1 0 0 0 0 1.41l3.59 3.59z" />
|
||||
<path d="M2 22l1-1H6l9-9" />
|
||||
<path d="M3 21V18l9-9" />
|
||||
<path d="M21.37 5.63a2.12 2.12 0 0 0-3-3L15.58 5.42a1.05 1.05 0 0 1-1.5 0 1.07 1.07 0 0 0-1.5 0L11.25 6.75a1.07 1.07 0 0 0 0 1.5l4.5 4.5a1.07 1.07 0 0 0 1.5 0l1.33-1.33a1.07 1.07 0 0 0 0-1.5 1.05 1.05 0 0 1 0-1.5Z" />
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 479 B After Width: | Height: | Size: 487 B |
14
icons/redo-2.svg
Normal file
@@ -0,0 +1,14 @@
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<path d="m15 14 5-5-5-5" />
|
||||
<path d="M20 9H9.5A5.5 5.5 0 0 0 4 14.5v0A5.5 5.5 0 0 0 9.5 20H13" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 310 B |
@@ -9,7 +9,7 @@
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<circle cx="9" cy="21" r="1" />
|
||||
<circle cx="8" cy="21" r="1" />
|
||||
<circle cx="19" cy="21" r="1" />
|
||||
<path d="M2 2H4.5L7.62 14.49A2 2 0 0 0 9.56 16h8.88a2 2 0 0 0 1.94-1.51L22 8H6" />
|
||||
<path d="M2.05 2.05h2l2.66 12.42a2 2 0 0 0 2 1.58h9.78a2 2 0 0 0 1.95-1.57l1.65-7.43H5.12" />
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 362 B After Width: | Height: | Size: 373 B |
14
icons/undo-2.svg
Normal file
@@ -0,0 +1,14 @@
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<path d="M9 14 4 9l5-5" />
|
||||
<path d="M4 9h10.5a5.5 5.5 0 0 1 5.5 5.5v0a5.5 5.5 0 0 1-5.5 5.5H11" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 311 B |
@@ -1,4 +1,6 @@
|
||||
import { createContext, useState } from 'react';
|
||||
import { createContext, useRef, useState, MutableRefObject, useContext, useMemo } from 'react';
|
||||
|
||||
type IconsRef = Record<string, SVGSVGElement>;
|
||||
|
||||
interface ICustomIconStyle {
|
||||
color: string;
|
||||
@@ -8,13 +10,14 @@ interface ICustomIconStyle {
|
||||
size: number;
|
||||
setSize: (n: number) => void;
|
||||
resetStyle: () => void;
|
||||
iconsRef: MutableRefObject<IconsRef>;
|
||||
}
|
||||
|
||||
const DEFAULT_STYLE = {
|
||||
color: 'currentColor',
|
||||
strokeWidth: 2,
|
||||
size: 24,
|
||||
}
|
||||
};
|
||||
|
||||
export const IconStyleContext = createContext<ICustomIconStyle>({
|
||||
color: 'currentColor',
|
||||
@@ -23,25 +26,43 @@ export const IconStyleContext = createContext<ICustomIconStyle>({
|
||||
setStroke: (n: number) => null,
|
||||
size: 24,
|
||||
setSize: (n: number) => null,
|
||||
resetStyle: () => null
|
||||
resetStyle: () => null,
|
||||
iconsRef: { current: {} },
|
||||
});
|
||||
|
||||
export function CustomizeIconContext({ children }) {
|
||||
export function CustomizeIconContext({ children }): JSX.Element {
|
||||
const iconsRef = useRef<IconsRef>({});
|
||||
const [color, setColor] = useState(DEFAULT_STYLE.color);
|
||||
const [stroke, setStroke] = useState(DEFAULT_STYLE.strokeWidth);
|
||||
const [size, setSize] = useState(DEFAULT_STYLE.size);
|
||||
|
||||
function resetStyle(){
|
||||
function resetStyle() {
|
||||
setColor(DEFAULT_STYLE.color);
|
||||
setStroke(DEFAULT_STYLE.strokeWidth);
|
||||
setSize(DEFAULT_STYLE.size);
|
||||
}
|
||||
|
||||
return (
|
||||
<IconStyleContext.Provider
|
||||
value={{ color, setColor, strokeWidth: stroke, setStroke, size, setSize, resetStyle }}
|
||||
>
|
||||
{children}
|
||||
</IconStyleContext.Provider>
|
||||
const value = useMemo(
|
||||
() => ({
|
||||
color,
|
||||
setColor,
|
||||
strokeWidth: stroke,
|
||||
setStroke,
|
||||
size,
|
||||
setSize,
|
||||
resetStyle,
|
||||
iconsRef,
|
||||
}),
|
||||
[color, setColor, stroke, setStroke, size, setSize, resetStyle, iconsRef],
|
||||
);
|
||||
|
||||
return <IconStyleContext.Provider value={value}>{children}</IconStyleContext.Provider>;
|
||||
}
|
||||
|
||||
export function useCustomizeIconContext(): ICustomIconStyle {
|
||||
const context = useContext(IconStyleContext);
|
||||
if (context === undefined) {
|
||||
throw new Error('useCustomizeIconContext must be used within a IconStyleContextProvider');
|
||||
}
|
||||
return context;
|
||||
}
|
||||
|
||||
@@ -13,20 +13,49 @@ import AngularLogo from '../../public/framework-logos/angular.svg';
|
||||
import FlutterLogo from '../../public/framework-logos/flutter.svg';
|
||||
import SvelteLogo from '../../public/framework-logos/svelte.svg';
|
||||
import LaravelLogo from '../../public/framework-logos/laravel.svg';
|
||||
import { useState } from 'react';
|
||||
import { useCustomizeIconContext } from './CustomizeIconContext';
|
||||
import { IconEntity } from '../types';
|
||||
|
||||
function generateZip(icons) {
|
||||
type IconContent = [icon: string, src:string]
|
||||
|
||||
async function generateZip(icons: IconContent[]) {
|
||||
const zip = new JSZip();
|
||||
Object.values(icons).forEach(icon =>
|
||||
// @ts-ignore
|
||||
zip.file(`${icon.name}.svg`, icon.src),
|
||||
|
||||
const addingZipPromises = icons.map(([name, src]) =>
|
||||
zip.file(`${name}.svg`, src),
|
||||
);
|
||||
|
||||
await Promise.all(addingZipPromises)
|
||||
|
||||
return zip.generateAsync({ type: 'blob' });
|
||||
}
|
||||
|
||||
const Header = ({ data }) => {
|
||||
interface HeaderProps {
|
||||
data: IconEntity[];
|
||||
}
|
||||
|
||||
const Header = ({ data }: HeaderProps) => {
|
||||
const [zippingIcons, setZippingIcons] = useState(false);
|
||||
const { iconsRef } = useCustomizeIconContext();
|
||||
|
||||
const downloadAllIcons = async () => {
|
||||
const zip = await generateZip(data);
|
||||
console.log(iconsRef);
|
||||
setZippingIcons(true);
|
||||
|
||||
let iconEntries: IconContent[] = Object.entries(iconsRef.current).map(([name, svgEl]) => [
|
||||
name,
|
||||
svgEl.outerHTML,
|
||||
]);
|
||||
|
||||
// Fallback
|
||||
if (iconEntries.length === 0) {
|
||||
iconEntries = data.map(icon => [icon.name, icon.src]);
|
||||
}
|
||||
|
||||
const zip = await generateZip(iconEntries);
|
||||
download(zip, 'lucide.zip');
|
||||
setZippingIcons(false);
|
||||
};
|
||||
|
||||
const repositoryUrl = 'https://github.com/lucide-icons/lucide';
|
||||
@@ -76,7 +105,7 @@ const Header = ({ data }) => {
|
||||
name: 'lucide-laravel',
|
||||
Logo: LaravelLogo,
|
||||
href: 'https://github.com/mallardduck/blade-lucide-icons',
|
||||
}
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
@@ -124,7 +153,13 @@ const Header = ({ data }) => {
|
||||
</Wrap>
|
||||
<Wrap marginTop={3} marginBottom={12} spacing="15px" justify="center">
|
||||
<WrapItem>
|
||||
<Button leftIcon={<Download />} size="lg" onClick={downloadAllIcons}>
|
||||
<Button
|
||||
leftIcon={<Download />}
|
||||
size="lg"
|
||||
onClick={downloadAllIcons}
|
||||
isLoading={zippingIcons}
|
||||
loadingText="Creating zip.."
|
||||
>
|
||||
Download all
|
||||
</Button>
|
||||
</WrapItem>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { Box, Button, ButtonProps, Flex, Text, useToast } from '@chakra-ui/react';
|
||||
import { Button, ButtonProps, Flex, Text, useToast } from '@chakra-ui/react';
|
||||
import download from 'downloadjs';
|
||||
import copy from 'copy-to-clipboard';
|
||||
import { memo, useContext } from 'react';
|
||||
import { IconStyleContext } from './CustomizeIconContext';
|
||||
import { memo } from 'react';
|
||||
import { useCustomizeIconContext } from './CustomizeIconContext';
|
||||
import { IconWrapper } from './IconWrapper';
|
||||
|
||||
interface IconListItemProps {
|
||||
@@ -13,9 +13,9 @@ interface IconListItemProps {
|
||||
onClick?: ButtonProps['onClick'];
|
||||
}
|
||||
|
||||
const IconListItem = ({ name, content, src, onClick }: IconListItemProps) => {
|
||||
const IconListItem = ({ name, content, onClick, src: svg }: IconListItemProps) => {
|
||||
const toast = useToast();
|
||||
const { color, size, strokeWidth } = useContext(IconStyleContext);
|
||||
const { color, size, strokeWidth, iconsRef } = useCustomizeIconContext();
|
||||
|
||||
return (
|
||||
<Button
|
||||
@@ -27,6 +27,7 @@ const IconListItem = ({ name, content, src, onClick }: IconListItemProps) => {
|
||||
position="relative"
|
||||
whiteSpace="normal"
|
||||
onClick={event => {
|
||||
const src = iconsRef.current[name].outerHTML ?? svg
|
||||
if (event.shiftKey) {
|
||||
copy(src);
|
||||
toast({
|
||||
@@ -54,6 +55,7 @@ const IconListItem = ({ name, content, src, onClick }: IconListItemProps) => {
|
||||
strokeWidth={strokeWidth}
|
||||
height={size}
|
||||
width={size}
|
||||
ref={iconEl => (iconsRef.current[name] = iconEl)}
|
||||
/>
|
||||
</Flex>
|
||||
<Flex flex={1} minHeight={10} align="center">
|
||||
|
||||
@@ -4,7 +4,7 @@ import { getAllData, getData } from '../../lib/icons';
|
||||
import IconOverview from '../../components/IconOverview';
|
||||
import Layout from '../../components/Layout';
|
||||
import Header from '../../components/Header';
|
||||
import { useEffect, useMemo } from 'react';
|
||||
import { useMemo } from 'react';
|
||||
|
||||
const IconPage = ({ icon, data }) => {
|
||||
const router = useRouter();
|
||||
@@ -30,19 +30,15 @@ const IconPage = ({ icon, data }) => {
|
||||
};
|
||||
|
||||
const currentIcon = useMemo(() => {
|
||||
if(icon.name === router.query.iconName) {
|
||||
return icon
|
||||
if (icon.name === router.query.iconName) {
|
||||
return icon;
|
||||
}
|
||||
return getIcon(router.query.iconName)
|
||||
}, [router.query])
|
||||
return getIcon(router.query.iconName);
|
||||
}, [router.query]);
|
||||
|
||||
return (
|
||||
<Layout>
|
||||
<IconDetailOverlay
|
||||
key={currentIcon.name}
|
||||
icon={currentIcon}
|
||||
close={onClose}
|
||||
/>
|
||||
<IconDetailOverlay key={currentIcon.name} icon={currentIcon} close={onClose} />
|
||||
<Header {...{ data }} />
|
||||
<IconOverview {...{ data }} />
|
||||
</Layout>
|
||||
|
||||
42
tags.json
@@ -317,6 +317,21 @@
|
||||
"diagram",
|
||||
"graph"
|
||||
],
|
||||
"bar-chart-3": [
|
||||
"statistics",
|
||||
"diagram",
|
||||
"graph"
|
||||
],
|
||||
"bar-chart-4": [
|
||||
"statistics",
|
||||
"diagram",
|
||||
"graph"
|
||||
],
|
||||
"bar-chart-horizontal": [
|
||||
"statistics",
|
||||
"diagram",
|
||||
"graph"
|
||||
],
|
||||
"baseline": [
|
||||
"text",
|
||||
"format",
|
||||
@@ -1513,6 +1528,11 @@
|
||||
"lightbulb-off": [
|
||||
"lights"
|
||||
],
|
||||
"line-chart": [
|
||||
"statistics",
|
||||
"diagram",
|
||||
"graph"
|
||||
],
|
||||
"link": [
|
||||
"chain",
|
||||
"url"
|
||||
@@ -1620,6 +1640,12 @@
|
||||
"travel",
|
||||
"marker"
|
||||
],
|
||||
"map-pin-off": [
|
||||
"location",
|
||||
"navigation",
|
||||
"travel",
|
||||
"marker"
|
||||
],
|
||||
"maximize": [
|
||||
"fullscreen",
|
||||
"expand"
|
||||
@@ -1784,6 +1810,14 @@
|
||||
"location",
|
||||
"travel"
|
||||
],
|
||||
"navigation-2-off": [
|
||||
"location",
|
||||
"travel"
|
||||
],
|
||||
"navigation-off": [
|
||||
"location",
|
||||
"travel"
|
||||
],
|
||||
"network": [
|
||||
"tree"
|
||||
],
|
||||
@@ -1993,6 +2027,10 @@
|
||||
"undo",
|
||||
"history"
|
||||
],
|
||||
"redo-2": [
|
||||
"undo",
|
||||
"history"
|
||||
],
|
||||
"refresh-ccw": [
|
||||
"arrows",
|
||||
"reload"
|
||||
@@ -2593,6 +2631,10 @@
|
||||
"redo",
|
||||
"history"
|
||||
],
|
||||
"undo-2": [
|
||||
"redo",
|
||||
"history"
|
||||
],
|
||||
"unlink": [
|
||||
"url",
|
||||
"unchain",
|
||||
|
||||