@qxs-bns/components 0.0.82 → 0.0.83

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 ADDED
@@ -0,0 +1,566 @@
1
+ # @qxs-bns/components
2
+
3
+ QXS Business System 组件库,基于 Vue 3 + TypeScript + Element Plus 构建的企业级组件库。
4
+
5
+ ## ✨ 特性
6
+
7
+ - 🎯 **企业级** - 专为企业级应用设计,提供丰富的业务组件
8
+ - 🔧 **二次封装** - 基于 Element Plus 进行增强,保持 API 一致性
9
+ - 📦 **按需加载** - 支持 Tree-shaking,减少打包体积
10
+ - 🎨 **主题定制** - 支持主题定制和暗黑模式
11
+ - 🌍 **国际化** - 内置国际化支持
12
+ - 📱 **响应式** - 移动端友好的响应式设计
13
+ - ♿ **无障碍** - 遵循 WAI-ARIA 标准
14
+ - 🎪 **TypeScript** - 完整的 TypeScript 类型定义
15
+
16
+ ## 📦 安装
17
+
18
+ ```bash
19
+ # npm
20
+ npm install @qxs-bns/components
21
+
22
+ # yarn
23
+ yarn add @qxs-bns/components
24
+
25
+ # pnpm
26
+ pnpm add @qxs-bns/components
27
+ ```
28
+
29
+ ## 🚀 快速开始
30
+
31
+ ### 完整引入
32
+
33
+ ```typescript
34
+ import { createApp } from 'vue'
35
+ import QxsComponents from '@qxs-bns/components'
36
+ import '@qxs-bns/components/dist/index.css'
37
+ import App from './App.vue'
38
+
39
+ const app = createApp(App)
40
+ app.use(QxsComponents)
41
+ app.mount('#app')
42
+ ```
43
+
44
+ ### 按需引入
45
+
46
+ ```vue
47
+ <template>
48
+ <QxsButton type="primary">按钮</QxsButton>
49
+ <QxsDataChart :data="chartData" show-type-name="bar" />
50
+ </template>
51
+
52
+ <script setup>
53
+ import { QxsButton, QxsDataChart } from '@qxs-bns/components'
54
+
55
+ const chartData = {
56
+ data: [
57
+ { name: '一月', value: 100 },
58
+ { name: '二月', value: 200 }
59
+ ]
60
+ }
61
+ </script>
62
+ ```
63
+
64
+ ## 🏗️ 项目结构
65
+
66
+ ```
67
+ packages/components/
68
+ ├── src/ # 源码目录
69
+ │ ├── button/ # 按钮组件
70
+ │ │ ├── src/ # 组件源码
71
+ │ │ │ └── button.vue
72
+ │ │ ├── style/ # 组件样式
73
+ │ │ │ └── index.scss
74
+ │ │ └── index.ts # 组件入口
75
+ │ ├── data-chart/ # 数据图表组件
76
+ │ ├── utils/ # 工具函数
77
+ │ ├── constants/ # 常量定义
78
+ │ └── index.ts # 总入口
79
+ ├── dist/ # 构建产物
80
+ ├── docs/ # 组件文档
81
+ └── package.json
82
+ ```
83
+
84
+ ## 🧩 核心组件
85
+
86
+ ### 基础组件
87
+
88
+ | 组件名 | 说明 | 文档 |
89
+ |--------|------|------|
90
+ | Button | 按钮组件 | [查看文档](./src/button/README.md) |
91
+ | Input | 输入框组件 | [查看文档](./src/input/README.md) |
92
+ | Select | 选择器组件 | [查看文档](./src/select/README.md) |
93
+
94
+ ### 数据展示
95
+
96
+ | 组件名 | 说明 | 文档 |
97
+ |--------|------|------|
98
+ | DataChart | 数据图表组件 | [查看文档](./src/data-chart/README.md) |
99
+ | Table | 表格组件 | [查看文档](./src/table/README.md) |
100
+ | Card | 卡片组件 | [查看文档](./src/card/README.md) |
101
+
102
+ ### 导航组件
103
+
104
+ | 组件名 | 说明 | 文档 |
105
+ |--------|------|------|
106
+ | Menu | 菜单组件 | [查看文档](./src/menu/README.md) |
107
+ | Breadcrumb | 面包屑组件 | [查看文档](./src/breadcrumb/README.md) |
108
+ | Pagination | 分页组件 | [查看文档](./src/pagination/README.md) |
109
+
110
+ ### 反馈组件
111
+
112
+ | 组件名 | 说明 | 文档 |
113
+ |--------|------|------|
114
+ | Dialog | 对话框组件 | [查看文档](./src/dialog/README.md) |
115
+ | Message | 消息提示组件 | [查看文档](./src/message/README.md) |
116
+ | Loading | 加载组件 | [查看文档](./src/loading/README.md) |
117
+
118
+ ## 🛠️ 开发指南
119
+
120
+ ### 环境要求
121
+
122
+ - Node.js >= 16
123
+ - pnpm >= 7
124
+ - Vue >= 3.3
125
+ - TypeScript >= 4.9
126
+
127
+ ### 本地开发
128
+
129
+ ```bash
130
+ # 克隆项目
131
+ git clone <repository-url>
132
+
133
+ # 安装依赖
134
+ pnpm install
135
+
136
+ # 启动开发服务器
137
+ pnpm dev
138
+
139
+ # 构建组件库
140
+ pnpm build
141
+
142
+ # 运行测试
143
+ pnpm test
144
+ ```
145
+
146
+ ### 创建新组件
147
+
148
+ 1. **创建组件目录**
149
+ ```bash
150
+ mkdir src/my-component
151
+ cd src/my-component
152
+ ```
153
+
154
+ 2. **创建必要文件**
155
+ ```
156
+ my-component/
157
+ ├── src/
158
+ │ └── my-component.vue
159
+ ├── style/
160
+ │ └── index.scss
161
+ ├── index.ts
162
+ └── README.md
163
+ ```
164
+
165
+ 3. **组件模板**
166
+ ```vue
167
+ <!-- src/my-component.vue -->
168
+ <template>
169
+ <div :class="ns.b()">
170
+ <slot />
171
+ </div>
172
+ </template>
173
+
174
+ <script setup lang="ts">
175
+ import { useNamespace } from '@qxs-bns/hooks'
176
+
177
+ defineOptions({
178
+ name: 'QxsMyComponent'
179
+ })
180
+
181
+ const ns = useNamespace('my-component')
182
+ </script>
183
+ ```
184
+
185
+ 4. **样式文件**
186
+ ```scss
187
+ // style/index.scss
188
+ @use 'sass:map';
189
+ @use '@qxs-bns/theme-chalk/src/mixins/mixins' as *;
190
+ @use '@qxs-bns/theme-chalk/src/common/var' as *;
191
+
192
+ @include b(my-component) {
193
+ // 组件样式
194
+ }
195
+ ```
196
+
197
+ 5. **入口文件**
198
+ ```typescript
199
+ // index.ts
200
+ import { withInstall } from '@qxs-bns/utils'
201
+ import MyComponent from './src/my-component.vue'
202
+
203
+ export const QxsMyComponent = withInstall(MyComponent)
204
+ export default QxsMyComponent
205
+
206
+ export * from './src/my-component'
207
+ ```
208
+
209
+ ## 📋 开发规范
210
+
211
+ ### 组件命名规范
212
+
213
+ #### Element Plus 二次封装组件
214
+ - **组件名**:保持与 Element Plus 一致,添加 `Qxs` 前缀
215
+ - **文件名**:使用 kebab-case
216
+ - **样式类名**:使用 Element Plus 的 BEM 命名规范
217
+
218
+ ```typescript
219
+ // ✅ 正确示例
220
+ export const QxsButton = withInstall(Button)
221
+ export const QxsInput = withInstall(Input)
222
+
223
+ // ❌ 错误示例
224
+ export const QxsBtn = withInstall(Button)
225
+ export const QxsInputField = withInstall(Input)
226
+ ```
227
+
228
+ #### 自定义组件
229
+ - **组件名**:使用 `@qxs-bns/hooks` 中的 `useNamespace` 函数
230
+ - **文件名**:使用 kebab-case
231
+ - **样式类名**:使用 BEM 命名规范
232
+
233
+ ```vue
234
+ <script setup lang="ts">
235
+ import { useNamespace } from '@qxs-bns/hooks'
236
+
237
+ defineOptions({
238
+ name: 'QxsDataChart' // 组件名使用 PascalCase
239
+ })
240
+
241
+ const ns = useNamespace('data-chart') // 使用 kebab-case
242
+ </script>
243
+
244
+ <template>
245
+ <div :class="ns.b()"> <!-- 生成 .qxs-data-chart -->
246
+ <div :class="ns.e('header')"> <!-- 生成 .qxs-data-chart__header -->
247
+ <div :class="ns.em('header', 'title')"> <!-- 生成 .qxs-data-chart__header--title -->
248
+ ```
249
+
250
+ ### Props 设计规范
251
+
252
+ ```typescript
253
+ // 使用 TypeScript 接口定义 Props
254
+ interface ButtonProps {
255
+ /**
256
+ * 按钮类型
257
+ * @default 'default'
258
+ */
259
+ type?: 'primary' | 'success' | 'warning' | 'danger' | 'info' | 'default'
260
+
261
+ /**
262
+ * 按钮尺寸
263
+ * @default 'default'
264
+ */
265
+ size?: 'large' | 'default' | 'small'
266
+
267
+ /**
268
+ * 是否禁用
269
+ * @default false
270
+ */
271
+ disabled?: boolean
272
+
273
+ /**
274
+ * 是否加载中
275
+ * @default false
276
+ */
277
+ loading?: boolean
278
+ }
279
+
280
+ // 使用 withDefaults 设置默认值
281
+ const props = withDefaults(defineProps<ButtonProps>(), {
282
+ type: 'default',
283
+ size: 'default',
284
+ disabled: false,
285
+ loading: false
286
+ })
287
+ ```
288
+
289
+ ### 事件设计规范
290
+
291
+ ```typescript
292
+ // 定义事件类型
293
+ interface ButtonEmits {
294
+ /**
295
+ * 点击事件
296
+ * @param event 原生事件对象
297
+ */
298
+ click: [event: MouseEvent]
299
+
300
+ /**
301
+ * 焦点事件
302
+ * @param event 原生事件对象
303
+ */
304
+ focus: [event: FocusEvent]
305
+
306
+ /**
307
+ * 失焦事件
308
+ * @param event 原生事件对象
309
+ */
310
+ blur: [event: FocusEvent]
311
+ }
312
+
313
+ const emit = defineEmits<ButtonEmits>()
314
+
315
+ // 事件处理
316
+ const handleClick = (event: MouseEvent) => {
317
+ if (props.disabled || props.loading) return
318
+ emit('click', event)
319
+ }
320
+ ```
321
+
322
+ ### 样式规范
323
+
324
+ #### SCSS 变量使用
325
+
326
+ ```scss
327
+ // 使用主题变量
328
+ @use '@qxs-bns/theme-chalk/src/common/var' as *;
329
+
330
+ @include b(button) {
331
+ // 使用 CSS 变量
332
+ background-color: var(#{getCssVarName('button', 'bg-color')});
333
+ border-color: var(#{getCssVarName('button', 'border-color')});
334
+ color: var(#{getCssVarName('button', 'text-color')});
335
+
336
+ // 状态样式
337
+ @include when(disabled) {
338
+ opacity: var(#{getCssVarName('disabled-opacity')});
339
+ cursor: not-allowed;
340
+ }
341
+
342
+ // 修饰符样式
343
+ @include m(primary) {
344
+ background-color: var(#{getCssVarName('color-primary')});
345
+ border-color: var(#{getCssVarName('color-primary')});
346
+ }
347
+ }
348
+ ```
349
+
350
+ #### BEM 命名规范
351
+
352
+ ```scss
353
+ // Block(块)
354
+ .qxs-button { }
355
+
356
+ // Element(元素)
357
+ .qxs-button__icon { }
358
+ .qxs-button__text { }
359
+
360
+ // Modifier(修饰符)
361
+ .qxs-button--primary { }
362
+ .qxs-button--large { }
363
+
364
+ // State(状态)
365
+ .qxs-button.is-disabled { }
366
+ .qxs-button.is-loading { }
367
+ ```
368
+
369
+ ## 🧪 测试规范
370
+
371
+ ### 单元测试
372
+
373
+ ```typescript
374
+ // button.test.ts
375
+ import { mount } from '@vue/test-utils'
376
+ import { describe, it, expect } from 'vitest'
377
+ import Button from '../src/button.vue'
378
+
379
+ describe('Button', () => {
380
+ it('should render correctly', () => {
381
+ const wrapper = mount(Button, {
382
+ props: { type: 'primary' },
383
+ slots: { default: 'Click me' }
384
+ })
385
+
386
+ expect(wrapper.classes()).toContain('qxs-button--primary')
387
+ expect(wrapper.text()).toBe('Click me')
388
+ })
389
+
390
+ it('should emit click event', async () => {
391
+ const wrapper = mount(Button)
392
+ await wrapper.trigger('click')
393
+
394
+ expect(wrapper.emitted('click')).toHaveLength(1)
395
+ })
396
+
397
+ it('should not emit click when disabled', async () => {
398
+ const wrapper = mount(Button, {
399
+ props: { disabled: true }
400
+ })
401
+ await wrapper.trigger('click')
402
+
403
+ expect(wrapper.emitted('click')).toBeUndefined()
404
+ })
405
+ })
406
+ ```
407
+
408
+ ### 组件快照测试
409
+
410
+ ```typescript
411
+ // button.snap.test.ts
412
+ import { mount } from '@vue/test-utils'
413
+ import { describe, it, expect } from 'vitest'
414
+ import Button from '../src/button.vue'
415
+
416
+ describe('Button Snapshots', () => {
417
+ it('should match snapshot with different types', () => {
418
+ const types = ['primary', 'success', 'warning', 'danger', 'info']
419
+
420
+ types.forEach(type => {
421
+ const wrapper = mount(Button, {
422
+ props: { type },
423
+ slots: { default: 'Button' }
424
+ })
425
+ expect(wrapper.html()).toMatchSnapshot(`button-${type}`)
426
+ })
427
+ })
428
+ })
429
+ ```
430
+
431
+ ## 📖 文档规范
432
+
433
+ ### 组件文档模板
434
+
435
+ 每个组件都应该包含完整的 README.md 文档:
436
+
437
+ ```markdown
438
+ # Button 按钮
439
+
440
+ 常用的操作按钮。
441
+
442
+ ## 基础用法
443
+
444
+ 基础的按钮用法。
445
+
446
+ :::demo 使用 `type`、`plain`、`round` 和 `circle` 属性来定义 Button 的样式。
447
+
448
+ button/basic
449
+
450
+ :::
451
+
452
+ ## API
453
+
454
+ ### Button Attributes
455
+
456
+ | 属性名 | 说明 | 类型 | 可选值 | 默认值 |
457
+ |--------|------|------|--------|--------|
458
+ | type | 类型 | string | primary / success / warning / danger / info / text | — |
459
+ | size | 尺寸 | string | large / small / mini | — |
460
+ | disabled | 是否禁用状态 | boolean | — | false |
461
+
462
+ ### Button Events
463
+
464
+ | 事件名 | 说明 | 参数 |
465
+ |--------|------|------|
466
+ | click | 点击时触发 | (event: Event) |
467
+
468
+ ### Button Slots
469
+
470
+ | 插槽名 | 说明 |
471
+ |--------|------|
472
+ | — | 默认插槽 |
473
+ ```
474
+
475
+ ## 🤝 贡献指南
476
+
477
+ ### 提交规范
478
+
479
+ 使用 [Conventional Commits](https://conventionalcommits.org/) 规范:
480
+
481
+ ```bash
482
+ # 新功能
483
+ feat(button): add loading state support
484
+
485
+ # 修复 bug
486
+ fix(data-chart): resolve chart rendering issue
487
+
488
+ # 文档更新
489
+ docs(readme): update installation guide
490
+
491
+ # 样式调整
492
+ style(button): adjust padding and margin
493
+
494
+ # 重构代码
495
+ refactor(utils): optimize namespace function
496
+
497
+ # 性能优化
498
+ perf(table): improve virtual scrolling performance
499
+
500
+ # 测试相关
501
+ test(button): add unit tests for disabled state
502
+ ```
503
+
504
+ ### 开发流程
505
+
506
+ 1. **Fork 项目**
507
+ 2. **创建功能分支**
508
+ ```bash
509
+ git checkout -b feat/new-component
510
+ ```
511
+ 3. **开发组件**
512
+ - 编写组件代码
513
+ - 添加单元测试
514
+ - 编写文档
515
+ 4. **提交代码**
516
+ ```bash
517
+ git add .
518
+ git commit -m "feat(new-component): add new component"
519
+ ```
520
+ 5. **推送分支**
521
+ ```bash
522
+ git push origin feat/new-component
523
+ ```
524
+ 6. **创建 Pull Request**
525
+
526
+ ### 代码审查清单
527
+
528
+ - [ ] 组件命名符合规范
529
+ - [ ] TypeScript 类型定义完整
530
+ - [ ] 单元测试覆盖率 > 80%
531
+ - [ ] 文档完整且示例可运行
532
+ - [ ] 样式符合设计规范
533
+ - [ ] 无障碍性支持
534
+ - [ ] 国际化支持
535
+
536
+ ## 🔧 常见问题
537
+
538
+ ### Q: 如何自定义主题?
539
+
540
+ A: 通过 CSS 变量覆盖默认主题:
541
+
542
+ ```css
543
+ :root {
544
+ --qxs-color-primary: #409eff;
545
+ --qxs-color-success: #67c23a;
546
+ --qxs-color-warning: #e6a23c;
547
+ --qxs-color-danger: #f56c6c;
548
+ --qxs-color-info: #909399;
549
+ }
550
+ ```
551
+
552
+ ### Q: 如何按需引入组件?
553
+
554
+ A: 使用 ES6 模块语法:
555
+
556
+ ```typescript
557
+ import { QxsButton, QxsInput } from '@qxs-bns/components'
558
+ ```
559
+
560
+ ### Q: 如何贡献新组件?
561
+
562
+ A: 请参考 [贡献指南](#🤝-贡献指南) 部分。
563
+
564
+ ## 📄 许可证
565
+
566
+ MIT License - 详见 [LICENSE](./LICENSE) 文件。
@@ -1,2 +1,2 @@
1
- var r="0.0.82";export{r as version};
1
+ var r="0.0.83";export{r as version};
2
2
  //# sourceMappingURL=package.json.mjs.map
@@ -1,2 +1,2 @@
1
- import{defineComponent as e,useAttrs as t,computed as i,ref as s,createElementBlock as l,openBlock as n,Fragment as r,createCommentVNode as o,createBlock as u,resolveDynamicComponent as a,normalizeStyle as c,normalizeClass as f,unref as v,createElementVNode as p,createVNode as y}from"vue";import{Icon as d}from"../../../node_modules/.pnpm/@iconify_vue@5.0.0_vue@3.5.18_typescript@5.9.2_/node_modules/@iconify/vue/dist/iconify.mjs";import{useNamespace as h}from"@qxs-bns/hooks";const m=["src"],g={"aria-hidden":"true",class:"size-inherit shrink-0"},k=["xlink:href"];var b=e({name:"QxsIcon",__name:"icon",props:{icon:{type:null,required:!0},flip:{type:null,required:!1,default:""},rotate:{type:Number,required:!1,default:0},color:{type:String,required:!1},size:{type:[String,Number],required:!1},localIconPrefix:{type:String,required:!1,default:"icon-"},fallback:{type:String,required:!1},loading:{type:String,required:!1}},setup(e){const b=t(),$=h("icon"),z=i(()=>"object"==typeof e.icon||"function"==typeof e.icon),S=i(()=>{if(z.value)return"component";const t=e.icon;return/^https?:\/\//.test(t)||(/^\.{1,2}\//.test(i=t)||i.startsWith("/")||i.includes("/"))?"img":/^i-[^:]+:[^:]+/.test(t)?"unocss":t.startsWith("i-")&&!t.includes(":")?"css":t.includes(":")&&!t.startsWith("i-")?"iconify":/^[\w-]+$/.test(t)&&!t.startsWith("i-")?"svg":"css";var i}),q=i(()=>{if(z.value)return"";const t=e.icon;return"img"===S.value||"unocss"===S.value||S.value,t}),x=i(()=>"css"===S.value?q.value.split(" ").filter(e=>e.trim()):[]);function _(e){return e?"number"==typeof e||/^\d+(?:\.\d+)?$/.test(e)?`${e}px`:e:""}const j=i(()=>{const t=[];switch(e.flip){case"horizontal":t.push("rotateY(180deg)");break;case"vertical":t.push("rotateX(180deg)");break;case"both":t.push("rotateX(180deg)"),t.push("rotateY(180deg)")}e.rotate&&t.push(`rotate(${e.rotate%360}deg)`);let i=`${e.color?`color: ${e.color};`:""}${e.size?`font-size: ${_(e.size)};`:""}${t.length?`transform: ${t.join(" ")};`:""}`;const s=b.style;if(s)if("string"==typeof s)i+=s;else if("object"==typeof s){i+=Object.entries(s).map(([e,t])=>`${e.replace(/([A-Z])/g,"-$1").toLowerCase()}: ${t};`).join("")}return i}),w=s(!0),I=s(!1);function W(){w.value=!1,I.value=!1}function C(){w.value=!1,I.value=!0}return(e,t)=>(n(),l(r,null,[o(" Vue组件 "),"component"===S.value?(n(),u(a(e.icon),{key:0,class:f([[v($).b()],"size-inherit shrink-0"]),style:c([j.value])},null,8,["class","style"])):"unocss"===S.value?(n(),l(r,{key:1},[o(" UnoCSS图标 "),p("i",{class:f([v($).b(),q.value]),style:c([j.value])},null,6)],2112)):"css"===S.value?(n(),l(r,{key:2},[o(" CSS类图标 "),p("i",{class:f(["size-inherit shrink-0",[v($).b(),...x.value]]),style:c([j.value])},null,6)],2112)):"iconify"===S.value?(n(),l(r,{key:3},[o(" Iconify图标 "),y(v(d),{class:f(["size-inherit shrink-0",[v($).b()]]),icon:q.value,style:c([j.value])},null,8,["icon","class","style"])],2112)):"img"===S.value?(n(),l(r,{key:4},[o(" 图片 "),o(" 加载中状态 "),w.value&&e.loading?(n(),l("i",{key:0,class:f(e.loading)},null,2)):I.value&&e.fallback?(n(),l(r,{key:1},[o(" 错误状态 "),p("i",{class:f(e.fallback)},null,2)],2112)):o("v-if",!0),o(" 图片本体 "),p("img",{src:q.value,class:f(["size-inherit shrink-0",[v($).b()]]),style:c([j.value,{width:e.size?_(e.size):"auto",height:"auto"}]),onLoad:W,onError:C},null,46,m)],64)):q.value?(n(),l(r,{key:5},[o(" SVG Sprite "),p("i",{class:f([v($).b()]),style:c([j.value])},[(n(),l("svg",g,[p("use",{"xlink:href":`#${e.localIconPrefix}${q.value}`},null,8,k)]))],6)],2112)):o("v-if",!0)],2112))}});export{b as default};
1
+ import{defineComponent as e,useAttrs as t,computed as i,ref as s,createElementBlock as l,openBlock as n,Fragment as r,createCommentVNode as o,createBlock as a,resolveDynamicComponent as u,mergeProps as c,unref as f,createElementVNode as v,createVNode as p,normalizeClass as y,normalizeStyle as d}from"vue";import{Icon as h}from"../../../node_modules/.pnpm/@iconify_vue@5.0.0_vue@3.5.18_typescript@5.9.2_/node_modules/@iconify/vue/dist/iconify.mjs";import{useNamespace as m}from"@qxs-bns/hooks";const g=["src"],k={"aria-hidden":"true",class:"size-inherit shrink-0"},b=["xlink:href"];var $=e({name:"QxsIcon",__name:"icon",props:{icon:{type:null,required:!0},flip:{type:null,required:!1,default:""},rotate:{type:Number,required:!1,default:0},color:{type:String,required:!1},size:{type:[String,Number],required:!1},localIconPrefix:{type:String,required:!1,default:"icon-"},fallback:{type:String,required:!1},loading:{type:String,required:!1}},setup(e){const $=t(),z=m("icon"),S=i(()=>"object"==typeof e.icon||"function"==typeof e.icon),q=i(()=>{if(S.value)return"component";const t=e.icon;return/^https?:\/\//.test(t)||(/^\.{1,2}\//.test(i=t)||i.startsWith("/")||i.includes("/"))?"img":/^i-[^:]+:[^:]+/.test(t)?"unocss":t.startsWith("i-")&&!t.includes(":")?"css":t.includes(":")&&!t.startsWith("i-")?"iconify":/^[\w-]+$/.test(t)&&!t.startsWith("i-")?"svg":"css";var i}),x=i(()=>{if(S.value)return"";const t=e.icon;return"img"===q.value||"unocss"===q.value||q.value,t}),_=i(()=>"css"===q.value?x.value.split(" ").filter(e=>e.trim()):[]);function j(e){return e?"number"==typeof e||/^\d+(?:\.\d+)?$/.test(e)?`${e}px`:e:""}const w=i(()=>{const t=[];switch(e.flip){case"horizontal":t.push("rotateY(180deg)");break;case"vertical":t.push("rotateX(180deg)");break;case"both":t.push("rotateX(180deg)"),t.push("rotateY(180deg)")}e.rotate&&t.push(`rotate(${e.rotate%360}deg)`);let i=`${e.color?`color: ${e.color};`:""}${e.size?`font-size: ${j(e.size)};`:""}${t.length?`transform: ${t.join(" ")};`:""}`;const s=$.style;if(s)if("string"==typeof s)i+=s;else if("object"==typeof s){i+=Object.entries(s).map(([e,t])=>`${e.replace(/([A-Z])/g,"-$1").toLowerCase()}: ${t};`).join("")}return i}),I=s(!0),W=s(!1);function C(){I.value=!1,W.value=!1}function L(){I.value=!1,W.value=!0}return(e,t)=>(n(),l(r,null,[o(" Vue组件 "),"component"===q.value?(n(),a(u(e.icon),c({key:0,class:[f(z).b()],style:[w.value]},f($),{class:"size-inherit shrink-0"}),null,16,["class","style"])):"unocss"===q.value?(n(),l(r,{key:1},[o(" UnoCSS图标 "),v("i",c({class:[f(z).b(),x.value],style:[w.value]},f($)),null,16)],2112)):"css"===q.value?(n(),l(r,{key:2},[o(" CSS类图标 "),v("i",c({class:["size-inherit shrink-0",[f(z).b(),..._.value]],style:[w.value]},f($)),null,16)],2112)):"iconify"===q.value?(n(),l(r,{key:3},[o(" Iconify图标 "),p(f(h),c({class:["size-inherit shrink-0",[f(z).b()]],icon:x.value,style:[w.value]},f($)),null,16,["icon","class","style"])],2112)):"img"===q.value?(n(),l(r,{key:4},[o(" 图片 "),o(" 加载中状态 "),I.value&&e.loading?(n(),l("i",{key:0,class:y(e.loading)},null,2)):W.value&&e.fallback?(n(),l(r,{key:1},[o(" 错误状态 "),v("i",{class:y(e.fallback)},null,2)],2112)):o("v-if",!0),o(" 图片本体 "),v("img",c({src:x.value,class:"size-inherit shrink-0"},f($),{class:[f(z).b()],style:[w.value,{width:e.size?j(e.size):"auto",height:"auto"}],onLoad:C,onError:L}),null,16,g)],64)):x.value?(n(),l(r,{key:5},[o(" SVG Sprite "),v("i",{class:y([f(z).b()]),style:d([w.value])},[(n(),l("svg",k,[v("use",{"xlink:href":`#${e.localIconPrefix}${x.value}`},null,8,b)]))],6)],2112)):o("v-if",!0)],2112))}});export{$ as default};
2
2
  //# sourceMappingURL=icon.vue.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"icon.vue.mjs","sources":["../../../../../../packages/components/src/icon/src/icon.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { Component, CSSProperties } from 'vue'\nimport { Icon } from '@iconify/vue'\nimport { useNamespace } from '@qxs-bns/hooks'\nimport { computed, ref, useAttrs } from 'vue'\n\ndefineOptions({\n name: 'QxsIcon',\n})\n\nconst {\n icon,\n flip = '',\n rotate = 0,\n color,\n size,\n localIconPrefix = 'icon-',\n fallback,\n loading,\n} = defineProps<PropsType>()\n\nconst attrs = useAttrs()\n\nconst ns = useNamespace('icon')\n\nexport interface PropsType {\n icon: string | Component\n flip?: 'horizontal' | 'vertical' | 'both' | '' | undefined\n rotate?: number\n color?: string\n size?: string | number\n localIconPrefix?: string\n // 新增功能:支持图片URL\n fallback?: string // 加载失败时的备用图标\n loading?: string // 加载中显示的图标\n}\n\nconst isComponentName = computed(() => typeof icon === 'object' || typeof icon === 'function')\n\nconst outputType = computed(() => {\n if (isComponentName.value) {\n return 'component'\n }\n\n const iconStr = icon as string\n\n // 检测是否为图片URL或路径\n const hasPathFeatures = (str: string) => {\n return /^\\.{1,2}\\//.test(str) || str.startsWith('/') || str.includes('/')\n }\n if (/^https?:\\/\\//.test(iconStr) || hasPathFeatures(iconStr)) {\n return 'img'\n }\n\n // 检测UnoCSS图标格式 (i-[provider]:[name])\n if (/^i-[^:]+:[^:]+/.test(iconStr)) {\n return 'unocss'\n }\n\n // 检测以i-开头的自定义CSS类图标(不包含冒号)\n if (iconStr.startsWith('i-') && !iconStr.includes(':')) {\n return 'css'\n }\n\n // 检测Iconify格式 (provider:name,但不以i-开头)\n if (iconStr.includes(':') && !iconStr.startsWith('i-')) {\n return 'iconify'\n }\n\n // 检测SVG sprite(单个单词,不包含空格和特殊字符,且不以i-开头)\n if (/^[\\w-]+$/.test(iconStr) && !iconStr.startsWith('i-')) {\n return 'svg'\n }\n\n // 其他情况都视为CSS类图标(包括多个类名等)\n return 'css'\n})\n\nconst outputName = computed(() => {\n if (isComponentName.value) {\n return ''\n }\n\n const iconStr = icon as string\n\n // 对于图片类型,直接返回URL\n if (outputType.value === 'img') {\n return iconStr\n }\n\n // 对于UnoCSS图标,直接返回类名\n if (outputType.value === 'unocss') {\n return iconStr\n }\n\n // 对于传统CSS图标,处理多个类名的情况\n if (outputType.value === 'css') {\n return iconStr\n }\n\n // 其他情况直接返回\n return iconStr\n})\n\n// 对于CSS类图标,将字符串拆分为类名数组\nconst cssClasses = computed(() => {\n if (outputType.value === 'css') {\n return outputName.value.split(' ').filter(cls => cls.trim())\n }\n return []\n})\n\n// 用正则匹配 size 是不是 number 值,再判断是否有 px 结尾的单位,没有则拼接\nfunction formatSize(size: string | number | undefined): string {\n if (!size) {\n return ''\n }\n\n // 如果是数字,直接添加 px\n if (typeof size === 'number') {\n return `${size}px`\n }\n\n // 如果是纯数字字符串,添加 px\n if (/^\\d+(?:\\.\\d+)?$/.test(size)) {\n return `${size}px`\n }\n\n // 如果已经有单位(px、em、rem等)或者不是纯数字,直接返回\n return size\n}\n\n// 统一的样式计算属性,适用于所有图标类型\n// 包含颜色、尺寸和变换(旋转、翻转)\n// Iconify 图标通过外层 i 标签应用这些样式\nconst style = computed(() => {\n const transform = [] as string[]\n switch (flip) {\n case 'horizontal':\n transform.push('rotateY(180deg)')\n break\n case 'vertical':\n transform.push('rotateX(180deg)')\n break\n case 'both':\n transform.push('rotateX(180deg)')\n transform.push('rotateY(180deg)')\n break\n // 对于 '' 和 undefined,不做任何处理\n }\n if (rotate) {\n transform.push(`rotate(${rotate % 360}deg)`)\n }\n\n // 构建基础样式\n let baseStyle = `${color ? `color: ${color};` : ''}${size ? `font-size: ${formatSize(size)};` : ''}${transform.length ? `transform: ${transform.join(' ')};` : ''}`\n\n // 拼接 attrs.style\n const attrsStyle = attrs.style\n if (attrsStyle) {\n if (typeof attrsStyle === 'string') {\n baseStyle += attrsStyle\n }\n else if (typeof attrsStyle === 'object') {\n // 处理对象形式的样式\n const styleEntries = Object.entries(attrsStyle as CSSProperties)\n const styleString = styleEntries\n .map(([key, value]) => `${key.replace(/([A-Z])/g, '-$1').toLowerCase()}: ${value};`)\n .join('')\n baseStyle += styleString\n }\n }\n\n return baseStyle\n})\n\n// 图片加载状态管理\nconst imageLoading = ref(true)\nconst imageError = ref(false)\n\nfunction handleImageLoad() {\n imageLoading.value = false\n imageError.value = false\n}\n\nfunction handleImageError() {\n imageLoading.value = false\n imageError.value = true\n}\n</script>\n\n<template>\n <!-- Vue组件 -->\n <component\n :is=\"icon\"\n v-if=\"outputType === 'component'\"\n :class=\"[ns.b()]\"\n :style=\"[style]\"\n class=\"size-inherit shrink-0\"\n />\n\n <!-- UnoCSS图标 -->\n <i\n v-else-if=\"outputType === 'unocss'\"\n :class=\"[ns.b(), outputName]\"\n :style=\"[style]\"\n />\n\n <!-- CSS类图标 -->\n <i\n v-else-if=\"outputType === 'css'\"\n class=\"size-inherit shrink-0\"\n :class=\"[ns.b(), ...cssClasses]\"\n :style=\"[style]\"\n />\n\n <!-- Iconify图标 -->\n <Icon\n v-else-if=\"outputType === 'iconify'\"\n class=\"size-inherit shrink-0\"\n :icon=\"outputName\"\n :class=\"[ns.b()]\"\n :style=\"[style]\"\n />\n\n <!-- 图片 -->\n <template v-else-if=\"outputType === 'img'\">\n <!-- 加载中状态 -->\n <i\n v-if=\"imageLoading && loading\"\n :class=\"loading\"\n />\n <!-- 错误状态 -->\n <i\n v-else-if=\"imageError && fallback\"\n :class=\"fallback\"\n />\n <!-- 图片本体 -->\n <img\n :src=\"outputName\"\n class=\"size-inherit shrink-0\"\n :class=\"[ns.b()]\"\n :style=\"[style, { width: size ? formatSize(size) : 'auto', height: 'auto' }]\"\n @load=\"handleImageLoad\"\n @error=\"handleImageError\"\n >\n </template>\n\n <!-- SVG Sprite -->\n <i\n v-else-if=\"outputName\"\n :class=\"[ns.b()]\"\n :style=\"[style]\"\n >\n <svg\n aria-hidden=\"true\"\n class=\"size-inherit shrink-0\"\n >\n <use :xlink:href=\"`#${localIconPrefix}${outputName}`\" />\n </svg>\n </i>\n</template>\n"],"names":["attrs","useAttrs","ns","useNamespace","isComponentName","computed","__props","icon","outputType","value","iconStr","test","str","startsWith","includes","outputName","cssClasses","split","filter","cls","trim","formatSize","size","style","transform","flip","push","rotate","baseStyle","color","length","join","attrsStyle","Object","entries","map","key","replace","toLowerCase","imageLoading","ref","imageError","handleImageLoad","handleImageError","_createCommentVNode","_openBlock","_createBlock","_resolveDynamicComponent","class","_normalizeClass","_unref","b","_createElementBlock","_Fragment","_createElementVNode","_createVNode","Icon","loading","fallback","src","width","height","onLoad","onError","_hoisted_2","localIconPrefix"],"mappings":"o6BAqBA,MAAMA,EAAQC,IAERC,EAAKC,EAAa,QAclBC,EAAkBC,EAAS,IAAsB,iBAATC,EAAAC,MAAqC,mBAATD,EAAAC,MAEpEC,EAAaH,EAAS,KAC1B,GAAID,EAAgBK,MAClB,MAAO,YAGT,MAAMC,EAAUJ,EAAAC,KAMhB,MAAI,eAAeI,KAAKD,KAFf,aAAaC,KADGC,EAG2BF,IAFjBE,EAAIC,WAAW,MAAQD,EAAIE,SAAS,MAG9D,MAIL,iBAAiBH,KAAKD,GACjB,SAILA,EAAQG,WAAW,QAAUH,EAAQI,SAAS,KACzC,MAILJ,EAAQI,SAAS,OAASJ,EAAQG,WAAW,MACxC,UAIL,WAAWF,KAAKD,KAAaA,EAAQG,WAAW,MAC3C,MAIF,MA5BiB,IAACD,IA+BrBG,EAAaV,EAAS,KAC1B,GAAID,EAAgBK,MAClB,MAAO,GAGT,MAAMC,EAAUJ,EAAAC,KAGhB,MAAyB,QAArBC,EAAWC,OAKU,WAArBD,EAAWC,OAKXD,EAAWC,MATNC,IAkBLM,EAAaX,EAAS,IACD,QAArBG,EAAWC,MACNM,EAAWN,MAAMQ,MAAM,KAAKC,OAAOC,GAAOA,EAAIC,QAEhD,IAIT,SAASC,EAAWC,GAClB,OAAKA,EAKe,iBAATA,GAKP,kBAAkBX,KAAKW,GAJlB,GAAGA,MASLA,EAdE,EAeX,CAKA,MAAMC,EAAQlB,EAAS,KACrB,MAAMmB,EAAY,GAClB,OAAQlB,EAAAmB,MACN,IAAK,aACHD,EAAUE,KAAK,mBACf,MACF,IAAK,WACHF,EAAUE,KAAK,mBACf,MACF,IAAK,OACHF,EAAUE,KAAK,mBACfF,EAAUE,KAAK,mBAIfpB,EAAAqB,QACFH,EAAUE,KAAK,UAAUpB,SAAS,WAIpC,IAAIsB,EAAY,GAAGtB,EAAAuB,MAAQ,UAAUvB,EAAAuB,SAAW,KAAKvB,EAAAgB,KAAO,cAAcD,EAAWf,EAAAgB,SAAW,KAAKE,EAAUM,OAAS,cAAcN,EAAUO,KAAK,QAAU,KAG/J,MAAMC,EAAahC,EAAMuB,MACzB,GAAIS,EACF,GAA0B,iBAAfA,EACTJ,GAAaI,OACf,GAC+B,iBAAfA,EAAyB,CAMvCJ,GAJqBK,OAAOC,QAAQF,GAEjCG,IAAI,EAAEC,EAAK3B,KAAW,GAAG2B,EAAIC,QAAQ,WAAY,OAAOC,kBAAkB7B,MAC1EsB,KAAK,GAEV,CAGF,OAAOH,IAIHW,EAAeC,GAAI,GACnBC,EAAaD,GAAI,GAEvB,SAASE,IACPH,EAAa9B,OAAQ,EACrBgC,EAAWhC,OAAQ,CACrB,CAEA,SAASkC,IACPJ,EAAa9B,OAAQ,EACrBgC,EAAWhC,OAAQ,CACrB,6BAIEmC,EAAA,WAGkB,cAAVpC,EAAAC,OAFRoC,IAAAC,EAMEC,EALKxC,EAAAA,MAAI,OAERyC,MAAKC,EAAA,CAAA,CAAGC,EAAAhD,GAAGiD,KAEN,0BADL5B,SAAQA,EAAAd,oCAMY,WAAVD,EAAAC,WADb2C,EAIEC,EAAA,CAAAjB,IAAA,GAAA,CALFQ,EAAA,cACAU,EAIE,IAAA,CAFCN,MAAKC,EAAA,CAAGC,EAAAhD,GAAGiD,IAAKpC,EAAAN,QAChBc,SAAQA,EAAAd,yBAKY,QAAVD,EAAAC,WADb2C,EAKEC,EAAA,CAAAjB,IAAA,GAAA,CANFQ,EAAA,YACAU,EAKE,IAAA,CAHAN,SAAM,wBAAuB,CACpBE,KAAGC,OAAQnC,EAAAP,SACnBc,SAAQA,EAAAd,yBAKY,YAAVD,EAAAC,WADb2C,EAMEC,EAAA,CAAAjB,IAAA,GAAA,CAPFQ,EAAA,eACAW,EAMEL,EAAAM,GAAA,CAJAR,MAAKC,EAAA,CAAC,wBAAuB,CAEpBC,EAAAhD,GAAGiD,OADX5C,KAAMQ,EAAAN,MAENc,SAAQA,EAAAd,kDAIoB,QAAVD,EAAAC,WAArB2C,EAoBWC,EAAA,CAAAjB,IAAA,GAAA,CArBXQ,EAAA,QAEEA,EAAA,WAEQL,EAAA9B,OAAgBgD,EAAAA,aADxBL,EAGE,IAAA,OADCJ,QAAOS,EAAAA,mBAIGhB,EAAAhC,OAAciD,EAAAA,cAD3BN,EAGEC,EAAA,CAAAjB,IAAA,GAAA,CAJFQ,EAAA,UACAU,EAGE,IAAA,CADCN,QAAOU,EAAAA,wCAEVd,EAAA,UACAU,EAOC,MAAA,CANEK,IAAK5C,EAAAN,MACNuC,MAAKC,EAAA,CAAC,wBAAuB,CACpBC,EAAAhD,GAAGiD,OACX5B,SAAQA,EAAAd,MAAK,CAAAmD,MAAWtC,OAAOD,EAAWC,EAAAA,MAAI,OAAAuC,OAAA,UAC9CC,OAAMpB,EACNqB,QAAOpB,oBAMC5B,EAAAN,WADb2C,EAWIC,EAAA,CAAAjB,IAAA,GAAA,CAZJQ,EAAA,gBACAU,EAWI,IAAA,CATDN,MAAKC,EAAA,CAAGC,EAAAhD,GAAGiD,MACX5B,SAAQA,EAAAd,WAEToC,IAAAO,EAKM,MALNY,EAKM,CADJV,EAAwD,MAAA,CAAlD,aAAU,IAAMW,EAAAA,kBAAkBlD,EAAAN"}
1
+ {"version":3,"file":"icon.vue.mjs","sources":["../../../../../../packages/components/src/icon/src/icon.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { Component, CSSProperties } from 'vue'\nimport { Icon } from '@iconify/vue'\nimport { useNamespace } from '@qxs-bns/hooks'\nimport { computed, ref, useAttrs } from 'vue'\n\ndefineOptions({\n name: 'QxsIcon',\n})\n\nconst {\n icon,\n flip = '',\n rotate = 0,\n color,\n size,\n localIconPrefix = 'icon-',\n fallback,\n loading,\n} = defineProps<PropsType>()\n\n// 支持 attrs 传递给图标组件\nconst attrs = useAttrs()\n\nconst ns = useNamespace('icon')\n\nexport interface PropsType {\n icon: string | Component\n flip?: 'horizontal' | 'vertical' | 'both' | '' | undefined\n rotate?: number\n color?: string\n size?: string | number\n localIconPrefix?: string\n // 新增功能:支持图片URL\n fallback?: string // 加载失败时的备用图标\n loading?: string // 加载中显示的图标\n}\n\nconst isComponentName = computed(() => typeof icon === 'object' || typeof icon === 'function')\n\nconst outputType = computed(() => {\n if (isComponentName.value) {\n return 'component'\n }\n\n const iconStr = icon as string\n\n // 检测是否为图片URL或路径\n const hasPathFeatures = (str: string) => {\n return /^\\.{1,2}\\//.test(str) || str.startsWith('/') || str.includes('/')\n }\n if (/^https?:\\/\\//.test(iconStr) || hasPathFeatures(iconStr)) {\n return 'img'\n }\n\n // 检测UnoCSS图标格式 (i-[provider]:[name])\n if (/^i-[^:]+:[^:]+/.test(iconStr)) {\n return 'unocss'\n }\n\n // 检测以i-开头的自定义CSS类图标(不包含冒号)\n if (iconStr.startsWith('i-') && !iconStr.includes(':')) {\n return 'css'\n }\n\n // 检测Iconify格式 (provider:name,但不以i-开头)\n if (iconStr.includes(':') && !iconStr.startsWith('i-')) {\n return 'iconify'\n }\n\n // 检测SVG sprite(单个单词,不包含空格和特殊字符,且不以i-开头)\n if (/^[\\w-]+$/.test(iconStr) && !iconStr.startsWith('i-')) {\n return 'svg'\n }\n\n // 其他情况都视为CSS类图标(包括多个类名等)\n return 'css'\n})\n\nconst outputName = computed(() => {\n if (isComponentName.value) {\n return ''\n }\n\n const iconStr = icon as string\n\n // 对于图片类型,直接返回URL\n if (outputType.value === 'img') {\n return iconStr\n }\n\n // 对于UnoCSS图标,直接返回类名\n if (outputType.value === 'unocss') {\n return iconStr\n }\n\n // 对于传统CSS图标,处理多个类名的情况\n if (outputType.value === 'css') {\n return iconStr\n }\n\n // 其他情况直接返回\n return iconStr\n})\n\n// 对于CSS类图标,将字符串拆分为类名数组\nconst cssClasses = computed(() => {\n if (outputType.value === 'css') {\n return outputName.value.split(' ').filter(cls => cls.trim())\n }\n return []\n})\n\n// 用正则匹配 size 是不是 number 值,再判断是否有 px 结尾的单位,没有则拼接\nfunction formatSize(size: string | number | undefined): string {\n if (!size) {\n return ''\n }\n\n // 如果是数字,直接添加 px\n if (typeof size === 'number') {\n return `${size}px`\n }\n\n // 如果是纯数字字符串,添加 px\n if (/^\\d+(?:\\.\\d+)?$/.test(size)) {\n return `${size}px`\n }\n\n // 如果已经有单位(px、em、rem等)或者不是纯数字,直接返回\n return size\n}\n\n// 统一的样式计算属性,适用于所有图标类型\n// 包含颜色、尺寸和变换(旋转、翻转)\n// Iconify 图标通过外层 i 标签应用这些样式\nconst style = computed(() => {\n const transform = [] as string[]\n switch (flip) {\n case 'horizontal':\n transform.push('rotateY(180deg)')\n break\n case 'vertical':\n transform.push('rotateX(180deg)')\n break\n case 'both':\n transform.push('rotateX(180deg)')\n transform.push('rotateY(180deg)')\n break\n // 对于 '' 和 undefined,不做任何处理\n }\n if (rotate) {\n transform.push(`rotate(${rotate % 360}deg)`)\n }\n\n // 构建基础样式\n let baseStyle = `${color ? `color: ${color};` : ''}${size ? `font-size: ${formatSize(size)};` : ''}${transform.length ? `transform: ${transform.join(' ')};` : ''}`\n\n // 拼接 attrs.style\n const attrsStyle = attrs.style\n if (attrsStyle) {\n if (typeof attrsStyle === 'string') {\n baseStyle += attrsStyle\n }\n else if (typeof attrsStyle === 'object') {\n // 处理对象形式的样式\n const styleEntries = Object.entries(attrsStyle as CSSProperties)\n const styleString = styleEntries\n .map(([key, value]) => `${key.replace(/([A-Z])/g, '-$1').toLowerCase()}: ${value};`)\n .join('')\n baseStyle += styleString\n }\n }\n\n return baseStyle\n})\n\n// 图片加载状态管理\nconst imageLoading = ref(true)\nconst imageError = ref(false)\n\nfunction handleImageLoad() {\n imageLoading.value = false\n imageError.value = false\n}\n\nfunction handleImageError() {\n imageLoading.value = false\n imageError.value = true\n}\n</script>\n\n<template>\n <!-- Vue组件 -->\n <component\n :is=\"icon\"\n v-if=\"outputType === 'component'\"\n :class=\"[ns.b()]\"\n :style=\"[style]\"\n v-bind=\"attrs\"\n class=\"size-inherit shrink-0\"\n />\n\n <!-- UnoCSS图标 -->\n <i\n v-else-if=\"outputType === 'unocss'\"\n :class=\"[ns.b(), outputName]\"\n :style=\"[style]\"\n v-bind=\"attrs\"\n />\n\n <!-- CSS类图标 -->\n <i\n v-else-if=\"outputType === 'css'\"\n class=\"size-inherit shrink-0\"\n :class=\"[ns.b(), ...cssClasses]\"\n :style=\"[style]\"\n v-bind=\"attrs\"\n />\n\n <!-- Iconify图标 -->\n <Icon\n v-else-if=\"outputType === 'iconify'\"\n class=\"size-inherit shrink-0\"\n :icon=\"outputName\"\n :class=\"[ns.b()]\"\n :style=\"[style]\"\n v-bind=\"attrs\"\n />\n\n <!-- 图片 -->\n <template v-else-if=\"outputType === 'img'\">\n <!-- 加载中状态 -->\n <i\n v-if=\"imageLoading && loading\"\n :class=\"loading\"\n />\n <!-- 错误状态 -->\n <i\n v-else-if=\"imageError && fallback\"\n :class=\"fallback\"\n />\n <!-- 图片本体 -->\n <img\n :src=\"outputName\"\n class=\"size-inherit shrink-0\"\n v-bind=\"attrs\"\n :class=\"[ns.b()]\"\n :style=\"[style, { width: size ? formatSize(size) : 'auto', height: 'auto' }]\"\n @load=\"handleImageLoad\"\n @error=\"handleImageError\"\n >\n </template>\n\n <!-- SVG Sprite -->\n <i\n v-else-if=\"outputName\"\n :class=\"[ns.b()]\"\n :style=\"[style]\"\n >\n <svg\n aria-hidden=\"true\"\n class=\"size-inherit shrink-0\"\n >\n <use :xlink:href=\"`#${localIconPrefix}${outputName}`\" />\n </svg>\n </i>\n</template>\n"],"names":["attrs","useAttrs","ns","useNamespace","isComponentName","computed","__props","icon","outputType","value","iconStr","test","str","startsWith","includes","outputName","cssClasses","split","filter","cls","trim","formatSize","size","style","transform","flip","push","rotate","baseStyle","color","length","join","attrsStyle","Object","entries","map","key","replace","toLowerCase","imageLoading","ref","imageError","handleImageLoad","handleImageError","_createCommentVNode","_createBlock","_resolveDynamicComponent","_mergeProps","class","_unref","b","_createElementBlock","_Fragment","_createElementVNode","_createVNode","loading","fallback","src","width","height","onLoad","onError","_normalizeClass","_openBlock","_hoisted_2","localIconPrefix"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- "use strict";exports.version="0.0.82";
1
+ "use strict";exports.version="0.0.83";
2
2
  //# sourceMappingURL=package.json.cjs.map