|
1 | | -// Framework-neutral port of @antfu/design's `DisplayIconifyRemoteIcon`: |
2 | | -// https://github.com/antfu/design/blob/main/packages/design/components/Display/DisplayIconifyRemoteIcon.vue |
3 | | -// |
4 | | -// Resolves a devframe dock `icon` (an Iconify `collection:icon` id, e.g. |
5 | | -// `ph:git-branch-duotone`) to its live, sanitized SVG markup, fetched from the |
6 | | -// public `api.iconify.design` CDN. Unlike a UnoCSS `preset-icons` class, this |
7 | | -// needs no `@iconify-json/*` collection installed and no hand-maintained |
8 | | -// id -> class table, since any Iconify id just works, at the cost of a network |
9 | | -// round-trip on first render. We reuse @antfu/design's own fetcher, cache and |
10 | | -// sanitizer (`utils/iconify.ts`) rather than reimplementing them; only the id |
11 | | -// parsing and light/dark selection below are devframe-specific, mirroring the |
12 | | -// upstream Vue component's own `icon` prop parsing. Vue surfaces should render |
13 | | -// `DisplayIconifyRemoteIcon` directly instead of using this port. |
14 | | -import { getIconifySvg } from '@antfu/design/utils/iconify' |
| 1 | +import type { DevframeIcon } from 'devframe/types' |
| 2 | +import { getIconSource, getIconSvg } from '../packages/hub-ui/src/client/utils/icons' |
15 | 3 |
|
16 | | -// Mirrors DisplayIconifyRemoteIcon.vue's own `collection:icon` parse (with an |
17 | | -// optional `i-` prefix tolerated so a UnoCSS-style id also works). |
18 | | -const ICONIFY_ID = /^(?:i-)?([\w-]+):([\w-]+)$/ |
19 | | - |
20 | | -/** |
21 | | - * Resolve a dock icon (a `collection:icon` string, or a `{ light, dark }` |
22 | | - * pair whose `light` variant is fetched) to its sanitized SVG markup. |
23 | | - * |
24 | | - * Returns `undefined` when the id doesn't parse or the fetch fails, so the |
25 | | - * caller can fall back to a text initial. |
26 | | - * |
27 | | - * @example |
28 | | - * await dockIconSvg('ph:git-branch-duotone') // → '<svg ...>...</svg>' |
29 | | - */ |
30 | | -export async function dockIconSvg(name: string | { light: string, dark: string } | undefined): Promise<string | undefined> { |
31 | | - const id = typeof name === 'string' ? name : name?.light |
32 | | - if (!id) |
33 | | - return undefined |
34 | | - const match = id.match(ICONIFY_ID) |
35 | | - if (!match) |
| 4 | +/** Resolve the selected icon variant; failed remote requests leave the monogram fallback. */ |
| 5 | +export async function dockIconSvg(icon: DevframeIcon | undefined, dark = false): Promise<string | undefined> { |
| 6 | + if (!icon) |
36 | 7 | return undefined |
37 | 8 | try { |
38 | | - return await getIconifySvg(match[1]!, match[2]!) |
| 9 | + return await getIconSvg(getIconSource(icon, dark)) |
39 | 10 | } |
40 | 11 | catch { |
41 | | - // A failed fetch (offline / flaky CDN) degrades to the text-initial |
42 | | - // fallback, not a thrown error out of a render path. |
43 | 12 | return undefined |
44 | 13 | } |
45 | 14 | } |
0 commit comments