@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.
- 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/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/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
|
@@ -13,33 +13,50 @@
|
|
|
13
13
|
export let allowNegative: boolean = false;
|
|
14
14
|
export let max: number | null = null;
|
|
15
15
|
export let min: number | null = null;
|
|
16
|
-
export let
|
|
16
|
+
export let onchange: OnChangeHandler<number | null> = null as unknown as OnChangeHandler<number | null>;
|
|
17
|
+
export let onfocus: (() => void) | null = null;
|
|
18
|
+
export let onblur: (() => void) | null = null;
|
|
17
19
|
export let textValue: string = '';
|
|
20
|
+
|
|
18
21
|
export const focus = () => {
|
|
19
22
|
editor.focus();
|
|
20
23
|
}
|
|
24
|
+
|
|
25
|
+
export const setFocus = () => {
|
|
26
|
+
setTimeout(() => {
|
|
27
|
+
editor && editor.focus();
|
|
28
|
+
}, 50);
|
|
29
|
+
}
|
|
21
30
|
|
|
22
31
|
let regex: RegExp;
|
|
32
|
+
let editor: HTMLInputElement;
|
|
33
|
+
let composing: boolean = false;
|
|
34
|
+
let currentText: string;
|
|
35
|
+
let isFocused = false;
|
|
23
36
|
|
|
24
|
-
|
|
37
|
+
const handleFocusEvent = (e: FocusEvent) => {
|
|
38
|
+
isFocused = true;
|
|
39
|
+
onfocus?.();
|
|
40
|
+
}
|
|
25
41
|
|
|
26
42
|
const handleBlurEvent = (e: FocusEvent) => {
|
|
27
43
|
isFocused = false;
|
|
44
|
+
onblur?.();
|
|
28
45
|
if (!readonly) {
|
|
29
46
|
value = parseFloat(textValue);
|
|
30
47
|
if (isNaN(value)) {
|
|
31
48
|
value = null;
|
|
32
49
|
}
|
|
33
50
|
if (value != null) {
|
|
34
|
-
if (min != null && value
|
|
51
|
+
if (min != null && value < min) {
|
|
35
52
|
value = min;
|
|
36
53
|
}
|
|
37
|
-
if (max != null && value
|
|
54
|
+
if (max != null && value > max) {
|
|
38
55
|
value = max;
|
|
39
56
|
}
|
|
40
57
|
textValue = utils.formatNumber(value, precision);
|
|
41
58
|
}
|
|
42
|
-
|
|
59
|
+
onchange?.(value);
|
|
43
60
|
} else {
|
|
44
61
|
e.stopPropagation();
|
|
45
62
|
}
|
|
@@ -47,21 +64,17 @@
|
|
|
47
64
|
|
|
48
65
|
const checkNewInputText = (s: string): boolean => {
|
|
49
66
|
const currentValue = editor.value;
|
|
50
|
-
const cursorStart = editor.selectionStart; //
|
|
51
|
-
const cursorEnd = editor.selectionEnd; //
|
|
67
|
+
const cursorStart = editor.selectionStart; // cursor start position
|
|
68
|
+
const cursorEnd = editor.selectionEnd; // cursor end position
|
|
52
69
|
let resultingString = currentValue.slice(0, cursorStart) + s + currentValue.slice(cursorEnd);
|
|
53
|
-
if (/[^0-9
|
|
70
|
+
if (/[^0-9\.\-]/.test(resultingString)) {
|
|
54
71
|
return false;
|
|
55
72
|
} else {
|
|
56
|
-
return regex.test(resultingString) &&
|
|
73
|
+
return regex.test(resultingString) &&
|
|
74
|
+
utils.isValidNumber(parseFloat(resultingString), precision, allowNegative, max, min);
|
|
57
75
|
}
|
|
58
76
|
}
|
|
59
77
|
|
|
60
|
-
|
|
61
|
-
let composing: boolean = false;
|
|
62
|
-
let currentText: string;
|
|
63
|
-
let isFocused = false;
|
|
64
|
-
|
|
65
78
|
const handlePaste = (event: ClipboardEvent) => {
|
|
66
79
|
const pasteData = event.clipboardData?.getData('text') || '';
|
|
67
80
|
if (!checkNewInputText(pasteData)) {
|
|
@@ -70,32 +83,32 @@
|
|
|
70
83
|
}
|
|
71
84
|
|
|
72
85
|
const handleKeyDown = (event: KeyboardEvent) => {
|
|
73
|
-
//
|
|
86
|
+
// Check for full-width characters or non-ASCII characters
|
|
74
87
|
if (/[^\x00-\x7F]/.test(event.key)) {
|
|
75
88
|
event.preventDefault();
|
|
76
89
|
event.stopPropagation();
|
|
77
90
|
return;
|
|
78
91
|
}
|
|
79
92
|
|
|
80
|
-
//
|
|
93
|
+
// Allow special keys like ctrl
|
|
81
94
|
const allowKeys = ['Backspace', 'Delete', 'Tab', 'ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown'];
|
|
82
95
|
if (allowKeys.includes(event.key)) return;
|
|
83
96
|
|
|
84
|
-
//
|
|
97
|
+
// Allow numbers, decimal points, negative signs (can customize based on precision)
|
|
85
98
|
if (/[\d\.\-]/.test(event.key)) return;
|
|
86
99
|
|
|
87
|
-
//
|
|
100
|
+
// Block other invalid characters
|
|
88
101
|
event.preventDefault();
|
|
89
102
|
event.stopPropagation();
|
|
90
103
|
};
|
|
91
104
|
const handleInput = () => {
|
|
92
|
-
if (composing) return; //
|
|
105
|
+
if (composing) return; // Ignore during composition (e.g., pinyin input)
|
|
93
106
|
|
|
94
|
-
//
|
|
107
|
+
// Validate if it's a valid number string
|
|
95
108
|
const raw = editor.value;
|
|
96
109
|
if (/[^\x00-\x7F]/.test(raw)) {
|
|
97
|
-
//
|
|
98
|
-
editor.value = textValue; //
|
|
110
|
+
// Contains Chinese, Japanese, Korean, full-width characters, emojis, etc.
|
|
111
|
+
editor.value = textValue; // Restore previous state
|
|
99
112
|
return;
|
|
100
113
|
}
|
|
101
114
|
if (regex.test(raw)) {
|
|
@@ -105,7 +118,7 @@
|
|
|
105
118
|
}
|
|
106
119
|
}
|
|
107
120
|
|
|
108
|
-
//
|
|
121
|
+
// When invalid, don't update value, only update textValue (allow user to continue typing)
|
|
109
122
|
textValue = raw;
|
|
110
123
|
}
|
|
111
124
|
|
|
@@ -118,10 +131,10 @@
|
|
|
118
131
|
const handleCompositionEnd = (event: CompositionEvent) => {
|
|
119
132
|
composing = false;
|
|
120
133
|
if (/[^\x00-\x7F]/.test(editor.value)) {
|
|
121
|
-
editor.value = currentText; //
|
|
134
|
+
editor.value = currentText; // Restore previous content
|
|
122
135
|
textValue = currentText;
|
|
123
136
|
} else {
|
|
124
|
-
handleInput(); //
|
|
137
|
+
handleInput(); // Normal input
|
|
125
138
|
}
|
|
126
139
|
};
|
|
127
140
|
|
|
@@ -135,7 +148,7 @@
|
|
|
135
148
|
</script>
|
|
136
149
|
<input class="number-editor" bind:this={editor} type="text" {readonly} {style} {disabled} placeholder={readonly || disabled ? '' : placeholder}
|
|
137
150
|
bind:value={textValue}
|
|
138
|
-
on:focus={
|
|
151
|
+
on:focus={handleFocusEvent}
|
|
139
152
|
on:blur={handleBlurEvent}
|
|
140
153
|
on:compositionstart={handleCompositionStart}
|
|
141
154
|
on:input={handleInput}
|
|
@@ -22,13 +22,17 @@ declare const NumberInput: $$__sveltets_2_IsomorphicComponent<{
|
|
|
22
22
|
allowNegative?: boolean;
|
|
23
23
|
max?: number | null;
|
|
24
24
|
min?: number | null;
|
|
25
|
-
|
|
25
|
+
onchange?: OnChangeHandler<number | null>;
|
|
26
|
+
onfocus?: (() => void) | null;
|
|
27
|
+
onblur?: (() => void) | null;
|
|
26
28
|
textValue?: string;
|
|
27
29
|
focus?: () => void;
|
|
30
|
+
setFocus?: () => void;
|
|
28
31
|
}, {
|
|
29
32
|
[evt: string]: CustomEvent<any>;
|
|
30
33
|
}, {}, {
|
|
31
34
|
focus: () => void;
|
|
35
|
+
setFocus: () => void;
|
|
32
36
|
}, string>;
|
|
33
37
|
type NumberInput = InstanceType<typeof NumberInput>;
|
|
34
38
|
export default NumberInput;
|
|
@@ -15,11 +15,15 @@
|
|
|
15
15
|
// Milliseconds between each scroll step
|
|
16
16
|
export let scrollInterval: number = 2000;
|
|
17
17
|
export let rowClickHandler: RowClickHandler | null = null;
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
// Height of the component in pixels
|
|
21
|
-
//table background color
|
|
18
|
+
// Table styling and behavior options
|
|
22
19
|
export let options: TableOptions;
|
|
20
|
+
// Custom CSS styles for the table container
|
|
21
|
+
export let style: string = '';
|
|
22
|
+
// Additional CSS classes
|
|
23
|
+
export let className: string = '';
|
|
24
|
+
// Focus/blur event handlers
|
|
25
|
+
export let onfocus: ((event: FocusEvent) => void) | null = null;
|
|
26
|
+
export let onblur: ((event: FocusEvent) => void) | null = null;
|
|
23
27
|
|
|
24
28
|
let tabOptions: TableOptions;
|
|
25
29
|
|
|
@@ -66,7 +70,11 @@
|
|
|
66
70
|
rowHeight = tableBody.children[0].offsetHeight;
|
|
67
71
|
visibleRowCount = Math.floor((tableContainer.offsetHeight - headerRow.offsetHeight) / rowHeight);
|
|
68
72
|
if (list.length <= visibleRowCount) return;
|
|
69
|
-
|
|
73
|
+
|
|
74
|
+
// 为无缝滚动准备足够的克隆数据
|
|
75
|
+
const duplicateCount = Math.ceil(visibleRowCount / list.length) + 1;
|
|
76
|
+
clonedRows = Array(duplicateCount).fill(list).flat();
|
|
77
|
+
|
|
70
78
|
startAutoScroll();
|
|
71
79
|
}
|
|
72
80
|
}
|
|
@@ -76,27 +84,40 @@
|
|
|
76
84
|
// Clear any existing timer
|
|
77
85
|
if (scrollTimer) clearInterval(scrollTimer);
|
|
78
86
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
tableBody.style.transition = 'transform 2s ease';
|
|
95
|
-
}, 50);
|
|
96
|
-
}, 50);
|
|
97
|
-
}
|
|
87
|
+
const originalDataHeight = list.length * rowHeight;
|
|
88
|
+
|
|
89
|
+
// 使用连续动画,通过动态创建style元素实现真正的无缝循环
|
|
90
|
+
const tableBody = tableContainer.querySelector('.table-body');
|
|
91
|
+
if (tableBody) {
|
|
92
|
+
// 创建CSS动画
|
|
93
|
+
const animationDuration = scrollInterval * list.length / 1000; // 总动画时长(秒)
|
|
94
|
+
|
|
95
|
+
// 移除之前的动画
|
|
96
|
+
tableBody.style.animation = 'none';
|
|
97
|
+
|
|
98
|
+
// 删除之前的style元素(如果存在)
|
|
99
|
+
const existingStyle = document.getElementById(`marqueeStyle_${id}`);
|
|
100
|
+
if (existingStyle) {
|
|
101
|
+
existingStyle.remove();
|
|
98
102
|
}
|
|
99
|
-
|
|
103
|
+
|
|
104
|
+
// 创建新的style元素
|
|
105
|
+
const styleElement = document.createElement('style');
|
|
106
|
+
styleElement.id = `marqueeStyle_${id}`;
|
|
107
|
+
styleElement.textContent = `
|
|
108
|
+
@keyframes marqueeScroll_${id} {
|
|
109
|
+
0% { transform: translateY(0px); }
|
|
110
|
+
100% { transform: translateY(-${originalDataHeight}px); }
|
|
111
|
+
}
|
|
112
|
+
`;
|
|
113
|
+
document.head.appendChild(styleElement);
|
|
114
|
+
|
|
115
|
+
// 强制浏览器重新计算样式
|
|
116
|
+
tableBody.offsetHeight;
|
|
117
|
+
|
|
118
|
+
// 应用新的动画
|
|
119
|
+
tableBody.style.animation = `marqueeScroll_${id} ${animationDuration}s linear infinite`;
|
|
120
|
+
}
|
|
100
121
|
}
|
|
101
122
|
|
|
102
123
|
const stopAutoScroll = () => {
|
|
@@ -104,6 +125,13 @@
|
|
|
104
125
|
clearInterval(scrollTimer);
|
|
105
126
|
scrollTimer = null;
|
|
106
127
|
}
|
|
128
|
+
|
|
129
|
+
// 停止CSS动画
|
|
130
|
+
const tableBody = tableContainer?.querySelector('.table-body');
|
|
131
|
+
if (tableBody) {
|
|
132
|
+
tableBody.style.animation = 'none';
|
|
133
|
+
tableBody.style.transform = 'translateY(0px)';
|
|
134
|
+
}
|
|
107
135
|
}
|
|
108
136
|
|
|
109
137
|
onMount(async () => {
|
|
@@ -112,6 +140,11 @@
|
|
|
112
140
|
|
|
113
141
|
onDestroy(() => {
|
|
114
142
|
stopAutoScroll();
|
|
143
|
+
// 清理动态创建的style元素
|
|
144
|
+
const existingStyle = document.getElementById(`marqueeStyle_${id}`);
|
|
145
|
+
if (existingStyle) {
|
|
146
|
+
existingStyle.remove();
|
|
147
|
+
}
|
|
115
148
|
});
|
|
116
149
|
|
|
117
150
|
$: if (list || autoScroll || scrollInterval) {
|
|
@@ -125,17 +158,39 @@
|
|
|
125
158
|
rowClickHandler?.(row)
|
|
126
159
|
}
|
|
127
160
|
|
|
161
|
+
const handleTableFocus = (event: FocusEvent) => {
|
|
162
|
+
onfocus?.(event);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
const handleTableBlur = (event: FocusEvent) => {
|
|
166
|
+
onblur?.(event);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
export const setFocus = () => {
|
|
170
|
+
const firstRow = tableContainer?.querySelector('.table-body .table-row');
|
|
171
|
+
if (firstRow) {
|
|
172
|
+
setTimeout(() => {
|
|
173
|
+
(firstRow as HTMLElement).focus();
|
|
174
|
+
}, 50);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
128
177
|
|
|
129
178
|
</script>
|
|
130
179
|
|
|
131
|
-
<div
|
|
180
|
+
<div
|
|
181
|
+
id="tab_{id}"
|
|
182
|
+
class="uniface-concise-datatable {className}"
|
|
183
|
+
{style}
|
|
184
|
+
on:focusin={handleTableFocus}
|
|
185
|
+
on:focusout={handleTableBlur}
|
|
186
|
+
>
|
|
132
187
|
{@html tableStyle}
|
|
133
188
|
<div class="table-container" bind:this={tableContainer}>
|
|
134
189
|
<!-- Fixed header -->
|
|
135
190
|
<div class="table-header">
|
|
136
|
-
<div class="table-row" bind:this={headerRow}>
|
|
191
|
+
<div class="table-row" bind:this={headerRow} role="row">
|
|
137
192
|
{#each columns as column, idx}
|
|
138
|
-
<div class="data-cell col_{idx}">
|
|
193
|
+
<div class="data-cell col_{idx}" role="columnheader">
|
|
139
194
|
{column.title ?? ''}
|
|
140
195
|
</div>
|
|
141
196
|
{/each}
|
|
@@ -143,14 +198,56 @@
|
|
|
143
198
|
</div>
|
|
144
199
|
|
|
145
200
|
<!-- Scrollable body -->
|
|
146
|
-
<div
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
201
|
+
<div
|
|
202
|
+
class="table-body-container"
|
|
203
|
+
bind:this={viewPanel}
|
|
204
|
+
class:auto-scroll={autoScroll}
|
|
205
|
+
role="table"
|
|
206
|
+
aria-label="Data table"
|
|
207
|
+
aria-rowcount={list.length + 1}
|
|
208
|
+
>
|
|
209
|
+
<div class="table-body">
|
|
210
|
+
{#if autoScroll}
|
|
211
|
+
<!-- 无缝滚动模式:渲染原始数据 + 足够的重复数据确保无缝滚动 -->
|
|
212
|
+
{#each list as row, rowIndex}
|
|
213
|
+
<DataRow
|
|
214
|
+
data={row}
|
|
215
|
+
{columns}
|
|
216
|
+
{rowIndex}
|
|
217
|
+
showAlternative={rowIndex % 2 == 1}
|
|
218
|
+
on:click={handleRowClick(row)}
|
|
219
|
+
/>
|
|
220
|
+
{/each}
|
|
221
|
+
<!-- 渲染第二份数据,确保无缝滚动 -->
|
|
222
|
+
{#each list as row, rowIndex}
|
|
223
|
+
<DataRow
|
|
224
|
+
data={row}
|
|
225
|
+
{columns}
|
|
226
|
+
rowIndex={rowIndex + list.length}
|
|
227
|
+
showAlternative={(rowIndex + list.length) % 2 == 1}
|
|
228
|
+
on:click={handleRowClick(row)}
|
|
229
|
+
/>
|
|
230
|
+
{/each}
|
|
231
|
+
<!-- 渲染第三份数据,确保视窗始终有足够内容 -->
|
|
232
|
+
{#each list as row, rowIndex}
|
|
233
|
+
<DataRow
|
|
234
|
+
data={row}
|
|
235
|
+
{columns}
|
|
236
|
+
rowIndex={rowIndex + list.length * 2}
|
|
237
|
+
showAlternative={(rowIndex + list.length * 2) % 2 == 1}
|
|
238
|
+
on:click={handleRowClick(row)}
|
|
239
|
+
/>
|
|
240
|
+
{/each}
|
|
241
|
+
{:else}
|
|
242
|
+
<!-- 正常模式:只渲染原始数据 -->
|
|
243
|
+
{#each list as row, rowIndex}
|
|
244
|
+
<DataRow
|
|
245
|
+
data={row}
|
|
246
|
+
{columns}
|
|
247
|
+
{rowIndex}
|
|
248
|
+
showAlternative={rowIndex % 2 == 1}
|
|
249
|
+
on:click={handleRowClick(row)}
|
|
250
|
+
/>
|
|
154
251
|
{/each}
|
|
155
252
|
{/if}
|
|
156
253
|
</div>
|
|
@@ -20,8 +20,15 @@ declare const ConciseListTable: $$__sveltets_2_IsomorphicComponent<{
|
|
|
20
20
|
scrollInterval?: number;
|
|
21
21
|
rowClickHandler?: RowClickHandler | null;
|
|
22
22
|
options: TableOptions;
|
|
23
|
+
style?: string;
|
|
24
|
+
className?: string;
|
|
25
|
+
onfocus?: ((event: FocusEvent) => void) | null;
|
|
26
|
+
onblur?: ((event: FocusEvent) => void) | null;
|
|
27
|
+
setFocus?: () => void;
|
|
23
28
|
}, {
|
|
24
29
|
[evt: string]: CustomEvent<any>;
|
|
25
|
-
}, {}, {
|
|
30
|
+
}, {}, {
|
|
31
|
+
setFocus: () => void;
|
|
32
|
+
}, string>;
|
|
26
33
|
type ConciseListTable = InstanceType<typeof ConciseListTable>;
|
|
27
34
|
export default ConciseListTable;
|
|
@@ -3,20 +3,19 @@
|
|
|
3
3
|
|
|
4
4
|
export let column: Column;
|
|
5
5
|
export let idx: number;
|
|
6
|
-
|
|
7
6
|
export let data: any;
|
|
8
7
|
|
|
9
8
|
let text: string;
|
|
10
9
|
let escapeHTML: boolean = false;
|
|
11
10
|
|
|
12
|
-
$: text = column.formatter ? column.formatter(data[column.field]) : data[column.field];
|
|
13
|
-
|
|
11
|
+
$: text = column.formatter ? column.formatter(data[column.field]) : (data[column.field] ?? '');
|
|
12
|
+
$: escapeHTML = column.escapeHTML ?? false;
|
|
14
13
|
</script>
|
|
15
14
|
|
|
16
|
-
<div class="data-cell col_{idx}">
|
|
15
|
+
<div class="data-cell col_{idx}" role="cell">
|
|
17
16
|
{#if escapeHTML}
|
|
18
|
-
{@html text}
|
|
19
|
-
{:else }
|
|
20
17
|
<span>{text}</span>
|
|
18
|
+
{:else }
|
|
19
|
+
{@html text}
|
|
21
20
|
{/if}
|
|
22
21
|
</div>
|
|
@@ -4,11 +4,31 @@
|
|
|
4
4
|
|
|
5
5
|
export let columns: Array<Column>;
|
|
6
6
|
export let data: any;
|
|
7
|
-
|
|
8
7
|
export let showAlternative: boolean;
|
|
8
|
+
export let rowIndex: number = 0;
|
|
9
|
+
|
|
10
|
+
const handleRowKeyDown = (event: KeyboardEvent) => {
|
|
11
|
+
if (event.key === 'Enter' || event.key === ' ') {
|
|
12
|
+
event.preventDefault();
|
|
13
|
+
// Trigger click event for keyboard users
|
|
14
|
+
const clickEvent = new MouseEvent('click', {
|
|
15
|
+
bubbles: true,
|
|
16
|
+
cancelable: true
|
|
17
|
+
});
|
|
18
|
+
event.currentTarget?.dispatchEvent(clickEvent);
|
|
19
|
+
}
|
|
20
|
+
};
|
|
9
21
|
</script>
|
|
10
22
|
|
|
11
|
-
<div
|
|
23
|
+
<div
|
|
24
|
+
class="table-row"
|
|
25
|
+
class:alternative={showAlternative}
|
|
26
|
+
role="row"
|
|
27
|
+
tabindex="0"
|
|
28
|
+
aria-rowindex={rowIndex + 2}
|
|
29
|
+
on:click
|
|
30
|
+
on:keydown={handleRowKeyDown}
|
|
31
|
+
>
|
|
12
32
|
{#each columns as column, idx}
|
|
13
33
|
<DataCell {idx} {column} {data}/>
|
|
14
34
|
{/each}
|