@ticatec/uniface-element 0.2.0 → 0.2.1
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/README.md +273 -1
- package/README_CN.md +341 -0
- package/dist/common/MouseClickHandler.d.ts +1 -1
- package/dist/dialog/CommonDialog.svelte +6 -3
- package/dist/dialog/CommonDialog.svelte.d.ts +2 -1
- package/dist/dialog/Dialog.svelte +36 -10
- package/dist/dialog/Dialog.svelte.d.ts +4 -3
- package/dist/dialog/DialogBoard.svelte +11 -8
- package/dist/dialog/DialogWrapper.svelte +10 -0
- package/dist/dialog/DialogWrapper.svelte.d.ts +22 -0
- package/dist/dialog/Dialogs.js +1 -1
- package/dist/dialog/ModalResult.d.ts +5 -0
- package/dist/dialog/ModalResult.js +5 -0
- package/docs/buttons/cn/ActionBar.md +459 -0
- package/docs/buttons/cn/Button.md +228 -0
- package/docs/buttons/cn/IconButton.md +294 -0
- package/docs/buttons/cn/README.md +600 -0
- package/docs/buttons/cn/TextButton.md +163 -0
- package/docs/buttons/en/ActionBar.md +459 -0
- package/docs/buttons/en/Button.md +228 -0
- package/docs/buttons/en/IconButton.md +294 -0
- package/docs/buttons/en/README.md +600 -0
- package/docs/buttons/en/TextButton.md +163 -0
- package/docs/containers/cn/accordion.md +622 -0
- package/docs/containers/cn/box.md +445 -0
- package/docs/containers/cn/card.md +404 -0
- package/docs/containers/cn/page.md +576 -0
- package/docs/containers/cn/tabs.md +686 -0
- package/docs/containers/en/accordion.md +622 -0
- package/docs/containers/en/box.md +445 -0
- package/docs/containers/en/card.md +404 -0
- package/docs/containers/en/page.md +576 -0
- package/docs/containers/en/tabs.md +686 -0
- package/docs/data-display/cn/concise-data-table.md +731 -0
- package/docs/data-display/cn/listbox.md +786 -0
- package/docs/data-display/cn/treeview.md +863 -0
- package/docs/data-display/en/concise-data-table.md +732 -0
- package/docs/data-display/en/listbox.md +786 -0
- package/docs/data-display/en/treeview.md +863 -0
- package/docs/data-table/cn/README.md +596 -0
- package/docs/data-table/en/README.md +596 -0
- package/docs/dialog/cn/README.md +767 -0
- package/docs/dialog/en/README.md +767 -0
- package/docs/form/cn/README.md +847 -0
- package/docs/form/en/README.md +847 -0
- package/docs/form-components/cn/README.md +495 -0
- package/docs/form-components/cn/attachmentfilesfield.md +757 -0
- package/docs/form-components/cn/cascade-options-select.md +374 -0
- package/docs/form-components/cn/checkbox.md +58 -0
- package/docs/form-components/cn/date-picker.md +138 -0
- package/docs/form-components/cn/datetime-picker.md +228 -0
- package/docs/form-components/cn/group-checkbox.md +405 -0
- package/docs/form-components/cn/group-radiobox.md +525 -0
- package/docs/form-components/cn/imagefilesfield.md +651 -0
- package/docs/form-components/cn/input-options-select.md +250 -0
- package/docs/form-components/cn/lookup-editor.md +406 -0
- package/docs/form-components/cn/memoeditor.md +409 -0
- package/docs/form-components/cn/number-editor.md +261 -0
- package/docs/form-components/cn/options-multi-select.md +177 -0
- package/docs/form-components/cn/options-select.md +83 -0
- package/docs/form-components/cn/passwordeditor.md +538 -0
- package/docs/form-components/cn/prompts-text-editor.md +241 -0
- package/docs/form-components/cn/radiobutton.md +84 -0
- package/docs/form-components/cn/switch.md +178 -0
- package/docs/form-components/cn/text-editor.md +142 -0
- package/docs/form-components/cn/time-editor.md +159 -0
- package/docs/form-components/cn/unit-number-editor.md +164 -0
- package/docs/form-components/en/README.md +463 -0
- package/docs/form-components/en/attachmentfilesfield.md +757 -0
- package/docs/form-components/en/cascade-options-select.md +358 -0
- package/docs/form-components/en/checkbox.md +59 -0
- package/docs/form-components/en/date-picker.md +138 -0
- package/docs/form-components/en/datetime-picker.md +228 -0
- package/docs/form-components/en/group-checkbox.md +395 -0
- package/docs/form-components/en/group-radiobox.md +498 -0
- package/docs/form-components/en/imagefilesfield.md +651 -0
- package/docs/form-components/en/input-options-select.md +239 -0
- package/docs/form-components/en/lookup-editor.md +389 -0
- package/docs/form-components/en/memoeditor.md +409 -0
- package/docs/form-components/en/number-editor.md +249 -0
- package/docs/form-components/en/options-multi-select.md +177 -0
- package/docs/form-components/en/options-select.md +83 -0
- package/docs/form-components/en/passwordeditor.md +538 -0
- package/docs/form-components/en/prompts-text-editor.md +241 -0
- package/docs/form-components/en/radiobutton.md +84 -0
- package/docs/form-components/en/switch.md +180 -0
- package/docs/form-components/en/text-editor.md +142 -0
- package/docs/form-components/en/time-editor.md +159 -0
- package/docs/form-components/en/unit-number-editor.md +164 -0
- package/docs/form-layout/cn/criteria-field.md +652 -0
- package/docs/form-layout/cn/flex-form.md +454 -0
- package/docs/form-layout/cn/flex-row-form.md +542 -0
- package/docs/form-layout/cn/form-field.md +923 -0
- package/docs/form-layout/cn/grid-form.md +676 -0
- package/docs/form-layout/en/criteria-field.md +652 -0
- package/docs/form-layout/en/flex-form.md +454 -0
- package/docs/form-layout/en/flex-row-form.md +542 -0
- package/docs/form-layout/en/form-field.md +923 -0
- package/docs/form-layout/en/grid-form.md +676 -0
- package/docs/global/cn/README.md +534 -0
- package/docs/global/en/README.md +534 -0
- package/docs/layout/cn/classiclayout.md +460 -0
- package/docs/layout/cn/headerlayout.md +524 -0
- package/docs/layout/cn/sidebarlayout.md +263 -0
- package/docs/layout/en/classiclayout.md +951 -0
- package/docs/layout/en/headerlayout.md +524 -0
- package/docs/layout/en/sidebarlayout.md +262 -0
- package/docs/misc/cn/README.md +1217 -0
- package/docs/misc/en/README.md +1217 -0
- package/docs/navigation/cn/breadcrumb.md +291 -0
- package/docs/navigation/cn/navigator.md +322 -0
- package/docs/navigation/cn/navigatormenu.md +512 -0
- package/docs/navigation/cn/progressbar.md +199 -0
- package/docs/navigation/cn/progressstepbar.md +299 -0
- package/docs/navigation/en/breadcrumb.md +291 -0
- package/docs/navigation/en/navigator.md +322 -0
- package/docs/navigation/en/navigatormenu.md +512 -0
- package/docs/navigation/en/progressbar.md +199 -0
- package/docs/navigation/en/progressstepbar.md +299 -0
- package/docs/search-filters/cn/daterange.md +1156 -0
- package/docs/search-filters/cn/numberrange.md +688 -0
- package/docs/search-filters/cn/searchbox.md +1582 -0
- package/docs/search-filters/en/daterange.md +1156 -0
- package/docs/search-filters/en/numberrange.md +688 -0
- package/docs/search-filters/en/searchbox.md +1582 -0
- package/package.json +38 -5
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
# PromptsTextEditor 组件
|
|
2
|
+
|
|
3
|
+
带自动完成提示的文本输入组件。
|
|
4
|
+
|
|
5
|
+
## 属性
|
|
6
|
+
|
|
7
|
+
| 属性 | 类型 | 默认值 | 描述 |
|
|
8
|
+
|------|------|--------|------|
|
|
9
|
+
| `variant` | `'' \| 'plain' \| 'outlined' \| 'filled'` | `''` | 外观变体 |
|
|
10
|
+
| `disabled` | `boolean` | `false` | 是否禁用 |
|
|
11
|
+
| `readonly` | `boolean` | `false` | 是否只读 |
|
|
12
|
+
| `compact` | `boolean` | `false` | 是否紧凑模式 |
|
|
13
|
+
| `value` | `string` | `''` | 输入值 |
|
|
14
|
+
| `placeholder` | `string` | `''` | 占位符文本 |
|
|
15
|
+
| `displayMode` | `DisplayMode` | `DisplayMode.Edit` | 显示模式 |
|
|
16
|
+
| `prompts` | `Array<string>` | `[]` | 提示选项数组 |
|
|
17
|
+
| `maxPrompts` | `number` | `10` | 最大显示提示数量 |
|
|
18
|
+
| `minChars` | `number` | `1` | 触发提示的最小字符数 |
|
|
19
|
+
| `caseSensitive` | `boolean` | `false` | 是否区分大小写 |
|
|
20
|
+
| `style` | `string` | `''` | 自定义样式 |
|
|
21
|
+
| `onChange` | `OnChangeHandler<string>` | - | 值变化回调 |
|
|
22
|
+
|
|
23
|
+
## 使用示例
|
|
24
|
+
|
|
25
|
+
```svelte
|
|
26
|
+
<script lang="ts">
|
|
27
|
+
import PromptsTextEditor from '@ticatec/uniface-element/PromptsTextEditor';
|
|
28
|
+
|
|
29
|
+
// 邮箱域名提示
|
|
30
|
+
const emailDomains: string[] = [
|
|
31
|
+
'gmail.com',
|
|
32
|
+
'qq.com',
|
|
33
|
+
'163.com',
|
|
34
|
+
'126.com',
|
|
35
|
+
'hotmail.com',
|
|
36
|
+
'yahoo.com',
|
|
37
|
+
'outlook.com',
|
|
38
|
+
'sina.com'
|
|
39
|
+
];
|
|
40
|
+
|
|
41
|
+
// 城市名称提示
|
|
42
|
+
const cities: string[] = [
|
|
43
|
+
'北京市',
|
|
44
|
+
'上海市',
|
|
45
|
+
'广州市',
|
|
46
|
+
'深圳市',
|
|
47
|
+
'杭州市',
|
|
48
|
+
'南京市',
|
|
49
|
+
'成都市',
|
|
50
|
+
'武汉市',
|
|
51
|
+
'西安市',
|
|
52
|
+
'重庆市'
|
|
53
|
+
];
|
|
54
|
+
|
|
55
|
+
let email: string = '';
|
|
56
|
+
let city: string = '';
|
|
57
|
+
|
|
58
|
+
const handleEmailChange = (value: string): void => {
|
|
59
|
+
email = value;
|
|
60
|
+
console.log('邮箱:', value);
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
const handleCityChange = (value: string): void => {
|
|
64
|
+
city = value;
|
|
65
|
+
console.log('城市:', value);
|
|
66
|
+
};
|
|
67
|
+
</script>
|
|
68
|
+
|
|
69
|
+
<!-- 邮箱输入(域名提示) -->
|
|
70
|
+
<PromptsTextEditor
|
|
71
|
+
placeholder="请输入邮箱地址"
|
|
72
|
+
prompts={emailDomains}
|
|
73
|
+
bind:value={email}
|
|
74
|
+
onChange={handleEmailChange}
|
|
75
|
+
/>
|
|
76
|
+
|
|
77
|
+
<!-- 城市输入(自动完成) -->
|
|
78
|
+
<PromptsTextEditor
|
|
79
|
+
placeholder="请输入城市名称"
|
|
80
|
+
prompts={cities}
|
|
81
|
+
minChars={1}
|
|
82
|
+
maxPrompts={5}
|
|
83
|
+
bind:value={city}
|
|
84
|
+
onChange={handleCityChange}
|
|
85
|
+
/>
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## 高级用法
|
|
89
|
+
|
|
90
|
+
### 动态提示
|
|
91
|
+
```svelte
|
|
92
|
+
<script lang="ts">
|
|
93
|
+
import { onMount } from 'svelte';
|
|
94
|
+
|
|
95
|
+
let searchValue: string = '';
|
|
96
|
+
let dynamicPrompts: string[] = [];
|
|
97
|
+
let isLoading: boolean = false;
|
|
98
|
+
|
|
99
|
+
// 从API获取提示
|
|
100
|
+
const fetchPrompts = async (query: string): Promise<string[]> => {
|
|
101
|
+
if (query.length < 2) return [];
|
|
102
|
+
|
|
103
|
+
isLoading = true;
|
|
104
|
+
try {
|
|
105
|
+
const response = await fetch(`/api/suggestions?q=${encodeURIComponent(query)}`);
|
|
106
|
+
const data = await response.json();
|
|
107
|
+
return data.suggestions || [];
|
|
108
|
+
} catch (error) {
|
|
109
|
+
console.error('获取提示失败:', error);
|
|
110
|
+
return [];
|
|
111
|
+
} finally {
|
|
112
|
+
isLoading = false;
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
// 防抖更新提示
|
|
117
|
+
let debounceTimeout: number;
|
|
118
|
+
const updatePrompts = (value: string): void => {
|
|
119
|
+
clearTimeout(debounceTimeout);
|
|
120
|
+
debounceTimeout = setTimeout(async () => {
|
|
121
|
+
dynamicPrompts = await fetchPrompts(value);
|
|
122
|
+
}, 300);
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
const handleSearchChange = (value: string): void => {
|
|
126
|
+
searchValue = value;
|
|
127
|
+
updatePrompts(value);
|
|
128
|
+
};
|
|
129
|
+
</script>
|
|
130
|
+
|
|
131
|
+
<PromptsTextEditor
|
|
132
|
+
placeholder="搜索产品..."
|
|
133
|
+
prompts={dynamicPrompts}
|
|
134
|
+
minChars={2}
|
|
135
|
+
maxPrompts={8}
|
|
136
|
+
bind:value={searchValue}
|
|
137
|
+
onChange={handleSearchChange}
|
|
138
|
+
/>
|
|
139
|
+
|
|
140
|
+
{#if isLoading}
|
|
141
|
+
<div class="loading-hint">正在获取建议...</div>
|
|
142
|
+
{/if}
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
### 标签输入
|
|
146
|
+
```svelte
|
|
147
|
+
<script lang="ts">
|
|
148
|
+
const availableTags: string[] = [
|
|
149
|
+
'JavaScript',
|
|
150
|
+
'TypeScript',
|
|
151
|
+
'Svelte',
|
|
152
|
+
'Vue.js',
|
|
153
|
+
'React',
|
|
154
|
+
'Node.js',
|
|
155
|
+
'Python',
|
|
156
|
+
'Java',
|
|
157
|
+
'Go',
|
|
158
|
+
'Rust'
|
|
159
|
+
];
|
|
160
|
+
|
|
161
|
+
let tagInput: string = '';
|
|
162
|
+
let selectedTags: string[] = [];
|
|
163
|
+
|
|
164
|
+
const handleTagInput = (value: string): void => {
|
|
165
|
+
tagInput = value;
|
|
166
|
+
|
|
167
|
+
// 检查是否输入了分隔符
|
|
168
|
+
if (value.includes(',') || value.includes(';')) {
|
|
169
|
+
const newTags = value.split(/[,;]/).map(tag => tag.trim()).filter(Boolean);
|
|
170
|
+
|
|
171
|
+
newTags.forEach(tag => {
|
|
172
|
+
if (tag && !selectedTags.includes(tag)) {
|
|
173
|
+
selectedTags = [...selectedTags, tag];
|
|
174
|
+
}
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
tagInput = ''; // 清空输入
|
|
178
|
+
}
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
const removeTag = (tagToRemove: string): void => {
|
|
182
|
+
selectedTags = selectedTags.filter(tag => tag !== tagToRemove);
|
|
183
|
+
};
|
|
184
|
+
|
|
185
|
+
// 过滤已选择的标签
|
|
186
|
+
$: filteredPrompts = availableTags.filter(tag =>
|
|
187
|
+
!selectedTags.includes(tag) &&
|
|
188
|
+
tag.toLowerCase().includes(tagInput.toLowerCase())
|
|
189
|
+
);
|
|
190
|
+
</script>
|
|
191
|
+
|
|
192
|
+
<div class="tag-input-container">
|
|
193
|
+
<!-- 已选择的标签 -->
|
|
194
|
+
<div class="selected-tags">
|
|
195
|
+
{#each selectedTags as tag}
|
|
196
|
+
<span class="tag">
|
|
197
|
+
{tag}
|
|
198
|
+
<button type="button" on:click={() => removeTag(tag)}>×</button>
|
|
199
|
+
</span>
|
|
200
|
+
{/each}
|
|
201
|
+
</div>
|
|
202
|
+
|
|
203
|
+
<!-- 标签输入 -->
|
|
204
|
+
<PromptsTextEditor
|
|
205
|
+
placeholder="输入标签名称..."
|
|
206
|
+
prompts={filteredPrompts}
|
|
207
|
+
bind:value={tagInput}
|
|
208
|
+
onChange={handleTagInput}
|
|
209
|
+
minChars={1}
|
|
210
|
+
maxPrompts={6}
|
|
211
|
+
/>
|
|
212
|
+
|
|
213
|
+
<div class="tag-hint">使用逗号或分号分隔多个标签</div>
|
|
214
|
+
</div>
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
## 最佳实践
|
|
218
|
+
|
|
219
|
+
### 1. 合理设置触发条件
|
|
220
|
+
```svelte
|
|
221
|
+
<!-- 短词汇:1个字符触发 -->
|
|
222
|
+
<PromptsTextEditor minChars={1} prompts={shortWords} />
|
|
223
|
+
|
|
224
|
+
<!-- 长词汇或搜索:2-3个字符触发 -->
|
|
225
|
+
<PromptsTextEditor minChars={2} prompts={searchTerms} />
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
### 2. 限制提示数量
|
|
229
|
+
```svelte
|
|
230
|
+
<!-- 避免显示过多提示 -->
|
|
231
|
+
<PromptsTextEditor maxPrompts={6} prompts={largeDataset} />
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
### 3. 区分大小写处理
|
|
235
|
+
```svelte
|
|
236
|
+
<!-- 代码或技术术语:区分大小写 -->
|
|
237
|
+
<PromptsTextEditor caseSensitive={true} prompts={codeSnippets} />
|
|
238
|
+
|
|
239
|
+
<!-- 一般文本:不区分大小写 -->
|
|
240
|
+
<PromptsTextEditor caseSensitive={false} prompts={commonWords} />
|
|
241
|
+
```
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# RadioButton 组件
|
|
2
|
+
|
|
3
|
+
单选按钮组件,用于在多个选项中选择一个。
|
|
4
|
+
|
|
5
|
+
## 属性
|
|
6
|
+
|
|
7
|
+
| 属性 | 类型 | 默认值 | 描述 |
|
|
8
|
+
|------|------|--------|------|
|
|
9
|
+
| `variant` | `'' \| 'plain' \| 'outlined' \| 'filled'` | `''` | 外观变体 |
|
|
10
|
+
| `disabled` | `boolean` | `false` | 是否禁用 |
|
|
11
|
+
| `readonly` | `boolean` | `false` | 是否只读 |
|
|
12
|
+
| `value` | `any` | `null` | 选中的值 |
|
|
13
|
+
| `groupValue` | `any` | `null` | 单选组的当前值 |
|
|
14
|
+
| `label` | `string` | `''` | 标签文本 |
|
|
15
|
+
| `displayMode` | `DisplayMode` | `DisplayMode.Edit` | 显示模式 |
|
|
16
|
+
| `style` | `string` | `''` | 自定义样式 |
|
|
17
|
+
| `onChange` | `OnChangeHandler<any>` | - | 值变化回调 |
|
|
18
|
+
|
|
19
|
+
## 使用示例
|
|
20
|
+
|
|
21
|
+
```svelte
|
|
22
|
+
<script lang="ts">
|
|
23
|
+
import RadioButton from '@ticatec/uniface-element/RadioButton';
|
|
24
|
+
|
|
25
|
+
let selectedPayment: string = 'credit';
|
|
26
|
+
let selectedSize: string = 'M';
|
|
27
|
+
|
|
28
|
+
const handlePaymentChange = (value: string): void => {
|
|
29
|
+
selectedPayment = value;
|
|
30
|
+
console.log('支付方式:', value);
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const handleSizeChange = (value: string): void => {
|
|
34
|
+
selectedSize = value;
|
|
35
|
+
console.log('尺寸:', value);
|
|
36
|
+
};
|
|
37
|
+
</script>
|
|
38
|
+
|
|
39
|
+
<!-- 支付方式选择 -->
|
|
40
|
+
<div>
|
|
41
|
+
<h4>请选择支付方式:</h4>
|
|
42
|
+
<RadioButton
|
|
43
|
+
label="信用卡支付"
|
|
44
|
+
value="credit"
|
|
45
|
+
groupValue={selectedPayment}
|
|
46
|
+
onChange={handlePaymentChange}
|
|
47
|
+
/>
|
|
48
|
+
<RadioButton
|
|
49
|
+
label="支付宝"
|
|
50
|
+
value="alipay"
|
|
51
|
+
groupValue={selectedPayment}
|
|
52
|
+
onChange={handlePaymentChange}
|
|
53
|
+
/>
|
|
54
|
+
<RadioButton
|
|
55
|
+
label="微信支付"
|
|
56
|
+
value="wechat"
|
|
57
|
+
groupValue={selectedPayment}
|
|
58
|
+
onChange={handlePaymentChange}
|
|
59
|
+
/>
|
|
60
|
+
</div>
|
|
61
|
+
|
|
62
|
+
<!-- 尺寸选择 -->
|
|
63
|
+
<div>
|
|
64
|
+
<h4>请选择尺寸:</h4>
|
|
65
|
+
<RadioButton
|
|
66
|
+
label="小号 (S)"
|
|
67
|
+
value="S"
|
|
68
|
+
groupValue={selectedSize}
|
|
69
|
+
onChange={handleSizeChange}
|
|
70
|
+
/>
|
|
71
|
+
<RadioButton
|
|
72
|
+
label="中号 (M)"
|
|
73
|
+
value="M"
|
|
74
|
+
groupValue={selectedSize}
|
|
75
|
+
onChange={handleSizeChange}
|
|
76
|
+
/>
|
|
77
|
+
<RadioButton
|
|
78
|
+
label="大号 (L)"
|
|
79
|
+
value="L"
|
|
80
|
+
groupValue={selectedSize}
|
|
81
|
+
onChange={handleSizeChange}
|
|
82
|
+
/>
|
|
83
|
+
</div>
|
|
84
|
+
```
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
# Switch 组件
|
|
2
|
+
|
|
3
|
+
开关组件,提供布尔值的可视化切换。
|
|
4
|
+
|
|
5
|
+
## 属性
|
|
6
|
+
|
|
7
|
+
| 属性 | 类型 | 默认值 | 描述 |
|
|
8
|
+
|------|------|--------|------|
|
|
9
|
+
| `variant` | `'' \| 'plain' \| 'outlined' \| 'filled'` | `''` | 外观变体 |
|
|
10
|
+
| `disabled` | `boolean` | `false` | 是否禁用 |
|
|
11
|
+
| `readonly` | `boolean` | `false` | 是否只读 |
|
|
12
|
+
| `value` | `boolean` | `false` | 开关状态 |
|
|
13
|
+
| `label` | `string` | `''` | 标签文本 |
|
|
14
|
+
| `size` | `'small' \| 'medium' \| 'large'` | `'medium'` | 开关大小 |
|
|
15
|
+
| `displayMode` | `DisplayMode` | `DisplayMode.Edit` | 显示模式 |
|
|
16
|
+
| `style` | `string` | `''` | 自定义样式 |
|
|
17
|
+
| `onChange` | `OnChangeHandler<boolean>` | - | 值变化回调 |
|
|
18
|
+
|
|
19
|
+
## 使用示例
|
|
20
|
+
|
|
21
|
+
```svelte
|
|
22
|
+
<script lang="ts">
|
|
23
|
+
import Switch from '@ticatec/uniface-element/Switch';
|
|
24
|
+
|
|
25
|
+
let darkMode: boolean = false;
|
|
26
|
+
let notifications: boolean = true;
|
|
27
|
+
let autoSave: boolean = false;
|
|
28
|
+
|
|
29
|
+
const handleDarkModeChange = (enabled: boolean): void => {
|
|
30
|
+
darkMode = enabled;
|
|
31
|
+
// 应用深色主题逻辑
|
|
32
|
+
document.body.classList.toggle('dark-theme', enabled);
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
const handleNotificationChange = (enabled: boolean): void => {
|
|
36
|
+
notifications = enabled;
|
|
37
|
+
console.log('通知设置:', enabled);
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const handleAutoSaveChange = (enabled: boolean): void => {
|
|
41
|
+
autoSave = enabled;
|
|
42
|
+
console.log('自动保存:', enabled);
|
|
43
|
+
};
|
|
44
|
+
</script>
|
|
45
|
+
|
|
46
|
+
<!-- 深色模式开关 -->
|
|
47
|
+
<Switch
|
|
48
|
+
label="深色模式"
|
|
49
|
+
bind:value={darkMode}
|
|
50
|
+
onChange={handleDarkModeChange}
|
|
51
|
+
/>
|
|
52
|
+
|
|
53
|
+
<!-- 通知开关(大尺寸) -->
|
|
54
|
+
<Switch
|
|
55
|
+
label="推送通知"
|
|
56
|
+
size="large"
|
|
57
|
+
bind:value={notifications}
|
|
58
|
+
onChange={handleNotificationChange}
|
|
59
|
+
/>
|
|
60
|
+
|
|
61
|
+
<!-- 自动保存开关(小尺寸) -->
|
|
62
|
+
<Switch
|
|
63
|
+
label="自动保存"
|
|
64
|
+
size="small"
|
|
65
|
+
bind:value={autoSave}
|
|
66
|
+
onChange={handleAutoSaveChange}
|
|
67
|
+
/>
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## 高级用法
|
|
71
|
+
|
|
72
|
+
### 设置面板
|
|
73
|
+
```svelte
|
|
74
|
+
<script lang="ts">
|
|
75
|
+
interface AppSettings {
|
|
76
|
+
darkMode: boolean;
|
|
77
|
+
notifications: boolean;
|
|
78
|
+
autoSave: boolean;
|
|
79
|
+
showPreview: boolean;
|
|
80
|
+
enableShortcuts: boolean;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
let settings: AppSettings = {
|
|
84
|
+
darkMode: false,
|
|
85
|
+
notifications: true,
|
|
86
|
+
autoSave: true,
|
|
87
|
+
showPreview: true,
|
|
88
|
+
enableShortcuts: true
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
const updateSetting = (key: keyof AppSettings) => (value: boolean): void => {
|
|
92
|
+
settings = { ...settings, [key]: value };
|
|
93
|
+
localStorage.setItem('app-settings', JSON.stringify(settings));
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
// 页面加载时恢复设置
|
|
97
|
+
onMount(() => {
|
|
98
|
+
const savedSettings = localStorage.getItem('app-settings');
|
|
99
|
+
if (savedSettings) {
|
|
100
|
+
settings = { ...settings, ...JSON.parse(savedSettings) };
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
</script>
|
|
104
|
+
|
|
105
|
+
<div class="settings-panel">
|
|
106
|
+
<h3>应用设置</h3>
|
|
107
|
+
|
|
108
|
+
<div class="setting-group">
|
|
109
|
+
<Switch
|
|
110
|
+
label="深色模式"
|
|
111
|
+
bind:value={settings.darkMode}
|
|
112
|
+
onChange={updateSetting('darkMode')}
|
|
113
|
+
/>
|
|
114
|
+
<p class="setting-description">启用深色主题以减少眼部疲劳</p>
|
|
115
|
+
</div>
|
|
116
|
+
|
|
117
|
+
<div class="setting-group">
|
|
118
|
+
<Switch
|
|
119
|
+
label="桌面通知"
|
|
120
|
+
bind:value={settings.notifications}
|
|
121
|
+
onChange={updateSetting('notifications')}
|
|
122
|
+
/>
|
|
123
|
+
<p class="setting-description">允许显示桌面通知</p>
|
|
124
|
+
</div>
|
|
125
|
+
|
|
126
|
+
<div class="setting-group">
|
|
127
|
+
<Switch
|
|
128
|
+
label="自动保存"
|
|
129
|
+
size="small"
|
|
130
|
+
bind:value={settings.autoSave}
|
|
131
|
+
onChange={updateSetting('autoSave')}
|
|
132
|
+
/>
|
|
133
|
+
<p class="setting-description">自动保存您的工作</p>
|
|
134
|
+
</div>
|
|
135
|
+
</div>
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
## 最佳实践
|
|
139
|
+
|
|
140
|
+
### 1. 提供即时反馈
|
|
141
|
+
```svelte
|
|
142
|
+
<script lang="ts">
|
|
143
|
+
let isOnline: boolean = true;
|
|
144
|
+
|
|
145
|
+
const toggleOnlineStatus = (status: boolean): void => {
|
|
146
|
+
isOnline = status;
|
|
147
|
+
|
|
148
|
+
// 显示状态变化提示
|
|
149
|
+
const message = status ? '已上线' : '已离线';
|
|
150
|
+
showToast(message);
|
|
151
|
+
};
|
|
152
|
+
</script>
|
|
153
|
+
|
|
154
|
+
<Switch
|
|
155
|
+
label={`状态: ${isOnline ? '在线' : '离线'}`}
|
|
156
|
+
bind:value={isOnline}
|
|
157
|
+
onChange={toggleOnlineStatus}
|
|
158
|
+
/>
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### 2. 条件禁用
|
|
162
|
+
```svelte
|
|
163
|
+
<script lang="ts">
|
|
164
|
+
let isPremiumUser: boolean = false;
|
|
165
|
+
let advancedFeatures: boolean = false;
|
|
166
|
+
|
|
167
|
+
$: canUseAdvancedFeatures = isPremiumUser;
|
|
168
|
+
</script>
|
|
169
|
+
|
|
170
|
+
<Switch
|
|
171
|
+
label="高级功能"
|
|
172
|
+
disabled={!canUseAdvancedFeatures}
|
|
173
|
+
bind:value={advancedFeatures}
|
|
174
|
+
/>
|
|
175
|
+
{#if !canUseAdvancedFeatures}
|
|
176
|
+
<p class="upgrade-hint">升级到高级版以使用此功能</p>
|
|
177
|
+
{/if}
|
|
178
|
+
```
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
# TextEditor 组件
|
|
2
|
+
|
|
3
|
+
基础文本输入组件,支持单行和多行文本输入。
|
|
4
|
+
|
|
5
|
+
## 属性
|
|
6
|
+
|
|
7
|
+
| 属性 | 类型 | 默认值 | 描述 |
|
|
8
|
+
|------|------|--------|------|
|
|
9
|
+
| `variant` | `'' \| 'plain' \| 'outlined' \| 'filled'` | `''` | 外观变体 |
|
|
10
|
+
| `disabled` | `boolean` | `false` | 是否禁用 |
|
|
11
|
+
| `readonly` | `boolean` | `false` | 是否只读 |
|
|
12
|
+
| `compact` | `boolean` | `false` | 是否紧凑模式 |
|
|
13
|
+
| `value` | `string` | `''` | 输入值 |
|
|
14
|
+
| `suffix` | `string` | `''` | 文本后缀 |
|
|
15
|
+
| `prefix` | `string` | `''` | 文本前缀 |
|
|
16
|
+
| `removable` | `boolean` | `true` | 显示清除按钮 |
|
|
17
|
+
| `displayMode` | `DisplayMode` | `DisplayMode.Edit` | 显示模式 |
|
|
18
|
+
| `style` | `string` | `''` | 自定义样式 |
|
|
19
|
+
| `onChange` | `(value: string) => void` | - | 值变化回调 |
|
|
20
|
+
|
|
21
|
+
## 事件
|
|
22
|
+
|
|
23
|
+
- `onChange(value: string)` - 当输入值发生变化时触发
|
|
24
|
+
|
|
25
|
+
## 使用示例
|
|
26
|
+
|
|
27
|
+
```svelte
|
|
28
|
+
<script lang="ts">
|
|
29
|
+
import TextEditor from '@ticatec/uniface-element/TextEditor';
|
|
30
|
+
|
|
31
|
+
let inputValue = '';
|
|
32
|
+
|
|
33
|
+
const handleChange = (value: string) => {
|
|
34
|
+
console.log('输入值:', value);
|
|
35
|
+
inputValue = value;
|
|
36
|
+
};
|
|
37
|
+
</script>
|
|
38
|
+
|
|
39
|
+
<!-- 基础输入 -->
|
|
40
|
+
<TextEditor
|
|
41
|
+
placeholder="请输入文本"
|
|
42
|
+
onChange={handleChange}
|
|
43
|
+
bind:value={inputValue}
|
|
44
|
+
/>
|
|
45
|
+
|
|
46
|
+
<!-- 带前缀和后缀的输入 -->
|
|
47
|
+
<TextEditor
|
|
48
|
+
prefix="¥"
|
|
49
|
+
suffix=".00"
|
|
50
|
+
placeholder="请输入金额"
|
|
51
|
+
onChange={handleChange}
|
|
52
|
+
bind:value={inputValue}
|
|
53
|
+
/>
|
|
54
|
+
|
|
55
|
+
<!-- 紧凑模式带清除按钮 -->
|
|
56
|
+
<TextEditor
|
|
57
|
+
compact={true}
|
|
58
|
+
removable={true}
|
|
59
|
+
placeholder="搜索..."
|
|
60
|
+
bind:value={inputValue}
|
|
61
|
+
/>
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## 最佳实践
|
|
65
|
+
|
|
66
|
+
### 表单验证
|
|
67
|
+
```svelte
|
|
68
|
+
<script lang="ts">
|
|
69
|
+
let value = '';
|
|
70
|
+
let error = '';
|
|
71
|
+
|
|
72
|
+
const validate = (inputValue) => {
|
|
73
|
+
if (!inputValue || inputValue.trim().length === 0) {
|
|
74
|
+
error = '此字段不能为空';
|
|
75
|
+
} else if (inputValue.length < 3) {
|
|
76
|
+
error = '至少需要3个字符';
|
|
77
|
+
} else {
|
|
78
|
+
error = '';
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
const handleChange = (newValue) => {
|
|
83
|
+
value = newValue;
|
|
84
|
+
validate(newValue);
|
|
85
|
+
};
|
|
86
|
+
</script>
|
|
87
|
+
|
|
88
|
+
<TextEditor
|
|
89
|
+
placeholder="请输入内容"
|
|
90
|
+
bind:value={value}
|
|
91
|
+
onChange={handleChange}
|
|
92
|
+
/>
|
|
93
|
+
{#if error}
|
|
94
|
+
<div class="error-message">{error}</div>
|
|
95
|
+
{/if}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### 带样式的文本输入
|
|
99
|
+
```svelte
|
|
100
|
+
<script lang="ts">
|
|
101
|
+
let description = '';
|
|
102
|
+
</script>
|
|
103
|
+
|
|
104
|
+
<TextEditor
|
|
105
|
+
variant="outlined"
|
|
106
|
+
placeholder="请输入描述信息..."
|
|
107
|
+
bind:value={description}
|
|
108
|
+
style="min-width: 300px;"
|
|
109
|
+
/>
|
|
110
|
+
<div class="char-count">{description.length} 个字符</div>
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
## 样式定制
|
|
114
|
+
|
|
115
|
+
```css
|
|
116
|
+
/* 自定义样式 */
|
|
117
|
+
.custom-text-editor {
|
|
118
|
+
border-radius: 8px;
|
|
119
|
+
border: 2px solid #e1e5e9;
|
|
120
|
+
font-family: 'Inter', sans-serif;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
.custom-text-editor:focus {
|
|
124
|
+
border-color: #007bff;
|
|
125
|
+
box-shadow: 0 0 0 3px rgba(0, 123, 255, 0.1);
|
|
126
|
+
}
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
## 无障碍访问
|
|
130
|
+
|
|
131
|
+
```svelte
|
|
132
|
+
<label for="user-name">用户名称:</label>
|
|
133
|
+
<TextEditor
|
|
134
|
+
id="user-name"
|
|
135
|
+
placeholder="请输入用户名称"
|
|
136
|
+
aria-describedby="name-help"
|
|
137
|
+
bind:value={userName}
|
|
138
|
+
/>
|
|
139
|
+
<div id="name-help" class="form-help">
|
|
140
|
+
用户名称将用于系统显示,建议使用真实姓名
|
|
141
|
+
</div>
|
|
142
|
+
```
|