@quiteer/naive-extra 0.0.1

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.
Files changed (171) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +86 -0
  3. package/dist/components/breadcrumb/index.d.ts +0 -0
  4. package/dist/components/breadcrumb/index.vue.d.ts +3 -0
  5. package/dist/components/breadcrumb/props.d.ts +0 -0
  6. package/dist/components/button/action/index.d.ts +3 -0
  7. package/dist/components/button/action/index.vue.d.ts +118 -0
  8. package/dist/components/button/action/props.d.ts +63 -0
  9. package/dist/components/button/action/utils.d.ts +8 -0
  10. package/dist/components/button/base/index.d.ts +3 -0
  11. package/dist/components/button/base/index.vue.d.ts +36 -0
  12. package/dist/components/button/base/props.d.ts +27 -0
  13. package/dist/components/button/index.d.ts +4 -0
  14. package/dist/components/button/types.d.ts +2 -0
  15. package/dist/components/form/helper.d.ts +11 -0
  16. package/dist/components/form/index.d.ts +3 -0
  17. package/dist/components/form/index.vue.d.ts +642 -0
  18. package/dist/components/form/props.d.ts +34 -0
  19. package/dist/components/icon/IconPicker.vue.d.ts +13 -0
  20. package/dist/components/icon/iconify.d.ts +25 -0
  21. package/dist/components/icon/index.d.ts +3 -0
  22. package/dist/components/icon/index.vue.d.ts +12 -0
  23. package/dist/components/layout/const.d.ts +22 -0
  24. package/dist/components/layout/context.d.ts +77 -0
  25. package/dist/components/layout/index.d.ts +5 -0
  26. package/dist/components/layout/index.vue.d.ts +80 -0
  27. package/dist/components/layout/layout-parts/AppBreadcrumb.vue.d.ts +3 -0
  28. package/dist/components/layout/layout-parts/AppFooter.vue.d.ts +18 -0
  29. package/dist/components/layout/layout-parts/AppHeader.vue.d.ts +18 -0
  30. package/dist/components/layout/layout-parts/AppLeftLogoInfo.vue.d.ts +3 -0
  31. package/dist/components/layout/layout-parts/AppMain.vue.d.ts +18 -0
  32. package/dist/components/layout/layout-parts/AppSidebar.vue.d.ts +4067 -0
  33. package/dist/components/layout/layout-parts/LayoutTransition.vue.d.ts +58 -0
  34. package/dist/components/layout/mode.d.ts +0 -0
  35. package/dist/components/layout/props.d.ts +35 -0
  36. package/dist/components/layout/types.d.ts +59 -0
  37. package/dist/components/layout/utils.d.ts +97 -0
  38. package/dist/components/provider/index.d.ts +3 -0
  39. package/dist/components/provider/index.vue.d.ts +19 -0
  40. package/dist/components/provider/props.d.ts +33 -0
  41. package/dist/components/search-bar/index.d.ts +3 -0
  42. package/dist/components/search-bar/index.vue.d.ts +1288 -0
  43. package/dist/components/search-bar/props.d.ts +15 -0
  44. package/dist/components/table/TableSetting.vue.d.ts +15 -0
  45. package/dist/components/table/index.d.ts +4 -0
  46. package/dist/components/table/index.vue.d.ts +17246 -0
  47. package/dist/components/table/props.d.ts +26 -0
  48. package/dist/components/table/useColumn.d.ts +15 -0
  49. package/dist/components/upload/enum.d.ts +18 -0
  50. package/dist/components/upload/index.d.ts +4 -0
  51. package/dist/components/upload/index.vue.d.ts +17 -0
  52. package/dist/components/upload/props.d.ts +7 -0
  53. package/dist/const/defaults.d.ts +7 -0
  54. package/dist/const/index.d.ts +2 -0
  55. package/dist/const/types.d.ts +134 -0
  56. package/dist/context/color.d.ts +13 -0
  57. package/dist/context/common.d.ts +117 -0
  58. package/dist/context/index.d.ts +41 -0
  59. package/dist/context/layout.d.ts +52 -0
  60. package/dist/context/loading-bar.d.ts +14 -0
  61. package/dist/context/locale.d.ts +143 -0
  62. package/dist/context/menu.d.ts +212 -0
  63. package/dist/context/message.d.ts +14 -0
  64. package/dist/context/notification.d.ts +14 -0
  65. package/dist/context/table.d.ts +917 -0
  66. package/dist/context/theme.d.ts +20 -0
  67. package/dist/hooks/index.d.ts +6 -0
  68. package/dist/hooks/useAdmin.d.ts +0 -0
  69. package/dist/hooks/useForm.d.ts +54 -0
  70. package/dist/hooks/useLayout.d.ts +116 -0
  71. package/dist/hooks/useProviderContext.d.ts +17 -0
  72. package/dist/hooks/useTable.d.ts +66 -0
  73. package/dist/hooks/useThemeOverrides.d.ts +8 -0
  74. package/dist/hooks/useUpload.d.ts +22 -0
  75. package/dist/index.css +36 -0
  76. package/dist/index.d.ts +29 -0
  77. package/dist/index.js +6771 -0
  78. package/dist/share/compact.d.ts +16 -0
  79. package/dist/share/index.d.ts +2 -0
  80. package/dist/share/menu.d.ts +0 -0
  81. package/dist/share/route.d.ts +0 -0
  82. package/dist/share/slot.d.ts +6 -0
  83. package/dist/utils/form.d.ts +0 -0
  84. package/dist/utils/index.d.ts +0 -0
  85. package/dist/utils/transformRoutes.d.ts +67 -0
  86. package/dist/utils/tree.d.ts +6 -0
  87. package/package.json +53 -0
  88. package/src/auto-imports.d.ts +73 -0
  89. package/src/components/breadcrumb/index.ts +0 -0
  90. package/src/components/breadcrumb/index.vue +0 -0
  91. package/src/components/breadcrumb/props.ts +0 -0
  92. package/src/components/button/action/index.ts +4 -0
  93. package/src/components/button/action/index.vue +313 -0
  94. package/src/components/button/action/props.ts +78 -0
  95. package/src/components/button/action/utils.ts +122 -0
  96. package/src/components/button/base/index.ts +4 -0
  97. package/src/components/button/base/index.vue +156 -0
  98. package/src/components/button/base/props.ts +29 -0
  99. package/src/components/button/index.ts +4 -0
  100. package/src/components/button/types.ts +2 -0
  101. package/src/components/form/helper.ts +73 -0
  102. package/src/components/form/index.ts +5 -0
  103. package/src/components/form/index.vue +243 -0
  104. package/src/components/form/props.ts +75 -0
  105. package/src/components/icon/IconPicker.vue +255 -0
  106. package/src/components/icon/iconify.ts +80 -0
  107. package/src/components/icon/index.ts +7 -0
  108. package/src/components/icon/index.vue +23 -0
  109. package/src/components/layout/const.ts +102 -0
  110. package/src/components/layout/context.ts +189 -0
  111. package/src/components/layout/index.ts +8 -0
  112. package/src/components/layout/index.vue +64 -0
  113. package/src/components/layout/layout-parts/AppBreadcrumb.vue +108 -0
  114. package/src/components/layout/layout-parts/AppFooter.vue +26 -0
  115. package/src/components/layout/layout-parts/AppHeader.vue +112 -0
  116. package/src/components/layout/layout-parts/AppLeftLogoInfo.vue +30 -0
  117. package/src/components/layout/layout-parts/AppMain.vue +34 -0
  118. package/src/components/layout/layout-parts/AppSidebar.vue +174 -0
  119. package/src/components/layout/layout-parts/LayoutTransition.vue +366 -0
  120. package/src/components/layout/mode.ts +0 -0
  121. package/src/components/layout/props.ts +36 -0
  122. package/src/components/layout/types.ts +79 -0
  123. package/src/components/layout/utils.ts +201 -0
  124. package/src/components/provider/index.ts +5 -0
  125. package/src/components/provider/index.vue +69 -0
  126. package/src/components/provider/props.ts +45 -0
  127. package/src/components/search-bar/index.ts +5 -0
  128. package/src/components/search-bar/index.vue +282 -0
  129. package/src/components/search-bar/props.ts +26 -0
  130. package/src/components/table/TableSetting.vue +253 -0
  131. package/src/components/table/index.ts +14 -0
  132. package/src/components/table/index.vue +179 -0
  133. package/src/components/table/props.ts +29 -0
  134. package/src/components/table/useColumn.ts +104 -0
  135. package/src/components/upload/enum.ts +21 -0
  136. package/src/components/upload/index.ts +9 -0
  137. package/src/components/upload/index.vue +267 -0
  138. package/src/components/upload/props.ts +8 -0
  139. package/src/components.d.ts +154 -0
  140. package/src/const/defaults.ts +94 -0
  141. package/src/const/index.ts +2 -0
  142. package/src/const/types.ts +139 -0
  143. package/src/context/color.ts +53 -0
  144. package/src/context/common.ts +27 -0
  145. package/src/context/index.ts +141 -0
  146. package/src/context/layout.ts +34 -0
  147. package/src/context/loading-bar.ts +26 -0
  148. package/src/context/locale.ts +22 -0
  149. package/src/context/menu.ts +26 -0
  150. package/src/context/message.ts +30 -0
  151. package/src/context/notification.ts +29 -0
  152. package/src/context/table.ts +32 -0
  153. package/src/context/theme.ts +35 -0
  154. package/src/hooks/index.ts +6 -0
  155. package/src/hooks/useAdmin.ts +0 -0
  156. package/src/hooks/useForm.ts +272 -0
  157. package/src/hooks/useLayout.ts +300 -0
  158. package/src/hooks/useProviderContext.ts +47 -0
  159. package/src/hooks/useTable.ts +241 -0
  160. package/src/hooks/useThemeOverrides.ts +18 -0
  161. package/src/hooks/useUpload.ts +82 -0
  162. package/src/index.ts +59 -0
  163. package/src/share/compact.ts +35 -0
  164. package/src/share/index.ts +2 -0
  165. package/src/share/menu.ts +0 -0
  166. package/src/share/route.ts +0 -0
  167. package/src/share/slot.ts +29 -0
  168. package/src/utils/form.ts +0 -0
  169. package/src/utils/index.ts +0 -0
  170. package/src/utils/transformRoutes.ts +163 -0
  171. package/src/utils/tree.ts +31 -0
@@ -0,0 +1,75 @@
1
+ import type { GridItemProps, GridProps, SwitchProps } from 'naive-ui'
2
+ import type { CSSProperties } from 'vue'
3
+ import type { Recordable } from '../../const'
4
+
5
+ export type ComponentType
6
+ = | 'NInput'
7
+ | 'NInputGroup'
8
+ | 'NInputPassword'
9
+ | 'NInputSearch'
10
+ | 'NInputTextArea'
11
+ | 'NInputNumber'
12
+ | 'NInputCountDown'
13
+ | 'NDynamicInput'
14
+ | 'NSelect'
15
+ | 'NTreeSelect'
16
+ | 'NRadioButtonGroup'
17
+ | 'NRadioGroup'
18
+ | 'NCheckbox'
19
+ | 'NCheckboxGroup'
20
+ | 'NAutoComplete'
21
+ | 'NCascader'
22
+ | 'NDatePicker'
23
+ | 'NMonthPicker'
24
+ | 'NRangePicker'
25
+ | 'NWeekPicker'
26
+ | 'NTimePicker'
27
+ | 'NSwitch'
28
+ | 'NStrengthMeter'
29
+ | 'NUpload'
30
+ | 'NIconPicker'
31
+ | 'NRender'
32
+ | 'NSlider'
33
+ | 'NRate'
34
+ | 'NDynamicTags'
35
+ | 'NImage'
36
+
37
+ export interface FormSchema<T = Recordable<string>> {
38
+ field: keyof T
39
+ label: string
40
+ labelMessage?: string
41
+ labelMessageStyle?: object | string
42
+ defaultValue?: any
43
+ component?: ComponentType
44
+ componentProps?: Record<string, any>
45
+ slot?: string
46
+ rules?: object[]
47
+ giProps?: GridItemProps
48
+ isFull?: boolean
49
+ suffix?: string
50
+ }
51
+
52
+ export interface Props {
53
+ schemas: FormSchema<Recordable<string>>[]
54
+ disabled?: boolean
55
+ // 标签宽度 固定宽度
56
+ labelWidth?: number | string
57
+ labelPlacement?: 'top' | 'left'
58
+ // 是否展示为行内表单
59
+ inline?: boolean
60
+ // 大小
61
+ size?: 'small' | 'medium' | 'large'
62
+ // 组件是否width 100%
63
+ isFull?: boolean
64
+ // grid 配置
65
+ gridProps?: GridProps
66
+ // grid 样式
67
+ gridStyle?: CSSProperties
68
+ // gi配置
69
+ giProps?: GridItemProps
70
+ }
71
+
72
+ export interface CustomSwitchProps extends SwitchProps {
73
+ checkedText: string
74
+ uncheckedText: string
75
+ }
@@ -0,0 +1,255 @@
1
+ <script setup lang="ts">
2
+ import { getCollections, getIconNames, searchIcons } from './iconify'
3
+ import QuiIcon from './index.vue'
4
+
5
+ const props = defineProps<{
6
+ modelValue?: string // 格式: "collection:name"
7
+ pageSize?: number // 每页加载数量
8
+ }>()
9
+
10
+ const emit = defineEmits<{
11
+ (e: 'update:modelValue', value: string): void
12
+ (e: 'select', value: string): void
13
+ }>()
14
+
15
+ const searchQuery = ref('')
16
+ const selectedCollection = ref<string>('mdi')
17
+ const currentPage = ref(1)
18
+ const hasMore = ref(true)
19
+ const loading = ref(false)
20
+
21
+ const collections = ref<string[]>([])
22
+ const allIcons = ref<{ collection: string, name: string }[]>([])
23
+ const displayedIcons = ref<{ collection: string, name: string }[]>([])
24
+
25
+ // 缓存各集合图标名
26
+ const iconsCache = new Map<string, string[]>()
27
+
28
+ const collectionOptions = computed(() => {
29
+ return collections.value.map(col => ({ label: col, value: col }))
30
+ })
31
+
32
+ async function initCollections() {
33
+ const cols = await getCollections()
34
+ collections.value = cols
35
+ if (cols.includes('mdi')) {
36
+ selectedCollection.value = 'mdi'
37
+ }
38
+ else if (cols.length > 0) {
39
+ selectedCollection.value = cols[0] || ''
40
+ }
41
+ }
42
+
43
+ async function loadPage(page: number, reset = false) {
44
+ loading.value = true
45
+ if (reset) {
46
+ currentPage.value = 1
47
+ displayedIcons.value = []
48
+ }
49
+ else {
50
+ currentPage.value = page
51
+ }
52
+
53
+ try {
54
+ const query = searchQuery.value.trim().toLowerCase()
55
+
56
+ // 如果是搜索模式
57
+ if (query) {
58
+ if (reset) {
59
+ // 执行搜索
60
+ allIcons.value = await searchIcons(query)
61
+ }
62
+ }
63
+ // 如果是浏览模式
64
+ else {
65
+ // 检查缓存
66
+ const currentCol = selectedCollection.value
67
+ let names = iconsCache.get(currentCol)
68
+
69
+ if (!names) {
70
+ names = await getIconNames(currentCol)
71
+ iconsCache.set(currentCol, names)
72
+ }
73
+
74
+ if (reset) {
75
+ allIcons.value = names.map(name => ({ collection: currentCol, name }))
76
+ }
77
+ }
78
+
79
+ // 分页逻辑
80
+ const pageSize = props.pageSize || 200
81
+ const start = (currentPage.value - 1) * pageSize
82
+ const end = start + pageSize
83
+
84
+ const pageIcons = allIcons.value.slice(start, end)
85
+
86
+ if (reset) {
87
+ displayedIcons.value = pageIcons
88
+ }
89
+ else {
90
+ displayedIcons.value.push(...pageIcons)
91
+ }
92
+
93
+ hasMore.value = end < allIcons.value.length
94
+ }
95
+ catch (error) {
96
+ console.error('Failed to load icons:', error)
97
+ }
98
+ finally {
99
+ loading.value = false
100
+ }
101
+ }
102
+
103
+ let searchTimeout: any
104
+
105
+ function handleSearchInput() {
106
+ clearTimeout(searchTimeout)
107
+ searchTimeout = setTimeout(() => {
108
+ currentPage.value = 1
109
+ loadPage(1, true)
110
+ }, 500)
111
+ }
112
+
113
+ function handleCollectionChange() {
114
+ searchQuery.value = '' // 切换集合时清空搜索
115
+ loadPage(1, true)
116
+ }
117
+
118
+ // 滚动到底部加载更多
119
+ function handleScroll(e: Event) {
120
+ const target = e.target as HTMLElement
121
+ if (target.scrollTop + target.clientHeight >= target.scrollHeight - 100) {
122
+ if (hasMore.value && !loading.value) {
123
+ currentPage.value++
124
+ loadPage(currentPage.value)
125
+ }
126
+ }
127
+ }
128
+
129
+ // 选择图标
130
+ function selectIcon(collection: string, name: string) {
131
+ const iconId = `${collection}:${name}`
132
+ emit('update:modelValue', iconId)
133
+ emit('select', iconId)
134
+ }
135
+
136
+ onMounted(async () => {
137
+ await initCollections()
138
+ loadPage(1, true)
139
+ })
140
+ </script>
141
+
142
+ <template>
143
+ <NCard
144
+ class="icon-picker w-full mx-auto h-[600px]"
145
+ content-style="padding: 0; display: flex; flex-direction: column; height: 100%; overflow: hidden;"
146
+ :bordered="true"
147
+ >
148
+ <!-- 搜索 & 集合筛选 -->
149
+ <div class="p-3 border-b border-gray-200 dark:border-gray-700">
150
+ <n-grid :cols="24" :x-gap="12">
151
+ <n-gi :span="16">
152
+ <NInput
153
+ v-model:value="searchQuery"
154
+ placeholder="搜索图标 (e.g. home, user)"
155
+ clearable
156
+ @input="handleSearchInput"
157
+ >
158
+ <template #prefix>
159
+ <QuiIcon icon="carbon:search" class="text-gray-400" />
160
+ </template>
161
+ </NInput>
162
+ </n-gi>
163
+ <n-gi :span="8">
164
+ <NSelect
165
+ v-model:value="selectedCollection"
166
+ :options="collectionOptions"
167
+ filterable
168
+ placeholder="选择集合"
169
+ :disabled="!!searchQuery"
170
+ @update:value="handleCollectionChange"
171
+ />
172
+ </n-gi>
173
+ </n-grid>
174
+ </div>
175
+
176
+ <!-- 图标网格 -->
177
+ <div class="flex-1 overflow-hidden relative">
178
+ <NScrollbar
179
+ class="h-full"
180
+ content-class="p-4"
181
+ @scroll="handleScroll"
182
+ >
183
+ <div v-if="displayedIcons.length">
184
+ <n-grid
185
+ cols="8 s:10 m:12 l:16 xl:20"
186
+ responsive="screen"
187
+ :x-gap="8"
188
+ :y-gap="8"
189
+ >
190
+ <n-gi
191
+ v-for="item in displayedIcons"
192
+ :key="`${item.collection}:${item.name}`"
193
+ >
194
+ <NTooltip trigger="hover">
195
+ <template #trigger>
196
+ <div
197
+ class="aspect-square flex items-center justify-center rounded cursor-pointer transition-colors border border-transparent hover:bg-gray-100 dark:hover:bg-gray-700 hover:border-gray-200 dark:hover:border-gray-600"
198
+ :class="{ 'bg-primary-50 text-primary-600 border-primary-200': modelValue === `${item.collection}:${item.name}` }"
199
+ @click="selectIcon(item.collection, item.name)"
200
+ >
201
+ <QuiIcon
202
+ :icon="`${item.collection}:${item.name}`"
203
+ size="24"
204
+ />
205
+ </div>
206
+ </template>
207
+ {{ item.name }}
208
+ </NTooltip>
209
+ </n-gi>
210
+ </n-grid>
211
+ </div>
212
+
213
+ <!-- 空状态 -->
214
+ <div v-if="!loading && !displayedIcons.length" class="h-full flex items-center justify-center min-h-[200px]">
215
+ <NEmpty description="未找到图标" />
216
+ </div>
217
+
218
+ <!-- 底部加载中 -->
219
+ <div v-if="loading && displayedIcons.length > 0" class="py-4 flex justify-center w-full">
220
+ <NSpin size="small" />
221
+ </div>
222
+ </NScrollbar>
223
+
224
+ <!-- 初始加载遮罩 -->
225
+ <div v-if="loading && displayedIcons.length === 0" class="absolute inset-0 flex items-center justify-center bg-white/80 dark:bg-gray-800/80 z-10">
226
+ <NSpin size="large" />
227
+ </div>
228
+ </div>
229
+
230
+ <!-- 当前选中预览 -->
231
+ <div v-if="modelValue" class="p-3 border-t border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-gray-900/50">
232
+ <n-flex justify="space-between" align="center">
233
+ <n-flex align="center" :size="8">
234
+ <span class="text-sm text-gray-500">已选:</span>
235
+ <div class="flex items-center gap-2 bg-white dark:bg-gray-800 px-2 py-1 rounded border border-gray-200 dark:border-gray-700">
236
+ <QuiIcon :icon="modelValue" size="20" />
237
+ <NText code class="text-sm">
238
+ {{ modelValue }}
239
+ </NText>
240
+ </div>
241
+ </n-flex>
242
+
243
+ <NTag size="small" type="success" :bordered="false">
244
+ {{ modelValue.split(':')[0] }}
245
+ </NTag>
246
+ </n-flex>
247
+ </div>
248
+ </NCard>
249
+ </template>
250
+
251
+ <style scoped>
252
+ .icon-picker {
253
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
254
+ }
255
+ </style>
@@ -0,0 +1,80 @@
1
+ /**
2
+ * 获取所有图标集合
3
+ *
4
+ * 从 Iconify API 获取可用的图标集合列表
5
+ *
6
+ * @returns {Promise<string[]>} 集合前缀列表
7
+ */
8
+ export async function getCollections(): Promise<string[]> {
9
+ try {
10
+ const response = await fetch('https://api.iconify.design/collections')
11
+ const data = await response.json()
12
+ return Object.keys(data)
13
+ }
14
+ catch (error) {
15
+ console.error('Failed to fetch collections:', error)
16
+ return []
17
+ }
18
+ }
19
+
20
+ /**
21
+ * 获取指定集合的所有图标名称
22
+ *
23
+ * @param collection - 集合前缀
24
+ * @returns {Promise<string[]>} 图标名称列表
25
+ */
26
+ export async function getIconNames(collection: string): Promise<string[]> {
27
+ try {
28
+ const response = await fetch(`https://api.iconify.design/collection?prefix=${collection}`)
29
+ const data = await response.json()
30
+
31
+ const names = new Set<string>()
32
+
33
+ // 从 uncategorized 获取
34
+ if (data.uncategorized) {
35
+ data.uncategorized.forEach((name: string) => names.add(name))
36
+ }
37
+
38
+ // 从 categories 获取
39
+ if (data.categories) {
40
+ Object.values(data.categories).forEach((categoryIcons: any) => {
41
+ categoryIcons.forEach((name: string) => names.add(name))
42
+ })
43
+ }
44
+
45
+ // 兜底:如果上面都没找到,尝试从 icons 对象键名获取
46
+ if (names.size === 0 && data.icons) {
47
+ Object.keys(data.icons).forEach(name => names.add(name))
48
+ }
49
+
50
+ return Array.from(names).sort()
51
+ }
52
+ catch (error) {
53
+ console.error(`Failed to fetch icons for ${collection}:`, error)
54
+ return []
55
+ }
56
+ }
57
+
58
+ /**
59
+ * 搜索图标
60
+ *
61
+ * @param query - 搜索关键词
62
+ * @returns {Promise<{collection: string, name: string}[]>} 图标列表
63
+ */
64
+ export async function searchIcons(query: string): Promise<{ collection: string, name: string }[]> {
65
+ try {
66
+ const response = await fetch(`https://api.iconify.design/search?query=${encodeURIComponent(query)}&limit=999`)
67
+ const data = await response.json()
68
+ if (data.icons) {
69
+ return data.icons.map((fullIcon: string) => {
70
+ const [collection, name] = fullIcon.split(':')
71
+ return { collection, name }
72
+ })
73
+ }
74
+ return []
75
+ }
76
+ catch (error) {
77
+ console.error('Failed to search icons:', error)
78
+ return []
79
+ }
80
+ }
@@ -0,0 +1,7 @@
1
+ import QuiIconPicker from './IconPicker.vue'
2
+ import QuiIcon from './index.vue'
3
+
4
+ export {
5
+ QuiIcon,
6
+ QuiIconPicker
7
+ }
@@ -0,0 +1,23 @@
1
+ <script setup lang="ts">
2
+ import { Icon } from '@iconify/vue'
3
+
4
+ defineProps<{
5
+ /**
6
+ * Iconify 图标名称,格式:`collection:name`
7
+ * 例如:'mdi:home', 'carbon:user', 'tabler:settings'
8
+ */
9
+ icon?: string
10
+ size?: string | number
11
+ color?: string
12
+ }>()
13
+ </script>
14
+
15
+ <template>
16
+ <Icon
17
+ v-if="icon"
18
+ :icon="icon"
19
+ :width="size"
20
+ :height="size"
21
+ :color="color"
22
+ />
23
+ </template>
@@ -0,0 +1,102 @@
1
+ import type { Props } from './props'
2
+ import type { LayoutType } from './types'
3
+
4
+ export const DEFAULT_LAYOUT_PROPS: Required<Omit<Props, 'baseRoutes'>> = {
5
+ /** @description 布局类型 */
6
+ type: 'side-menu',
7
+ /** @description 是否显示边框 */
8
+ bordered: true,
9
+ /** @description 反色样式(Header/Sider/Footer/Menu) */
10
+ inverted: false,
11
+ /** @description 是否折叠侧边栏 */
12
+ isCollapsed: false,
13
+ /** @description 是否显示底部 */
14
+ showFooter: true,
15
+ /** @description 头部高度 */
16
+ headerHeight: 54,
17
+ /** @description 底部高度 */
18
+ footerHeight: 42,
19
+ /** @description 底部是否占满宽度 */
20
+ footerFull: true,
21
+ /** @description 侧边栏宽度 */
22
+ siderWidth: 220,
23
+ /** @description 侧边栏混合模式的宽度 */
24
+ siderMixedWidth: 80,
25
+ /** @description 折叠侧边栏宽度 */
26
+ collapsedWidth: 60,
27
+ /** @description 当前激活的路由键 */
28
+ activeKey: '/',
29
+ /** @description 菜单路由 */
30
+ menuOptions: [],
31
+ /** @description 是否开启手风琴模式 */
32
+ accordion: true
33
+ }
34
+
35
+ export const DEFAULT_LAYOUT_TYPE: { type: LayoutType, name: string, desc: string }[] = [
36
+ {
37
+ type: 'side-menu',
38
+ name: '左侧菜单布局',
39
+ desc: '左侧多层级菜单布局,顶部为面包屑'
40
+ },
41
+ {
42
+ type: 'side-group-menu',
43
+ name: '左侧分组菜单布局',
44
+ desc: '左侧多层级菜单布局,分组展示,顶部为面包屑'
45
+ },
46
+ {
47
+ type: 'side-mixed-menu',
48
+ name: '左侧混合菜单布局',
49
+ desc: '左侧多层级菜单布局,第一级菜单可折叠,其余层级为标题和分组展示,顶部为面包屑'
50
+ },
51
+ {
52
+ type: 'side-menu/2',
53
+ name: '左侧-顶部菜单布局',
54
+ desc: '左侧单层级菜单布局,顶部为水平多层级菜单,无面包屑'
55
+ },
56
+ {
57
+ type: 'top-menu',
58
+ name: '顶部菜单布局',
59
+ desc: '无侧边栏,顶部为水平多层级菜单,无面包屑'
60
+ },
61
+ {
62
+ type: 'top-menu/2',
63
+ name: '顶部-左侧菜单布局',
64
+ desc: '顶部菜单为主,顶部为水平单层级菜单,左侧为垂直多层级菜单,无面包屑'
65
+ },
66
+ {
67
+ type: 'top-group-menu/2',
68
+ name: '顶部-左侧分组菜单布局',
69
+ desc: '顶部菜单为主,顶部为水平单层级菜单,左侧为垂直多层级菜单,分组展示,无面包屑'
70
+ },
71
+ {
72
+ type: 'top-mixed-menu/2',
73
+ name: '顶部-左侧混合菜单布局',
74
+ desc: '顶部菜单为主,顶部为水平单层级菜单,左侧为垂直多层级菜单,左侧第一级菜单可折叠,其余层级为标题和分组展示,无面包屑'
75
+ },
76
+ {
77
+ type: 'blank',
78
+ name: '无菜单布局',
79
+ desc: '无菜单布局,页面不包含任何主导航菜单,适用于登录页、引导页、全屏应用等场景'
80
+ }
81
+ ] as const
82
+
83
+ /** @description 所有布局类型 */
84
+ export const ALL_LAYOUT_TYPES: LayoutType[] = DEFAULT_LAYOUT_TYPE.map(item => item.type)
85
+
86
+ /** @description 侧边栏布局类型 */
87
+ export const SIDE_LAYOUT_TYPES: LayoutType[] = ['side-menu', 'side-menu/2', 'side-group-menu', 'side-mixed-menu', 'top-menu/2', 'top-group-menu/2', 'top-mixed-menu/2']
88
+
89
+ /** @description 侧边栏分组布局类型 */
90
+ export const SIDE_GROUP_LAYOUT_TYPES: LayoutType[] = ['side-group-menu', 'top-group-menu/2']
91
+
92
+ /** @description 侧边栏混合布局类型 */
93
+ export const SIDE_MIXED_LAYOUT_TYPES: LayoutType[] = ['side-mixed-menu', 'top-mixed-menu/2']
94
+
95
+ /** @description 顶部布局类型 */
96
+ export const TOP_LAYOUT_TYPES: LayoutType[] = ['side-menu/2', 'top-menu', 'top-menu/2', 'top-group-menu/2', 'top-mixed-menu/2']
97
+
98
+ /** @description 面包屑布局类型 */
99
+ export const BREADCRUMB_LAYOUT_TYPES: LayoutType[] = ['side-menu', 'side-group-menu', 'side-mixed-menu']
100
+
101
+ /** @description 无菜单布局类型 */
102
+ export const BLANK_LAYOUT_TYPES: LayoutType[] = ['blank']