@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,67 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
@component Alert
|
|
3
|
+
警告框组件,使用 tabler icon 替代 emoji,更精致。
|
|
4
|
+
-->
|
|
5
|
+
<script lang='ts'>
|
|
6
|
+
import type { AlertProps } from '../../types.js'
|
|
7
|
+
import { uiM } from '../../messages.js'
|
|
8
|
+
import { cn, getAlertVariantClass } from '../../utils.js'
|
|
9
|
+
import IconButton from '../primitives/IconButton.svelte'
|
|
10
|
+
|
|
11
|
+
const {
|
|
12
|
+
variant = 'info',
|
|
13
|
+
title = '',
|
|
14
|
+
dismissible = false,
|
|
15
|
+
class: className = '',
|
|
16
|
+
onclose,
|
|
17
|
+
children,
|
|
18
|
+
}: AlertProps = $props()
|
|
19
|
+
|
|
20
|
+
let visible = $state(true)
|
|
21
|
+
|
|
22
|
+
const alertClass = $derived(
|
|
23
|
+
cn(
|
|
24
|
+
'alert',
|
|
25
|
+
getAlertVariantClass(variant),
|
|
26
|
+
className,
|
|
27
|
+
),
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
// 图标映射:使用 tabler icon 类
|
|
31
|
+
const iconMap: Record<string, string> = {
|
|
32
|
+
info: 'icon-[tabler--info-circle]',
|
|
33
|
+
success: 'icon-[tabler--circle-check]',
|
|
34
|
+
warning: 'icon-[tabler--alert-triangle]',
|
|
35
|
+
error: 'icon-[tabler--circle-x]',
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function handleClose() {
|
|
39
|
+
visible = false
|
|
40
|
+
onclose?.()
|
|
41
|
+
}
|
|
42
|
+
</script>
|
|
43
|
+
|
|
44
|
+
{#if visible}
|
|
45
|
+
<div class={alertClass} role='alert'>
|
|
46
|
+
<span class='{iconMap[variant] ?? iconMap.info} size-5 shrink-0'></span>
|
|
47
|
+
|
|
48
|
+
<div>
|
|
49
|
+
{#if title}
|
|
50
|
+
<h3 class='font-semibold text-sm'>{title}</h3>
|
|
51
|
+
{/if}
|
|
52
|
+
{#if children}
|
|
53
|
+
<div class='text-sm'>
|
|
54
|
+
{@render children()}
|
|
55
|
+
</div>
|
|
56
|
+
{/if}
|
|
57
|
+
</div>
|
|
58
|
+
|
|
59
|
+
{#if dismissible}
|
|
60
|
+
<IconButton size='sm' variant='ghost' label={uiM('common_close')} onclick={handleClose}>
|
|
61
|
+
{#snippet children()}
|
|
62
|
+
<span class='icon-[tabler--x] size-4'></span>
|
|
63
|
+
{/snippet}
|
|
64
|
+
</IconButton>
|
|
65
|
+
{/if}
|
|
66
|
+
</div>
|
|
67
|
+
{/if}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
@h-ai/ui — AppBar(顶部应用栏,支持安全区域)
|
|
3
|
+
|
|
4
|
+
用法:
|
|
5
|
+
<AppBar title="首页">
|
|
6
|
+
{#snippet leading()}<BackButton />{/snippet}
|
|
7
|
+
{#snippet trailing()}<Avatar />{/snippet}
|
|
8
|
+
</AppBar>
|
|
9
|
+
-->
|
|
10
|
+
<script lang='ts'>
|
|
11
|
+
import type { Snippet } from 'svelte'
|
|
12
|
+
import { cn } from '../../utils.js'
|
|
13
|
+
|
|
14
|
+
interface Props {
|
|
15
|
+
/** 标题文本 */
|
|
16
|
+
title?: string
|
|
17
|
+
/** 是否适配顶部安全区域 */
|
|
18
|
+
safeArea?: boolean
|
|
19
|
+
/** 是否固定在顶部 */
|
|
20
|
+
fixed?: boolean
|
|
21
|
+
/** 额外 CSS 类 */
|
|
22
|
+
class?: string
|
|
23
|
+
/** 左侧内容(返回按钮等) */
|
|
24
|
+
leading?: Snippet
|
|
25
|
+
/** 右侧内容(操作按钮等) */
|
|
26
|
+
trailing?: Snippet
|
|
27
|
+
/** 自定义标题区域 */
|
|
28
|
+
children?: Snippet
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const {
|
|
32
|
+
title,
|
|
33
|
+
safeArea = true,
|
|
34
|
+
fixed = true,
|
|
35
|
+
class: className,
|
|
36
|
+
leading,
|
|
37
|
+
trailing,
|
|
38
|
+
children,
|
|
39
|
+
}: Props = $props()
|
|
40
|
+
</script>
|
|
41
|
+
|
|
42
|
+
<header
|
|
43
|
+
class={cn(
|
|
44
|
+
'flex items-center h-14 px-4 bg-base-100 border-b border-base-200',
|
|
45
|
+
safeArea && 'hai-safe-top',
|
|
46
|
+
fixed && 'fixed top-0 left-0 right-0 z-40',
|
|
47
|
+
className,
|
|
48
|
+
)}
|
|
49
|
+
>
|
|
50
|
+
<!-- 左侧 -->
|
|
51
|
+
<div class='flex items-center min-w-[48px]'>
|
|
52
|
+
{#if leading}
|
|
53
|
+
{@render leading()}
|
|
54
|
+
{/if}
|
|
55
|
+
</div>
|
|
56
|
+
|
|
57
|
+
<!-- 标题区域 -->
|
|
58
|
+
<div class='flex-1 text-center font-semibold text-base truncate'>
|
|
59
|
+
{#if children}
|
|
60
|
+
{@render children()}
|
|
61
|
+
{:else if title}
|
|
62
|
+
{title}
|
|
63
|
+
{/if}
|
|
64
|
+
</div>
|
|
65
|
+
|
|
66
|
+
<!-- 右侧 -->
|
|
67
|
+
<div class='flex items-center min-w-[48px] justify-end'>
|
|
68
|
+
{#if trailing}
|
|
69
|
+
{@render trailing()}
|
|
70
|
+
{/if}
|
|
71
|
+
</div>
|
|
72
|
+
</header>
|
|
73
|
+
|
|
74
|
+
<!-- 占位区域(fixed 模式下避免内容被遮挡) -->
|
|
75
|
+
{#if fixed}
|
|
76
|
+
<div class={cn('h-14', safeArea && 'hai-safe-top')}></div>
|
|
77
|
+
{/if}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
interface Props {
|
|
3
|
+
/** 标题文本 */
|
|
4
|
+
title?: string;
|
|
5
|
+
/** 是否适配顶部安全区域 */
|
|
6
|
+
safeArea?: boolean;
|
|
7
|
+
/** 是否固定在顶部 */
|
|
8
|
+
fixed?: boolean;
|
|
9
|
+
/** 额外 CSS 类 */
|
|
10
|
+
class?: string;
|
|
11
|
+
/** 左侧内容(返回按钮等) */
|
|
12
|
+
leading?: Snippet;
|
|
13
|
+
/** 右侧内容(操作按钮等) */
|
|
14
|
+
trailing?: Snippet;
|
|
15
|
+
/** 自定义标题区域 */
|
|
16
|
+
children?: Snippet;
|
|
17
|
+
}
|
|
18
|
+
declare const AppBar: import("svelte").Component<Props, {}, "">;
|
|
19
|
+
type AppBar = ReturnType<typeof AppBar>;
|
|
20
|
+
export default AppBar;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
@h-ai/ui — BottomNav(底部导航栏)
|
|
3
|
+
|
|
4
|
+
用法:
|
|
5
|
+
<BottomNav items={navItems} active="home" onchange={(id) => goto(`/${id}`)} />
|
|
6
|
+
-->
|
|
7
|
+
<script lang='ts'>
|
|
8
|
+
import type { BottomNavItem } from './bottom-nav-types.js'
|
|
9
|
+
import { cn } from '../../utils.js'
|
|
10
|
+
|
|
11
|
+
// eslint-disable-next-line no-import-assign -- type re-export
|
|
12
|
+
export type { BottomNavItem }
|
|
13
|
+
|
|
14
|
+
interface Props {
|
|
15
|
+
/** 导航项列表 */
|
|
16
|
+
items: BottomNavItem[]
|
|
17
|
+
/** 当前激活项 ID */
|
|
18
|
+
active?: string
|
|
19
|
+
/** 切换回调 */
|
|
20
|
+
onchange?: (id: string) => void
|
|
21
|
+
/** 是否适配底部安全区域 */
|
|
22
|
+
safeArea?: boolean
|
|
23
|
+
/** 额外 CSS 类 */
|
|
24
|
+
class?: string
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const {
|
|
28
|
+
items,
|
|
29
|
+
active,
|
|
30
|
+
onchange,
|
|
31
|
+
safeArea = true,
|
|
32
|
+
class: className,
|
|
33
|
+
}: Props = $props()
|
|
34
|
+
</script>
|
|
35
|
+
|
|
36
|
+
<nav
|
|
37
|
+
class={cn(
|
|
38
|
+
'fixed bottom-0 left-0 right-0 bg-base-100 border-t border-base-200 z-40',
|
|
39
|
+
safeArea && 'hai-safe-bottom',
|
|
40
|
+
className,
|
|
41
|
+
)}
|
|
42
|
+
>
|
|
43
|
+
<div class='flex items-center justify-around h-14'>
|
|
44
|
+
{#each items as item (item.id)}
|
|
45
|
+
<button
|
|
46
|
+
type='button'
|
|
47
|
+
class={cn(
|
|
48
|
+
'flex flex-col items-center justify-center flex-1 h-full relative transition-colors',
|
|
49
|
+
'hai-no-select',
|
|
50
|
+
item.id === active ? 'text-primary' : 'text-base-content/60',
|
|
51
|
+
)}
|
|
52
|
+
onclick={() => onchange?.(item.id)}
|
|
53
|
+
>
|
|
54
|
+
<!-- 图标 -->
|
|
55
|
+
<div class='relative w-6 h-6 mb-0.5'>
|
|
56
|
+
{#if item.icon}
|
|
57
|
+
{@render item.icon()}
|
|
58
|
+
{:else if item.iconClass}
|
|
59
|
+
<span class='{item.iconClass} w-6 h-6'></span>
|
|
60
|
+
{/if}
|
|
61
|
+
{#if item.badge && item.badge > 0}
|
|
62
|
+
<span class='absolute -top-1 -right-2 badge badge-error badge-xs text-[10px] min-w-4 h-4'>
|
|
63
|
+
{item.badge > 99 ? '99+' : item.badge}
|
|
64
|
+
</span>
|
|
65
|
+
{/if}
|
|
66
|
+
</div>
|
|
67
|
+
<!-- 文本 -->
|
|
68
|
+
<span class='text-xs leading-tight'>{item.label}</span>
|
|
69
|
+
</button>
|
|
70
|
+
{/each}
|
|
71
|
+
</div>
|
|
72
|
+
</nav>
|
|
73
|
+
|
|
74
|
+
<!-- 占位(避免内容被遮挡) -->
|
|
75
|
+
<div class={cn('h-14', safeArea && 'hai-safe-bottom')}></div>
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { BottomNavItem } from './bottom-nav-types.js';
|
|
2
|
+
interface Props {
|
|
3
|
+
/** 导航项列表 */
|
|
4
|
+
items: BottomNavItem[];
|
|
5
|
+
/** 当前激活项 ID */
|
|
6
|
+
active?: string;
|
|
7
|
+
/** 切换回调 */
|
|
8
|
+
onchange?: (id: string) => void;
|
|
9
|
+
/** 是否适配底部安全区域 */
|
|
10
|
+
safeArea?: boolean;
|
|
11
|
+
/** 额外 CSS 类 */
|
|
12
|
+
class?: string;
|
|
13
|
+
}
|
|
14
|
+
declare const BottomNav: import("svelte").Component<Props, {
|
|
15
|
+
BottomNavItem: typeof BottomNavItem;
|
|
16
|
+
}, "">;
|
|
17
|
+
type BottomNav = ReturnType<typeof BottomNav>;
|
|
18
|
+
export default BottomNav;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
=============================================================================
|
|
3
|
+
@h-ai/ui - Breadcrumb 组件
|
|
4
|
+
=============================================================================
|
|
5
|
+
面包屑导航组件
|
|
6
|
+
|
|
7
|
+
使用 Svelte 5 Runes ($props)
|
|
8
|
+
=============================================================================
|
|
9
|
+
-->
|
|
10
|
+
<script lang='ts'>
|
|
11
|
+
import type { BreadcrumbProps } from '../../types.js'
|
|
12
|
+
import { cn } from '../../utils.js'
|
|
13
|
+
|
|
14
|
+
const {
|
|
15
|
+
items,
|
|
16
|
+
class: className = '',
|
|
17
|
+
}: BreadcrumbProps = $props()
|
|
18
|
+
|
|
19
|
+
const breadcrumbClass = $derived(
|
|
20
|
+
cn(
|
|
21
|
+
'breadcrumbs text-sm',
|
|
22
|
+
className,
|
|
23
|
+
),
|
|
24
|
+
)
|
|
25
|
+
</script>
|
|
26
|
+
|
|
27
|
+
<div class={breadcrumbClass}>
|
|
28
|
+
<ul>
|
|
29
|
+
{#each items as item, index}
|
|
30
|
+
<li>
|
|
31
|
+
{#if item.href && index < items.length - 1}
|
|
32
|
+
<a href={item.href}>
|
|
33
|
+
{#if item.icon}
|
|
34
|
+
<span class='mr-1'>{item.icon}</span>
|
|
35
|
+
{/if}
|
|
36
|
+
{item.label}
|
|
37
|
+
</a>
|
|
38
|
+
{:else}
|
|
39
|
+
<span>
|
|
40
|
+
{#if item.icon}
|
|
41
|
+
<span class='mr-1'>{item.icon}</span>
|
|
42
|
+
{/if}
|
|
43
|
+
{item.label}
|
|
44
|
+
</span>
|
|
45
|
+
{/if}
|
|
46
|
+
</li>
|
|
47
|
+
{/each}
|
|
48
|
+
</ul>
|
|
49
|
+
</div>
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
@component Calendar
|
|
3
|
+
日历组件,基于 Bits UI headless + DaisyUI 样式。
|
|
4
|
+
支持单选/多选、日期范围限制、自定义不可用日期。
|
|
5
|
+
|
|
6
|
+
@prop {DateValue} value - 选中日期(双向绑定)
|
|
7
|
+
@prop {DateValue} minValue - 最小可选日期
|
|
8
|
+
@prop {DateValue} maxValue - 最大可选日期
|
|
9
|
+
@prop {number} weekStartsOn - 周起始日(0=周日,1=周一)
|
|
10
|
+
@prop {function} isDateUnavailable - 自定义不可用日期判断函数
|
|
11
|
+
@prop {function} onchange - 日期变更回调
|
|
12
|
+
|
|
13
|
+
@example
|
|
14
|
+
```svelte
|
|
15
|
+
<script>
|
|
16
|
+
import { CalendarDate } from '@internationalized/date'
|
|
17
|
+
let date = $state(new CalendarDate(2024, 1, 15))
|
|
18
|
+
</script>
|
|
19
|
+
<Calendar bind:value={date} />
|
|
20
|
+
```
|
|
21
|
+
-->
|
|
22
|
+
<script lang='ts'>
|
|
23
|
+
import type { DateValue } from '@internationalized/date'
|
|
24
|
+
import { Calendar as BitsCalendar } from 'bits-ui'
|
|
25
|
+
|
|
26
|
+
interface Props {
|
|
27
|
+
/** 选中日期(双向绑定) */
|
|
28
|
+
value?: DateValue
|
|
29
|
+
/** 占位日期(控制日历显示月份) */
|
|
30
|
+
placeholder?: DateValue
|
|
31
|
+
/** 最小可选日期 */
|
|
32
|
+
minValue?: DateValue
|
|
33
|
+
/** 最大可选日期 */
|
|
34
|
+
maxValue?: DateValue
|
|
35
|
+
/** 周起始日(0=周日,1=周一,默认 1) */
|
|
36
|
+
weekStartsOn?: 0 | 1 | 2 | 3 | 4 | 5 | 6
|
|
37
|
+
/** 自定义不可用日期判断函数 */
|
|
38
|
+
isDateUnavailable?: (date: DateValue) => boolean
|
|
39
|
+
/** 是否禁用 */
|
|
40
|
+
disabled?: boolean
|
|
41
|
+
/** 是否只读 */
|
|
42
|
+
readonly?: boolean
|
|
43
|
+
/** 自定义类名 */
|
|
44
|
+
class?: string
|
|
45
|
+
/** 日期变更回调 */
|
|
46
|
+
onchange?: (value: DateValue | undefined) => void
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
let {
|
|
50
|
+
value = $bindable(),
|
|
51
|
+
placeholder = $bindable(),
|
|
52
|
+
minValue,
|
|
53
|
+
maxValue,
|
|
54
|
+
weekStartsOn = 1,
|
|
55
|
+
isDateUnavailable,
|
|
56
|
+
disabled = false,
|
|
57
|
+
readonly: isReadonly = false,
|
|
58
|
+
class: className = '',
|
|
59
|
+
onchange,
|
|
60
|
+
}: Props = $props()
|
|
61
|
+
</script>
|
|
62
|
+
|
|
63
|
+
<div class={className}>
|
|
64
|
+
<BitsCalendar.Root
|
|
65
|
+
type='single'
|
|
66
|
+
bind:value
|
|
67
|
+
bind:placeholder
|
|
68
|
+
{minValue}
|
|
69
|
+
{maxValue}
|
|
70
|
+
{weekStartsOn}
|
|
71
|
+
{isDateUnavailable}
|
|
72
|
+
{disabled}
|
|
73
|
+
readonly={isReadonly}
|
|
74
|
+
onValueChange={v => onchange?.(v)}
|
|
75
|
+
>
|
|
76
|
+
{#snippet children({ months, weekdays })}
|
|
77
|
+
<BitsCalendar.Header class='flex items-center justify-between px-1 pb-3'>
|
|
78
|
+
<BitsCalendar.PrevButton class='btn btn-ghost btn-sm btn-circle'>
|
|
79
|
+
<span class='icon-[tabler--chevron-left] size-4'></span>
|
|
80
|
+
</BitsCalendar.PrevButton>
|
|
81
|
+
<BitsCalendar.Heading class='text-sm font-semibold' />
|
|
82
|
+
<BitsCalendar.NextButton class='btn btn-ghost btn-sm btn-circle'>
|
|
83
|
+
<span class='icon-[tabler--chevron-right] size-4'></span>
|
|
84
|
+
</BitsCalendar.NextButton>
|
|
85
|
+
</BitsCalendar.Header>
|
|
86
|
+
|
|
87
|
+
{#each months as month}
|
|
88
|
+
<BitsCalendar.Grid class='w-full border-collapse'>
|
|
89
|
+
<BitsCalendar.GridHead>
|
|
90
|
+
<BitsCalendar.GridRow class='flex w-full'>
|
|
91
|
+
{#each weekdays as day}
|
|
92
|
+
<BitsCalendar.HeadCell class='w-9 text-center text-xs font-medium text-base-content/50'>
|
|
93
|
+
{day}
|
|
94
|
+
</BitsCalendar.HeadCell>
|
|
95
|
+
{/each}
|
|
96
|
+
</BitsCalendar.GridRow>
|
|
97
|
+
</BitsCalendar.GridHead>
|
|
98
|
+
|
|
99
|
+
<BitsCalendar.GridBody>
|
|
100
|
+
{#each month.weeks as weekDates}
|
|
101
|
+
<BitsCalendar.GridRow class='flex w-full'>
|
|
102
|
+
{#each weekDates as date}
|
|
103
|
+
<BitsCalendar.Cell {date} month={month.value} class='p-0'>
|
|
104
|
+
<BitsCalendar.Day class='inline-flex size-9 items-center justify-center rounded-lg text-sm transition-colors hover:bg-base-200 data-[selected]:bg-primary data-[selected]:text-primary-content data-[disabled]:opacity-30 data-[unavailable]:line-through data-[unavailable]:opacity-30 data-[outside-month]:text-base-content/30'>
|
|
105
|
+
{date.day}
|
|
106
|
+
</BitsCalendar.Day>
|
|
107
|
+
</BitsCalendar.Cell>
|
|
108
|
+
{/each}
|
|
109
|
+
</BitsCalendar.GridRow>
|
|
110
|
+
{/each}
|
|
111
|
+
</BitsCalendar.GridBody>
|
|
112
|
+
</BitsCalendar.Grid>
|
|
113
|
+
{/each}
|
|
114
|
+
{/snippet}
|
|
115
|
+
</BitsCalendar.Root>
|
|
116
|
+
</div>
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { DateValue } from '@internationalized/date';
|
|
2
|
+
interface Props {
|
|
3
|
+
/** 选中日期(双向绑定) */
|
|
4
|
+
value?: DateValue;
|
|
5
|
+
/** 占位日期(控制日历显示月份) */
|
|
6
|
+
placeholder?: DateValue;
|
|
7
|
+
/** 最小可选日期 */
|
|
8
|
+
minValue?: DateValue;
|
|
9
|
+
/** 最大可选日期 */
|
|
10
|
+
maxValue?: DateValue;
|
|
11
|
+
/** 周起始日(0=周日,1=周一,默认 1) */
|
|
12
|
+
weekStartsOn?: 0 | 1 | 2 | 3 | 4 | 5 | 6;
|
|
13
|
+
/** 自定义不可用日期判断函数 */
|
|
14
|
+
isDateUnavailable?: (date: DateValue) => boolean;
|
|
15
|
+
/** 是否禁用 */
|
|
16
|
+
disabled?: boolean;
|
|
17
|
+
/** 是否只读 */
|
|
18
|
+
readonly?: boolean;
|
|
19
|
+
/** 自定义类名 */
|
|
20
|
+
class?: string;
|
|
21
|
+
/** 日期变更回调 */
|
|
22
|
+
onchange?: (value: DateValue | undefined) => void;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Calendar
|
|
26
|
+
* 日历组件,基于 Bits UI headless + DaisyUI 样式。
|
|
27
|
+
* 支持单选/多选、日期范围限制、自定义不可用日期。
|
|
28
|
+
*
|
|
29
|
+
* @prop {DateValue} value - 选中日期(双向绑定)
|
|
30
|
+
* @prop {DateValue} minValue - 最小可选日期
|
|
31
|
+
* @prop {DateValue} maxValue - 最大可选日期
|
|
32
|
+
* @prop {number} weekStartsOn - 周起始日(0=周日,1=周一)
|
|
33
|
+
* @prop {function} isDateUnavailable - 自定义不可用日期判断函数
|
|
34
|
+
* @prop {function} onchange - 日期变更回调
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* ```svelte
|
|
38
|
+
* <script>
|
|
39
|
+
* import { CalendarDate } from '@internationalized/date'
|
|
40
|
+
* let date = $state(new CalendarDate(2024, 1, 15))
|
|
41
|
+
* </script>
|
|
42
|
+
* <Calendar bind:value={date} />
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
declare const Calendar: import("svelte").Component<Props, {}, "value" | "placeholder">;
|
|
46
|
+
type Calendar = ReturnType<typeof Calendar>;
|
|
47
|
+
export default Calendar;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
@component Card
|
|
3
|
+
卡片组件,默认使用 border 而非 shadow,更现代克制。
|
|
4
|
+
-->
|
|
5
|
+
<script lang='ts'>
|
|
6
|
+
import type { CardProps } from '../../types.js'
|
|
7
|
+
import { cn } from '../../utils.js'
|
|
8
|
+
|
|
9
|
+
const {
|
|
10
|
+
title = '',
|
|
11
|
+
bordered = false,
|
|
12
|
+
shadow = 'sm',
|
|
13
|
+
padding = 'md',
|
|
14
|
+
class: className = '',
|
|
15
|
+
header,
|
|
16
|
+
footer,
|
|
17
|
+
children,
|
|
18
|
+
}: CardProps = $props()
|
|
19
|
+
|
|
20
|
+
const paddingMap = {
|
|
21
|
+
'none': '',
|
|
22
|
+
'xs': 'p-2',
|
|
23
|
+
'sm': 'p-3',
|
|
24
|
+
'md': 'p-4',
|
|
25
|
+
'lg': 'p-6',
|
|
26
|
+
'xl': 'p-8',
|
|
27
|
+
'2xl': 'p-10',
|
|
28
|
+
'3xl': 'p-12',
|
|
29
|
+
'4xl': 'p-16',
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const shadowMap = {
|
|
33
|
+
true: 'shadow-md',
|
|
34
|
+
false: '',
|
|
35
|
+
sm: 'shadow-sm',
|
|
36
|
+
md: 'shadow-md',
|
|
37
|
+
lg: 'shadow-lg',
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const cardClass = $derived(
|
|
41
|
+
cn(
|
|
42
|
+
'card bg-base-100 rounded-xl border border-base-content/6',
|
|
43
|
+
bordered && 'border-base-300',
|
|
44
|
+
typeof shadow === 'boolean' ? shadowMap[String(shadow) as 'true' | 'false'] : shadowMap[shadow],
|
|
45
|
+
className,
|
|
46
|
+
),
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
const bodyClass = $derived(
|
|
50
|
+
cn(
|
|
51
|
+
'card-body',
|
|
52
|
+
paddingMap[padding],
|
|
53
|
+
),
|
|
54
|
+
)
|
|
55
|
+
</script>
|
|
56
|
+
|
|
57
|
+
<div class={cardClass}>
|
|
58
|
+
<div class={bodyClass}>
|
|
59
|
+
{#if header}
|
|
60
|
+
<div class='card-title text-sm font-semibold'>
|
|
61
|
+
{@render header()}
|
|
62
|
+
</div>
|
|
63
|
+
{:else if title}
|
|
64
|
+
<h2 class='card-title text-sm font-semibold'>{title}</h2>
|
|
65
|
+
{/if}
|
|
66
|
+
|
|
67
|
+
{#if children}
|
|
68
|
+
{@render children()}
|
|
69
|
+
{/if}
|
|
70
|
+
|
|
71
|
+
{#if footer}
|
|
72
|
+
<div class='card-actions justify-end mt-4'>
|
|
73
|
+
{@render footer()}
|
|
74
|
+
</div>
|
|
75
|
+
{/if}
|
|
76
|
+
</div>
|
|
77
|
+
</div>
|