Skip to content

Commit 1b28ec2

Browse files
ezequidiasantfu
andauthored
feat: support iconify customization (#199)
Co-authored-by: Anthony Fu <[email protected]>
1 parent 1ccb7c2 commit 1b28ec2

File tree

11 files changed

+94
-13
lines changed

11 files changed

+94
-13
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
"@iconify/collections": "^1.0.441",
4040
"@iconify/types": "^2.0.0",
4141
"@iconify/utils": "^2.1.25",
42-
"@iconify/vue": "^4.1.2",
42+
"@iconify/vue": "4.1.3-beta.1",
4343
"@nuxt/devtools-kit": "^1.3.9",
4444
"@nuxt/kit": "^3.12.4",
4545
"consola": "^3.2.3",

playground/app.config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ export default defineAppConfig({
55
aliases: {
66
github: 'carbon:logo-github',
77
nuxt: 'logos:nuxt-icon',
8-
rocket: 'fluent-emoji:rocket',
8+
rocket: 'skill-icons:rocket',
99
nxt: 'NuxtLogo',
1010
},
1111
},

playground/app.vue

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,13 @@ const mode = useCookie<'svg' | 'css'>('nuxt-icon-demo-mode', {
1616
const iconsRaw = useCookie<string[]>('nuxt-icon-demo-icons', {
1717
default: () => ['logos-nuxt-icon', 'logos-vitejs', 'logos-vue'],
1818
})
19+
const stroke = useCookie<number>('nuxt-icon-demo-stroke', {
20+
default: () => 0.5,
21+
})
22+
23+
const customize = (content: string) => {
24+
return content.replace(/stroke-width="[^"]*"/g, `stroke-width="${stroke.value}"`)
25+
}
1926
2027
const icons = ref<string[]>(iconsRaw.value)
2128
@@ -36,6 +43,7 @@ function addRandom() {
3643
function clear() {
3744
icons.value = []
3845
iconsRaw.value = icons.value
46+
stroke.value = 0.5
3947
}
4048
</script>
4149

@@ -51,6 +59,17 @@ function clear() {
5159
CSS
5260
</option>
5361
</select>
62+
<div class="flex gap-2 mb-0.5 items-center">
63+
<div>Stroke:</div>
64+
<input
65+
v-model="stroke"
66+
type="range"
67+
class="mt-1.5"
68+
min="0.5"
69+
step="0.1"
70+
max="3"
71+
>
72+
</div>
5473
<button
5574
class="flex items-center gap-1"
5675
@click="addRandom"
@@ -92,6 +111,7 @@ function clear() {
92111
<Icon
93112
:name="icon"
94113
:mode="mode"
114+
:customize
95115
/>
96116
</div>
97117
<div class="text-xs font-mono opacity-50">
@@ -109,33 +129,39 @@ function clear() {
109129
<Icon
110130
name="uil:github"
111131
:mode
132+
:customize
112133
/>
113134
<Icon
114135
name="uil:github"
115136
size="24"
116137
:mode
138+
:customize
117139
/>
118140
<Icon
119141
name="uil:github"
120142
size="48"
121143
:mode
144+
:customize
122145
/>
123146
</p>
124147
<p>
125148
Global components:
126149
<Icon
127150
name="NuxtLogo"
128151
:mode
152+
:customize
129153
/>
130154
<Icon
131155
name="NuxtLogo"
132156
size="24"
133157
:mode
158+
:customize
134159
/>
135160
<Icon
136161
name="NuxtLogo"
137162
size="48"
138163
:mode
164+
:customize
139165
/>
140166
</p>
141167
<p>
@@ -144,6 +170,7 @@ function clear() {
144170
name="custom1:nuxt-v1"
145171
size="64"
146172
:mode
173+
:customize
147174
/>
148175
<Icon
149176
name="custom1:nuxt-v2"
@@ -154,11 +181,13 @@ function clear() {
154181
name="custom1:nuxt-v3-beta"
155182
size="64"
156183
:mode
184+
:customize
157185
/>
158186
<Icon
159187
name="custom1:nuxt-v3"
160188
size="64"
161189
:mode
190+
:customize
162191
/>
163192
</p>
164193
<p>
@@ -167,6 +196,7 @@ function clear() {
167196
name="layer:layer"
168197
size="64"
169198
:mode
199+
:customize
170200
/>
171201
</p>
172202
<!-- <p>
@@ -187,27 +217,32 @@ function clear() {
187217
name="github"
188218
size="24"
189219
:mode
220+
:customize
190221
/>
191222
<Icon
192223
name="nuxt"
193224
size="24"
194225
:mode
226+
:customize
195227
/>
196228
<Icon
197229
name="rocket"
198230
size="24"
199231
:mode
232+
:customize
200233
/>
201234
<Icon
202235
name="nxt"
203236
size="24"
237+
:customize
204238
/>
205239
</p>
206240
<p>
207241
`i-` syntax:
208242
<Icon
209-
name="i-fluent-emoji-high-contrast-1st-place-medal"
243+
name="i-solar:medal-ribbon-bold-duotone"
210244
:mode
245+
:customize
211246
/>
212247
</p>
213248
<!-- <p>
@@ -223,10 +258,12 @@ function clear() {
223258
<Icon
224259
name="i-ph-code"
225260
:mode
261+
:customize
226262
/>
227263
<Icon
228264
name="ph:table"
229265
:mode
266+
:customize
230267
/>
231268
</p>
232269
</div>

pnpm-lock.yaml

Lines changed: 5 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/module.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ export default defineNuxtModule<ModuleOptions>({
5353
mode: schema['mode'].$default,
5454
attrs: schema['attrs'].$default,
5555
collections: schema['collections'].$default,
56+
customize: schema['customize'].$default,
5657
},
5758
async setup(options, nuxt) {
5859
const resolver = createResolver(import.meta.url)

src/runtime/components/css.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import { addIcon, getIcon as _getIcon } from '@iconify/vue'
22
import { computed, watch, h, defineComponent } from 'vue'
33
import { getIconCSS } from '@iconify/utils/lib/css/icon'
4+
import type { PropType } from 'vue'
45
import type { IconifyIcon } from '@iconify/types'
5-
import type { NuxtIconRuntimeOptions, NuxtIconRuntimeServerOptions } from '../../types'
6+
import type { NuxtIconRuntimeOptions, NuxtIconRuntimeServerOptions, IconifyIconCustomizeCallback } from '../../types'
67
import { loadIcon } from './shared'
78
import { useAppConfig, useNuxtApp, useHead, useRuntimeConfig } from '#imports'
89

@@ -65,9 +66,13 @@ export const NuxtIconCss = /* @__PURE__ */ defineComponent({
6566
name: 'NuxtIconCss',
6667
props: {
6768
name: {
68-
type: String,
69+
type: String as PropType<string>,
6970
required: true,
7071
},
72+
customize: {
73+
type: Function as PropType<IconifyIconCustomizeCallback>,
74+
required: false,
75+
},
7176
},
7277
async setup(props) {
7378
const nuxt = useNuxtApp()
@@ -95,6 +100,7 @@ export const NuxtIconCss = /* @__PURE__ */ defineComponent({
95100
const css = getIconCSS(icon, {
96101
iconSelector,
97102
format: 'compressed',
103+
customise: props.customize,
98104
})
99105
if (options.cssLayer && withLayer) {
100106
return `@layer ${options.cssLayer} { ${css} }`

src/runtime/components/index.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { getIcon as _getIcon } from '@iconify/vue'
22
import type { PropType } from 'vue'
33
import { computed, defineComponent, h } from 'vue'
4-
import type { NuxtIconRuntimeOptions } from '../../types'
4+
import type { NuxtIconRuntimeOptions, IconifyIconCustomizeCallback } from '../../types'
55
import { NuxtIconCss } from './css'
66
import { NuxtIconSvg } from './svg'
77
import { useResolvedName } from './shared'
@@ -24,6 +24,10 @@ export default defineComponent({
2424
required: false,
2525
default: null,
2626
},
27+
customize: {
28+
type: Function as PropType<IconifyIconCustomizeCallback>,
29+
required: false,
30+
},
2731
},
2832
async setup(props, { slots }) {
2933
const nuxtApp = useNuxtApp()
@@ -41,6 +45,7 @@ export default defineComponent({
4145
? { fontSize: Number.isNaN(+size) ? size : size + 'px' }
4246
: null
4347
})
48+
const customize = props.customize || options.customize
4449

4550
return () => h(
4651
component.value,
@@ -49,6 +54,7 @@ export default defineComponent({
4954
name: name.value,
5055
class: options.class,
5156
style: style.value,
57+
customize,
5258
},
5359
slots,
5460
)

src/runtime/components/svg.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,21 @@
11
import { Icon as Iconify, addIcon } from '@iconify/vue'
22
import { h } from 'vue'
3-
import type { NuxtIconRuntimeOptions } from '../../types'
3+
import type { PropType } from 'vue'
4+
import type { NuxtIconRuntimeOptions, IconifyIconCustomizeCallback } from '../../types'
45
import { loadIcon, useResolvedName } from './shared'
56
import { useAsyncData, useNuxtApp, defineComponent, useAppConfig } from '#imports'
67

78
export const NuxtIconSvg = /* @__PURE__ */ defineComponent({
89
name: 'NuxtIconSvg',
910
props: {
1011
name: {
11-
type: String,
12+
type: String as PropType<string>,
1213
required: true,
1314
},
15+
customize: {
16+
type: Function as PropType<IconifyIconCustomizeCallback>,
17+
required: false,
18+
},
1419
},
1520
async setup(props, { slots }) {
1621
const nuxt = useNuxtApp()
@@ -40,6 +45,8 @@ export const NuxtIconSvg = /* @__PURE__ */ defineComponent({
4045
icon: name.value,
4146
ssr: true,
4247
class: options.class,
48+
// Iconify uses `customise`, where we expose `customize` for consistency
49+
customise: props.customize,
4350
}, slots)
4451
},
4552
})

src/schema-types.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
// This file is generated from scripts/schema.ts
22

3+
import type { IconifyIconCustomizeCallback } from './types'
4+
35
export interface NuxtIconRuntimeOptions {
46
/**
57
* Icon Size
@@ -124,4 +126,11 @@ export interface NuxtIconRuntimeOptions {
124126
* @default "/api/_nuxt_icon"
125127
*/
126128
localApiEndpoint: string
129+
130+
/**
131+
* Callback to customize iconify data
132+
*
133+
* @default undefined
134+
*/
135+
customize: IconifyIconCustomizeCallback
127136
}

src/schema.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,4 +135,12 @@ export const schema = {
135135
tags: ['@studioIcon material-symbols:api'],
136136
},
137137
},
138+
customize: {
139+
$default: undefined,
140+
$schema: {
141+
title: 'Customize callback',
142+
description: 'Customize icon content (replace stroke-width, colors, etc...).',
143+
tags: ['@studioIcon material-symbols:edit'],
144+
},
145+
},
138146
} satisfies SchemaDefinition

src/types.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,13 @@ import type { NuxtIconRuntimeOptions } from './schema-types'
33

44
export type { NuxtIconRuntimeOptions }
55

6+
export type IconifyIconCustomizeCallback = (
7+
content: string,
8+
name?: string,
9+
prefix?: string,
10+
provider?: string
11+
) => string
12+
613
export interface NuxtIconRuntimeServerOptions {
714
/**
815
* List of pre-compiled CSS classnames to be used for server-side CSS icon rendering

0 commit comments

Comments
 (0)