-
-
Notifications
You must be signed in to change notification settings - Fork 570
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(lucide-react): Add DynamicIcon component (#2686)
* Adding the DynamicIcon component * Fix imports * Add docs * Formatting * Fix use client in output rollup * revert changes * Fix formatting * Revert changes in icons directory * Revert time command * update exports
- Loading branch information
1 parent
d5fe5a0
commit 58c2e10
Showing
11 changed files
with
281 additions
and
110 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
'use client'; | ||
|
||
import { createElement, forwardRef, useEffect, useState } from 'react'; | ||
import { IconNode, LucideIcon, LucideProps } from './types'; | ||
import dynamicIconImports from './dynamicIconImports'; | ||
import Icon from './Icon'; | ||
|
||
export type DynamicIconModule = { default: LucideIcon; __iconNode: IconNode }; | ||
|
||
export type IconName = keyof typeof dynamicIconImports; | ||
|
||
export const iconNames = Object.keys(dynamicIconImports) as Array<IconName>; | ||
|
||
interface DynamicIconComponentProps extends LucideProps { | ||
name: IconName; | ||
fallback?: () => JSX.Element | null; | ||
} | ||
|
||
async function getIconNode(name: IconName) { | ||
if (!(name in dynamicIconImports)) { | ||
throw new Error('[lucide-react]: Name in Lucide DynamicIcon not found'); | ||
} | ||
|
||
// TODO: Replace this with a generic iconNode package. | ||
const icon = (await dynamicIconImports[name]()) as DynamicIconModule; | ||
|
||
return icon.__iconNode; | ||
} | ||
|
||
/** | ||
* Dynamic Lucide icon component | ||
* | ||
* @component Icon | ||
* @param {object} props | ||
* @param {string} props.color - The color of the icon | ||
* @param {number} props.size - The size of the icon | ||
* @param {number} props.strokeWidth - The stroke width of the icon | ||
* @param {boolean} props.absoluteStrokeWidth - Whether to use absolute stroke width | ||
* @param {string} props.className - The class name of the icon | ||
* @param {IconNode} props.children - The children of the icon | ||
* @param {IconNode} props.iconNode - The icon node of the icon | ||
* | ||
* @returns {ForwardRefExoticComponent} LucideIcon | ||
*/ | ||
const DynamicIcon = forwardRef<SVGSVGElement, DynamicIconComponentProps>( | ||
({ name, fallback: Fallback, ...props }, ref) => { | ||
const [iconNode, setIconNode] = useState<IconNode>(); | ||
|
||
useEffect(() => { | ||
getIconNode(name) | ||
.then(setIconNode) | ||
.catch((error) => { | ||
console.error(error); | ||
}); | ||
}, [name]); | ||
|
||
if (iconNode == null) { | ||
if (Fallback == null) { | ||
return null; | ||
} | ||
|
||
return createElement(Fallback); | ||
} | ||
|
||
return createElement(Icon, { | ||
ref, | ||
...props, | ||
iconNode, | ||
}); | ||
}, | ||
); | ||
|
||
export default DynamicIcon; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
export { | ||
default as DynamicIcon, | ||
iconNames, | ||
type DynamicIconModule, | ||
type IconName, | ||
} from './DynamicIcon'; | ||
export { default as dynamicIconImports } from './dynamicIconImports'; |
Oops, something went wrong.