@ticatec/uniface-element 0.2.3 → 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.
- package/dist/accordion/README.md +169 -0
- package/dist/accordion/README_CN.md +176 -0
- package/dist/action-bar/README.md +275 -0
- package/dist/action-bar/README_CN.md +285 -0
- package/dist/app-layout/README.md +374 -0
- package/dist/app-layout/README_CN.md +381 -0
- package/dist/app-top-bar/README.md +357 -0
- package/dist/app-top-bar/README_CN.md +365 -0
- package/dist/attachment-files/AttachmentFilesField.svelte +67 -1
- package/dist/attachment-files/AttachmentFilesField.svelte.d.ts +8 -1
- package/dist/base-calendar/CalendarBase.svelte +0 -3
- package/dist/box/README.md +385 -0
- package/dist/box/README_CN.md +393 -0
- package/dist/breadcrumbs/README.md +442 -0
- package/dist/breadcrumbs/README_CN.md +442 -0
- package/dist/button/Button.svelte +27 -7
- package/dist/button/Button.svelte.d.ts +3 -1
- package/dist/button/IconButton.svelte +26 -6
- package/dist/button/IconButton.svelte.d.ts +3 -1
- package/dist/button/IconButton_README.md +513 -0
- package/dist/button/IconButton_README_CN.md +513 -0
- package/dist/button/README.md +428 -0
- package/dist/button/README_CN.md +428 -0
- package/dist/button/TextButton.svelte +26 -6
- package/dist/button/TextButton.svelte.d.ts +3 -1
- package/dist/button/TextButton_README.md +571 -0
- package/dist/button/TextButton_README_CN.md +571 -0
- package/dist/card/README.md +666 -0
- package/dist/card/README_CN.md +666 -0
- package/dist/cascade-options-select/CascadeOptionSelect.svelte +43 -7
- package/dist/cascade-options-select/CascadeOptionSelect.svelte.d.ts +3 -4
- package/dist/cascade-options-select/README.md +663 -2
- package/dist/cascade-options-select/README_CN.md +664 -0
- package/dist/checkbox/CheckBox.svelte +20 -6
- package/dist/checkbox/CheckBox.svelte.d.ts +4 -2
- package/dist/checkbox/README.md +562 -0
- package/dist/checkbox/README_CN.md +727 -0
- package/dist/common-editor/NumberInput.svelte +39 -26
- package/dist/common-editor/NumberInput.svelte.d.ts +5 -1
- package/dist/concise-data-table/ConciseListTable.svelte +133 -36
- package/dist/concise-data-table/ConciseListTable.svelte.d.ts +8 -1
- package/dist/concise-data-table/DataCell.svelte +5 -6
- package/dist/concise-data-table/DataRow.svelte +22 -2
- package/dist/concise-data-table/DataRow.svelte.d.ts +1 -0
- package/dist/concise-data-table/README.md +606 -0
- package/dist/concise-data-table/README_CN.md +611 -0
- package/dist/context-menu/ContextMenu.svelte +138 -21
- package/dist/context-menu/ContextMenu.svelte.d.ts +5 -0
- package/dist/context-menu/ContextMenuItem.d.ts +20 -4
- package/dist/context-menu/README.md +551 -0
- package/dist/context-menu/README_CN.md +551 -0
- package/dist/criteria-field/CriteriaField.svelte +3 -5
- package/dist/criteria-field/README.md +532 -0
- package/dist/criteria-field/README_CN.md +532 -0
- package/dist/data-table/README.md +712 -0
- package/dist/data-table/README_CN.md +712 -0
- package/dist/date-picker/DatePicker.svelte +44 -7
- package/dist/date-picker/DatePicker.svelte.d.ts +3 -4
- package/dist/date-picker/DateTimePicker.svelte +32 -8
- package/dist/date-picker/DateTimePicker.svelte.d.ts +3 -4
- package/dist/date-picker/README.md +326 -0
- package/dist/date-picker/README_CN.md +316 -0
- package/dist/date-picker/ScrollBar.svelte +18 -8
- package/dist/date-picker/ScrollBar.svelte.d.ts +1 -1
- package/dist/date-picker/TimePanel.svelte +5 -5
- package/dist/date-picker/TimePanel.svelte.d.ts +1 -1
- package/dist/date-range/README.md +374 -0
- package/dist/date-range/README_CN.md +374 -0
- package/dist/dialog/DialogBoard.svelte +1 -1
- package/dist/dialog/README.md +596 -0
- package/dist/dialog/README_CN.md +596 -0
- package/dist/drawer/README.md +679 -1
- package/dist/drawer/README_CN.md +679 -0
- package/dist/group-box/group-check-box/GroupCheckBox.svelte +62 -5
- package/dist/group-box/group-check-box/GroupCheckBox.svelte.d.ts +7 -2
- package/dist/group-box/group-check-box/README.md +749 -0
- package/dist/group-box/group-check-box/README_CN.md +750 -0
- package/dist/group-box/group-radio-box/GroupRadioBox.svelte +69 -4
- package/dist/group-box/group-radio-box/GroupRadioBox.svelte.d.ts +8 -2
- package/dist/group-box/group-radio-box/README.md +920 -0
- package/dist/group-box/group-radio-box/README_CN.md +920 -0
- package/dist/image-files/README.md +1346 -0
- package/dist/image-files/README_CN.md +1346 -0
- package/dist/input-options-select/InputOptionsSelect.svelte +161 -65
- package/dist/input-options-select/InputOptionsSelect.svelte.d.ts +4 -1
- package/dist/lib/forwardAllEvents.d.ts +3 -0
- package/dist/lib/forwardAllEvents.js +24 -0
- package/dist/list-box/README.md +579 -0
- package/dist/list-box/README_CN.md +682 -0
- package/dist/lookup-editor/LookupEditor.svelte +15 -3
- package/dist/lookup-editor/LookupEditor.svelte.d.ts +3 -4
- package/dist/lookup-editor/README.md +684 -0
- package/dist/lookup-editor/README_CN.md +684 -0
- package/dist/memo-editor/MemoEditor.svelte +77 -27
- package/dist/memo-editor/MemoEditor.svelte.d.ts +6 -3
- package/dist/memo-editor/README.md +819 -0
- package/dist/memo-editor/README_CN.md +819 -0
- package/dist/message-box/README.md +398 -0
- package/dist/message-box/README_CN.md +398 -0
- package/dist/number-editor/NumberEditor.svelte +2 -2
- package/dist/number-editor/NumberEditor.svelte.d.ts +1 -1
- package/dist/number-editor/README.md +353 -22
- package/dist/number-editor/README_CN.md +357 -0
- package/dist/number-range/README.md +443 -0
- package/dist/number-range/README_CN.md +443 -0
- package/dist/options-multi-select/OptionsMultiSelect.svelte +87 -12
- package/dist/options-multi-select/OptionsMultiSelect.svelte.d.ts +3 -1
- package/dist/options-multi-select/README.md +480 -0
- package/dist/options-multi-select/README_CN.md +480 -0
- package/dist/options-select/OptionsSelect.svelte +36 -5
- package/dist/options-select/OptionsSelect.svelte.d.ts +3 -4
- package/dist/options-select/README.md +632 -0
- package/dist/options-select/README_CN.md +632 -0
- package/dist/page/README.md +605 -0
- package/dist/page/README_CN.md +605 -0
- package/dist/pagination/README.md +946 -0
- package/dist/pagination/README_CN.md +946 -0
- package/dist/pagination-panel/README.md +1075 -0
- package/dist/pagination-panel/README_CN.md +1075 -0
- package/dist/popup-hint/README.md +841 -0
- package/dist/popup-hint/README_CN.md +840 -0
- package/dist/progress-bar/README.md +242 -0
- package/dist/progress-bar/README_CN.md +242 -0
- package/dist/progress-step-bar/README.md +316 -0
- package/dist/progress-step-bar/README_CN.md +316 -0
- package/dist/prompts-text-editor/PromptsTextEditor.svelte +6 -3
- package/dist/prompts-text-editor/PromptsTextEditor.svelte.d.ts +3 -1
- package/dist/prompts-text-editor/README.md +329 -0
- package/dist/prompts-text-editor/README_CN.md +329 -0
- package/dist/property-editor/README.md +969 -0
- package/dist/property-editor/README_CN.md +969 -0
- package/dist/radio-button/README.md +372 -0
- package/dist/radio-button/README_CN.md +372 -0
- package/dist/radio-button/RadioButton.svelte +32 -3
- package/dist/radio-button/RadioButton.svelte.d.ts +12 -1
- package/dist/search-box/README.md +425 -0
- package/dist/search-box/README_CN.md +424 -0
- package/dist/search-box/SearchBox.svelte +22 -6
- package/dist/search-box/SearchBox.svelte.d.ts +4 -1
- package/dist/tabs/README.md +919 -0
- package/dist/tabs/README_CN.md +920 -0
- package/dist/tag/README.md +922 -0
- package/dist/tag/README_CN.md +922 -0
- package/dist/text-editor/PasswordEditor.svelte +17 -2
- package/dist/text-editor/PasswordEditor.svelte.d.ts +3 -3
- package/dist/text-editor/PasswordEditor_README.md +551 -0
- package/dist/text-editor/PasswordEditor_README_CN.md +551 -0
- package/dist/text-editor/README.md +466 -0
- package/dist/text-editor/README_CN.md +466 -0
- package/dist/text-editor/TextEditor.svelte +51 -19
- package/dist/text-editor/TextEditor.svelte.d.ts +0 -1
- package/dist/ticatec-uniface-web.css +1 -0
- package/dist/time-editor/README.md +498 -24
- package/dist/time-editor/README_CN.md +498 -0
- package/dist/time-editor/TimeEditor.svelte +7 -3
- package/dist/time-editor/TimeEditor.svelte.d.ts +3 -1
- package/dist/toast/README.md +667 -0
- package/dist/toast/README_CN.md +667 -0
- package/dist/transfer/README.md +795 -0
- package/dist/transfer/Transfer.svelte +6 -4
- package/dist/transfer/Transfer.svelte.d.ts +3 -1
- package/dist/tree-view/README.md +761 -0
- package/dist/tree-view/README_CN.md +761 -0
- package/dist/tree-view/TreeView.svelte +5 -3
- package/dist/tree-view/TreeView.svelte.d.ts +3 -1
- package/dist/unit-number-editor/README.md +546 -20
- package/dist/unit-number-editor/README_CN.md +525 -0
- package/dist/unit-number-editor/UnitNumberEditor.svelte +62 -8
- package/dist/unit-number-editor/UnitNumberEditor.svelte.d.ts +5 -1
- package/docs/form-field/cn/README_CN.md +364 -0
- package/docs/form-field/en/README.md +364 -0
- package/docs/form-panel/flex-form/cn/README_CN.md +586 -0
- package/docs/form-panel/flex-form/en/README.md +586 -0
- package/docs/form-panel/flex-row-form/cn/README_CN.md +787 -0
- package/docs/form-panel/flex-row-form/en/README.md +787 -0
- package/docs/form-panel/grid-form/en/README.md +744 -0
- package/package.json +1 -1
- 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
|