@greypan/web-ui 2.1.8 → 3.0.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 (148) hide show
  1. package/README.CN.md +47 -7
  2. package/README.md +54 -13
  3. package/dist/assets/menu-portal.js +1 -1
  4. package/dist/assets/menu-portal.js.map +1 -1
  5. package/dist/components/autocomplete/index.d.ts +121 -0
  6. package/dist/components/autocomplete/index.js +414 -0
  7. package/dist/components/autocomplete/index.js.map +1 -0
  8. package/dist/components/autocomplete/style.js +6 -0
  9. package/dist/components/autocomplete/style.js.map +1 -0
  10. package/dist/components/avatar/index.d.ts +0 -1
  11. package/dist/components/avatar/index.js +9 -9
  12. package/dist/components/avatar/index.js.map +1 -1
  13. package/dist/components/back-top/index.d.ts +0 -1
  14. package/dist/components/back-top/index.js.map +1 -1
  15. package/dist/components/badge/index.d.ts +0 -1
  16. package/dist/components/badge/index.js +5 -5
  17. package/dist/components/badge/index.js.map +1 -1
  18. package/dist/components/button/index.d.ts +0 -1
  19. package/dist/components/button/index.js +8 -8
  20. package/dist/components/button/index.js.map +1 -1
  21. package/dist/components/button/style.js +1 -1
  22. package/dist/components/button/style.js.map +1 -1
  23. package/dist/components/button-group/index.d.ts +0 -1
  24. package/dist/components/button-group/index.js.map +1 -1
  25. package/dist/components/checkbox/index.js +7 -5
  26. package/dist/components/checkbox/index.js.map +1 -1
  27. package/dist/components/checkbox-group/index.js +2 -2
  28. package/dist/components/checkbox-group/index.js.map +1 -1
  29. package/dist/components/context-menu/index.js +25 -25
  30. package/dist/components/context-menu/index.js.map +1 -1
  31. package/dist/components/dialog/index.d.ts +1 -0
  32. package/dist/components/dialog/index.js +9 -5
  33. package/dist/components/dialog/index.js.map +1 -1
  34. package/dist/components/drawer/index.js +7 -7
  35. package/dist/components/drawer/index.js.map +1 -1
  36. package/dist/components/dropdown/index.js +31 -30
  37. package/dist/components/dropdown/index.js.map +1 -1
  38. package/dist/components/dropdown-divider/index.d.ts +0 -1
  39. package/dist/components/dropdown-divider/index.js.map +1 -1
  40. package/dist/components/dropdown-header/index.d.ts +0 -1
  41. package/dist/components/dropdown-header/index.js.map +1 -1
  42. package/dist/components/dropdown-item/index.d.ts +0 -1
  43. package/dist/components/dropdown-item/index.js.map +1 -1
  44. package/dist/components/dropdown-item/style.js +1 -1
  45. package/dist/components/dropdown-item/style.js.map +1 -1
  46. package/dist/components/empty/index.d.ts +0 -1
  47. package/dist/components/empty/index.js +6 -6
  48. package/dist/components/empty/index.js.map +1 -1
  49. package/dist/components/icon/index.d.ts +0 -1
  50. package/dist/components/icon/index.js.map +1 -1
  51. package/dist/components/index.d.ts +5 -0
  52. package/dist/components/index.js +36 -35
  53. package/dist/components/input/index.d.ts +2 -0
  54. package/dist/components/input/index.js +24 -13
  55. package/dist/components/input/index.js.map +1 -1
  56. package/dist/components/input/style.js +1 -1
  57. package/dist/components/input/style.js.map +1 -1
  58. package/dist/components/input-number/index.d.ts +2 -0
  59. package/dist/components/input-number/index.js +25 -12
  60. package/dist/components/input-number/index.js.map +1 -1
  61. package/dist/components/input-number/style.js +1 -1
  62. package/dist/components/input-number/style.js.map +1 -1
  63. package/dist/components/layout/index.d.ts +0 -1
  64. package/dist/components/layout/index.js +4 -4
  65. package/dist/components/layout/index.js.map +1 -1
  66. package/dist/components/option/index.d.ts +0 -11
  67. package/dist/components/option/index.js.map +1 -1
  68. package/dist/components/option/style.js +1 -1
  69. package/dist/components/option/style.js.map +1 -1
  70. package/dist/components/popover/index.js +12 -12
  71. package/dist/components/popover/index.js.map +1 -1
  72. package/dist/components/radio/index.js +8 -5
  73. package/dist/components/radio/index.js.map +1 -1
  74. package/dist/components/radio-group/index.js +2 -2
  75. package/dist/components/radio-group/index.js.map +1 -1
  76. package/dist/components/segmented/index.js +2 -2
  77. package/dist/components/segmented/index.js.map +1 -1
  78. package/dist/components/segmented-trigger/index.d.ts +1 -0
  79. package/dist/components/segmented-trigger/index.js +11 -2
  80. package/dist/components/segmented-trigger/index.js.map +1 -1
  81. package/dist/components/select/index.d.ts +0 -1
  82. package/dist/components/select/index.js +19 -30
  83. package/dist/components/select/index.js.map +1 -1
  84. package/dist/components/select/style.js +1 -1
  85. package/dist/components/select/style.js.map +1 -1
  86. package/dist/components/spinner/index.d.ts +0 -1
  87. package/dist/components/spinner/index.js.map +1 -1
  88. package/dist/components/svg-draw-lines/index.d.ts +0 -1
  89. package/dist/components/svg-draw-lines/index.js.map +1 -1
  90. package/dist/components/switch/index.js +6 -6
  91. package/dist/components/textarea/index.js +18 -15
  92. package/dist/components/textarea/index.js.map +1 -1
  93. package/dist/components/textarea/style.js +1 -1
  94. package/dist/components/textarea/style.js.map +1 -1
  95. package/dist/components/theme/index.d.ts +0 -1
  96. package/dist/components/theme/index.js.map +1 -1
  97. package/dist/components/toast/toast.js +13 -13
  98. package/dist/components/tooltip/index.js +13 -13
  99. package/dist/components/tooltip/index.js.map +1 -1
  100. package/dist/icons/generated/lucide-external-link.d.ts +6 -0
  101. package/dist/icons/generated/lucide-external-link.js +10 -0
  102. package/dist/icons/generated/lucide-external-link.js.map +1 -0
  103. package/dist/icons/generated/lucide-file-text.d.ts +6 -0
  104. package/dist/icons/generated/lucide-file-text.js +10 -0
  105. package/dist/icons/generated/lucide-file-text.js.map +1 -0
  106. package/dist/icons/generated/lucide-film.d.ts +6 -0
  107. package/dist/icons/generated/lucide-film.js +10 -0
  108. package/dist/icons/generated/lucide-film.js.map +1 -0
  109. package/dist/icons/generated/lucide-folder-open.d.ts +6 -0
  110. package/dist/icons/generated/lucide-folder-open.js +10 -0
  111. package/dist/icons/generated/lucide-folder-open.js.map +1 -0
  112. package/dist/icons/generated/lucide-layout-grid.d.ts +6 -0
  113. package/dist/icons/generated/lucide-layout-grid.js +10 -0
  114. package/dist/icons/generated/lucide-layout-grid.js.map +1 -0
  115. package/dist/icons/generated/lucide-music.d.ts +6 -0
  116. package/dist/icons/generated/lucide-music.js +10 -0
  117. package/dist/icons/generated/lucide-music.js.map +1 -0
  118. package/dist/icons/generated/lucide-package.d.ts +6 -0
  119. package/dist/icons/generated/lucide-package.js +10 -0
  120. package/dist/icons/generated/lucide-package.js.map +1 -0
  121. package/dist/icons/generated/lucide-pencil.d.ts +6 -0
  122. package/dist/icons/generated/lucide-pencil.js +10 -0
  123. package/dist/icons/generated/lucide-pencil.js.map +1 -0
  124. package/dist/icons/generated/lucide-refresh-cw.d.ts +6 -0
  125. package/dist/icons/generated/lucide-refresh-cw.js +10 -0
  126. package/dist/icons/generated/lucide-refresh-cw.js.map +1 -0
  127. package/dist/icons/generated/lucide-tags.d.ts +6 -0
  128. package/dist/icons/generated/lucide-tags.js +10 -0
  129. package/dist/icons/generated/lucide-tags.js.map +1 -0
  130. package/dist/icons/generated/lucide-wrench.d.ts +6 -0
  131. package/dist/icons/generated/lucide-wrench.js +10 -0
  132. package/dist/icons/generated/lucide-wrench.js.map +1 -0
  133. package/dist/icons/index.d.ts +11 -0
  134. package/dist/icons/index.js +12 -1
  135. package/dist/shared/menu-portal/menu-portal.js +10 -11
  136. package/dist/shared/menu-portal/menu-portal.js.map +1 -1
  137. package/dist/shared/overlay/anchored-panel.js +12 -12
  138. package/dist/shared/overlay/overlay.js +55 -33
  139. package/dist/shared/overlay/overlay.js.map +1 -1
  140. package/dist/shared/overlay/portal.js +25 -13
  141. package/dist/shared/overlay/portal.js.map +1 -1
  142. package/dist/shared/scroll-lock/scroll-lock.js +13 -12
  143. package/dist/shared/scroll-lock/scroll-lock.js.map +1 -1
  144. package/dist/shared/theme/overlay-root.js +3 -3
  145. package/dist/types/react.d.ts +15 -41
  146. package/dist/types/utils.d.ts +38 -4
  147. package/dist/types/vue.d.ts +17 -49
  148. package/package.json +6 -6
package/README.CN.md CHANGED
@@ -33,7 +33,7 @@ import '@greypan/web-ui'
33
33
 
34
34
  ### React
35
35
 
36
- 需要 `@types/react >= 16` 作为可选 peer 依赖。
36
+ 需要 `@types/react >= 19` 作为可选 peer 依赖。
37
37
 
38
38
  ```ts
39
39
  // vite.config.ts
@@ -56,7 +56,7 @@ function App() {
56
56
  <web-ui-button variant="primary" onClick={() => alert('点击')}>
57
57
  按钮
58
58
  </web-ui-button>
59
- <web-ui-input onInput={e => console.log((e.target as any).value)} />
59
+ <web-ui-input onInput={e => console.log(e.currentTarget.value)} />
60
60
  </>
61
61
  )
62
62
  }
@@ -65,8 +65,11 @@ function App() {
65
65
  #### React 自定义元素事件与布尔属性
66
66
 
67
67
  React 19 按 JSX 键名中的 `on` 后缀原样注册 Custom Element 事件。事件名大小写敏感:`open-change`
68
- 必须绑定为 `onopen-change`,不能写成 `onOpenChange`。标准 `input` 和 `change` 事件仍使用 React
69
- 惯用的 `onInput` 和 `onChange`。布尔属性遵循原生 HTML 语义:属性缺失为 `false`,属性存在为 `true`。
68
+ 必须绑定为 `onopen-change`,不能写成 `onOpenChange`。标准 `input`、`change`、`focus`、`blur`
69
+ 事件使用 React 惯用的 `onInput`、`onChange`、`onFocus`、`onBlur` handler——其 `currentTarget`
70
+ 类型为组件实例,value/checked 读取无需 cast;`target` 遵循 React SyntheticEvent 语义(`EventTarget`),
71
+ 不承诺为组件实例。kebab-case 自定义事件携带精确类型的 `CustomEvent` detail。
72
+ 布尔属性遵循原生 HTML 语义:属性缺失为 `false`,属性存在为 `true`。
70
73
 
71
74
  ```tsx
72
75
  <web-ui-dialog
@@ -96,7 +99,7 @@ useEffect(() => {
96
99
 
97
100
  ### Vue
98
101
 
99
- 需要 `vue >= 3` 作为可选 peer 依赖。
102
+ 需要 `vue >= 3.5` 作为可选 peer 依赖。
100
103
 
101
104
  ```ts
102
105
  // vite.config.ts
@@ -120,9 +123,16 @@ import '@greypan/web-ui/types/vue'
120
123
  <template>
121
124
  <web-ui-button variant="primary" @click="handleClick">按钮</web-ui-button>
122
125
  <web-ui-input v-model="value" />
126
+ <web-ui-select :value="framework" @change="framework = $event.target.value" />
123
127
  </template>
124
128
  ```
125
129
 
130
+ Vue 事件类型零 cast:带值组件上的 `@input`/`@change` 解析到组件 emit,`$event.target` 即为组件实例,
131
+ `value`/`checked` 直接读取;kebab-case 事件(如 `open-change`)的 `$event.detail` 保持 `CustomEvent` 载荷类型。
132
+ 命名 handler 用 `WebUiEvent<WebUiXxx, 'change'>` 标注;当变量或泛型表示事件名时,使用
133
+ `WebUiEventName<WebUiXxx>`,它只接受该组件 `$events` 的 string key。未声明为 emit 的原生事件
134
+ (`@click`/`@focus` 等)在任何 `web-ui-*` 元素上仍可绑定。
135
+
126
136
  ### 属性与事件边界
127
137
 
128
138
  `web-ui-*` 元素是公开 DOM 边界。`id`、`class`、`style`、全局 HTML 属性和 `data-*` 保留在 Custom Element 宿主上,
@@ -141,6 +151,7 @@ ARIA 属性同样必须显式支持:使用组件文档化的命名属性,而
141
151
  | | [`<web-ui-textarea>`](#web-ui-textarea) |
142
152
  | | [`<web-ui-input-number>`](#web-ui-input-number) |
143
153
  | | [`<web-ui-select>`](#web-ui-select) |
154
+ | | [`<web-ui-autocomplete>`](#web-ui-autocomplete) |
144
155
  | | [`<web-ui-slider>`](#web-ui-slider) |
145
156
  | | [`<web-ui-checkbox>`](#web-ui-checkbox) |
146
157
  | | [`<web-ui-radio>`](#web-ui-radio) |
@@ -189,6 +200,7 @@ ARIA 属性同样必须显式支持:使用组件文档化的命名属性,而
189
200
  | `placeholder` | `string` | `''` | 占位文本 |
190
201
  | `name` | `string` | `''` | 表单字段名 |
191
202
  | `disabled` | `boolean` | `false` | 禁用状态 |
203
+ | `readonly` | `boolean` | `false` | 只读状态 |
192
204
  | `required` | `boolean` | `false` | 必填校验 |
193
205
  | `clearable` | `boolean` | `false` | 显示清除按钮 |
194
206
  | `full` | `boolean` | `false` | 全宽 |
@@ -242,11 +254,12 @@ ARIA 属性同样必须显式支持:使用组件文档化的命名属性,而
242
254
  | `placeholder` | `string` | `''` | 占位文本 |
243
255
  | `name` | `string` | `''` | 表单字段名 |
244
256
  | `disabled` | `boolean` | `false` | 禁用状态 |
257
+ | `readonly` | `boolean` | `false` | 只读状态 |
245
258
  | `required` | `boolean` | `false` | 必填校验 |
246
259
 
247
260
  **事件:** `input`, `change`
248
261
 
249
- ArrowUp/ArrowDown 键增减数值。
262
+ ArrowUp/ArrowDown 键增减数值。空输入或 `-` 在提交时被忽略,值保持在最后一个有效数字。
250
263
 
251
264
  #### `<web-ui-select>`
252
265
 
@@ -269,6 +282,32 @@ ArrowUp/ArrowDown 键增减数值。
269
282
 
270
283
  子 `<web-ui-option>` 通过 `option-register` / `option-unregister` 注册。支持 ArrowDown/ArrowUp/Enter/Escape 键盘导航。
271
284
 
285
+ #### `<web-ui-autocomplete>`
286
+
287
+ 可输入并过滤候选的单值选择器。
288
+
289
+ | 属性 | 类型 | 默认值 | 说明 |
290
+ | ------------------ | ---------------------------------- | ------------ | ------------------------------------------------------- |
291
+ | `value` | `string` | `''` | 当前输入文本(表单值) |
292
+ | `selected-value` | `string` | `''` | 输入文本精确匹配 label 的 option 的 value(派生,只读) |
293
+ | `placeholder` | `string` | `''` | 占位文本 |
294
+ | `filter` | `'none' \| 'prefix' \| 'contains'` | `'contains'` | 候选过滤模式(按 option label 匹配) |
295
+ | `name` | `string` | `''` | 表单字段名 |
296
+ | `disabled` | `boolean` | `false` | 禁用状态 |
297
+ | `readonly` | `boolean` | `false` | 只读状态(不可输入、不可展开下拉) |
298
+ | `required` | `boolean` | `false` | 必填校验 |
299
+ | `portal` | `boolean` | `false` | 在主题浮层容器中渲染 |
300
+ | `no-scroll-lock` | `boolean` | `false` | 打开时不锁定页面滚动 |
301
+ | `overlayContainer` | `HTMLElement \| () => HTMLElement` | — | 显式 Portal 容器 |
302
+ | `aria-label` | `string` | — | 无障碍名称 |
303
+ | `aria-labelledby` | `string` | — | 无障碍名称引用 |
304
+
305
+ **事件:** `input`, `change`, `focus`, `blur`, `open-change` (`CustomEvent<{ open: boolean }>`)
306
+
307
+ **插槽:** `default`(投影 `<web-ui-option>` 元素)
308
+
309
+ 键入时按 label 过滤候选(`contains` 或 `prefix`,`none` 关闭过滤)。选择 option 时文本回填为该项 label,`selected-value` 暴露该项的 value;`change` 在选择提交时触发。支持 ArrowDown/ArrowUp/Enter/Escape 键盘导航。
310
+
272
311
  #### `<web-ui-slider>`
273
312
 
274
313
  范围滑块,支持刻度标记和垂直方向。
@@ -447,6 +486,7 @@ ArrowUp/ArrowDown 键增减数值。
447
486
  | `open` | `boolean` | `false` | 对话框可见性 |
448
487
  | `no-scroll-lock` | `boolean` | `false` | 打开时不锁定页面滚动 |
449
488
  | `no-backdrop-close` | `boolean` | `false` | 禁止点击遮罩关闭 |
489
+ | `no-escape-close` | `boolean` | `false` | 禁止按 Escape 关闭 |
450
490
 
451
491
  **事件:** `open-change` (`CustomEvent<{ open: boolean }>`)
452
492
 
@@ -454,7 +494,7 @@ ArrowUp/ArrowDown 键增减数值。
454
494
 
455
495
  **方法:** `showModal()`, `close()`
456
496
 
457
- 使用原生 `<dialog>`,`@cancel` 阻止默认关闭行为(Escape 调用 `close()`)。点击遮罩关闭。
497
+ 使用原生 `<dialog>`,`@cancel` 阻止默认关闭行为。除非存在 `no-escape-close`,否则 Escape 调用 `close()`;除非存在 `no-backdrop-close`,否则点击遮罩关闭。
458
498
 
459
499
  #### `<web-ui-drawer>`
460
500
 
package/README.md CHANGED
@@ -33,7 +33,7 @@ import '@greypan/web-ui'
33
33
 
34
34
  ### React
35
35
 
36
- Requires `@types/react >= 16` as optional peer dependency.
36
+ Requires `@types/react >= 19` as optional peer dependency.
37
37
 
38
38
  ```ts
39
39
  // vite.config.ts
@@ -56,7 +56,7 @@ function App() {
56
56
  <web-ui-button variant="primary" onClick={() => alert('clicked')}>
57
57
  Click
58
58
  </web-ui-button>
59
- <web-ui-input onInput={e => console.log((e.target as any).value)} />
59
+ <web-ui-input onInput={e => console.log(e.currentTarget.value)} />
60
60
  </>
61
61
  )
62
62
  }
@@ -65,9 +65,12 @@ function App() {
65
65
  #### React custom-element events and boolean properties
66
66
 
67
67
  React 19 registers Custom Element events using the suffix of the JSX `on` key unchanged. Event names are
68
- case-sensitive: bind `open-change` as `onopen-change`, not `onOpenChange`. Standard `input` and `change`
69
- events continue to use React's conventional `onInput` and `onChange`. Boolean properties follow native HTML
70
- semantics: absence is `false` and presence is `true`.
68
+ case-sensitive: bind `open-change` as `onopen-change`, not `onOpenChange`. Standard `input`, `change`, `focus`,
69
+ and `blur` events use React's conventional `onInput`, `onChange`, `onFocus`, and `onBlur` handlers — their
70
+ `currentTarget` is typed as the component instance, so `value` and `checked` are read cast-free. The `target`
71
+ follows React SyntheticEvent semantics (`EventTarget`) and is not narrowed. Kebab-case custom events carry their
72
+ `CustomEvent` detail typed. Boolean properties follow native HTML semantics: absence is `false` and presence is
73
+ `true`.
71
74
 
72
75
  ```tsx
73
76
  <web-ui-dialog
@@ -98,7 +101,7 @@ useEffect(() => {
98
101
 
99
102
  ### Vue
100
103
 
101
- Requires `vue >= 3` as optional peer dependency.
104
+ Requires `vue >= 3.5` as optional peer dependency.
102
105
 
103
106
  ```ts
104
107
  // vite.config.ts
@@ -122,9 +125,17 @@ import '@greypan/web-ui/types/vue'
122
125
  <template>
123
126
  <web-ui-button variant="primary" @click="handleClick">Click</web-ui-button>
124
127
  <web-ui-input v-model="value" />
128
+ <web-ui-select :value="framework" @change="framework = $event.target.value" />
125
129
  </template>
126
130
  ```
127
131
 
132
+ Vue events are typed cast-free: `@input`/`@change` on value-bearing components resolve to the component emit, so
133
+ `$event.target` is the component instance and `value`/`checked` are read directly. `$event.detail` keeps the
134
+ `CustomEvent` payload type for kebab-case events like `open-change`. Named handlers annotate with
135
+ `WebUiEvent<WebUiXxx, 'change'>`; use `WebUiEventName<WebUiXxx>` when a value or generic represents an
136
+ event name, because it accepts only the component's string `$events` keys. `@click`/`@focus` and other native
137
+ events not declared as emits remain bindable on any `web-ui-*` element.
138
+
128
139
  ### Attribute and event boundaries
129
140
 
130
141
  `web-ui-*` elements are the public DOM boundary. `id`, `class`, `style`, global HTML attributes, and `data-*` stay on
@@ -145,6 +156,7 @@ state changes; assigning a property programmatically does not emit them.
145
156
  | | [`<web-ui-textarea>`](#web-ui-textarea) |
146
157
  | | [`<web-ui-input-number>`](#web-ui-input-number) |
147
158
  | | [`<web-ui-select>`](#web-ui-select) |
159
+ | | [`<web-ui-autocomplete>`](#web-ui-autocomplete) |
148
160
  | | [`<web-ui-slider>`](#web-ui-slider) |
149
161
  | | [`<web-ui-checkbox>`](#web-ui-checkbox) |
150
162
  | | [`<web-ui-radio>`](#web-ui-radio) |
@@ -193,6 +205,7 @@ Text input with clearable, prefix/suffix slots.
193
205
  | `placeholder` | `string` | `''` | Placeholder text |
194
206
  | `name` | `string` | `''` | Form field name |
195
207
  | `disabled` | `boolean` | `false` | Disabled state |
208
+ | `readonly` | `boolean` | `false` | Read-only state |
196
209
  | `required` | `boolean` | `false` | Required validation |
197
210
  | `clearable` | `boolean` | `false` | Show clear button |
198
211
  | `full` | `boolean` | `false` | Full width |
@@ -246,11 +259,12 @@ Numeric input with step buttons and keyboard control.
246
259
  | `placeholder` | `string` | `''` | Placeholder text |
247
260
  | `name` | `string` | `''` | Form field name |
248
261
  | `disabled` | `boolean` | `false` | Disabled state |
262
+ | `readonly` | `boolean` | `false` | Read-only state |
249
263
  | `required` | `boolean` | `false` | Required validation |
250
264
 
251
265
  **Events:** `input`, `change`
252
266
 
253
- ArrowUp/ArrowDown keyboard increments and decrements the value.
267
+ ArrowUp/ArrowDown keyboard increments and decrements the value. Empty or `-` input is ignored on commit; the value stays at the last valid number.
254
268
 
255
269
  #### `<web-ui-select>`
256
270
 
@@ -275,6 +289,32 @@ Select dropdown with option items, keyboard navigation, and portal support.
275
289
 
276
290
  Child `<web-ui-option>` elements register via `option-register` / `option-unregister` events. Supports ArrowDown/ArrowUp/Enter/Escape keyboard navigation.
277
291
 
292
+ #### `<web-ui-autocomplete>`
293
+
294
+ Editable combobox with input filtering and single option selection.
295
+
296
+ | Attribute | Type | Default | Description |
297
+ | ------------------ | ---------------------------------- | ------------ | ------------------------------------------------------------------------- |
298
+ | `value` | `string` | `''` | Current input text (form value) |
299
+ | `selected-value` | `string` | `''` | Value of the option exactly matching the input label (derived, read-only) |
300
+ | `placeholder` | `string` | `''` | Placeholder text |
301
+ | `filter` | `'none' \| 'prefix' \| 'contains'` | `'contains'` | Candidate filtering mode (matched against option label) |
302
+ | `name` | `string` | `''` | Form field name |
303
+ | `disabled` | `boolean` | `false` | Disabled state |
304
+ | `readonly` | `boolean` | `false` | Read-only state (no typing, no dropdown) |
305
+ | `required` | `boolean` | `false` | Required validation |
306
+ | `portal` | `boolean` | `false` | Render dropdown in theme overlay |
307
+ | `no-scroll-lock` | `boolean` | `false` | Do not lock body scroll when open |
308
+ | `overlayContainer` | `HTMLElement \| () => HTMLElement` | — | Explicit portal container |
309
+ | `aria-label` | `string` | — | Accessible name |
310
+ | `aria-labelledby` | `string` | — | Accessible name references |
311
+
312
+ **Events:** `input`, `change`, `focus`, `blur`, `open-change` (`CustomEvent<{ open: boolean }>`)
313
+
314
+ **Slots:** `default` (project `<web-ui-option>` elements)
315
+
316
+ Typing filters the option list by label (`contains` or `prefix`, or `none` to disable filtering). Selecting an option fills the input with its label and exposes the option's value via `selected-value`; `change` fires on selection commit. Supports ArrowDown/ArrowUp/Enter/Escape keyboard navigation.
317
+
278
318
  #### `<web-ui-slider>`
279
319
 
280
320
  Range slider with marks and vertical orientation.
@@ -451,11 +491,12 @@ Propagates `direction` attribute to child buttons.
451
491
 
452
492
  Modal dialog using native `<dialog>` with `showModal()`.
453
493
 
454
- | Attribute | Type | Default | Description |
455
- | ------------------- | --------- | ------- | --------------------------------- |
456
- | `open` | `boolean` | `false` | Dialog visibility |
457
- | `no-scroll-lock` | `boolean` | `false` | Do not lock body scroll when open |
458
- | `no-backdrop-close` | `boolean` | `false` | Do not close on backdrop click |
494
+ | Attribute | Type | Default | Description |
495
+ | ------------------- | --------- | ------- | ----------------------------------- |
496
+ | `open` | `boolean` | `false` | Dialog visibility |
497
+ | `no-scroll-lock` | `boolean` | `false` | Do not lock body scroll when open |
498
+ | `no-backdrop-close` | `boolean` | `false` | Do not close on backdrop click |
499
+ | `no-escape-close` | `boolean` | `false` | Do not close when Escape is pressed |
459
500
 
460
501
  **Events:** `open-change` (`CustomEvent<{ open: boolean }>`)
461
502
 
@@ -463,7 +504,7 @@ Modal dialog using native `<dialog>` with `showModal()`.
463
504
 
464
505
  **Methods:** `showModal()`, `close()`
465
506
 
466
- Uses native `<dialog>` with `@cancel` prevention (Escape calls `close()`). Click on backdrop closes dialog.
507
+ Uses native `<dialog>` with `@cancel` prevention. Escape calls `close()` unless `no-escape-close` is present. Click on backdrop closes dialog unless `no-backdrop-close` is present.
467
508
 
468
509
  #### `<web-ui-drawer>`
469
510
 
@@ -1,5 +1,5 @@
1
1
  //#region src/assets/menu-portal.css?inline
2
- var e = ".wui-menu-portal-overlay{--wui-glass-shadow:var(--wui-shadow-pop,0 3px 9px #00000045);--wui-duration-overlay-enter:var(--wui-duration-menu-enter,.14s);--wui-duration-overlay-exit:var(--wui-duration-menu-exit,.1s);-webkit-user-select:none;user-select:none;z-index:var(--wui-layer-menu,100);box-sizing:border-box;min-width:200px;max-width:90vw;max-height:80vh;color:var(--wui-color-text,#1b1b1b);background-color:var(--wui-color-surface-overlay,#f6f6f6e0);border-radius:20px;position:fixed;overflow:hidden}.wui-menu-portal-overlay .wui-menu-scroll{max-height:80vh;overflow-y:auto}.wui-menu-portal-overlay .wui-menu-content{padding:4px}.wui-menu-portal-overlay.dropdown-overlay .wui-menu-scroll{max-height:320px}.wui-menu-portal-overlay.dropdown-overlay[data-level]:not([data-level=\"0\"]),.wui-menu-portal-overlay.context-submenu{z-index:var(--wui-layer-menu-submenu,110)}";
2
+ var e = ".wui-menu-portal-overlay{--wui-glass-shadow:var(--wui-shadow-pop,0 3px 9px #00000045);--wui-duration-overlay-enter:var(--wui-duration-menu-enter,.14s);--wui-duration-overlay-exit:var(--wui-duration-menu-exit,.1s);--wui-overlay-min-width:200px;-webkit-user-select:none;user-select:none;z-index:var(--wui-layer-menu,100);box-sizing:border-box;min-width:var(--wui-overlay-min-width,120px);max-width:90vw;max-height:80vh;color:var(--wui-color-text,#1b1b1b);background-color:var(--wui-color-surface-overlay,#f6f6f6e0);border-radius:20px;position:fixed;overflow:hidden}.wui-menu-portal-overlay .wui-menu-scroll{max-height:80vh;overflow-y:auto}.wui-menu-portal-overlay .wui-menu-content{padding:4px}.wui-menu-portal-overlay.dropdown-overlay .wui-menu-scroll{max-height:320px}.wui-menu-portal-overlay.dropdown-overlay[data-level]:not([data-level=\"0\"]),.wui-menu-portal-overlay.context-submenu{z-index:var(--wui-layer-menu-submenu,110)}";
3
3
  //#endregion
4
4
  export { e as default };
5
5
 
@@ -1 +1 @@
1
- {"version":3,"file":"menu-portal.js","names":[],"sources":["../../src/assets/menu-portal.css?inline"],"sourcesContent":[".wui-menu-portal-overlay {\n --wui-glass-shadow: var(--wui-shadow-pop, 0 3px 9px rgb(0 0 0 / 0.27));\n --wui-duration-overlay-enter: var(--wui-duration-menu-enter, 140ms);\n --wui-duration-overlay-exit: var(--wui-duration-menu-exit, 100ms);\n user-select: none;\n\n position: fixed;\n z-index: var(--wui-layer-menu, 100);\n\n overflow: hidden;\n\n box-sizing: border-box;\n min-width: 200px;\n max-width: 90vw;\n max-height: 80vh;\n border-radius: 20px;\n\n color: var(--wui-color-text, #1b1b1b);\n\n background-color: var(--wui-color-surface-overlay, rgb(246 246 246 / 0.88));\n\n & .wui-menu-scroll {\n overflow-y: auto;\n max-height: 80vh;\n }\n\n & .wui-menu-content {\n padding: 4px;\n }\n\n &.dropdown-overlay {\n & .wui-menu-scroll {\n max-height: 320px;\n }\n\n &[data-level]:not([data-level='0']) {\n z-index: var(--wui-layer-menu-submenu, 110);\n }\n }\n\n &.context-submenu {\n z-index: var(--wui-layer-menu-submenu, 110);\n }\n}\n"],"mappings":""}
1
+ {"version":3,"file":"menu-portal.js","names":[],"sources":["../../src/assets/menu-portal.css?inline"],"sourcesContent":[".wui-menu-portal-overlay {\n --wui-glass-shadow: var(--wui-shadow-pop, 0 3px 9px rgb(0 0 0 / 0.27));\n --wui-duration-overlay-enter: var(--wui-duration-menu-enter, 140ms);\n --wui-duration-overlay-exit: var(--wui-duration-menu-exit, 100ms);\n --wui-overlay-min-width: 200px;\n user-select: none;\n\n position: fixed;\n z-index: var(--wui-layer-menu, 100);\n\n overflow: hidden;\n\n box-sizing: border-box;\n min-width: var(--wui-overlay-min-width, 120px);\n max-width: 90vw;\n max-height: 80vh;\n border-radius: 20px;\n\n color: var(--wui-color-text, #1b1b1b);\n\n background-color: var(--wui-color-surface-overlay, rgb(246 246 246 / 0.88));\n\n & .wui-menu-scroll {\n overflow-y: auto;\n max-height: 80vh;\n }\n\n & .wui-menu-content {\n padding: 4px;\n }\n\n &.dropdown-overlay {\n & .wui-menu-scroll {\n max-height: 320px;\n }\n\n &[data-level]:not([data-level='0']) {\n z-index: var(--wui-layer-menu-submenu, 110);\n }\n }\n\n &.context-submenu {\n z-index: var(--wui-layer-menu-submenu, 110);\n }\n}\n"],"mappings":""}
@@ -0,0 +1,121 @@
1
+ import { LitElement, PropertyValues } from 'lit';
2
+ import { OverlayContainer } from '../../shared/overlay/portal';
3
+ declare const FILTER_MODES: readonly ["none", "prefix", "contains"];
4
+ type FilterMode = (typeof FILTER_MODES)[number];
5
+ /**
6
+ * `web-ui-autocomplete`:可输入并过滤候选的单值选择器。
7
+ *
8
+ * 与 `web-ui-select` 共用 `<web-ui-option>` 子项注册协议与浮层能力,但触发区是
9
+ * 可编辑输入框:`value` 即当前输入文本(表单值),键入时按 `filter` 模式过滤候选,
10
+ * 选择 option 时文本回填为该项 label,`selected-value` 暴露该项的 value。
11
+ */
12
+ export declare class WebUiAutocomplete extends LitElement {
13
+ static styles: import('lit').CSSResult[];
14
+ static formAssociated: boolean;
15
+ private _internals?;
16
+ private _formDisabled;
17
+ placeholder: string;
18
+ disabled: boolean;
19
+ readonly: boolean;
20
+ required: boolean;
21
+ portal: boolean;
22
+ noScrollLock: boolean;
23
+ overlayContainer?: OverlayContainer;
24
+ name: string;
25
+ ariaLabel: string | null;
26
+ ariaLabelledby: string | undefined;
27
+ private _filter;
28
+ get filter(): FilterMode;
29
+ set filter(v: string);
30
+ private _value;
31
+ get value(): string;
32
+ set value(v: string);
33
+ private _selectedValue;
34
+ get selectedValue(): string;
35
+ private _setSelectedValue;
36
+ private get _isDisabled();
37
+ private _isOpen;
38
+ private _activeIndex;
39
+ private _focused;
40
+ private static _nextInstanceId;
41
+ private readonly _idPrefix;
42
+ private readonly _optionIds;
43
+ private readonly _a11yOptionIds;
44
+ private _nextOptionId;
45
+ private _nextA11yOptionId;
46
+ private _options;
47
+ private _portal?;
48
+ private _portalContent?;
49
+ private readonly _pendingUnregisteredOptions;
50
+ private readonly _scrollLock;
51
+ private readonly _panel;
52
+ get isOpen(): boolean;
53
+ get open(): boolean;
54
+ private _onClickOutside;
55
+ private _onFocusOut;
56
+ private _handlePanelPointerDown;
57
+ connectedCallback(): void;
58
+ attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void;
59
+ disconnectedCallback(): void;
60
+ firstUpdated(): void;
61
+ private _queryOptions;
62
+ willUpdate(): void;
63
+ updated(changed: PropertyValues): void;
64
+ formResetCallback(): void;
65
+ formDisabledCallback(disabled: boolean): void;
66
+ formStateRestoreCallback(state: string | File | FormData | null): void;
67
+ private _syncValidity;
68
+ private _syncOpenAttribute;
69
+ private _syncSelectedValue;
70
+ private _syncOptionA11y;
71
+ private _ensureOptionIds;
72
+ private _getA11yOptionId;
73
+ private _applyFilter;
74
+ private _syncEmptyState;
75
+ private _bindOption;
76
+ private _unbindOption;
77
+ private _refreshOptions;
78
+ private _syncPortalContent;
79
+ private _scheduleOptionsRefresh;
80
+ private _onOptionRegister;
81
+ private _onOptionUnregister;
82
+ private _onSlotChange;
83
+ private _handleOptionClick;
84
+ private _onOptionUpdate;
85
+ private _handleOptionPointerOver;
86
+ private _handleOptionPointerDown;
87
+ private _onKeydown;
88
+ private _navigateActive;
89
+ private _setInitialActiveOption;
90
+ private _syncActiveOption;
91
+ private _selectOption;
92
+ private _onInput;
93
+ private _onInnerChange;
94
+ private _onFocus;
95
+ private _onBlur;
96
+ private _open;
97
+ private _close;
98
+ private _dispatchOpenChange;
99
+ private _openOverlay;
100
+ private _closeOverlay;
101
+ private _reconfigureOverlay;
102
+ private _syncScrollLock;
103
+ private _createPortal;
104
+ private _getLabelledbyText;
105
+ render(): import('lit').TemplateResult<1>;
106
+ readonly $events: {
107
+ input: Event;
108
+ change: Event;
109
+ focus: FocusEvent;
110
+ blur: FocusEvent;
111
+ 'open-change': CustomEvent<{
112
+ open: boolean;
113
+ }>;
114
+ };
115
+ }
116
+ declare global {
117
+ interface HTMLElementTagNameMap {
118
+ 'web-ui-autocomplete': WebUiAutocomplete;
119
+ }
120
+ }
121
+ export {};