@ticatec/uniface-element 0.2.0 → 0.2.2
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 +320 -1
- package/README_CN.md +392 -0
- package/dist/accordion/Accordion.svelte +1 -1
- package/dist/action-bar/ActionBar.svelte +7 -1
- package/dist/attachment-files/FileRender.svelte +1 -1
- package/dist/attachment-files/FileUploadBar.svelte +7 -6
- package/dist/attachment-files/FileUploadPanel.svelte +2 -2
- package/dist/base-calendar/DateContext.js +5 -4
- package/dist/base-calendar/YearPickupPanel.svelte +4 -4
- package/dist/card/Card.svelte +1 -1
- package/dist/card/Card.svelte.d.ts +1 -1
- package/dist/cascade-options-select/CascadeOptionSelect.svelte +2 -3
- package/dist/cascade-options-select/CascadeOptionSelect.svelte.d.ts +46 -1
- package/dist/cascade-options-select/CascadePanel.svelte +1 -1
- package/dist/checkbox/CheckBox.svelte +1 -1
- package/dist/color-picker/ColorPicker.svelte +9 -9
- package/dist/color-picker/ColorPicker.svelte.d.ts +0 -2
- package/dist/color-picker/ColorPickerPanel.svelte +11 -15
- package/dist/color-picker/ColorPickerPanel.svelte.d.ts +1 -1
- package/dist/common/CommonPicker.svelte +2 -2
- package/dist/common/CommonPicker.svelte.d.ts +1 -1
- package/dist/common/MouseClickHandler.d.ts +1 -1
- package/dist/common/Popover.svelte +28 -6
- package/dist/common/Popover.svelte.d.ts +9 -3
- package/dist/common/uniface-utils.js +6 -4
- package/dist/common-editor/CommonEditor.svelte +1 -1
- package/dist/common-editor/CommonEditor.svelte.d.ts +1 -1
- package/dist/common-editor/NumberInput.svelte +1 -1
- package/dist/common-editor/NumberInput.svelte.d.ts +1 -1
- package/dist/concise-data-table/ConciseListTable.svelte +7 -2
- package/dist/concise-data-table/ConciseListTable.svelte.d.ts +1 -0
- package/dist/concise-data-table/DataRow.svelte +1 -1
- package/dist/concise-data-table/TableOptions.d.ts +1 -1
- package/dist/data-table/DataTable.svelte +1 -1
- package/dist/data-table/parts/ActionsPanel.svelte +4 -3
- package/dist/data-table/parts/ActionsRow.svelte +3 -3
- package/dist/data-table/parts/ContentPanel.svelte +3 -2
- package/dist/data-table/parts/FixedColumnsPanel.svelte +0 -1
- package/dist/data-table/parts/FixedColumnsPanel.svelte.d.ts +1 -2
- package/dist/data-table/parts/FixedHeaderPanel.svelte +2 -2
- package/dist/data-table/parts/FixedRow.svelte +2 -1
- package/dist/data-table/parts/FixedRow.svelte.d.ts +1 -1
- package/dist/data-table/parts/HrefCell.svelte +23 -2
- package/dist/data-table/parts/PopupMenu.svelte +25 -2
- package/dist/data-table/parts/PopupMenu.svelte.d.ts +8 -1
- package/dist/date-picker/DatePicker.svelte +0 -1
- package/dist/date-picker/DateTimePicker.svelte +3 -3
- package/dist/date-picker/ScrollBar.svelte +4 -7
- package/dist/date-range/DateRangeEditor.svelte +1 -1
- package/dist/dialog/CommonDialog.svelte +8 -5
- package/dist/dialog/CommonDialog.svelte.d.ts +2 -1
- package/dist/dialog/Dialog.svelte +37 -12
- 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/{common-editor/DateInput.svelte.d.ts → dialog/DialogWrapper.svelte.d.ts} +6 -13
- package/dist/dialog/Dialogs.js +1 -1
- package/dist/dialog/ModalResult.d.ts +5 -0
- package/dist/dialog/ModalResult.js +5 -0
- package/dist/drawer/Drawer.svelte +1 -1
- package/dist/form-field/FormField.svelte +2 -1
- package/dist/form-field/FormField.svelte.d.ts +1 -0
- package/dist/form-panel/flex-row-form/FormContainer.svelte +1 -1
- package/dist/form-panel/grid-form/EmptyCell.svelte +8 -7
- package/dist/form-panel/grid-form/EmptyCell.svelte.d.ts +2 -2
- package/dist/form-panel/grid-form/GridField.svelte +1 -1
- package/dist/i18nRes/i18nRes.d.ts +2 -0
- package/dist/i18nRes/i18nRes.js +44 -0
- package/dist/i18nRes/index.d.ts +2 -0
- package/dist/i18nRes/index.js +2 -0
- package/dist/image-files/ImageFilesField.svelte +1 -1
- package/dist/indicator/IndicatorBoard.svelte +1 -1
- package/dist/inline-cell-editor/InvalidEditor.svelte +1 -0
- package/dist/input-options-select/InputOptionsSelect.svelte +6 -6
- package/dist/input-options-select/InputOptionsSelect.svelte.d.ts +1 -1
- package/dist/layout/flex/FlexBlock.svelte +1 -1
- package/dist/lookup-editor/LookupEditor.svelte +1 -1
- package/dist/memo-editor/MemoEditor.svelte +2 -2
- package/dist/message-box/IMessageBox.d.ts +2 -4
- package/dist/message-box/IMessageBox.js +4 -6
- package/dist/message-box/MessageBoxBoard.svelte +1 -3
- package/dist/options-multi-select/OptionsMultiSelect.svelte +1 -1
- package/dist/prompts-text-editor/PromptsTextEditor.svelte +2 -2
- package/dist/prompts-text-editor/PromptsTextEditor.svelte.d.ts +1 -1
- package/dist/property-editor/PropertyEditor.svelte +3 -3
- package/dist/text-editor/PasswordEditor.svelte +1 -1
- package/dist/transfer/Transfer.svelte +17 -12
- package/dist/transfer/Transfer.svelte.d.ts +0 -1
- package/dist/unit-number-editor/UnitNumberEditor.svelte +2 -2
- 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 +53 -13
- package/dist/common-editor/DateInput.svelte +0 -27
- package/dist/i18n_resources/index.d.ts +0 -3
- package/dist/i18n_resources/index.js +0 -3
- /package/dist/{i18n_resources → i18nRes}/uniface_cn_resource.d.ts +0 -0
- /package/dist/{i18n_resources → i18nRes}/uniface_cn_resource.js +0 -0
- /package/dist/{i18n_resources → i18nRes}/uniface_en_resource.d.ts +0 -0
- /package/dist/{i18n_resources → i18nRes}/uniface_en_resource.js +0 -0
|
@@ -0,0 +1,409 @@
|
|
|
1
|
+
# MemoEditor Component
|
|
2
|
+
|
|
3
|
+
The MemoEditor component provides a multi-line text input with advanced features including character counting, resizing options, and display mode support for longer text content.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Multi-line Text Input**: Textarea-based input for longer text content
|
|
8
|
+
- **Character Counting**: Optional character limit and counter display
|
|
9
|
+
- **Resizable Input**: Configurable resize behavior (none, horizontal, vertical, both)
|
|
10
|
+
- **Display Modes**: Edit and view modes with HTML rendering
|
|
11
|
+
- **Text Wrapping**: Configurable text wrapping behavior
|
|
12
|
+
- **Clear Function**: Built-in clear button with icon
|
|
13
|
+
- **Variant Support**: Multiple styling variants (plain, outlined, filled)
|
|
14
|
+
- **HTML Escaping**: Safe HTML rendering in view mode
|
|
15
|
+
|
|
16
|
+
## Import
|
|
17
|
+
|
|
18
|
+
```typescript
|
|
19
|
+
import MemoEditor from '@ticatec/uniface-element/MemoEditor';
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Basic Usage
|
|
23
|
+
|
|
24
|
+
### Simple Memo Editor
|
|
25
|
+
|
|
26
|
+
```svelte
|
|
27
|
+
<script>
|
|
28
|
+
import MemoEditor from '@ticatec/uniface-element/MemoEditor';
|
|
29
|
+
|
|
30
|
+
let content = '';
|
|
31
|
+
</script>
|
|
32
|
+
|
|
33
|
+
<MemoEditor
|
|
34
|
+
bind:value={content}
|
|
35
|
+
input$rows={4}
|
|
36
|
+
placeholder="Enter your memo..."
|
|
37
|
+
/>
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### With Character Limit and Counter
|
|
41
|
+
|
|
42
|
+
```svelte
|
|
43
|
+
<script>
|
|
44
|
+
import MemoEditor from '@ticatec/uniface-element/MemoEditor';
|
|
45
|
+
|
|
46
|
+
let message = '';
|
|
47
|
+
</script>
|
|
48
|
+
|
|
49
|
+
<MemoEditor
|
|
50
|
+
bind:value={message}
|
|
51
|
+
maxLength={500}
|
|
52
|
+
showIndicator={true}
|
|
53
|
+
input$rows={5}
|
|
54
|
+
placeholder="Write your message (max 500 characters)..."
|
|
55
|
+
/>
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### Resizable Editor
|
|
59
|
+
|
|
60
|
+
```svelte
|
|
61
|
+
<script>
|
|
62
|
+
import MemoEditor from '@ticatec/uniface-element/MemoEditor';
|
|
63
|
+
|
|
64
|
+
let notes = '';
|
|
65
|
+
</script>
|
|
66
|
+
|
|
67
|
+
<MemoEditor
|
|
68
|
+
bind:value={notes}
|
|
69
|
+
resize="both"
|
|
70
|
+
input$rows={6}
|
|
71
|
+
variant="outlined"
|
|
72
|
+
placeholder="Resizable notes editor..."
|
|
73
|
+
/>
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## API Reference
|
|
77
|
+
|
|
78
|
+
### Props
|
|
79
|
+
|
|
80
|
+
| Property | Type | Default | Description |
|
|
81
|
+
|----------|------|---------|-------------|
|
|
82
|
+
| `value` | `string` | required | The text content |
|
|
83
|
+
| `disabled` | `boolean` | `false` | Whether the editor is disabled |
|
|
84
|
+
| `readonly` | `boolean` | `false` | Whether the editor is read-only |
|
|
85
|
+
| `variant` | `'' \| 'plain' \| 'outlined' \| 'filled'` | `''` | Visual variant |
|
|
86
|
+
| `style` | `string` | `''` | Additional CSS styles |
|
|
87
|
+
| `wrap` | `'hard' \| 'soft'` | `'hard'` | Text wrapping behavior |
|
|
88
|
+
| `resize` | `'none' \| 'horizontal' \| 'vertical' \| 'both'` | `'none'` | Resize capability |
|
|
89
|
+
| `displayMode` | `DisplayMode` | `DisplayMode.Edit` | Display mode (Edit/View) |
|
|
90
|
+
| `input$rows` | `number` | `3` | Number of visible text lines |
|
|
91
|
+
| `showIndicator` | `boolean` | `false` | Show character counter |
|
|
92
|
+
| `maxLength` | `number` | `null` | Maximum character limit |
|
|
93
|
+
|
|
94
|
+
### DisplayMode Enum
|
|
95
|
+
|
|
96
|
+
```typescript
|
|
97
|
+
enum DisplayMode {
|
|
98
|
+
Edit = 'edit',
|
|
99
|
+
View = 'view'
|
|
100
|
+
}
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## Advanced Examples
|
|
104
|
+
|
|
105
|
+
### Comment System
|
|
106
|
+
|
|
107
|
+
```svelte
|
|
108
|
+
<script>
|
|
109
|
+
import MemoEditor, { DisplayMode } from '@ticatec/uniface-element/MemoEditor';
|
|
110
|
+
|
|
111
|
+
let comment = '';
|
|
112
|
+
let isEditing = true;
|
|
113
|
+
let savedComments = [];
|
|
114
|
+
|
|
115
|
+
const saveComment = () => {
|
|
116
|
+
if (comment.trim()) {
|
|
117
|
+
savedComments = [...savedComments, {
|
|
118
|
+
id: Date.now(),
|
|
119
|
+
content: comment,
|
|
120
|
+
timestamp: new Date().toLocaleString()
|
|
121
|
+
}];
|
|
122
|
+
comment = '';
|
|
123
|
+
}
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
const editComment = (commentObj) => {
|
|
127
|
+
comment = commentObj.content;
|
|
128
|
+
isEditing = true;
|
|
129
|
+
};
|
|
130
|
+
</script>
|
|
131
|
+
|
|
132
|
+
<div class="comment-system">
|
|
133
|
+
<div class="comment-input">
|
|
134
|
+
<MemoEditor
|
|
135
|
+
bind:value={comment}
|
|
136
|
+
maxLength={1000}
|
|
137
|
+
showIndicator={true}
|
|
138
|
+
input$rows={4}
|
|
139
|
+
variant="outlined"
|
|
140
|
+
resize="vertical"
|
|
141
|
+
placeholder="Write your comment..."
|
|
142
|
+
style="margin-bottom: 10px;"
|
|
143
|
+
/>
|
|
144
|
+
<button on:click={saveComment} disabled={!comment.trim()}>
|
|
145
|
+
Post Comment
|
|
146
|
+
</button>
|
|
147
|
+
</div>
|
|
148
|
+
|
|
149
|
+
<div class="comment-list">
|
|
150
|
+
{#each savedComments as commentObj (commentObj.id)}
|
|
151
|
+
<div class="comment-item" style="border: 1px solid #ddd; padding: 10px; margin: 5px 0;">
|
|
152
|
+
<MemoEditor
|
|
153
|
+
value={commentObj.content}
|
|
154
|
+
displayMode={DisplayMode.View}
|
|
155
|
+
style="border: none; background: transparent;"
|
|
156
|
+
/>
|
|
157
|
+
<div class="comment-meta" style="font-size: 0.8em; color: #666; margin-top: 5px;">
|
|
158
|
+
{commentObj.timestamp}
|
|
159
|
+
<button on:click={() => editComment(commentObj)}>Edit</button>
|
|
160
|
+
</div>
|
|
161
|
+
</div>
|
|
162
|
+
{/each}
|
|
163
|
+
</div>
|
|
164
|
+
</div>
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
### Rich Text Note-Taking
|
|
168
|
+
|
|
169
|
+
```svelte
|
|
170
|
+
<script>
|
|
171
|
+
import MemoEditor, { DisplayMode } from '@ticatec/uniface-element/MemoEditor';
|
|
172
|
+
|
|
173
|
+
let notes = {};
|
|
174
|
+
let currentNoteId = null;
|
|
175
|
+
let currentContent = '';
|
|
176
|
+
let isPreviewMode = false;
|
|
177
|
+
|
|
178
|
+
const createNote = () => {
|
|
179
|
+
const id = Date.now();
|
|
180
|
+
notes[id] = {
|
|
181
|
+
title: `Note ${Object.keys(notes).length + 1}`,
|
|
182
|
+
content: '',
|
|
183
|
+
lastModified: new Date()
|
|
184
|
+
};
|
|
185
|
+
currentNoteId = id;
|
|
186
|
+
currentContent = '';
|
|
187
|
+
isPreviewMode = false;
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
const selectNote = (id) => {
|
|
191
|
+
if (currentNoteId && notes[currentNoteId]) {
|
|
192
|
+
notes[currentNoteId].content = currentContent;
|
|
193
|
+
notes[currentNoteId].lastModified = new Date();
|
|
194
|
+
}
|
|
195
|
+
currentNoteId = id;
|
|
196
|
+
currentContent = notes[id].content;
|
|
197
|
+
isPreviewMode = false;
|
|
198
|
+
};
|
|
199
|
+
|
|
200
|
+
const saveCurrentNote = () => {
|
|
201
|
+
if (currentNoteId && notes[currentNoteId]) {
|
|
202
|
+
notes[currentNoteId].content = currentContent;
|
|
203
|
+
notes[currentNoteId].lastModified = new Date();
|
|
204
|
+
}
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
const togglePreview = () => {
|
|
208
|
+
saveCurrentNote();
|
|
209
|
+
isPreviewMode = !isPreviewMode;
|
|
210
|
+
};
|
|
211
|
+
</script>
|
|
212
|
+
|
|
213
|
+
<div class="note-app" style="display: flex; height: 400px;">
|
|
214
|
+
<div class="note-list" style="width: 200px; border-right: 1px solid #ddd; padding: 10px;">
|
|
215
|
+
<button on:click={createNote} style="width: 100%; margin-bottom: 10px;">
|
|
216
|
+
New Note
|
|
217
|
+
</button>
|
|
218
|
+
{#each Object.entries(notes) as [id, note] (id)}
|
|
219
|
+
<div
|
|
220
|
+
class="note-item"
|
|
221
|
+
class:active={currentNoteId == id}
|
|
222
|
+
style="padding: 8px; margin: 2px 0; cursor: pointer; background: {currentNoteId == id ? '#e3f2fd' : 'transparent'};"
|
|
223
|
+
on:click={() => selectNote(id)}
|
|
224
|
+
>
|
|
225
|
+
<div style="font-weight: bold; font-size: 0.9em;">{note.title}</div>
|
|
226
|
+
<div style="font-size: 0.7em; color: #666;">{note.lastModified.toLocaleDateString()}</div>
|
|
227
|
+
</div>
|
|
228
|
+
{/each}
|
|
229
|
+
</div>
|
|
230
|
+
|
|
231
|
+
<div class="note-editor" style="flex: 1; display: flex; flex-direction: column;">
|
|
232
|
+
{#if currentNoteId}
|
|
233
|
+
<div class="editor-toolbar" style="padding: 10px; border-bottom: 1px solid #ddd;">
|
|
234
|
+
<button on:click={togglePreview}>
|
|
235
|
+
{isPreviewMode ? 'Edit' : 'Preview'}
|
|
236
|
+
</button>
|
|
237
|
+
<button on:click={saveCurrentNote}>Save</button>
|
|
238
|
+
</div>
|
|
239
|
+
|
|
240
|
+
<div class="editor-content" style="flex: 1; padding: 10px;">
|
|
241
|
+
<MemoEditor
|
|
242
|
+
bind:value={currentContent}
|
|
243
|
+
displayMode={isPreviewMode ? DisplayMode.View : DisplayMode.Edit}
|
|
244
|
+
resize="none"
|
|
245
|
+
input$rows={15}
|
|
246
|
+
maxLength={10000}
|
|
247
|
+
showIndicator={!isPreviewMode}
|
|
248
|
+
style="height: 100%; border: none;"
|
|
249
|
+
placeholder="Start writing your note..."
|
|
250
|
+
/>
|
|
251
|
+
</div>
|
|
252
|
+
{:else}
|
|
253
|
+
<div class="no-note" style="flex: 1; display: flex; align-items: center; justify-content: center; color: #666;">
|
|
254
|
+
Select a note or create a new one
|
|
255
|
+
</div>
|
|
256
|
+
{/if}
|
|
257
|
+
</div>
|
|
258
|
+
</div>
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
### Form with Validation
|
|
262
|
+
|
|
263
|
+
```svelte
|
|
264
|
+
<script>
|
|
265
|
+
import MemoEditor from '@ticatec/uniface-element/MemoEditor';
|
|
266
|
+
|
|
267
|
+
let formData = {
|
|
268
|
+
description: '',
|
|
269
|
+
feedback: '',
|
|
270
|
+
requirements: ''
|
|
271
|
+
};
|
|
272
|
+
|
|
273
|
+
let errors = {};
|
|
274
|
+
|
|
275
|
+
const validateField = (field, value) => {
|
|
276
|
+
switch (field) {
|
|
277
|
+
case 'description':
|
|
278
|
+
return value.trim().length >= 10 ? '' : 'Description must be at least 10 characters';
|
|
279
|
+
case 'feedback':
|
|
280
|
+
return value.trim().length >= 5 ? '' : 'Feedback must be at least 5 characters';
|
|
281
|
+
case 'requirements':
|
|
282
|
+
return value.trim().length > 0 ? '' : 'Requirements are required';
|
|
283
|
+
default:
|
|
284
|
+
return '';
|
|
285
|
+
}
|
|
286
|
+
};
|
|
287
|
+
|
|
288
|
+
const handleFieldChange = (field) => (event) => {
|
|
289
|
+
const value = event.target.value;
|
|
290
|
+
formData[field] = value;
|
|
291
|
+
errors[field] = validateField(field, value);
|
|
292
|
+
};
|
|
293
|
+
|
|
294
|
+
const submitForm = () => {
|
|
295
|
+
// Validate all fields
|
|
296
|
+
Object.keys(formData).forEach(field => {
|
|
297
|
+
errors[field] = validateField(field, formData[field]);
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
const hasErrors = Object.values(errors).some(error => error !== '');
|
|
301
|
+
|
|
302
|
+
if (!hasErrors) {
|
|
303
|
+
console.log('Form submitted:', formData);
|
|
304
|
+
alert('Form submitted successfully!');
|
|
305
|
+
}
|
|
306
|
+
};
|
|
307
|
+
</script>
|
|
308
|
+
|
|
309
|
+
<form class="validated-form" style="max-width: 600px; margin: 0 auto;">
|
|
310
|
+
<div class="field-group" style="margin-bottom: 20px;">
|
|
311
|
+
<label for="description" style="display: block; margin-bottom: 5px; font-weight: bold;">
|
|
312
|
+
Project Description *
|
|
313
|
+
</label>
|
|
314
|
+
<MemoEditor
|
|
315
|
+
bind:value={formData.description}
|
|
316
|
+
input$rows={4}
|
|
317
|
+
maxLength={500}
|
|
318
|
+
showIndicator={true}
|
|
319
|
+
variant="outlined"
|
|
320
|
+
resize="vertical"
|
|
321
|
+
placeholder="Describe your project..."
|
|
322
|
+
on:input={handleFieldChange('description')}
|
|
323
|
+
/>
|
|
324
|
+
{#if errors.description}
|
|
325
|
+
<div class="error" style="color: #d32f2f; font-size: 0.875em; margin-top: 4px;">
|
|
326
|
+
{errors.description}
|
|
327
|
+
</div>
|
|
328
|
+
{/if}
|
|
329
|
+
</div>
|
|
330
|
+
|
|
331
|
+
<div class="field-group" style="margin-bottom: 20px;">
|
|
332
|
+
<label for="feedback" style="display: block; margin-bottom: 5px; font-weight: bold;">
|
|
333
|
+
Additional Feedback
|
|
334
|
+
</label>
|
|
335
|
+
<MemoEditor
|
|
336
|
+
bind:value={formData.feedback}
|
|
337
|
+
input$rows={3}
|
|
338
|
+
maxLength={300}
|
|
339
|
+
showIndicator={true}
|
|
340
|
+
variant="filled"
|
|
341
|
+
placeholder="Any additional feedback..."
|
|
342
|
+
on:input={handleFieldChange('feedback')}
|
|
343
|
+
/>
|
|
344
|
+
{#if errors.feedback}
|
|
345
|
+
<div class="error" style="color: #d32f2f; font-size: 0.875em; margin-top: 4px;">
|
|
346
|
+
{errors.feedback}
|
|
347
|
+
</div>
|
|
348
|
+
{/if}
|
|
349
|
+
</div>
|
|
350
|
+
|
|
351
|
+
<div class="field-group" style="margin-bottom: 20px;">
|
|
352
|
+
<label for="requirements" style="display: block; margin-bottom: 5px; font-weight: bold;">
|
|
353
|
+
Requirements *
|
|
354
|
+
</label>
|
|
355
|
+
<MemoEditor
|
|
356
|
+
bind:value={formData.requirements}
|
|
357
|
+
input$rows={5}
|
|
358
|
+
variant="outlined"
|
|
359
|
+
resize="both"
|
|
360
|
+
placeholder="List your requirements..."
|
|
361
|
+
on:input={handleFieldChange('requirements')}
|
|
362
|
+
/>
|
|
363
|
+
{#if errors.requirements}
|
|
364
|
+
<div class="error" style="color: #d32f2f; font-size: 0.875em; margin-top: 4px;">
|
|
365
|
+
{errors.requirements}
|
|
366
|
+
</div>
|
|
367
|
+
{/if}
|
|
368
|
+
</div>
|
|
369
|
+
|
|
370
|
+
<button type="button" on:click={submitForm} style="padding: 10px 20px; background: #1976d2; color: white; border: none; border-radius: 4px;">
|
|
371
|
+
Submit Form
|
|
372
|
+
</button>
|
|
373
|
+
</form>
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
## Best Practices
|
|
377
|
+
|
|
378
|
+
1. **Character Limits**: Set appropriate `maxLength` for user guidance and data constraints
|
|
379
|
+
2. **Visual Feedback**: Use `showIndicator` with character limits for better UX
|
|
380
|
+
3. **Accessibility**: Provide clear labels and placeholder text
|
|
381
|
+
4. **Resize Behavior**: Choose appropriate resize options based on layout constraints
|
|
382
|
+
5. **Validation**: Implement client-side validation with clear error messages
|
|
383
|
+
6. **Performance**: Consider debouncing for real-time validation or auto-save features
|
|
384
|
+
7. **Content Safety**: The component automatically escapes HTML in view mode
|
|
385
|
+
|
|
386
|
+
## Styling Notes
|
|
387
|
+
|
|
388
|
+
- The component supports standard variant styling (plain, outlined, filled)
|
|
389
|
+
- Custom styles can be applied via the `style` prop
|
|
390
|
+
- Character counter appears at the bottom-right when enabled
|
|
391
|
+
- Clear button appears when content is present and not disabled
|
|
392
|
+
|
|
393
|
+
## Events
|
|
394
|
+
|
|
395
|
+
The component forwards standard textarea events:
|
|
396
|
+
- `on:blur`
|
|
397
|
+
- `on:focus`
|
|
398
|
+
- `on:keydown`
|
|
399
|
+
- `on:keyup`
|
|
400
|
+
- `on:keypress`
|
|
401
|
+
- `on:change`
|
|
402
|
+
- `on:input`
|
|
403
|
+
|
|
404
|
+
## Accessibility Considerations
|
|
405
|
+
|
|
406
|
+
- Proper focus management for textarea element
|
|
407
|
+
- Character limit information is visually presented
|
|
408
|
+
- Clear button provides alternative content clearing method
|
|
409
|
+
- HTML content is safely escaped in view mode
|
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
# NumberEditor Component
|
|
2
|
+
|
|
3
|
+
Specialized component for numeric input, supporting integers and floating-point numbers.
|
|
4
|
+
|
|
5
|
+
## Properties
|
|
6
|
+
|
|
7
|
+
| Property | Type | Default | Description |
|
|
8
|
+
|----------|------|---------|-------------|
|
|
9
|
+
| `variant` | `'' \| 'plain' \| 'outlined' \| 'filled'` | `''` | Appearance variant |
|
|
10
|
+
| `disabled` | `boolean` | `false` | Whether disabled |
|
|
11
|
+
| `readonly` | `boolean` | `false` | Whether read-only |
|
|
12
|
+
| `compact` | `boolean` | `false` | Whether compact mode |
|
|
13
|
+
| `value` | `number \| null` | `null` | Numeric value |
|
|
14
|
+
| `placeholder` | `string` | `''` | Placeholder text |
|
|
15
|
+
| `precision` | `number \| null` | `null` | Number of decimal places |
|
|
16
|
+
| `suffix` | `string` | `''` | Text suffix |
|
|
17
|
+
| `prefix` | `string` | `''` | Text prefix |
|
|
18
|
+
| `allowNegative` | `boolean` | `false` | Allow negative numbers |
|
|
19
|
+
| `displayMode` | `DisplayMode` | `DisplayMode.Edit` | Display mode |
|
|
20
|
+
| `max` | `number \| null` | `null` | Maximum value |
|
|
21
|
+
| `min` | `number \| null` | `null` | Minimum value |
|
|
22
|
+
| `removable` | `boolean` | `true` | Show clear button |
|
|
23
|
+
| `style` | `string` | `''` | Custom styles |
|
|
24
|
+
| `onChange` | `OnChangeHandler<number \| null>` | - | Value change callback |
|
|
25
|
+
|
|
26
|
+
## Usage Examples
|
|
27
|
+
|
|
28
|
+
```svelte
|
|
29
|
+
<script lang="ts">
|
|
30
|
+
import NumberEditor from '@ticatec/uniface-element/NumberEditor';
|
|
31
|
+
|
|
32
|
+
let price: number | null = null;
|
|
33
|
+
let quantity: number | null = 1;
|
|
34
|
+
let rating: number | null = null;
|
|
35
|
+
|
|
36
|
+
const handlePriceChange = (value: number | null) => {
|
|
37
|
+
price = value;
|
|
38
|
+
console.log('Price:', value);
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
const handleQuantityChange = (value: number | null) => {
|
|
42
|
+
quantity = value;
|
|
43
|
+
console.log('Quantity:', value);
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
const handleRatingChange = (value: number | null) => {
|
|
47
|
+
rating = value;
|
|
48
|
+
console.log('Rating:', value);
|
|
49
|
+
};
|
|
50
|
+
</script>
|
|
51
|
+
|
|
52
|
+
<!-- Price input with prefix -->
|
|
53
|
+
<NumberEditor
|
|
54
|
+
placeholder="Enter price"
|
|
55
|
+
min={0}
|
|
56
|
+
precision={2}
|
|
57
|
+
prefix="$"
|
|
58
|
+
onChange={handlePriceChange}
|
|
59
|
+
bind:value={price}
|
|
60
|
+
/>
|
|
61
|
+
|
|
62
|
+
<!-- Quantity input with limits -->
|
|
63
|
+
<NumberEditor
|
|
64
|
+
placeholder="Enter quantity"
|
|
65
|
+
min={1}
|
|
66
|
+
max={999}
|
|
67
|
+
precision={0}
|
|
68
|
+
onChange={handleQuantityChange}
|
|
69
|
+
bind:value={quantity}
|
|
70
|
+
/>
|
|
71
|
+
|
|
72
|
+
<!-- Rating input with suffix -->
|
|
73
|
+
<NumberEditor
|
|
74
|
+
placeholder="Enter rating"
|
|
75
|
+
min={0}
|
|
76
|
+
max={5}
|
|
77
|
+
precision={1}
|
|
78
|
+
suffix="/5"
|
|
79
|
+
onChange={handleRatingChange}
|
|
80
|
+
bind:value={rating}
|
|
81
|
+
/>
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## Advanced Usage
|
|
85
|
+
|
|
86
|
+
### Currency Input
|
|
87
|
+
```svelte
|
|
88
|
+
<script lang="ts">
|
|
89
|
+
let amount: number | null = null;
|
|
90
|
+
|
|
91
|
+
const handleAmountChange = (value: number | null) => {
|
|
92
|
+
amount = value;
|
|
93
|
+
console.log('Amount:', value);
|
|
94
|
+
};
|
|
95
|
+
</script>
|
|
96
|
+
|
|
97
|
+
<div class="currency-input">
|
|
98
|
+
<NumberEditor
|
|
99
|
+
placeholder="Enter amount"
|
|
100
|
+
min={0}
|
|
101
|
+
precision={2}
|
|
102
|
+
prefix="$"
|
|
103
|
+
bind:value={amount}
|
|
104
|
+
onChange={handleAmountChange}
|
|
105
|
+
/>
|
|
106
|
+
</div>
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### Percentage Input
|
|
110
|
+
```svelte
|
|
111
|
+
<script lang="ts">
|
|
112
|
+
let percentage: number | null = null;
|
|
113
|
+
|
|
114
|
+
const handlePercentageChange = (value: number | null) => {
|
|
115
|
+
// Limit to 0-100 range
|
|
116
|
+
if (value !== null) {
|
|
117
|
+
percentage = Math.min(Math.max(value, 0), 100);
|
|
118
|
+
} else {
|
|
119
|
+
percentage = value;
|
|
120
|
+
}
|
|
121
|
+
};
|
|
122
|
+
</script>
|
|
123
|
+
|
|
124
|
+
<div class="percentage-input">
|
|
125
|
+
<NumberEditor
|
|
126
|
+
placeholder="Enter percentage"
|
|
127
|
+
min={0}
|
|
128
|
+
max={100}
|
|
129
|
+
precision={1}
|
|
130
|
+
suffix="%"
|
|
131
|
+
bind:value={percentage}
|
|
132
|
+
onChange={handlePercentageChange}
|
|
133
|
+
/>
|
|
134
|
+
</div>
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### Form Validation
|
|
138
|
+
```svelte
|
|
139
|
+
<script lang="ts">
|
|
140
|
+
let age: number | null = null;
|
|
141
|
+
let ageError = '';
|
|
142
|
+
|
|
143
|
+
const validateAge = (value: number | null) => {
|
|
144
|
+
if (value === null) {
|
|
145
|
+
ageError = 'Age cannot be empty';
|
|
146
|
+
} else if (value < 18) {
|
|
147
|
+
ageError = 'Age must be at least 18';
|
|
148
|
+
} else if (value > 120) {
|
|
149
|
+
ageError = 'Please enter a valid age';
|
|
150
|
+
} else {
|
|
151
|
+
ageError = '';
|
|
152
|
+
}
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
const handleAgeChange = (value: number) => {
|
|
156
|
+
age = value;
|
|
157
|
+
validateAge(value);
|
|
158
|
+
};
|
|
159
|
+
</script>
|
|
160
|
+
|
|
161
|
+
<div class="form-field">
|
|
162
|
+
<NumberEditor
|
|
163
|
+
placeholder="Enter age"
|
|
164
|
+
min={1}
|
|
165
|
+
max={120}
|
|
166
|
+
bind:value={age}
|
|
167
|
+
onChange={handleAgeChange}
|
|
168
|
+
/>
|
|
169
|
+
{#if ageError}
|
|
170
|
+
<div class="error-message">{ageError}</div>
|
|
171
|
+
{/if}
|
|
172
|
+
</div>
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
## Style Customization
|
|
176
|
+
|
|
177
|
+
```css
|
|
178
|
+
.currency-input {
|
|
179
|
+
position: relative;
|
|
180
|
+
display: flex;
|
|
181
|
+
flex-direction: column;
|
|
182
|
+
gap: 4px;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
.currency-display {
|
|
186
|
+
font-size: 12px;
|
|
187
|
+
color: #6c757d;
|
|
188
|
+
font-weight: 500;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
.percentage-input {
|
|
192
|
+
display: flex;
|
|
193
|
+
align-items: center;
|
|
194
|
+
gap: 8px;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
.suffix {
|
|
198
|
+
font-weight: 500;
|
|
199
|
+
color: #495057;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
.form-field {
|
|
203
|
+
margin-bottom: 16px;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
.error-message {
|
|
207
|
+
color: #dc3545;
|
|
208
|
+
font-size: 12px;
|
|
209
|
+
margin-top: 4px;
|
|
210
|
+
}
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
## Best Practices
|
|
214
|
+
|
|
215
|
+
### 1. Set Appropriate Precision
|
|
216
|
+
```svelte
|
|
217
|
+
<!-- Currency: 2 decimal places -->
|
|
218
|
+
<NumberEditor precision={2} prefix="$" />
|
|
219
|
+
|
|
220
|
+
<!-- Percentage: 1 decimal place -->
|
|
221
|
+
<NumberEditor precision={1} suffix="%" max={100} />
|
|
222
|
+
|
|
223
|
+
<!-- Integer: no precision setting -->
|
|
224
|
+
<NumberEditor precision={0} />
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
### 2. Use Prefixes and Suffixes
|
|
228
|
+
```svelte
|
|
229
|
+
<!-- Currency -->
|
|
230
|
+
<NumberEditor prefix="$" precision={2} />
|
|
231
|
+
|
|
232
|
+
<!-- Percentage -->
|
|
233
|
+
<NumberEditor suffix="%" precision={1} />
|
|
234
|
+
|
|
235
|
+
<!-- Units -->
|
|
236
|
+
<NumberEditor suffix="kg" precision={2} />
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
### 3. Set Reasonable Range Limits
|
|
240
|
+
```svelte
|
|
241
|
+
<!-- Age -->
|
|
242
|
+
<NumberEditor min={0} max={150} precision={0} />
|
|
243
|
+
|
|
244
|
+
<!-- Rating -->
|
|
245
|
+
<NumberEditor min={0} max={5} precision={1} />
|
|
246
|
+
|
|
247
|
+
<!-- Price -->
|
|
248
|
+
<NumberEditor min={0} precision={2} allowNegative={false} />
|
|
249
|
+
```
|