@ticatec/uniface-element 0.2.4 → 0.3.0

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 (176) hide show
  1. package/dist/accordion/README.md +169 -0
  2. package/dist/accordion/README_CN.md +176 -0
  3. package/dist/action-bar/README.md +275 -0
  4. package/dist/action-bar/README_CN.md +285 -0
  5. package/dist/app-layout/README.md +374 -0
  6. package/dist/app-layout/README_CN.md +381 -0
  7. package/dist/app-top-bar/README.md +357 -0
  8. package/dist/app-top-bar/README_CN.md +365 -0
  9. package/dist/attachment-files/AttachmentFilesField.svelte +67 -1
  10. package/dist/attachment-files/AttachmentFilesField.svelte.d.ts +8 -1
  11. package/dist/base-calendar/CalendarBase.svelte +0 -3
  12. package/dist/box/README.md +385 -0
  13. package/dist/box/README_CN.md +393 -0
  14. package/dist/breadcrumbs/README.md +442 -0
  15. package/dist/breadcrumbs/README_CN.md +442 -0
  16. package/dist/button/Button.svelte +27 -7
  17. package/dist/button/Button.svelte.d.ts +3 -1
  18. package/dist/button/IconButton.svelte +26 -6
  19. package/dist/button/IconButton.svelte.d.ts +3 -1
  20. package/dist/button/IconButton_README.md +513 -0
  21. package/dist/button/IconButton_README_CN.md +513 -0
  22. package/dist/button/README.md +428 -0
  23. package/dist/button/README_CN.md +428 -0
  24. package/dist/button/TextButton.svelte +26 -6
  25. package/dist/button/TextButton.svelte.d.ts +3 -1
  26. package/dist/button/TextButton_README.md +571 -0
  27. package/dist/button/TextButton_README_CN.md +571 -0
  28. package/dist/card/README.md +666 -0
  29. package/dist/card/README_CN.md +666 -0
  30. package/dist/cascade-options-select/CascadeOptionSelect.svelte +43 -7
  31. package/dist/cascade-options-select/CascadeOptionSelect.svelte.d.ts +3 -4
  32. package/dist/cascade-options-select/README.md +663 -2
  33. package/dist/cascade-options-select/README_CN.md +664 -0
  34. package/dist/checkbox/CheckBox.svelte +20 -6
  35. package/dist/checkbox/CheckBox.svelte.d.ts +4 -2
  36. package/dist/checkbox/README.md +562 -0
  37. package/dist/checkbox/README_CN.md +727 -0
  38. package/dist/common-editor/NumberInput.svelte +39 -26
  39. package/dist/common-editor/NumberInput.svelte.d.ts +5 -1
  40. package/dist/concise-data-table/ConciseListTable.svelte +133 -36
  41. package/dist/concise-data-table/ConciseListTable.svelte.d.ts +8 -1
  42. package/dist/concise-data-table/DataCell.svelte +5 -6
  43. package/dist/concise-data-table/DataRow.svelte +22 -2
  44. package/dist/concise-data-table/DataRow.svelte.d.ts +1 -0
  45. package/dist/concise-data-table/README.md +606 -0
  46. package/dist/concise-data-table/README_CN.md +611 -0
  47. package/dist/context-menu/ContextMenu.svelte +138 -21
  48. package/dist/context-menu/ContextMenu.svelte.d.ts +5 -0
  49. package/dist/context-menu/ContextMenuItem.d.ts +20 -4
  50. package/dist/context-menu/README.md +551 -0
  51. package/dist/context-menu/README_CN.md +551 -0
  52. package/dist/criteria-field/CriteriaField.svelte +3 -5
  53. package/dist/criteria-field/README.md +532 -0
  54. package/dist/criteria-field/README_CN.md +532 -0
  55. package/dist/data-table/README.md +712 -0
  56. package/dist/data-table/README_CN.md +712 -0
  57. package/dist/date-picker/DatePicker.svelte +44 -7
  58. package/dist/date-picker/DatePicker.svelte.d.ts +3 -4
  59. package/dist/date-picker/DateTimePicker.svelte +32 -8
  60. package/dist/date-picker/DateTimePicker.svelte.d.ts +3 -4
  61. package/dist/date-picker/README.md +326 -0
  62. package/dist/date-picker/README_CN.md +316 -0
  63. package/dist/date-picker/ScrollBar.svelte +18 -8
  64. package/dist/date-picker/ScrollBar.svelte.d.ts +1 -1
  65. package/dist/date-picker/TimePanel.svelte +5 -5
  66. package/dist/date-picker/TimePanel.svelte.d.ts +1 -1
  67. package/dist/date-range/README.md +374 -0
  68. package/dist/date-range/README_CN.md +374 -0
  69. package/dist/dialog/README.md +596 -0
  70. package/dist/dialog/README_CN.md +596 -0
  71. package/dist/drawer/README.md +679 -1
  72. package/dist/drawer/README_CN.md +679 -0
  73. package/dist/group-box/group-check-box/GroupCheckBox.svelte +62 -5
  74. package/dist/group-box/group-check-box/GroupCheckBox.svelte.d.ts +7 -2
  75. package/dist/group-box/group-check-box/README.md +749 -0
  76. package/dist/group-box/group-check-box/README_CN.md +750 -0
  77. package/dist/group-box/group-radio-box/GroupRadioBox.svelte +69 -4
  78. package/dist/group-box/group-radio-box/GroupRadioBox.svelte.d.ts +8 -2
  79. package/dist/group-box/group-radio-box/README.md +920 -0
  80. package/dist/group-box/group-radio-box/README_CN.md +920 -0
  81. package/dist/image-files/README.md +1346 -0
  82. package/dist/image-files/README_CN.md +1346 -0
  83. package/dist/input-options-select/InputOptionsSelect.svelte +161 -65
  84. package/dist/input-options-select/InputOptionsSelect.svelte.d.ts +4 -1
  85. package/dist/lib/forwardAllEvents.d.ts +3 -0
  86. package/dist/lib/forwardAllEvents.js +24 -0
  87. package/dist/list-box/README.md +579 -0
  88. package/dist/list-box/README_CN.md +682 -0
  89. package/dist/lookup-editor/LookupEditor.svelte +15 -3
  90. package/dist/lookup-editor/LookupEditor.svelte.d.ts +3 -4
  91. package/dist/lookup-editor/README.md +684 -0
  92. package/dist/lookup-editor/README_CN.md +684 -0
  93. package/dist/memo-editor/MemoEditor.svelte +77 -27
  94. package/dist/memo-editor/MemoEditor.svelte.d.ts +6 -3
  95. package/dist/memo-editor/README.md +819 -0
  96. package/dist/memo-editor/README_CN.md +819 -0
  97. package/dist/message-box/README.md +398 -0
  98. package/dist/message-box/README_CN.md +398 -0
  99. package/dist/number-editor/NumberEditor.svelte +2 -2
  100. package/dist/number-editor/NumberEditor.svelte.d.ts +1 -1
  101. package/dist/number-editor/README.md +353 -22
  102. package/dist/number-editor/README_CN.md +357 -0
  103. package/dist/number-range/README.md +443 -0
  104. package/dist/number-range/README_CN.md +443 -0
  105. package/dist/options-multi-select/OptionsMultiSelect.svelte +87 -12
  106. package/dist/options-multi-select/OptionsMultiSelect.svelte.d.ts +3 -1
  107. package/dist/options-multi-select/README.md +480 -0
  108. package/dist/options-multi-select/README_CN.md +480 -0
  109. package/dist/options-select/OptionsSelect.svelte +36 -5
  110. package/dist/options-select/OptionsSelect.svelte.d.ts +3 -4
  111. package/dist/options-select/README.md +632 -0
  112. package/dist/options-select/README_CN.md +632 -0
  113. package/dist/page/README.md +605 -0
  114. package/dist/page/README_CN.md +605 -0
  115. package/dist/pagination/README.md +946 -0
  116. package/dist/pagination/README_CN.md +946 -0
  117. package/dist/pagination-panel/README.md +1075 -0
  118. package/dist/pagination-panel/README_CN.md +1075 -0
  119. package/dist/popup-hint/README.md +841 -0
  120. package/dist/popup-hint/README_CN.md +840 -0
  121. package/dist/progress-bar/README.md +242 -0
  122. package/dist/progress-bar/README_CN.md +242 -0
  123. package/dist/progress-step-bar/README.md +316 -0
  124. package/dist/progress-step-bar/README_CN.md +316 -0
  125. package/dist/prompts-text-editor/PromptsTextEditor.svelte +6 -3
  126. package/dist/prompts-text-editor/PromptsTextEditor.svelte.d.ts +3 -1
  127. package/dist/prompts-text-editor/README.md +329 -0
  128. package/dist/prompts-text-editor/README_CN.md +329 -0
  129. package/dist/property-editor/README.md +969 -0
  130. package/dist/property-editor/README_CN.md +969 -0
  131. package/dist/radio-button/README.md +372 -0
  132. package/dist/radio-button/README_CN.md +372 -0
  133. package/dist/radio-button/RadioButton.svelte +32 -3
  134. package/dist/radio-button/RadioButton.svelte.d.ts +12 -1
  135. package/dist/search-box/README.md +425 -0
  136. package/dist/search-box/README_CN.md +424 -0
  137. package/dist/search-box/SearchBox.svelte +22 -6
  138. package/dist/search-box/SearchBox.svelte.d.ts +4 -1
  139. package/dist/tabs/README.md +919 -0
  140. package/dist/tabs/README_CN.md +920 -0
  141. package/dist/tag/README.md +922 -0
  142. package/dist/tag/README_CN.md +922 -0
  143. package/dist/text-editor/PasswordEditor.svelte +17 -2
  144. package/dist/text-editor/PasswordEditor.svelte.d.ts +3 -3
  145. package/dist/text-editor/PasswordEditor_README.md +551 -0
  146. package/dist/text-editor/PasswordEditor_README_CN.md +551 -0
  147. package/dist/text-editor/README.md +466 -0
  148. package/dist/text-editor/README_CN.md +466 -0
  149. package/dist/text-editor/TextEditor.svelte +51 -19
  150. package/dist/text-editor/TextEditor.svelte.d.ts +0 -1
  151. package/dist/time-editor/README.md +498 -24
  152. package/dist/time-editor/README_CN.md +498 -0
  153. package/dist/time-editor/TimeEditor.svelte +7 -3
  154. package/dist/time-editor/TimeEditor.svelte.d.ts +3 -1
  155. package/dist/toast/README.md +667 -0
  156. package/dist/toast/README_CN.md +667 -0
  157. package/dist/transfer/README.md +795 -0
  158. package/dist/transfer/Transfer.svelte +6 -4
  159. package/dist/transfer/Transfer.svelte.d.ts +3 -1
  160. package/dist/tree-view/README.md +761 -0
  161. package/dist/tree-view/README_CN.md +761 -0
  162. package/dist/tree-view/TreeView.svelte +5 -3
  163. package/dist/tree-view/TreeView.svelte.d.ts +3 -1
  164. package/dist/unit-number-editor/README.md +546 -20
  165. package/dist/unit-number-editor/README_CN.md +525 -0
  166. package/dist/unit-number-editor/UnitNumberEditor.svelte +62 -8
  167. package/dist/unit-number-editor/UnitNumberEditor.svelte.d.ts +5 -1
  168. package/docs/form-field/cn/README_CN.md +364 -0
  169. package/docs/form-field/en/README.md +364 -0
  170. package/docs/form-panel/flex-form/cn/README_CN.md +586 -0
  171. package/docs/form-panel/flex-form/en/README.md +586 -0
  172. package/docs/form-panel/flex-row-form/cn/README_CN.md +787 -0
  173. package/docs/form-panel/flex-row-form/en/README.md +787 -0
  174. package/docs/form-panel/grid-form/en/README.md +744 -0
  175. package/package.json +1 -1
  176. package/dist/drawer/README-CN.md +0 -1
@@ -0,0 +1,840 @@
1
+ # PopupHint 弹出提示
2
+
3
+ 一个全局提示框系统,当用户悬停在元素上时提供上下文提示和信息,具有自动定位和时间控制功能。
4
+
5
+ ## 功能特性
6
+
7
+ - **全局访问**: 通过 `window.Hint` 在整个应用中使用
8
+ - **鼠标跟踪**: 自动在鼠标光标附近定位提示
9
+ - **延迟显示**: 500毫秒延迟显示以防止闪烁
10
+ - **自动隐藏**: 当鼠标离开元素时自动隐藏
11
+ - **门户渲染**: 在文档主体中渲染提示以确保正确的z-index层级
12
+ - **响应式定位**: 自动调整位置以保持在视口内
13
+ - **事件管理**: 正确清理事件监听器
14
+ - **轻量级**: 通过高效的事件处理实现最小性能影响
15
+
16
+ ## 安装
17
+
18
+ ```bash
19
+ npm install @ticatec/uniface-element
20
+ ```
21
+
22
+ ## 设置
23
+
24
+ 首先,在你的根布局或应用组件中添加 PopupHint 组件:
25
+
26
+ ```svelte
27
+ <script>
28
+ import PopupHint from '@ticatec/uniface-element/PopupHint';
29
+ </script>
30
+
31
+ <!-- 应用内容 -->
32
+ <main>
33
+ <!-- 你的组件 -->
34
+ </main>
35
+
36
+ <!-- PopupHint - 全局实例 -->
37
+ <PopupHint />
38
+ ```
39
+
40
+ ## 基本用法
41
+
42
+ 一旦 PopupHint 被挂载,你就可以在应用的任何地方显示提示:
43
+
44
+ ```javascript
45
+ // 悬停在元素上时显示提示
46
+ function handleMouseEnter(event) {
47
+ window.Hint.show(
48
+ event.target, // 目标元素
49
+ '这是一个有用的提示!', // 提示文本
50
+ event.clientX, // 鼠标X坐标
51
+ event.clientY // 鼠标Y坐标
52
+ );
53
+ }
54
+ ```
55
+
56
+ ## API 参考
57
+
58
+ ### 全局方法
59
+
60
+ #### `window.Hint.show(element, text, x, y)`
61
+
62
+ 在指定坐标附近显示提示框。
63
+
64
+ **参数:**
65
+ - `element` (Element): 触发提示的目标元素
66
+ - `text` (string): 要显示的提示文本
67
+ - `x` (number): 鼠标X坐标
68
+ - `y` (number): 鼠标Y坐标
69
+
70
+ **行为:**
71
+ - 添加自动 `mouseleave` 事件监听器来隐藏提示
72
+ - 500毫秒延迟显示以防止意外触发
73
+ - 自动在光标附近定位提示并带有偏移
74
+
75
+ ### 类型
76
+
77
+ ```typescript
78
+ export type ShowHint = (element: Element, text: string, x: number, y: number) => void;
79
+
80
+ export default interface IHint {
81
+ show: ShowHint;
82
+ }
83
+ ```
84
+
85
+ ## 示例
86
+
87
+ ### 基本按钮提示
88
+
89
+ ```svelte
90
+ <script>
91
+ function showHint(text) {
92
+ return function(event) {
93
+ window.Hint.show(event.target, text, event.clientX, event.clientY);
94
+ };
95
+ }
96
+ </script>
97
+
98
+ <div class="button-group">
99
+ <button on:mouseenter={showHint('保存当前工作')}>
100
+ 保存
101
+ </button>
102
+
103
+ <button on:mouseenter={showHint('取消所有更改')}>
104
+ 取消
105
+ </button>
106
+
107
+ <button on:mouseenter={showHint('导出数据为Excel格式')}>
108
+ 导出
109
+ </button>
110
+ </div>
111
+ ```
112
+
113
+ ### 图标工具提示
114
+
115
+ ```svelte
116
+ <script>
117
+ import Icon from '@ticatec/uniface-element/Icon';
118
+
119
+ const iconHints = {
120
+ edit: '编辑此项目',
121
+ delete: '删除此项目(无法撤销)',
122
+ share: '与他人分享',
123
+ bookmark: '添加到书签',
124
+ download: '下载文件'
125
+ };
126
+
127
+ function handleIconHover(iconType) {
128
+ return function(event) {
129
+ const hint = iconHints[iconType];
130
+ if (hint) {
131
+ window.Hint.show(event.target, hint, event.clientX, event.clientY);
132
+ }
133
+ };
134
+ }
135
+ </script>
136
+
137
+ <div class="toolbar">
138
+ <Icon
139
+ name="icon_google_edit"
140
+ on:mouseenter={handleIconHover('edit')}
141
+ />
142
+ <Icon
143
+ name="icon_google_delete"
144
+ on:mouseenter={handleIconHover('delete')}
145
+ />
146
+ <Icon
147
+ name="icon_google_share"
148
+ on:mouseenter={handleIconHover('share')}
149
+ />
150
+ <Icon
151
+ name="icon_google_bookmark"
152
+ on:mouseenter={handleIconHover('bookmark')}
153
+ />
154
+ <Icon
155
+ name="icon_google_download"
156
+ on:mouseenter={handleIconHover('download')}
157
+ />
158
+ </div>
159
+
160
+ <style>
161
+ .toolbar {
162
+ display: flex;
163
+ gap: 8px;
164
+ padding: 12px;
165
+ }
166
+ </style>
167
+ ```
168
+
169
+ ### 表单字段提示
170
+
171
+ ```svelte
172
+ <script>
173
+ import FormField from '@ticatec/uniface-element/FormField';
174
+ import TextEditor from '@ticatec/uniface-element/TextEditor';
175
+
176
+ let formData = {
177
+ username: '',
178
+ email: '',
179
+ password: ''
180
+ };
181
+
182
+ const fieldHints = {
183
+ username: '用户名必须是3-20个字符,仅限字母和数字',
184
+ email: '我们将使用此邮箱进行账户恢复和通知',
185
+ password: '密码必须至少8个字符,包含大写、小写字母和数字'
186
+ };
187
+
188
+ function showFieldHint(fieldName) {
189
+ return function(event) {
190
+ window.Hint.show(event.target, fieldHints[fieldName], event.clientX, event.clientY);
191
+ };
192
+ }
193
+ </script>
194
+
195
+ <form class="registration-form">
196
+ <FormField label="用户名">
197
+ <TextEditor
198
+ variant="outlined"
199
+ bind:value={formData.username}
200
+ placeholder="输入用户名"
201
+ on:mouseenter={showFieldHint('username')}
202
+ />
203
+ </FormField>
204
+
205
+ <FormField label="邮箱">
206
+ <TextEditor
207
+ variant="outlined"
208
+ bind:value={formData.email}
209
+ placeholder="输入邮箱地址"
210
+ on:mouseenter={showFieldHint('email')}
211
+ />
212
+ </FormField>
213
+
214
+ <FormField label="密码">
215
+ <TextEditor
216
+ variant="outlined"
217
+ type="password"
218
+ bind:value={formData.password}
219
+ placeholder="输入密码"
220
+ on:mouseenter={showFieldHint('password')}
221
+ />
222
+ </FormField>
223
+ </form>
224
+ ```
225
+
226
+ ### 数据表格行提示
227
+
228
+ ```svelte
229
+ <script>
230
+ let users = [
231
+ {
232
+ id: 1,
233
+ name: '张三',
234
+ email: 'zhangsan@example.com',
235
+ status: 'active',
236
+ lastLogin: '2024-01-15 14:30:00',
237
+ role: '管理员'
238
+ },
239
+ {
240
+ id: 2,
241
+ name: '李四',
242
+ email: 'lisi@example.com',
243
+ status: 'inactive',
244
+ lastLogin: '2024-01-10 09:15:00',
245
+ role: '用户'
246
+ }
247
+ ];
248
+
249
+ function showUserHint(user) {
250
+ return function(event) {
251
+ const hint = `
252
+ 最后登录: ${user.lastLogin}
253
+ 角色: ${user.role}
254
+ 状态: ${user.status === 'active' ? '活跃' : '非活跃'}
255
+ ID: ${user.id}
256
+ `;
257
+ window.Hint.show(event.target, hint, event.clientX, event.clientY);
258
+ };
259
+ }
260
+
261
+ function showStatusHint(status) {
262
+ return function(event) {
263
+ const hints = {
264
+ active: '用户当前活跃,可以访问系统',
265
+ inactive: '用户账户已被停用',
266
+ pending: '用户注册等待批准',
267
+ suspended: '用户账户已被暂时挂起'
268
+ };
269
+
270
+ window.Hint.show(event.target, hints[status] || '未知状态', event.clientX, event.clientY);
271
+ };
272
+ }
273
+ </script>
274
+
275
+ <table class="user-table">
276
+ <thead>
277
+ <tr>
278
+ <th>姓名</th>
279
+ <th>邮箱</th>
280
+ <th>状态</th>
281
+ </tr>
282
+ </thead>
283
+ <tbody>
284
+ {#each users as user}
285
+ <tr on:mouseenter={showUserHint(user)}>
286
+ <td>{user.name}</td>
287
+ <td>{user.email}</td>
288
+ <td>
289
+ <span
290
+ class="status status-{user.status}"
291
+ on:mouseenter={showStatusHint(user.status)}
292
+ >
293
+ {user.status === 'active' ? '活跃' : '非活跃'}
294
+ </span>
295
+ </td>
296
+ </tr>
297
+ {/each}
298
+ </tbody>
299
+ </table>
300
+
301
+ <style>
302
+ .user-table {
303
+ width: 100%;
304
+ border-collapse: collapse;
305
+ }
306
+
307
+ .user-table th,
308
+ .user-table td {
309
+ padding: 12px;
310
+ text-align: left;
311
+ border-bottom: 1px solid #ddd;
312
+ }
313
+
314
+ .user-table tr:hover {
315
+ background-color: #f5f5f5;
316
+ }
317
+
318
+ .status {
319
+ padding: 4px 8px;
320
+ border-radius: 12px;
321
+ font-size: 12px;
322
+ font-weight: 600;
323
+ text-transform: uppercase;
324
+ }
325
+
326
+ .status-active {
327
+ background: #d4edda;
328
+ color: #155724;
329
+ }
330
+
331
+ .status-inactive {
332
+ background: #f8d7da;
333
+ color: #721c24;
334
+ }
335
+ </style>
336
+ ```
337
+
338
+ ### 图表和图形提示
339
+
340
+ ```svelte
341
+ <script>
342
+ let chartData = [
343
+ { month: '1月', sales: 12000, growth: '+15%' },
344
+ { month: '2月', sales: 13500, growth: '+12.5%' },
345
+ { month: '3月', sales: 11200, growth: '-17%' },
346
+ { month: '4月', sales: 14800, growth: '+32%' },
347
+ { month: '5月', sales: 16200, growth: '+9.5%' }
348
+ ];
349
+
350
+ function showChartHint(dataPoint) {
351
+ return function(event) {
352
+ const hint = `
353
+ 月份: ${dataPoint.month}
354
+ 销售额: ¥${dataPoint.sales.toLocaleString()}
355
+ 增长: ${dataPoint.growth}
356
+ `;
357
+ window.Hint.show(event.target, hint, event.clientX, event.clientY);
358
+ };
359
+ }
360
+ </script>
361
+
362
+ <div class="chart-container">
363
+ <h3>销售图表</h3>
364
+ <div class="chart">
365
+ {#each chartData as data, i}
366
+ <div
367
+ class="chart-bar"
368
+ style="height: {(data.sales / 20000) * 200}px;"
369
+ on:mouseenter={showChartHint(data)}
370
+ >
371
+ <div class="bar-label">{data.month}</div>
372
+ </div>
373
+ {/each}
374
+ </div>
375
+ </div>
376
+
377
+ <style>
378
+ .chart-container {
379
+ padding: 20px;
380
+ }
381
+
382
+ .chart {
383
+ display: flex;
384
+ align-items: flex-end;
385
+ gap: 12px;
386
+ height: 250px;
387
+ border-bottom: 2px solid #333;
388
+ padding: 20px 0;
389
+ }
390
+
391
+ .chart-bar {
392
+ background: linear-gradient(to top, #007bff, #66b3ff);
393
+ width: 60px;
394
+ border-radius: 4px 4px 0 0;
395
+ cursor: pointer;
396
+ transition: transform 0.2s;
397
+ position: relative;
398
+ }
399
+
400
+ .chart-bar:hover {
401
+ transform: scale(1.05);
402
+ }
403
+
404
+ .bar-label {
405
+ position: absolute;
406
+ bottom: -25px;
407
+ left: 50%;
408
+ transform: translateX(-50%);
409
+ font-size: 12px;
410
+ font-weight: 600;
411
+ }
412
+ </style>
413
+ ```
414
+
415
+ ### 图片画廊元数据
416
+
417
+ ```svelte
418
+ <script>
419
+ let images = [
420
+ {
421
+ id: 1,
422
+ src: 'https://picsum.photos/300/200?random=1',
423
+ title: '夕阳风景',
424
+ description: '山峦上的美丽夕阳',
425
+ camera: '佳能 EOS R5',
426
+ settings: 'f/8, 1/250s, ISO 100',
427
+ location: '科罗拉多州落基山脉'
428
+ },
429
+ {
430
+ id: 2,
431
+ src: 'https://picsum.photos/300/200?random=2',
432
+ title: '城市建筑',
433
+ description: '现代建筑设计',
434
+ camera: '索尼 A7R IV',
435
+ settings: 'f/11, 1/125s, ISO 200',
436
+ location: '西雅图市中心'
437
+ }
438
+ ];
439
+
440
+ function showImageHint(image) {
441
+ return function(event) {
442
+ const hint = `
443
+ ${image.title}
444
+
445
+ ${image.description}
446
+
447
+ 相机: ${image.camera}
448
+ 设置: ${image.settings}
449
+ 位置: ${image.location}
450
+ `;
451
+ window.Hint.show(event.target, hint, event.clientX, event.clientY);
452
+ };
453
+ }
454
+ </script>
455
+
456
+ <div class="gallery">
457
+ {#each images as image}
458
+ <div
459
+ class="image-card"
460
+ on:mouseenter={showImageHint(image)}
461
+ >
462
+ <img src={image.src} alt={image.title} />
463
+ <div class="image-overlay">
464
+ <h4>{image.title}</h4>
465
+ </div>
466
+ </div>
467
+ {/each}
468
+ </div>
469
+
470
+ <style>
471
+ .gallery {
472
+ display: grid;
473
+ grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
474
+ gap: 20px;
475
+ padding: 20px;
476
+ }
477
+
478
+ .image-card {
479
+ position: relative;
480
+ border-radius: 8px;
481
+ overflow: hidden;
482
+ cursor: pointer;
483
+ transition: transform 0.2s;
484
+ }
485
+
486
+ .image-card:hover {
487
+ transform: translateY(-4px);
488
+ }
489
+
490
+ .image-card img {
491
+ width: 100%;
492
+ height: 200px;
493
+ object-fit: cover;
494
+ }
495
+
496
+ .image-overlay {
497
+ position: absolute;
498
+ bottom: 0;
499
+ left: 0;
500
+ right: 0;
501
+ background: linear-gradient(transparent, rgba(0,0,0,0.7));
502
+ color: white;
503
+ padding: 20px;
504
+ }
505
+
506
+ .image-overlay h4 {
507
+ margin: 0;
508
+ font-size: 16px;
509
+ }
510
+ </style>
511
+ ```
512
+
513
+ ### 进度指示器状态
514
+
515
+ ```svelte
516
+ <script>
517
+ let tasks = [
518
+ {
519
+ id: 1,
520
+ name: '数据库迁移',
521
+ progress: 75,
522
+ status: '进行中',
523
+ eta: '剩余2小时',
524
+ details: '正在迁移用户数据表(4个中已完成3个)'
525
+ },
526
+ {
527
+ id: 2,
528
+ name: 'API测试',
529
+ progress: 100,
530
+ status: '已完成',
531
+ eta: '已完成',
532
+ details: '所有端点测试成功,覆盖率100%'
533
+ },
534
+ {
535
+ id: 3,
536
+ name: 'UI更新',
537
+ progress: 45,
538
+ status: '进行中',
539
+ eta: '剩余4小时',
540
+ details: '正在更新12个组件(12个中已完成5个)'
541
+ }
542
+ ];
543
+
544
+ function showProgressHint(task) {
545
+ return function(event) {
546
+ const hint = `
547
+ 任务: ${task.name}
548
+ 状态: ${task.status}
549
+ 进度: ${task.progress}%
550
+ 预计完成: ${task.eta}
551
+
552
+ 详情: ${task.details}
553
+ `;
554
+ window.Hint.show(event.target, hint, event.clientX, event.clientY);
555
+ };
556
+ }
557
+ </script>
558
+
559
+ <div class="progress-dashboard">
560
+ <h3>任务进度</h3>
561
+ {#each tasks as task}
562
+ <div class="progress-item">
563
+ <div class="progress-info">
564
+ <span class="task-name">{task.name}</span>
565
+ <span class="progress-percent">{task.progress}%</span>
566
+ </div>
567
+ <div
568
+ class="progress-bar"
569
+ on:mouseenter={showProgressHint(task)}
570
+ >
571
+ <div
572
+ class="progress-fill"
573
+ style="width: {task.progress}%"
574
+ ></div>
575
+ </div>
576
+ </div>
577
+ {/each}
578
+ </div>
579
+
580
+ <style>
581
+ .progress-dashboard {
582
+ max-width: 500px;
583
+ padding: 20px;
584
+ }
585
+
586
+ .progress-item {
587
+ margin-bottom: 16px;
588
+ }
589
+
590
+ .progress-info {
591
+ display: flex;
592
+ justify-content: space-between;
593
+ margin-bottom: 8px;
594
+ }
595
+
596
+ .task-name {
597
+ font-weight: 600;
598
+ }
599
+
600
+ .progress-percent {
601
+ color: #666;
602
+ }
603
+
604
+ .progress-bar {
605
+ height: 8px;
606
+ background: #e0e0e0;
607
+ border-radius: 4px;
608
+ overflow: hidden;
609
+ cursor: pointer;
610
+ }
611
+
612
+ .progress-fill {
613
+ height: 100%;
614
+ background: linear-gradient(90deg, #007bff, #28a745);
615
+ transition: width 0.3s ease;
616
+ }
617
+ </style>
618
+ ```
619
+
620
+ ### 动态内容条件提示
621
+
622
+ ```svelte
623
+ <script>
624
+ let user = {
625
+ name: '张三',
626
+ email: 'zhangsan@example.com',
627
+ role: '管理员',
628
+ lastActive: '2024-01-15T10:30:00Z',
629
+ permissions: ['读取', '写入', '删除', '管理']
630
+ };
631
+
632
+ function showUserBadgeHint(event) {
633
+ const now = new Date();
634
+ const lastActive = new Date(user.lastActive);
635
+ const hoursAgo = Math.floor((now - lastActive) / (1000 * 60 * 60));
636
+
637
+ let activityStatus;
638
+ if (hoursAgo < 1) {
639
+ activityStatus = '当前在线';
640
+ } else if (hoursAgo < 24) {
641
+ activityStatus = `${hoursAgo}小时前在线`;
642
+ } else {
643
+ const daysAgo = Math.floor(hoursAgo / 24);
644
+ activityStatus = `${daysAgo}天前在线`;
645
+ }
646
+
647
+ const hint = `
648
+ ${user.name} (${user.role.toUpperCase()})
649
+ ${user.email}
650
+
651
+ ${activityStatus}
652
+
653
+ 权限: ${user.permissions.join('、')}
654
+ `;
655
+
656
+ window.Hint.show(event.target, hint, event.clientX, event.clientY);
657
+ }
658
+
659
+ function showPermissionHint(permission) {
660
+ return function(event) {
661
+ const permissionDescriptions = {
662
+ '读取': '可以查看所有内容和数据',
663
+ '写入': '可以创建和编辑内容',
664
+ '删除': '可以删除内容和数据',
665
+ '管理': '拥有所有功能的完全管理权限'
666
+ };
667
+
668
+ const hint = permissionDescriptions[permission] || '未知权限';
669
+ window.Hint.show(event.target, hint, event.clientX, event.clientY);
670
+ };
671
+ }
672
+ </script>
673
+
674
+ <div class="user-profile">
675
+ <div
676
+ class="user-badge"
677
+ on:mouseenter={showUserBadgeHint}
678
+ >
679
+ <div class="avatar">
680
+ {user.name.charAt(0)}
681
+ </div>
682
+ <div class="user-info">
683
+ <div class="user-name">{user.name}</div>
684
+ <div class="user-role">{user.role}</div>
685
+ </div>
686
+ </div>
687
+
688
+ <div class="permissions">
689
+ <h4>权限</h4>
690
+ <div class="permission-badges">
691
+ {#each user.permissions as permission}
692
+ <span
693
+ class="permission-badge"
694
+ on:mouseenter={showPermissionHint(permission)}
695
+ >
696
+ {permission}
697
+ </span>
698
+ {/each}
699
+ </div>
700
+ </div>
701
+ </div>
702
+
703
+ <style>
704
+ .user-profile {
705
+ max-width: 300px;
706
+ padding: 20px;
707
+ border: 1px solid #ddd;
708
+ border-radius: 8px;
709
+ }
710
+
711
+ .user-badge {
712
+ display: flex;
713
+ align-items: center;
714
+ gap: 12px;
715
+ cursor: pointer;
716
+ padding: 8px;
717
+ border-radius: 6px;
718
+ transition: background-color 0.2s;
719
+ }
720
+
721
+ .user-badge:hover {
722
+ background-color: #f5f5f5;
723
+ }
724
+
725
+ .avatar {
726
+ width: 40px;
727
+ height: 40px;
728
+ background: #007bff;
729
+ color: white;
730
+ border-radius: 50%;
731
+ display: flex;
732
+ align-items: center;
733
+ justify-content: center;
734
+ font-weight: bold;
735
+ }
736
+
737
+ .user-name {
738
+ font-weight: 600;
739
+ }
740
+
741
+ .user-role {
742
+ color: #666;
743
+ font-size: 14px;
744
+ }
745
+
746
+ .permissions {
747
+ margin-top: 20px;
748
+ }
749
+
750
+ .permissions h4 {
751
+ margin: 0 0 12px 0;
752
+ }
753
+
754
+ .permission-badges {
755
+ display: flex;
756
+ flex-wrap: wrap;
757
+ gap: 6px;
758
+ }
759
+
760
+ .permission-badge {
761
+ background: #e3f2fd;
762
+ color: #1976d2;
763
+ padding: 4px 8px;
764
+ border-radius: 12px;
765
+ font-size: 12px;
766
+ font-weight: 600;
767
+ cursor: pointer;
768
+ transition: background-color 0.2s;
769
+ }
770
+
771
+ .permission-badge:hover {
772
+ background: #bbdefb;
773
+ }
774
+ </style>
775
+ ```
776
+
777
+ ## 最佳实践
778
+
779
+ 1. **有意义的内容**: 在提示中提供真正有用的信息
780
+ 2. **适当的时机**: 500毫秒延迟防止意外触发
781
+ 3. **简洁的文本**: 保持提示文本简短但信息丰富
782
+ 4. **一致的定位**: 使用鼠标坐标进行自然定位
783
+ 5. **性能**: 避免在提示生成中进行复杂计算
784
+ 6. **无障碍性**: 考虑键盘用户和屏幕阅读器
785
+ 7. **内容层次**: 将提示用于次要信息,而非主要操作
786
+
787
+ ## 样式
788
+
789
+ PopupHint 组件可以通过CSS进行样式设置:
790
+
791
+ ```css
792
+ .uniface-popup-hint {
793
+ position: fixed;
794
+ background: rgba(0, 0, 0, 0.8);
795
+ color: white;
796
+ padding: 8px 12px;
797
+ border-radius: 6px;
798
+ font-size: 13px;
799
+ line-height: 1.4;
800
+ z-index: 10000;
801
+ pointer-events: none;
802
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
803
+ max-width: 300px;
804
+ word-wrap: break-word;
805
+ }
806
+
807
+ .uniface-popup-hint::before {
808
+ content: '';
809
+ position: absolute;
810
+ top: -4px;
811
+ left: 8px;
812
+ width: 0;
813
+ height: 0;
814
+ border-left: 4px solid transparent;
815
+ border-right: 4px solid transparent;
816
+ border-bottom: 4px solid rgba(0, 0, 0, 0.8);
817
+ }
818
+ ```
819
+
820
+ ## 无障碍功能
821
+
822
+ - 提示是补充信息,不是关键UI元素
823
+ - 不干扰键盘导航
824
+ - 内容是增强理解的描述性文本
825
+ - 适当使用时与屏幕阅读器兼容
826
+ - 不捕获焦点或阻止交互
827
+
828
+ ## 性能考虑
829
+
830
+ - 使用事件委托实现高效的内存管理
831
+ - 自动清理事件监听器防止内存泄漏
832
+ - 门户渲染确保正确的层级而不重新计算布局
833
+ - 最小的DOM操作实现流畅性能
834
+
835
+ ## 相关组件
836
+
837
+ - [Tooltip](../tooltip/README.md) - 用于更结构化的工具提示内容
838
+ - [MessageBox](../message-box/README.md) - 用于模态信息对话框
839
+ - [Toast](../toast/README.md) - 用于通知消息
840
+ - [Dialog](../dialog/README.md) - 用于复杂的交互内容