-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(icon): initial icon implementation
- Loading branch information
Showing
7 changed files
with
142 additions
and
4 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
import DOMPurify from 'dompurify'; | ||
import { LitElement, css, html } from 'lit'; | ||
import { customElement, property } from 'lit/decorators.js'; | ||
import { unsafeHTML } from 'lit/directives/unsafe-html.js'; | ||
|
||
import { getIcon } from './store'; | ||
|
||
type IconSize = 'xxs' | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'xxl'; | ||
|
||
@customElement('cx-icon') | ||
export class Icon extends LitElement { | ||
static readonly styles = css` | ||
:host { | ||
--_icon-size: 32px; | ||
display: inline-block; | ||
width: var(--_icon-size); | ||
height: var(--_icon-size); | ||
line-height: 0; | ||
} | ||
:host([size='xxs']) { | ||
--_icon-size: 8px; | ||
} | ||
:host([size='xs']) { | ||
--_icon-size: 16px; | ||
} | ||
:host([size='sm']) { | ||
--_icon-size: 24px; | ||
} | ||
:host([size='md']) { | ||
--_icon-size: 32px; | ||
} | ||
:host([size='lg']) { | ||
--_icon-size: 40px; | ||
} | ||
:host([size='xl']) { | ||
--_icon-size: 48px; | ||
} | ||
:host([size='xxl']) { | ||
--_icon-size: 56px; | ||
} | ||
svg { | ||
width: 100%; | ||
height: 100%; | ||
} | ||
`; | ||
|
||
@property({ type: String, reflect: true }) | ||
name = ''; | ||
|
||
// Setting this to reflect: true will make the size attribute reflect to the DOM, which makes the current | ||
// CSS-selector-based approach for sizing work in React. If another approach is used, this whole property may be removed. | ||
@property({ type: String, reflect: true }) | ||
size: IconSize | undefined = undefined; | ||
|
||
render() { | ||
return html`${unsafeHTML(DOMPurify.sanitize(getIcon(this.name)?.svg ?? ''))}`; | ||
} | ||
} | ||
|
||
declare global { | ||
interface HTMLElementTagNameMap { | ||
'cx-icon': Icon; | ||
} | ||
} |
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,2 @@ | ||
export * from './icon'; | ||
export { addIcons } from './store'; |
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,12 @@ | ||
{ | ||
"name": "@computas/designsystem-icon", | ||
"version": "1.0.0", | ||
"type": "module", | ||
"private": "true", | ||
"scripts": { | ||
"build": "tsup" | ||
}, | ||
"devDependencies": { | ||
"tsup": "^8.3.5" | ||
} | ||
} |
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,10 @@ | ||
import { createComponent } from '@lit/react'; | ||
import * as React from 'react'; | ||
|
||
import { Icon } from './index'; | ||
|
||
export const CxIcon = createComponent({ | ||
tagName: 'cx-icon', | ||
elementClass: Icon, | ||
react: React, | ||
}); |
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,40 @@ | ||
interface IconData { | ||
svg: string; | ||
} | ||
type IconRegistry = Record<string, IconData>; | ||
|
||
let _cxGlobalIconsStore: IconRegistry = {}; | ||
|
||
/** | ||
* Add icons to the global icon store to make them available for use in the `<e-icon>/Icon` component. | ||
* | ||
* You can add multiple icons at once. The key of the input object is the icon name corresponding to the `name` | ||
* prop in the `<e-icon>/Icon` component. While this can be any string, it is recommended to use the icon name as the key. | ||
* Some selectors depend on the `filledColor` icons to keep `filledColor` in the icon name to work properly. | ||
* @param icons - An object of icon names and their corresponding SVG data. | ||
* | ||
* @example | ||
* ```ts | ||
* import { addIcons } from '@computas/designsystem/icon'; | ||
* | ||
* // import the icon data (SVG string) | ||
* import download from '@computas/designsystem/icon/svg/download?raw'; | ||
* | ||
* addIcons({ | ||
* download: { svg: download } | ||
* }); | ||
* ``` | ||
*/ | ||
export const addIcons = (icons: IconRegistry) => { | ||
_cxGlobalIconsStore = { ..._cxGlobalIconsStore, ...icons }; | ||
}; | ||
|
||
export const getIcon = (name: string): IconData | undefined => { | ||
// Need to check `name` because it can be `undefined` on initial render depending on property vs attribute | ||
if (name && !_cxGlobalIconsStore[name]) { | ||
throw new Error( | ||
`Icon "${name}" not found. Ensure the icon name is correct and that it has been added to the global icon store using \`addIcons\`.`, | ||
); | ||
} | ||
return _cxGlobalIconsStore[name]; | ||
}; |