@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,102 @@
1
+ <!--
2
+ @component Avatar
3
+ 头像组件,支持图片、名字首字母 fallback
4
+ -->
5
+ <script lang='ts'>
6
+ import type { AvatarProps } from '../../types.js'
7
+ import { cn } from '../../utils.js'
8
+
9
+ const {
10
+ src = '',
11
+ alt = '',
12
+ name = '',
13
+ size = 'md',
14
+ shape = 'circle',
15
+ class: className = '',
16
+ }: AvatarProps = $props()
17
+
18
+ const sizeMap = {
19
+ 'xs': 'w-6 h-6',
20
+ 'sm': 'w-8 h-8',
21
+ 'md': 'w-10 h-10',
22
+ 'lg': 'w-14 h-14',
23
+ 'xl': 'w-20 h-20',
24
+ '2xl': 'w-24 h-24',
25
+ '3xl': 'w-28 h-28',
26
+ '4xl': 'w-32 h-32',
27
+ }
28
+
29
+ const textSizeMap = {
30
+ 'xs': 'text-2xs',
31
+ 'sm': 'text-xs',
32
+ 'md': 'text-sm',
33
+ 'lg': 'text-lg',
34
+ 'xl': 'text-2xl',
35
+ '2xl': 'text-3xl',
36
+ '3xl': 'text-4xl',
37
+ '4xl': 'text-5xl',
38
+ }
39
+
40
+ /* 获取名称首字母 */
41
+ const initials = $derived(() => {
42
+ if (!name)
43
+ return ''
44
+ const parts = name.trim().split(/\s+/)
45
+ if (parts.length >= 2) {
46
+ return (parts[0][0] + parts[1][0]).toUpperCase()
47
+ }
48
+ return name.slice(0, 2).toUpperCase()
49
+ })
50
+
51
+ /* 根据名称 hash 生成渐变色 */
52
+ const gradientPairs = [
53
+ ['from-blue-400 to-indigo-500', 'text-white'],
54
+ ['from-emerald-400 to-teal-500', 'text-white'],
55
+ ['from-amber-400 to-orange-500', 'text-white'],
56
+ ['from-rose-400 to-pink-500', 'text-white'],
57
+ ['from-violet-400 to-purple-500', 'text-white'],
58
+ ['from-cyan-400 to-sky-500', 'text-white'],
59
+ ] as const
60
+
61
+ const colorPair = $derived(() => {
62
+ if (!name)
63
+ return gradientPairs[0]
64
+ const hash = name.split('').reduce((acc, char) => acc + char.charCodeAt(0), 0)
65
+ return gradientPairs[hash % gradientPairs.length]
66
+ })
67
+
68
+ const sizeValue = $derived(typeof size === 'number' ? `${size}px` : undefined)
69
+
70
+ const containerClass = $derived(
71
+ cn(
72
+ 'avatar',
73
+ !src && 'placeholder',
74
+ ),
75
+ )
76
+
77
+ const innerClass = $derived(
78
+ cn(
79
+ 'flex items-center justify-center font-semibold',
80
+ typeof size === 'string' && sizeMap[size],
81
+ shape === 'circle' ? 'rounded-full' : 'rounded-lg',
82
+ !src && `bg-gradient-to-br ${colorPair()[0]} ${colorPair()[1]}`,
83
+ className,
84
+ ),
85
+ )
86
+ </script>
87
+
88
+ <div class={containerClass}>
89
+ <div
90
+ class={innerClass}
91
+ style:width={sizeValue}
92
+ style:height={sizeValue}
93
+ >
94
+ {#if src}
95
+ <img {src} {alt} />
96
+ {:else}
97
+ <span class={typeof size === 'string' ? textSizeMap[size] : 'text-lg'}>
98
+ {initials()}
99
+ </span>
100
+ {/if}
101
+ </div>
102
+ </div>
@@ -0,0 +1,8 @@
1
+ import type { AvatarProps } from '../../types.js';
2
+ /**
3
+ * Avatar
4
+ * 头像组件,支持图片、名字首字母 fallback
5
+ */
6
+ declare const Avatar: import("svelte").Component<AvatarProps, {}, "">;
7
+ type Avatar = ReturnType<typeof Avatar>;
8
+ export default Avatar;
@@ -0,0 +1,33 @@
1
+ <!--
2
+ @component Badge
3
+ 徽章组件,支持多种变体与尺寸
4
+ -->
5
+ <script lang='ts'>
6
+ import type { BadgeProps } from '../../types.js'
7
+ import { cn, getBadgeSizeClass, getBadgeVariantClass } from '../../utils.js'
8
+
9
+ const {
10
+ variant = 'default',
11
+ size = 'md',
12
+ outline = false,
13
+ class: className = '',
14
+ children,
15
+ }: BadgeProps = $props()
16
+
17
+ const badgeClass = $derived(
18
+ cn(
19
+ 'badge',
20
+ getBadgeVariantClass(variant),
21
+ getBadgeSizeClass(size),
22
+ outline && 'badge-outline',
23
+ 'font-medium tracking-tight',
24
+ className,
25
+ ),
26
+ )
27
+ </script>
28
+
29
+ <span class={badgeClass}>
30
+ {#if children}
31
+ {@render children()}
32
+ {/if}
33
+ </span>
@@ -0,0 +1,8 @@
1
+ import type { BadgeProps } from '../../types.js';
2
+ /**
3
+ * Badge
4
+ * 徽章组件,支持多种变体与尺寸
5
+ */
6
+ declare const Badge: import("svelte").Component<BadgeProps, {}, "">;
7
+ type Badge = ReturnType<typeof Badge>;
8
+ export default Badge;
@@ -0,0 +1,45 @@
1
+ <!--
2
+ =============================================================================
3
+ @h-ai/ui - BareButton 组件
4
+ =============================================================================
5
+ 无样式按钮组件(不注入 btn 类),用于自定义布局场景
6
+
7
+ 使用 Svelte 5 Runes ($props)
8
+ =============================================================================
9
+ -->
10
+ <script lang='ts'>
11
+ import type { BareButtonProps } from '../../types.js'
12
+
13
+ const {
14
+ type = 'button',
15
+ disabled = false,
16
+ class: className = '',
17
+ ariaLabel = '',
18
+ role = undefined,
19
+ ariaSelected = undefined,
20
+ tabindex = undefined,
21
+ onclick,
22
+ onkeydown,
23
+ children,
24
+ }: BareButtonProps = $props()
25
+
26
+ function handleClick(e: MouseEvent) {
27
+ onclick?.(e)
28
+ }
29
+ </script>
30
+
31
+ <button
32
+ {type}
33
+ class={className}
34
+ disabled={disabled}
35
+ aria-label={ariaLabel || undefined}
36
+ role={role}
37
+ aria-selected={ariaSelected}
38
+ tabindex={tabindex}
39
+ onclick={handleClick}
40
+ onkeydown={onkeydown}
41
+ >
42
+ {#if children}
43
+ {@render children()}
44
+ {/if}
45
+ </button>
@@ -0,0 +1,4 @@
1
+ import type { BareButtonProps } from '../../types.js';
2
+ declare const BareButton: import("svelte").Component<BareButtonProps, {}, "">;
3
+ type BareButton = ReturnType<typeof BareButton>;
4
+ export default BareButton;
@@ -0,0 +1,101 @@
1
+ <!--
2
+ =============================================================================
3
+ @h-ai/ui - BareInput 组件
4
+ =============================================================================
5
+ 无样式输入框组件,仅渲染原生 input
6
+
7
+ 使用 Svelte 5 Runes ($props, $bindable)
8
+ =============================================================================
9
+ -->
10
+ <script lang='ts'>
11
+ import type { BareInputProps } from '../../types.js'
12
+
13
+ let {
14
+ value = $bindable(''),
15
+ type = 'text',
16
+ placeholder,
17
+ disabled = false,
18
+ readonly = false,
19
+ required = false,
20
+ class: className = '',
21
+ id,
22
+ name,
23
+ autocomplete,
24
+ pattern,
25
+ list,
26
+ accept,
27
+ multiple,
28
+ minlength,
29
+ maxlength,
30
+ min,
31
+ max,
32
+ step,
33
+ inputmode,
34
+ inputRef = $bindable<HTMLInputElement | undefined>(),
35
+ role,
36
+ ariaExpanded,
37
+ ariaControls,
38
+ ariaAutocomplete,
39
+ oninput,
40
+ onchange,
41
+ onkeydown,
42
+ onblur,
43
+ onfocus,
44
+ oninvalid,
45
+ }: BareInputProps = $props()
46
+
47
+ function handleInput(e: Event & { currentTarget: HTMLInputElement }) {
48
+ value = e.currentTarget.value
49
+ oninput?.(e)
50
+ }
51
+
52
+ function handleChange(e: Event & { currentTarget: HTMLInputElement }) {
53
+ onchange?.(e)
54
+ }
55
+
56
+ function handleKeydown(e: KeyboardEvent & { currentTarget: HTMLInputElement }) {
57
+ onkeydown?.(e)
58
+ }
59
+
60
+ function handleBlur(e: FocusEvent & { currentTarget: HTMLInputElement }) {
61
+ onblur?.(e)
62
+ }
63
+
64
+ function handleFocus(e: FocusEvent & { currentTarget: HTMLInputElement }) {
65
+ onfocus?.(e)
66
+ }
67
+ </script>
68
+
69
+ <input
70
+ bind:this={inputRef}
71
+ {id}
72
+ {name}
73
+ {type}
74
+ {placeholder}
75
+ {disabled}
76
+ {readonly}
77
+ {required}
78
+ {pattern}
79
+ {list}
80
+ {accept}
81
+ {multiple}
82
+ {minlength}
83
+ {min}
84
+ {max}
85
+ {maxlength}
86
+ {step}
87
+ inputmode={inputmode}
88
+ autocomplete={autocomplete as HTMLInputElement['autocomplete']}
89
+ role={role}
90
+ aria-expanded={ariaExpanded}
91
+ aria-controls={ariaControls}
92
+ aria-autocomplete={ariaAutocomplete}
93
+ class={className}
94
+ bind:value
95
+ oninput={handleInput}
96
+ onchange={handleChange}
97
+ onkeydown={handleKeydown}
98
+ onblur={handleBlur}
99
+ onfocus={handleFocus}
100
+ oninvalid={oninvalid}
101
+ />
@@ -0,0 +1,4 @@
1
+ import type { BareInputProps } from '../../types.js';
2
+ declare const BareInput: import("svelte").Component<BareInputProps, {}, "value" | "inputRef">;
3
+ type BareInput = ReturnType<typeof BareInput>;
4
+ export default BareInput;
@@ -0,0 +1,60 @@
1
+ <!--
2
+ @component Button
3
+ 通用按钮组件,支持多种变体和尺寸。
4
+ -->
5
+ <script lang='ts'>
6
+ import type { ButtonProps } from '../../types.js'
7
+ import { cn, getSizeClass, getVariantClass } from '../../utils.js'
8
+
9
+ const {
10
+ variant = 'default',
11
+ size = 'md',
12
+ ariaLabel = '',
13
+ disabled = false,
14
+ loading = false,
15
+ outline = false,
16
+ circle = false,
17
+ class: className = '',
18
+ type = 'button',
19
+ onclick,
20
+ children,
21
+ }: ButtonProps = $props()
22
+
23
+ const buttonClass = $derived(
24
+ cn(
25
+ 'btn no-animation',
26
+ getVariantClass(variant),
27
+ getSizeClass(size),
28
+ outline && 'btn-outline',
29
+ circle && 'btn-circle',
30
+ loading && 'opacity-70 pointer-events-none',
31
+ 'font-medium tracking-[-0.01em]',
32
+ 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/40 focus-visible:ring-offset-2 focus-visible:ring-offset-base-100',
33
+ 'active:scale-[0.97]',
34
+ className,
35
+ ),
36
+ )
37
+
38
+ function handleClick(e: MouseEvent) {
39
+ if (disabled || loading) {
40
+ e.preventDefault()
41
+ return
42
+ }
43
+ onclick?.(e)
44
+ }
45
+ </script>
46
+
47
+ <button
48
+ {type}
49
+ class={buttonClass}
50
+ disabled={disabled || loading}
51
+ aria-label={ariaLabel || undefined}
52
+ onclick={handleClick}
53
+ >
54
+ {#if loading}
55
+ <span class='loading loading-spinner loading-xs'></span>
56
+ {/if}
57
+ {#if children}
58
+ {@render children()}
59
+ {/if}
60
+ </button>
@@ -0,0 +1,8 @@
1
+ import type { ButtonProps } from '../../types.js';
2
+ /**
3
+ * Button
4
+ * 通用按钮组件,支持多种变体和尺寸。
5
+ */
6
+ declare const Button: import("svelte").Component<ButtonProps, {}, "">;
7
+ type Button = ReturnType<typeof Button>;
8
+ export default Button;
@@ -0,0 +1,58 @@
1
+ <!--
2
+ =============================================================================
3
+ @h-ai/ui - Checkbox 组件
4
+ =============================================================================
5
+ 复选框组件
6
+
7
+ 使用 Svelte 5 Runes ($props, $derived, $bindable)
8
+ =============================================================================
9
+ -->
10
+ <script lang='ts'>
11
+ import type { CheckboxProps } from '../../types.js'
12
+ import { cn, generateId, getSizeClass } from '../../utils.js'
13
+
14
+ let {
15
+ checked = $bindable(false),
16
+ label = '',
17
+ size = 'md',
18
+ disabled = false,
19
+ readonly = false,
20
+ indeterminate = false,
21
+ class: className = '',
22
+ onchange,
23
+ }: CheckboxProps = $props()
24
+
25
+ const id = generateId('checkbox')
26
+
27
+ const checkboxClass = $derived(
28
+ cn(
29
+ 'checkbox',
30
+ getSizeClass(size, 'checkbox'),
31
+ className,
32
+ ),
33
+ )
34
+
35
+ function handleChange(e: Event & { currentTarget: HTMLInputElement }) {
36
+ if (readonly)
37
+ return
38
+ checked = e.currentTarget.checked
39
+ onchange?.(checked)
40
+ }
41
+ </script>
42
+
43
+ <div class='inline-flex'>
44
+ <label class='label cursor-pointer gap-2' for={id}>
45
+ <input
46
+ {id}
47
+ type='checkbox'
48
+ class={checkboxClass}
49
+ disabled={disabled || readonly}
50
+ bind:checked
51
+ bind:indeterminate
52
+ onchange={handleChange}
53
+ />
54
+ {#if label}
55
+ <span>{label}</span>
56
+ {/if}
57
+ </label>
58
+ </div>
@@ -0,0 +1,4 @@
1
+ import type { CheckboxProps } from '../../types.js';
2
+ declare const Checkbox: import("svelte").Component<CheckboxProps, {}, "checked">;
3
+ type Checkbox = ReturnType<typeof Checkbox>;
4
+ export default Checkbox;
@@ -0,0 +1,105 @@
1
+ <!--
2
+ =============================================================================
3
+ @h-ai/ui - IconButton 组件
4
+ =============================================================================
5
+ 图标按钮组件
6
+
7
+ 使用 Svelte 5 Runes ($props, $derived)
8
+ =============================================================================
9
+ -->
10
+ <script lang='ts'>
11
+ import type { IconButtonProps } from '../../types.js'
12
+ import { cn, getSizeClass, getVariantClass } from '../../utils.js'
13
+
14
+ const {
15
+ icon,
16
+ label = '',
17
+ ariaLabel = '',
18
+ tooltip = '',
19
+ variant = 'default',
20
+ size = 'md',
21
+ disabled = false,
22
+ loading = false,
23
+ class: className = '',
24
+ onclick,
25
+ children,
26
+ }: IconButtonProps = $props()
27
+
28
+ /** 计算最终的 aria-label */
29
+ const computedAriaLabel = $derived(ariaLabel || label || tooltip)
30
+
31
+ const buttonClass = $derived(
32
+ cn(
33
+ 'btn btn-circle',
34
+ getVariantClass(variant),
35
+ getSizeClass(size),
36
+ loading && 'btn-loading',
37
+ className,
38
+ ),
39
+ )
40
+
41
+ const iconSize = $derived({
42
+ 'xs': 'w-3 h-3',
43
+ 'sm': 'w-4 h-4',
44
+ 'md': 'w-5 h-5',
45
+ 'lg': 'w-6 h-6',
46
+ 'xl': 'w-7 h-7',
47
+ '2xl': 'w-8 h-8',
48
+ '3xl': 'w-9 h-9',
49
+ '4xl': 'w-10 h-10',
50
+ }[size])
51
+
52
+ function handleClick(e: MouseEvent) {
53
+ if (disabled || loading) {
54
+ e.preventDefault()
55
+ return
56
+ }
57
+ onclick?.(e)
58
+ }
59
+ </script>
60
+
61
+ {#if tooltip}
62
+ <div class='tooltip' data-tip={tooltip}>
63
+ <button
64
+ type='button'
65
+ class={buttonClass}
66
+ {disabled}
67
+ aria-label={computedAriaLabel}
68
+ onclick={handleClick}
69
+ >
70
+ {#if loading}
71
+ <span class='loading loading-spinner'></span>
72
+ {:else if children}
73
+ {@render children()}
74
+ {:else if typeof icon === 'function'}
75
+ {@render icon()}
76
+ {:else if icon}
77
+ <span class={iconSize}>
78
+ <!-- eslint-disable-next-line svelte/no-at-html-tags -- 受控 SVG 图标渲染 -->
79
+ {@html icon}
80
+ </span>
81
+ {/if}
82
+ </button>
83
+ </div>
84
+ {:else}
85
+ <button
86
+ type='button'
87
+ class={buttonClass}
88
+ {disabled}
89
+ aria-label={computedAriaLabel}
90
+ onclick={handleClick}
91
+ >
92
+ {#if loading}
93
+ <span class='loading loading-spinner'></span>
94
+ {:else if children}
95
+ {@render children()}
96
+ {:else if typeof icon === 'function'}
97
+ {@render icon()}
98
+ {:else if icon}
99
+ <span class={iconSize}>
100
+ <!-- eslint-disable-next-line svelte/no-at-html-tags -- 受控 SVG 图标渲染 -->
101
+ {@html icon}
102
+ </span>
103
+ {/if}
104
+ </button>
105
+ {/if}
@@ -0,0 +1,4 @@
1
+ import type { IconButtonProps } from '../../types.js';
2
+ declare const IconButton: import("svelte").Component<IconButtonProps, {}, "">;
3
+ type IconButton = ReturnType<typeof IconButton>;
4
+ export default IconButton;
@@ -0,0 +1,130 @@
1
+ <!--
2
+ @component Input
3
+ 文本输入框组件,支持自定义验证消息
4
+ -->
5
+ <script lang='ts'>
6
+ import type { InputProps } from '../../types.js'
7
+ import { cn } from '../../utils.js'
8
+
9
+ let {
10
+ value = $bindable(''),
11
+ placeholder = '',
12
+ type = 'text',
13
+ size = 'md',
14
+ disabled = false,
15
+ readonly = false,
16
+ required = false,
17
+ error = '',
18
+ validationMessage = '',
19
+ class: className = '',
20
+ id,
21
+ name,
22
+ autocomplete,
23
+ pattern,
24
+ list,
25
+ inputmode,
26
+ step,
27
+ minlength,
28
+ min,
29
+ max,
30
+ maxlength,
31
+ inputRef = $bindable<HTMLInputElement | undefined>(),
32
+ oninput,
33
+ onchange,
34
+ onkeydown,
35
+ onblur,
36
+ onfocus,
37
+ oninvalid,
38
+ }: InputProps = $props()
39
+
40
+ const containerHeight = $derived(
41
+ size === 'xs'
42
+ ? 'h-8'
43
+ : size === 'sm'
44
+ ? 'h-9'
45
+ : size === 'lg'
46
+ ? 'h-12'
47
+ : size === 'xl'
48
+ ? 'h-14'
49
+ : 'h-10',
50
+ )
51
+
52
+ const containerClass = $derived(
53
+ cn(
54
+ 'flex items-center w-full rounded-lg border bg-base-100',
55
+ containerHeight,
56
+ error
57
+ ? 'border-error/60 focus-within:ring-2 focus-within:ring-error/15'
58
+ : 'border-base-content/15 focus-within:border-primary/50 focus-within:ring-2 focus-within:ring-primary/10',
59
+ 'transition-[border-color,box-shadow] duration-150',
60
+ disabled && 'opacity-50 cursor-not-allowed',
61
+ className,
62
+ ),
63
+ )
64
+
65
+ function handleInput(e: Event & { currentTarget: HTMLInputElement }) {
66
+ if (validationMessage) {
67
+ e.currentTarget.setCustomValidity('')
68
+ }
69
+ value = e.currentTarget.value
70
+ oninput?.(e)
71
+ }
72
+
73
+ function handleChange(e: Event & { currentTarget: HTMLInputElement }) {
74
+ onchange?.(e)
75
+ }
76
+
77
+ function handleKeydown(e: KeyboardEvent & { currentTarget: HTMLInputElement }) {
78
+ onkeydown?.(e)
79
+ }
80
+
81
+ function handleBlur(e: FocusEvent & { currentTarget: HTMLInputElement }) {
82
+ onblur?.(e)
83
+ }
84
+
85
+ function handleFocus(e: FocusEvent & { currentTarget: HTMLInputElement }) {
86
+ onfocus?.(e)
87
+ }
88
+
89
+ function handleInvalid(e: Event & { currentTarget: HTMLInputElement }) {
90
+ if (validationMessage) {
91
+ e.currentTarget.setCustomValidity(validationMessage)
92
+ }
93
+ oninvalid?.(e)
94
+ }
95
+ </script>
96
+
97
+ <div class='fieldset w-full'>
98
+ <div class={containerClass}>
99
+ <input
100
+ bind:this={inputRef}
101
+ {id}
102
+ {name}
103
+ {type}
104
+ {placeholder}
105
+ {disabled}
106
+ {readonly}
107
+ {required}
108
+ {pattern}
109
+ {list}
110
+ {minlength}
111
+ {min}
112
+ {max}
113
+ {maxlength}
114
+ {step}
115
+ inputmode={inputmode}
116
+ autocomplete={autocomplete as HTMLInputElement['autocomplete']}
117
+ class='flex-1 h-full px-3 bg-transparent border-none outline-none text-sm placeholder:text-base-content/35'
118
+ bind:value
119
+ oninput={handleInput}
120
+ onchange={handleChange}
121
+ onkeydown={handleKeydown}
122
+ onblur={handleBlur}
123
+ onfocus={handleFocus}
124
+ oninvalid={handleInvalid}
125
+ />
126
+ </div>
127
+ {#if error}
128
+ <p class='mt-1.5 text-xs text-error/80 leading-tight'>{error}</p>
129
+ {/if}
130
+ </div>
@@ -0,0 +1,8 @@
1
+ import type { InputProps } from '../../types.js';
2
+ /**
3
+ * Input
4
+ * 文本输入框组件,支持自定义验证消息
5
+ */
6
+ declare const Input: import("svelte").Component<InputProps, {}, "value" | "inputRef">;
7
+ type Input = ReturnType<typeof Input>;
8
+ export default Input;