@h-ai/ui 0.1.0-alpha5

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 (234) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +488 -0
  3. package/auto-import.d.ts +96 -0
  4. package/auto-import.js +259 -0
  5. package/dist/components/compounds/Accordion.svelte +142 -0
  6. package/dist/components/compounds/Accordion.svelte.d.ts +25 -0
  7. package/dist/components/compounds/ActionSheet.svelte +116 -0
  8. package/dist/components/compounds/ActionSheet.svelte.d.ts +22 -0
  9. package/dist/components/compounds/Alert.svelte +67 -0
  10. package/dist/components/compounds/Alert.svelte.d.ts +8 -0
  11. package/dist/components/compounds/AppBar.svelte +77 -0
  12. package/dist/components/compounds/AppBar.svelte.d.ts +20 -0
  13. package/dist/components/compounds/BottomNav.svelte +75 -0
  14. package/dist/components/compounds/BottomNav.svelte.d.ts +18 -0
  15. package/dist/components/compounds/Breadcrumb.svelte +49 -0
  16. package/dist/components/compounds/Breadcrumb.svelte.d.ts +4 -0
  17. package/dist/components/compounds/Calendar.svelte +116 -0
  18. package/dist/components/compounds/Calendar.svelte.d.ts +47 -0
  19. package/dist/components/compounds/Card.svelte +77 -0
  20. package/dist/components/compounds/Card.svelte.d.ts +8 -0
  21. package/dist/components/compounds/Combobox.svelte +327 -0
  22. package/dist/components/compounds/Combobox.svelte.d.ts +69 -0
  23. package/dist/components/compounds/Confirm.svelte +90 -0
  24. package/dist/components/compounds/Confirm.svelte.d.ts +4 -0
  25. package/dist/components/compounds/DataTable.svelte +133 -0
  26. package/dist/components/compounds/DataTable.svelte.d.ts +69 -0
  27. package/dist/components/compounds/DatePicker.svelte +135 -0
  28. package/dist/components/compounds/DatePicker.svelte.d.ts +46 -0
  29. package/dist/components/compounds/Drawer.svelte +113 -0
  30. package/dist/components/compounds/Drawer.svelte.d.ts +4 -0
  31. package/dist/components/compounds/Dropdown.svelte +91 -0
  32. package/dist/components/compounds/Dropdown.svelte.d.ts +8 -0
  33. package/dist/components/compounds/Empty.svelte +83 -0
  34. package/dist/components/compounds/Empty.svelte.d.ts +4 -0
  35. package/dist/components/compounds/Form.svelte +96 -0
  36. package/dist/components/compounds/Form.svelte.d.ts +7 -0
  37. package/dist/components/compounds/FormField.svelte +56 -0
  38. package/dist/components/compounds/FormField.svelte.d.ts +4 -0
  39. package/dist/components/compounds/InfiniteScroll.svelte +82 -0
  40. package/dist/components/compounds/InfiniteScroll.svelte.d.ts +22 -0
  41. package/dist/components/compounds/Modal.svelte +123 -0
  42. package/dist/components/compounds/Modal.svelte.d.ts +8 -0
  43. package/dist/components/compounds/PageHeader.svelte +44 -0
  44. package/dist/components/compounds/PageHeader.svelte.d.ts +28 -0
  45. package/dist/components/compounds/Pagination.svelte +157 -0
  46. package/dist/components/compounds/Pagination.svelte.d.ts +4 -0
  47. package/dist/components/compounds/Popover.svelte +137 -0
  48. package/dist/components/compounds/Popover.svelte.d.ts +4 -0
  49. package/dist/components/compounds/PullRefresh.svelte +98 -0
  50. package/dist/components/compounds/PullRefresh.svelte.d.ts +16 -0
  51. package/dist/components/compounds/Result.svelte +84 -0
  52. package/dist/components/compounds/Result.svelte.d.ts +4 -0
  53. package/dist/components/compounds/SafeArea.svelte +37 -0
  54. package/dist/components/compounds/SafeArea.svelte.d.ts +12 -0
  55. package/dist/components/compounds/Skeleton.svelte +75 -0
  56. package/dist/components/compounds/Skeleton.svelte.d.ts +8 -0
  57. package/dist/components/compounds/Steps.svelte +111 -0
  58. package/dist/components/compounds/Steps.svelte.d.ts +4 -0
  59. package/dist/components/compounds/SwipeCell.svelte +115 -0
  60. package/dist/components/compounds/SwipeCell.svelte.d.ts +19 -0
  61. package/dist/components/compounds/Tabs.svelte +79 -0
  62. package/dist/components/compounds/Tabs.svelte.d.ts +8 -0
  63. package/dist/components/compounds/TagInput.svelte +108 -0
  64. package/dist/components/compounds/TagInput.svelte.d.ts +4 -0
  65. package/dist/components/compounds/Timeline.svelte +167 -0
  66. package/dist/components/compounds/Timeline.svelte.d.ts +25 -0
  67. package/dist/components/compounds/ToastContainer.svelte +59 -0
  68. package/dist/components/compounds/ToastContainer.svelte.d.ts +3 -0
  69. package/dist/components/compounds/Tooltip.svelte +41 -0
  70. package/dist/components/compounds/Tooltip.svelte.d.ts +4 -0
  71. package/dist/components/compounds/accordion-types.d.ts +16 -0
  72. package/dist/components/compounds/accordion-types.js +5 -0
  73. package/dist/components/compounds/action-sheet-types.d.ts +14 -0
  74. package/dist/components/compounds/action-sheet-types.js +5 -0
  75. package/dist/components/compounds/bottom-nav-types.d.ts +17 -0
  76. package/dist/components/compounds/bottom-nav-types.js +5 -0
  77. package/dist/components/compounds/index.d.ts +44 -0
  78. package/dist/components/compounds/index.js +54 -0
  79. package/dist/components/compounds/swipe-cell-types.d.ts +14 -0
  80. package/dist/components/compounds/swipe-cell-types.js +5 -0
  81. package/dist/components/compounds/timeline-types.d.ts +20 -0
  82. package/dist/components/compounds/timeline-types.js +5 -0
  83. package/dist/components/index.d.ts +9 -0
  84. package/dist/components/index.js +12 -0
  85. package/dist/components/primitives/Avatar.svelte +102 -0
  86. package/dist/components/primitives/Avatar.svelte.d.ts +8 -0
  87. package/dist/components/primitives/Badge.svelte +33 -0
  88. package/dist/components/primitives/Badge.svelte.d.ts +8 -0
  89. package/dist/components/primitives/BareButton.svelte +45 -0
  90. package/dist/components/primitives/BareButton.svelte.d.ts +4 -0
  91. package/dist/components/primitives/BareInput.svelte +101 -0
  92. package/dist/components/primitives/BareInput.svelte.d.ts +4 -0
  93. package/dist/components/primitives/Button.svelte +60 -0
  94. package/dist/components/primitives/Button.svelte.d.ts +8 -0
  95. package/dist/components/primitives/Checkbox.svelte +58 -0
  96. package/dist/components/primitives/Checkbox.svelte.d.ts +4 -0
  97. package/dist/components/primitives/IconButton.svelte +105 -0
  98. package/dist/components/primitives/IconButton.svelte.d.ts +4 -0
  99. package/dist/components/primitives/Input.svelte +130 -0
  100. package/dist/components/primitives/Input.svelte.d.ts +8 -0
  101. package/dist/components/primitives/Progress.svelte +58 -0
  102. package/dist/components/primitives/Progress.svelte.d.ts +4 -0
  103. package/dist/components/primitives/Radio.svelte +60 -0
  104. package/dist/components/primitives/Radio.svelte.d.ts +25 -0
  105. package/dist/components/primitives/Range.svelte +117 -0
  106. package/dist/components/primitives/Range.svelte.d.ts +27 -0
  107. package/dist/components/primitives/Rating.svelte +148 -0
  108. package/dist/components/primitives/Rating.svelte.d.ts +27 -0
  109. package/dist/components/primitives/Select.svelte +95 -0
  110. package/dist/components/primitives/Select.svelte.d.ts +25 -0
  111. package/dist/components/primitives/Spinner.svelte +54 -0
  112. package/dist/components/primitives/Spinner.svelte.d.ts +4 -0
  113. package/dist/components/primitives/Switch.svelte +53 -0
  114. package/dist/components/primitives/Switch.svelte.d.ts +4 -0
  115. package/dist/components/primitives/Tag.svelte +64 -0
  116. package/dist/components/primitives/Tag.svelte.d.ts +4 -0
  117. package/dist/components/primitives/Textarea.svelte +92 -0
  118. package/dist/components/primitives/Textarea.svelte.d.ts +4 -0
  119. package/dist/components/primitives/ToggleCheckbox.svelte +36 -0
  120. package/dist/components/primitives/ToggleCheckbox.svelte.d.ts +4 -0
  121. package/dist/components/primitives/ToggleInput.svelte +36 -0
  122. package/dist/components/primitives/ToggleInput.svelte.d.ts +4 -0
  123. package/dist/components/primitives/ToggleRadio.svelte +36 -0
  124. package/dist/components/primitives/ToggleRadio.svelte.d.ts +4 -0
  125. package/dist/components/primitives/index.d.ts +26 -0
  126. package/dist/components/primitives/index.js +30 -0
  127. package/dist/components/scenes/ai/AiDocumentDownloadMenu.svelte +387 -0
  128. package/dist/components/scenes/ai/AiDocumentDownloadMenu.svelte.d.ts +38 -0
  129. package/dist/components/scenes/ai/AiDocumentEditor.svelte +2259 -0
  130. package/dist/components/scenes/ai/AiDocumentEditor.svelte.d.ts +4 -0
  131. package/dist/components/scenes/ai/MarkdownRenderer.svelte +460 -0
  132. package/dist/components/scenes/ai/MarkdownRenderer.svelte.d.ts +4 -0
  133. package/dist/components/scenes/ai/document-download.d.ts +40 -0
  134. package/dist/components/scenes/ai/document-download.js +300 -0
  135. package/dist/components/scenes/ai/document-parse.d.ts +28 -0
  136. package/dist/components/scenes/ai/document-parse.js +243 -0
  137. package/dist/components/scenes/ai/document-types.d.ts +164 -0
  138. package/dist/components/scenes/ai/document-types.js +1 -0
  139. package/dist/components/scenes/ai/index.d.ts +17 -0
  140. package/dist/components/scenes/ai/index.js +13 -0
  141. package/dist/components/scenes/ai/markdown-parse.d.ts +32 -0
  142. package/dist/components/scenes/ai/markdown-parse.js +161 -0
  143. package/dist/components/scenes/app/FeedbackModal.svelte +160 -0
  144. package/dist/components/scenes/app/FeedbackModal.svelte.d.ts +47 -0
  145. package/dist/components/scenes/app/LanguageSwitch.svelte +136 -0
  146. package/dist/components/scenes/app/LanguageSwitch.svelte.d.ts +50 -0
  147. package/dist/components/scenes/app/SettingsModal.svelte +174 -0
  148. package/dist/components/scenes/app/SettingsModal.svelte.d.ts +31 -0
  149. package/dist/components/scenes/app/ThemeSelector.svelte +176 -0
  150. package/dist/components/scenes/app/ThemeSelector.svelte.d.ts +31 -0
  151. package/dist/components/scenes/app/ThemeToggle.svelte +76 -0
  152. package/dist/components/scenes/app/ThemeToggle.svelte.d.ts +29 -0
  153. package/dist/components/scenes/app/index.d.ts +11 -0
  154. package/dist/components/scenes/app/index.js +11 -0
  155. package/dist/components/scenes/crud/CrudDeleteConfirm.svelte +39 -0
  156. package/dist/components/scenes/crud/CrudDeleteConfirm.svelte.d.ts +18 -0
  157. package/dist/components/scenes/crud/CrudDetailDrawer.svelte +155 -0
  158. package/dist/components/scenes/crud/CrudDetailDrawer.svelte.d.ts +38 -0
  159. package/dist/components/scenes/crud/CrudEditDrawer.svelte +222 -0
  160. package/dist/components/scenes/crud/CrudEditDrawer.svelte.d.ts +48 -0
  161. package/dist/components/scenes/crud/CrudFilterBar.svelte +96 -0
  162. package/dist/components/scenes/crud/CrudFilterBar.svelte.d.ts +31 -0
  163. package/dist/components/scenes/crud/CrudPage.svelte +499 -0
  164. package/dist/components/scenes/crud/CrudPage.svelte.d.ts +114 -0
  165. package/dist/components/scenes/crud/crud-types.d.ts +135 -0
  166. package/dist/components/scenes/crud/crud-types.js +7 -0
  167. package/dist/components/scenes/crud/index.d.ts +12 -0
  168. package/dist/components/scenes/crud/index.js +11 -0
  169. package/dist/components/scenes/crypto/EncryptedInput.svelte +156 -0
  170. package/dist/components/scenes/crypto/EncryptedInput.svelte.d.ts +32 -0
  171. package/dist/components/scenes/crypto/HashDisplay.svelte +97 -0
  172. package/dist/components/scenes/crypto/HashDisplay.svelte.d.ts +4 -0
  173. package/dist/components/scenes/crypto/SignatureDisplay.svelte +161 -0
  174. package/dist/components/scenes/crypto/SignatureDisplay.svelte.d.ts +4 -0
  175. package/dist/components/scenes/crypto/index.d.ts +9 -0
  176. package/dist/components/scenes/crypto/index.js +11 -0
  177. package/dist/components/scenes/iam/ChangePasswordForm.svelte +134 -0
  178. package/dist/components/scenes/iam/ChangePasswordForm.svelte.d.ts +8 -0
  179. package/dist/components/scenes/iam/ForgotPasswordForm.svelte +147 -0
  180. package/dist/components/scenes/iam/ForgotPasswordForm.svelte.d.ts +4 -0
  181. package/dist/components/scenes/iam/LoginForm.svelte +191 -0
  182. package/dist/components/scenes/iam/LoginForm.svelte.d.ts +8 -0
  183. package/dist/components/scenes/iam/PasswordInput.svelte +203 -0
  184. package/dist/components/scenes/iam/PasswordInput.svelte.d.ts +49 -0
  185. package/dist/components/scenes/iam/PermGuard.svelte +69 -0
  186. package/dist/components/scenes/iam/PermGuard.svelte.d.ts +16 -0
  187. package/dist/components/scenes/iam/RegisterForm.svelte +269 -0
  188. package/dist/components/scenes/iam/RegisterForm.svelte.d.ts +8 -0
  189. package/dist/components/scenes/iam/ResetPasswordForm.svelte +153 -0
  190. package/dist/components/scenes/iam/ResetPasswordForm.svelte.d.ts +8 -0
  191. package/dist/components/scenes/iam/UserProfile.svelte +251 -0
  192. package/dist/components/scenes/iam/UserProfile.svelte.d.ts +4 -0
  193. package/dist/components/scenes/iam/index.d.ts +16 -0
  194. package/dist/components/scenes/iam/index.js +18 -0
  195. package/dist/components/scenes/iam/password-utils.d.ts +15 -0
  196. package/dist/components/scenes/iam/password-utils.js +19 -0
  197. package/dist/components/scenes/iam/permission-context.svelte.d.ts +90 -0
  198. package/dist/components/scenes/iam/permission-context.svelte.js +114 -0
  199. package/dist/components/scenes/index.d.ts +13 -0
  200. package/dist/components/scenes/index.js +20 -0
  201. package/dist/components/scenes/storage/AvatarUpload.svelte +218 -0
  202. package/dist/components/scenes/storage/AvatarUpload.svelte.d.ts +4 -0
  203. package/dist/components/scenes/storage/FileList.svelte +260 -0
  204. package/dist/components/scenes/storage/FileList.svelte.d.ts +4 -0
  205. package/dist/components/scenes/storage/FileUpload.svelte +400 -0
  206. package/dist/components/scenes/storage/FileUpload.svelte.d.ts +7 -0
  207. package/dist/components/scenes/storage/ImageUpload.svelte +285 -0
  208. package/dist/components/scenes/storage/ImageUpload.svelte.d.ts +4 -0
  209. package/dist/components/scenes/storage/index.d.ts +10 -0
  210. package/dist/components/scenes/storage/index.js +12 -0
  211. package/dist/components/scenes/types.d.ts +583 -0
  212. package/dist/components/scenes/types.js +7 -0
  213. package/dist/i18n.svelte.d.ts +44 -0
  214. package/dist/i18n.svelte.js +108 -0
  215. package/dist/index.d.ts +13 -0
  216. package/dist/index.js +19 -0
  217. package/dist/messages/en-US.json +242 -0
  218. package/dist/messages/zh-CN.json +242 -0
  219. package/dist/messages.d.ts +29 -0
  220. package/dist/messages.js +42 -0
  221. package/dist/styles/design-tokens.css +58 -0
  222. package/dist/styles/global.css +218 -0
  223. package/dist/styles/mobile.css +105 -0
  224. package/dist/theme-config.d.ts +92 -0
  225. package/dist/theme-config.js +122 -0
  226. package/dist/toast.svelte.d.ts +45 -0
  227. package/dist/toast.svelte.js +77 -0
  228. package/dist/types.d.ts +944 -0
  229. package/dist/types.js +7 -0
  230. package/dist/utils/platform.svelte.d.ts +54 -0
  231. package/dist/utils/platform.svelte.js +87 -0
  232. package/dist/utils.d.ts +46 -0
  233. package/dist/utils.js +100 -0
  234. package/package.json +69 -0
@@ -0,0 +1,67 @@
1
+ <!--
2
+ @component Alert
3
+ 警告框组件,使用 tabler icon 替代 emoji,更精致。
4
+ -->
5
+ <script lang='ts'>
6
+ import type { AlertProps } from '../../types.js'
7
+ import { uiM } from '../../messages.js'
8
+ import { cn, getAlertVariantClass } from '../../utils.js'
9
+ import IconButton from '../primitives/IconButton.svelte'
10
+
11
+ const {
12
+ variant = 'info',
13
+ title = '',
14
+ dismissible = false,
15
+ class: className = '',
16
+ onclose,
17
+ children,
18
+ }: AlertProps = $props()
19
+
20
+ let visible = $state(true)
21
+
22
+ const alertClass = $derived(
23
+ cn(
24
+ 'alert',
25
+ getAlertVariantClass(variant),
26
+ className,
27
+ ),
28
+ )
29
+
30
+ // 图标映射:使用 tabler icon 类
31
+ const iconMap: Record<string, string> = {
32
+ info: 'icon-[tabler--info-circle]',
33
+ success: 'icon-[tabler--circle-check]',
34
+ warning: 'icon-[tabler--alert-triangle]',
35
+ error: 'icon-[tabler--circle-x]',
36
+ }
37
+
38
+ function handleClose() {
39
+ visible = false
40
+ onclose?.()
41
+ }
42
+ </script>
43
+
44
+ {#if visible}
45
+ <div class={alertClass} role='alert'>
46
+ <span class='{iconMap[variant] ?? iconMap.info} size-5 shrink-0'></span>
47
+
48
+ <div>
49
+ {#if title}
50
+ <h3 class='font-semibold text-sm'>{title}</h3>
51
+ {/if}
52
+ {#if children}
53
+ <div class='text-sm'>
54
+ {@render children()}
55
+ </div>
56
+ {/if}
57
+ </div>
58
+
59
+ {#if dismissible}
60
+ <IconButton size='sm' variant='ghost' label={uiM('common_close')} onclick={handleClose}>
61
+ {#snippet children()}
62
+ <span class='icon-[tabler--x] size-4'></span>
63
+ {/snippet}
64
+ </IconButton>
65
+ {/if}
66
+ </div>
67
+ {/if}
@@ -0,0 +1,8 @@
1
+ import type { AlertProps } from '../../types.js';
2
+ /**
3
+ * Alert
4
+ * 警告框组件,使用 tabler icon 替代 emoji,更精致。
5
+ */
6
+ declare const Alert: import("svelte").Component<AlertProps, {}, "">;
7
+ type Alert = ReturnType<typeof Alert>;
8
+ export default Alert;
@@ -0,0 +1,77 @@
1
+ <!--
2
+ @h-ai/ui — AppBar(顶部应用栏,支持安全区域)
3
+
4
+ 用法:
5
+ <AppBar title="首页">
6
+ {#snippet leading()}<BackButton />{/snippet}
7
+ {#snippet trailing()}<Avatar />{/snippet}
8
+ </AppBar>
9
+ -->
10
+ <script lang='ts'>
11
+ import type { Snippet } from 'svelte'
12
+ import { cn } from '../../utils.js'
13
+
14
+ interface Props {
15
+ /** 标题文本 */
16
+ title?: string
17
+ /** 是否适配顶部安全区域 */
18
+ safeArea?: boolean
19
+ /** 是否固定在顶部 */
20
+ fixed?: boolean
21
+ /** 额外 CSS 类 */
22
+ class?: string
23
+ /** 左侧内容(返回按钮等) */
24
+ leading?: Snippet
25
+ /** 右侧内容(操作按钮等) */
26
+ trailing?: Snippet
27
+ /** 自定义标题区域 */
28
+ children?: Snippet
29
+ }
30
+
31
+ const {
32
+ title,
33
+ safeArea = true,
34
+ fixed = true,
35
+ class: className,
36
+ leading,
37
+ trailing,
38
+ children,
39
+ }: Props = $props()
40
+ </script>
41
+
42
+ <header
43
+ class={cn(
44
+ 'flex items-center h-14 px-4 bg-base-100 border-b border-base-200',
45
+ safeArea && 'hai-safe-top',
46
+ fixed && 'fixed top-0 left-0 right-0 z-40',
47
+ className,
48
+ )}
49
+ >
50
+ <!-- 左侧 -->
51
+ <div class='flex items-center min-w-[48px]'>
52
+ {#if leading}
53
+ {@render leading()}
54
+ {/if}
55
+ </div>
56
+
57
+ <!-- 标题区域 -->
58
+ <div class='flex-1 text-center font-semibold text-base truncate'>
59
+ {#if children}
60
+ {@render children()}
61
+ {:else if title}
62
+ {title}
63
+ {/if}
64
+ </div>
65
+
66
+ <!-- 右侧 -->
67
+ <div class='flex items-center min-w-[48px] justify-end'>
68
+ {#if trailing}
69
+ {@render trailing()}
70
+ {/if}
71
+ </div>
72
+ </header>
73
+
74
+ <!-- 占位区域(fixed 模式下避免内容被遮挡) -->
75
+ {#if fixed}
76
+ <div class={cn('h-14', safeArea && 'hai-safe-top')}></div>
77
+ {/if}
@@ -0,0 +1,20 @@
1
+ import type { Snippet } from 'svelte';
2
+ interface Props {
3
+ /** 标题文本 */
4
+ title?: string;
5
+ /** 是否适配顶部安全区域 */
6
+ safeArea?: boolean;
7
+ /** 是否固定在顶部 */
8
+ fixed?: boolean;
9
+ /** 额外 CSS 类 */
10
+ class?: string;
11
+ /** 左侧内容(返回按钮等) */
12
+ leading?: Snippet;
13
+ /** 右侧内容(操作按钮等) */
14
+ trailing?: Snippet;
15
+ /** 自定义标题区域 */
16
+ children?: Snippet;
17
+ }
18
+ declare const AppBar: import("svelte").Component<Props, {}, "">;
19
+ type AppBar = ReturnType<typeof AppBar>;
20
+ export default AppBar;
@@ -0,0 +1,75 @@
1
+ <!--
2
+ @h-ai/ui — BottomNav(底部导航栏)
3
+
4
+ 用法:
5
+ <BottomNav items={navItems} active="home" onchange={(id) => goto(`/${id}`)} />
6
+ -->
7
+ <script lang='ts'>
8
+ import type { BottomNavItem } from './bottom-nav-types.js'
9
+ import { cn } from '../../utils.js'
10
+
11
+ // eslint-disable-next-line no-import-assign -- type re-export
12
+ export type { BottomNavItem }
13
+
14
+ interface Props {
15
+ /** 导航项列表 */
16
+ items: BottomNavItem[]
17
+ /** 当前激活项 ID */
18
+ active?: string
19
+ /** 切换回调 */
20
+ onchange?: (id: string) => void
21
+ /** 是否适配底部安全区域 */
22
+ safeArea?: boolean
23
+ /** 额外 CSS 类 */
24
+ class?: string
25
+ }
26
+
27
+ const {
28
+ items,
29
+ active,
30
+ onchange,
31
+ safeArea = true,
32
+ class: className,
33
+ }: Props = $props()
34
+ </script>
35
+
36
+ <nav
37
+ class={cn(
38
+ 'fixed bottom-0 left-0 right-0 bg-base-100 border-t border-base-200 z-40',
39
+ safeArea && 'hai-safe-bottom',
40
+ className,
41
+ )}
42
+ >
43
+ <div class='flex items-center justify-around h-14'>
44
+ {#each items as item (item.id)}
45
+ <button
46
+ type='button'
47
+ class={cn(
48
+ 'flex flex-col items-center justify-center flex-1 h-full relative transition-colors',
49
+ 'hai-no-select',
50
+ item.id === active ? 'text-primary' : 'text-base-content/60',
51
+ )}
52
+ onclick={() => onchange?.(item.id)}
53
+ >
54
+ <!-- 图标 -->
55
+ <div class='relative w-6 h-6 mb-0.5'>
56
+ {#if item.icon}
57
+ {@render item.icon()}
58
+ {:else if item.iconClass}
59
+ <span class='{item.iconClass} w-6 h-6'></span>
60
+ {/if}
61
+ {#if item.badge && item.badge > 0}
62
+ <span class='absolute -top-1 -right-2 badge badge-error badge-xs text-[10px] min-w-4 h-4'>
63
+ {item.badge > 99 ? '99+' : item.badge}
64
+ </span>
65
+ {/if}
66
+ </div>
67
+ <!-- 文本 -->
68
+ <span class='text-xs leading-tight'>{item.label}</span>
69
+ </button>
70
+ {/each}
71
+ </div>
72
+ </nav>
73
+
74
+ <!-- 占位(避免内容被遮挡) -->
75
+ <div class={cn('h-14', safeArea && 'hai-safe-bottom')}></div>
@@ -0,0 +1,18 @@
1
+ import type { BottomNavItem } from './bottom-nav-types.js';
2
+ interface Props {
3
+ /** 导航项列表 */
4
+ items: BottomNavItem[];
5
+ /** 当前激活项 ID */
6
+ active?: string;
7
+ /** 切换回调 */
8
+ onchange?: (id: string) => void;
9
+ /** 是否适配底部安全区域 */
10
+ safeArea?: boolean;
11
+ /** 额外 CSS 类 */
12
+ class?: string;
13
+ }
14
+ declare const BottomNav: import("svelte").Component<Props, {
15
+ BottomNavItem: typeof BottomNavItem;
16
+ }, "">;
17
+ type BottomNav = ReturnType<typeof BottomNav>;
18
+ export default BottomNav;
@@ -0,0 +1,49 @@
1
+ <!--
2
+ =============================================================================
3
+ @h-ai/ui - Breadcrumb 组件
4
+ =============================================================================
5
+ 面包屑导航组件
6
+
7
+ 使用 Svelte 5 Runes ($props)
8
+ =============================================================================
9
+ -->
10
+ <script lang='ts'>
11
+ import type { BreadcrumbProps } from '../../types.js'
12
+ import { cn } from '../../utils.js'
13
+
14
+ const {
15
+ items,
16
+ class: className = '',
17
+ }: BreadcrumbProps = $props()
18
+
19
+ const breadcrumbClass = $derived(
20
+ cn(
21
+ 'breadcrumbs text-sm',
22
+ className,
23
+ ),
24
+ )
25
+ </script>
26
+
27
+ <div class={breadcrumbClass}>
28
+ <ul>
29
+ {#each items as item, index}
30
+ <li>
31
+ {#if item.href && index < items.length - 1}
32
+ <a href={item.href}>
33
+ {#if item.icon}
34
+ <span class='mr-1'>{item.icon}</span>
35
+ {/if}
36
+ {item.label}
37
+ </a>
38
+ {:else}
39
+ <span>
40
+ {#if item.icon}
41
+ <span class='mr-1'>{item.icon}</span>
42
+ {/if}
43
+ {item.label}
44
+ </span>
45
+ {/if}
46
+ </li>
47
+ {/each}
48
+ </ul>
49
+ </div>
@@ -0,0 +1,4 @@
1
+ import type { BreadcrumbProps } from '../../types.js';
2
+ declare const Breadcrumb: import("svelte").Component<BreadcrumbProps, {}, "">;
3
+ type Breadcrumb = ReturnType<typeof Breadcrumb>;
4
+ export default Breadcrumb;
@@ -0,0 +1,116 @@
1
+ <!--
2
+ @component Calendar
3
+ 日历组件,基于 Bits UI headless + DaisyUI 样式。
4
+ 支持单选/多选、日期范围限制、自定义不可用日期。
5
+
6
+ @prop {DateValue} value - 选中日期(双向绑定)
7
+ @prop {DateValue} minValue - 最小可选日期
8
+ @prop {DateValue} maxValue - 最大可选日期
9
+ @prop {number} weekStartsOn - 周起始日(0=周日,1=周一)
10
+ @prop {function} isDateUnavailable - 自定义不可用日期判断函数
11
+ @prop {function} onchange - 日期变更回调
12
+
13
+ @example
14
+ ```svelte
15
+ <script>
16
+ import { CalendarDate } from '@internationalized/date'
17
+ let date = $state(new CalendarDate(2024, 1, 15))
18
+ </script>
19
+ <Calendar bind:value={date} />
20
+ ```
21
+ -->
22
+ <script lang='ts'>
23
+ import type { DateValue } from '@internationalized/date'
24
+ import { Calendar as BitsCalendar } from 'bits-ui'
25
+
26
+ interface Props {
27
+ /** 选中日期(双向绑定) */
28
+ value?: DateValue
29
+ /** 占位日期(控制日历显示月份) */
30
+ placeholder?: DateValue
31
+ /** 最小可选日期 */
32
+ minValue?: DateValue
33
+ /** 最大可选日期 */
34
+ maxValue?: DateValue
35
+ /** 周起始日(0=周日,1=周一,默认 1) */
36
+ weekStartsOn?: 0 | 1 | 2 | 3 | 4 | 5 | 6
37
+ /** 自定义不可用日期判断函数 */
38
+ isDateUnavailable?: (date: DateValue) => boolean
39
+ /** 是否禁用 */
40
+ disabled?: boolean
41
+ /** 是否只读 */
42
+ readonly?: boolean
43
+ /** 自定义类名 */
44
+ class?: string
45
+ /** 日期变更回调 */
46
+ onchange?: (value: DateValue | undefined) => void
47
+ }
48
+
49
+ let {
50
+ value = $bindable(),
51
+ placeholder = $bindable(),
52
+ minValue,
53
+ maxValue,
54
+ weekStartsOn = 1,
55
+ isDateUnavailable,
56
+ disabled = false,
57
+ readonly: isReadonly = false,
58
+ class: className = '',
59
+ onchange,
60
+ }: Props = $props()
61
+ </script>
62
+
63
+ <div class={className}>
64
+ <BitsCalendar.Root
65
+ type='single'
66
+ bind:value
67
+ bind:placeholder
68
+ {minValue}
69
+ {maxValue}
70
+ {weekStartsOn}
71
+ {isDateUnavailable}
72
+ {disabled}
73
+ readonly={isReadonly}
74
+ onValueChange={v => onchange?.(v)}
75
+ >
76
+ {#snippet children({ months, weekdays })}
77
+ <BitsCalendar.Header class='flex items-center justify-between px-1 pb-3'>
78
+ <BitsCalendar.PrevButton class='btn btn-ghost btn-sm btn-circle'>
79
+ <span class='icon-[tabler--chevron-left] size-4'></span>
80
+ </BitsCalendar.PrevButton>
81
+ <BitsCalendar.Heading class='text-sm font-semibold' />
82
+ <BitsCalendar.NextButton class='btn btn-ghost btn-sm btn-circle'>
83
+ <span class='icon-[tabler--chevron-right] size-4'></span>
84
+ </BitsCalendar.NextButton>
85
+ </BitsCalendar.Header>
86
+
87
+ {#each months as month}
88
+ <BitsCalendar.Grid class='w-full border-collapse'>
89
+ <BitsCalendar.GridHead>
90
+ <BitsCalendar.GridRow class='flex w-full'>
91
+ {#each weekdays as day}
92
+ <BitsCalendar.HeadCell class='w-9 text-center text-xs font-medium text-base-content/50'>
93
+ {day}
94
+ </BitsCalendar.HeadCell>
95
+ {/each}
96
+ </BitsCalendar.GridRow>
97
+ </BitsCalendar.GridHead>
98
+
99
+ <BitsCalendar.GridBody>
100
+ {#each month.weeks as weekDates}
101
+ <BitsCalendar.GridRow class='flex w-full'>
102
+ {#each weekDates as date}
103
+ <BitsCalendar.Cell {date} month={month.value} class='p-0'>
104
+ <BitsCalendar.Day class='inline-flex size-9 items-center justify-center rounded-lg text-sm transition-colors hover:bg-base-200 data-[selected]:bg-primary data-[selected]:text-primary-content data-[disabled]:opacity-30 data-[unavailable]:line-through data-[unavailable]:opacity-30 data-[outside-month]:text-base-content/30'>
105
+ {date.day}
106
+ </BitsCalendar.Day>
107
+ </BitsCalendar.Cell>
108
+ {/each}
109
+ </BitsCalendar.GridRow>
110
+ {/each}
111
+ </BitsCalendar.GridBody>
112
+ </BitsCalendar.Grid>
113
+ {/each}
114
+ {/snippet}
115
+ </BitsCalendar.Root>
116
+ </div>
@@ -0,0 +1,47 @@
1
+ import type { DateValue } from '@internationalized/date';
2
+ interface Props {
3
+ /** 选中日期(双向绑定) */
4
+ value?: DateValue;
5
+ /** 占位日期(控制日历显示月份) */
6
+ placeholder?: DateValue;
7
+ /** 最小可选日期 */
8
+ minValue?: DateValue;
9
+ /** 最大可选日期 */
10
+ maxValue?: DateValue;
11
+ /** 周起始日(0=周日,1=周一,默认 1) */
12
+ weekStartsOn?: 0 | 1 | 2 | 3 | 4 | 5 | 6;
13
+ /** 自定义不可用日期判断函数 */
14
+ isDateUnavailable?: (date: DateValue) => boolean;
15
+ /** 是否禁用 */
16
+ disabled?: boolean;
17
+ /** 是否只读 */
18
+ readonly?: boolean;
19
+ /** 自定义类名 */
20
+ class?: string;
21
+ /** 日期变更回调 */
22
+ onchange?: (value: DateValue | undefined) => void;
23
+ }
24
+ /**
25
+ * Calendar
26
+ * 日历组件,基于 Bits UI headless + DaisyUI 样式。
27
+ * 支持单选/多选、日期范围限制、自定义不可用日期。
28
+ *
29
+ * @prop {DateValue} value - 选中日期(双向绑定)
30
+ * @prop {DateValue} minValue - 最小可选日期
31
+ * @prop {DateValue} maxValue - 最大可选日期
32
+ * @prop {number} weekStartsOn - 周起始日(0=周日,1=周一)
33
+ * @prop {function} isDateUnavailable - 自定义不可用日期判断函数
34
+ * @prop {function} onchange - 日期变更回调
35
+ *
36
+ * @example
37
+ * ```svelte
38
+ * <script>
39
+ * import { CalendarDate } from '@internationalized/date'
40
+ * let date = $state(new CalendarDate(2024, 1, 15))
41
+ * </script>
42
+ * <Calendar bind:value={date} />
43
+ * ```
44
+ */
45
+ declare const Calendar: import("svelte").Component<Props, {}, "value" | "placeholder">;
46
+ type Calendar = ReturnType<typeof Calendar>;
47
+ export default Calendar;
@@ -0,0 +1,77 @@
1
+ <!--
2
+ @component Card
3
+ 卡片组件,默认使用 border 而非 shadow,更现代克制。
4
+ -->
5
+ <script lang='ts'>
6
+ import type { CardProps } from '../../types.js'
7
+ import { cn } from '../../utils.js'
8
+
9
+ const {
10
+ title = '',
11
+ bordered = false,
12
+ shadow = 'sm',
13
+ padding = 'md',
14
+ class: className = '',
15
+ header,
16
+ footer,
17
+ children,
18
+ }: CardProps = $props()
19
+
20
+ const paddingMap = {
21
+ 'none': '',
22
+ 'xs': 'p-2',
23
+ 'sm': 'p-3',
24
+ 'md': 'p-4',
25
+ 'lg': 'p-6',
26
+ 'xl': 'p-8',
27
+ '2xl': 'p-10',
28
+ '3xl': 'p-12',
29
+ '4xl': 'p-16',
30
+ }
31
+
32
+ const shadowMap = {
33
+ true: 'shadow-md',
34
+ false: '',
35
+ sm: 'shadow-sm',
36
+ md: 'shadow-md',
37
+ lg: 'shadow-lg',
38
+ }
39
+
40
+ const cardClass = $derived(
41
+ cn(
42
+ 'card bg-base-100 rounded-xl border border-base-content/6',
43
+ bordered && 'border-base-300',
44
+ typeof shadow === 'boolean' ? shadowMap[String(shadow) as 'true' | 'false'] : shadowMap[shadow],
45
+ className,
46
+ ),
47
+ )
48
+
49
+ const bodyClass = $derived(
50
+ cn(
51
+ 'card-body',
52
+ paddingMap[padding],
53
+ ),
54
+ )
55
+ </script>
56
+
57
+ <div class={cardClass}>
58
+ <div class={bodyClass}>
59
+ {#if header}
60
+ <div class='card-title text-sm font-semibold'>
61
+ {@render header()}
62
+ </div>
63
+ {:else if title}
64
+ <h2 class='card-title text-sm font-semibold'>{title}</h2>
65
+ {/if}
66
+
67
+ {#if children}
68
+ {@render children()}
69
+ {/if}
70
+
71
+ {#if footer}
72
+ <div class='card-actions justify-end mt-4'>
73
+ {@render footer()}
74
+ </div>
75
+ {/if}
76
+ </div>
77
+ </div>
@@ -0,0 +1,8 @@
1
+ import type { CardProps } from '../../types.js';
2
+ /**
3
+ * Card
4
+ * 卡片组件,默认使用 border 而非 shadow,更现代克制。
5
+ */
6
+ declare const Card: import("svelte").Component<CardProps, {}, "">;
7
+ type Card = ReturnType<typeof Card>;
8
+ export default Card;