@ticatec/uniface-element 0.1.15 → 0.1.17
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/action-bar/ActionBar.svelte +2 -2
- package/dist/attachment-files/FileUploadBar.svelte +1 -1
- package/dist/attachment-files/FileUploadPanel.svelte +1 -1
- package/dist/base-calendar/CalendarBase.svelte +7 -3
- package/dist/base-calendar/CalendarBase.svelte.d.ts +0 -3
- package/dist/base-calendar/DateContext.d.ts +0 -9
- package/dist/base-calendar/DateContext.js +7 -68
- package/dist/base-calendar/index.d.ts +2 -2
- package/dist/base-calendar/index.js +2 -2
- package/dist/box/Box.svelte +11 -7
- package/dist/box/Box.svelte.d.ts +8 -3
- package/dist/checkbox/CheckBox.svelte +16 -7
- package/dist/checkbox/CheckBox.svelte.d.ts +1 -1
- package/dist/common/CommonPicker.svelte +14 -8
- package/dist/common/CommonPicker.svelte.d.ts +1 -1
- package/dist/common-editor/CommonEditor.svelte +17 -9
- package/dist/common-editor/CommonEditor.svelte.d.ts +2 -0
- package/dist/common-range-editor/CommonRangeEditor.svelte +8 -9
- package/dist/common-range-editor/CommonRangeEditor.svelte.d.ts +0 -2
- package/dist/criteria-field/CriteriaField.svelte +3 -2
- package/dist/criteria-field/CriteriaField.svelte.d.ts +1 -0
- package/dist/data-table/parts/ActionsPanel.svelte +2 -2
- package/dist/data-table/parts/FixedHeaderPanel.svelte +1 -1
- package/dist/date-picker/DateTimePicker.svelte +3 -7
- package/dist/date-range/DateRangeEditor.svelte +2 -2
- package/dist/dialog/Dialog.svelte +1 -1
- package/dist/form-field/FormField.svelte +9 -11
- package/dist/form-field/FormField.svelte.d.ts +2 -1
- package/dist/i18n_resources/index.d.ts +3 -0
- package/dist/i18n_resources/index.js +3 -0
- package/dist/i18n_resources/uniface_cn_resource.d.ts +29 -0
- package/dist/i18n_resources/uniface_cn_resource.js +37 -0
- package/dist/i18n_resources/uniface_en_resource.d.ts +29 -0
- package/dist/i18n_resources/uniface_en_resource.js +37 -0
- package/dist/input-options-select/InputOptionsSelect.svelte +105 -28
- package/dist/input-options-select/InputOptionsSelect.svelte.d.ts +2 -4
- package/dist/list-box/ListBox.svelte +81 -47
- package/dist/list-box/ListBox.svelte.d.ts +10 -16
- package/dist/message-box/IMessageBox.js +1 -1
- package/dist/nav-menu/NavigatorMenuItem.svelte +1 -1
- package/dist/options-multi-select/OptionsMultiSelect.svelte +1 -1
- package/dist/property-editor/PropertyEditor.svelte +1 -1
- package/dist/search-box/SearchBox.svelte +22 -15
- package/dist/search-box/SearchBox.svelte.d.ts +8 -4
- package/dist/text-editor/TextEditor.svelte +2 -3
- package/dist/ticatec-uniface-web.css +606 -583
- package/package.json +8 -7
- package/dist/UnifaceResource.d.ts +0 -43
- package/dist/UnifaceResource.js +0 -57
- package/dist/assets/arrow_down.svg +0 -1
- package/dist/assets/arrow_up.svg +0 -1
- package/dist/assets/calendar_icon.svg +0 -1
- package/dist/assets/delete_icon.svg +0 -1
- package/dist/assets/icon-dropdown.svg +0 -1
- package/dist/assets/icon_left.svg +0 -1
- package/dist/assets/icon_right.svg +0 -1
- package/dist/assets/pickup-options.svg +0 -1
- package/dist/assets/retry.png +0 -0
- package/dist/i18nContext.d.ts +0 -21
- package/dist/i18nContext.js +0 -29
|
@@ -5,18 +5,20 @@
|
|
|
5
5
|
export {className as class}
|
|
6
6
|
export let label: string = "Label:"
|
|
7
7
|
export let style: string = '';
|
|
8
|
-
export let label$style: string =
|
|
8
|
+
export let label$style: string | null = null;
|
|
9
9
|
export let required: boolean = false;
|
|
10
10
|
export let error: string = '';
|
|
11
11
|
export let arrangement: 'vertical' | 'horizontal' = 'vertical';
|
|
12
12
|
export let labelSuffix: string = ':';
|
|
13
13
|
|
|
14
|
+
export let label$alignment: 'center' | 'top' = 'center'
|
|
15
|
+
|
|
14
16
|
let className: string = '';
|
|
15
17
|
|
|
16
18
|
</script>
|
|
17
19
|
<div class="uniface-form-field {arrangement} {className}" {style}>
|
|
18
20
|
<div class="form-content" style="width: 100%">
|
|
19
|
-
<div class="field-label" style=
|
|
21
|
+
<div class="field-label" style={label$style} class:vert-top={arrangement== 'horizontal' && label$alignment=='top'}>
|
|
20
22
|
{#if required}
|
|
21
23
|
<span class="required-indicator">*</span>
|
|
22
24
|
{/if}
|
|
@@ -25,14 +27,10 @@
|
|
|
25
27
|
<div class="field">
|
|
26
28
|
<slot/>
|
|
27
29
|
</div>
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
<div class="form-content" style="width: 100%">
|
|
31
|
-
{#if arrangement == "horizontal"}
|
|
32
|
-
<div class="field-label" style={label$style}>
|
|
33
|
-
</div>
|
|
34
|
-
{/if}
|
|
30
|
+
{#if !utils.isEmpty(error)}
|
|
31
|
+
<div class="empty-field"></div>
|
|
35
32
|
<div class="field-hint"><span>{error}</span></div>
|
|
36
|
-
|
|
37
|
-
|
|
33
|
+
{/if}
|
|
34
|
+
</div>
|
|
35
|
+
|
|
38
36
|
</div>
|
|
@@ -20,11 +20,12 @@ declare const FormField: $$__sveltets_2_IsomorphicComponent<$$__sveltets_2_Props
|
|
|
20
20
|
class?: string;
|
|
21
21
|
label?: string;
|
|
22
22
|
style?: string;
|
|
23
|
-
label$style?: string;
|
|
23
|
+
label$style?: string | null;
|
|
24
24
|
required?: boolean;
|
|
25
25
|
error?: string;
|
|
26
26
|
arrangement?: "vertical" | "horizontal";
|
|
27
27
|
labelSuffix?: string;
|
|
28
|
+
label$alignment?: "center" | "top";
|
|
28
29
|
}, {
|
|
29
30
|
default: {};
|
|
30
31
|
}>, {
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
declare const langRes: {
|
|
2
|
+
uniface: {
|
|
3
|
+
btnClose: string;
|
|
4
|
+
btnCancel: string;
|
|
5
|
+
btnConfirm: string;
|
|
6
|
+
calendar: {
|
|
7
|
+
months: string[];
|
|
8
|
+
monthsAbbr: string[];
|
|
9
|
+
weekTitle: string[];
|
|
10
|
+
weekTitleAbbr: string[];
|
|
11
|
+
confirmText: string;
|
|
12
|
+
};
|
|
13
|
+
upload: {
|
|
14
|
+
btnCancel: string;
|
|
15
|
+
btnRetry: string;
|
|
16
|
+
btnRemove: string;
|
|
17
|
+
btnPickup: string;
|
|
18
|
+
};
|
|
19
|
+
propertyEditor: {
|
|
20
|
+
colName: string;
|
|
21
|
+
colValue: string;
|
|
22
|
+
};
|
|
23
|
+
dataTable: {
|
|
24
|
+
rowNo: string;
|
|
25
|
+
actions: string;
|
|
26
|
+
};
|
|
27
|
+
};
|
|
28
|
+
};
|
|
29
|
+
export default langRes;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
const langRes = {
|
|
2
|
+
uniface: {
|
|
3
|
+
btnClose: "关闭",
|
|
4
|
+
btnCancel: '取消',
|
|
5
|
+
btnConfirm: "确认",
|
|
6
|
+
calendar: {
|
|
7
|
+
months: [
|
|
8
|
+
'一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'
|
|
9
|
+
],
|
|
10
|
+
monthsAbbr: [
|
|
11
|
+
'一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'
|
|
12
|
+
],
|
|
13
|
+
weekTitle: [
|
|
14
|
+
"星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"
|
|
15
|
+
],
|
|
16
|
+
weekTitleAbbr: [
|
|
17
|
+
"日", "一", "二", "三", "四", "五", "六"
|
|
18
|
+
],
|
|
19
|
+
confirmText: "确认"
|
|
20
|
+
},
|
|
21
|
+
upload: {
|
|
22
|
+
btnCancel: '取消',
|
|
23
|
+
btnRetry: "重试",
|
|
24
|
+
btnRemove: "删除",
|
|
25
|
+
btnPickup: "选择文件"
|
|
26
|
+
},
|
|
27
|
+
propertyEditor: {
|
|
28
|
+
colName: "属性",
|
|
29
|
+
colValue: "值"
|
|
30
|
+
},
|
|
31
|
+
dataTable: {
|
|
32
|
+
rowNo: "序号",
|
|
33
|
+
actions: "操作"
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
export default langRes;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
declare const langRes: {
|
|
2
|
+
uniface: {
|
|
3
|
+
btnClose: string;
|
|
4
|
+
btnCancel: string;
|
|
5
|
+
btnConfirm: string;
|
|
6
|
+
calendar: {
|
|
7
|
+
months: string[];
|
|
8
|
+
monthsAbbr: string[];
|
|
9
|
+
weekTitle: string[];
|
|
10
|
+
weekTitleAbbr: string[];
|
|
11
|
+
confirmText: string;
|
|
12
|
+
};
|
|
13
|
+
upload: {
|
|
14
|
+
btnCancel: string;
|
|
15
|
+
btnRetry: string;
|
|
16
|
+
btnRemove: string;
|
|
17
|
+
btnPickup: string;
|
|
18
|
+
};
|
|
19
|
+
propertyEditor: {
|
|
20
|
+
colName: string;
|
|
21
|
+
colValue: string;
|
|
22
|
+
};
|
|
23
|
+
dataTable: {
|
|
24
|
+
rowNo: string;
|
|
25
|
+
actions: string;
|
|
26
|
+
};
|
|
27
|
+
};
|
|
28
|
+
};
|
|
29
|
+
export default langRes;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
const langRes = {
|
|
2
|
+
uniface: {
|
|
3
|
+
btnClose: "Close",
|
|
4
|
+
btnCancel: 'Cancel',
|
|
5
|
+
btnConfirm: "OK",
|
|
6
|
+
calendar: {
|
|
7
|
+
months: [
|
|
8
|
+
'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'
|
|
9
|
+
],
|
|
10
|
+
monthsAbbr: [
|
|
11
|
+
'Jan', 'Feb', 'Mar', 'Api', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'
|
|
12
|
+
],
|
|
13
|
+
weekTitle: [
|
|
14
|
+
"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"
|
|
15
|
+
],
|
|
16
|
+
weekTitleAbbr: [
|
|
17
|
+
"Sun", "Mon", "Tue", "Wed", "Thr", "Fri", "Sat"
|
|
18
|
+
],
|
|
19
|
+
confirmText: "OK"
|
|
20
|
+
},
|
|
21
|
+
upload: {
|
|
22
|
+
btnCancel: 'Cancel',
|
|
23
|
+
btnRetry: "Retry",
|
|
24
|
+
btnRemove: "Delete",
|
|
25
|
+
btnPickup: "Pickup files"
|
|
26
|
+
},
|
|
27
|
+
propertyEditor: {
|
|
28
|
+
colName: "Attribute",
|
|
29
|
+
colValue: "Value"
|
|
30
|
+
},
|
|
31
|
+
dataTable: {
|
|
32
|
+
rowNo: "Row#",
|
|
33
|
+
actions: "Actions"
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
export default langRes;
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
|
|
3
3
|
import {DisplayMode} from "../common/DisplayMode";
|
|
4
|
-
import Popover from "../common/Popover.svelte";
|
|
5
4
|
import type {OnChangeHandler} from "../common/OnChangeHandler";
|
|
6
|
-
import
|
|
5
|
+
import {tick} from "svelte";
|
|
6
|
+
import type {LazyLoader} from "../list-box/types"
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
import loading from "../assets/loading.gif"
|
|
9
|
+
import CommonPicker from "../common/CommonPicker.svelte";
|
|
10
|
+
import i18n from "@ticatec/i18n";
|
|
9
11
|
|
|
10
12
|
export let variant: '' | 'plain' | 'outlined' | 'filled' = '';
|
|
11
13
|
export let disabled: boolean = false;
|
|
@@ -13,7 +15,6 @@
|
|
|
13
15
|
export let compact: boolean = false;
|
|
14
16
|
export let text: string = '';
|
|
15
17
|
export let value: any = null;
|
|
16
|
-
export let options: Array<any> = [];
|
|
17
18
|
export let keyField: string = "code";
|
|
18
19
|
export let textField: string = "text";
|
|
19
20
|
export let menu$height: number = 0;
|
|
@@ -22,17 +23,69 @@
|
|
|
22
23
|
export let displayMode: DisplayMode = DisplayMode.Edit;
|
|
23
24
|
export let itemRender: any = null;
|
|
24
25
|
export let onChange: OnChangeHandler<any> = null as unknown as OnChangeHandler<any>;
|
|
25
|
-
export let
|
|
26
|
+
export let lazyLoader: LazyLoader;
|
|
26
27
|
|
|
27
28
|
let editor: any;
|
|
28
29
|
let inputText: string;
|
|
29
30
|
let oldValue: any = value;
|
|
31
|
+
let options: Array<any> = [];
|
|
32
|
+
let scrollElement: any;
|
|
33
|
+
|
|
34
|
+
let idleTime = 0;
|
|
35
|
+
let interval: any;
|
|
36
|
+
let pageNo: number;
|
|
37
|
+
let isBusy: boolean;
|
|
38
|
+
let hasMore: boolean;
|
|
39
|
+
|
|
40
|
+
const handleInputText = () => {
|
|
41
|
+
if ((text ?? '').trim().length > 0 && lazyLoader != null) {
|
|
42
|
+
if (interval == null) {
|
|
43
|
+
idleTime = 0;
|
|
44
|
+
interval = setInterval(delayReload, 50)
|
|
45
|
+
} else {
|
|
46
|
+
idleTime = 0;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
const lazyLoad = async (clean: boolean = true) => {
|
|
51
|
+
console.log('开始读取数据...', text)
|
|
52
|
+
isBusy = true;
|
|
53
|
+
try {
|
|
54
|
+
let result = await lazyLoader?.(text, pageNo);
|
|
55
|
+
if (result) {
|
|
56
|
+
if (clean) {
|
|
57
|
+
options = result.list;
|
|
58
|
+
} else {
|
|
59
|
+
options = [...options, ...result.list];
|
|
60
|
+
}
|
|
61
|
+
hasMore = result.hasMore;
|
|
62
|
+
}
|
|
63
|
+
showPopup = true;
|
|
64
|
+
} finally {
|
|
65
|
+
isBusy = false;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const delayReload = async () => {
|
|
70
|
+
idleTime++;
|
|
71
|
+
if (idleTime > 10) {
|
|
72
|
+
clearInterval(interval);
|
|
73
|
+
interval = null;
|
|
74
|
+
pageNo = 1;
|
|
75
|
+
if (showPopup) {
|
|
76
|
+
scrollElement.scrollTop = 0;
|
|
77
|
+
}
|
|
78
|
+
await lazyLoad();
|
|
79
|
+
await tick();
|
|
80
|
+
editor.focus();
|
|
81
|
+
}
|
|
82
|
+
}
|
|
30
83
|
|
|
31
84
|
const handleItemClick = (data: any) => () => {
|
|
32
85
|
value = data[keyField];
|
|
33
86
|
text = data[textField];
|
|
34
87
|
if (value != oldValue) {
|
|
35
|
-
onChange?.(
|
|
88
|
+
onChange?.(data);
|
|
36
89
|
}
|
|
37
90
|
editor.focus();
|
|
38
91
|
showPopup = false;
|
|
@@ -44,7 +97,7 @@
|
|
|
44
97
|
if (composing == false) {
|
|
45
98
|
text = inputText;
|
|
46
99
|
value = null;
|
|
47
|
-
|
|
100
|
+
handleInputText();
|
|
48
101
|
}
|
|
49
102
|
};
|
|
50
103
|
const handleCompositionStart = (event: CompositionEvent) => {
|
|
@@ -55,31 +108,39 @@
|
|
|
55
108
|
composing = false;
|
|
56
109
|
text = inputText;
|
|
57
110
|
value = null;
|
|
58
|
-
|
|
111
|
+
handleInputText();
|
|
59
112
|
};
|
|
60
113
|
|
|
61
|
-
const handleBlurEvent = (e: FocusEvent) => {
|
|
62
|
-
if (value == null) {
|
|
63
|
-
text = '';
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
114
|
const clean = () => {
|
|
68
115
|
value = null;
|
|
69
116
|
text = '';
|
|
70
117
|
onChange?.(value);
|
|
118
|
+
showPopup = false;
|
|
119
|
+
editor.focus();
|
|
71
120
|
}
|
|
72
121
|
|
|
73
122
|
let showPopup: boolean = false;
|
|
74
123
|
|
|
75
124
|
let mh;
|
|
76
125
|
|
|
77
|
-
$: mh = `height: ${menu$height > 0 ? menu$height + 'px' : 'auto'}`;
|
|
126
|
+
$: mh = `min-height: 80px; height: ${menu$height > 0 ? menu$height + 'px' : 'auto'}`;
|
|
78
127
|
|
|
79
128
|
$: showPopup = options && options.length > 0;
|
|
80
129
|
|
|
81
130
|
$: inputText = text;
|
|
82
131
|
|
|
132
|
+
const loadMore = async () => {
|
|
133
|
+
editor.focus();
|
|
134
|
+
if (lazyLoader && !isBusy && hasMore) {
|
|
135
|
+
pageNo++;
|
|
136
|
+
await lazyLoad(false);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
$: if (!showPopup && value == null) {
|
|
141
|
+
text = '';
|
|
142
|
+
}
|
|
143
|
+
|
|
83
144
|
|
|
84
145
|
</script>
|
|
85
146
|
<!-- 待解决浏览模式显示的问题 -->
|
|
@@ -87,21 +148,37 @@
|
|
|
87
148
|
<CommonPicker {displayMode} {variant} {style} {compact}
|
|
88
149
|
bind:showPopup canClean={value!=null} autoFit {clean} textValue={text} {readonly} {disabled}>
|
|
89
150
|
<input style="width: 100%" bind:this={editor} {placeholder}
|
|
90
|
-
class="text-editor" bind:value={inputText} {
|
|
151
|
+
class="text-editor" bind:value={inputText} readonly={isBusy}
|
|
91
152
|
on:input={handleInput}
|
|
92
|
-
on:compositionstart={handleCompositionStart} on:compositionend={handleCompositionEnd}
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
153
|
+
on:compositionstart={handleCompositionStart} on:compositionend={handleCompositionEnd}/>
|
|
154
|
+
{#if isBusy}
|
|
155
|
+
<div style="position: absolute; top: 0px; bottom: 0px; right: 8px">
|
|
156
|
+
<div style="position: relative; top: 50%; transform: translateY(-50%)">
|
|
157
|
+
<img src={loading} width="16" height="16"/>
|
|
158
|
+
</div>
|
|
159
|
+
</div>
|
|
160
|
+
{/if}
|
|
161
|
+
<div class="options-popover" bind:this={scrollElement} style={mh} slot="popup-panel">
|
|
96
162
|
{#each options as op}
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
163
|
+
<div class="option-item" on:click={handleItemClick(op)} aria-hidden="true">
|
|
164
|
+
{#if itemRender != null}
|
|
165
|
+
<svelte:component this={itemRender} item={op}/>
|
|
166
|
+
{:else}
|
|
167
|
+
<div style="padding: 6px 8px">
|
|
168
|
+
<span>{op[textField]}</span>
|
|
169
|
+
</div>
|
|
170
|
+
{/if}
|
|
171
|
+
</div>
|
|
105
172
|
{/each}
|
|
173
|
+
{#if hasMore}
|
|
174
|
+
<div class="more-indicator-footer" on:click={loadMore}>
|
|
175
|
+
{i18n.getText('uniface.loadMore', 'Load more')}
|
|
176
|
+
</div>
|
|
177
|
+
{/if}
|
|
178
|
+
{#if isBusy}
|
|
179
|
+
<div class="popover-mask-overlay">
|
|
180
|
+
|
|
181
|
+
</div>
|
|
182
|
+
{/if}
|
|
106
183
|
</div>
|
|
107
184
|
</CommonPicker>
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { DisplayMode } from "../common/DisplayMode";
|
|
2
2
|
import type { OnChangeHandler } from "../common/OnChangeHandler";
|
|
3
|
+
import type { LazyLoader } from "../list-box/types";
|
|
3
4
|
interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
|
|
4
5
|
new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
|
|
5
6
|
$$bindings?: Bindings;
|
|
@@ -20,7 +21,6 @@ declare const InputOptionsSelect: $$__sveltets_2_IsomorphicComponent<{
|
|
|
20
21
|
compact?: boolean;
|
|
21
22
|
text?: string;
|
|
22
23
|
value?: any;
|
|
23
|
-
options?: Array<any>;
|
|
24
24
|
keyField?: string;
|
|
25
25
|
textField?: string;
|
|
26
26
|
menu$height?: number;
|
|
@@ -29,10 +29,8 @@ declare const InputOptionsSelect: $$__sveltets_2_IsomorphicComponent<{
|
|
|
29
29
|
displayMode?: DisplayMode;
|
|
30
30
|
itemRender?: any;
|
|
31
31
|
onChange?: OnChangeHandler<any>;
|
|
32
|
-
|
|
32
|
+
lazyLoader: LazyLoader;
|
|
33
33
|
}, {
|
|
34
|
-
focus: FocusEvent;
|
|
35
|
-
} & {
|
|
36
34
|
[evt: string]: CustomEvent<any>;
|
|
37
35
|
}, {}, {}, string>;
|
|
38
36
|
type InputOptionsSelect = InstanceType<typeof InputOptionsSelect>;
|
|
@@ -1,30 +1,36 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import {onMount} from "svelte";
|
|
2
|
+
import {onMount, tick} from "svelte";
|
|
3
3
|
import SearchBox from "../search-box"
|
|
4
4
|
import type {FunFilter} from "./types";
|
|
5
5
|
import type {LazyLoader} from "./types";
|
|
6
6
|
import CheckBox from "../checkbox/CheckBox.svelte";
|
|
7
|
+
import Box from "../box";
|
|
8
|
+
import loading from "../assets/loading.gif"
|
|
7
9
|
|
|
8
10
|
let className: string = '';
|
|
9
11
|
|
|
10
12
|
type OnSelectChange = (item: any) => void;
|
|
11
13
|
type OnItemDblClick = (item: any) => void;
|
|
12
14
|
|
|
13
|
-
export let readonly:boolean = false;
|
|
14
|
-
export let style: string =
|
|
15
|
-
export let header$style: string =
|
|
16
|
-
export let list:Array<any>;
|
|
15
|
+
export let readonly: boolean = false;
|
|
16
|
+
export let style: string | null = null;
|
|
17
|
+
export let header$style: string | null = null;
|
|
18
|
+
export let list: Array<any>;
|
|
17
19
|
export let itemRender: any;
|
|
18
20
|
export let selectMode: 'none' | 'single' | 'multiple' = 'none';
|
|
19
|
-
export let filter: FunFilter | null;
|
|
21
|
+
export let filter: FunFilter | null = null;
|
|
20
22
|
export let lazyLoader: LazyLoader | null = null;
|
|
21
23
|
export let selectedItem: any = null;
|
|
22
24
|
export let selectedList: Array<any> = [];
|
|
23
25
|
export {className as class};
|
|
24
26
|
export let item$props: any = null;
|
|
25
|
-
export let onSelectChange: OnSelectChange= null as unknown as OnSelectChange;
|
|
27
|
+
export let onSelectChange: OnSelectChange = null as unknown as OnSelectChange;
|
|
26
28
|
export let onItemDblClick: OnItemDblClick = null as unknown as OnItemDblClick;
|
|
27
29
|
|
|
30
|
+
export let title: string = null as unknown as string;
|
|
31
|
+
export let round: boolean = false;
|
|
32
|
+
export let footer$style: string | null = null;
|
|
33
|
+
|
|
28
34
|
let filterText: string;
|
|
29
35
|
let hasMore: boolean;
|
|
30
36
|
let isBusy: boolean = false;
|
|
@@ -32,8 +38,8 @@
|
|
|
32
38
|
|
|
33
39
|
let filteredList: Array<any>;
|
|
34
40
|
|
|
35
|
-
const handleItemClick = (item:any) => (e: MouseEvent) => {
|
|
36
|
-
if (selectMode == 'single' && readonly==false) {
|
|
41
|
+
const handleItemClick = (item: any) => (e: MouseEvent) => {
|
|
42
|
+
if (selectMode == 'single' && readonly == false) {
|
|
37
43
|
if (selectedItem != item) {
|
|
38
44
|
selectedItem = item;
|
|
39
45
|
onSelectChange?.(item);
|
|
@@ -41,14 +47,14 @@
|
|
|
41
47
|
}
|
|
42
48
|
}
|
|
43
49
|
|
|
44
|
-
const handleItemDblClick = (item:any) => (e: MouseEvent) => {
|
|
50
|
+
const handleItemDblClick = (item: any) => (e: MouseEvent) => {
|
|
45
51
|
if (selectMode == 'single') {
|
|
46
52
|
onItemDblClick?.(item);
|
|
47
53
|
}
|
|
48
54
|
}
|
|
49
55
|
|
|
50
56
|
const doFilter = () => {
|
|
51
|
-
const newList:Array<any> = [];
|
|
57
|
+
const newList: Array<any> = [];
|
|
52
58
|
list.forEach(item => {
|
|
53
59
|
if (filter?.(item, filterText)) {
|
|
54
60
|
newList.push(item)
|
|
@@ -62,6 +68,7 @@
|
|
|
62
68
|
}
|
|
63
69
|
|
|
64
70
|
const lazyLoad = async (clean: boolean = true) => {
|
|
71
|
+
console.log('加载数据...')
|
|
65
72
|
isBusy = true;
|
|
66
73
|
try {
|
|
67
74
|
let result = await lazyLoader?.(filterText, pageNo);
|
|
@@ -71,18 +78,40 @@
|
|
|
71
78
|
} else {
|
|
72
79
|
list = [...list, ...result.list];
|
|
73
80
|
}
|
|
81
|
+
selectedItem = null;
|
|
74
82
|
filteredList = list;
|
|
75
83
|
hasMore = result.hasMore;
|
|
84
|
+
console.log('加载数据完成')
|
|
76
85
|
}
|
|
77
86
|
} finally {
|
|
78
87
|
isBusy = false;
|
|
79
88
|
}
|
|
80
89
|
}
|
|
81
90
|
|
|
82
|
-
|
|
83
|
-
|
|
91
|
+
let idleTime = 0;
|
|
92
|
+
const delayReload = async () => {
|
|
93
|
+
idleTime ++;
|
|
94
|
+
if (idleTime > 10) {
|
|
95
|
+
clearInterval(interval);
|
|
96
|
+
interval = null;
|
|
84
97
|
pageNo = 1;
|
|
85
|
-
|
|
98
|
+
scrollElement.scrollTop = 0;
|
|
99
|
+
await lazyLoad();
|
|
100
|
+
await tick();
|
|
101
|
+
searchBox.focus();
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
let interval: any;
|
|
106
|
+
const handleCriteriaChange = () => {
|
|
107
|
+
if (lazyLoader != null) {
|
|
108
|
+
if (interval == null) {
|
|
109
|
+
idleTime = 0;
|
|
110
|
+
interval = setInterval(delayReload, 50)
|
|
111
|
+
} else {
|
|
112
|
+
idleTime = 0;
|
|
113
|
+
}
|
|
114
|
+
|
|
86
115
|
} else {
|
|
87
116
|
if (filterText.length > 0) {
|
|
88
117
|
doFilter();
|
|
@@ -100,22 +129,20 @@
|
|
|
100
129
|
}
|
|
101
130
|
}
|
|
102
131
|
|
|
103
|
-
const handleSelectionChanged = (item: any) => (
|
|
132
|
+
const handleSelectionChanged = (item: any) => () => {
|
|
133
|
+
console.log('选择项目', item);
|
|
104
134
|
let idx = selectedList.indexOf(item);
|
|
105
|
-
if (
|
|
106
|
-
|
|
107
|
-
selectedList = [...selectedList, item];
|
|
108
|
-
}
|
|
135
|
+
if (idx < 0) {
|
|
136
|
+
selectedList = [...selectedList, item];
|
|
109
137
|
} else {
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
selectedList = [...selectedList];
|
|
113
|
-
}
|
|
138
|
+
selectedList.splice(idx, 1);
|
|
139
|
+
selectedList = [...selectedList];
|
|
114
140
|
}
|
|
115
141
|
}
|
|
116
142
|
|
|
117
143
|
onMount(async () => {
|
|
118
144
|
if (lazyLoader != null) {
|
|
145
|
+
console.log('加载数据...')
|
|
119
146
|
filterText = '';
|
|
120
147
|
await lazyLoad();
|
|
121
148
|
}
|
|
@@ -126,7 +153,8 @@
|
|
|
126
153
|
await lazyLoad(false);
|
|
127
154
|
}
|
|
128
155
|
|
|
129
|
-
let scrollElement:any;
|
|
156
|
+
let scrollElement: any;
|
|
157
|
+
let searchBox: any;
|
|
130
158
|
|
|
131
159
|
const handleScroll = () => {
|
|
132
160
|
const bottom = scrollElement.scrollHeight - scrollElement.scrollTop === scrollElement.clientHeight;
|
|
@@ -135,27 +163,36 @@
|
|
|
135
163
|
}
|
|
136
164
|
}
|
|
137
165
|
|
|
166
|
+
$: boxHeaderStyle = `${header$style ?? ''}; height: auto; ${($$slots.header || filter || lazyLoader || title) ? '' : 'display: none'}`
|
|
138
167
|
|
|
139
168
|
</script>
|
|
140
169
|
|
|
141
|
-
<
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
170
|
+
<Box class="uniface-listbox {className}" {round} {footer$style} {style} showFooter={$$slots.footer!=null}
|
|
171
|
+
header$style={boxHeaderStyle}>
|
|
172
|
+
<svelte:fragment slot="header">
|
|
173
|
+
{#if title || $$slots['header']}
|
|
174
|
+
<slot name="header">
|
|
175
|
+
<div class="title">
|
|
176
|
+
<span>{title}</span>
|
|
177
|
+
</div>
|
|
178
|
+
</slot>
|
|
179
|
+
{/if}
|
|
180
|
+
{#if readonly === false && (filter || lazyLoader)}
|
|
181
|
+
<div class="header-search">
|
|
182
|
+
<SearchBox bind:this={searchBox} compact variant="plain" disabled={isBusy} style="width: 100%" bind:value={filterText} onChange={handleCriteriaChange}/>
|
|
183
|
+
</div>
|
|
184
|
+
{/if}
|
|
185
|
+
</svelte:fragment>
|
|
152
186
|
<div class="listbox-content" class:selectable={selectMode==='single'} bind:this={scrollElement} on:scroll={handleScroll}>
|
|
153
187
|
{#if filteredList && itemRender}
|
|
154
188
|
{#each filteredList as item}
|
|
155
189
|
{#if selectMode === "multiple"}
|
|
156
|
-
<div class="listview-item" style="display: flex; flex-direction: row; align-items: center">
|
|
157
|
-
<CheckBox style="flex: 0 0 auto
|
|
158
|
-
|
|
190
|
+
<div class="listview-item" style="display: flex; flex-direction: row; align-items: center; gap: 8px">
|
|
191
|
+
<CheckBox style="flex: 0 0 auto" {readonly} value={selectedList.indexOf(item) > -1}
|
|
192
|
+
onChange={handleSelectionChanged(item)}/>
|
|
193
|
+
<div style="flex: 1 1 auto; cursor: pointer" aria-hidden="true" on:click={handleSelectionChanged(item)}>
|
|
194
|
+
<svelte:component this={itemRender} {readonly} {item} {...item$props}/>
|
|
195
|
+
</div>
|
|
159
196
|
</div>
|
|
160
197
|
{:else }
|
|
161
198
|
<div class="listview-item" class:selected={item===selectedItem} aria-hidden="true"
|
|
@@ -166,19 +203,16 @@
|
|
|
166
203
|
{/if}
|
|
167
204
|
{/each}
|
|
168
205
|
{/if}
|
|
169
|
-
<slot></slot>
|
|
170
206
|
{#if hasMore}
|
|
171
207
|
<slot name="loadMoreIndicator"></slot>
|
|
172
208
|
{/if}
|
|
173
209
|
</div>
|
|
174
|
-
|
|
175
|
-
<div class="listbox-footer">
|
|
176
|
-
<slot name="footer"></slot>
|
|
177
|
-
</div>
|
|
178
|
-
{/if}
|
|
210
|
+
<slot name="footer" slot="footer"/>
|
|
179
211
|
{#if isBusy}
|
|
180
|
-
<div class="
|
|
181
|
-
|
|
212
|
+
<div class="list-view-mask">
|
|
213
|
+
<div style="height: 100%; height: 100%; text-align: center">
|
|
214
|
+
<img width="48" height="48" style="position: relative; top: 50%; transform: translateY(-50%)" src={loading} alt="nothing">
|
|
215
|
+
</div>
|
|
182
216
|
</div>
|
|
183
217
|
{/if}
|
|
184
|
-
</
|
|
218
|
+
</Box>
|