@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,58 @@
1
+ <!--
2
+ =============================================================================
3
+ @h-ai/ui - Progress 组件
4
+ =============================================================================
5
+ 进度条组件
6
+
7
+ 使用 Svelte 5 Runes ($props, $derived)
8
+ =============================================================================
9
+ -->
10
+ <script lang='ts'>
11
+ import type { ProgressProps } from '../../types.js'
12
+ import { cn, getProgressVariantClass } from '../../utils.js'
13
+
14
+ const {
15
+ value,
16
+ max = 100,
17
+ size = 'md',
18
+ variant = 'primary',
19
+ showLabel = false,
20
+ class: className = '',
21
+ }: ProgressProps = $props()
22
+
23
+ const sizeMap = {
24
+ 'xs': 'h-1',
25
+ 'sm': 'h-2',
26
+ 'md': 'h-3',
27
+ 'lg': 'h-4',
28
+ 'xl': 'h-5',
29
+ '2xl': 'h-6',
30
+ '3xl': 'h-7',
31
+ '4xl': 'h-8',
32
+ }
33
+
34
+ const percentage = $derived(Math.min(100, Math.max(0, (value / max) * 100)))
35
+
36
+ const progressClass = $derived(
37
+ cn(
38
+ 'progress w-full',
39
+ getProgressVariantClass(variant),
40
+ sizeMap[size],
41
+ className,
42
+ ),
43
+ )
44
+ </script>
45
+
46
+ <div class='w-full'>
47
+ <progress
48
+ class={progressClass}
49
+ {value}
50
+ {max}
51
+ ></progress>
52
+
53
+ {#if showLabel}
54
+ <div class='text-xs text-center mt-1'>
55
+ {percentage.toFixed(0)}%
56
+ </div>
57
+ {/if}
58
+ </div>
@@ -0,0 +1,4 @@
1
+ import type { ProgressProps } from '../../types.js';
2
+ declare const Progress: import("svelte").Component<ProgressProps, {}, "">;
3
+ type Progress = ReturnType<typeof Progress>;
4
+ export default Progress;
@@ -0,0 +1,60 @@
1
+ <!--
2
+ =============================================================================
3
+ @h-ai/ui - Radio 组件
4
+ =============================================================================
5
+ 单选框组件,支持组模式
6
+
7
+ 使用 Svelte 5 Runes ($props, $derived, $bindable)
8
+ =============================================================================
9
+ -->
10
+ <script lang='ts' generics="T = string">
11
+ import type { RadioProps, SelectOption } from '../../types.js'
12
+ import { cn, getSizeClass } from '../../utils.js'
13
+
14
+ let {
15
+ value = $bindable() as T,
16
+ options = [] as SelectOption<T>[],
17
+ name = '',
18
+ size = 'md',
19
+ disabled = false,
20
+ direction = 'vertical',
21
+ class: className = '',
22
+ onchange,
23
+ }: RadioProps<T> = $props()
24
+
25
+ const containerClass = $derived(
26
+ cn(
27
+ 'flex gap-2',
28
+ direction === 'horizontal' ? 'flex-row flex-wrap' : 'flex-col',
29
+ className,
30
+ ),
31
+ )
32
+
33
+ const radioClass = $derived(
34
+ cn(
35
+ 'radio',
36
+ getSizeClass(size, 'radio'),
37
+ ),
38
+ )
39
+
40
+ function handleChange(optionValue: T) {
41
+ value = optionValue
42
+ onchange?.(optionValue)
43
+ }
44
+ </script>
45
+
46
+ <div class={containerClass} role='radiogroup'>
47
+ {#each options as option (option.value)}
48
+ <label class='label cursor-pointer gap-2 justify-start'>
49
+ <input
50
+ type='radio'
51
+ {name}
52
+ class={radioClass}
53
+ checked={value === option.value}
54
+ disabled={disabled || option.disabled}
55
+ onchange={() => handleChange(option.value)}
56
+ />
57
+ <span>{option.label}</span>
58
+ </label>
59
+ {/each}
60
+ </div>
@@ -0,0 +1,25 @@
1
+ import type { RadioProps } from '../../types.js';
2
+ declare function $$render<T = string>(): {
3
+ props: RadioProps<T>;
4
+ exports: {};
5
+ bindings: "value";
6
+ slots: {};
7
+ events: {};
8
+ };
9
+ declare class __sveltets_Render<T = string> {
10
+ props(): ReturnType<typeof $$render<T>>['props'];
11
+ events(): ReturnType<typeof $$render<T>>['events'];
12
+ slots(): ReturnType<typeof $$render<T>>['slots'];
13
+ bindings(): "value";
14
+ exports(): {};
15
+ }
16
+ interface $$IsomorphicComponent {
17
+ new <T = string>(options: import('svelte').ComponentConstructorOptions<ReturnType<__sveltets_Render<T>['props']>>): import('svelte').SvelteComponent<ReturnType<__sveltets_Render<T>['props']>, ReturnType<__sveltets_Render<T>['events']>, ReturnType<__sveltets_Render<T>['slots']>> & {
18
+ $$bindings?: ReturnType<__sveltets_Render<T>['bindings']>;
19
+ } & ReturnType<__sveltets_Render<T>['exports']>;
20
+ <T = string>(internal: unknown, props: ReturnType<__sveltets_Render<T>['props']> & {}): ReturnType<__sveltets_Render<T>['exports']>;
21
+ z_$$bindings?: ReturnType<__sveltets_Render<any>['bindings']>;
22
+ }
23
+ declare const Radio: $$IsomorphicComponent;
24
+ type Radio<T = string> = InstanceType<typeof Radio<T>>;
25
+ export default Radio;
@@ -0,0 +1,117 @@
1
+ <!--
2
+ =============================================================================
3
+ @h-ai/ui - Range 组件
4
+ =============================================================================
5
+ 范围滑块组件,支持不同尺寸和颜色变体
6
+
7
+ 使用 Svelte 5 Runes ($props, $derived)
8
+ 使用 DaisyUI range 类
9
+ =============================================================================
10
+ -->
11
+ <script lang='ts'>
12
+ import { cn } from '../../utils.js'
13
+ import BareInput from './BareInput.svelte'
14
+
15
+ interface Props {
16
+ /** 当前值 */
17
+ value?: number
18
+ /** 最小值 */
19
+ min?: number
20
+ /** 最大值 */
21
+ max?: number
22
+ /** 步长 */
23
+ step?: number
24
+ /** 尺寸 */
25
+ size?: 'xs' | 'sm' | 'md' | 'lg'
26
+ /** 颜色变体 */
27
+ variant?: 'default' | 'primary' | 'secondary' | 'accent' | 'success' | 'warning' | 'error' | 'info'
28
+ /** 是否显示步长刻度 */
29
+ showSteps?: boolean
30
+ /** 是否禁用 */
31
+ disabled?: boolean
32
+ /** 变化事件 */
33
+ onchange?: (value: number) => void
34
+ /** 输入事件 */
35
+ oninput?: (value: number) => void
36
+ /** 自定义类名 */
37
+ class?: string
38
+ }
39
+
40
+ let {
41
+ value = $bindable(0),
42
+ min = 0,
43
+ max = 100,
44
+ step = 1,
45
+ size = 'md',
46
+ variant = 'default',
47
+ showSteps = false,
48
+ disabled = false,
49
+ onchange,
50
+ oninput,
51
+ class: className = '',
52
+ }: Props = $props()
53
+
54
+ const sizeClass = $derived({
55
+ xs: 'range-xs',
56
+ sm: 'range-sm',
57
+ md: 'range-md',
58
+ lg: 'range-lg',
59
+ }[size] || 'range-md')
60
+
61
+ const variantClass = $derived({
62
+ default: '',
63
+ primary: 'range-primary',
64
+ secondary: 'range-secondary',
65
+ accent: 'range-accent',
66
+ success: 'range-success',
67
+ warning: 'range-warning',
68
+ error: 'range-error',
69
+ info: 'range-info',
70
+ }[variant] || '')
71
+
72
+ const rangeClass = $derived(
73
+ cn(
74
+ 'range',
75
+ sizeClass,
76
+ variantClass,
77
+ className,
78
+ ),
79
+ )
80
+
81
+ // 计算步长数量
82
+ const stepCount = $derived(showSteps ? Math.floor((max - min) / step) + 1 : 0)
83
+
84
+ function handleInput(e: Event) {
85
+ const target = e.target as HTMLInputElement
86
+ value = Number(target.value)
87
+ oninput?.(value)
88
+ }
89
+
90
+ function handleChange(e: Event) {
91
+ const target = e.target as HTMLInputElement
92
+ value = Number(target.value)
93
+ onchange?.(value)
94
+ }
95
+ </script>
96
+
97
+ <div class='w-full'>
98
+ <BareInput
99
+ type='range'
100
+ class={rangeClass}
101
+ {min}
102
+ {max}
103
+ {step}
104
+ value={`${value}`}
105
+ {disabled}
106
+ oninput={handleInput}
107
+ onchange={handleChange}
108
+ />
109
+
110
+ {#if showSteps && stepCount > 0}
111
+ <div class='flex w-full justify-between px-2 text-xs text-base-content/60'>
112
+ {#each Array.from({ length: stepCount }) as _}
113
+ <span>|</span>
114
+ {/each}
115
+ </div>
116
+ {/if}
117
+ </div>
@@ -0,0 +1,27 @@
1
+ interface Props {
2
+ /** 当前值 */
3
+ value?: number;
4
+ /** 最小值 */
5
+ min?: number;
6
+ /** 最大值 */
7
+ max?: number;
8
+ /** 步长 */
9
+ step?: number;
10
+ /** 尺寸 */
11
+ size?: 'xs' | 'sm' | 'md' | 'lg';
12
+ /** 颜色变体 */
13
+ variant?: 'default' | 'primary' | 'secondary' | 'accent' | 'success' | 'warning' | 'error' | 'info';
14
+ /** 是否显示步长刻度 */
15
+ showSteps?: boolean;
16
+ /** 是否禁用 */
17
+ disabled?: boolean;
18
+ /** 变化事件 */
19
+ onchange?: (value: number) => void;
20
+ /** 输入事件 */
21
+ oninput?: (value: number) => void;
22
+ /** 自定义类名 */
23
+ class?: string;
24
+ }
25
+ declare const Range: import("svelte").Component<Props, {}, "value">;
26
+ type Range = ReturnType<typeof Range>;
27
+ export default Range;
@@ -0,0 +1,148 @@
1
+ <!--
2
+ =============================================================================
3
+ @h-ai/ui - Rating 组件
4
+ =============================================================================
5
+ 星级评分组件,支持全星/半星、只读模式、不同尺寸和颜色
6
+
7
+ 使用 Svelte 5 Runes ($props, $state, $derived)
8
+ 使用 DaisyUI rating 类
9
+ =============================================================================
10
+ -->
11
+ <script lang='ts'>
12
+ import { uiM } from '../../messages.js'
13
+ import { cn } from '../../utils.js'
14
+
15
+ interface Props {
16
+ /** 当前评分值 (0 - max) */
17
+ value?: number
18
+ /** 最大星数 */
19
+ max?: number
20
+ /** 尺寸 */
21
+ size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl'
22
+ /** 颜色 */
23
+ color?: 'default' | 'primary' | 'secondary' | 'accent' | 'warning' | 'success' | 'error' | 'info'
24
+ /** 是否只读 */
25
+ readonly?: boolean
26
+ /** 是否支持半星 */
27
+ half?: boolean
28
+ /** 是否允许清除(点击已选星清除) */
29
+ clearable?: boolean
30
+ /** 是否禁用 */
31
+ disabled?: boolean
32
+ /** 评分名称(用于表单) */
33
+ name?: string
34
+ /** 变化事件 */
35
+ onchange?: (value: number) => void
36
+ /** 自定义类名 */
37
+ class?: string
38
+ }
39
+
40
+ let {
41
+ value = $bindable(0),
42
+ max = 5,
43
+ size = 'md',
44
+ color = 'warning',
45
+ readonly = false,
46
+ half = false,
47
+ clearable = false,
48
+ disabled = false,
49
+ name = `rating-${Math.random().toString(36).slice(2, 9)}`,
50
+ onchange,
51
+ class: className = '',
52
+ }: Props = $props()
53
+
54
+ const sizeClass = $derived({
55
+ xs: 'rating-xs',
56
+ sm: 'rating-sm',
57
+ md: 'rating-md',
58
+ lg: 'rating-lg',
59
+ xl: 'rating-xl',
60
+ }[size] || 'rating-md')
61
+
62
+ const colorClass = $derived({
63
+ default: 'bg-base-content',
64
+ primary: 'bg-primary',
65
+ secondary: 'bg-secondary',
66
+ accent: 'bg-accent',
67
+ warning: 'bg-warning',
68
+ success: 'bg-success',
69
+ error: 'bg-error',
70
+ info: 'bg-info',
71
+ }[color] || 'bg-warning')
72
+
73
+ const ratingClass = $derived(
74
+ cn(
75
+ 'rating',
76
+ sizeClass,
77
+ half && 'rating-half',
78
+ className,
79
+ ),
80
+ )
81
+
82
+ function handleChange(newValue: number) {
83
+ if (readonly || disabled)
84
+ return
85
+ value = newValue
86
+ onchange?.(newValue)
87
+ }
88
+
89
+ // 生成评分项
90
+ const items = $derived.by(() => {
91
+ const result: { value: number, isHalf: boolean }[] = []
92
+
93
+ if (clearable) {
94
+ result.push({ value: 0, isHalf: false })
95
+ }
96
+
97
+ for (let i = 1; i <= max; i++) {
98
+ if (half) {
99
+ result.push({ value: i - 0.5, isHalf: true })
100
+ result.push({ value: i, isHalf: false })
101
+ }
102
+ else {
103
+ result.push({ value: i, isHalf: false })
104
+ }
105
+ }
106
+
107
+ return result
108
+ })
109
+ </script>
110
+
111
+ {#if readonly}
112
+ <!-- 只读模式 - 使用 div 而非 input -->
113
+ <div class={cn('rating', sizeClass, className)}>
114
+ {#each Array.from({ length: max }) as _, i}
115
+ <div
116
+ class={cn(
117
+ 'mask mask-star-2',
118
+ colorClass,
119
+ i < Math.floor(value) && 'opacity-100',
120
+ i >= Math.ceil(value) && 'opacity-30',
121
+ i === Math.floor(value) && value % 1 !== 0 && 'opacity-60',
122
+ )}
123
+ aria-label={uiM('rating_star', { count: i + 1 })}
124
+ aria-current={i + 1 <= value ? 'true' : undefined}
125
+ ></div>
126
+ {/each}
127
+ </div>
128
+ {:else}
129
+ <!-- 交互模式 - 使用 radio input -->
130
+ <div class={ratingClass}>
131
+ {#each items as item}
132
+ <input
133
+ type='radio'
134
+ {name}
135
+ class={cn(
136
+ item.value === 0 ? 'rating-hidden' : 'mask mask-star-2',
137
+ item.value !== 0 && colorClass,
138
+ half && item.isHalf && 'mask-half-1',
139
+ half && !item.isHalf && item.value !== 0 && 'mask-half-2',
140
+ )}
141
+ aria-label={item.value === 0 ? uiM('rating_clear') : uiM('rating_star', { count: item.value })}
142
+ checked={value === item.value}
143
+ {disabled}
144
+ onchange={() => handleChange(item.value)}
145
+ />
146
+ {/each}
147
+ </div>
148
+ {/if}
@@ -0,0 +1,27 @@
1
+ interface Props {
2
+ /** 当前评分值 (0 - max) */
3
+ value?: number;
4
+ /** 最大星数 */
5
+ max?: number;
6
+ /** 尺寸 */
7
+ size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';
8
+ /** 颜色 */
9
+ color?: 'default' | 'primary' | 'secondary' | 'accent' | 'warning' | 'success' | 'error' | 'info';
10
+ /** 是否只读 */
11
+ readonly?: boolean;
12
+ /** 是否支持半星 */
13
+ half?: boolean;
14
+ /** 是否允许清除(点击已选星清除) */
15
+ clearable?: boolean;
16
+ /** 是否禁用 */
17
+ disabled?: boolean;
18
+ /** 评分名称(用于表单) */
19
+ name?: string;
20
+ /** 变化事件 */
21
+ onchange?: (value: number) => void;
22
+ /** 自定义类名 */
23
+ class?: string;
24
+ }
25
+ declare const Rating: import("svelte").Component<Props, {}, "value">;
26
+ type Rating = ReturnType<typeof Rating>;
27
+ export default Rating;
@@ -0,0 +1,95 @@
1
+ <!--
2
+ =============================================================================
3
+ @h-ai/ui - Select 组件
4
+ =============================================================================
5
+ 下拉选择框组件
6
+
7
+ 使用 Svelte 5 Runes ($props, $derived, $bindable)
8
+ 支持自定义验证消息(validationMessage)覆盖浏览器原生提示
9
+ =============================================================================
10
+ -->
11
+ <script lang='ts' generics="T = string">
12
+ import type { SelectProps } from '../../types.js'
13
+ import { cn, getInputSizeClass } from '../../utils.js'
14
+
15
+ let {
16
+ value = $bindable<T>(),
17
+ options,
18
+ placeholder = '',
19
+ size = 'md',
20
+ disabled = false,
21
+ required = false,
22
+ error = '',
23
+ validationMessage = '',
24
+ class: className = '',
25
+ id,
26
+ onchange,
27
+ children,
28
+ }: SelectProps<T> = $props()
29
+
30
+ let selectRef: HTMLSelectElement | undefined = $state()
31
+
32
+ const selectClass = $derived(
33
+ cn(
34
+ 'select w-full',
35
+ getInputSizeClass(size),
36
+ error && 'select-error',
37
+ className,
38
+ ),
39
+ )
40
+
41
+ // 当 validationMessage 变化时更新自定义验证消息
42
+ $effect(() => {
43
+ if (selectRef) {
44
+ selectRef.setCustomValidity(validationMessage)
45
+ }
46
+ })
47
+
48
+ function handleChange(e: Event & { currentTarget: HTMLSelectElement }) {
49
+ const selectedValue = e.currentTarget.value as T
50
+ value = selectedValue
51
+ // 选择后重置自定义验证
52
+ if (validationMessage) {
53
+ e.currentTarget.setCustomValidity(validationMessage)
54
+ }
55
+ onchange?.(selectedValue)
56
+ }
57
+
58
+ function handleInvalid(e: Event & { currentTarget: HTMLSelectElement }) {
59
+ if (validationMessage) {
60
+ e.currentTarget.setCustomValidity(validationMessage)
61
+ }
62
+ }
63
+ </script>
64
+
65
+ <div class='fieldset w-full'>
66
+ <select
67
+ bind:this={selectRef}
68
+ {id}
69
+ class={selectClass}
70
+ {disabled}
71
+ {required}
72
+ onchange={handleChange}
73
+ oninvalid={handleInvalid}
74
+ >
75
+ {#if placeholder}
76
+ <option value="" disabled selected={!value}>{placeholder}</option>
77
+ {/if}
78
+ {#if children}
79
+ {@render children()}
80
+ {:else if options}
81
+ {#each options as option}
82
+ <option
83
+ value={option.value as string}
84
+ disabled={option.disabled}
85
+ selected={value === option.value}
86
+ >
87
+ {option.label}
88
+ </option>
89
+ {/each}
90
+ {/if}
91
+ </select>
92
+ {#if error}
93
+ <span class='fieldset-label text-error'>{error}</span>
94
+ {/if}
95
+ </div>
@@ -0,0 +1,25 @@
1
+ import type { SelectProps } from '../../types.js';
2
+ declare function $$render<T = string>(): {
3
+ props: SelectProps<T>;
4
+ exports: {};
5
+ bindings: "value";
6
+ slots: {};
7
+ events: {};
8
+ };
9
+ declare class __sveltets_Render<T = string> {
10
+ props(): ReturnType<typeof $$render<T>>['props'];
11
+ events(): ReturnType<typeof $$render<T>>['events'];
12
+ slots(): ReturnType<typeof $$render<T>>['slots'];
13
+ bindings(): "value";
14
+ exports(): {};
15
+ }
16
+ interface $$IsomorphicComponent {
17
+ new <T = string>(options: import('svelte').ComponentConstructorOptions<ReturnType<__sveltets_Render<T>['props']>>): import('svelte').SvelteComponent<ReturnType<__sveltets_Render<T>['props']>, ReturnType<__sveltets_Render<T>['events']>, ReturnType<__sveltets_Render<T>['slots']>> & {
18
+ $$bindings?: ReturnType<__sveltets_Render<T>['bindings']>;
19
+ } & ReturnType<__sveltets_Render<T>['exports']>;
20
+ <T = string>(internal: unknown, props: ReturnType<__sveltets_Render<T>['props']> & {}): ReturnType<__sveltets_Render<T>['exports']>;
21
+ z_$$bindings?: ReturnType<__sveltets_Render<any>['bindings']>;
22
+ }
23
+ declare const Select: $$IsomorphicComponent;
24
+ type Select<T = string> = InstanceType<typeof Select<T>>;
25
+ export default Select;
@@ -0,0 +1,54 @@
1
+ <!--
2
+ =============================================================================
3
+ @h-ai/ui - Spinner 组件
4
+ =============================================================================
5
+ 加载指示器组件
6
+
7
+ 使用 Svelte 5 Runes ($props, $derived)
8
+ =============================================================================
9
+ -->
10
+ <script lang='ts'>
11
+ import type { SpinnerProps } from '../../types.js'
12
+ import { cn } from '../../utils.js'
13
+
14
+ const {
15
+ size = 'md',
16
+ variant = 'primary',
17
+ class: className = '',
18
+ }: SpinnerProps = $props()
19
+
20
+ const sizeMap = {
21
+ 'xs': 'loading-xs',
22
+ 'sm': 'loading-sm',
23
+ 'md': 'loading-md',
24
+ 'lg': 'loading-lg',
25
+ 'xl': 'loading-lg', // DaisyUI 没有 xl,使用 lg
26
+ '2xl': 'loading-lg',
27
+ '3xl': 'loading-lg',
28
+ '4xl': 'loading-lg',
29
+ }
30
+
31
+ const variantMap = {
32
+ default: 'text-neutral',
33
+ primary: 'text-primary',
34
+ secondary: 'text-secondary',
35
+ success: 'text-success',
36
+ warning: 'text-warning',
37
+ error: 'text-error',
38
+ info: 'text-info',
39
+ ghost: 'text-base-content',
40
+ link: 'text-base-content',
41
+ outline: 'text-base-content',
42
+ }
43
+
44
+ const spinnerClass = $derived(
45
+ cn(
46
+ 'loading loading-spinner',
47
+ sizeMap[size],
48
+ variantMap[variant] ?? variantMap.default,
49
+ className,
50
+ ),
51
+ )
52
+ </script>
53
+
54
+ <span class={spinnerClass}></span>
@@ -0,0 +1,4 @@
1
+ import type { SpinnerProps } from '../../types.js';
2
+ declare const Spinner: import("svelte").Component<SpinnerProps, {}, "">;
3
+ type Spinner = ReturnType<typeof Spinner>;
4
+ export default Spinner;