@stacksjs/iconify-core 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +88 -0
- package/package.json +32 -0
- package/src/index.ts +141 -0
package/README.md
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# @stacksjs/iconify-core
|
|
2
|
+
|
|
3
|
+
Core utilities for using Iconify icons in stx templates.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
bun add @stacksjs/iconify-core
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
This package provides the core utilities for rendering icons. You'll typically use it alongside a specific icon collection package like `@stacksjs/iconify-lucide` or `@stacksjs/iconify-mdi`.
|
|
14
|
+
|
|
15
|
+
```typescript
|
|
16
|
+
import { renderIcon } from '@stacksjs/iconify-core'
|
|
17
|
+
import type { IconData, IconProps } from '@stacksjs/iconify-core'
|
|
18
|
+
|
|
19
|
+
const iconData: IconData = {
|
|
20
|
+
body: '<path fill="currentColor" d="..."/>',
|
|
21
|
+
width: 24,
|
|
22
|
+
height: 24,
|
|
23
|
+
viewBox: '0 0 24 24'
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const svg = renderIcon(iconData, {
|
|
27
|
+
size: 32,
|
|
28
|
+
color: '#4a90e2'
|
|
29
|
+
})
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## API
|
|
33
|
+
|
|
34
|
+
### `renderIcon(iconData: IconData, props?: IconProps): string`
|
|
35
|
+
|
|
36
|
+
Renders an icon to an SVG string.
|
|
37
|
+
|
|
38
|
+
#### Parameters
|
|
39
|
+
|
|
40
|
+
- `iconData`: Icon data object containing SVG body and dimensions
|
|
41
|
+
- `props`: Optional rendering options
|
|
42
|
+
|
|
43
|
+
#### Icon Props
|
|
44
|
+
|
|
45
|
+
```typescript
|
|
46
|
+
interface IconProps {
|
|
47
|
+
size?: string | number // Icon size (width and height)
|
|
48
|
+
width?: string | number // Icon width
|
|
49
|
+
height?: string | number // Icon height
|
|
50
|
+
color?: string // Icon color (default: 'currentColor')
|
|
51
|
+
hFlip?: boolean // Flip horizontally
|
|
52
|
+
vFlip?: boolean // Flip vertically
|
|
53
|
+
rotate?: 0 | 90 | 180 | 270 // Rotation in degrees
|
|
54
|
+
class?: string // Additional CSS classes
|
|
55
|
+
style?: string // Additional inline styles
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Example
|
|
60
|
+
|
|
61
|
+
```typescript
|
|
62
|
+
import { home } from '@stacksjs/iconify-lucide'
|
|
63
|
+
import { renderIcon } from '@stacksjs/iconify-core'
|
|
64
|
+
|
|
65
|
+
// Basic usage
|
|
66
|
+
const icon1 = renderIcon(home, { size: 24 })
|
|
67
|
+
|
|
68
|
+
// With color
|
|
69
|
+
const icon2 = renderIcon(home, { size: 24, color: '#ff0000' })
|
|
70
|
+
|
|
71
|
+
// With transformations
|
|
72
|
+
const icon3 = renderIcon(home, {
|
|
73
|
+
size: 24,
|
|
74
|
+
rotate: 90,
|
|
75
|
+
hFlip: true
|
|
76
|
+
})
|
|
77
|
+
|
|
78
|
+
// With custom classes and styles
|
|
79
|
+
const icon4 = renderIcon(home, {
|
|
80
|
+
size: 24,
|
|
81
|
+
class: 'my-icon',
|
|
82
|
+
style: 'opacity: 0.8;'
|
|
83
|
+
})
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## License
|
|
87
|
+
|
|
88
|
+
MIT
|
package/package.json
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@stacksjs/iconify-core",
|
|
3
|
+
"type": "module",
|
|
4
|
+
"version": "0.1.3",
|
|
5
|
+
"description": "Core utilities for Iconify SVG icons in stx",
|
|
6
|
+
"author": "Chris Breuer <chris@stacksjs.org>",
|
|
7
|
+
"license": "MIT",
|
|
8
|
+
"keywords": [
|
|
9
|
+
"iconify",
|
|
10
|
+
"icons",
|
|
11
|
+
"svg",
|
|
12
|
+
"stx",
|
|
13
|
+
"ui"
|
|
14
|
+
],
|
|
15
|
+
"exports": {
|
|
16
|
+
".": {
|
|
17
|
+
"types": "./dist/index.d.ts",
|
|
18
|
+
"import": "./dist/index.js"
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
"main": "./dist/index.js",
|
|
22
|
+
"module": "./dist/index.js",
|
|
23
|
+
"types": "./dist/index.d.ts",
|
|
24
|
+
"files": [
|
|
25
|
+
"dist",
|
|
26
|
+
"src"
|
|
27
|
+
],
|
|
28
|
+
"scripts": {
|
|
29
|
+
"build": "bun build.ts",
|
|
30
|
+
"dev": "bun build.ts --watch"
|
|
31
|
+
}
|
|
32
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
export interface IconProps {
|
|
2
|
+
/**
|
|
3
|
+
* Icon name
|
|
4
|
+
*/
|
|
5
|
+
name?: string
|
|
6
|
+
/**
|
|
7
|
+
* Icon size (width and height)
|
|
8
|
+
* @default "1em"
|
|
9
|
+
*/
|
|
10
|
+
size?: string | number
|
|
11
|
+
/**
|
|
12
|
+
* Icon width
|
|
13
|
+
*/
|
|
14
|
+
width?: string | number
|
|
15
|
+
/**
|
|
16
|
+
* Icon height
|
|
17
|
+
*/
|
|
18
|
+
height?: string | number
|
|
19
|
+
/**
|
|
20
|
+
* Icon color
|
|
21
|
+
* @default "currentColor"
|
|
22
|
+
*/
|
|
23
|
+
color?: string
|
|
24
|
+
/**
|
|
25
|
+
* Horizontal flip
|
|
26
|
+
*/
|
|
27
|
+
hFlip?: boolean
|
|
28
|
+
/**
|
|
29
|
+
* Vertical flip
|
|
30
|
+
*/
|
|
31
|
+
vFlip?: boolean
|
|
32
|
+
/**
|
|
33
|
+
* Rotation in degrees
|
|
34
|
+
*/
|
|
35
|
+
rotate?: 0 | 90 | 180 | 270 | 1 | 2 | 3
|
|
36
|
+
/**
|
|
37
|
+
* Additional CSS classes
|
|
38
|
+
*/
|
|
39
|
+
class?: string
|
|
40
|
+
/**
|
|
41
|
+
* Additional inline styles
|
|
42
|
+
*/
|
|
43
|
+
style?: string
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export interface IconData {
|
|
47
|
+
/**
|
|
48
|
+
* Icon body (SVG path data)
|
|
49
|
+
*/
|
|
50
|
+
body: string
|
|
51
|
+
/**
|
|
52
|
+
* Icon width (default: 24)
|
|
53
|
+
*/
|
|
54
|
+
width?: number
|
|
55
|
+
/**
|
|
56
|
+
* Icon height (default: 24)
|
|
57
|
+
*/
|
|
58
|
+
height?: number
|
|
59
|
+
/**
|
|
60
|
+
* Icon viewBox
|
|
61
|
+
*/
|
|
62
|
+
viewBox?: string
|
|
63
|
+
/**
|
|
64
|
+
* Whether the icon uses currentColor
|
|
65
|
+
*/
|
|
66
|
+
currentColor?: boolean
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Generate SVG string from icon data
|
|
71
|
+
*/
|
|
72
|
+
export function renderIcon(iconData: IconData, props: IconProps = {}): string {
|
|
73
|
+
const {
|
|
74
|
+
size,
|
|
75
|
+
width: propWidth,
|
|
76
|
+
height: propHeight,
|
|
77
|
+
color = 'currentColor',
|
|
78
|
+
hFlip = false,
|
|
79
|
+
vFlip = false,
|
|
80
|
+
rotate = 0,
|
|
81
|
+
class: className = '',
|
|
82
|
+
style: customStyle = '',
|
|
83
|
+
} = props
|
|
84
|
+
|
|
85
|
+
const width = propWidth || size || iconData.width || 24
|
|
86
|
+
const height = propHeight || size || iconData.height || 24
|
|
87
|
+
const viewBox = iconData.viewBox || `0 0 ${iconData.width || 24} ${iconData.height || 24}`
|
|
88
|
+
|
|
89
|
+
// Build transform
|
|
90
|
+
const transforms: string[] = []
|
|
91
|
+
if (hFlip)
|
|
92
|
+
transforms.push('scaleX(-1)')
|
|
93
|
+
if (vFlip)
|
|
94
|
+
transforms.push('scaleY(-1)')
|
|
95
|
+
if (rotate) {
|
|
96
|
+
const deg = typeof rotate === 'number' && rotate < 4 ? rotate * 90 : rotate
|
|
97
|
+
transforms.push(`rotate(${deg}deg)`)
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const transform = transforms.length > 0 ? transforms.join(' ') : ''
|
|
101
|
+
const transformStyle = transform ? `transform: ${transform};` : ''
|
|
102
|
+
|
|
103
|
+
// Build style
|
|
104
|
+
const styles: string[] = []
|
|
105
|
+
if (transformStyle)
|
|
106
|
+
styles.push(transformStyle)
|
|
107
|
+
if (customStyle)
|
|
108
|
+
styles.push(customStyle)
|
|
109
|
+
|
|
110
|
+
const style = styles.length > 0 ? ` style="${styles.join(' ')}"` : ''
|
|
111
|
+
const classAttr = className ? ` class="${className}"` : ''
|
|
112
|
+
|
|
113
|
+
// Replace currentColor in body if color is specified
|
|
114
|
+
let body = iconData.body
|
|
115
|
+
if (color && color !== 'currentColor') {
|
|
116
|
+
body = body.replace(/currentColor/g, color)
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
return `<svg xmlns="http://www.w3.org/2000/svg" width="${width}" height="${height}" viewBox="${viewBox}"${classAttr}${style}>${body}</svg>`
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Generate icon component CSS
|
|
124
|
+
*/
|
|
125
|
+
export function generateIconCSS(prefix: string): string {
|
|
126
|
+
return `
|
|
127
|
+
.icon-${prefix} {
|
|
128
|
+
display: inline-block;
|
|
129
|
+
width: 1em;
|
|
130
|
+
height: 1em;
|
|
131
|
+
vertical-align: -0.125em;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
.icon-${prefix} svg {
|
|
135
|
+
width: 100%;
|
|
136
|
+
height: 100%;
|
|
137
|
+
}
|
|
138
|
+
`.trim()
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
export { type IconData as Icon }
|