@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,841 @@
1
+ # PopupHint
2
+
3
+ A global tooltip system that provides contextual hints and information when users hover over elements, with automatic positioning and timing controls.
4
+
5
+ ## Features
6
+
7
+ - **Global Access**: Available throughout the application via `window.Hint`
8
+ - **Mouse Tracking**: Automatically positions hints near mouse cursor
9
+ - **Delayed Display**: 500ms delay before showing to prevent flickering
10
+ - **Auto Hide**: Automatically hides when mouse leaves the element
11
+ - **Portal Rendering**: Renders hints in document body for proper z-index layering
12
+ - **Responsive Positioning**: Automatically adjusts position to stay within viewport
13
+ - **Event Management**: Proper cleanup of event listeners
14
+ - **Lightweight**: Minimal performance impact with efficient event handling
15
+
16
+ ## Installation
17
+
18
+ ```bash
19
+ npm install @ticatec/uniface-element
20
+ ```
21
+
22
+ ## Setup
23
+
24
+ First, add the PopupHint component to your root layout or app component:
25
+
26
+ ```svelte
27
+ <script>
28
+ import PopupHint from '@ticatec/uniface-element/PopupHint';
29
+ </script>
30
+
31
+ <!-- Your app content -->
32
+ <main>
33
+ <!-- Your components -->
34
+ </main>
35
+
36
+ <!-- PopupHint - Global instance -->
37
+ <PopupHint />
38
+ ```
39
+
40
+ ## Basic Usage
41
+
42
+ Once the PopupHint is mounted, you can show hints from anywhere in your application:
43
+
44
+ ```javascript
45
+ // Show a hint when hovering over an element
46
+ function handleMouseEnter(event) {
47
+ window.Hint.show(
48
+ event.target, // Target element
49
+ 'This is a helpful hint!', // Hint text
50
+ event.clientX, // Mouse X position
51
+ event.clientY // Mouse Y position
52
+ );
53
+ }
54
+ ```
55
+
56
+ ## API Reference
57
+
58
+ ### Global Methods
59
+
60
+ #### `window.Hint.show(element, text, x, y)`
61
+
62
+ Shows a hint tooltip near the specified coordinates.
63
+
64
+ **Parameters:**
65
+ - `element` (Element): The target element that triggered the hint
66
+ - `text` (string): The hint text to display
67
+ - `x` (number): Mouse X coordinate
68
+ - `y` (number): Mouse Y coordinate
69
+
70
+ **Behavior:**
71
+ - Adds automatic `mouseleave` event listener to hide hint
72
+ - 500ms delay before showing to prevent accidental triggers
73
+ - Automatically positions hint near cursor with offset
74
+
75
+ ### Types
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
+ ## Examples
86
+
87
+ ### Basic Button Hints
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('Save your current work')}>
100
+ Save
101
+ </button>
102
+
103
+ <button on:mouseenter={showHint('Cancel all changes')}>
104
+ Cancel
105
+ </button>
106
+
107
+ <button on:mouseenter={showHint('Export data to Excel format')}>
108
+ Export
109
+ </button>
110
+ </div>
111
+ ```
112
+
113
+ ### Icon Tooltips
114
+
115
+ ```svelte
116
+ <script>
117
+ import Icon from '@ticatec/uniface-element/Icon';
118
+
119
+ const iconHints = {
120
+ edit: 'Edit this item',
121
+ delete: 'Delete this item (cannot be undone)',
122
+ share: 'Share with others',
123
+ bookmark: 'Add to bookmarks',
124
+ download: 'Download file'
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
+ ### Form Field Hints
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: 'Username must be 3-20 characters, letters and numbers only',
184
+ email: 'We\'ll use this email for account recovery and notifications',
185
+ password: 'Password must be at least 8 characters with uppercase, lowercase, and numbers'
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="Username">
197
+ <TextEditor
198
+ variant="outlined"
199
+ bind:value={formData.username}
200
+ placeholder="Enter username"
201
+ on:mouseenter={showFieldHint('username')}
202
+ />
203
+ </FormField>
204
+
205
+ <FormField label="Email">
206
+ <TextEditor
207
+ variant="outlined"
208
+ bind:value={formData.email}
209
+ placeholder="Enter email address"
210
+ on:mouseenter={showFieldHint('email')}
211
+ />
212
+ </FormField>
213
+
214
+ <FormField label="Password">
215
+ <TextEditor
216
+ variant="outlined"
217
+ type="password"
218
+ bind:value={formData.password}
219
+ placeholder="Enter password"
220
+ on:mouseenter={showFieldHint('password')}
221
+ />
222
+ </FormField>
223
+ </form>
224
+ ```
225
+
226
+ ### Data Table Row Hints
227
+
228
+ ```svelte
229
+ <script>
230
+ let users = [
231
+ {
232
+ id: 1,
233
+ name: 'John Doe',
234
+ email: 'john@example.com',
235
+ status: 'active',
236
+ lastLogin: '2024-01-15 14:30:00',
237
+ role: 'Administrator'
238
+ },
239
+ {
240
+ id: 2,
241
+ name: 'Jane Smith',
242
+ email: 'jane@example.com',
243
+ status: 'inactive',
244
+ lastLogin: '2024-01-10 09:15:00',
245
+ role: 'User'
246
+ }
247
+ ];
248
+
249
+ function showUserHint(user) {
250
+ return function(event) {
251
+ const hint = `
252
+ Last Login: ${user.lastLogin}
253
+ Role: ${user.role}
254
+ Status: ${user.status.toUpperCase()}
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: 'User is currently active and can access the system',
265
+ inactive: 'User account has been deactivated',
266
+ pending: 'User registration is pending approval',
267
+ suspended: 'User account has been temporarily suspended'
268
+ };
269
+
270
+ window.Hint.show(event.target, hints[status] || 'Unknown status', event.clientX, event.clientY);
271
+ };
272
+ }
273
+ </script>
274
+
275
+ <table class="user-table">
276
+ <thead>
277
+ <tr>
278
+ <th>Name</th>
279
+ <th>Email</th>
280
+ <th>Status</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}
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
+ ### Chart and Graph Hints
339
+
340
+ ```svelte
341
+ <script>
342
+ let chartData = [
343
+ { month: 'Jan', sales: 12000, growth: '+15%' },
344
+ { month: 'Feb', sales: 13500, growth: '+12.5%' },
345
+ { month: 'Mar', sales: 11200, growth: '-17%' },
346
+ { month: 'Apr', sales: 14800, growth: '+32%' },
347
+ { month: 'May', sales: 16200, growth: '+9.5%' }
348
+ ];
349
+
350
+ function showChartHint(dataPoint) {
351
+ return function(event) {
352
+ const hint = `
353
+ Month: ${dataPoint.month}
354
+ Sales: $${dataPoint.sales.toLocaleString()}
355
+ Growth: ${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>Sales Chart</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
+ ### Image Gallery with Metadata
416
+
417
+ ```svelte
418
+ <script>
419
+ let images = [
420
+ {
421
+ id: 1,
422
+ src: 'https://picsum.photos/300/200?random=1',
423
+ title: 'Sunset Landscape',
424
+ description: 'Beautiful sunset over mountains',
425
+ camera: 'Canon EOS R5',
426
+ settings: 'f/8, 1/250s, ISO 100',
427
+ location: 'Rocky Mountains, Colorado'
428
+ },
429
+ {
430
+ id: 2,
431
+ src: 'https://picsum.photos/300/200?random=2',
432
+ title: 'Urban Architecture',
433
+ description: 'Modern building design',
434
+ camera: 'Sony A7R IV',
435
+ settings: 'f/11, 1/125s, ISO 200',
436
+ location: 'Downtown Seattle'
437
+ }
438
+ ];
439
+
440
+ function showImageHint(image) {
441
+ return function(event) {
442
+ const hint = `
443
+ ${image.title}
444
+
445
+ ${image.description}
446
+
447
+ Camera: ${image.camera}
448
+ Settings: ${image.settings}
449
+ Location: ${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
+ ### Progress Indicators with Status
514
+
515
+ ```svelte
516
+ <script>
517
+ let tasks = [
518
+ {
519
+ id: 1,
520
+ name: 'Database Migration',
521
+ progress: 75,
522
+ status: 'In Progress',
523
+ eta: '2 hours remaining',
524
+ details: 'Migrating user data tables (3 of 4 completed)'
525
+ },
526
+ {
527
+ id: 2,
528
+ name: 'API Testing',
529
+ progress: 100,
530
+ status: 'Completed',
531
+ eta: 'Finished',
532
+ details: 'All endpoints tested successfully with 100% coverage'
533
+ },
534
+ {
535
+ id: 3,
536
+ name: 'UI Updates',
537
+ progress: 45,
538
+ status: 'In Progress',
539
+ eta: '4 hours remaining',
540
+ details: 'Updating 12 components (5 of 12 completed)'
541
+ }
542
+ ];
543
+
544
+ function showProgressHint(task) {
545
+ return function(event) {
546
+ const hint = `
547
+ Task: ${task.name}
548
+ Status: ${task.status}
549
+ Progress: ${task.progress}%
550
+ ETA: ${task.eta}
551
+
552
+ Details: ${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>Task Progress</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
+ ### Conditional Hints with Dynamic Content
621
+
622
+ ```svelte
623
+ <script>
624
+ let user = {
625
+ name: 'John Doe',
626
+ email: 'john@example.com',
627
+ role: 'admin',
628
+ lastActive: '2024-01-15T10:30:00Z',
629
+ permissions: ['read', 'write', 'delete', 'admin']
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 = 'Active now';
640
+ } else if (hoursAgo < 24) {
641
+ activityStatus = `Active ${hoursAgo} hours ago`;
642
+ } else {
643
+ const daysAgo = Math.floor(hoursAgo / 24);
644
+ activityStatus = `Active ${daysAgo} days ago`;
645
+ }
646
+
647
+ const hint = `
648
+ ${user.name} (${user.role.toUpperCase()})
649
+ ${user.email}
650
+
651
+ ${activityStatus}
652
+
653
+ Permissions: ${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
+ read: 'Can view all content and data',
663
+ write: 'Can create and edit content',
664
+ delete: 'Can remove content and data',
665
+ admin: 'Full administrative access to all features'
666
+ };
667
+
668
+ const hint = permissionDescriptions[permission] || 'Unknown 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.split(' ').map(n => n[0]).join('')}
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>Permissions</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
+ text-transform: capitalize;
745
+ }
746
+
747
+ .permissions {
748
+ margin-top: 20px;
749
+ }
750
+
751
+ .permissions h4 {
752
+ margin: 0 0 12px 0;
753
+ }
754
+
755
+ .permission-badges {
756
+ display: flex;
757
+ flex-wrap: wrap;
758
+ gap: 6px;
759
+ }
760
+
761
+ .permission-badge {
762
+ background: #e3f2fd;
763
+ color: #1976d2;
764
+ padding: 4px 8px;
765
+ border-radius: 12px;
766
+ font-size: 12px;
767
+ font-weight: 600;
768
+ cursor: pointer;
769
+ transition: background-color 0.2s;
770
+ }
771
+
772
+ .permission-badge:hover {
773
+ background: #bbdefb;
774
+ }
775
+ </style>
776
+ ```
777
+
778
+ ## Best Practices
779
+
780
+ 1. **Meaningful Content**: Provide genuinely helpful information in hints
781
+ 2. **Appropriate Timing**: The 500ms delay prevents accidental triggers
782
+ 3. **Concise Text**: Keep hint text brief but informative
783
+ 4. **Consistent Positioning**: Use mouse coordinates for natural positioning
784
+ 5. **Performance**: Avoid complex calculations in hint generation
785
+ 6. **Accessibility**: Consider keyboard users and screen readers
786
+ 7. **Content Hierarchy**: Use hints for secondary information, not primary actions
787
+
788
+ ## Styling
789
+
790
+ The PopupHint component can be styled through CSS:
791
+
792
+ ```css
793
+ .uniface-popup-hint {
794
+ position: fixed;
795
+ background: rgba(0, 0, 0, 0.8);
796
+ color: white;
797
+ padding: 8px 12px;
798
+ border-radius: 6px;
799
+ font-size: 13px;
800
+ line-height: 1.4;
801
+ z-index: 10000;
802
+ pointer-events: none;
803
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
804
+ max-width: 300px;
805
+ word-wrap: break-word;
806
+ }
807
+
808
+ .uniface-popup-hint::before {
809
+ content: '';
810
+ position: absolute;
811
+ top: -4px;
812
+ left: 8px;
813
+ width: 0;
814
+ height: 0;
815
+ border-left: 4px solid transparent;
816
+ border-right: 4px solid transparent;
817
+ border-bottom: 4px solid rgba(0, 0, 0, 0.8);
818
+ }
819
+ ```
820
+
821
+ ## Accessibility
822
+
823
+ - Hints are supplementary information, not critical UI elements
824
+ - Does not interfere with keyboard navigation
825
+ - Content is descriptive text that enhances understanding
826
+ - Compatible with screen readers when used appropriately
827
+ - Does not trap focus or block interaction
828
+
829
+ ## Performance Considerations
830
+
831
+ - Uses event delegation for efficient memory management
832
+ - Automatic cleanup of event listeners prevents memory leaks
833
+ - Portal rendering ensures proper layering without layout recalculation
834
+ - Minimal DOM manipulation for smooth performance
835
+
836
+ ## Related Components
837
+
838
+ - [Tooltip](../tooltip/README.md) - For more structured tooltip content
839
+ - [MessageBox](../message-box/README.md) - For modal information dialogs
840
+ - [Toast](../toast/README.md) - For notification messages
841
+ - [Dialog](../dialog/README.md) - For complex interactive content