@haiyue/ui 0.1.1 → 0.2.1

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 (99) hide show
  1. package/CHANGELOG.md +56 -0
  2. package/README.md +504 -1
  3. package/dist/adapters/web/controls.d.ts +19 -0
  4. package/dist/adapters/web/controls.js +284 -0
  5. package/dist/adapters/web/dom.d.ts +10 -0
  6. package/dist/adapters/web/dom.js +98 -0
  7. package/dist/adapters/web/index.d.ts +3 -0
  8. package/dist/adapters/web/index.js +3 -0
  9. package/dist/adapters/web/renderer.d.ts +18 -0
  10. package/dist/adapters/web/renderer.js +545 -0
  11. package/dist/adapters/web/styles.d.ts +3 -0
  12. package/dist/adapters/web/styles.js +62 -0
  13. package/dist/adapters/web/types.d.ts +46 -0
  14. package/dist/adapters/web/types.js +2 -0
  15. package/dist/affix.d.ts +35 -0
  16. package/dist/affix.js +137 -0
  17. package/dist/badge.d.ts +45 -0
  18. package/dist/badge.js +168 -0
  19. package/dist/border-beam.js +3 -1
  20. package/dist/breadcrumb.d.ts +37 -0
  21. package/dist/breadcrumb.js +210 -0
  22. package/dist/button-group.d.ts +12 -0
  23. package/dist/button-group.js +72 -0
  24. package/dist/button.d.ts +15 -1
  25. package/dist/button.js +101 -12
  26. package/dist/cascader.d.ts +65 -0
  27. package/dist/cascader.js +479 -0
  28. package/dist/collapse.d.ts +55 -0
  29. package/dist/collapse.js +261 -0
  30. package/dist/core/actions.d.ts +32 -0
  31. package/dist/core/actions.js +145 -0
  32. package/dist/core/data.d.ts +4 -0
  33. package/dist/core/data.js +27 -0
  34. package/dist/core/index.d.ts +7 -0
  35. package/dist/core/index.js +6 -0
  36. package/dist/core/platform-view.d.ts +17 -0
  37. package/dist/core/platform-view.js +84 -0
  38. package/dist/core/selection.d.ts +14 -0
  39. package/dist/core/selection.js +93 -0
  40. package/dist/core/text.d.ts +31 -0
  41. package/dist/core/text.js +154 -0
  42. package/dist/core/types.d.ts +250 -0
  43. package/dist/core/types.js +2 -0
  44. package/dist/core/validation.d.ts +24 -0
  45. package/dist/core/validation.js +238 -0
  46. package/dist/date-picker.d.ts +60 -0
  47. package/dist/date-picker.js +355 -0
  48. package/dist/dialog.d.ts +4 -0
  49. package/dist/dialog.js +23 -5
  50. package/dist/divider.d.ts +33 -0
  51. package/dist/divider.js +113 -0
  52. package/dist/draggable.d.ts +78 -0
  53. package/dist/draggable.js +255 -0
  54. package/dist/expandable.d.ts +32 -0
  55. package/dist/expandable.js +136 -0
  56. package/dist/index.d.ts +47 -1
  57. package/dist/index.js +69 -0
  58. package/dist/input.d.ts +30 -1
  59. package/dist/input.js +166 -54
  60. package/dist/portable/index.d.ts +4 -0
  61. package/dist/portable/index.js +3 -0
  62. package/dist/portable/page.d.ts +38 -0
  63. package/dist/portable/page.js +361 -0
  64. package/dist/portable/theme.d.ts +19 -0
  65. package/dist/portable/theme.js +40 -0
  66. package/dist/portable/tree.d.ts +10 -0
  67. package/dist/portable/tree.js +96 -0
  68. package/dist/range.d.ts +3 -0
  69. package/dist/range.js +16 -5
  70. package/dist/rate.d.ts +46 -0
  71. package/dist/rate.js +193 -0
  72. package/dist/resizable.d.ts +97 -0
  73. package/dist/resizable.js +426 -0
  74. package/dist/skeleton.d.ts +41 -0
  75. package/dist/skeleton.js +141 -0
  76. package/dist/steps.d.ts +45 -0
  77. package/dist/steps.js +203 -0
  78. package/dist/table.d.ts +106 -0
  79. package/dist/table.js +689 -0
  80. package/dist/tabs.d.ts +7 -0
  81. package/dist/tabs.js +90 -16
  82. package/dist/tag.d.ts +55 -0
  83. package/dist/tag.js +225 -0
  84. package/dist/time-picker.d.ts +62 -0
  85. package/dist/time-picker.js +298 -0
  86. package/dist/timeline.d.ts +48 -0
  87. package/dist/timeline.js +201 -0
  88. package/dist/toast.d.ts +55 -0
  89. package/dist/toast.js +224 -0
  90. package/dist/tour.d.ts +89 -0
  91. package/dist/tour.js +306 -0
  92. package/dist/virtual-keyboard.d.ts +95 -0
  93. package/dist/virtual-keyboard.js +432 -0
  94. package/dist/virtual-list.js +12 -10
  95. package/dist/virtual-mouse.d.ts +82 -0
  96. package/dist/virtual-mouse.js +358 -0
  97. package/dist/watermark.d.ts +44 -0
  98. package/dist/watermark.js +148 -0
  99. package/package.json +135 -7
package/CHANGELOG.md ADDED
@@ -0,0 +1,56 @@
1
+ # Changelog
2
+
3
+ ## 0.2.1 - 2026-10-20
4
+
5
+ - 新增可按需导入的 `HYTag` / `<hy-tag>` 标签组件,支持语义与自定义配色、三种尺寸、文字或 icon 插槽、可取消的关闭事件、可选择状态、键盘操作和禁用状态;新增 `HYToast` / `<hy-toast>` 轻提示组件,支持五种状态、上/中/下位置、自动或持久显示、最大数量、手动关闭/清空、生命周期事件与完整计时器清理。
6
+ - M24 G05 新增独立 `adapters/web` 子路径:18 种共享语义映射、显式注册、受控输入/选择/弹窗、主题/安全区、预览资源生命周期与基础组件示例。新增可选 `controlled` 属性(Tabs/Range/Dialog)和 Input `password` 类型;旧默认 API 保留。修复关闭后立即重开的过期回调,以及共享页面把隐藏标签页误判为可聚焦的问题。Chromium/WebKit 自动化已通过,物理输入与读屏验收范围单独记录。
7
+ - M24 G03 新增独立 `core` / `portable` 子路径:18 种组件语义、交互 controller、受限页面组合、selector 订阅、稳定节点差异、事务、生命周期与主题数据;无 DOM/NativeScript/Engine 依赖。仅完成核心及记录型后端验证,真实平台适配分别由 G05/G06/G08 交付,旧 Web API 保持不变。
8
+ - 扩展 `HYVirtualKeyboard` / `<hy-virtual-keyboard>`:默认 QWERTY 布局补齐上、下方向键及多行文本纵向光标移动;新增 `qwerty` / `numeric` 模式切换和可复用的 `HY_VIRTUAL_KEYBOARD_NUMERIC_LAYOUT` 内置数字键盘。
9
+ - 扩展 `HYButton` / `<hy-button>`:支持 `icon` 属性或 `icon` 插槽、`icon-position` 前后位置、会阻止重复点击并带无障碍忙碌状态的 `loading` 旋转图标;新增可按需导入的 `HYButtonGroup` / `<hy-button-group>`,支持横向和纵向组合按钮。
10
+ - 示例页外壳改为使用 Haiyue UI 自身搭建:主题按钮、组件搜索、命令面板、状态徽标和演示操作均复用公开 Web Components;导航/内容和演示/参数区域使用 `HYSplit` 调节尺寸,用法代码通过只读 CodeMirror 提供 HTML、JavaScript 与 CSS 语法高亮,并为 `HYButton` 暴露 `button` part 与 pressed 状态转发。
11
+ - 新增可按需导入的 `HYResizable` / `<hy-resizable>` 调整框组件,支持四个角点与四条边缩放、内容拖动、位置尺寸 API、父容器/视口/元素边界、网格吸附、宽高比、尺寸限制、键盘控制和生命周期事件。
12
+ - 扩展 `HYInput` / `<hy-input>`:新增 prefix/suffix 属性与同名插槽、`search` 输入类型、可访问的搜索按钮、回车/API 搜索和组合 `search` 事件。
13
+ - 新增可按需导入的 `HYDraggable` / `<hy-draggable>` 拖拽容器,支持手柄与排除选择器、双轴/单轴移动、父容器/视口/元素边界、网格吸附、键盘控制、位置 API、生命周期事件与主题样式钩子。
14
+ - 新增可按需导入的 `HYVirtualKeyboard` / `<hy-virtual-keyboard>` 虚拟键盘,提供默认 QWERTY 与自定义布局、输入目标绑定、Shift/Caps、编辑和光标按键、物理键盘同步、按键播放 API、组合事件与主题样式钩子。
15
+ - 新增可按需导入的 `HYCollapse` / `<hy-collapse>` 折叠面板组件,支持多项或手风琴展开、默认/当前展开项、禁用面板、图标位置、触发区域、边框/幽灵样式、隐藏内容销毁和无障碍键盘操作。
16
+ - 新增可按需导入的 `HYBadge` / `<hy-badge>` 徽标组件,支持计数上限、零值显隐、圆点、小尺寸、语义状态、自定义颜色、偏移、标题和无障碍状态播报。
17
+ - 新增可按需导入的 `HYAffix` / `<hy-affix>` 固钉组件,支持窗口或自定义滚动容器、顶部/底部偏移、布局占位、禁用、层级和吸附状态事件。
18
+ - 新增可按需导入的 `HYTour` / `<hy-tour>` 漫游式引导组件,支持目标定位、四向或居中浮层、聚光遮罩、自动滚动、键盘/遮罩关闭、步骤控制和生命周期事件。
19
+ - 新增可按需导入的 `HYSteps` / `<hy-steps>` 步骤条组件,支持横向/纵向、当前步骤、自动及显式状态、自定义图标、描述、副标题、紧凑尺寸、点击导航与禁用步骤。
20
+ - 新增可按需导入的 `HYDivider` / `<hy-divider>` 分割线组件,支持横向/纵向、实线/虚线/点线/双线、粗细、颜色、间距,以及插槽或属性文字和三种文字位置。
21
+ - 新增可按需导入的 `HYRate` / `<hy-rate>` 星级评分组件,支持通过 `allow-half` 属性选择半星,并提供星数、清空、自定义字符、提示、只读/禁用、键盘控制及组合事件。
22
+ - 新增可按需导入的 `HYTimeline` / `<hy-timeline>` 时间轴组件,支持状态与自定义颜色/节点、左右和交替布局、倒序、Pending、响应式单列及内容渲染钩子。
23
+ - 新增可按需导入的 `HYWatermark` / `<hy-watermark>` 水印组件,支持单行或多行文字、图片、旋转、间距、偏移、尺寸、字体、颜色、透明度与层级配置,并保持底层内容可交互。
24
+ - 新增可按需导入的 `HYSkeleton` / `<hy-skeleton>` 骨架屏,支持内容自动切换、头像、标题、段落行数与宽度、尺寸、圆角、加载动画、无障碍状态及减少动态效果偏好。
25
+ - 新增可按需导入的 `HYDatePicker` / `<hy-date-picker>` 日期选择器,支持 ISO 日期、范围限制、周起始日、Today、清空、月历键盘导航与组合事件。
26
+ - 新增可按需导入的 `HYTimePicker` / `<hy-time-picker>` 时间选择器,支持时分秒、分秒步长、时间范围、Now、确认、清空、列键盘导航与组合事件。
27
+ - 新增可按需导入的 `HYCascader` / `<hy-cascader>` 级联下拉,支持树形选项、受控路径、父级选择、禁用与清空、点击外部或 Esc 关闭、方向键导航及组合事件。
28
+ - 新增可按需导入的 `HYBreadcrumb` / `<hy-breadcrumb>` 面包屑导航,兼容 `title` / `label` 项文本,支持链接、动作项、禁用项、当前页语义、自定义分隔符与内容渲染,以及可取消的 `breadcrumb-click` 事件。
29
+ - 新增可按需导入的 `HYTable` / `<hy-table>` 数据表格,支持本地分页、标题旁漏斗过滤菜单、全局与列级过滤入口显隐、稳定排序、自定义单元格渲染,以及 `table-change` / `row-click` 组合事件。
30
+ - 新增可按需导入的 `HYVirtualMouse` / `<hy-virtual-mouse>` 固定定位虚拟鼠标,支持状态图片与 CSS 定制、动画移动、按下/抬起、左中右键点击 API,以及组合事件和生命周期清理。
31
+
32
+ ## 0.1.2 - 2026-09-03
33
+
34
+ - 修复 `<hy-virtual-list>` 快速滚动时 light DOM slot 异步分发旧行的问题;虚拟窗口现在完全在 Shadow DOM 内同步替换,避免上一范围的条目再次闪现。
35
+ - 新增 `HYExpandable` / `<hy-expandable>`:保持内容挂载的非模态展开容器,提供独立子入口、尺寸与按钮位置配置、自定义图标、事件和主题变量。
36
+ - 修复展开容器位于嵌套 Shadow DOM 时 Escape 无法恢复的问题;内部菜单可优先消费 Escape,嵌套展开容器每次只关闭内层。
37
+ - Tabs 支持横向溢出滚动,并保持标签文字不换行。
38
+ - 补充展开容器示例和浏览器交互回归,覆盖键盘、焦点、事件、内容保留及断开重连。
39
+ - API 基线、包体积与消费者验证由 UI 仓库独立维护,不再由 Engine 发布门禁管理。
40
+
41
+ ## 0.1.1 - 2026-08-22
42
+
43
+ - 新增可按需导入的 `HYRange` / `<hy-range>` 数值滑块,支持单值和双拖拽点区间、步进与键盘操作、实时/提交事件,以及拖拽点和轨道样式定制。
44
+ - 新增可按需导入的 `HYBorderBeam` / `<hy-border-beam>` 响应式边框流光组件,支持粗细、速度倍率、颜色和多流光错相配置。
45
+ - 新增可按需导入的 `HYNotification` / `<hy-notification>` 通知中心,提供 success/info/warning/error 语义配色和图标、六向 placement、自动关闭、Z 轴堆叠及可选倒计时进度条。
46
+ - 新增可按需导入的 `HYDrawer` / `<hy-drawer>` 抽屉组件,支持四向 placement、可选蒙层、Esc/蒙层关闭、焦点管理及 `destroyOnHidden` 内容卸载。
47
+ - 新增可按需导入的 `HYVirtualList` / `<hy-virtual-list>` 固定行高虚拟列表,仅渲染可视区与 overscan 缓冲项,并提供内部滚动条、范围事件、点击事件和 `scrollToIndex()`。
48
+ - 组件品牌前缀从 `GE/ge` 统一迁移为 `HY/hy`,不保留旧标签、类名或 CSS token alias;新增可独立导入的 Moonlight 淡蓝亮色和 Nightfall 深蓝紫暗色皮肤。
49
+ - 独立 UI 仓库移除重复的 `ui/` workspace 层级,并为全部组件新增 `@haiyue/ui/<component>` 独立、无副作用的公开入口;根入口继续提供显式全量注册。
50
+
51
+ ## 0.1.0 - 2026-07-13
52
+
53
+ - 建立海月 3D 优先的稳定包边界、生命周期、编辑器工作流、可观测性、资产管线和脚本 runtime。
54
+ - 用 `simple` / `batched` / `gpu-driven` / `diagnostic` RenderProfile 替换公开渲染布尔开关,并加入显式设备降级报告。
55
+ - 加入原生 glTF metallic-roughness PBR、directional shadow map、environment IBL、material variants 和可扩展材质 shader contract。
56
+ - examples/games 改为 manifest 驱动,统一 build policy、能力覆盖矩阵、真实 WebGPU 像素基线和 release gate。
package/README.md CHANGED
@@ -3,6 +3,8 @@
3
3
  Dependency-free Web Components for HaiyueStudio products. Components own presentation and local interaction;
4
4
  they do not depend on Engine, Editor, Games, or AIStudio state.
5
5
 
6
+ **Online component gallery:** <https://haiyuestudio.github.io/UI/>
7
+
6
8
  Public classes use the `HY` prefix and custom-element tags use `hy-`:
7
9
 
8
10
  ```html
@@ -21,10 +23,12 @@ helpers, and registration stays explicit:
21
23
 
22
24
  ```ts
23
25
  import { defineButtonComponents } from '@haiyue/ui/button';
26
+ import { defineButtonGroupComponents } from '@haiyue/ui/button-group';
24
27
  import { defineTreeComponents } from '@haiyue/ui/tree';
25
28
  import { defineVirtualListComponents } from '@haiyue/ui/virtual-list';
26
29
 
27
30
  defineButtonComponents();
31
+ defineButtonGroupComponents();
28
32
  defineTreeComponents();
29
33
  defineVirtualListComponents();
30
34
  ```
@@ -44,6 +48,128 @@ defineHaiyueUI();
44
48
  Because `defineHaiyueUI()` references the complete component set, prefer focused subpaths in bundle-sensitive
45
49
  product entry points.
46
50
 
51
+ ## Tag and toast
52
+
53
+ Tags provide compact semantic labels with optional checked and close interactions. Toasts are an imperative,
54
+ lightweight feedback surface for short-lived messages; use Notification when a message also needs a description
55
+ or richer stacked content.
56
+
57
+ ```ts
58
+ import { defineTagComponents } from '@haiyue/ui/tag';
59
+ import { defineToastComponents } from '@haiyue/ui/toast';
60
+
61
+ defineTagComponents();
62
+ defineToastComponents();
63
+ ```
64
+
65
+ ```html
66
+ <hy-tag variant="success" icon="✓" closable>Synced</hy-tag>
67
+ <hy-tag variant="primary" checkable value="featured">Featured</hy-tag>
68
+ <hy-toast id="feedback" placement="top" duration="3" closable></hy-toast>
69
+ <script type="module">
70
+ feedback.success('Saved successfully');
71
+ const key = feedback.loading('Exporting…');
72
+ // Reusing a key replaces the persistent loading toast.
73
+ feedback.success({ key, message: 'Export complete' });
74
+ </script>
75
+ ```
76
+
77
+ ## Button icons, loading, and groups
78
+
79
+ Buttons accept a text `icon` or a richer `icon` slot. Set `icon-position="end"` to place it after the label.
80
+ The boolean `loading` attribute replaces the configured icon with a spinner, marks the native button busy, and
81
+ temporarily disables activation so an asynchronous request cannot be submitted twice.
82
+
83
+ ```html
84
+ <hy-button label="Publish" icon="↥"></hy-button>
85
+ <hy-button label="Continue" icon="→" icon-position="end"></hy-button>
86
+ <hy-button loading label="Syncing"></hy-button>
87
+ <hy-button label="Upload"><svg slot="icon" aria-hidden="true">…</svg></hy-button>
88
+
89
+ <hy-button-group aria-label="History actions">
90
+ <hy-button label="Undo" icon="↶"></hy-button>
91
+ <hy-button label="Redo" icon="↷"></hy-button>
92
+ </hy-button-group>
93
+ ```
94
+
95
+ Use `orientation="vertical"` for a stacked group. Button styling is exposed through the `button`, `content`,
96
+ `icon`, and `spinner` parts; the group exposes its container as the `group` part.
97
+
98
+ ## Input and search
99
+
100
+ `HYInput` supports plain-text `prefix` and `suffix` attributes as well as named slots for icons or richer
101
+ content. Use `type="search"` to add an accessible search action button:
102
+
103
+ ```html
104
+ <hy-input type="search" prefix="⌕" suffix="assets"
105
+ placeholder="Search…" search-label="Search assets"></hy-input>
106
+
107
+ <hy-input placeholder="Amount">
108
+ <span slot="prefix">¥</span>
109
+ <span slot="suffix">CNY</span>
110
+ </hy-input>
111
+ ```
112
+
113
+ Search inputs emit a composed, cancelable `search` event when the user presses Enter, activates the search
114
+ button, or the application calls `search()`. Its detail contains `{ value, valid, source }`, where `source` is
115
+ `enter`, `button`, or `api`. Existing `value-change`, validation, number, and color input behavior remains
116
+ available. Style the `control`, `input`, `prefix`, `suffix`, and `search-button` parts or the
117
+ `--hy-input-affix-*` and `--hy-input-search-*` tokens.
118
+
119
+ ## Portable component semantics (M24 G03/G05, unreleased)
120
+
121
+ `@haiyue/ui/core` provides platform-independent component types, validation, selection/input/action
122
+ controllers and the `PlatformView` lifetime contract. `@haiyue/ui/portable` provides `HYPage`, selector
123
+ bindings, keyed updates, transactions, focus/modal policy and semantic theme conversion. Both entries
124
+ can be imported without DOM, NativeScript or Engine. They do not register existing Web Components.
125
+
126
+ ```ts
127
+ import { hyNode, hyKey, type HYRenderer } from '@haiyue/ui/core';
128
+ import { HYPage } from '@haiyue/ui/portable';
129
+
130
+ export function mountPage(renderer: HYRenderer) {
131
+ const page = new HYPage(renderer);
132
+ page.mount(hyNode('Column', 'settings', { layout: { gap: 8 } }, {
133
+ children: [hyNode('Text', 'title', { text: 'Settings' })],
134
+ }));
135
+ page.setProps(hyKey('settings', 'title'), 'Text', { text: 'Preview settings' });
136
+ return page; // The shell forwards suspend/resume and calls dispose on exit.
137
+ }
138
+ ```
139
+
140
+ Author keys are stable and unique within each parent, including its named slots. `hyKey()` builds
141
+ scoped keys for bindings, events and focus. `setProps()` completely replaces a node's props; use
142
+ `transaction()` for one synchronous batch. Group all selectors for a given store in one `bind(store,
143
+ bindings)` call so an application transaction produces one renderer commit. Identical props produce
144
+ no writes; reordering preserves instances. Applications persist values on `commit`, not `valueChange`.
145
+
146
+ The Web backend is available from `@haiyue/ui/adapters/web`: explicitly call
147
+ `definePortableWebComponents()`, construct `new HYWebRenderer(connectedElement, options)`, then pass it
148
+ to `HYPage`. It reuses seven existing Web Components and maps the other semantic kinds to browser
149
+ elements. It introduces no runtime package dependencies or automatic registration. See the
150
+ [Web adapter guide](docs/web-adapter.md) and [interactive example](examples/portable-ui/index.html).
151
+ Run `npm run test:web-adapter` for Chromium/WebKit regression coverage.
152
+
153
+ These APIs are under development and have not been published. Mobile mapping is G06, desktop mapping
154
+ G08, and ShaderLab shared-page migration G07. Existing Web component APIs below remain independent. See the
155
+ [portable UI guide](docs/portable-ui.md) and [typed composition example](test/portable/fixtures/settings-page.ts).
156
+ Run `npm run verify:portable` for semantics, no-DOM types, and an isolated offline tarball consumer.
157
+
158
+ ## Tabs
159
+
160
+ `@haiyue/ui/tabs` retains its existing `HYTabs`, `HYTabOption`, `HYTabChangeDetail`, and
161
+ `defineTabsComponents` exports; the 0.1.3 fix adds no new public exports. Assign `options`
162
+ and `value`, provide children with matching `slot` names, and listen for `tab-change`.
163
+ Property-assigned options and the selected value survive reconnection. Set `aria-label`
164
+ to name the tablist. Arrow keys, Home and End both move focus and activate the next
165
+ enabled tab with roving focus; the active tab labels its panel within the component's
166
+ shadow tree. The generated `aria-controls` and tabpanel ids are per-instance opaque
167
+ values and should not be treated as stable application selectors.
168
+
169
+ The existing `@haiyue/ui/border-beam` exports are also unchanged. Its constructor only
170
+ builds shadow content; host appearance is applied after creation, avoiding browser
171
+ custom-element construction errors during repeated `document.createElement` calls.
172
+
47
173
  ## Virtual list
48
174
 
49
175
  `<hy-virtual-list>` renders only the visible fixed-height rows plus a configurable overscan buffer. The full
@@ -65,6 +191,220 @@ Use the `height` property (or `height` attribute) for the internal viewport. `vi
65
191
  exclusive `endIndex` / `visibleEndIndex` values, and `item-click` reports the source item and absolute index.
66
192
  The scrollbar can be themed with inherited semantic tokens and `--hy-virtual-list-scrollbar-size`.
67
193
 
194
+ ## Breadcrumb
195
+
196
+ Import and register breadcrumb navigation independently:
197
+
198
+ ```ts
199
+ import { defineBreadcrumbComponents } from '@haiyue/ui/breadcrumb';
200
+
201
+ defineBreadcrumbComponents();
202
+ const breadcrumb = document.querySelector('hy-breadcrumb');
203
+ breadcrumb.items = [
204
+ { key: 'projects', title: 'Projects', href: '/projects' },
205
+ { key: 'scene', title: 'Ocean World' },
206
+ { key: 'lighting', title: 'Lighting' },
207
+ ];
208
+ breadcrumb.separator = '›';
209
+ ```
210
+
211
+ Item text may use the Ant Design-compatible `title` field or its `label` alias. The final item is exposed as
212
+ the current page with `aria-current="page"`. Earlier items render as links when
213
+ they provide `href`, or as action buttons otherwise; disabled items remain readable but cannot be activated.
214
+ Listen for the composed, cancelable `breadcrumb-click` event to handle actions or prevent link navigation.
215
+ Use `renderItem` for custom item content, and `ariaLabel` when rendered content needs an explicit accessible
216
+ name. Styling hooks include the `nav`, `list`, `item`, `link`, `button`, `current`, `disabled`, and `separator`
217
+ shadow parts plus the `--hy-breadcrumb-*` CSS variables.
218
+
219
+ ## Cascader
220
+
221
+ Use the focused `@haiyue/ui/cascader` entry for hierarchical selection:
222
+
223
+ ```ts
224
+ import { defineCascaderComponents } from '@haiyue/ui/cascader';
225
+
226
+ defineCascaderComponents();
227
+ const cascader = document.querySelector('hy-cascader');
228
+ cascader.options = [
229
+ { label: 'Project', value: 'project', children: [
230
+ { label: 'Scenes', value: 'scenes', children: [
231
+ { label: 'Moon Temple', value: 'temple' },
232
+ ] },
233
+ ] },
234
+ ];
235
+ cascader.value = ['project', 'scenes', 'temple'];
236
+ ```
237
+
238
+ Selecting a leaf commits the complete value path and emits `value-change` with both values and resolved option
239
+ objects. Enable `changeOnSelect` (or `change-on-select`) when parent paths should also be committed. The component
240
+ supports string and number values, disabled options, clearing, a custom `displaySeparator`, controlled `open`
241
+ state, outside-pointer and Escape closing, and arrow/Home/End keyboard navigation. `open-change` reports panel
242
+ visibility. Shadow parts expose `control`, `trigger`, `label`, `arrow`, `clear`, `panel`, `column`, `option`,
243
+ `option-item`, and `empty` for product-specific styling.
244
+
245
+ ## Date and time pickers
246
+
247
+ Date and time selection remain independently importable, so an application only ships the picker it uses:
248
+
249
+ ```ts
250
+ import { defineDatePickerComponents } from '@haiyue/ui/date-picker';
251
+ import { defineTimePickerComponents } from '@haiyue/ui/time-picker';
252
+
253
+ defineDatePickerComponents();
254
+ defineTimePickerComponents();
255
+ ```
256
+
257
+ `<hy-date-picker>` emits ISO `YYYY-MM-DD` values and provides a locale-aware month calendar, `min` / `max`
258
+ constraints, Monday or Sunday `weekStart`, Today, clearing, outside-pointer and Escape closing, and arrow,
259
+ Home/End, and PageUp/PageDown keyboard navigation.
260
+
261
+ `<hy-time-picker>` emits 24-hour `HH:mm` or `HH:mm:ss` values. Enable `showSeconds`, configure
262
+ `minuteStep` / `secondStep`, and constrain selection with `min` / `max`. Its scrollable hour, minute, and second
263
+ columns support keyboard traversal, Now, explicit confirmation, clearing, and controlled `open` state. Both
264
+ components emit composed `value-change` and `open-change` events and expose their controls through shadow parts.
265
+
266
+ ## Skeleton
267
+
268
+ Import the loading placeholder independently and place the real content in its default slot:
269
+
270
+ ```ts
271
+ import { defineSkeletonComponents } from '@haiyue/ui/skeleton';
272
+
273
+ defineSkeletonComponents();
274
+ ```
275
+
276
+ `<hy-skeleton>` defaults to a title and three paragraph rows. Enable `active` for the shimmer animation, add
277
+ `avatar`, choose `avatarShape`, `avatarSize`, `size`, and `round`, or tune `rows`, `titleWidth`, and the
278
+ `paragraphWidths` property. Set `loading = false` to remove placeholder DOM and reveal the slotted content.
279
+ The host exposes `aria-busy`, honors reduced-motion preferences, inherits both Haiyue themes, and provides
280
+ `placeholder`, `content`, `avatar`, `body`, `title`, `paragraph`, and `row` shadow parts.
281
+
282
+ ## Steps
283
+
284
+ Use `@haiyue/ui/steps` to show task, form, or publishing progress. Assign `items` with a required `title` and
285
+ optional `description`, `subtitle`, `icon`, `status`, and `disabled` state. `current` is zero-based and derives
286
+ `finish`, `process`, and `wait` states automatically unless an item provides an explicit status. Set
287
+ `direction` to `horizontal` or `vertical`, use `size="small"` for compact layouts, and enable `clickable` when
288
+ users may navigate between steps. Click navigation updates `current` and emits the composed `step-change` event.
289
+ The ordered list exposes `aria-current="step"` and shadow parts for every structural and status element.
290
+
291
+ ## Badge
292
+
293
+ Import `@haiyue/ui/badge` to decorate slotted content with a count or notification dot, or to render a standalone
294
+ semantic status. Numeric counts are capped by `overflowCount` (99 by default); use `showZero`, `dot`, `size`,
295
+ `color`, `title`, and the `[x, y]` `offset` property for display control. The `default`, `success`, `processing`,
296
+ `warning`, and `error` statuses accept accompanying `text`, expose status semantics, and honor reduced-motion
297
+ preferences. Structural styling hooks include `wrapper`, `badge`, `badge-content`, `status`, `status-dot`, and
298
+ `status-text` shadow parts.
299
+
300
+ ## Collapse
301
+
302
+ Import `@haiyue/ui/collapse` and assign typed `items` containing `key`, `title`, optional `content`, `extra`,
303
+ `disabled`, and `showArrow` values. `activeKeys` supports multiple open panels, while `accordion` limits the
304
+ group to one. Configure `iconPosition`, `collapsible`, `bordered`, `ghost`, and `destroyOnHidden`; call
305
+ `toggle(key, expanded?)` for imperative control. Each header is a native keyboard-accessible button connected
306
+ to a labelled region, and user changes emit the composed `collapse-change` event with the active keys and
307
+ changed panel. The component exposes structural shadow parts from `collapse` and `panel` through `body`.
308
+
309
+ ## Affix
310
+
311
+ Import `@haiyue/ui/affix` to pin actions, navigation, or status content after it crosses a viewport threshold.
312
+ Use the `offset-top` or `offset-bottom` attributes, or the `topOffset` / `bottomOffset` properties, and assign an
313
+ element to `target` when the scroll container is not the browser window. The component preserves the original
314
+ layout with an internal placeholder, exposes the read-only `affixed` state, and emits the composed
315
+ `affix-change` event. Call `refresh()` after layout changes that do not trigger resize observation.
316
+
317
+ ## Tour
318
+
319
+ Import `@haiyue/ui/tour` for step-by-step product guidance. Assign `steps` with a title, optional description,
320
+ target selector, element, or resolver function, and an optional `top`, `right`, `bottom`, `left`, or `center`
321
+ placement. The component can render a spotlight mask, scroll targets into view, close from Escape or mask
322
+ interaction, and is controlled through `open` and zero-based `current`. Use `start()`, `next()`, `previous()`,
323
+ and `close()` from application code; observe `tour-change`, `tour-close`, `tour-finish`, and `tour-open-change`
324
+ for lifecycle state. Focus returns to the launch control when the tour ends.
325
+
326
+ ## Divider
327
+
328
+ Import `@haiyue/ui/divider` for semantic horizontal or vertical separators. Text can be supplied through the
329
+ default slot or the `label` property. Choose `solid`, `dashed`, `dotted`, or `double` with `lineStyle`, and place
330
+ text at `start`, `center`, or `end` with `textPlacement`. `thickness`, `color`, and `spacing` provide direct
331
+ appearance controls, while the `divider`, `line`, `line-before`, `line-after`, `text`, and `fallback` shadow
332
+ parts support product-specific styling. The internal separator exposes the correct `aria-orientation`.
333
+
334
+ ## Timeline
335
+
336
+ Use `@haiyue/ui/timeline` for ordered activity, history, and process displays. Assign typed `items` containing
337
+ `title`, optional `label` and `description`, semantic `status`, custom `color` or `dot`, and an optional per-item
338
+ `position`. The `left`, `right`, and `alternate` modes control placement; `reverse` flips the order and moves an
339
+ optional `pending` node to the leading edge. `renderItem` and `renderDot` provide DOM customization without
340
+ changing the data contract. The ordered list automatically collapses to a readable single-column layout on
341
+ narrow screens and its pending animation honors reduced-motion preferences.
342
+
343
+ ## Rate
344
+
345
+ Import and register the star rating independently:
346
+
347
+ ```ts
348
+ import { defineRateComponents } from '@haiyue/ui/rate';
349
+
350
+ defineRateComponents();
351
+ ```
352
+
353
+ `<hy-rate>` exposes a controlled numeric `value` and defaults to five stars. Add `allow-half` (or set
354
+ `allowHalf = true`) for 0.5 increments. Configure `count`, `allowClear`, `character`, and `tooltips`, or set
355
+ `disabled` / `readOnly` for non-editable states. The component exposes slider semantics, arrow/Home/End keyboard
356
+ control, `value-change` and `hover-change` composed events, plus `group`, `star`, and `fill` shadow parts.
357
+
358
+ ## Watermark
359
+
360
+ Wrap any content and render a non-interactive repeated text or image mark above it:
361
+
362
+ ```ts
363
+ import { defineWatermarkComponents } from '@haiyue/ui/watermark';
364
+
365
+ defineWatermarkComponents();
366
+ const watermark = document.querySelector('hy-watermark');
367
+ watermark.content = ['HAIYUE', 'INTERNAL'];
368
+ ```
369
+
370
+ Use `content` for one or more text lines, or set `image` to prefer an image mark. Geometry is controlled by
371
+ `rotate`, `gapX`, `gapY`, `offsetX`, `offsetY`, `markWidth`, and `markHeight`; typography and appearance use
372
+ `fontSize`, `fontFamily`, `fontWeight`, `color`, `opacity`, and `zIndex`. The SVG pattern lives inside the
373
+ component shadow root, is hidden from assistive technology, and uses `pointer-events: none`, so links, buttons,
374
+ and other slotted content remain interactive. Shadow parts expose `content`, `overlay`, `mark`, `text`, and
375
+ `image` for targeted styling.
376
+
377
+ ## Table
378
+
379
+ Import the data table from its focused entry. It applies local filters first, then stable sorting, and finally
380
+ pagination, so only the current page is rendered as rows:
381
+
382
+ ```ts
383
+ import { defineTableComponents } from '@haiyue/ui/table';
384
+
385
+ defineTableComponents();
386
+ const table = document.querySelector('hy-table');
387
+ table.columns = [
388
+ { key: 'name', title: 'Name', sortable: true, filterable: true },
389
+ { key: 'role', title: 'Role', filterOptions: roles },
390
+ { key: 'score', title: 'Score', sortable: true, align: 'right' },
391
+ ];
392
+ table.dataSource = records;
393
+ table.pageSize = 20;
394
+ ```
395
+
396
+ Use `page`, `pageSize`, `pageSizeOptions`, and `pagination` for paging; `filters`, `setFilter()`, and
397
+ `clearFilters()` for filtering; and `sort`, `sortBy()`, and `clearSort()` for ordering. Columns may provide a
398
+ custom `filter`, `sorter`, or `render` function. `table-change` reports the complete processed state after a
399
+ user or API change, while `row-click` returns the source record and its original absolute index. The `empty`
400
+ slot, semantic theme tokens, and exported shadow parts support content and visual customization.
401
+
402
+ Filterable columns show a funnel control beside the title. Set `table.showFilters = false` or
403
+ `show-filters="false"` to hide all filter controls while keeping programmatic filtering active. Set
404
+ `showFilter: false` on an individual column to hide only that column's funnel. The filter menu, trigger, panel,
405
+ input, and clear action are exposed through the `filter-menu`, `filter-trigger`, `filter-panel`, `filter`, and
406
+ `filter-clear` shadow parts.
407
+
68
408
  ## Drawer
69
409
 
70
410
  Import and register the drawer independently when a product needs an off-canvas panel:
@@ -139,6 +479,104 @@ Single-value mode uses `value`; interval mode exposes `lowerValue`, `upperValue`
139
479
  `rail`, `track`, `handle`, `handle-lower`, and `handle-upper` shadow parts. `value-input` reports live movement and
140
480
  `value-change` reports a committed pointer or keyboard change.
141
481
 
482
+ ## Virtual keyboard
483
+
484
+ Import the on-screen keyboard independently and bind it to a text input or textarea:
485
+
486
+ ```ts
487
+ import { defineVirtualKeyboardComponents } from '@haiyue/ui/virtual-keyboard';
488
+
489
+ defineVirtualKeyboardComponents();
490
+ const keyboard = document.querySelector('hy-virtual-keyboard');
491
+ keyboard.target = document.querySelector('textarea');
492
+ keyboard.physicalSync = true;
493
+ keyboard.mode = 'numeric'; // switch back with 'qwerty'
494
+ await keyboard.type('Haiyue UI', { interval: 45 });
495
+ ```
496
+
497
+ The default exported `HY_VIRTUAL_KEYBOARD_QWERTY_LAYOUT` includes digits, letters, Shift, Caps Lock, editing,
498
+ all four arrow directions, caret, and navigation keys. Set `mode` to `qwerty` or `numeric`; the numeric mode uses
499
+ the exported `HY_VIRTUAL_KEYBOARD_NUMERIC_LAYOUT` with digits, decimal, minus, deletion, and Enter keys. Assign
500
+ `layout` with rows of typed key descriptors for shortcut or product-specific keyboards. Pointer and native keyboard activation edit the bound target and emit its normal
501
+ `input` event; `physicalSync` mirrors real key state without duplicating native input. `press()`, `release()`,
502
+ `tap()`, `type()`, and `clear()` support guided playback. Observe `virtual-keyboard-down`,
503
+ `virtual-keyboard-up`, and `virtual-keyboard-input`, or style `keyboard`, `row`, `key`, and per-code key parts
504
+ with the `--hy-virtual-keyboard-*` tokens.
505
+
506
+ ## Draggable container
507
+
508
+ Import the transform-based container independently, then use any slotted element as its handle:
509
+
510
+ ```ts
511
+ import { defineDraggableComponents } from '@haiyue/ui/draggable';
512
+
513
+ defineDraggableComponents();
514
+ const panel = document.querySelector('hy-draggable');
515
+ panel.bounds = 'parent';
516
+ panel.axis = 'both';
517
+ panel.grid = 8;
518
+ panel.moveTo(24, 24);
519
+ ```
520
+
521
+ `bounds` accepts `none`, `parent`, `viewport`, or an `HTMLElement`; `axis` accepts `both`, `x`, or `y`.
522
+ Use `handle` to restrict pointer starts to a selector and `cancel` to exclude interactive content. The default
523
+ cancel selector protects inputs, buttons, links, editable content, and `[data-no-drag]`. Arrow keys move by one
524
+ grid step, Shift multiplies that step by ten, and Home resets the position. `moveTo()`, `moveBy()`, `reset()`,
525
+ and `refresh()` provide imperative control. Observe cancelable `drag-start`, followed by `drag-move` and
526
+ `drag-end`; style the exported `surface` part and `--hy-draggable-*` tokens.
527
+
528
+ ## Resizable container
529
+
530
+ Import the eight-handle transform frame independently. Its four corner points and four edge-midpoint handles
531
+ resize the rectangle; dragging the content surface moves it:
532
+
533
+ ```ts
534
+ import { defineResizableComponents } from '@haiyue/ui/resizable';
535
+
536
+ defineResizableComponents();
537
+ const frame = document.querySelector('hy-resizable');
538
+ frame.bounds = 'parent';
539
+ frame.grid = 8;
540
+ frame.aspectRatio = 16 / 9;
541
+ frame.setRect({ x: 48, y: 48, width: 240, height: 135 });
542
+ ```
543
+
544
+ Configure `minWidth`, `minHeight`, `maxWidth`, and `maxHeight`, or use the matching kebab-case attributes.
545
+ `bounds` accepts `none`, `parent`, `viewport`, or an `HTMLElement`; `movable="false"` keeps content stationary
546
+ while preserving resize handles. The focused frame and handles support arrows, Shift acceleration, and Home
547
+ reset. Imperative APIs include `setRect()`, `moveTo()`, `moveBy()`, `resizeTo()`, `reset()`, and `refresh()`.
548
+ Observe cancelable `resize-start`, continuous `resize`, and `resize-end` events. Shadow parts expose `frame`,
549
+ `content`, `handle`, and every directional handle such as `handle-nw`; appearance uses `--hy-resizable-*` tokens.
550
+
551
+ ## Virtual mouse
552
+
553
+ Import the fixed-position cursor visual independently. It never intercepts pointer input or synthesizes clicks on
554
+ page elements; host applications receive composed events and decide how actions map to product behavior:
555
+
556
+ ```ts
557
+ import { defineVirtualMouseComponents } from '@haiyue/ui/virtual-mouse';
558
+
559
+ defineVirtualMouseComponents();
560
+ const mouse = document.querySelector('hy-virtual-mouse');
561
+ mouse.images = {
562
+ idle: '/cursor-idle.png',
563
+ 'left-down': '/cursor-left.png',
564
+ 'right-down': '/cursor-right.png',
565
+ };
566
+ mouse.show();
567
+ await mouse.moveTo(420, 280, { animate: true, duration: 600 });
568
+ await mouse.leftClick();
569
+ await mouse.rightClick();
570
+ ```
571
+
572
+ Use `moveTo()` / `moveBy()` for coordinates, `press()` / `release()` for held-button states, and
573
+ `leftClick()` / `middleClick()` / `rightClick()` for timed click feedback. `animated`, `duration`, and `easing`
574
+ provide host defaults; every move may override them. State images may also be supplied through `idle-image`,
575
+ `left-down-image`, `middle-down-image`, and `right-down-image`. Style the exported `cursor`, `shape`, `image`,
576
+ and `indicator` parts or the `--hy-virtual-mouse-*` CSS variables. Events include `virtual-mouse-move-start`,
577
+ `virtual-mouse-move`, `virtual-mouse-move-end`, `virtual-mouse-down`, `virtual-mouse-up`, and
578
+ `virtual-mouse-click`.
579
+
142
580
  ## Themes
143
581
 
144
582
  Two optional CSS theme entries are provided. Import only the skin a product needs, or import both when the
@@ -163,6 +601,8 @@ All theme tokens use the `--hy-` prefix and may be overridden by consuming produ
163
601
 
164
602
  ## Component examples
165
603
 
604
+ Browse the published gallery at <https://haiyuestudio.github.io/UI/>.
605
+
166
606
  Run the interactive component gallery locally:
167
607
 
168
608
  ```bash
@@ -170,4 +610,67 @@ npm run examples
170
610
  ```
171
611
 
172
612
  Then open <http://localhost:4173/>. The gallery provides a left-side component index and live examples for
173
- every exported component, including editable parameters and event output.
613
+ every exported component, including editable parameters and event output. The gallery shell itself dogfoods
614
+ Haiyue UI: theme actions, component search, command results, status, and example action controls use the
615
+ published Web Components rather than parallel page-only widgets. The navigation/content shell and eligible
616
+ preview/control cards use `hy-split` for keyboard- and pointer-adjustable sizing. Usage blocks are rendered as
617
+ read-only CodeMirror editors with HTML, JavaScript, and CSS syntax highlighting.
618
+
619
+ ## Expandable container
620
+
621
+ Explicit export: `@haiyue/ui/expandable` → `HYExpandable`, `defineExpandableComponents`,
622
+ `HYExpandableButtonPosition`, `HYExpandableChangeDetail`. Also included in `defineHaiyueUI()`.
623
+
624
+ ```html
625
+ <hy-expandable expanded-width="1200px" expanded-height="90dvh"
626
+ button-position="top-right" expand-label="放大" restore-label="还原">
627
+ <div>Your graph, editor, or other stateful content</div>
628
+ <!-- Optional SVG elements: slot="expand-icon" / slot="restore-icon" -->
629
+ </hy-expandable>
630
+ ```
631
+
632
+ `expanded` is a reflected boolean attribute/property; `toggle()` switches it.
633
+ `expandedWidth` / `expandedHeight` accept CSS lengths (defaults `90vw` / `90dvh`).
634
+ Sizes are clamped to the viewport with a margin; the normal size belongs to the host's layout/CSS.
635
+ `buttonPosition` supports `top-right`, `top-left`, `bottom-right`, `bottom-left`.
636
+ `expanded-change` bubbles with `{ expanded: boolean }`. `expand-icon` / `restore-icon` slots
637
+ replace the built-in SVG icons without accepting HTML strings. Labels also become tooltips.
638
+ Style through inherited `--hy-surface-color`, `--hy-border-color`, `--hy-text-color`,
639
+ `--hy-accent-color` and `--hy-expandable-{margin,padding,radius,shadow,button-size,button-offset}`;
640
+ `panel` and `toggle` are CSS parts.
641
+
642
+ Requires a browser supporting the Popover API. Expansion is non-modal and uses a fixed top-layer
643
+ panel so transformed/overflow ancestors cannot clip it. The same slotted DOM stays mounted;
644
+ normal-flow height is preserved while expanded. Keyboard activation uses the native button;
645
+ Escape restores the focused container. Disconnect closes the panel and releases event listeners.
646
+
647
+ ## Independent release checks
648
+
649
+ UI releases independently of Engine.
650
+
651
+ ```bash
652
+ npm ci
653
+ npx playwright install chromium
654
+ npm run release:check
655
+ ```
656
+
657
+ Candidates: `.artifacts/packages/`. Review API changes before `npm run api:update`.
658
+ See [release review](review/release-0.1.2.md).
659
+
660
+ ### 共享组件目录(开发中)
661
+
662
+ `@haiyue/ui/core` 的 `HYComponentProps` 增加五种节点,Web 适配复用对应组件子模块,Native 适配使用原生控件;不新增根导出,也不自动注册全部组件。现有 18 种节点保持兼容,支持范围由 renderer 的 `capabilities.components` 声明。
663
+
664
+ | 节点 | 对应 WebComponent | 当前共享属性 |
665
+ | --- | --- | --- |
666
+ | `Checkbox` | `hy-checkbox` | `text`, `checked`, `disabled`;区别于原生开关 `Toggle` |
667
+ | `RadioGroup` | 一组 `hy-radio` | `value`, `options`, `disabled`;值必须出现在选项中 |
668
+ | `Rate` | `hy-rate` | `value`(0 到 count 的整数), `count`(1–10), `disabled`, `readOnly` |
669
+ | `Badge` | `hy-badge` | 独立文本 `text`,计数截断由应用决定 |
670
+ | `Divider` | `hy-divider` | 水平分隔线,可选 `text` |
671
+
672
+ 交互节点受应用状态控制,通过同一 transaction 的 `valueChange` / `commit` 提议变更;应用拒绝时保留已接受值。评分的半星、悬浮效果,徽标的圆点、动画、悬挂计数,分隔线的垂直/虚线模式尚未纳入共享协议。请勿把 WebComponent 的所有属性直接传入通用节点。
673
+
674
+ Native 仓库的 `examples/ui-validation/mobile` 提供独立「Haiyue UI」组件实验室;折叠内容、步骤导航与按钮组是基础节点组合示例,不是新增协议节点。
675
+
676
+ Web 的 `hy-badge` 新增可选 `literal` 属性(默认为 false):启用后 `count` 按原始文字显示,保留 0、前导零和大数字。普通计数的隐藏零值、截断,以及 status/text 模式保持原行为;共享 Badge 适配显式启用此模式。
@@ -0,0 +1,19 @@
1
+ import type { HYNode } from '../../core/types.js';
2
+ import type { HYWebControl, HYWebControlContext } from './types.js';
3
+ /** Registration is explicit and limited to the reused components. */
4
+ export declare function definePortableWebComponents(): void;
5
+ export declare const componentTags: Readonly<{
6
+ Checkbox: "hy-checkbox";
7
+ RadioGroup: "div";
8
+ Rate: "hy-rate";
9
+ Badge: "hy-badge";
10
+ Divider: "hy-divider";
11
+ Button: "hy-button";
12
+ Toggle: "hy-checkbox";
13
+ Select: "hy-select";
14
+ Tabs: "hy-tabs";
15
+ TextInput: "hy-input";
16
+ Slider: "hy-range";
17
+ Dialog: "hy-dialog";
18
+ }>;
19
+ export declare function createControl(node: HYNode, context: HYWebControlContext, revision: number): HYWebControl | undefined;