Skip to content

Commit e639783

Browse files
committed
feat: Introduce a new set of SVG icons, update UnoCSS configuration, refactor icon integration and build scripts.
1 parent 86d2017 commit e639783

98 files changed

Lines changed: 704 additions & 1302 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

bun.lock

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

eslint.config.mjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import eslint from '@eslint/js'
44
import eslintPluginAstro from 'eslint-plugin-astro'
55
import tseslint from 'typescript-eslint'
66

7-
/** @type {import('eslint').Linter.FlatConfig[]} */
7+
/** @type {import('eslint').Linter.Config[]} */
88
const config = [
99
eslint.configs.recommended,
1010
...tseslint.configs.recommended,

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
"@eslint/js": "^9.39.2",
5454
"@ianvs/prettier-plugin-sort-imports": "^4.7.0",
5555
"@iconify-json/mingcute": "^1.2.6",
56+
"@types/node": "^25.0.3",
5657
"eslint": "^9.39.2",
5758
"eslint-plugin-astro": "^1.5.0",
5859
"fontmin": "^1.1.1",

packages/pure/components/basic/ThemeProvider.astro

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
</script>
2121

2222
<script>
23-
import { Icons } from '../../libs/icons'
2423
import { listenThemeChange } from '../../utils'
2524

2625
// Listen for theme change event
@@ -31,7 +30,9 @@
3130
const toast = document.createElement('div')
3231
toast.className =
3332
'animate fixed bottom-8 z-20 px-4 py-2 bg-muted text-foreground rounded-lg border shadow-lg flex items-center gap-2'
34-
toast.innerHTML = `<svg width='22' height='22' viewBox='0 0 24 24' fill='currentColor'>${Icons.info}</svg> <span>${message}</span>`
33+
// Inline info icon to avoid importing large Icons object
34+
const infoIcon = '<g fill="none"><path d="m12.593 23.258l-.011.002l-.071.035l-.02.004l-.014-.004l-.071-.035q-.016-.005-.024.005l-.004.01l-.017.428l.005.02l.01.013l.104.074l.015.004l.012-.004l.104-.074l.012-.016l.004-.017l-.017-.427q-.004-.016-.017-.018m.265-.113l-.013.002l-.185.093l-.01.01l-.003.011l.018.43l.005.012l.008.007l.201.093q.019.005.029-.008l.004-.014l-.034-.614q-.005-.018-.02-.022m-.715.002a.02.02 0 0 0-.027.006l-.006.014l-.034.614q.001.018.017.024l.015-.002l.201-.093l.01-.008l.004-.011l.017-.43l-.003-.012l-.01-.01z"/><path fill="currentColor" d="M12 2c5.523 0 10 4.477 10 10s-4.477 10-10 10S2 17.523 2 12S6.477 2 12 2m0 2a8 8 0 1 0 0 16a8 8 0 0 0 0-16m-.01 6c.558 0 1.01.452 1.01 1.01v5.124A1 1 0 0 1 12.5 18h-.49A1.01 1.01 0 0 1 11 16.99V12a1 1 0 1 1 0-2zM12 7a1 1 0 1 1 0 2a1 1 0 0 1 0-2"/></g>'
35+
toast.innerHTML = `<svg width='22' height='22' viewBox='0 0 24 24' fill='currentColor'>${infoIcon}</svg> <span>${message}</span>`
3536
document.body.appendChild(toast)
3637
setTimeout(() => {
3738
toast.remove()

packages/pure/components/user/Aside.astro

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
---
22
import { AstroError } from 'astro/errors'
33
4-
import { Icons } from '../../libs/icons'
54
import Icon from './Icon.astro'
65
76
const asideVariants = [
@@ -15,9 +14,7 @@ const asideVariants = [
1514
] as const
1615
const asideStyles = ['solid', 'card'] as const
1716
18-
type IconName = keyof typeof Icons
19-
20-
const defaultIcons: Record<(typeof asideVariants)[number], IconName> = {
17+
const defaultIcons: Record<(typeof asideVariants)[number], string> = {
2118
important: 'important',
2219
info: 'callout_info',
2320
note: 'note',
@@ -58,26 +55,19 @@ if (style && !asideStyles.includes(style)) {
5855
}
5956
6057
// Determine the icon to render
61-
let iconToRender: IconName | undefined
58+
let iconToRender: string | undefined = undefined
6259
let isEmoji = false
6360
6461
if (icon) {
6562
// Check if the provided icon is an emoji
6663
const emojiRegex = /\p{Emoji}/u // Unicode property escape for emoji
6764
if (emojiRegex.test(icon)) {
68-
iconToRender = undefined // Set to undefined if it\'s an emoji, handled by isEmoji
6965
isEmoji = true
70-
} else if (icon in Icons) {
71-
iconToRender = icon as IconName
7266
} else {
73-
// Fallback to default icon if provided icon name is not found in Icons
74-
console.warn(
75-
`Icon "${icon}" not found in icons.ts. Falling back to default icon for type "${type}".`
76-
)
77-
iconToRender = defaultIcons[type] as IconName
67+
iconToRender = icon
7868
}
7969
} else {
80-
iconToRender = defaultIcons[type] as IconName
70+
iconToRender = defaultIcons[type]
8171
}
8272
---
8373

packages/pure/components/user/Button.astro

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,6 @@
11
---
22
import { cn } from '../../utils'
33
4-
interface Props {
5-
as?: string
6-
title?: string
7-
href?: string
8-
variant?: 'button' | 'pill' | 'back' | 'ahead'
9-
class?: string
10-
}
11-
124
const { as: Tag = 'a', class: className, title, href, variant = 'button', ...props } = Astro.props
135
---
146

packages/pure/components/user/Icon.astro

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
11
---
2-
import { Icons } from '../../libs/icons'
2+
const icons = import.meta.glob<string>('/src/icons/*.svg', {
3+
query: '?raw',
4+
import: 'default',
5+
eager: true
6+
})
37
48
interface Props {
5-
name: keyof typeof Icons
9+
name: string
610
label?: string
711
color?: string
812
size?: string
@@ -12,20 +16,19 @@ interface Props {
1216
const { name, label, size = '1em', color, class: className, ...props } = Astro.props
1317
const a11yAttrs = label ? ({ 'aria-label': label } as const) : ({ 'aria-hidden': 'true' } as const)
1418
15-
let svgContent = Icons[name];
16-
let viewBox = '0 0 24 24'; // Default viewBox
19+
const svgContentRaw = icons[`/src/icons/${name}.svg`]
20+
let svgContent = ''
21+
let viewBox = '0 0 24 24'
1722
18-
// Check if the SVG content starts with an <svg> tag
19-
if (typeof svgContent === 'string' && svgContent.trim().startsWith('<svg')) {
20-
const viewBoxMatch = svgContent.match(/viewBox="([^"]*)"/);
23+
if (svgContentRaw) {
24+
svgContent = svgContentRaw
25+
const viewBoxMatch = svgContent.match(/viewBox="([^"]*)"/)
2126
if (viewBoxMatch && viewBoxMatch[1]) {
22-
viewBox = viewBoxMatch[1];
27+
viewBox = viewBoxMatch[1]
2328
}
24-
25-
// Extract content inside the <svg> tags
26-
const contentMatch = svgContent.match(/<svg[^>]*>(.*?)<\/svg>/s);
29+
const contentMatch = svgContent.match(/<svg[^>]*>(.*?)<\/svg>/s)
2730
if (contentMatch && contentMatch[1]) {
28-
svgContent = contentMatch[1];
31+
svgContent = contentMatch[1]
2932
}
3033
}
3134
---

0 commit comments

Comments
 (0)