@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.
- package/LICENSE +202 -0
- package/README.md +488 -0
- package/auto-import.d.ts +96 -0
- package/auto-import.js +259 -0
- package/dist/components/compounds/Accordion.svelte +142 -0
- package/dist/components/compounds/Accordion.svelte.d.ts +25 -0
- package/dist/components/compounds/ActionSheet.svelte +116 -0
- package/dist/components/compounds/ActionSheet.svelte.d.ts +22 -0
- package/dist/components/compounds/Alert.svelte +67 -0
- package/dist/components/compounds/Alert.svelte.d.ts +8 -0
- package/dist/components/compounds/AppBar.svelte +77 -0
- package/dist/components/compounds/AppBar.svelte.d.ts +20 -0
- package/dist/components/compounds/BottomNav.svelte +75 -0
- package/dist/components/compounds/BottomNav.svelte.d.ts +18 -0
- package/dist/components/compounds/Breadcrumb.svelte +49 -0
- package/dist/components/compounds/Breadcrumb.svelte.d.ts +4 -0
- package/dist/components/compounds/Calendar.svelte +116 -0
- package/dist/components/compounds/Calendar.svelte.d.ts +47 -0
- package/dist/components/compounds/Card.svelte +77 -0
- package/dist/components/compounds/Card.svelte.d.ts +8 -0
- package/dist/components/compounds/Combobox.svelte +327 -0
- package/dist/components/compounds/Combobox.svelte.d.ts +69 -0
- package/dist/components/compounds/Confirm.svelte +90 -0
- package/dist/components/compounds/Confirm.svelte.d.ts +4 -0
- package/dist/components/compounds/DataTable.svelte +133 -0
- package/dist/components/compounds/DataTable.svelte.d.ts +69 -0
- package/dist/components/compounds/DatePicker.svelte +135 -0
- package/dist/components/compounds/DatePicker.svelte.d.ts +46 -0
- package/dist/components/compounds/Drawer.svelte +113 -0
- package/dist/components/compounds/Drawer.svelte.d.ts +4 -0
- package/dist/components/compounds/Dropdown.svelte +91 -0
- package/dist/components/compounds/Dropdown.svelte.d.ts +8 -0
- package/dist/components/compounds/Empty.svelte +83 -0
- package/dist/components/compounds/Empty.svelte.d.ts +4 -0
- package/dist/components/compounds/Form.svelte +96 -0
- package/dist/components/compounds/Form.svelte.d.ts +7 -0
- package/dist/components/compounds/FormField.svelte +56 -0
- package/dist/components/compounds/FormField.svelte.d.ts +4 -0
- package/dist/components/compounds/InfiniteScroll.svelte +82 -0
- package/dist/components/compounds/InfiniteScroll.svelte.d.ts +22 -0
- package/dist/components/compounds/Modal.svelte +123 -0
- package/dist/components/compounds/Modal.svelte.d.ts +8 -0
- package/dist/components/compounds/PageHeader.svelte +44 -0
- package/dist/components/compounds/PageHeader.svelte.d.ts +28 -0
- package/dist/components/compounds/Pagination.svelte +157 -0
- package/dist/components/compounds/Pagination.svelte.d.ts +4 -0
- package/dist/components/compounds/Popover.svelte +137 -0
- package/dist/components/compounds/Popover.svelte.d.ts +4 -0
- package/dist/components/compounds/PullRefresh.svelte +98 -0
- package/dist/components/compounds/PullRefresh.svelte.d.ts +16 -0
- package/dist/components/compounds/Result.svelte +84 -0
- package/dist/components/compounds/Result.svelte.d.ts +4 -0
- package/dist/components/compounds/SafeArea.svelte +37 -0
- package/dist/components/compounds/SafeArea.svelte.d.ts +12 -0
- package/dist/components/compounds/Skeleton.svelte +75 -0
- package/dist/components/compounds/Skeleton.svelte.d.ts +8 -0
- package/dist/components/compounds/Steps.svelte +111 -0
- package/dist/components/compounds/Steps.svelte.d.ts +4 -0
- package/dist/components/compounds/SwipeCell.svelte +115 -0
- package/dist/components/compounds/SwipeCell.svelte.d.ts +19 -0
- package/dist/components/compounds/Tabs.svelte +79 -0
- package/dist/components/compounds/Tabs.svelte.d.ts +8 -0
- package/dist/components/compounds/TagInput.svelte +108 -0
- package/dist/components/compounds/TagInput.svelte.d.ts +4 -0
- package/dist/components/compounds/Timeline.svelte +167 -0
- package/dist/components/compounds/Timeline.svelte.d.ts +25 -0
- package/dist/components/compounds/ToastContainer.svelte +59 -0
- package/dist/components/compounds/ToastContainer.svelte.d.ts +3 -0
- package/dist/components/compounds/Tooltip.svelte +41 -0
- package/dist/components/compounds/Tooltip.svelte.d.ts +4 -0
- package/dist/components/compounds/accordion-types.d.ts +16 -0
- package/dist/components/compounds/accordion-types.js +5 -0
- package/dist/components/compounds/action-sheet-types.d.ts +14 -0
- package/dist/components/compounds/action-sheet-types.js +5 -0
- package/dist/components/compounds/bottom-nav-types.d.ts +17 -0
- package/dist/components/compounds/bottom-nav-types.js +5 -0
- package/dist/components/compounds/index.d.ts +44 -0
- package/dist/components/compounds/index.js +54 -0
- package/dist/components/compounds/swipe-cell-types.d.ts +14 -0
- package/dist/components/compounds/swipe-cell-types.js +5 -0
- package/dist/components/compounds/timeline-types.d.ts +20 -0
- package/dist/components/compounds/timeline-types.js +5 -0
- package/dist/components/index.d.ts +9 -0
- package/dist/components/index.js +12 -0
- package/dist/components/primitives/Avatar.svelte +102 -0
- package/dist/components/primitives/Avatar.svelte.d.ts +8 -0
- package/dist/components/primitives/Badge.svelte +33 -0
- package/dist/components/primitives/Badge.svelte.d.ts +8 -0
- package/dist/components/primitives/BareButton.svelte +45 -0
- package/dist/components/primitives/BareButton.svelte.d.ts +4 -0
- package/dist/components/primitives/BareInput.svelte +101 -0
- package/dist/components/primitives/BareInput.svelte.d.ts +4 -0
- package/dist/components/primitives/Button.svelte +60 -0
- package/dist/components/primitives/Button.svelte.d.ts +8 -0
- package/dist/components/primitives/Checkbox.svelte +58 -0
- package/dist/components/primitives/Checkbox.svelte.d.ts +4 -0
- package/dist/components/primitives/IconButton.svelte +105 -0
- package/dist/components/primitives/IconButton.svelte.d.ts +4 -0
- package/dist/components/primitives/Input.svelte +130 -0
- package/dist/components/primitives/Input.svelte.d.ts +8 -0
- package/dist/components/primitives/Progress.svelte +58 -0
- package/dist/components/primitives/Progress.svelte.d.ts +4 -0
- package/dist/components/primitives/Radio.svelte +60 -0
- package/dist/components/primitives/Radio.svelte.d.ts +25 -0
- package/dist/components/primitives/Range.svelte +117 -0
- package/dist/components/primitives/Range.svelte.d.ts +27 -0
- package/dist/components/primitives/Rating.svelte +148 -0
- package/dist/components/primitives/Rating.svelte.d.ts +27 -0
- package/dist/components/primitives/Select.svelte +95 -0
- package/dist/components/primitives/Select.svelte.d.ts +25 -0
- package/dist/components/primitives/Spinner.svelte +54 -0
- package/dist/components/primitives/Spinner.svelte.d.ts +4 -0
- package/dist/components/primitives/Switch.svelte +53 -0
- package/dist/components/primitives/Switch.svelte.d.ts +4 -0
- package/dist/components/primitives/Tag.svelte +64 -0
- package/dist/components/primitives/Tag.svelte.d.ts +4 -0
- package/dist/components/primitives/Textarea.svelte +92 -0
- package/dist/components/primitives/Textarea.svelte.d.ts +4 -0
- package/dist/components/primitives/ToggleCheckbox.svelte +36 -0
- package/dist/components/primitives/ToggleCheckbox.svelte.d.ts +4 -0
- package/dist/components/primitives/ToggleInput.svelte +36 -0
- package/dist/components/primitives/ToggleInput.svelte.d.ts +4 -0
- package/dist/components/primitives/ToggleRadio.svelte +36 -0
- package/dist/components/primitives/ToggleRadio.svelte.d.ts +4 -0
- package/dist/components/primitives/index.d.ts +26 -0
- package/dist/components/primitives/index.js +30 -0
- package/dist/components/scenes/ai/AiDocumentDownloadMenu.svelte +387 -0
- package/dist/components/scenes/ai/AiDocumentDownloadMenu.svelte.d.ts +38 -0
- package/dist/components/scenes/ai/AiDocumentEditor.svelte +2259 -0
- package/dist/components/scenes/ai/AiDocumentEditor.svelte.d.ts +4 -0
- package/dist/components/scenes/ai/MarkdownRenderer.svelte +460 -0
- package/dist/components/scenes/ai/MarkdownRenderer.svelte.d.ts +4 -0
- package/dist/components/scenes/ai/document-download.d.ts +40 -0
- package/dist/components/scenes/ai/document-download.js +300 -0
- package/dist/components/scenes/ai/document-parse.d.ts +28 -0
- package/dist/components/scenes/ai/document-parse.js +243 -0
- package/dist/components/scenes/ai/document-types.d.ts +164 -0
- package/dist/components/scenes/ai/document-types.js +1 -0
- package/dist/components/scenes/ai/index.d.ts +17 -0
- package/dist/components/scenes/ai/index.js +13 -0
- package/dist/components/scenes/ai/markdown-parse.d.ts +32 -0
- package/dist/components/scenes/ai/markdown-parse.js +161 -0
- package/dist/components/scenes/app/FeedbackModal.svelte +160 -0
- package/dist/components/scenes/app/FeedbackModal.svelte.d.ts +47 -0
- package/dist/components/scenes/app/LanguageSwitch.svelte +136 -0
- package/dist/components/scenes/app/LanguageSwitch.svelte.d.ts +50 -0
- package/dist/components/scenes/app/SettingsModal.svelte +174 -0
- package/dist/components/scenes/app/SettingsModal.svelte.d.ts +31 -0
- package/dist/components/scenes/app/ThemeSelector.svelte +176 -0
- package/dist/components/scenes/app/ThemeSelector.svelte.d.ts +31 -0
- package/dist/components/scenes/app/ThemeToggle.svelte +76 -0
- package/dist/components/scenes/app/ThemeToggle.svelte.d.ts +29 -0
- package/dist/components/scenes/app/index.d.ts +11 -0
- package/dist/components/scenes/app/index.js +11 -0
- package/dist/components/scenes/crud/CrudDeleteConfirm.svelte +39 -0
- package/dist/components/scenes/crud/CrudDeleteConfirm.svelte.d.ts +18 -0
- package/dist/components/scenes/crud/CrudDetailDrawer.svelte +155 -0
- package/dist/components/scenes/crud/CrudDetailDrawer.svelte.d.ts +38 -0
- package/dist/components/scenes/crud/CrudEditDrawer.svelte +222 -0
- package/dist/components/scenes/crud/CrudEditDrawer.svelte.d.ts +48 -0
- package/dist/components/scenes/crud/CrudFilterBar.svelte +96 -0
- package/dist/components/scenes/crud/CrudFilterBar.svelte.d.ts +31 -0
- package/dist/components/scenes/crud/CrudPage.svelte +499 -0
- package/dist/components/scenes/crud/CrudPage.svelte.d.ts +114 -0
- package/dist/components/scenes/crud/crud-types.d.ts +135 -0
- package/dist/components/scenes/crud/crud-types.js +7 -0
- package/dist/components/scenes/crud/index.d.ts +12 -0
- package/dist/components/scenes/crud/index.js +11 -0
- package/dist/components/scenes/crypto/EncryptedInput.svelte +156 -0
- package/dist/components/scenes/crypto/EncryptedInput.svelte.d.ts +32 -0
- package/dist/components/scenes/crypto/HashDisplay.svelte +97 -0
- package/dist/components/scenes/crypto/HashDisplay.svelte.d.ts +4 -0
- package/dist/components/scenes/crypto/SignatureDisplay.svelte +161 -0
- package/dist/components/scenes/crypto/SignatureDisplay.svelte.d.ts +4 -0
- package/dist/components/scenes/crypto/index.d.ts +9 -0
- package/dist/components/scenes/crypto/index.js +11 -0
- package/dist/components/scenes/iam/ChangePasswordForm.svelte +134 -0
- package/dist/components/scenes/iam/ChangePasswordForm.svelte.d.ts +8 -0
- package/dist/components/scenes/iam/ForgotPasswordForm.svelte +147 -0
- package/dist/components/scenes/iam/ForgotPasswordForm.svelte.d.ts +4 -0
- package/dist/components/scenes/iam/LoginForm.svelte +191 -0
- package/dist/components/scenes/iam/LoginForm.svelte.d.ts +8 -0
- package/dist/components/scenes/iam/PasswordInput.svelte +203 -0
- package/dist/components/scenes/iam/PasswordInput.svelte.d.ts +49 -0
- package/dist/components/scenes/iam/PermGuard.svelte +69 -0
- package/dist/components/scenes/iam/PermGuard.svelte.d.ts +16 -0
- package/dist/components/scenes/iam/RegisterForm.svelte +269 -0
- package/dist/components/scenes/iam/RegisterForm.svelte.d.ts +8 -0
- package/dist/components/scenes/iam/ResetPasswordForm.svelte +153 -0
- package/dist/components/scenes/iam/ResetPasswordForm.svelte.d.ts +8 -0
- package/dist/components/scenes/iam/UserProfile.svelte +251 -0
- package/dist/components/scenes/iam/UserProfile.svelte.d.ts +4 -0
- package/dist/components/scenes/iam/index.d.ts +16 -0
- package/dist/components/scenes/iam/index.js +18 -0
- package/dist/components/scenes/iam/password-utils.d.ts +15 -0
- package/dist/components/scenes/iam/password-utils.js +19 -0
- package/dist/components/scenes/iam/permission-context.svelte.d.ts +90 -0
- package/dist/components/scenes/iam/permission-context.svelte.js +114 -0
- package/dist/components/scenes/index.d.ts +13 -0
- package/dist/components/scenes/index.js +20 -0
- package/dist/components/scenes/storage/AvatarUpload.svelte +218 -0
- package/dist/components/scenes/storage/AvatarUpload.svelte.d.ts +4 -0
- package/dist/components/scenes/storage/FileList.svelte +260 -0
- package/dist/components/scenes/storage/FileList.svelte.d.ts +4 -0
- package/dist/components/scenes/storage/FileUpload.svelte +400 -0
- package/dist/components/scenes/storage/FileUpload.svelte.d.ts +7 -0
- package/dist/components/scenes/storage/ImageUpload.svelte +285 -0
- package/dist/components/scenes/storage/ImageUpload.svelte.d.ts +4 -0
- package/dist/components/scenes/storage/index.d.ts +10 -0
- package/dist/components/scenes/storage/index.js +12 -0
- package/dist/components/scenes/types.d.ts +583 -0
- package/dist/components/scenes/types.js +7 -0
- package/dist/i18n.svelte.d.ts +44 -0
- package/dist/i18n.svelte.js +108 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.js +19 -0
- package/dist/messages/en-US.json +242 -0
- package/dist/messages/zh-CN.json +242 -0
- package/dist/messages.d.ts +29 -0
- package/dist/messages.js +42 -0
- package/dist/styles/design-tokens.css +58 -0
- package/dist/styles/global.css +218 -0
- package/dist/styles/mobile.css +105 -0
- package/dist/theme-config.d.ts +92 -0
- package/dist/theme-config.js +122 -0
- package/dist/toast.svelte.d.ts +45 -0
- package/dist/toast.svelte.js +77 -0
- package/dist/types.d.ts +944 -0
- package/dist/types.js +7 -0
- package/dist/utils/platform.svelte.d.ts +54 -0
- package/dist/utils/platform.svelte.js +87 -0
- package/dist/utils.d.ts +46 -0
- package/dist/utils.js +100 -0
- package/package.json +69 -0
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
=============================================================================
|
|
3
|
+
@h-ai/ui - TagInput 组件
|
|
4
|
+
=============================================================================
|
|
5
|
+
标签输入框组件
|
|
6
|
+
|
|
7
|
+
使用 Svelte 5 Runes ($props, $state, $bindable)
|
|
8
|
+
=============================================================================
|
|
9
|
+
-->
|
|
10
|
+
<script lang='ts'>
|
|
11
|
+
import type { TagInputProps } from '../../types.js'
|
|
12
|
+
import { uiM } from '../../messages.js'
|
|
13
|
+
import { cn, getInputSizeClass } from '../../utils.js'
|
|
14
|
+
import BareInput from '../primitives/BareInput.svelte'
|
|
15
|
+
import Tag from '../primitives/Tag.svelte'
|
|
16
|
+
|
|
17
|
+
let {
|
|
18
|
+
tags = $bindable([]),
|
|
19
|
+
placeholder,
|
|
20
|
+
maxTags = 0,
|
|
21
|
+
allowDuplicates = false,
|
|
22
|
+
disabled = false,
|
|
23
|
+
size = 'md',
|
|
24
|
+
class: className = '',
|
|
25
|
+
onchange,
|
|
26
|
+
}: TagInputProps = $props()
|
|
27
|
+
|
|
28
|
+
let inputValue = $state('')
|
|
29
|
+
let inputElement = $state<HTMLInputElement | undefined>(undefined)
|
|
30
|
+
|
|
31
|
+
const displayPlaceholder = $derived(placeholder ?? uiM('tag_input_placeholder'))
|
|
32
|
+
|
|
33
|
+
const containerClass = $derived(
|
|
34
|
+
cn(
|
|
35
|
+
'input flex flex-wrap items-center gap-1 min-h-[2.5rem] h-auto py-1',
|
|
36
|
+
getInputSizeClass(size),
|
|
37
|
+
disabled && 'input-disabled',
|
|
38
|
+
className,
|
|
39
|
+
),
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
const canAddMore = $derived(maxTags === 0 || tags.length < maxTags)
|
|
43
|
+
|
|
44
|
+
function addTag(value: string) {
|
|
45
|
+
const trimmed = value.trim()
|
|
46
|
+
if (!trimmed)
|
|
47
|
+
return
|
|
48
|
+
if (!allowDuplicates && tags.includes(trimmed))
|
|
49
|
+
return
|
|
50
|
+
if (!canAddMore)
|
|
51
|
+
return
|
|
52
|
+
|
|
53
|
+
tags = [...tags, trimmed]
|
|
54
|
+
inputValue = ''
|
|
55
|
+
onchange?.(tags)
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function removeTag(index: number) {
|
|
59
|
+
tags = tags.filter((_, i) => i !== index)
|
|
60
|
+
onchange?.(tags)
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function handleKeydown(e: KeyboardEvent) {
|
|
64
|
+
if (e.key === 'Enter') {
|
|
65
|
+
e.preventDefault()
|
|
66
|
+
addTag(inputValue)
|
|
67
|
+
}
|
|
68
|
+
else if (e.key === 'Backspace' && !inputValue && tags.length > 0) {
|
|
69
|
+
removeTag(tags.length - 1)
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function handleBlur() {
|
|
74
|
+
if (inputValue.trim()) {
|
|
75
|
+
addTag(inputValue)
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
</script>
|
|
79
|
+
|
|
80
|
+
<div
|
|
81
|
+
class={containerClass}
|
|
82
|
+
onclick={() => inputElement?.focus()}
|
|
83
|
+
onkeydown={e => e.key === 'Enter' && inputElement?.focus()}
|
|
84
|
+
role='textbox'
|
|
85
|
+
tabindex='-1'
|
|
86
|
+
>
|
|
87
|
+
{#each tags as tag, index (index)}
|
|
88
|
+
<Tag
|
|
89
|
+
text={tag}
|
|
90
|
+
size='sm'
|
|
91
|
+
closable={!disabled}
|
|
92
|
+
onclose={() => removeTag(index)}
|
|
93
|
+
/>
|
|
94
|
+
{/each}
|
|
95
|
+
|
|
96
|
+
{#if canAddMore && !disabled}
|
|
97
|
+
<BareInput
|
|
98
|
+
type='text'
|
|
99
|
+
class='flex-1 min-w-[100px] bg-transparent border-none outline-none text-sm'
|
|
100
|
+
bind:value={inputValue}
|
|
101
|
+
bind:inputRef={inputElement}
|
|
102
|
+
placeholder={displayPlaceholder}
|
|
103
|
+
{disabled}
|
|
104
|
+
onkeydown={handleKeydown}
|
|
105
|
+
onblur={handleBlur}
|
|
106
|
+
/>
|
|
107
|
+
{/if}
|
|
108
|
+
</div>
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
=============================================================================
|
|
3
|
+
@h-ai/ui - Timeline 组件
|
|
4
|
+
=============================================================================
|
|
5
|
+
时间线组件,支持垂直/水平方向、多种样式变体
|
|
6
|
+
|
|
7
|
+
使用 Svelte 5 Runes ($props, $derived)
|
|
8
|
+
使用 DaisyUI timeline 类
|
|
9
|
+
=============================================================================
|
|
10
|
+
-->
|
|
11
|
+
|
|
12
|
+
<script lang='ts'>
|
|
13
|
+
import type { Snippet } from 'svelte'
|
|
14
|
+
import type { TimelineItem } from './timeline-types.js'
|
|
15
|
+
import { cn } from '../../utils.js'
|
|
16
|
+
|
|
17
|
+
interface Props {
|
|
18
|
+
/** 时间线项数据 */
|
|
19
|
+
items: TimelineItem[]
|
|
20
|
+
/** 方向 */
|
|
21
|
+
direction?: 'vertical' | 'horizontal'
|
|
22
|
+
/** 是否响应式(小屏垂直,大屏水平) */
|
|
23
|
+
responsive?: boolean
|
|
24
|
+
/** 内容位置 */
|
|
25
|
+
position?: 'start' | 'end' | 'alternate'
|
|
26
|
+
/** 是否紧凑模式 */
|
|
27
|
+
compact?: boolean
|
|
28
|
+
/** 是否使用盒子样式 */
|
|
29
|
+
boxed?: boolean
|
|
30
|
+
/** 图标对齐方式 */
|
|
31
|
+
snapIcon?: boolean
|
|
32
|
+
/** 自定义类名 */
|
|
33
|
+
class?: string
|
|
34
|
+
/** 自定义项渲染 */
|
|
35
|
+
children?: Snippet<[TimelineItem, number]>
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const {
|
|
39
|
+
items,
|
|
40
|
+
direction = 'vertical',
|
|
41
|
+
responsive = false,
|
|
42
|
+
position = 'end',
|
|
43
|
+
compact = false,
|
|
44
|
+
boxed = false,
|
|
45
|
+
snapIcon = false,
|
|
46
|
+
class: className = '',
|
|
47
|
+
children,
|
|
48
|
+
}: Props = $props()
|
|
49
|
+
|
|
50
|
+
const timelineClass = $derived(
|
|
51
|
+
cn(
|
|
52
|
+
'timeline',
|
|
53
|
+
direction === 'vertical' && 'timeline-vertical',
|
|
54
|
+
direction === 'horizontal' && 'timeline-horizontal',
|
|
55
|
+
responsive && 'timeline-vertical lg:timeline-horizontal',
|
|
56
|
+
compact && 'timeline-compact',
|
|
57
|
+
snapIcon && 'timeline-snap-icon',
|
|
58
|
+
className,
|
|
59
|
+
),
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
function getColorClass(color?: string): string {
|
|
63
|
+
const colorMap: Record<string, string> = {
|
|
64
|
+
primary: 'bg-primary text-primary-content',
|
|
65
|
+
secondary: 'bg-secondary text-secondary-content',
|
|
66
|
+
accent: 'bg-accent text-accent-content',
|
|
67
|
+
success: 'bg-success text-success-content',
|
|
68
|
+
warning: 'bg-warning text-warning-content',
|
|
69
|
+
error: 'bg-error text-error-content',
|
|
70
|
+
info: 'bg-info text-info-content',
|
|
71
|
+
}
|
|
72
|
+
return colorMap[color || 'default'] || 'bg-base-content'
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function getLineColorClass(item: TimelineItem, isAfter: boolean): string {
|
|
76
|
+
if (!item.completed && isAfter)
|
|
77
|
+
return ''
|
|
78
|
+
return item.color ? `bg-${item.color}` : 'bg-primary'
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function shouldShowStart(index: number): boolean {
|
|
82
|
+
if (position === 'start')
|
|
83
|
+
return true
|
|
84
|
+
if (position === 'alternate')
|
|
85
|
+
return index % 2 === 0
|
|
86
|
+
return false
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function shouldShowEnd(index: number): boolean {
|
|
90
|
+
if (position === 'end')
|
|
91
|
+
return true
|
|
92
|
+
if (position === 'alternate')
|
|
93
|
+
return index % 2 === 1
|
|
94
|
+
return false
|
|
95
|
+
}
|
|
96
|
+
</script>
|
|
97
|
+
|
|
98
|
+
<ul class={timelineClass}>
|
|
99
|
+
{#each items as item, index (item.id)}
|
|
100
|
+
<li>
|
|
101
|
+
<!-- 前置连线 -->
|
|
102
|
+
{#if index > 0}
|
|
103
|
+
<hr class={cn(items[index - 1].completed && getLineColorClass(items[index - 1], true))} />
|
|
104
|
+
{/if}
|
|
105
|
+
|
|
106
|
+
<!-- 开始位置内容 -->
|
|
107
|
+
{#if position !== 'end' && shouldShowStart(index)}
|
|
108
|
+
<div class={cn('timeline-start', boxed && 'timeline-box')}>
|
|
109
|
+
{#if children}
|
|
110
|
+
{@render children(item, index)}
|
|
111
|
+
{:else}
|
|
112
|
+
{#if item.time}
|
|
113
|
+
<time class='text-xs text-base-content/60'>{item.time}</time>
|
|
114
|
+
{/if}
|
|
115
|
+
<div class='font-semibold'>{item.title}</div>
|
|
116
|
+
{#if item.description}
|
|
117
|
+
<p class='text-sm text-base-content/70'>{item.description}</p>
|
|
118
|
+
{/if}
|
|
119
|
+
{/if}
|
|
120
|
+
</div>
|
|
121
|
+
{:else if item.time && position === 'end'}
|
|
122
|
+
<div class='timeline-start text-xs text-base-content/60'>
|
|
123
|
+
{item.time}
|
|
124
|
+
</div>
|
|
125
|
+
{/if}
|
|
126
|
+
|
|
127
|
+
<!-- 中间图标 -->
|
|
128
|
+
<div class='timeline-middle'>
|
|
129
|
+
{#if item.icon}
|
|
130
|
+
<span class={cn(
|
|
131
|
+
'flex h-6 w-6 items-center justify-center rounded-full text-sm',
|
|
132
|
+
getColorClass(item.color),
|
|
133
|
+
)}>
|
|
134
|
+
{item.icon}
|
|
135
|
+
</span>
|
|
136
|
+
{:else}
|
|
137
|
+
<span class={cn(
|
|
138
|
+
'flex h-4 w-4 rounded-full',
|
|
139
|
+
item.completed ? getColorClass(item.color) : 'bg-base-300',
|
|
140
|
+
)}></span>
|
|
141
|
+
{/if}
|
|
142
|
+
</div>
|
|
143
|
+
|
|
144
|
+
<!-- 结束位置内容 -->
|
|
145
|
+
{#if position !== 'start' && shouldShowEnd(index)}
|
|
146
|
+
<div class={cn('timeline-end', boxed && 'timeline-box')}>
|
|
147
|
+
{#if children}
|
|
148
|
+
{@render children(item, index)}
|
|
149
|
+
{:else}
|
|
150
|
+
{#if item.time && position === 'alternate'}
|
|
151
|
+
<time class='text-xs text-base-content/60'>{item.time}</time>
|
|
152
|
+
{/if}
|
|
153
|
+
<div class='font-semibold'>{item.title}</div>
|
|
154
|
+
{#if item.description}
|
|
155
|
+
<p class='text-sm text-base-content/70'>{item.description}</p>
|
|
156
|
+
{/if}
|
|
157
|
+
{/if}
|
|
158
|
+
</div>
|
|
159
|
+
{/if}
|
|
160
|
+
|
|
161
|
+
<!-- 后置连线 -->
|
|
162
|
+
{#if index < items.length - 1}
|
|
163
|
+
<hr class={cn(item.completed && getLineColorClass(item, true))} />
|
|
164
|
+
{/if}
|
|
165
|
+
</li>
|
|
166
|
+
{/each}
|
|
167
|
+
</ul>
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
import type { TimelineItem } from './timeline-types.js';
|
|
3
|
+
interface Props {
|
|
4
|
+
/** 时间线项数据 */
|
|
5
|
+
items: TimelineItem[];
|
|
6
|
+
/** 方向 */
|
|
7
|
+
direction?: 'vertical' | 'horizontal';
|
|
8
|
+
/** 是否响应式(小屏垂直,大屏水平) */
|
|
9
|
+
responsive?: boolean;
|
|
10
|
+
/** 内容位置 */
|
|
11
|
+
position?: 'start' | 'end' | 'alternate';
|
|
12
|
+
/** 是否紧凑模式 */
|
|
13
|
+
compact?: boolean;
|
|
14
|
+
/** 是否使用盒子样式 */
|
|
15
|
+
boxed?: boolean;
|
|
16
|
+
/** 图标对齐方式 */
|
|
17
|
+
snapIcon?: boolean;
|
|
18
|
+
/** 自定义类名 */
|
|
19
|
+
class?: string;
|
|
20
|
+
/** 自定义项渲染 */
|
|
21
|
+
children?: Snippet<[TimelineItem, number]>;
|
|
22
|
+
}
|
|
23
|
+
declare const Timeline: import("svelte").Component<Props, {}, "">;
|
|
24
|
+
type Timeline = ReturnType<typeof Timeline>;
|
|
25
|
+
export default Timeline;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
=============================================================================
|
|
3
|
+
@h-ai/ui - ToastContainer 组件
|
|
4
|
+
=============================================================================
|
|
5
|
+
Toast 容器组件,显示所有 Toast 通知
|
|
6
|
+
|
|
7
|
+
使用 Svelte 5 Runes ($derived)
|
|
8
|
+
=============================================================================
|
|
9
|
+
-->
|
|
10
|
+
<script lang='ts'>
|
|
11
|
+
import { uiM } from '../../messages.js'
|
|
12
|
+
import { toast } from '../../toast.svelte.js'
|
|
13
|
+
import { cn, getAlertVariantClass } from '../../utils.js'
|
|
14
|
+
import IconButton from '../primitives/IconButton.svelte'
|
|
15
|
+
|
|
16
|
+
const positionMap = {
|
|
17
|
+
'top-right': 'toast-top toast-end',
|
|
18
|
+
'top-left': 'toast-top toast-start',
|
|
19
|
+
'bottom-right': 'toast-bottom toast-end',
|
|
20
|
+
'bottom-left': 'toast-bottom toast-start',
|
|
21
|
+
'top-center': 'toast-top toast-center',
|
|
22
|
+
'bottom-center': 'toast-bottom toast-center',
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// 按位置分组
|
|
26
|
+
const groupedItems = $derived(() => {
|
|
27
|
+
const groups: Record<string, typeof toast.items> = {}
|
|
28
|
+
|
|
29
|
+
for (const item of toast.items) {
|
|
30
|
+
const position = item.position ?? 'top-right'
|
|
31
|
+
if (!groups[position]) {
|
|
32
|
+
groups[position] = []
|
|
33
|
+
}
|
|
34
|
+
groups[position].push(item)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return groups
|
|
38
|
+
})
|
|
39
|
+
</script>
|
|
40
|
+
|
|
41
|
+
{#each Object.entries(groupedItems()) as [position, items]}
|
|
42
|
+
<div class={cn('toast z-50', positionMap[position as keyof typeof positionMap])}>
|
|
43
|
+
{#each items as item (item.id)}
|
|
44
|
+
<div class={cn('alert', getAlertVariantClass(item.variant ?? 'info'))}>
|
|
45
|
+
<span>{item.message}</span>
|
|
46
|
+
{#if item.dismissible}
|
|
47
|
+
<IconButton
|
|
48
|
+
variant='ghost'
|
|
49
|
+
size='sm'
|
|
50
|
+
onclick={() => toast.remove(item.id)}
|
|
51
|
+
ariaLabel={uiM('toast_dismiss')}
|
|
52
|
+
>
|
|
53
|
+
✕
|
|
54
|
+
</IconButton>
|
|
55
|
+
{/if}
|
|
56
|
+
</div>
|
|
57
|
+
{/each}
|
|
58
|
+
</div>
|
|
59
|
+
{/each}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
=============================================================================
|
|
3
|
+
@h-ai/ui - Tooltip 组件
|
|
4
|
+
=============================================================================
|
|
5
|
+
提示框组件
|
|
6
|
+
|
|
7
|
+
使用 Svelte 5 Runes ($props, $derived)
|
|
8
|
+
=============================================================================
|
|
9
|
+
-->
|
|
10
|
+
<script lang='ts'>
|
|
11
|
+
import type { TooltipProps } from '../../types.js'
|
|
12
|
+
import { cn } from '../../utils.js'
|
|
13
|
+
|
|
14
|
+
const {
|
|
15
|
+
content,
|
|
16
|
+
position = 'top',
|
|
17
|
+
class: className = '',
|
|
18
|
+
children,
|
|
19
|
+
}: TooltipProps = $props()
|
|
20
|
+
|
|
21
|
+
const positionMap = {
|
|
22
|
+
top: 'tooltip-top',
|
|
23
|
+
right: 'tooltip-right',
|
|
24
|
+
bottom: 'tooltip-bottom',
|
|
25
|
+
left: 'tooltip-left',
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const tooltipClass = $derived(
|
|
29
|
+
cn(
|
|
30
|
+
'tooltip',
|
|
31
|
+
positionMap[position],
|
|
32
|
+
className,
|
|
33
|
+
),
|
|
34
|
+
)
|
|
35
|
+
</script>
|
|
36
|
+
|
|
37
|
+
<div class={tooltipClass} data-tip={content}>
|
|
38
|
+
{#if children}
|
|
39
|
+
{@render children()}
|
|
40
|
+
{/if}
|
|
41
|
+
</div>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @h-ai/ui — Accordion 类型定义
|
|
3
|
+
* @module accordion-types
|
|
4
|
+
*/
|
|
5
|
+
export interface AccordionItem {
|
|
6
|
+
/** 唯一标识 */
|
|
7
|
+
id: string;
|
|
8
|
+
/** 标题 */
|
|
9
|
+
title: string;
|
|
10
|
+
/** 内容(字符串或 Snippet) */
|
|
11
|
+
content?: string;
|
|
12
|
+
/** 是否禁用 */
|
|
13
|
+
disabled?: boolean;
|
|
14
|
+
/** 图标(可选) */
|
|
15
|
+
icon?: string;
|
|
16
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @h-ai/ui — ActionSheet 类型定义
|
|
3
|
+
* @module action-sheet-types
|
|
4
|
+
*/
|
|
5
|
+
export interface ActionSheetItem {
|
|
6
|
+
/** 操作 ID */
|
|
7
|
+
id: string;
|
|
8
|
+
/** 显示文本 */
|
|
9
|
+
label: string;
|
|
10
|
+
/** 是否为危险操作(红色文字) */
|
|
11
|
+
destructive?: boolean;
|
|
12
|
+
/** 是否禁用 */
|
|
13
|
+
disabled?: boolean;
|
|
14
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @h-ai/ui — BottomNav 类型定义
|
|
3
|
+
* @module bottom-nav-types
|
|
4
|
+
*/
|
|
5
|
+
import type { Snippet } from 'svelte';
|
|
6
|
+
export interface BottomNavItem {
|
|
7
|
+
/** 导航项 ID */
|
|
8
|
+
id: string;
|
|
9
|
+
/** 显示文本 */
|
|
10
|
+
label: string;
|
|
11
|
+
/** 图标 Snippet(与 iconClass 二选一) */
|
|
12
|
+
icon?: Snippet;
|
|
13
|
+
/** CSS 图标类名,如 'icon-[tabler--home]'(与 icon 二选一) */
|
|
14
|
+
iconClass?: string;
|
|
15
|
+
/** 角标数字 */
|
|
16
|
+
badge?: number;
|
|
17
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @h-ai/ui — 组合组件 (Compounds)
|
|
3
|
+
*
|
|
4
|
+
* 由多个原子组件组合而成的复杂 UI 模式,提供更完整的交互体验。
|
|
5
|
+
* @module index
|
|
6
|
+
*/
|
|
7
|
+
export type { AccordionItem } from './accordion-types.js';
|
|
8
|
+
export { default as Accordion } from './Accordion.svelte';
|
|
9
|
+
export type { ActionSheetItem } from './action-sheet-types.js';
|
|
10
|
+
export { default as ActionSheet } from './ActionSheet.svelte';
|
|
11
|
+
export { default as Alert } from './Alert.svelte';
|
|
12
|
+
export { default as AppBar } from './AppBar.svelte';
|
|
13
|
+
export type { BottomNavItem } from './bottom-nav-types.js';
|
|
14
|
+
export { default as BottomNav } from './BottomNav.svelte';
|
|
15
|
+
export { default as Breadcrumb } from './Breadcrumb.svelte';
|
|
16
|
+
export { default as Calendar } from './Calendar.svelte';
|
|
17
|
+
export { default as Card } from './Card.svelte';
|
|
18
|
+
export { default as Combobox } from './Combobox.svelte';
|
|
19
|
+
export { default as Confirm } from './Confirm.svelte';
|
|
20
|
+
export { default as DataTable } from './DataTable.svelte';
|
|
21
|
+
export { default as DatePicker } from './DatePicker.svelte';
|
|
22
|
+
export { default as Drawer } from './Drawer.svelte';
|
|
23
|
+
export { default as Dropdown } from './Dropdown.svelte';
|
|
24
|
+
export { default as Empty } from './Empty.svelte';
|
|
25
|
+
export { default as Form } from './Form.svelte';
|
|
26
|
+
export { default as FormField } from './FormField.svelte';
|
|
27
|
+
export { default as InfiniteScroll } from './InfiniteScroll.svelte';
|
|
28
|
+
export { default as Modal } from './Modal.svelte';
|
|
29
|
+
export { default as PageHeader } from './PageHeader.svelte';
|
|
30
|
+
export { default as Pagination } from './Pagination.svelte';
|
|
31
|
+
export { default as Popover } from './Popover.svelte';
|
|
32
|
+
export { default as PullRefresh } from './PullRefresh.svelte';
|
|
33
|
+
export { default as Result } from './Result.svelte';
|
|
34
|
+
export { default as SafeArea } from './SafeArea.svelte';
|
|
35
|
+
export { default as Skeleton } from './Skeleton.svelte';
|
|
36
|
+
export { default as Steps } from './Steps.svelte';
|
|
37
|
+
export type { SwipeCellAction } from './swipe-cell-types.js';
|
|
38
|
+
export { default as SwipeCell } from './SwipeCell.svelte';
|
|
39
|
+
export { default as Tabs } from './Tabs.svelte';
|
|
40
|
+
export { default as TagInput } from './TagInput.svelte';
|
|
41
|
+
export type { TimelineItem } from './timeline-types.js';
|
|
42
|
+
export { default as Timeline } from './Timeline.svelte';
|
|
43
|
+
export { default as ToastContainer } from './ToastContainer.svelte';
|
|
44
|
+
export { default as Tooltip } from './Tooltip.svelte';
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @h-ai/ui — 组合组件 (Compounds)
|
|
3
|
+
*
|
|
4
|
+
* 由多个原子组件组合而成的复杂 UI 模式,提供更完整的交互体验。
|
|
5
|
+
* @module index
|
|
6
|
+
*/
|
|
7
|
+
export { default as Accordion } from './Accordion.svelte';
|
|
8
|
+
export { default as ActionSheet } from './ActionSheet.svelte';
|
|
9
|
+
// 反馈提示
|
|
10
|
+
export { default as Alert } from './Alert.svelte';
|
|
11
|
+
// 移动端顶部应用栏
|
|
12
|
+
export { default as AppBar } from './AppBar.svelte';
|
|
13
|
+
export { default as BottomNav } from './BottomNav.svelte';
|
|
14
|
+
// 导航控件
|
|
15
|
+
export { default as Breadcrumb } from './Breadcrumb.svelte';
|
|
16
|
+
// 日历(Bits UI headless + DaisyUI 样式)
|
|
17
|
+
export { default as Calendar } from './Calendar.svelte';
|
|
18
|
+
// 数据展示
|
|
19
|
+
export { default as Card } from './Card.svelte';
|
|
20
|
+
// 可搜索下拉选择(Bits UI headless + DaisyUI 样式)
|
|
21
|
+
export { default as Combobox } from './Combobox.svelte';
|
|
22
|
+
export { default as Confirm } from './Confirm.svelte';
|
|
23
|
+
export { default as DataTable } from './DataTable.svelte';
|
|
24
|
+
// 日期选择器(Bits UI headless + DaisyUI 样式)
|
|
25
|
+
export { default as DatePicker } from './DatePicker.svelte';
|
|
26
|
+
// 弹层容器
|
|
27
|
+
export { default as Drawer } from './Drawer.svelte';
|
|
28
|
+
export { default as Dropdown } from './Dropdown.svelte';
|
|
29
|
+
// 状态占位
|
|
30
|
+
export { default as Empty } from './Empty.svelte';
|
|
31
|
+
// 表单组合
|
|
32
|
+
export { default as Form } from './Form.svelte';
|
|
33
|
+
export { default as FormField } from './FormField.svelte';
|
|
34
|
+
// 无限滚动 / 上拉加载
|
|
35
|
+
export { default as InfiniteScroll } from './InfiniteScroll.svelte';
|
|
36
|
+
export { default as Modal } from './Modal.svelte';
|
|
37
|
+
// 页面头部
|
|
38
|
+
export { default as PageHeader } from './PageHeader.svelte';
|
|
39
|
+
export { default as Pagination } from './Pagination.svelte';
|
|
40
|
+
export { default as Popover } from './Popover.svelte';
|
|
41
|
+
// 下拉刷新
|
|
42
|
+
export { default as PullRefresh } from './PullRefresh.svelte';
|
|
43
|
+
export { default as Result } from './Result.svelte';
|
|
44
|
+
// 安全区域包裹
|
|
45
|
+
export { default as SafeArea } from './SafeArea.svelte';
|
|
46
|
+
export { default as Skeleton } from './Skeleton.svelte';
|
|
47
|
+
export { default as Steps } from './Steps.svelte';
|
|
48
|
+
export { default as SwipeCell } from './SwipeCell.svelte';
|
|
49
|
+
export { default as Tabs } from './Tabs.svelte';
|
|
50
|
+
export { default as TagInput } from './TagInput.svelte';
|
|
51
|
+
export { default as Timeline } from './Timeline.svelte';
|
|
52
|
+
// Toast(统一使用 store 驱动模式)
|
|
53
|
+
export { default as ToastContainer } from './ToastContainer.svelte';
|
|
54
|
+
export { default as Tooltip } from './Tooltip.svelte';
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @h-ai/ui — SwipeCell 类型定义
|
|
3
|
+
* @module swipe-cell-types
|
|
4
|
+
*/
|
|
5
|
+
export interface SwipeCellAction {
|
|
6
|
+
/** 操作 ID */
|
|
7
|
+
id: string;
|
|
8
|
+
/** 显示文本 */
|
|
9
|
+
label: string;
|
|
10
|
+
/** 按钮变体 */
|
|
11
|
+
variant?: 'primary' | 'error' | 'warning' | 'info';
|
|
12
|
+
/** 按钮宽度(px) */
|
|
13
|
+
width?: number;
|
|
14
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @h-ai/ui — Timeline 类型定义
|
|
3
|
+
* @module timeline-types
|
|
4
|
+
*/
|
|
5
|
+
export interface TimelineItem {
|
|
6
|
+
/** 唯一标识 */
|
|
7
|
+
id: string;
|
|
8
|
+
/** 标题 */
|
|
9
|
+
title: string;
|
|
10
|
+
/** 描述内容 */
|
|
11
|
+
description?: string;
|
|
12
|
+
/** 时间/日期标签 */
|
|
13
|
+
time?: string;
|
|
14
|
+
/** 图标(可选,支持 emoji 或字符) */
|
|
15
|
+
icon?: string;
|
|
16
|
+
/** 状态颜色 */
|
|
17
|
+
color?: 'default' | 'primary' | 'secondary' | 'accent' | 'success' | 'warning' | 'error' | 'info';
|
|
18
|
+
/** 是否已完成 */
|
|
19
|
+
completed?: boolean;
|
|
20
|
+
}
|