@ticatec/uniface-element 0.3.17 → 0.3.19

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.
@@ -0,0 +1,193 @@
1
+ # FormField 表单字段
2
+
3
+ 一个表单字段包装组件,为表单输入提供一致的布局,包括标签、错误消息和必填指示器。
4
+
5
+ ## 特性
6
+
7
+ - **标签支持**: 显示带可选后缀的标签
8
+ - **必填指示器**: 必填字段的视觉指示器
9
+ - **错误显示**: 显示验证错误消息
10
+ - **灵活布局**: 中心或顶部标签对齐
11
+ - **自定义样式**: 标签和容器的自定义样式
12
+ - **响应式高度**: 可调整的字段高度
13
+
14
+ ## 安装
15
+
16
+ ```bash
17
+ npm install @ticatec/uniface-element
18
+ ```
19
+
20
+ ```typescript
21
+ import FormField from '@ticatec/uniface-element/FormField';
22
+ ```
23
+
24
+ ## 基本用法
25
+
26
+ ```svelte
27
+ <script>
28
+ import FormField from '@ticatec/uniface-element/FormField';
29
+ import TextEditor from '@ticatec/uniface-element/TextEditor';
30
+ </script>
31
+
32
+ <FormField label="用户名" required>
33
+ <TextEditor placeholder="请输入用户名" />
34
+ </FormField>
35
+ ```
36
+
37
+ ## 属性
38
+
39
+ | 属性 | 类型 | 默认值 | 说明 |
40
+ |------|------|---------|-------------|
41
+ | `label` | `string` | `'Label:'` | 字段标签文本 |
42
+ | `labelSuffix` | `string` | `':'` | 标签后的后缀文本 |
43
+ | `required` | `boolean` | `false` | 显示必填指示器 (*) |
44
+ | `error` | `string \| null` | `null` | 要显示的错误消息 |
45
+ | `labelAlignment` | `'center' \| 'top'` | `'center'` | 标签垂直对齐方式 |
46
+ | `labelStyle` | `string \| null` | `null` | 标签的自定义CSS |
47
+ | `style` | `string` | `''` | 容器的自定义CSS |
48
+ | `height` | `string` | `'auto'` | 字段区域的高度 |
49
+ | `class` | `string` | `''` | CSS类名 |
50
+
51
+ ## 示例
52
+
53
+ ### 基本表单字段
54
+
55
+ ```svelte
56
+ <script>
57
+ import FormField from '@ticatec/uniface-element/FormField';
58
+ import TextEditor from '@ticatec/uniface-element/TextEditor';
59
+ </script>
60
+
61
+ <FormField label="邮箱">
62
+ <TextEditor type="email" placeholder="user@example.com" />
63
+ </FormField>
64
+ ```
65
+
66
+ ### 必填字段
67
+
68
+ ```svelte
69
+ <script>
70
+ import FormField from '@ticatec/uniface-element/FormField';
71
+ import TextEditor from '@ticatec/uniface-element/TextEditor';
72
+ </script>
73
+
74
+ <FormField label="密码" required>
75
+ <TextEditor type="password" placeholder="请输入密码" />
76
+ </FormField>
77
+ ```
78
+
79
+ ### 带错误消息
80
+
81
+ ```svelte
82
+ <script>
83
+ import FormField from '@ticatec/uniface-element/FormField';
84
+ import TextEditor from '@ticatec/uniface-element/TextEditor';
85
+
86
+ let error = '此字段为必填项';
87
+ </script>
88
+
89
+ <FormField label="用户名" {error} required>
90
+ <TextEditor placeholder="请输入用户名" />
91
+ </FormField>
92
+ ```
93
+
94
+ ### 顶部标签对齐
95
+
96
+ ```svelte
97
+ <script>
98
+ import FormField from '@ticatec/uniface-element/FormField';
99
+ import TextEditor from '@ticatec/uniface-element/TextEditor';
100
+ </script>
101
+
102
+ <FormField label="描述" labelAlignment="top">
103
+ <TextEditor placeholder="请输入描述" />
104
+ </FormField>
105
+ ```
106
+
107
+ ### 自定义标签样式
108
+
109
+ ```svelte
110
+ <script>
111
+ import FormField from '@ticatec/uniface-element/FormField';
112
+ import TextEditor from '@ticatec/uniface-element/TextEditor';
113
+ </script>
114
+
115
+ <FormField
116
+ label="重要字段"
117
+ labelStyle="color: #007acc; font-weight: bold;"
118
+ >
119
+ <TextEditor placeholder="请输入值" />
120
+ </FormField>
121
+ ```
122
+
123
+ ### 完整表单示例
124
+
125
+ ```svelte
126
+ <script>
127
+ import FormField from '@ticatec/uniface-element/FormField';
128
+ import TextEditor from '@ticatec/uniface-element/TextEditor';
129
+ import Button from '@ticatec/uniface-element/Button';
130
+
131
+ let formData = {
132
+ username: '',
133
+ email: '',
134
+ password: ''
135
+ };
136
+
137
+ let errors = {
138
+ username: '',
139
+ email: '',
140
+ password: ''
141
+ };
142
+
143
+ function validate() {
144
+ if (!formData.username) {
145
+ errors.username = '用户名为必填项';
146
+ }
147
+ if (!formData.email) {
148
+ errors.email = '邮箱为必填项';
149
+ }
150
+ if (!formData.password) {
151
+ errors.password = '密码为必填项';
152
+ }
153
+ }
154
+
155
+ function handleSubmit() {
156
+ validate();
157
+ if (Object.values(errors).every(e => !e)) {
158
+ console.log('表单提交:', formData);
159
+ }
160
+ }
161
+ </script>
162
+
163
+ <form on:submit|preventDefault={handleSubmit}>
164
+ <FormField label="用户名" required error={errors.username}>
165
+ <TextEditor bind:value={formData.username} placeholder="请输入用户名" />
166
+ </FormField>
167
+
168
+ <FormField label="邮箱" required error={errors.email}>
169
+ <TextEditor bind:value={formData.email} type="email" placeholder="user@example.com" />
170
+ </FormField>
171
+
172
+ <FormField label="密码" required error={errors.password}>
173
+ <TextEditor bind:value={formData.password} type="password" placeholder="请输入密码" />
174
+ </FormField>
175
+
176
+ <Button type="primary" onclick={handleSubmit}>提交</Button>
177
+ </form>
178
+ ```
179
+
180
+ ## 最佳实践
181
+
182
+ 1. **始终使用标签**: 为可访问性提供清晰、描述性的标签
183
+ 2. **标记必填字段**: 对必填字段使用 `required` 属性
184
+ 3. **显示错误**: 在字段下方显示验证错误
185
+ 4. **一致对齐**: 在整个表单中使用相同的标签对齐方式
186
+ 5. **自定义样式**: 需要特殊强调时使用 labelStyle
187
+
188
+ ## 无障碍访问
189
+
190
+ - 表单字段的正确标签关联
191
+ - 屏幕阅读器的必填指示器
192
+ - 验证反馈的错误消息显示
193
+ - 语义化HTML结构
@@ -3,7 +3,7 @@
3
3
  export let fieldLayout: 'vertical' | 'horizontal' = 'vertical';
4
4
 
5
5
  </script>
6
- <div class="flex-form" class:field-layout-horizontal={fieldLayout=='horizontal'} {style}>
6
+ <div class="flex-form" class:field-layout-horizontal={fieldLayout=='horizontal'} {style}>
7
7
  <div>
8
8
  <slot/>
9
9
  </div>
@@ -0,0 +1,116 @@
1
+ # InlineCellEditor
2
+
3
+ A lightweight wrapper component for inline editing in table cells or other constrained spaces.
4
+
5
+ ## Features
6
+
7
+ - **Minimal Wrapper**: Simple slot-based component for maximum flexibility
8
+ - **Inline Editing**: Designed for inline editing scenarios
9
+ - **Custom Styling**: Accepts custom styles
10
+ - **Focus Handling**: Built-in focus event handling
11
+
12
+ ## Installation
13
+
14
+ ```bash
15
+ npm install @ticatec/uniface-element
16
+ ```
17
+
18
+ ```typescript
19
+ import InlineCellEditor from '@ticatec/uniface-element/InlineCellEditor';
20
+ ```
21
+
22
+ ## Basic Usage
23
+
24
+ ```svelte
25
+ <script>
26
+ import InlineCellEditor from '@ticatec/uniface-element/InlineCellEditor';
27
+ import TextEditor from '@ticatec/uniface-element/TextEditor';
28
+ </script>
29
+
30
+ <InlineCellEditor>
31
+ <TextEditor placeholder="Edit inline..." />
32
+ </InlineCellEditor>
33
+ ```
34
+
35
+ ## Props
36
+
37
+ | Prop | Type | Default | Description |
38
+ |------|------|---------|-------------|
39
+ | `style` | `string` | `''` | Custom CSS styles |
40
+
41
+ ## Examples
42
+
43
+ ### Basic Inline Editor
44
+
45
+ ```svelte
46
+ <script>
47
+ import InlineCellEditor from '@ticatec/uniface-element/InlineCellEditor';
48
+ import TextEditor from '@ticatec/uniface-element/TextEditor';
49
+
50
+ let value = '';
51
+ </script>
52
+
53
+ <InlineCellEditor>
54
+ <TextEditor bind:value={value} placeholder="Click to edit" />
55
+ </InlineCellEditor>
56
+ ```
57
+
58
+ ### In Table Cells
59
+
60
+ ```svelte
61
+ <script>
62
+ import InlineCellEditor from '@ticatec/uniface-element/InlineCellEditor';
63
+ import TextEditor from '@ticatec/uniface-element/TextEditor';
64
+
65
+ let data = [
66
+ { name: 'Item 1', price: 100 },
67
+ { name: 'Item 2', price: 200 }
68
+ ];
69
+ </script>
70
+
71
+ <table>
72
+ {#each data as item}
73
+ <tr>
74
+ <td>
75
+ <InlineCellEditor>
76
+ <TextEditor bind:value={item.name} />
77
+ </InlineCellEditor>
78
+ </td>
79
+ <td>
80
+ <InlineCellEditor>
81
+ <TextEditor bind:value={item.price} type="number" />
82
+ </InlineCellEditor>
83
+ </td>
84
+ </tr>
85
+ {/each}
86
+ </table>
87
+ ```
88
+
89
+ ### With Custom Styling
90
+
91
+ ```svelte
92
+ <script>
93
+ import InlineCellEditor from '@ticatec/uniface-element/InlineCellEditor';
94
+ import TextEditor from '@ticatec/uniface-element/TextEditor';
95
+
96
+ let value = '';
97
+ </script>
98
+
99
+ <InlineCellEditor style="padding: 4px; background: #f5f5f5;">
100
+ <TextEditor bind:value={value} compact />
101
+ </InlineCellEditor>
102
+ ```
103
+
104
+ ## Use Cases
105
+
106
+ - **Table Cell Editing**: Edit data directly in table cells
107
+ - **Form Grids**: Compact editing in form layouts
108
+ - **List Items**: Inline editing in list views
109
+ - **Data Grids**: Spreadsheet-like editing experience
110
+
111
+ ## Best Practices
112
+
113
+ 1. **Use with Compact Editors**: Pair with compact form components
114
+ 2. **Minimal Styling**: Keep inline editors simple and unobtrusive
115
+ 3. **Focus Management**: Ensure proper focus handling for accessibility
116
+ 4. **Validation**: Implement validation on blur or change events
@@ -0,0 +1,116 @@
1
+ # InlineCellEditor 内联单元格编辑器
2
+
3
+ 一个轻量级的包装组件,用于表格单元格或其他受限空间中的内联编辑。
4
+
5
+ ## 特性
6
+
7
+ - **最小化包装**: 基于插槽的简单组件,最大化灵活性
8
+ - **内联编辑**: 专为内联编辑场景设计
9
+ - **自定义样式**: 接受自定义样式
10
+ - **焦点处理**: 内置焦点事件处理
11
+
12
+ ## 安装
13
+
14
+ ```bash
15
+ npm install @ticatec/uniface-element
16
+ ```
17
+
18
+ ```typescript
19
+ import InlineCellEditor from '@ticatec/uniface-element/InlineCellEditor';
20
+ ```
21
+
22
+ ## 基本用法
23
+
24
+ ```svelte
25
+ <script>
26
+ import InlineCellEditor from '@ticatec/uniface-element/InlineCellEditor';
27
+ import TextEditor from '@ticatec/uniface-element/TextEditor';
28
+ </script>
29
+
30
+ <InlineCellEditor>
31
+ <TextEditor placeholder="点击编辑..." />
32
+ </InlineCellEditor>
33
+ ```
34
+
35
+ ## 属性
36
+
37
+ | 属性 | 类型 | 默认值 | 说明 |
38
+ |------|------|---------|-------------|
39
+ | `style` | `string` | `''` | 自定义CSS样式 |
40
+
41
+ ## 示例
42
+
43
+ ### 基本内联编辑器
44
+
45
+ ```svelte
46
+ <script>
47
+ import InlineCellEditor from '@ticatec/uniface-element/InlineCellEditor';
48
+ import TextEditor from '@ticatec/uniface-element/TextEditor';
49
+
50
+ let value = '';
51
+ </script>
52
+
53
+ <InlineCellEditor>
54
+ <TextEditor bind:value={value} placeholder="点击编辑" />
55
+ </InlineCellEditor>
56
+ ```
57
+
58
+ ### 在表格单元格中
59
+
60
+ ```svelte
61
+ <script>
62
+ import InlineCellEditor from '@ticatec/uniface-element/InlineCellEditor';
63
+ import TextEditor from '@ticatec/uniface-element/TextEditor';
64
+
65
+ let data = [
66
+ { name: '项目1', price: 100 },
67
+ { name: '项目2', price: 200 }
68
+ ];
69
+ </script>
70
+
71
+ <table>
72
+ {#each data as item}
73
+ <tr>
74
+ <td>
75
+ <InlineCellEditor>
76
+ <TextEditor bind:value={item.name} />
77
+ </InlineCellEditor>
78
+ </td>
79
+ <td>
80
+ <InlineCellEditor>
81
+ <TextEditor bind:value={item.price} type="number" />
82
+ </InlineCellEditor>
83
+ </td>
84
+ </tr>
85
+ {/each}
86
+ </table>
87
+ ```
88
+
89
+ ### 自定义样式
90
+
91
+ ```svelte
92
+ <script>
93
+ import InlineCellEditor from '@ticatec/uniface-element/InlineCellEditor';
94
+ import TextEditor from '@ticatec/uniface-element/TextEditor';
95
+
96
+ let value = '';
97
+ </script>
98
+
99
+ <InlineCellEditor style="padding: 4px; background: #f5f5f5;">
100
+ <TextEditor bind:value={value} compact />
101
+ </InlineCellEditor>
102
+ ```
103
+
104
+ ## 使用场景
105
+
106
+ - **表格单元格编辑**: 直接在表格单元格中编辑数据
107
+ - **表单网格**: 表单布局中的紧凑编辑
108
+ - **列表项**: 列表视图中的内联编辑
109
+ - **数据网格**: 类似电子表格的编辑体验
110
+
111
+ ## 最佳实践
112
+
113
+ 1. **使用紧凑编辑器**: 与紧凑的表单组件配对使用
114
+ 2. **最小化样式**: 保持内联编辑器简单且不突兀
115
+ 3. **焦点管理**: 确保正确的焦点处理以实现无障碍访问
116
+ 4. **验证**: 在模糊或更改事件上实现验证
@@ -9,7 +9,7 @@ Each node created from `TreeNodes` or `CommonTreeNodes` is an instance of the `T
9
9
  ## TreeNode Class
10
10
 
11
11
  ```typescript
12
- class TreeNode<T> {
12
+ class TreeNode<T> implements ITreeNode<T> {
13
13
  /** The node's data object (readonly) */
14
14
  public readonly item: T;
15
15
 
@@ -20,26 +20,26 @@ class TreeNode<T> {
20
20
  public loading: boolean;
21
21
 
22
22
  /** Parent node (null for root nodes) */
23
- public parent: TreeNode<T> | null;
23
+ public readonly parent: TreeNode<T> | null;
24
24
 
25
- /** Child nodes (readonly, use methods to modify) */
26
- get children(): ReadonlyArray<TreeNode<T>>;
25
+ /** Node level (root = 0) */
26
+ get level(): number;
27
27
 
28
- /** Add a child node to the current node */
29
- append(childItem: T): void;
28
+ /** Child nodes (shallow copy, use methods to modify) */
29
+ get children(): Array<TreeNode<T>> | null;
30
+
31
+ /** Add child(ren) to the current node */
32
+ append(childItem: T | Array<T>): ITreeNode<T> | Array<ITreeNode<T>>;
30
33
 
31
34
  /** Remove the current node (from its parent) */
32
35
  detach(): void;
33
36
 
34
- /** Move the current node to a different parent */
35
- moveTo(newParent: TreeNode<T>): void;
37
+ /** Move the current node to a different parent (returns new node) */
38
+ moveTo(newParent: TreeNode<T>): TreeNode<T>;
36
39
 
37
40
  /** Replace the current node's data */
38
41
  replace(newItem: T): void;
39
42
 
40
- /** Remove a specific child node by ID */
41
- removeChild(childId: any): void;
42
-
43
43
  /** Remove all child nodes */
44
44
  removeChildren(): void;
45
45
  }
@@ -87,25 +87,33 @@ class NodeViewOptions<T> {
87
87
 
88
88
  ### 1. append(childItem)
89
89
 
90
- Add a child node to the current node.
90
+ Add child(ren) to the current node.
91
91
 
92
- **Parameter**:
93
- - `childItem: T` - The child node's data object
92
+ **Parameters**:
93
+ - `childItem: T | Array<T>` - The child node's data object or array of child objects
94
94
 
95
95
  **Example**:
96
96
  ```typescript
97
- // Pass data object directly
97
+ // Add a single child
98
98
  parentNode.append({
99
99
  id: 123,
100
100
  name: "New Child",
101
101
  parentId: parentNode.item.id // Will be set automatically
102
102
  });
103
+
104
+ // Add multiple children at once
105
+ parentNode.append([
106
+ { id: 124, name: "Child 1", parentId: parentNode.item.id },
107
+ { id: 125, name: "Child 2", parentId: parentNode.item.id }
108
+ ]);
103
109
  ```
104
110
 
111
+ **Returns**:
112
+ - `ITreeNode<T> | Array<ITreeNode<T>>` - The added child node(s)
113
+
105
114
  **Notes**:
106
115
  - Automatically initializes children array if needed
107
116
  - If a sort function is configured, nodes will be automatically sorted
108
- - The parent's `expand` is automatically set to `true`
109
117
  - Triggers version update for reactive updates
110
118
 
111
119
  ---
@@ -195,32 +203,7 @@ node.replace({
195
203
 
196
204
  ---
197
205
 
198
- ### 5. removeChild(childId)
199
-
200
- Remove a specific child node.
201
-
202
- **Parameter**:
203
- - `childId: any` - ID of the child node to remove
204
-
205
- **Example**:
206
- ```typescript
207
- // Remove child with specific ID
208
- parentNode.removeChild(123);
209
-
210
- // Use variable
211
- const childId = childNode.item.id;
212
- parentNode.removeChild(childId);
213
- ```
214
-
215
- **Notes**:
216
- - Only removes direct children, not grandchildren recursively
217
- - Silently ignores if child doesn't exist
218
- - All descendants of the child node are also removed
219
- - Triggers version update for reactive updates
220
-
221
- ---
222
-
223
- ### 6. removeChildren()
206
+ ### 5. removeChildren()
224
207
 
225
208
  Remove all child nodes.
226
209
 
@@ -322,12 +305,6 @@ interface TreeNodeOptions<T> {
322
305
  activeNode = null;
323
306
  }
324
307
 
325
- // Delete specific child
326
- function deleteChild(childId: number) {
327
- if (!activeNode) return;
328
- activeNode.removeChild(childId);
329
- }
330
-
331
308
  // Clear all children
332
309
  function clearChildren() {
333
310
  if (!activeNode) return;
@@ -383,11 +360,10 @@ interface TreeNodeOptions<T> {
383
360
 
384
361
  ```typescript
385
362
  // Operate directly on a node instance
386
- node.append(childItem); // Add child to this node
363
+ node.append(childItem); // Add child(ren) to this node
387
364
  node.detach(); // Remove this node from its parent
388
365
  node.replace(newItem); // Replace this node's data
389
366
  node.moveTo(newParentNode); // Move this node to another parent
390
- node.removeChild(childId); // Remove specific child
391
367
  node.removeChildren(); // Remove all children
392
368
  ```
393
369
 
@@ -409,9 +385,8 @@ treeNodes.extractDirectories(item); // Extract directory structure (TreeNodes on
409
385
  The data object stored in the node. Cannot be modified directly. Use `replace()` to update data.
410
386
 
411
387
  ### children (readonly)
412
- Returns a read-only array of child nodes. To modify children, use the methods:
413
- - `append()` - add a child
414
- - `removeChild()` - remove a specific child
388
+ Returns a shallow copy of the child nodes array. To modify children, use the methods:
389
+ - `append()` - add child(ren)
415
390
  - `removeChildren()` - remove all children
416
391
 
417
392
  ### expand
@@ -488,10 +463,10 @@ function findChild(node: TreeNode, childId: number) {
488
463
 
489
464
  ### Q: Can I modify the children array directly?
490
465
 
491
- No. The `children` property is read-only. Use the provided methods instead:
492
- - `append()` to add
493
- - `removeChild()` to remove specific child
494
- - `removeChildren()` to remove all
466
+ No. The `children` property returns a shallow copy. Use the provided methods instead:
467
+ - `append()` to add child(ren)
468
+ - `removeChildren()` to remove all children
469
+ - To remove a specific child, iterate through children and call `detach()` on the child node
495
470
 
496
471
  ### Q: How to recursively operate on all descendants?
497
472