@h-ai/ui 0.1.0-alpha.61 → 0.1.0-alpha.63

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 (79) hide show
  1. package/README.en.md +93 -8
  2. package/README.ja.md +93 -8
  3. package/README.md +94 -8
  4. package/auto-import.d.ts +3 -0
  5. package/auto-import.js +3 -0
  6. package/dist/components/compounds/Combobox.svelte +19 -6
  7. package/dist/components/compounds/Combobox.svelte.d.ts +2 -2
  8. package/dist/components/compounds/DatePicker.svelte +14 -5
  9. package/dist/components/compounds/DatePicker.svelte.d.ts +2 -2
  10. package/dist/components/compounds/Form.svelte +10 -6
  11. package/dist/components/compounds/FormField.svelte +78 -13
  12. package/dist/components/compounds/FormLayout.svelte +59 -0
  13. package/dist/components/compounds/FormLayout.svelte.d.ts +4 -0
  14. package/dist/components/compounds/TagInput.svelte +1 -1
  15. package/dist/components/compounds/index.d.ts +1 -0
  16. package/dist/components/compounds/index.js +1 -0
  17. package/dist/components/primitives/BareInput.svelte +7 -1
  18. package/dist/components/primitives/Checkbox.svelte +8 -2
  19. package/dist/components/primitives/Input.svelte +22 -11
  20. package/dist/components/primitives/Select.svelte +77 -18
  21. package/dist/components/primitives/Textarea.svelte +27 -13
  22. package/dist/components/primitives/Textarea.svelte.d.ts +1 -1
  23. package/dist/components/scenes/app/FeedbackModal.svelte +29 -19
  24. package/dist/components/scenes/app/FeedbackModal.svelte.d.ts +2 -2
  25. package/dist/components/scenes/crud/CrudEditPanel.svelte +148 -118
  26. package/dist/components/scenes/crud/CrudEditPanel.svelte.d.ts +4 -25
  27. package/dist/components/scenes/crud/CrudPage.svelte +5 -41
  28. package/dist/components/scenes/crud/CrudPage.svelte.d.ts +2 -53
  29. package/dist/components/scenes/crud/crud-controller.svelte.d.ts +4 -1
  30. package/dist/components/scenes/crud/crud-form-validation.d.ts +4 -0
  31. package/dist/components/scenes/crud/crud-form-validation.js +39 -0
  32. package/dist/components/scenes/crud/crud-types.d.ts +9 -42
  33. package/dist/components/scenes/guide/GuideHost.svelte +111 -0
  34. package/dist/components/scenes/guide/GuideHost.svelte.d.ts +16 -0
  35. package/dist/components/scenes/guide/HelpCenter.svelte +94 -0
  36. package/dist/components/scenes/guide/HelpCenter.svelte.d.ts +13 -0
  37. package/dist/components/scenes/guide/index.d.ts +2 -0
  38. package/dist/components/scenes/guide/index.js +2 -0
  39. package/dist/components/scenes/iam/AuthPanel.svelte +55 -47
  40. package/dist/components/scenes/iam/ChangePasswordForm.svelte +57 -59
  41. package/dist/components/scenes/iam/ForgotPasswordForm.svelte +89 -84
  42. package/dist/components/scenes/iam/LoginForm.svelte +134 -132
  43. package/dist/components/scenes/iam/PasswordInput.svelte +25 -7
  44. package/dist/components/scenes/iam/PasswordInput.svelte.d.ts +2 -2
  45. package/dist/components/scenes/iam/RegisterForm.svelte +95 -97
  46. package/dist/components/scenes/iam/ResetPasswordForm.svelte +83 -85
  47. package/dist/components/scenes/iam/UserProfile.svelte +9 -5
  48. package/dist/components/scenes/iam/auth-error-message.d.ts +2 -4
  49. package/dist/components/scenes/index.d.ts +1 -0
  50. package/dist/components/scenes/index.js +1 -0
  51. package/dist/components/scenes/storage/FileUpload.svelte +1 -1
  52. package/dist/components/scenes/storage/ImageUpload.svelte +1 -0
  53. package/dist/components/scenes/types.d.ts +9 -9
  54. package/dist/guide-storage.d.ts +6 -0
  55. package/dist/guide-storage.js +67 -0
  56. package/dist/guide-types.d.ts +78 -0
  57. package/dist/guide-types.js +1 -0
  58. package/dist/guide.d.ts +3 -0
  59. package/dist/guide.js +3 -0
  60. package/dist/guide.svelte.d.ts +8 -0
  61. package/dist/guide.svelte.js +450 -0
  62. package/dist/i18n.svelte.d.ts +2 -1
  63. package/dist/i18n.svelte.js +2 -1
  64. package/dist/index.d.ts +2 -0
  65. package/dist/index.js +2 -0
  66. package/dist/internal/form-context.d.ts +12 -0
  67. package/dist/internal/form-context.js +9 -0
  68. package/dist/internal/form-validation.svelte.d.ts +16 -0
  69. package/dist/internal/form-validation.svelte.js +76 -0
  70. package/dist/internal/locale.d.ts +2 -0
  71. package/dist/internal/locale.js +22 -0
  72. package/dist/messages/en-US.json +30 -1
  73. package/dist/messages/zh-CN.json +30 -1
  74. package/dist/messages.d.ts +2 -1
  75. package/dist/messages.js +6 -4
  76. package/dist/styles/guide.css +88 -0
  77. package/dist/types.d.ts +57 -10
  78. package/package.json +13 -2
  79. package/vite.js +1 -0
@@ -0,0 +1,9 @@
1
+ import { getContext } from 'svelte';
2
+ export const FORM_LAYOUT_CONTEXT = Symbol('hai-form-layout');
3
+ export const FORM_FIELD_CONTEXT = Symbol('hai-form-field');
4
+ export function getFormLayoutContext() {
5
+ return getContext(FORM_LAYOUT_CONTEXT);
6
+ }
7
+ export function getFormFieldContext() {
8
+ return getContext(FORM_FIELD_CONTEXT);
9
+ }
@@ -0,0 +1,16 @@
1
+ /** 将原生校验状态保留为消息键,显示时按当前 UI 语言解析。 */
2
+ import type { UIMessageKey } from '../messages.js';
3
+ import type { FormText } from '../types.js';
4
+ export interface FormValidationIssue {
5
+ key: UIMessageKey;
6
+ params?: Record<string, string | number>;
7
+ }
8
+ type FormControl = HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement;
9
+ export declare function resolveFormText(text?: FormText): string;
10
+ export declare function createControlValidation(getOverride?: () => FormText | undefined, getValue?: () => unknown): {
11
+ readonly message: string;
12
+ invalid(control: FormControl): void;
13
+ input(control: FormControl): void;
14
+ reset: () => void;
15
+ };
16
+ export {};
@@ -0,0 +1,76 @@
1
+ import { untrack } from 'svelte';
2
+ import { getUILocale, uiM } from '../messages.js';
3
+ export function resolveFormText(text) {
4
+ if (typeof text !== 'function')
5
+ return text ?? '';
6
+ // 应用翻译函数也在 UI 语言同步后重新求值。
7
+ void getUILocale();
8
+ return text();
9
+ }
10
+ function readIssue(control) {
11
+ if (!control.willValidate)
12
+ return undefined;
13
+ const validity = control.validity;
14
+ if (validity.valueMissing)
15
+ return { key: 'form_required' };
16
+ if (validity.typeMismatch)
17
+ return { key: control.getAttribute('type') === 'email' ? 'form_email' : 'form_url' };
18
+ if (validity.tooShort)
19
+ return { key: 'form_min_length', params: { min: control.getAttribute('minlength') ?? '' } };
20
+ if (validity.tooLong)
21
+ return { key: 'form_max_length', params: { max: control.getAttribute('maxlength') ?? '' } };
22
+ if (validity.rangeUnderflow)
23
+ return { key: 'form_min', params: { min: control.getAttribute('min') ?? '' } };
24
+ if (validity.rangeOverflow)
25
+ return { key: 'form_max', params: { max: control.getAttribute('max') ?? '' } };
26
+ if (validity.stepMismatch)
27
+ return { key: 'form_step', params: { step: control.getAttribute('step') ?? '1' } };
28
+ if (validity.badInput)
29
+ return { key: 'form_number' };
30
+ if (validity.patternMismatch)
31
+ return { key: 'form_pattern' };
32
+ return undefined;
33
+ }
34
+ export function createControlValidation(getOverride = () => undefined, getValue) {
35
+ let issue = $state();
36
+ let currentControl = $state();
37
+ function reset() {
38
+ issue = undefined;
39
+ currentControl?.setCustomValidity('');
40
+ }
41
+ $effect(() => {
42
+ const form = currentControl?.form;
43
+ form?.addEventListener('reset', reset);
44
+ return () => form?.removeEventListener('reset', reset);
45
+ });
46
+ $effect(() => {
47
+ getValue?.();
48
+ const control = currentControl;
49
+ if (control) {
50
+ // 回填、重置及约束变更不一定触发 input;同步清除过期的原生错误。
51
+ untrack(() => {
52
+ control.setCustomValidity('');
53
+ if (issue)
54
+ issue = readIssue(control);
55
+ });
56
+ }
57
+ });
58
+ return {
59
+ get message() {
60
+ return issue ? resolveFormText(getOverride()) || uiM(issue.key, issue.params) : '';
61
+ },
62
+ invalid(control) {
63
+ currentControl = control;
64
+ control.setCustomValidity('');
65
+ issue = readIssue(control);
66
+ control.setCustomValidity(issue ? resolveFormText(getOverride()) || uiM(issue.key, issue.params) : '');
67
+ },
68
+ input(control) {
69
+ currentControl = control;
70
+ control.setCustomValidity('');
71
+ if (issue)
72
+ issue = readIssue(control);
73
+ },
74
+ reset,
75
+ };
76
+ }
@@ -0,0 +1,2 @@
1
+ export declare function readUILocale(): string;
2
+ export declare function changeUILocale(locale: string): void;
@@ -0,0 +1,22 @@
1
+ /** UI 语言变更触发组件重新求值;实际语言仍由 core 统一管理。 */
2
+ import { core } from '@h-ai/core';
3
+ import { untrack } from 'svelte';
4
+ import { createSubscriber } from 'svelte/reactivity';
5
+ let notifyLocaleChange;
6
+ const subscribe = createSubscriber((update) => {
7
+ notifyLocaleChange = update;
8
+ return () => {
9
+ notifyLocaleChange = undefined;
10
+ };
11
+ });
12
+ export function readUILocale() {
13
+ subscribe();
14
+ return core.i18n.getGlobalLocale();
15
+ }
16
+ export function changeUILocale(locale) {
17
+ core.i18n.setGlobalLocale(locale);
18
+ // 宿主可能在 $effect 中同步语言,setter 不能反向订阅自身状态。
19
+ untrack(() => {
20
+ notifyLocaleChange?.();
21
+ });
22
+ }
@@ -351,5 +351,34 @@
351
351
  "password_policy_uppercase": "Include uppercase letters",
352
352
  "password_policy_lowercase": "Include lowercase letters",
353
353
  "password_policy_number": "Include numbers",
354
- "password_policy_special": "Include special characters"
354
+ "password_policy_special": "Include special characters",
355
+ "guide_welcome": "Welcome",
356
+ "guide_start": "Start tour",
357
+ "guide_later": "Remind me later",
358
+ "guide_dismiss": "Do not remind me",
359
+ "guide_help": "Help center",
360
+ "guide_close": "Close",
361
+ "guide_loading": "Preparing your tour…",
362
+ "guide_next": "Next",
363
+ "guide_previous": "Previous",
364
+ "guide_done": "Done",
365
+ "guide_progress": "Step {current} of {total}",
366
+ "guide_search": "Search help",
367
+ "guide_empty": "No matching help content",
368
+ "guide_tours": "Product tours",
369
+ "guide_unavailable": "This tour is unavailable. Choose another topic in the help center.",
370
+ "guide_targetMissing": "This action is not available on the current page. Try again later or read the help content.",
371
+ "guide_startFailed": "Unable to start the tour. Please try again later.",
372
+ "form_required": "This field is required.",
373
+ "form_email": "Enter a valid email address.",
374
+ "form_url": "Enter a valid URL.",
375
+ "form_number": "Enter a valid number.",
376
+ "form_min_length": "Enter at least {min} characters.",
377
+ "form_max_length": "Enter no more than {max} characters.",
378
+ "form_min": "Enter a value of at least {min}.",
379
+ "form_max": "Enter a value no greater than {max}.",
380
+ "form_step": "Enter a value in increments of {step}.",
381
+ "form_pattern": "Enter a value in the required format.",
382
+ "select_clear": "Clear selection",
383
+ "select_no_match": "No matching options"
355
384
  }
@@ -351,5 +351,34 @@
351
351
  "password_policy_uppercase": "包含大写字母",
352
352
  "password_policy_lowercase": "包含小写字母",
353
353
  "password_policy_number": "包含数字",
354
- "password_policy_special": "包含特殊字符"
354
+ "password_policy_special": "包含特殊字符",
355
+ "guide_welcome": "欢迎使用",
356
+ "guide_start": "开始引导",
357
+ "guide_later": "稍后提醒",
358
+ "guide_dismiss": "不再提醒",
359
+ "guide_help": "帮助中心",
360
+ "guide_close": "关闭",
361
+ "guide_loading": "正在准备引导…",
362
+ "guide_next": "下一步",
363
+ "guide_previous": "上一步",
364
+ "guide_done": "完成",
365
+ "guide_progress": "第 {current} / {total} 步",
366
+ "guide_search": "搜索帮助内容",
367
+ "guide_empty": "没有找到相关帮助内容",
368
+ "guide_tours": "操作导览",
369
+ "guide_unavailable": "此引导暂不可用,请从帮助中心选择其他内容。",
370
+ "guide_targetMissing": "当前页面暂未提供此操作。请稍后重试或查看帮助内容。",
371
+ "guide_startFailed": "无法开始引导,请稍后重试。",
372
+ "form_required": "请填写此项。",
373
+ "form_email": "请输入有效的邮箱地址。",
374
+ "form_url": "请输入有效的网址。",
375
+ "form_number": "请输入有效的数字。",
376
+ "form_min_length": "请至少输入 {min} 个字符。",
377
+ "form_max_length": "请最多输入 {max} 个字符。",
378
+ "form_min": "请输入不小于 {min} 的值。",
379
+ "form_max": "请输入不大于 {max} 的值。",
380
+ "form_step": "请按 {step} 的步长输入。",
381
+ "form_pattern": "请按要求的格式填写。",
382
+ "select_clear": "清空选择",
383
+ "select_no_match": "无匹配选项"
355
384
  }
@@ -11,6 +11,7 @@ export type UIMessageKey = keyof typeof messagesZhCN;
11
11
  *
12
12
  * @param key - 消息 key
13
13
  * @param params - 可选的插值参数
14
+ * @param locale - 可选的宿主语言;省略时使用现有全局语言
14
15
  * @returns 当前 locale 对应的翻译文本
15
16
  *
16
17
  * @example
@@ -18,7 +19,7 @@ export type UIMessageKey = keyof typeof messagesZhCN;
18
19
  * uiM('password_show') // => '显示密码' (zh-CN) 或 'Show password' (en-US)
19
20
  * ```
20
21
  */
21
- export declare function uiM(key: UIMessageKey, params?: Record<string, string | number | boolean>): string;
22
+ export declare function uiM(key: UIMessageKey, params?: Record<string, string | number | boolean>, locale?: string): string;
22
23
  /**
23
24
  * 获取当前 UI 模块使用的 locale
24
25
  */
package/dist/messages.js CHANGED
@@ -5,6 +5,7 @@
5
5
  * @module messages
6
6
  */
7
7
  import { core } from '@h-ai/core';
8
+ import { changeUILocale, readUILocale } from './internal/locale.js';
8
9
  // 导入消息文件
9
10
  import messagesEnUS from './messages/en-US.json';
10
11
  import messagesZhCN from './messages/zh-CN.json';
@@ -18,6 +19,7 @@ const getMessage = core.i18n.createMessageGetter({
18
19
  *
19
20
  * @param key - 消息 key
20
21
  * @param params - 可选的插值参数
22
+ * @param locale - 可选的宿主语言;省略时使用现有全局语言
21
23
  * @returns 当前 locale 对应的翻译文本
22
24
  *
23
25
  * @example
@@ -25,18 +27,18 @@ const getMessage = core.i18n.createMessageGetter({
25
27
  * uiM('password_show') // => '显示密码' (zh-CN) 或 'Show password' (en-US)
26
28
  * ```
27
29
  */
28
- export function uiM(key, params) {
29
- return getMessage(key, params ? { params } : undefined);
30
+ export function uiM(key, params, locale) {
31
+ return getMessage(key, { params, locale: locale ?? readUILocale() });
30
32
  }
31
33
  /**
32
34
  * 获取当前 UI 模块使用的 locale
33
35
  */
34
36
  export function getUILocale() {
35
- return core.i18n.getGlobalLocale();
37
+ return readUILocale();
36
38
  }
37
39
  /**
38
40
  * 手动设置 UI 模块的 locale(通常不需要,会自动同步)
39
41
  */
40
42
  export function setUILocale(locale) {
41
- core.i18n.setGlobalLocale(locale);
43
+ changeUILocale(locale);
42
44
  }
@@ -0,0 +1,88 @@
1
+ /* 引导浮层挂到 body,使用全局主题变量,避免 Svelte 局部样式失效。 */
2
+ .driver-popover.hai-guide-popover {
3
+ background: var(--color-base-100);
4
+ color: var(--color-base-content);
5
+ border: 1px solid color-mix(in oklch, var(--color-base-content) 12%, transparent);
6
+ border-radius: var(--hai-radius-lg, 16px);
7
+ box-shadow: var(--shadow-overlay, 0 16px 48px -12px #0003);
8
+ padding: 20px;
9
+ min-width: 240px;
10
+ max-width: min(360px, calc(100vw - 24px));
11
+ --driver-popover-font-family: inherit;
12
+ }
13
+
14
+ .hai-guide-popover .driver-popover-title {
15
+ font-size: 16px;
16
+ font-weight: 600;
17
+ line-height: 1.5;
18
+ }
19
+ .hai-guide-popover .driver-popover-description {
20
+ font-size: 14px;
21
+ line-height: 1.75;
22
+ overflow-wrap: anywhere;
23
+ }
24
+ .hai-guide-popover .driver-popover-progress-text {
25
+ color: color-mix(in oklch, var(--color-base-content) 55%, transparent);
26
+ font-size: 12px;
27
+ }
28
+ .hai-guide-popover .driver-popover-close-btn {
29
+ color: var(--color-base-content);
30
+ min-width: 36px;
31
+ min-height: 36px;
32
+ }
33
+ .hai-guide-popover .driver-popover-footer button {
34
+ border: 1px solid color-mix(in oklch, var(--color-base-content) 12%, transparent);
35
+ border-radius: var(--hai-radius-md, 8px);
36
+ background: var(--color-base-200);
37
+ color: var(--color-base-content);
38
+ padding: 8px 12px;
39
+ font-size: 13px;
40
+ font-weight: 500;
41
+ text-shadow: none;
42
+ min-height: 36px;
43
+ }
44
+ .hai-guide-popover .driver-popover-footer .driver-popover-next-btn {
45
+ background: var(--color-primary);
46
+ color: var(--color-primary-content);
47
+ border-color: var(--color-primary);
48
+ }
49
+ .hai-guide-popover button:focus-visible {
50
+ outline: 2px solid var(--color-primary);
51
+ outline-offset: 2px;
52
+ }
53
+ .hai-guide-popover .driver-popover-arrow-side-top {
54
+ border-top-color: var(--color-base-100);
55
+ }
56
+ .hai-guide-popover .driver-popover-arrow-side-bottom {
57
+ border-bottom-color: var(--color-base-100);
58
+ }
59
+ .hai-guide-popover .driver-popover-arrow-side-left {
60
+ border-left-color: var(--color-base-100);
61
+ }
62
+ .hai-guide-popover .driver-popover-arrow-side-right {
63
+ border-right-color: var(--color-base-100);
64
+ }
65
+ .hai-guide-offer {
66
+ padding-bottom: max(20px, env(safe-area-inset-bottom));
67
+ }
68
+
69
+ /* 引擎会禁用高亮区域外的指针事件,等待提示的取消按钮必须保持可操作。 */
70
+ .driver-active .hai-guide-loading,
71
+ .driver-active .hai-guide-loading * {
72
+ pointer-events: auto;
73
+ }
74
+
75
+ @media (max-width: 640px) {
76
+ .hai-guide-popover .driver-popover-footer button,
77
+ .hai-guide-popover .driver-popover-close-btn {
78
+ min-height: var(--hai-touch-target-min, 44px);
79
+ }
80
+ }
81
+
82
+ @media (prefers-reduced-motion: reduce) {
83
+ .driver-overlay,
84
+ .hai-guide-popover {
85
+ animation: none !important;
86
+ transition: none !important;
87
+ }
88
+ }
package/dist/types.d.ts CHANGED
@@ -102,9 +102,9 @@ export interface InputProps extends DataAttributes {
102
102
  /** 是否必填 */
103
103
  required?: boolean;
104
104
  /** 错误消息 */
105
- error?: string;
105
+ error?: FormText;
106
106
  /** 自定义验证消息(用于覆盖浏览器原生验证提示) */
107
- validationMessage?: string;
107
+ validationMessage?: FormText;
108
108
  /** 自定义类名 */
109
109
  class?: string;
110
110
  /** 元素 ID */
@@ -182,6 +182,10 @@ export interface BareInputProps extends DataAttributes {
182
182
  ariaControls?: string;
183
183
  /** aria-autocomplete */
184
184
  ariaAutocomplete?: 'none' | 'list' | 'inline' | 'both';
185
+ /** 字段校验状态 */
186
+ ariaInvalid?: boolean;
187
+ /** 字段提示/错误元素 ID */
188
+ ariaDescribedby?: string;
185
189
  /** 元素 ID */
186
190
  id?: string;
187
191
  /** input 引用 */
@@ -255,10 +259,19 @@ export interface TextareaProps extends DataAttributes {
255
259
  required?: boolean;
256
260
  /** 是否自动调整高度 */
257
261
  autoResize?: boolean;
258
- inputmode?: HTMLInputElement['inputMode'];
259
- error?: string;
262
+ inputmode?: InputProps['inputmode'];
263
+ error?: FormText;
260
264
  /** 自定义验证消息(用于覆盖浏览器原生验证提示) */
261
- validationMessage?: string;
265
+ validationMessage?: FormText;
266
+ /** 最小长度 */
267
+ minlength?: number;
268
+ /** 最大长度 */
269
+ maxlength?: number;
270
+ /** 原生控件引用 */
271
+ textareaRef?: HTMLTextAreaElement;
272
+ oninvalid?: (e: Event & {
273
+ currentTarget: HTMLTextAreaElement;
274
+ }) => void;
262
275
  /** 自定义类名 */
263
276
  class?: string;
264
277
  /** 元素 ID */
@@ -302,7 +315,11 @@ export interface SelectProps<T = string> extends DataAttributes {
302
315
  /** 是否可筛选(启用后可在输入框内输入过滤选项) */
303
316
  filterable?: boolean;
304
317
  /** 错误消息 */
305
- error?: string;
318
+ error?: FormText;
319
+ /** 自定义验证提示,仅在校验失败时显示。 */
320
+ validationMessage?: FormText;
321
+ /** 表单字段名 */
322
+ name?: string;
306
323
  /** 自定义类名 */
307
324
  class?: string;
308
325
  /** 元素 ID */
@@ -314,6 +331,8 @@ export interface SelectProps<T = string> extends DataAttributes {
314
331
  * 复选框属性
315
332
  */
316
333
  export interface CheckboxProps extends DataAttributes {
334
+ /** 元素 ID;用于 FormField 标签关联。 */
335
+ id?: string;
317
336
  /** 是否选中 */
318
337
  checked?: boolean;
319
338
  /** 标签 */
@@ -766,7 +785,27 @@ export interface DropdownProps extends DataAttributes {
766
785
  /**
767
786
  * 表单属性
768
787
  */
769
- export interface FormProps extends DataAttributes {
788
+ /** 表单标签位置:独立成行或与控件同行。 */
789
+ export type FormLabelPosition = 'top' | 'left';
790
+ /** 双列表单字段占用列数;auto 根据控件类型判断。 */
791
+ export type FormColSpan = 'auto' | 1 | 2;
792
+ /** 支持延迟求值的表单文案,切换语言时重新解析。 */
793
+ export type FormText = string | (() => string);
794
+ /** 表单布局配置;窄容器自动收为单列。 */
795
+ export interface FormLayoutOptions {
796
+ /** 字段列数,默认 1。 */
797
+ columns?: 1 | 2;
798
+ /** 标签位置,默认 top。 */
799
+ labelPosition?: FormLabelPosition;
800
+ /** 同行标签宽度(CSS 值),默认 8rem。 */
801
+ labelWidth?: string;
802
+ }
803
+ /** 可嵌入原生 form 的布局容器。 */
804
+ export interface FormLayoutProps extends FormLayoutOptions, DataAttributes {
805
+ class?: string;
806
+ children?: Snippet;
807
+ }
808
+ export interface FormProps extends FormLayoutOptions, DataAttributes {
770
809
  /** 表单 ID */
771
810
  id?: string;
772
811
  /** 自定义类名 */
@@ -789,13 +828,21 @@ export interface FormProps extends DataAttributes {
789
828
  */
790
829
  export interface FormFieldProps extends DataAttributes {
791
830
  /** 标签 */
792
- label?: string;
831
+ label?: FormText;
832
+ /** 关联控件 ID;省略时为内部控件自动提供唯一 ID。 */
833
+ for?: string;
834
+ /** 覆盖所在表单的标签位置。 */
835
+ labelPosition?: FormLabelPosition;
836
+ /** 覆盖所在表单的同行标签宽度。 */
837
+ labelWidth?: string;
838
+ /** 双列时的占用列数,默认 auto;多行文本、上传和多选自动占两列。 */
839
+ colSpan?: FormColSpan;
793
840
  /** 字段名 */
794
841
  name?: string;
795
842
  /** 错误消息 */
796
- error?: string;
843
+ error?: FormText;
797
844
  /** 提示信息 */
798
- hint?: string;
845
+ hint?: FormText;
799
846
  /** 是否必填 */
800
847
  required?: boolean;
801
848
  /** 自定义类名 */
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@h-ai/ui",
3
3
  "type": "module",
4
- "version": "0.1.0-alpha.61",
4
+ "version": "0.1.0-alpha.63",
5
5
  "description": "Hai Framework UI component library for Svelte 5 Runes.",
6
6
  "license": "Apache-2.0",
7
7
  "svelte": "./dist/index.js",
@@ -19,10 +19,20 @@
19
19
  "types": "./vite.d.ts",
20
20
  "import": "./vite.js"
21
21
  },
22
+ "./i18n": {
23
+ "types": "./dist/i18n.svelte.d.ts",
24
+ "svelte": "./dist/i18n.svelte.js",
25
+ "import": "./dist/i18n.svelte.js"
26
+ },
22
27
  "./theme": {
23
28
  "types": "./dist/theme-config.d.ts",
24
29
  "import": "./dist/theme-config.js"
25
30
  },
31
+ "./guide": {
32
+ "types": "./dist/guide.d.ts",
33
+ "svelte": "./dist/guide.js",
34
+ "import": "./dist/guide.js"
35
+ },
26
36
  "./components/*": {
27
37
  "types": "./dist/components/*.d.ts",
28
38
  "svelte": "./dist/components/*.js",
@@ -49,10 +59,11 @@
49
59
  "svelte": "^5.57.2"
50
60
  },
51
61
  "dependencies": {
52
- "@h-ai/core": "0.1.0-alpha.61",
62
+ "@h-ai/core": "0.1.0-alpha.63",
53
63
  "@internationalized/date": "^3.12.4",
54
64
  "@shikijs/langs": "^4.5.0",
55
65
  "bits-ui": "^2.19.5",
66
+ "driver.js": "1.9.0",
56
67
  "html2canvas": "^1.4.1",
57
68
  "jspdf": "^4.2.1",
58
69
  "layerchart": "2.6.1",
package/vite.js CHANGED
@@ -68,6 +68,7 @@ export const haiPrebundledDeps = Object.freeze([
68
68
  'html2canvas',
69
69
  // ─── 工具 ───
70
70
  'tailwind-merge',
71
+ 'driver.js',
71
72
  // ─── 框架运行时(@h-ai/core / @h-ai/crypto / @h-ai/kit 在登录等路径引入) ───
72
73
  'nanoid',
73
74
  'process',